问:
Comparison of HTML String & highlight the difference
Problem statement: Two input string with styling like strong,li,ol,line-through etc in HTML. In the screen, there should be two box : Original Text & Edited Text. If any text of original Text is missing in Edited Text then it should highlight that word in red colour. If he has added anything in Edited Text which is not in Original Text, then it should highlight that text in yellow colour in Edited Text

Expected Output: In first box it should highlight the deleted text in red colour & In second box it should highlight the edited text in yellow colour

Solution Tried: :
  1> Tried with DIff Match Patch but not working properly as my input string contains html string. I can't strip the tags as it will lose its styling.

2> Tried with HtmlDiff but this is giving both deleted word & modified word in a single string. Very difficult to modify this library.

Any lead or help will be much appreciated. Thank you

答:
```<code><!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style>
html, body {
  font: normal 14px/1.4 sans-serif;
  background: #f1f1f1;
}

p {
  margin: 0 0 1rem;
}

ins {
  background: lightgreen;
  text-decoration: none;
}

del {
  background: pink;
}

table {
  border-collapse: collapse;
  width: 100%;
}
table td{
  border: 1px solid #ccc;
}

.card {
  background: #fff;
  border: 1px solid #ccc;
  border-radius: 3px;
  margin: 1rem;
  padding: 1rem;
}

.card .card {
  margin: 0;
  flex: 1 0 0;
}

.row {
  display: flex;
  justify-content: space-between;
  margin-right: -8px;
}

.col {
  display: flex;
  flex: 1 0 0;
  flex-direction: column;
  margin-right: 8px;
}
</style>
</head>
<body>
<div class="card">
  <div class="row">
    <div class="col">
      <h4>Past version</h4>
      <div class="card" id="outputOriginal"></div>
    </div>
    <div class="col">
      <h4>Changes</h4>
      <div class="card" id="output"></div>
    </div>
    <div class="col">
      <h4>New version</h4>
      <div class="card" id="outputNew"></div>
    </div>
  </div>
</div>

</body>
</html>
<script>

  var Match, calculate_operations, consecutive_where, create_index, diff, find_match, find_matching_blocks, html_to_tokens, is_end_of_tag, is_start_of_tag, is_tag, is_whitespace, isnt_tag, op_map, recursively_find_matching_blocks, render_operations, wrap;
  is_end_of_tag = function(char) {
    return char === '>';
  };
  is_start_of_tag = function(char) {
    return char === '<';
  };
  is_whitespace = function(char) {
    return /^\s+$/.test(char);
  };
  is_tag = function(token) {
    return /^\s*<[^>]+>\s*$/.test(token);
  };
  isnt_tag = function(token) {
    return !is_tag(token);
  };
  Match = class Match {
    constructor(start_in_before1, start_in_after1, length1) {
      this.start_in_before = start_in_before1;
      this.start_in_after = start_in_after1;
      this.length = length1;
      this.end_in_before = (this.start_in_before + this.length) - 1;
      this.end_in_after = (this.start_in_after + this.length) - 1;
    }
  };
  html_to_tokens = function(html) {
    var char, current_word, i, len, mode, words;
    mode = 'char';
    current_word = '';
    words = [];
    for (i = 0, len = html.length; i < len; i++) {
      char = html[i];
      switch (mode) {
        case 'tag':
          if (is_end_of_tag(char)) {
            current_word += '>';
            words.push(current_word);
            current_word = '';
            if (is_whitespace(char)) {
              mode = 'whitespace';
            } else {
              mode = 'char';
            }
          } else {
            current_word += char;
          }
          break;
        case 'char':
          if (is_start_of_tag(char)) {
            if (current_word) {
              words.push(current_word);
            }
            current_word = '<';
            mode = 'tag';
          } else if (/\s/.test(char)) {
            if (current_word) {
              words.push(current_word);
            }
            current_word = char;
            mode = 'whitespace';
          } else if (/[\w\#@]+/i.test(char)) {
            current_word += char;
          } else {
            if (current_word) {
              words.push(current_word);
            }
            current_word = char;
          }
          break;
        case 'whitespace':
          if (is_start_of_tag(char)) {
            if (current_word) {
              words.push(current_word);
            }
            current_word = '<';
            mode = 'tag';
          } else if (is_whitespace(char)) {
            current_word += char;
          } else {
            if (current_word) {
              words.push(current_word);
            }
            current_word = char;
            mode = 'char';
          }
          break;
        default:
          throw new Error(`Unknown mode ${mode}`);
      }
    }
    if (current_word) {
      words.push(current_word);
    }
    return words;
  };
  find_match = function(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, start_in_before, end_in_before, start_in_after, end_in_after) {
    var best_match_in_after, best_match_in_before, best_match_length, i, index_in_after, index_in_before, j, len, locations_in_after, looking_for, match, match_length_at, new_match_length, new_match_length_at, ref, ref1;
    best_match_in_before = start_in_before;
    best_match_in_after = start_in_after;
    best_match_length = 0;
    match_length_at = {};
    for (index_in_before = i = ref = start_in_before, ref1 = end_in_before;
      (ref <= ref1 ? i < ref1 : i > ref1); index_in_before = ref <= ref1 ? ++i : --i) {
      new_match_length_at = {};
      looking_for = before_tokens[index_in_before];
      locations_in_after = index_of_before_locations_in_after_tokens[looking_for];
      for (j = 0, len = locations_in_after.length; j < len; j++) {
        index_in_after = locations_in_after[j];
        if (index_in_after < start_in_after) {
          continue;
        }
        if (index_in_after >= end_in_after) {
          break;
        }
        if (match_length_at[index_in_after - 1] == null) {
          match_length_at[index_in_after - 1] = 0;
        }
        new_match_length = match_length_at[index_in_after - 1] + 1;
        new_match_length_at[index_in_after] = new_match_length;
        if (new_match_length > best_match_length) {
          best_match_in_before = index_in_before - new_match_length + 1;
          best_match_in_after = index_in_after - new_match_length + 1;
          best_match_length = new_match_length;
        }
      }
      match_length_at = new_match_length_at;
    }
    if (best_match_length !== 0) {
      match = new Match(best_match_in_before, best_match_in_after, best_match_length);
    }
    return match;
  };
  recursively_find_matching_blocks = function(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, start_in_before, end_in_before, start_in_after, end_in_after, matching_blocks) {
    var match;
    match = find_match(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, start_in_before, end_in_before, start_in_after, end_in_after);
    if (match != null) {
      if (start_in_before < match.start_in_before && start_in_after < match.start_in_after) {
        recursively_find_matching_blocks(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, start_in_before, match.start_in_before, start_in_after, match.start_in_after, matching_blocks);
      }
      matching_blocks.push(match);
      if (match.end_in_before <= end_in_before && match.end_in_after <= end_in_after) {
        recursively_find_matching_blocks(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, match.end_in_before + 1, end_in_before, match.end_in_after + 1, end_in_after, matching_blocks);
      }
    }
    return matching_blocks;
  };
  create_index = function(p) {
    var i, idx, index, len, ref, token;
    if (p.find_these == null) {
      throw new Error('params must have find_these key');
    }
    if (p.in_these == null) {
      throw new Error('params must have in_these key');
    }
    index = {};
    ref = p.find_these;
    for (i = 0, len = ref.length; i < len; i++) {
      token = ref[i];
      index[token] = [];
      idx = p.in_these.indexOf(token);
      while (idx !== -1) {
        index[token].push(idx);
        idx = p.in_these.indexOf(token, idx + 1);
      }
    }
    return index;
  };
  find_matching_blocks = function(before_tokens, after_tokens) {
    var index_of_before_locations_in_after_tokens, matching_blocks;
    matching_blocks = [];
    index_of_before_locations_in_after_tokens = create_index({
      find_these: before_tokens,
      in_these: after_tokens
    });
    return recursively_find_matching_blocks(before_tokens, after_tokens, index_of_before_locations_in_after_tokens, 0, before_tokens.length, 0, after_tokens.length, matching_blocks);
  };
  calculate_operations = function(before_tokens, after_tokens) {
    var action_map, action_up_to_match_positions, i, index, is_single_whitespace, j, last_op, len, len1, match, match_starts_at_current_position_in_after, match_starts_at_current_position_in_before, matches, op, operations, position_in_after, position_in_before, post_processed;
    if (before_tokens == null) {
      throw new Error('before_tokens?');
    }
    if (after_tokens == null) {
      throw new Error('after_tokens?');
    }
    position_in_before = position_in_after = 0;
    operations = [];
    action_map = {
      'false,false': 'replace',
      'true,false': 'insert',
      'false,true': 'delete',
      'true,true': 'none'
    };
    matches = find_matching_blocks(before_tokens, after_tokens);
    matches.push(new Match(before_tokens.length, after_tokens.length, 0));
    for (index = i = 0, len = matches.length; i < len; index = ++i) {
      match = matches[index];
      match_starts_at_current_position_in_before = position_in_before === match.start_in_before;
      match_starts_at_current_position_in_after = position_in_after === match.start_in_after;
      action_up_to_match_positions = action_map[[match_starts_at_current_position_in_before, match_starts_at_current_position_in_after].toString()];
      if (action_up_to_match_positions !== 'none') {
        operations.push({
          action: action_up_to_match_positions,
          start_in_before: position_in_before,
          end_in_before: (action_up_to_match_positions !== 'insert' ? match.start_in_before - 1 : void 0),
          start_in_after: position_in_after,
          end_in_after: (action_up_to_match_positions !== 'delete' ? match.start_in_after - 1 : void 0)
        });
      }
      if (match.length !== 0) {
        operations.push({
          action: 'equal',
          start_in_before: match.start_in_before,
          end_in_before: match.end_in_before,
          start_in_after: match.start_in_after,
          end_in_after: match.end_in_after
        });
      }
      position_in_before = match.end_in_before + 1;
      position_in_after = match.end_in_after + 1;
    }
    post_processed = [];
    last_op = {
      action: 'none'
    };
    is_single_whitespace = function(op) {
      if (op.action !== 'equal') {
        return false;
      }
      if (op.end_in_before - op.start_in_before !== 0) {
        return false;
      }
      return /^\s$/.test(before_tokens.slice(op.start_in_before, +op.end_in_before + 1 || 9e9));
    };
    for (j = 0, len1 = operations.length; j < len1; j++) {
      op = operations[j];
      if (((is_single_whitespace(op)) && last_op.action === 'replace') || (op.action === 'replace' && last_op.action === 'replace')) {
        last_op.end_in_before = op.end_in_before;
        last_op.end_in_after = op.end_in_after;
      } else {
        post_processed.push(op);
        last_op = op;
      }
    }
    return post_processed;
  };
  consecutive_where = function(start, content, predicate) {
    var answer, i, index, last_matching_index, len, token;
    content = content.slice(start, +content.length + 1 || 9e9);
    last_matching_index = void 0;
    for (index = i = 0, len = content.length; i < len; index = ++i) {
      token = content[index];
      answer = predicate(token);
      if (answer === true) {
        last_matching_index = index;
      }
      if (answer === false) {
        break;
      }
    }
    if (last_matching_index != null) {
      return content.slice(0, +last_matching_index + 1 || 9e9);
    }
    return [];
  };
  wrap = function(tag, content) {
    var length, non_tags, position, rendering, tags;
    rendering = '';
    position = 0;
    length = content.length;
    while (true) {
      if (position >= length) {
        break;
      }
      non_tags = consecutive_where(position, content, isnt_tag);
      position += non_tags.length;
      if (non_tags.length !== 0) {
        rendering += `<${tag}>${non_tags.join('')}</${tag}>`;
      }
      if (position >= length) {
        break;
      }
      tags = consecutive_where(position, content, is_tag);
      position += tags.length;
      rendering += tags.join('');
    }
    return rendering;
  };
  op_map = {
    equal: function(op, before_tokens, after_tokens) {
      return before_tokens.slice(op.start_in_before, +op.end_in_before + 1 || 9e9).join('');
    },
    insert: function(op, before_tokens, after_tokens) {
      var val;
      val = after_tokens.slice(op.start_in_after, +op.end_in_after + 1 || 9e9);
      return wrap('ins', val);
    },
    delete: function(op, before_tokens, after_tokens) {
      var val;
      val = before_tokens.slice(op.start_in_before, +op.end_in_before + 1 || 9e9);
      return wrap('del', val);
    }
  };
  op_map.replace = function(op, before_tokens, after_tokens) {
    return (op_map.delete(op, before_tokens, after_tokens)) + (op_map.insert(op, before_tokens, after_tokens));
  };
  render_operations = function(before_tokens, after_tokens, operations) {
    var i, len, op, rendering;
    rendering = '';
    for (i = 0, len = operations.length; i < len; i++) {
      op = operations[i];
      rendering += op_map[op.action](op, before_tokens, after_tokens);
    }
    return rendering;
  };
  diff = function(before, after) {
    var ops;
    if (before === after) {
      return before;
    }
    before = html_to_tokens(before);
    after = html_to_tokens(after);
    ops = calculate_operations(before, after);
    return render_operations(before, after, ops);
  };
  diff.html_to_tokens = html_to_tokens;
  diff.find_matching_blocks = find_matching_blocks;
  find_matching_blocks.find_match = find_match;
  find_matching_blocks.create_index = create_index;
  diff.calculate_operations = calculate_operations;
  diff.render_operations = render_operations;
  if (typeof define === 'function') {
    define([], function() {
      return diff;
    });
  } else if (typeof module !== "undefined" && module !== null) {
    module.exports = diff;
  } else {
    this.htmldiff = diff;
  }

  let originalHTML = `
