Frage

Little Hintergrund ..

Ich bin in den Prozess der Herstellung eines OpenGL-Spiel mit Java und LWJGL . Ich habe eine TextRenderer-Klasse geschrieben, den Text mit im Cache gespeicherten Seiten von Glyphen macht. Die Glyphen selbst sind in Java2D zu BufferedImages gemacht und zusammen mit den Glyphen-Messungen in Textur Seiten verpackt. TextRenderer zieht die Zeichen als strukturierte Quads, die im Cache gespeicherten Informationen verwendet wird.

Das alles funktioniert gut, mit einer Ausnahme: fehlende Kerning. Zugegeben, es ist nicht notwendig, da der Text aussieht haben fein, wie es ist, aber es würde die Qualität zu verbessern, wenn ich Zugriff auf die Schrift Unterschneidungsinformationen hatte.

Und die Frage ist ..

Ist es möglich, die Kerning-Informationen mit Klar Java, in einer Art und Weise zu erhalten, die über Windows, Linux und MacOS X tragbar sein würde? Damals, als ich die TextRenderer schrieb ich sah sich kurz, konnte aber nicht so einen Weg finden ..

Eine mögliche Lösung

Wenn es keine Möglichkeit gibt, dies zu tun in reiner Java, dachte ich an ein separates Werkzeug Schreiben mit Freetype . Wie in ihren Funktionen Seite aufgelistet:

  

Freetype 2 enthält Informationen, die   oft von anderen nicht verfügbar   ähnliche Schrift Motoren, wie Kerning   Entfernungen , Glyphennamen, vertikale   Metriken, etc.

Das Werkzeug würde speichern die Kerningpaare für gemeinsame Zeichen in eine Datei, die meinen Text-Renderer laden in und nutzen würde. Also das ist wahrscheinlich das, was ich tun werde, wenn ihr nicht mit einer besseren Alternative kommen. :)

War es hilfreich?

Lösung

Die einzigen Bibliotheken die ich kenne, die Kerning info „somwhat“ lesen richtig sind iText und FOP von Apache.

http://www.1t3xt.info/api /com/lowagie/text/pdf/BaseFont.html http: / /svn.apache.org/viewvc/xmlgraphics/fop/tags/fop-0_95/src/java/org/apache/fop/fonts/ (ein Link zum sVN, da es keinen Online-api zu sein scheint)

Andere Tipps

Beginnend mit Java SE 6, Java kann Kerning Informationen zur Verfügung stellen, wenn die Schriftart es bietet. Es ist standardmäßig ausgeschaltet und kann wie folgt eingeschaltet werden:

Map<TextAttribute, Object> textAttributes = new HashMap<TextAttribute, Object>();  

textAttributes.put(TextAttribute.FAMILY, "Arial");  
textAttributes.put(TextAttribute.SIZE, 25f);  
textAttributes.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);  

Font font = Font.getFont(textAttributes);  

Dieser Forum-Thread enthält eine ausführlichere Diskussion zum Thema:

http://forums.sun.com/thread.jspa?threadID=5359127

auf dem Weg in den Unterschneidungsinformationen zu finden und offline in meinem javaScript Bereitstellung, las ich diese Frage auch hier und da gibt es keine Antwort war, suchte ich weiter und am Ende bekam ich diese:

Zwei JavaScript-Objekte, die von der Unicode des Glyphen indiziert werden können:

GLYPHS = {};
KERNS  = {};

Und sie sind wie folgt festgelegt:

// GLYPHS[ unicode ] = [ "name", width ];
// KERNS [ unicode ] = { "nextGlyphName"        : horizontalAdjustment };
//                   = { GLYPHS[ unicode ][ 0 ] : horizontalAdjustment };

Also, wenn ich meine „Text“ string haben, gehe ich durch sie Zeichen für Zeichen und verwenden seine Unicode die Glyphen Namen und Breite wie diese zuzugreifen:

glUnicode = "Text".charCodeAt( strIndex );            // "T" == 84
glName    = GLYPHS[ glUnicode ][ 0 ];
glWidth   = GLYPHS[ glUnicode ][ 1 ];

den Kerning-Wert zuzugreifen, haben wir bei dem nächsten Zeichen Unicode-Wert suchen, die dies:

nextGlyphUnicode = "Text".charCodeAt( strIndex + 1 ); // "e" == 101

Und wenn das folgende Objekt vorhanden ist, dann ist diese Aussage wird Ihnen die Kerning Breite (Sie haben die Existenz überprüfen Sie zuerst wie folgt aus:

if ( !( KERNS[ glUnicode ] == undefined ) ) {
  if ( !( KERNS[ glUnicode ][ GLYPHS[ nextGlyphUnicode ][ 0 ] ] == undefined ) ) {
  ...

):

kernWidth = KERNS[ glUnicode ][ GLYPHS[ nextGlyphUnicode ][ 0 ] ];

In diesem Beispiel kernWidth für die "e" nach dem "T" wäre

kernWidth == -143

Ich denke, das ist, was Sie suchen, nicht wahr? Alle Informationen zugänglich über den Unicode-Wert des Zeichens und den Unicode-Wert des folgenden Zeichens. Sehr einfach und sehr schön.

Also habe ich eine Datei für jede Schriftart und die erste Seite sieht wie folgt aus:

// Family Name
// 'Times New Roman'
// EM size
// '2048'
// is_quadratic
// '1'
//
// GLYPHS[ unicode ] = [ "name", width ];
// KERNS [ unicode ] = { "nextGlyphName"        : horizontalAdjustment };
//                   = { GLYPHS[ unicode ][ 0 ] : horizontalAdjustment };
GLYPHS = {};
KERNS  = {};

GLYPHS[    32 ] = [ "space",  512 ];
KERNS [    32 ] = {
  "Upsilondieresis" :   -76,
  "Upsilon"         :   -76,
  "Tau"             :   -37,
  "Lambda"          :  -113,
  "Delta"           :  -113,
  "Alpha"           :  -113,
  "Alphatonos"      :  -113,
  "Y"               :   -76,
  "W"               :   -37,
  "V"               :   -37,
  "T"               :   -37,
  "A"               :  -113
};
GLYPHS[    33 ] = [ "exclam",  682 ];
GLYPHS[    34 ] = [ "quotedbl",  836 ];
GLYPHS[    35 ] = [ "numbersign", 1024 ];
GLYPHS[    36 ] = [ "dollar", 1024 ];
GLYPHS[    37 ] = [ "percent", 1706 ];
GLYPHS[    38 ] = [ "ampersand", 1593 ];
GLYPHS[    39 ] = [ "quotesingle",  369 ];
GLYPHS[    40 ] = [ "parenleft",  682 ];
GLYPHS[    41 ] = [ "parenright",  682 ];
GLYPHS[    42 ] = [ "asterisk", 1024 ];
GLYPHS[    43 ] = [ "plus", 1155 ];
GLYPHS[    44 ] = [ "comma",  512 ];
GLYPHS[    45 ] = [ "hyphen",  682 ];
GLYPHS[    46 ] = [ "period",  512 ];
GLYPHS[    47 ] = [ "slash",  569 ];
GLYPHS[    48 ] = [ "zero", 1024 ];
GLYPHS[    49 ] = [ "one", 1024 ];
KERNS [    49 ] = {
  "one"             :   -76
};
GLYPHS[    50 ] = [ "two", 1024 ];
GLYPHS[    51 ] = [ "three", 1024 ];
GLYPHS[    52 ] = [ "four", 1024 ];
GLYPHS[    53 ] = [ "five", 1024 ];
GLYPHS[    54 ] = [ "six", 1024 ];
GLYPHS[    55 ] = [ "seven", 1024 ];
GLYPHS[    56 ] = [ "eight", 1024 ];
GLYPHS[    57 ] = [ "nine", 1024 ];
GLYPHS[    58 ] = [ "colon",  569 ];
GLYPHS[    59 ] = [ "semicolon",  569 ];
GLYPHS[    60 ] = [ "less", 1155 ];
GLYPHS[    61 ] = [ "equal", 1155 ];
GLYPHS[    62 ] = [ "greater", 1155 ];
GLYPHS[    63 ] = [ "question",  909 ];
GLYPHS[    64 ] = [ "at", 1886 ];
GLYPHS[    65 ] = [ "A", 1479 ];
KERNS [    65 ] = {
  "quoteright"      :  -227,
  "y"               :  -188,
  "w"               :  -188,
  "v"               :  -152,
  "Y"               :  -188,
  "W"               :  -164,
  "V"               :  -264,
  "T"               :  -227,
  "space"           :  -113
};
GLYPHS[    66 ] = [ "B", 1366 ];
GLYPHS[    67 ] = [ "C", 1366 ];

Sie können kopieren Sie den Inhalt jedes Sie in Ihrem Sourcecode-Datei benötigen oder es in zur Laufzeit lesen Sie die Objekte haben, vorhanden.

Und die Dateien können mit dem folgenden Skript erstellt werden, die innerhalb der fontforge des „embedded“ Python 2.7 Interpreter fein läuft. Dieses Skript ist für eine Windows-Maschine konzipiert, so dass Sie Ihre Wege auf den ersten anpassen!

#
# run these two commands in the fontforge "embedded" python interpreter (ffpython.exe)
# >>> script = open( "Scripts\\Kernings.py", "r" )
# >>> exec script

import fontforge

fontFilenames = [
  "arial.ttf",
  "arialbd.ttf",
  "ariali.ttf",
  "arialbi.ttf",
  "ARIALN.TTF",
  "ARIALNB.TTF",
  "ARIALNI.TTF",
  "ARIALNBI.TTF",
  "calibri.ttf",
  "calibrib.ttf",
  "calibrii.ttf",
  "calibriz.ttf",
  "cambria.ttc",
  "cambriab.ttf",
  "cambriai.ttf",
  "cambriaz.ttf",
  "times.ttf",
  "timesbd.ttf",
  "timesi.ttf",
  "timesbi.ttf",
  "verdana.ttf",
  "verdanab.ttf",
  "verdanai.ttf",
  "verdanaz.ttf"
  ]

for actFontFile in fontFilenames :
  print( "c:\\windows\\fonts\\" + actFontFile )
  out  = open( "Scripts\\Kern_" + actFontFile[ : len( actFontFile ) - 4 ] + "_json.txt", "w" )
  font = fontforge.open( "c:\\windows\\fonts\\" + actFontFile )
  out.write(
      "// Family Name\n// '"  + font.familyname          + "'\n"
    + "// EM size\n// '"      + str( font.em )           + "'\n"
    + "// is_quadratic\n// '" + str( font.is_quadratic ) + "'\n"
    + "//\n"
    + '// GLYPHS[ unicode ] = [ "name", width ];\n'
    + '// KERNS [ unicode ] = { "nextGlyphName"        : horizontalAdjustment };\n'
    + "//                   = { GLYPHS[ unicode ][ 0 ] : horizontalAdjustment };\n"
    + "GLYPHS = {};\n"
    + "KERNS  = {};\n\n"
    )
  glyphIdIterator = font.__iter__()
  for glyphName in glyphIdIterator :
    if font[ glyphName ].unicode >=0 :
      kerningStrings = []
      outstring = ( "GLYPHS[ "
        + str( font[ glyphName ].unicode ).rjust( 5 ) + " ] = [ \""
        + glyphName + "\"," 
        + str( font[ glyphName ].width ).rjust( 5 ) + " ];\n"
        )
      subs = font[ glyphName ].getPosSub("*")
      if len( subs ):
        for sub in subs:
          if len( sub ):
            for subsub in sub:
              if str( subsub ).lower().find( "'kern'" ) >=0:
                kerningStrings.append(
                  ("  \"" + str( sub[ 2 ] ) + "\"").ljust( 20 )
                + ":"     + str( sub[ 5 ] ).rjust( 6 )
                )
                break
      krnStrLen = len( kerningStrings )
      if ( krnStrLen ) :
        outstring = outstring + ( "KERNS [ "
          + str( font[ glyphName ].unicode ).rjust( 5 ) + " ] = {" )
        for kerningString in kerningStrings :
          outstring = outstring + "\n" + kerningString + ","
        outstring = outstring.rstrip( "," )
        outstring = outstring + "\n};\n"
      out.write( outstring )
  out.close()
  font.close()

Ich hoffe, dies kann helfen. Vielen Dank für Ihre Aufmerksamkeit,

Richard

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top