<p>Hello Mr. Wayne, decide what to do:</p>
<span> Entertainment Session </span>
<label> Country Second </label>
<table>
<tbody>
<tr>
<td>s</td>
<td>a</td>
<td>b1</td>
</tr>
<tr>
<td>s</td>
<td>y</td>
<td>x</td>
</tr>
<tr>
<td>s</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>

<ul><li>Kill The Joker</li><li>Save Thalia Al Gul</li><li>Save Gotham</li></ul><h4>I am a heading 4</h4>`;

let newHTML = `<p>Hello Mr. Wayne, decide what to do:</p>

<span> Entertainment Session general</span>
<label> Country First </label>
<p>Call Alfred, take Thalia Al Gul to the cinema, save Gotham</p>
<table>
<tbody>
<tr>
<td>s</td>
<td>a</td>
<td>b1</td>
</tr>
<tr>
<td>s</td>
<td>y</td>
<td>x</td>
</tr>
<tr>
<td><p>ssiludfhgljkshdflkgjhlskdfjg bkm,nb,mnb,mnb,mnb ,mnb,mnb,mnb ,mnb,mnb ,mnb ,mnb ,mnb ,mnb,mnb ,mnb </p></td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
<span>Use the mouse to choose an option.</span>`;

// Diff HTML strings
let output = htmldiff(originalHTML, newHTML);

// Show HTML diff output as HTML (crazy right?)!
document.getElementById("output").innerHTML = output;
document.getElementById("outputOriginal").innerHTML = originalHTML;
document.getElementById("outputNew").innerHTML = newHTML;
</script>
</code>```


来源: stackexchange

问:
Material-UI Typeography gutterbottom - Increase margin
I'm running Material-UI v4 and the Typography elements when they have gutterbottom set all look to have way too little margin.

What is the correct way to global add more marginbottom to my Typography elements? I assume in the theme - but not sure how!

答:
Based on the [implementation][1] of the Typography component. gutterBottom is set to a fixed value of '0.35em'. It cannot be changed on the global theme. You'll have to wrap the typography component to apply custom margins.

See Github issue here for updates! Requested a feature for it.
https://github.com/mui-org/material-ui/issues/13371

ContentLicense: CC BY-SA 4.0


问:
How to compare request.get result in if else statement
I am making a new script which will take as input list of Ethereum private keys and produce the corresponding addresses with balances, and save the balance in the file if it's found along with private key and the address.

Now, I'm almost certain that my problem lies within the conditional, but cannot figure it out.

Script steps:
 1. Take file of private keys as input (-i flag)
 2. Convert them to public addresses/decode them
 3. Trigger an API call to Etherscan for the information about the address
 4. If the json()["result"] > 0 in API call, write it in output file (-o flag), else print out and sleep for 1 second

Can anyone give a heads up on where I am making mistake?

My code:

```<code>#!/usr/bin/python
import sys, os, argparse, requests, ethereum, binascii, time
from multiprocessing import Pool

def scanether(balance):
    try:
        # Convert private key to address and print the result
        eth_address = ethereum.utils.privtoaddr(INPUTFILE)
        eth_address_hex = binascii.hexlify(eth_address).decode("utf-8")
        eth_balance = requests.get("https://api.etherscan.io/api?module=account&action=balance&address=0x" + eth_address_hex + "&tag=latest&apikey=APIKEYHERE").json()["result"]

        # Check if the result is > 0
        if ('result' != 0) in r.eth_balance:
            print("[*] Address with balance found: " + eth_address_hex + priv)
            # Write match to OUTPUTFILE
            fHandle = open(OUTPUTFILE,'a')
            fHandle.write(eth_address_hex + privkey + "\n")
            fHandle.close()
        else:
            print("balance: {} address: 0x{} privkey: {}".format(float(eth_balance)/100000000, eth_address_hex, priv))
            time.sleep(1)

    except Exception as e:
        return

if __name__ == '__main__':
    print("""
# Finding the Ethereum address with balance
        """)
    # Parse arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--inputfile', default='input.txt', help='input file')
    parser.add_argument('-o', '--outputfile', default='output.txt', help='output file')
    parser.add_argument('-t', '--threads', default=200, help='threads')
    args = parser.parse_args()

    INPUTFILE=args.inputfile
    OUTPUTFILE=args.outputfile
    MAXPROCESSES=int(args.threads)

    try:
        addresses = open(INPUTFILE, "r").readlines()
    except FileNotFoundError as e:
        print(e)
        exit(e.errno)

    print("Scan in progress...")
    pool = Pool(processes=MAXPROCESSES)
    pool.map(scanether, addresses)
    print("Scan finished.")
</code>```

The output is below:

答:
The problem is that you are using some variables that are not in the function scope:

```<code>def scanether(balance):
    try:
        # Convert private key to address and print the result
        eth_address = ethereum.utils.privtoaddr(INPUTFILE)
        ...

        # Check if the result is > 0
        if ('result' != 0) in r.eth_balance:
            print("[*] Address with balance found: " + eth_address_hex + priv)
            # Write match to OUTPUTFILE
            fHandle = open(OUTPUTFILE,'a')
            ...

    except Exception as e:
        return
</code>```

Here INPUTFILE and OUTPUTFILE are not in the scope, it will raise an exception that is captured and then the function simply returns...

You need to pass them as arguments:

```<code>def scanether(balance, INPUTFILE, OUTPUTFILE):
    ...

...

    print("Scan in progress...")
    pool = Pool(processes=MAXPROCESSES)
    def scanether_wrapper(address, ifile=INPUTFILE, ofile=OUTPUTFILE):
        return scanether(address, ifile, ofile)
    pool.map(scanether_wrapper, addresses)
    print("Scan finished.")
</code>```

Body:
I am making a new script which will take as input list of Ethereum private keys and produce the corresponding addresses with balances, and save the balance in the file if it's found along with private key and the address.

Now, I'm almost certain that my problem lies within the conditional, but cannot figure it out.

Script steps:
 1. Take file of private keys as input (-i flag)
 2. Convert them to public addresses/decode them
 3. Trigger an API call to Etherscan for the information about the address
 4. If the json()["result"] > 0 in API call, write it in output file (-o flag), else print out and sleep for 1 second

Can anyone give a heads up on where I am making mistake?

My code:

#!/usr/bin/python
import sys, os, argparse, requests, ethereum, binascii, time
from multiprocessing import Pool

def scanether(balance):
    try:
        # Convert private key to address and print the result
        eth_address = ethereum.utils.privtoaddr(INPUTFILE)
        eth_address_hex = binascii.hexlify(eth_address).decode("utf-8")
        eth_balance = requests.get("https://api.etherscan.io/api?module=account&action=balance&address=0x" + eth_address_hex + "&tag=latest&apikey=APIKEYHERE").json()["result"]

        # Check if the result is > 0
        if ('result' != 0) in r.eth_balance:
            print("[*] Address with balance found: " + eth_address_hex + priv)
            # Write match to OUTPUTFILE
            fHandle = open(OUTPUTFILE,'a')
            fHandle.write(eth_address_hex + privkey + "\n")
            fHandle.close()
        else:
            print("balance: {} address: 0x{} privkey: {}".format(float(eth_balance)/100000000, eth_address_hex, priv))
            time.sleep(1)

    except Exception as e:
        return

if __name__ == '__main__':
    print("""
# Finding the Ethereum address with balance
        """)
    # Parse arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--inputfile', default='input.txt', help='input file')
    parser.add_argument('-o', '--outputfile', default='output.txt', help='output file')
    parser.add_argument('-t', '--threads', default=200, help='threads')
    args = parser.parse_args()

    INPUTFILE=args.inputfile
    OUTPUTFILE=args.outputfile
    MAXPROCESSES=int(args.threads)

    try:
        addresses = open(INPUTFILE, "r").readlines()
    except FileNotFoundError as e:
        print(e)
        exit(e.errno)

    print("Scan in progress...")
    pool = Pool(processes=MAXPROCESSES)
    pool.map(scanether, addresses)
    print("Scan finished.")

The output is below:

Body:
The problem is that you are using some variables that are not in the function scope:

def scanether(balance):
    try:
        # Convert private key to address and print the result
        eth_address = ethereum.utils.privtoaddr(INPUTFILE)
        ...

        # Check if the result is > 0
        if ('result' != 0) in r.eth_balance:
            print("[*] Address with balance found: " + eth_address_hex + priv)
            # Write match to OUTPUTFILE
            fHandle = open(OUTPUTFILE,'a')
            ...

    except Exception as e:
        return

Here INPUTFILE and OUTPUTFILE are not in the scope, it will raise an exception that is captured and then the function simply returns...

You need to pass them as arguments:

def scanether(balance, INPUTFILE, OUTPUTFILE):
    ...

...

    print("Scan in progress...")
    pool = Pool(processes=MAXPROCESSES)
    def scanether_wrapper(address, ifile=INPUTFILE, ofile=OUTPUTFILE):
        return scanether(address, ifile, ofile)
    pool.map(scanether_wrapper, addresses)
    print("Scan finished.")


问:
Cross-Compiling JRE/JDK
Have somebody experiences with cross-compiling the sun-java5 source package (debian) from i386/i586 to the hppa architecture?

Or know a source for java for PA-RISC? I've found only the Package for HP-UX.

Kaffe/gcj are not able to run my third-party java application

答:
Not sure how strong your stomach is (I apologize in advance in the likely case this doesn't work out of the box and you spend months of your life on it :-)

http://openjdk.java.net/projects/zero/

"Zero is a port of OpenJDK that uses no assembler and therefore can trivially be built on any system. The goal of this project is be to be able to build a TCK-compliant OpenJDK of reasonable performance on any platform with no additional porting work.

The interpreter part of Zero is known to work on PowerPC (32- and 64-bit), x86-64, IA-64, ARM and zSeries. Zero is currently Linux- and GCC-specific, but supporting other operating systems and compilers is one area in which contributions are particularly welcome."

Apparently it now passes the TCK

OwnerDisplayName: qwerty

ContentLicense: CC BY-SA 2.5

Title: Cross-Compiling JRE/JDK

LastEditorDisplayName: starblue

OwnerDisplayName: TofuBeer


问:
Two square bracket overloading
I am writing a matrix class in c++ and trying to overload some operator like = and >> and << etc.

I was unable to overload operator [][] for matrix class.
if i have an object of class matrix like M1  then i can use this way for giving value to each element:

```<code>M1[1][2]=5;
</code>```

OR

```<code>int X;

X=M1[4][5];
</code>```

答:
You can't overload [][] as such, since there isn't such an
operator.  You can overload [] to return something which also
has an [] defined on it (a proxy); in the simplest case,
something like a double* will work, but it's usually better,
although a bit more work, to use a full class.  (Place to add
bounds checking, for example.)

Alternatively, you can overload (x,y).  Depending on who you
ask, one format or the other is "better".  (In fact, it's
strictly a question of style.)

Title: Two square bracket overloading

Body:
I am writing a matrix class in c++ and trying to overload some operator like = and >> and << etc.

I was unable to overload operator [][] for matrix class.
if i have an object of class matrix like M1  then i can use this way for giving value to each element:

M1[1][2]=5;

OR

int X;

X=M1[4][5];

ContentLicense: CC BY-SA 3.0


问:
Initialize array whose size is a compile-time constant to single value
I have a c-style array whose size is defined by a #define and can change based on compiling options, e.g.

```<code>#if LINUX
# define SIZE 4
#else
# define SIZE 5
#endif
static int myArr[SIZE] = { /* ??? */ };
</code>```

How can I initialize the whole array to a non-zero value, for example all 42?

答:
I don't know a solution for C-style arrays, though with constexpr and C++17 you could do this with std::array.

```<code>constexpr std::array<int, SIZE> createFilledArray (int value){
   std::array<int, SIZE> a{0};
   for (auto i = 0; i < SIZE; ++i)
       a[i] = value;
   return a;
}

static constexpr auto myArr = createFilledArray(42);
</code>```

Code at compiler explorer

The disadvantage of this is that you can't change the array.
If you remove the constexpr from the variable, your compiler should be able to optimize this.

From C++20 on, you can force the initialization:

```<code>static constinit auto myArr = createFilledArray(42);
</code>```

Not sure if the proposal is already merged in: see constinit proposal

Body:
I have a c-style array whose size is defined by a #define and can change based on compiling options, e.g.

#if LINUX
# define SIZE 4
#else
# define SIZE 5
#endif
static int myArr[SIZE] = { /* ??? */ };

How can I initialize the whole array to a non-zero value, for example all 42?

Body:
I don't know a solution for C-style arrays, though with constexpr and C++17 you could do this with std::array.

constexpr std::array<int, SIZE> createFilledArray (int value){
   std::array<int, SIZE> a{0};
   for (auto i = 0; i < SIZE; ++i)
       a[i] = value;
   return a;
}

static constexpr auto myArr = createFilledArray(42);

Code at compiler explorer

The disadvantage of this is that you can't change the array.
If you remove the constexpr from the variable, your compiler should be able to optimize this.

From C++20 on, you can force the initialization:

static constinit auto myArr = createFilledArray(42);

Not sure if the proposal is already merged in: see constinit proposal


问:
Why is this regex expression returning 'true'?
I am using this exact regex in a RegularExpressionValidator and it works fine. However this code in c# is returning true. Can you please let me know what I am doing wrong?

I am checking for numbers only regex

```<code>var x = Regex.IsMatch("1234asdf", @"[0-9]+").ToString();
</code>```

答:
Other answers talk about why your regex needs to be anchored. However, nobody's picked up on the RegularExpressionValidator part of your question.

I'm assuming you mean System.Web.RegularExpressionValidator. RegularExpressionValidator does more than just checking whether the regex matches - it also checks whether the regex is an exact match. That is, it effectively adds the ^ and $ anchoring for you.

The code:

```<code>Match m = RegexUtil.Match(controlValue, ValidationExpression, RegexOptions.None, MatchTimeout);
return(m.Success && m.Index == 0 && m.Length == controlValue.Length);
</code>```

Note how it checks m.Success, but also checks that the match starts at the beginning of the value being checked, and ends at the end of the value being checked.

(System.ComponentModel.DataAnnotations.RegularExpressionAttribute does the same thing).

Body:
I am using this exact regex in a RegularExpressionValidator and it works fine. However this code in c# is returning true. Can you please let me know what I am doing wrong?

I am checking for numbers only regex

var x = Regex.IsMatch("1234asdf", @"[0-9]+").ToString();

Body:
Other answers talk about why your regex needs to be anchored. However, nobody's picked up on the RegularExpressionValidator part of your question.

I'm assuming you mean System.Web.RegularExpressionValidator. RegularExpressionValidator does more than just checking whether the regex matches - it also checks whether the regex is an exact match. That is, it effectively adds the ^ and $ anchoring for you.

The code:

Match m = RegexUtil.Match(controlValue, ValidationExpression, RegexOptions.None, MatchTimeout);
return(m.Success && m.Index == 0 && m.Length == controlValue.Length);

Note how it checks m.Success, but also checks that the match starts at the beginning of the value being checked, and ends at the end of the value being checked.

(System.ComponentModel.DataAnnotations.RegularExpressionAttribute does the same thing).


问:
Different between in operator and for loop?
i was wondering if the "in" operator work as a for loop and if the time complexity are equivalent?

for n in range(10):
    if n == 5:
        return True
return False

5 in range(10)
```

答:
They are working differently in these cases.

In the loop, for variable in iterable will set variable to each element of iterable. In your case, n will be equal to 0, than 1, than 2... than 9.

In the second case, without the loop, in checks if a variable in the iterable. So in your case it will check if 5 is in the iterator 0-1-2-...-9.

Let's modify your code with prints:

```<code>def a():
    for n in range(10):
        print(n)
        if n == 5:
            return True
    return False

a()
print()
print(5 in range(10))
</code>```

It will print:

```<code>0
1
2
3
4
5

True
</code>```

So in the first case you are set n sequentially to 0-9. In the second case you are just checking 5 is in 0-9.

Body:
They are working differently in these cases.

In the loop, for variable in iterable will set variable to each element of iterable. In your case, n will be equal to 0, than 1, than 2... than 9.

In the second case, without the loop, in checks if a variable in the iterable. So in your case it will check if 5 is in the iterator 0-1-2-...-9.

Let's modify your code with prints:

def a():
    for n in range(10):
        print(n)
        if n == 5:
            return True
    return False

a()
print()
print(5 in range(10))

It will print:

0
1
2
3
4
5

True

So in the first case you are set n sequentially to 0-9. In the second case you are just checking 5 is in 0-9.


问:
Onclick global function with local parameter
Follow-up after a question about ordering XHR functions
It's a recursive situation where sendRequest() is creating a field with an onclick link to itself. This onclick link stores the variable word, that should be fed to sendRequest upon call.

```<code><script type="text/javascript">
function inputReq(){
    sendRequest(wordform.word.value)
}
function sendRequest(str){
    //we start by removing the now superfluous rows
    table=document.getElementById('table')
    while(table.rows.length>2){
        table.deleteRow(2);
    }
    var request = new XMLHttpRequest();
    console.log('sending request');
    request.open('GET', 'http://127.0.0.1:5000/api.html?query='+str, true);
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            json=request.responseText;
            console.log(json);
            //json.forEach(function(obj) {
            //});
            for (word in json){
                var row=table.insertRow();
                var scoreC=row.insertCell();
                var wordC=row.insertCell();
                scoreC.innerHTML=json[word];
                wordC.innerHTML=word;
                wordC.onclick=(function(i)  {sendRequest(i);})(word);
            }
        } else {
            console.log("Silence on the line");
        }
    }
    request.send();
}
</script>
<!DOCTYPE html>
<html>
<head>
<title>Query Page</title>
</head>
<body>
<h1>Query Page</h1>

<table id='table' style="width:100%">
<tr><form name='wordform'>
    <th>Concept: <input type="text" name="word"></th>
    <th><input type="button" onclick="inputReq()" value='Find Associations'></th>
</form></tr>
</body>
</html>
</code>```

The XHR response looks like this:

```<code>{"milk": 1, "cheese": 3, "bread": 2}
</code>```

I have been following this schema but this line is calling the function instead of adding the onclick link:

```<code>wordC.onclick=(function(i)  {sendRequest(i);})(word);
</code>```

答:
Because it's an IIFE (Immediately Invoked Function Expression) it's called instantly. Place another function around it.

```<code>wordC.onclick = () => (function(i) { sendRequest(i); })(word);
</code>```

(The above doesn't look like it's got the surrounding function, but it does - it's an ES6 arrow function).

Body:
Follow-up after a question about ordering XHR functions
It's a recursive situation where sendRequest() is creating a field with an onclick link to itself. This onclick link stores the variable word, that should be fed to sendRequest upon call.

<!DOCTYPE html>

<title>Query Page</title>

Query Page

<form name='wordform'>
    Concept: <input type="text" name="word">
    <input type="button" onclick="inputReq()" value='Find Associations'>
</form>

The XHR response looks like this:

{"milk": 1, "cheese": 3, "bread": 2}

I have been following this schema but this line is calling the function instead of adding the onclick link:

wordC.onclick=(function(i)  {sendRequest(i);})(word);

Body:
Because it's an IIFE (Immediately Invoked Function Expression) it's called instantly. Place another function around it.

wordC.onclick = () => (function(i) { sendRequest(i); })(word);

(The above doesn't look like it's got the surrounding function, but it does - it's an ES6 arrow function).


问:
how to redirect using react router
The maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

```<code>  import React, { Component } from "react";
  import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
  import Login from "./component/auth/Login";
  import HomeScreen from "./component/home-screen/HomeScreen";
       class App extends Component {
           constructor(props) {
            super(props);

              this.state = {
                   user: {}
                 };
                 }

              componentDidMount() {
                    this.authListener();
               }

     authListener() {
firebase.auth().onAuthStateChanged(user => {
  if (user) {
    this.setState({ user });
  } else {
    this.setState({ user: null });
  }
});
}

render() {
  return (
  <BrowserRouter>
    <div className="App">
      <Switch>
        <Route exact path="/" component={Landing} />
        {this.state.user ? (
          <Redirect to="/homescreen" />
        ) : (
          <Redirect to="/login" />
        )}
        <Route exact path="/login" component={Login} />
        <Route exact path="/homescreen" component={HomeScreen} />
        <Route exact path="/users" component={Users} />
        <Route exact path="/users/:id" component={UserDetail} />
        <Route component={Error} />
      </Switch>
    </div>
  </BrowserRouter>
);
}
}

 export default App;
</code>```

答:
//App.js
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: ""
    };
  }

  componentDidMount() {
    this.authListener();
  }

  authListener() {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.setState({
          user
        });
      } else {
        this.setState({
          user: null
        });
      }
    });
  }

  render() {
    return (
    <BrowserRouter>

      <Switch>
        <Route exact path="/" component={(props)=><Landing {...props} users = {this.state.user}/>}/>
        <Route exact path="/login" component={Login} />
        <Route exact path="/homescreen" component={HomeScreen} />
      </Switch>

  </BrowserRouter>
    );
  }
}

export default App;```
</div>
</div>
</p>

<p>in your landing Component check user value and navigate to respective routes.</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>//Landing.js
class Landing extends Component {
  componentDidMount() {
    if (this.props.users) {
      this.props.history.push("homescreen")
    } else if (this.props.users === null) {
      this.props.history.push("login")
    }
  }
  render() {
    return (
      <div>
        <h1>landing page</h1>
      </div>
    );
  }
}</code>```

Title: how to redirect using react router

Body:
The maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

  import React, { Component } from "react";
  import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
  import Login from "./component/auth/Login";
  import HomeScreen from "./component/home-screen/HomeScreen";
       class App extends Component {
           constructor(props) {
            super(props);

              this.state = {
                   user: {}
                 };
                 }

              componentDidMount() {
                    this.authListener();
               }

     authListener() {
firebase.auth().onAuthStateChanged(user => {
  if (user) {
    this.setState({ user });
  } else {
    this.setState({ user: null });
  }
});
}

render() {
  return (
  <BrowserRouter>

      <Switch>
        <Route exact path="/" component={Landing} />
        {this.state.user ? (
          <Redirect to="/homescreen" />
        ) : (
          <Redirect to="/login" />
        )}
        <Route exact path="/login" component={Login} />
        <Route exact path="/homescreen" component={HomeScreen} />
        <Route exact path="/users" component={Users} />
        <Route exact path="/users/:id" component={UserDetail} />
        <Route component={Error} />
      </Switch>

  </BrowserRouter>
);
}
}

 export default App;

Body:
//App.js
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: ""
    };
  }

  componentDidMount() {
    this.authListener();
  }

  authListener() {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.setState({
          user
        });
      } else {
        this.setState({
          user: null
        });
      }
    });
  }

  render() {
    return (
    <BrowserRouter>
    <div className="App">
      <Switch>
        <Route exact path="/" component={(props)=><Landing {...props} users = {this.state.user}/>}/>
        <Route exact path="/login" component={Login} />
        <Route exact path="/homescreen" component={HomeScreen} />
      </Switch>
    </div>
  </BrowserRouter>
    );
  }
}

export default App;

in your landing Component check user value and navigate to respective routes.

//Landing.js
class Landing extends Component {
  componentDidMount() {
    if (this.props.users) {
      this.props.history.push("homescreen")
    } else if (this.props.users === null) {
      this.props.history.push("login")
    }
  }
  render() {
    return (
      <div>
        <h1>landing page</h1>
      </div>
    );
  }
}


问:
How to fix ic_launcher_foregorund.xml unexpected token and top level element not found
I am building a TODO app and I'm getting this error when I wanna run my app that says the problem in v23/ic_launcher_foreground.xml the code is like this

```<code><adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="white"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
</code>```

the problems are
1. Unexpected token

2. top level element not found

Error

```<code>Executing tasks: [:app:assembleDebug]

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:compileDebugAidl NO-SOURCE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:checkDebugManifest UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:prepareLintJar UP-TO-DATE
> Task :app:generateDebugSources UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:mainApkListPersistenceDebug UP-TO-DATE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> 1 exception was raised by workers:
  com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource compilation failed
  C:\Users\CHARAN\Desktop\Android Development\BPTODO\app\src\main\res\drawable-v24\ic_launcher_foreground.xml:40: error: not well-formed (invalid token).
  C:\Users\CHARAN\Desktop\Android Development\BPTODO\app\src\main\res\drawable-v24\ic_launcher_foreground.xml: error: file failed to compile.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 27s
8 actionable tasks: 1 executed, 7 up-to-date
</code>```

答:
I think the unexpected token is referring to the word "white".

try this:

Option 1:

```<code><adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="#FFFFFF"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
</code>```

Or Option 2:

```<code><adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@color/white"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
</code>```

and add to your colors.xml

```<code><color name="white">#FFFFFF</color>
</code>```

Body:
I am building a TODO app and I'm getting this error when I wanna run my app that says the problem in v23/ic_launcher_foreground.xml the code is like this

<adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="white"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

the problems are
1. Unexpected token

2. top level element not found

Error

Executing tasks: [:app:assembleDebug]

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:compileDebugAidl NO-SOURCE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:checkDebugManifest UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:prepareLintJar UP-TO-DATE
> Task :app:generateDebugSources UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:mainApkListPersistenceDebug UP-TO-DATE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> 1 exception was raised by workers:
  com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource compilation failed
  C:\Users\CHARAN\Desktop\Android Development\BPTODO\app\src\main\res\drawable-v24\ic_launcher_foreground.xml:40: error: not well-formed (invalid token).
  C:\Users\CHARAN\Desktop\Android Development\BPTODO\app\src\main\res\drawable-v24\ic_launcher_foreground.xml: error: file failed to compile.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 27s
8 actionable tasks: 1 executed, 7 up-to-date

Body:
I think the unexpected token is referring to the word "white".

try this:

Option 1:

<adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="#FFFFFF"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Or Option 2:

<adaptive-icon
    xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@color/white"/>
    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

and add to your colors.xml

<color name="white">#FFFFFF</color>


问:
Is there any way to find out the total sum of the time of a particular event?
I have a dataset with a timestamp(upto micro seconds) and I have also 'y' variable as 'Machining'.
I want to sum the total time whenever an event took place

As of now I didnt get handy code.

I want total even time and non event time

答:
In order to calculate the elapsed time of an event, you need the start_time and the end_time. Then calculate:

```<code>elapsed_time = end_time - start_time
</code>```

However, from the data provided, it is unclear what the timestamp represent: is it the start, or the end of an event?

Maybe you could use the timestamp of the next event to estimate the end time of the previous one, but this may not be accurate (or under certain circumstances, entirely false).

Body:
In order to calculate the elapsed time of an event, you need the start_time and the end_time. Then calculate:

elapsed_time = end_time - start_time

However, from the data provided, it is unclear what the timestamp represent: is it the start, or the end of an event?

Maybe you could use the timestamp of the next event to estimate the end time of the previous one, but this may not be accurate (or under certain circumstances, entirely false).


问:
LWJGL 2 - Always show front of 3D font
I'm trying to always show the front of a 3D font to the user. I tried rotating the font when rotating the camera, but never could get it to work.

I currently have this:

I'm trying to do this (font always faces front):

TrueTypeFont.java

```<code>package com.displee.render.font;

import lombok.AllArgsConstructor;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * A TrueType font implementation originally for Slick, edited for Bobjob's Engine
 * @original author James Chambers (Jimmy)
 * @original author Jeremy Adams (elias4444)
 * @original author Kevin Glass (kevglass)
 * @original author Peter Korzuszek (genail)
 * @new version edited by David Aaron Muhar (bobjob)
 */
public class TrueTypeFont {

    public final static int ALIGN_LEFT = 0, ALIGN_RIGHT = 1, ALIGN_CENTER = 2;
    /**
     * Array that holds necessary information about the font characters
     */
    private IntObject[] charArray = new IntObject[256];

    /**
     * Map of user defined font characters (Character <-> IntObject)
     */
    private Map customChars = new HashMap();

    /**
     * Boolean flag on whether AntiAliasing is enabled or not
     */
    private boolean antiAlias;

    /**
     * Font's size
     */
    private int fontSize = 0;

    /**
     * Font's height
     */
    private int fontHeight = 0;

    /**
     * Texture used to cache the font 0-255 characters
     */
    private int fontTextureID;

    /**
     * Default font texture width
     */
    private int textureWidth = 512;

    /**
     * Default font texture height
     */
    private int textureHeight = 512;

    /**
     * A reference to Java's AWT Font that we create our font texture from
     */
    private Font font;

    /**
     * The font metrics for our Java AWT font
     */
    private FontMetrics fontMetrics;

    private int correctL = 9, correctR = 8;

    private class IntObject {

        /**
         * Character's width
         */
        public int width;

        /**
         * Character's height
         */
        public int height;

        /**
         * Character's stored x position
         */
        public int storedX;

        /**
         * Character's stored y position
         */
        public int storedY;
    }

    public TrueTypeFont(Font font, boolean antiAlias, char[] additionalChars) {
        this.font = font;
        this.fontSize = font.getSize() + 3;
        this.antiAlias = antiAlias;

        createSet(additionalChars);

        fontHeight -= 1;
        if (fontHeight <= 0) {
            fontHeight = 1;
        }
    }

    public TrueTypeFont(Font font, boolean antiAlias) {
        this(font, antiAlias, null);
    }

    public void setCorrection(boolean on) {
        if (on) {
            correctL = 2;
            correctR = 1;
        } else {
            correctL = 0;
            correctR = 0;
        }
    }

    private BufferedImage getFontImage(char ch) {
        // Create a temporary image to extract the character's size
        BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) tempfontImage.getGraphics();
        if (antiAlias == true) {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }
        g.setFont(font);
        fontMetrics = g.getFontMetrics();
        int charwidth = fontMetrics.charWidth(ch) + 8;

        if (charwidth <= 0) {
            charwidth = 7;
        }
        int charheight = fontMetrics.getHeight() + 3;
        if (charheight <= 0) {
            charheight = fontSize;
        }

        // Create another image holding the character we are creating
        BufferedImage fontImage;
        fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gt = (Graphics2D) fontImage.getGraphics();
        if (antiAlias == true) {
            gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }
        gt.setFont(font);

        gt.setColor(Color.WHITE);
        int charx = 3;
        int chary = 1;
        gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent());
        //fontImage = ImageUtils.flipVertically(fontImage);
        //fontImage = ImageUtils.flipHorizontally(fontImage);
        //fontImage = ImageUtils.flipHorizontallyAndVertically(fontImage);
        return fontImage;

    }

    private void createSet(char[] customCharsArray) {
        // If there are custom chars then I expand the font texture twice
        if (customCharsArray != null && customCharsArray.length > 0) {
            textureWidth *= 2;
        }

        // In any case this should be done in other way. Texture with size 512x512
        // can maintain only 256 characters with resolution of 32x32. The texture
        // size should be calculated dynamicaly by looking at character sizes.

        try {

            BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D) imgTemp.getGraphics();

            g.setColor(new Color(0, 0, 0, 1));
            g.fillRect(0, 0, textureWidth, textureHeight);

            int rowHeight = 0;
            int positionX = 0;
            int positionY = 0;

            int customCharsLength = (customCharsArray != null) ? customCharsArray.length : 0;

            for (int i = 0; i < 256 + customCharsLength; i++) {

                // get 0-255 characters and then custom characters
                char ch = (i < 256) ? (char) i : customCharsArray[i - 256];

                BufferedImage fontImage = getFontImage(ch);

                IntObject newIntObject = new IntObject();

                newIntObject.width = fontImage.getWidth();
                newIntObject.height = fontImage.getHeight();

                if (positionX + newIntObject.width >= textureWidth) {
                    positionX = 0;
                    positionY += rowHeight;
                    rowHeight = 0;
                }

                newIntObject.storedX = positionX;
                newIntObject.storedY = positionY;

                if (newIntObject.height > fontHeight) {
                    fontHeight = newIntObject.height;
                }

                if (newIntObject.height > rowHeight) {
                    rowHeight = newIntObject.height;
                }

                // Draw it here
                g.drawImage(fontImage, positionX, positionY, null);

                positionX += newIntObject.width;

                if (i < 256) { // standard characters
                    charArray[i] = newIntObject;
                } else { // custom characters
                    customChars.put(new Character(ch), newIntObject);
                }

                fontImage = null;
            }

            fontTextureID = loadImage(imgTemp);

            //.getTexture(font.toString(), imgTemp);

        } catch (Exception e) {
            System.err.println("Failed to create font.");
            e.printStackTrace();
        }
    }

    private void drawQuad(float drawX, float drawY, float drawX2, float drawY2, float srcX, float srcY, float srcX2, float srcY2, float z) {
        float DrawWidth = drawX2 - drawX;
        float DrawHeight = drawY2 - drawY;
        float TextureSrcX = srcX / textureWidth;
        float TextureSrcY = srcY / textureHeight;
        float SrcWidth = srcX2 - srcX;
        float SrcHeight = srcY2 - srcY;
        float RenderWidth = (SrcWidth / textureWidth);
        float RenderHeight = (SrcHeight / textureHeight);

        GL11.glTexCoord2f(TextureSrcX, TextureSrcY);
        GL11.glVertex3f(drawX, drawY, z);
        GL11.glTexCoord2f(TextureSrcX, TextureSrcY + RenderHeight);
        GL11.glVertex3f(drawX, drawY + DrawHeight, z);
        GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight);
        GL11.glVertex3f(drawX + DrawWidth, drawY + DrawHeight, z);
        GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY);
        GL11.glVertex3f(drawX + DrawWidth, drawY, z);
    }

    public int getWidth(String whatchars) {
        int totalwidth = 0;
        IntObject intObject = null;
        int currentChar = 0;
        for (int i = 0; i < whatchars.length(); i++) {
            currentChar = whatchars.charAt(i);
            if (currentChar < 256) {
                intObject = charArray[currentChar];
            } else {
                intObject = (IntObject) customChars.get(new Character((char) currentChar));
            }

            if (intObject != null) {
                totalwidth += intObject.width;
            }
        }
        return totalwidth;
    }

    public int getHeight() {
        return fontHeight;
    }

    public int getHeight(String HeightString) {
        return fontHeight;
    }

    public int getLineHeight() {
        return fontHeight;
    }

    public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY) {
        drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, ALIGN_LEFT);
    }

    public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY, int format) {
        drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, format);
    }

    public void drawString(float x, float y, float z, String whatchars, int startIndex, int endIndex, float scaleX, float scaleY, int format) {

        IntObject intObject = null;
        int charCurrent;

        int totalwidth = 0;
        int i = startIndex, d, c;
        float startY = 0;

        switch (format) {
            case ALIGN_RIGHT: {
                d = -1;
                c = correctR;

                while (i < endIndex) {
                    if (whatchars.charAt(i) == '\n') {
                        startY -= fontHeight;
                    }
                    i++;
                }
                break;
            }
            case ALIGN_CENTER: {
                for (int l = startIndex; l <= endIndex; l++) {
                    charCurrent = whatchars.charAt(l);
                    if (charCurrent == '\n') {
                        break;
                    }
                    if (charCurrent < 256) {
                        intObject = charArray[charCurrent];
                    } else {
                        intObject = (IntObject) customChars.get(new Character((char) charCurrent));
                    }
                    totalwidth += intObject.width - correctL;
                }
                totalwidth /= -2;
            }
            case ALIGN_LEFT:
            default: {
                d = 1;
                c = correctL;
                break;
            }

        }

        java.util.List<QuadObject> list = new ArrayList<>(endIndex - startIndex);

        while (i >= startIndex && i <= endIndex) {

            charCurrent = whatchars.charAt(i);
            if (charCurrent < 256) {
                intObject = charArray[charCurrent];
            } else {
                intObject = (IntObject) customChars.get(new Character((char) charCurrent));
            }

            if (intObject != null) {
                if (d < 0) {
                    totalwidth += (intObject.width - c) * d;
                }
                if (charCurrent == '\n') {
                    startY -= fontHeight * d;
                    totalwidth = 0;
                    if (format == ALIGN_CENTER) {
                        for (int l = i + 1; l <= endIndex; l++) {
                            charCurrent = whatchars.charAt(l);
                            if (charCurrent == '\n') {
                                break;
                            }
                            if (charCurrent < 256) {
                                intObject = charArray[charCurrent];
                            } else {
                                intObject = (IntObject) customChars.get(new Character((char) charCurrent));
                            }
                            totalwidth += intObject.width - correctL;
                        }
                        totalwidth /= -2;
                    }
                    //if center get next lines total width/2;
                } else {
                    QuadObject quad = new QuadObject((totalwidth + intObject.width) * scaleX + x, startY * scaleY + y, totalwidth * scaleX + x, (startY + intObject.height) * scaleY + y, intObject.storedX + intObject.width, intObject.storedY + intObject.height, intObject.storedX, intObject.storedY, z);
                    list.add(quad);
                    if (d > 0) {
                        totalwidth += (intObject.width - c) * d;
                    }
                }
                i += d;

            }
        }

        float centerX = 0;
        for(QuadObject quad : list) {
            centerX += quad.drawX + (quad.drawX2 - quad.drawX);
        }
        centerX /= 2.0f;
        float centerY = 0;
        for(QuadObject quad : list) {
            centerY += quad.drawY + (quad.drawY2 - quad.drawY);
        }
        centerY /= 2.0f;

        //GL11.glTranslatef( -centerX, -centerY, -z);
        //GL11.glTranslatef(0, 0, -z);
        GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
        GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);
        //GL11.glRotatef(-Test3DFont.rotation.z, 0.0f, 0.0f, 1.0f);
        //GL11.glTranslatef(0, 0, z);
        //GL11.glTranslatef(centerX, centerY, z); // M1 - 2nd translation

        GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
        GL11.glBegin(GL11.GL_QUADS);
        for(QuadObject quad : list) {
            drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
        }
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glEnd();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    }

    public static int loadImage(BufferedImage bufferedImage) {
        try {
            short width = (short) bufferedImage.getWidth();
            short height = (short) bufferedImage.getHeight();
            //textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? (byte)32 : (byte)24;
            int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
            ByteBuffer byteBuffer;
            DataBuffer db = bufferedImage.getData().getDataBuffer();
            if (db instanceof DataBufferInt) {
                int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
                byte newI[] = new byte[intI.length * 4];
                for (int i = 0; i < intI.length; i++) {
                    byte b[] = intToByteArray(intI[i]);
                    int newIndex = i * 4;

                    newI[newIndex] = b[1];
                    newI[newIndex + 1] = b[2];
                    newI[newIndex + 2] = b[3];
                    newI[newIndex + 3] = b[0];
                }

                byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
            } else {
                byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
            }
            byteBuffer.flip();

            int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA;
            IntBuffer textureId = BufferUtils.createIntBuffer(1);
            ;
            GL11.glGenTextures(textureId);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);

            GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);

            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL11.GL_UNSIGNED_BYTE, byteBuffer.order(ByteOrder.nativeOrder()));
            return textureId.get(0);

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }

        return -1;
    }

    public static boolean isSupported(String fontname) {
        Font font[] = getFonts();
        for (int i = font.length - 1; i >= 0; i--) {
            if (font[i].getName().equalsIgnoreCase(fontname)) {
                return true;
            }
        }
        return false;
    }

    public static Font[] getFonts() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    }

    public static byte[] intToByteArray(int value) {
        return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
    }

    public void destroy() {
        IntBuffer scratch = BufferUtils.createIntBuffer(1);
        scratch.put(0, fontTextureID);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
        GL11.glDeleteTextures(scratch);
    }

    @AllArgsConstructor
    private class QuadObject {
        private float drawX;
        private float drawY;
        private float drawX2;
        private float drawY2;
        private float srcX;
        private float srcY;
        private float srcX2;
        private float srcY2;
        private float z;
    }
}
</code>```

Test3DFont.java

```<code>package com.displee.render.font;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;

import java.awt.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;

public class Test3DFont {

    private static final int WIDTH = 800;
    private static final int HEIGHT = 600;

    private static final float FOV = 45f;
    private static final float NEAR = 0.1f;
    private static final float FAR = 1000f;

    private static boolean mousePressed;
    private static Vector3f startCoordinations = new Vector3f();
    private static float scale = 0.05f;

    public static Vector3f rotation = new Vector3f(0, 0, 0);
    private static Vector3f startRotation = new Vector3f();

    private static TrueTypeFont font;

    private static boolean running = true;

    public static void main(String[] args) throws Exception {
        initializeDisplay();
        font = new TrueTypeFont(new Font("serif", Font.PLAIN, 30), true);
        initializeGL();
        while(running) {
            glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
            handleMouse();

            font.drawString(0, 0, 0, "Test", 0.1f, 0.1f);

            loadDefaultRotation();
            setViewport();

            drawGrid();
            Display.sync(60);
            Display.update();

            if (Display.isCloseRequested()) {
                break;
            }
        }
        font.destroy();
        Display.destroy();
    }

    private static void initializeDisplay() throws LWJGLException {
        Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
        Display.create();
        setViewport();
    }

    public static void set2DMode() {
        //GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
        GL11.glPushMatrix();                                     // Store The Projection Matrix
        GL11.glLoadIdentity();                                   // Reset The Projection Matrix
        GL11.glOrtho(0, WIDTH, 0, HEIGHT, -1, 1);                          // Set Up An Ortho Screen
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
        GL11.glPushMatrix();                                     // Store The Modelview Matrix
        GL11.glLoadIdentity();                                   // Reset The Modelview Matrix
    }

    public static void set3DMode() {
        GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
        GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
        GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
        //GL11.glEnable(GL11.GL_DEPTH_TEST);
    }

    private static void setViewport() {
        glViewport(0, 0, WIDTH, HEIGHT);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(FOV, (float) WIDTH / (float) HEIGHT, NEAR, FAR);
        glMatrixMode(GL_MODELVIEW);
    }

    private static void initializeGL() {
        glShadeModel(GL_SMOOTH);
        glEnable(GL_NORMALIZE);
        glEnable(GL_BLEND);
        glCullFace(GL_BACK);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    private static void handleMouse() {
        scale += Mouse.getDWheel() > 0 ? 0.005f : Mouse.getDWheel() < 0 ? -0.005f : 0;
        int x = Mouse.getY();
        int y = Mouse.getX();
        if (!mousePressed) {
            mousePressed = Mouse.isButtonDown(0);
            if (mousePressed) {
                startCoordinations.set((float) x, (float) y, 0.0f);
                startRotation = new Vector3f(rotation);
            }
        } else if (!Mouse.isButtonDown(0)) {
            mousePressed = false;
        }
        if (!mousePressed) {
            return;
        }
        float differenceX = x - startCoordinations.x;
        float differenceY = y - startCoordinations.y;
        rotation.set(startRotation.x - (differenceX * 0.5F), startRotation.y + (differenceY * 0.5F), 0);
    }

    private static void loadDefaultRotation() {
        glLoadIdentity();
        Vector3f cameraPosition = new Vector3f();
        glTranslatef(cameraPosition.x, cameraPosition.y, -10);
        glRotatef(rotation.x, 1.0F, 0.0F, 0.0F);
        glRotatef(rotation.y, 0.0F, 1.0F, 0.0F);
        glRotatef(rotation.z, 0.0F, 0.0F, 1.0F);
        glScalef(scale, scale, scale);
    }

    private static void drawGrid() {
        glColor4f(0.7176471f, 0.7176471f, 0.7176471f, 1.0f);
        glBegin(GL_LINES);
        float size = 50;
        float step = 10;
        for (float i = -size; i <= size; i += step) {
            glVertex3f(i, 0, size);
            glVertex3f(i, 0, -size);
            glVertex3f(size, 0, i);
            glVertex3f(-size, 0, i);
        }
        glEnd();
    }

    public static int[] getScreenCoords(double x, double y, double z) {
        FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
        IntBuffer viewport = BufferUtils.createIntBuffer(16);
        FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
        FloatBuffer projection = BufferUtils.createFloatBuffer(16);
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
        GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
        GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
        boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
        if (result) {
            return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
        }
        return null;
    }

}
</code>```

Can anyone help me with this? How can I make it so I always see the front of the font?

Update 1:
I've got it almost working by rotating the quads. I've added the following code in the drawString method before enabling texture 2D:

```<code>GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);
</code>```

I've updated the code. It currently looks like this:

答:
I finally fixed it by pushing a matrix and using the original x, y and z coords in the translation. I also had to subtract 180 from the rotation because that's my starting rotation. Ended up with the following code:

```<code>    GL11.glPushMatrix();
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(180 - rotation.y, 0.0f, 1.0f, 0.0f);
    GL11.glTranslatef(-x, -y, -z);

    GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
    GL11.glBegin(GL11.GL_QUADS);
    for(QuadObject quad : list) {
        drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
    }
    GL11.glDisable(GL11.GL_TEXTURE_2D);
    GL11.glEnd();
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

    GL11.glPopMatrix();
</code>```

Title: LWJGL 2 - Always show front of 3D font

Body:
I'm trying to always show the front of a 3D font to the user. I tried rotating the font when rotating the camera, but never could get it to work.

I currently have this:

I'm trying to do this (font always faces front):

TrueTypeFont.java

package com.displee.render.font;

import lombok.AllArgsConstructor;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * A TrueType font implementation originally for Slick, edited for Bobjob's Engine
 * @original author James Chambers (Jimmy)
 * @original author Jeremy Adams (elias4444)
 * @original author Kevin Glass (kevglass)
 * @original author Peter Korzuszek (genail)
 * @new version edited by David Aaron Muhar (bobjob)
 */
public class TrueTypeFont {

    public final static int ALIGN_LEFT = 0, ALIGN_RIGHT = 1, ALIGN_CENTER = 2;
    /**
     * Array that holds necessary information about the font characters
     */
    private IntObject[] charArray = new IntObject[256];

    /**
     * Map of user defined font characters (Character <-> IntObject)
     */
    private Map customChars = new HashMap();

    /**
     * Boolean flag on whether AntiAliasing is enabled or not
     */
    private boolean antiAlias;

    /**
     * Font's size
     */
    private int fontSize = 0;

    /**
     * Font's height
     */
    private int fontHeight = 0;

    /**
     * Texture used to cache the font 0-255 characters
     */
    private int fontTextureID;

    /**
     * Default font texture width
     */
    private int textureWidth = 512;

    /**
     * Default font texture height
     */
    private int textureHeight = 512;

    /**
     * A reference to Java's AWT Font that we create our font texture from
     */
    private Font font;

    /**
     * The font metrics for our Java AWT font
     */
    private FontMetrics fontMetrics;

    private int correctL = 9, correctR = 8;

    private class IntObject {

        /**
         * Character's width
         */
        public int width;

        /**
         * Character's height
         */
        public int height;

        /**
         * Character's stored x position
         */
        public int storedX;

        /**
         * Character's stored y position
         */
        public int storedY;
    }

    public TrueTypeFont(Font font, boolean antiAlias, char[] additionalChars) {
        this.font = font;
        this.fontSize = font.getSize() + 3;
        this.antiAlias = antiAlias;

        createSet(additionalChars);

        fontHeight -= 1;
        if (fontHeight <= 0) {
            fontHeight = 1;
        }
    }

    public TrueTypeFont(Font font, boolean antiAlias) {
        this(font, antiAlias, null);
    }

    public void setCorrection(boolean on) {
        if (on) {
            correctL = 2;
            correctR = 1;
        } else {
            correctL = 0;
            correctR = 0;
        }
    }

    private BufferedImage getFontImage(char ch) {
        // Create a temporary image to extract the character's size
        BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) tempfontImage.getGraphics();
        if (antiAlias == true) {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }
        g.setFont(font);
        fontMetrics = g.getFontMetrics();
        int charwidth = fontMetrics.charWidth(ch) + 8;

        if (charwidth <= 0) {
            charwidth = 7;
        }
        int charheight = fontMetrics.getHeight() + 3;
        if (charheight <= 0) {
            charheight = fontSize;
        }

        // Create another image holding the character we are creating
        BufferedImage fontImage;
        fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D gt = (Graphics2D) fontImage.getGraphics();
        if (antiAlias == true) {
            gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }
        gt.setFont(font);

        gt.setColor(Color.WHITE);
        int charx = 3;
        int chary = 1;
        gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent());
        //fontImage = ImageUtils.flipVertically(fontImage);
        //fontImage = ImageUtils.flipHorizontally(fontImage);
        //fontImage = ImageUtils.flipHorizontallyAndVertically(fontImage);
        return fontImage;

    }

    private void createSet(char[] customCharsArray) {
        // If there are custom chars then I expand the font texture twice
        if (customCharsArray != null && customCharsArray.length > 0) {
            textureWidth *= 2;
        }

        // In any case this should be done in other way. Texture with size 512x512
        // can maintain only 256 characters with resolution of 32x32. The texture
        // size should be calculated dynamicaly by looking at character sizes.

        try {

            BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D) imgTemp.getGraphics();

            g.setColor(new Color(0, 0, 0, 1));
            g.fillRect(0, 0, textureWidth, textureHeight);

            int rowHeight = 0;
            int positionX = 0;
            int positionY = 0;

            int customCharsLength = (customCharsArray != null) ? customCharsArray.length : 0;

            for (int i = 0; i < 256 + customCharsLength; i++) {

                // get 0-255 characters and then custom characters
                char ch = (i < 256) ? (char) i : customCharsArray[i - 256];

                BufferedImage fontImage = getFontImage(ch);

                IntObject newIntObject = new IntObject();

                newIntObject.width = fontImage.getWidth();
                newIntObject.height = fontImage.getHeight();

                if (positionX + newIntObject.width >= textureWidth) {
                    positionX = 0;
                    positionY += rowHeight;
                    rowHeight = 0;
                }

                newIntObject.storedX = positionX;
                newIntObject.storedY = positionY;

                if (newIntObject.height > fontHeight) {
                    fontHeight = newIntObject.height;
                }

                if (newIntObject.height > rowHeight) {
                    rowHeight = newIntObject.height;
                }

                // Draw it here
                g.drawImage(fontImage, positionX, positionY, null);

                positionX += newIntObject.width;

                if (i < 256) { // standard characters
                    charArray[i] = newIntObject;
                } else { // custom characters
                    customChars.put(new Character(ch), newIntObject);
                }

                fontImage = null;
            }

            fontTextureID = loadImage(imgTemp);

            //.getTexture(font.toString(), imgTemp);

        } catch (Exception e) {
            System.err.println("Failed to create font.");
            e.printStackTrace();
        }
    }

    private void drawQuad(float drawX, float drawY, float drawX2, float drawY2, float srcX, float srcY, float srcX2, float srcY2, float z) {
        float DrawWidth = drawX2 - drawX;
        float DrawHeight = drawY2 - drawY;
        float TextureSrcX = srcX / textureWidth;
        float TextureSrcY = srcY / textureHeight;
        float SrcWidth = srcX2 - srcX;
        float SrcHeight = srcY2 - srcY;
        float RenderWidth = (SrcWidth / textureWidth);
        float RenderHeight = (SrcHeight / textureHeight);

        GL11.glTexCoord2f(TextureSrcX, TextureSrcY);
        GL11.glVertex3f(drawX, drawY, z);
        GL11.glTexCoord2f(TextureSrcX, TextureSrcY + RenderHeight);
        GL11.glVertex3f(drawX, drawY + DrawHeight, z);
        GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight);
        GL11.glVertex3f(drawX + DrawWidth, drawY + DrawHeight, z);
        GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY);
        GL11.glVertex3f(drawX + DrawWidth, drawY, z);
    }

    public int getWidth(String whatchars) {
        int totalwidth = 0;
        IntObject intObject = null;
        int currentChar = 0;
        for (int i = 0; i < whatchars.length(); i++) {
            currentChar = whatchars.charAt(i);
            if (currentChar < 256) {
                intObject = charArray[currentChar];
            } else {
                intObject = (IntObject) customChars.get(new Character((char) currentChar));
            }

            if (intObject != null) {
                totalwidth += intObject.width;
            }
        }
        return totalwidth;
    }

    public int getHeight() {
        return fontHeight;
    }

    public int getHeight(String HeightString) {
        return fontHeight;
    }

    public int getLineHeight() {
        return fontHeight;
    }

    public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY) {
        drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, ALIGN_LEFT);
    }

    public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY, int format) {
        drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, format);
    }

    public void drawString(float x, float y, float z, String whatchars, int startIndex, int endIndex, float scaleX, float scaleY, int format) {

        IntObject intObject = null;
        int charCurrent;

        int totalwidth = 0;
        int i = startIndex, d, c;
        float startY = 0;

        switch (format) {
            case ALIGN_RIGHT: {
                d = -1;
                c = correctR;

                while (i < endIndex) {
                    if (whatchars.charAt(i) == '\n') {
                        startY -= fontHeight;
                    }
                    i++;
                }
                break;
            }
            case ALIGN_CENTER: {
                for (int l = startIndex; l <= endIndex; l++) {
                    charCurrent = whatchars.charAt(l);
                    if (charCurrent == '\n') {
                        break;
                    }
                    if (charCurrent < 256) {
                        intObject = charArray[charCurrent];
                    } else {
                        intObject = (IntObject) customChars.get(new Character((char) charCurrent));
                    }
                    totalwidth += intObject.width - correctL;
                }
                totalwidth /= -2;
            }
            case ALIGN_LEFT:
            default: {
                d = 1;
                c = correctL;
                break;
            }

        }

        java.util.List<QuadObject> list = new ArrayList<>(endIndex - startIndex);

        while (i >= startIndex && i <= endIndex) {

            charCurrent = whatchars.charAt(i);
            if (charCurrent < 256) {
                intObject = charArray[charCurrent];
            } else {
                intObject = (IntObject) customChars.get(new Character((char) charCurrent));
            }

            if (intObject != null) {
                if (d < 0) {
                    totalwidth += (intObject.width - c) * d;
                }
                if (charCurrent == '\n') {
                    startY -= fontHeight * d;
                    totalwidth = 0;
                    if (format == ALIGN_CENTER) {
                        for (int l = i + 1; l <= endIndex; l++) {
                            charCurrent = whatchars.charAt(l);
                            if (charCurrent == '\n') {
                                break;
                            }
                            if (charCurrent < 256) {
                                intObject = charArray[charCurrent];
                            } else {
                                intObject = (IntObject) customChars.get(new Character((char) charCurrent));
                            }
                            totalwidth += intObject.width - correctL;
                        }
                        totalwidth /= -2;
                    }
                    //if center get next lines total width/2;
                } else {
                    QuadObject quad = new QuadObject((totalwidth + intObject.width) * scaleX + x, startY * scaleY + y, totalwidth * scaleX + x, (startY + intObject.height) * scaleY + y, intObject.storedX + intObject.width, intObject.storedY + intObject.height, intObject.storedX, intObject.storedY, z);
                    list.add(quad);
                    if (d > 0) {
                        totalwidth += (intObject.width - c) * d;
                    }
                }
                i += d;

            }
        }

        float centerX = 0;
        for(QuadObject quad : list) {
            centerX += quad.drawX + (quad.drawX2 - quad.drawX);
        }
        centerX /= 2.0f;
        float centerY = 0;
        for(QuadObject quad : list) {
            centerY += quad.drawY + (quad.drawY2 - quad.drawY);
        }
        centerY /= 2.0f;

        //GL11.glTranslatef( -centerX, -centerY, -z);
        //GL11.glTranslatef(0, 0, -z);
        GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
        GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);
        //GL11.glRotatef(-Test3DFont.rotation.z, 0.0f, 0.0f, 1.0f);
        //GL11.glTranslatef(0, 0, z);
        //GL11.glTranslatef(centerX, centerY, z); // M1 - 2nd translation

        GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
        GL11.glBegin(GL11.GL_QUADS);
        for(QuadObject quad : list) {
            drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
        }
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glEnd();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    }

    public static int loadImage(BufferedImage bufferedImage) {
        try {
            short width = (short) bufferedImage.getWidth();
            short height = (short) bufferedImage.getHeight();
            //textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? (byte)32 : (byte)24;
            int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
            ByteBuffer byteBuffer;
            DataBuffer db = bufferedImage.getData().getDataBuffer();
            if (db instanceof DataBufferInt) {
                int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
                byte newI[] = new byte[intI.length * 4];
                for (int i = 0; i < intI.length; i++) {
                    byte b[] = intToByteArray(intI[i]);
                    int newIndex = i * 4;

                    newI[newIndex] = b[1];
                    newI[newIndex + 1] = b[2];
                    newI[newIndex + 2] = b[3];
                    newI[newIndex + 3] = b[0];
                }

                byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
            } else {
                byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
            }
            byteBuffer.flip();

            int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA;
            IntBuffer textureId = BufferUtils.createIntBuffer(1);
            ;
            GL11.glGenTextures(textureId);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);

            GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);

            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL11.GL_UNSIGNED_BYTE, byteBuffer.order(ByteOrder.nativeOrder()));
            return textureId.get(0);

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }

        return -1;
    }

    public static boolean isSupported(String fontname) {
        Font font[] = getFonts();
        for (int i = font.length - 1; i >= 0; i--) {
            if (font[i].getName().equalsIgnoreCase(fontname)) {
                return true;
            }
        }
        return false;
    }

    public static Font[] getFonts() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    }

    public static byte[] intToByteArray(int value) {
        return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
    }

    public void destroy() {
        IntBuffer scratch = BufferUtils.createIntBuffer(1);
        scratch.put(0, fontTextureID);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
        GL11.glDeleteTextures(scratch);
    }

    @AllArgsConstructor
    private class QuadObject {
        private float drawX;
        private float drawY;
        private float drawX2;
        private float drawY2;
        private float srcX;
        private float srcY;
        private float srcX2;
        private float srcY2;
        private float z;
    }
}

Test3DFont.java

package com.displee.render.font;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;

import java.awt.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;

public class Test3DFont {

    private static final int WIDTH = 800;
    private static final int HEIGHT = 600;

    private static final float FOV = 45f;
    private static final float NEAR = 0.1f;
    private static final float FAR = 1000f;

    private static boolean mousePressed;
    private static Vector3f startCoordinations = new Vector3f();
    private static float scale = 0.05f;

    public static Vector3f rotation = new Vector3f(0, 0, 0);
    private static Vector3f startRotation = new Vector3f();

    private static TrueTypeFont font;

    private static boolean running = true;

    public static void main(String[] args) throws Exception {
        initializeDisplay();
        font = new TrueTypeFont(new Font("serif", Font.PLAIN, 30), true);
        initializeGL();
        while(running) {
            glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
            handleMouse();

            font.drawString(0, 0, 0, "Test", 0.1f, 0.1f);

            loadDefaultRotation();
            setViewport();

            drawGrid();
            Display.sync(60);
            Display.update();

            if (Display.isCloseRequested()) {
                break;
            }
        }
        font.destroy();
        Display.destroy();
    }

    private static void initializeDisplay() throws LWJGLException {
        Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
        Display.create();
        setViewport();
    }

    public static void set2DMode() {
        //GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
        GL11.glPushMatrix();                                     // Store The Projection Matrix
        GL11.glLoadIdentity();                                   // Reset The Projection Matrix
        GL11.glOrtho(0, WIDTH, 0, HEIGHT, -1, 1);                          // Set Up An Ortho Screen
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
        GL11.glPushMatrix();                                     // Store The Modelview Matrix
        GL11.glLoadIdentity();                                   // Reset The Modelview Matrix
    }

    public static void set3DMode() {
        GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
        GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
        GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
        //GL11.glEnable(GL11.GL_DEPTH_TEST);
    }

    private static void setViewport() {
        glViewport(0, 0, WIDTH, HEIGHT);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(FOV, (float) WIDTH / (float) HEIGHT, NEAR, FAR);
        glMatrixMode(GL_MODELVIEW);
    }

    private static void initializeGL() {
        glShadeModel(GL_SMOOTH);
        glEnable(GL_NORMALIZE);
        glEnable(GL_BLEND);
        glCullFace(GL_BACK);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    private static void handleMouse() {
        scale += Mouse.getDWheel() > 0 ? 0.005f : Mouse.getDWheel() < 0 ? -0.005f : 0;
        int x = Mouse.getY();
        int y = Mouse.getX();
        if (!mousePressed) {
            mousePressed = Mouse.isButtonDown(0);
            if (mousePressed) {
                startCoordinations.set((float) x, (float) y, 0.0f);
                startRotation = new Vector3f(rotation);
            }
        } else if (!Mouse.isButtonDown(0)) {
            mousePressed = false;
        }
        if (!mousePressed) {
            return;
        }
        float differenceX = x - startCoordinations.x;
        float differenceY = y - startCoordinations.y;
        rotation.set(startRotation.x - (differenceX * 0.5F), startRotation.y + (differenceY * 0.5F), 0);
    }

    private static void loadDefaultRotation() {
        glLoadIdentity();
        Vector3f cameraPosition = new Vector3f();
        glTranslatef(cameraPosition.x, cameraPosition.y, -10);
        glRotatef(rotation.x, 1.0F, 0.0F, 0.0F);
        glRotatef(rotation.y, 0.0F, 1.0F, 0.0F);
        glRotatef(rotation.z, 0.0F, 0.0F, 1.0F);
        glScalef(scale, scale, scale);
    }

    private static void drawGrid() {
        glColor4f(0.7176471f, 0.7176471f, 0.7176471f, 1.0f);
        glBegin(GL_LINES);
        float size = 50;
        float step = 10;
        for (float i = -size; i <= size; i += step) {
            glVertex3f(i, 0, size);
            glVertex3f(i, 0, -size);
            glVertex3f(size, 0, i);
            glVertex3f(-size, 0, i);
        }
        glEnd();
    }

    public static int[] getScreenCoords(double x, double y, double z) {
        FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
        IntBuffer viewport = BufferUtils.createIntBuffer(16);
        FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
        FloatBuffer projection = BufferUtils.createFloatBuffer(16);
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
        GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
        GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
        boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
        if (result) {
            return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
        }
        return null;
    }

}

Can anyone help me with this? How can I make it so I always see the front of the font?

Update 1:
I've got it almost working by rotating the quads. I've added the following code in the drawString method before enabling texture 2D:

GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);

I've updated the code. It currently looks like this:

Body:
I finally fixed it by pushing a matrix and using the original x, y and z coords in the translation. I also had to subtract 180 from the rotation because that's my starting rotation. Ended up with the following code:

    GL11.glPushMatrix();
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(180 - rotation.y, 0.0f, 1.0f, 0.0f);
    GL11.glTranslatef(-x, -y, -z);

    GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
    GL11.glBegin(GL11.GL_QUADS);
    for(QuadObject quad : list) {
        drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
    }
    GL11.glDisable(GL11.GL_TEXTURE_2D);
    GL11.glEnd();
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

    GL11.glPopMatrix();