Вопрос

Небольшая предыстория..

Я нахожусь в процессе создания игры на OpenGL, используя Java и LWJGL.Я написал книгу TextRenderer-класс, который отображает текст с использованием кэшированных страниц глифов.Сами глифы отображаются в Java2D для BufferedImages и упакованы на страницы текстур вместе с измерениями глифов. TextRenderer рисует символы в виде текстурированных квадратов, используя кэшированную информацию.

Все это работает хорошо, за исключением одной вещи:отсутствует кернинг.Конечно, в этом нет необходимости, поскольку текст и так выглядит нормально, но это улучшило бы качество, если бы у меня был доступ к информации о кернинге шрифтов.

И вот в чем вопрос..

Возможно ли получить информацию о кернинге, используя обычную Java, таким образом, чтобы она была переносима в Windows, Linux и macOS X ?Еще тогда, когда я писал TextRenderer Я бегло огляделся по сторонам, но не смог найти такого выхода..

Одно из возможных решений

Если нет способа сделать это на чистой Java, я подумывал о написании отдельного инструмента с использованием Свободный Тип.Как указано на странице их функций:

FreeType 2 предоставляет информацию, которая часто недоступна в других похожих системах обработки шрифтов, таких как кернинг расстояния, имена глифов, вертикальная метрики и т. д.

Инструмент сохранит пары кернинга для общих символов в файл, который загрузит и будет использовать мой инструмент визуализации текста.Так что, вероятно, это то, что я сделаю, если вы, ребята, не придумаете лучшей альтернативы.:)

Это было полезно?

Решение

Единственными библиотеками, о которых я знаю, которые правильно считывают информацию о кернинге "somwhat", являются iText - Текст и ЩЕГОЛЬ из 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/ (ссылка на svn, поскольку, похоже, онлайн-api не существует)

Другие советы

Начиная с Java SE 6, Java может предоставлять информацию о кернинге, когда ее предоставляет шрифт.Он выключен по умолчанию и может быть включен следующим образом:

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);  

Эта ветка форума содержит более подробное обсуждение этой темы:

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

по пути поиска информации о кернинге и предоставления ее в автономном режиме в моем JavaScript я также прочитал этот вопрос здесь, и поскольку ответа не было, я поискал дальше, и в конце я получил это:

Два объекта javascript, которые могут быть проиндексированы с помощью символа unicode:

GLYPHS = {};
KERNS  = {};

И они расположены вот так:

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

Итак, если у меня есть моя строка "Text", я просматриваю ее посимвольно и использую его unicode для доступа к имени и ширине глифа следующим образом:

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

Чтобы получить доступ к значению кернинга, мы должны посмотреть на следующее значение символов в юникоде, которое является следующим:

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

И если следующий объект существует, то этот оператор предоставит вам ширину кернинга (сначала вы должны проверить наличие следующим образом:

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

):

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

В этом примере ширина ядра для буквы "e", следующей за буквой "T", будет равна

kernWidth == -143

Я думаю, это то, что вы искали, не так ли?Вся информация доступна через значение символа в юникоде и значение следующего символа в юникоде.Очень просто и очень приятно.

Итак, я создал файл для каждого шрифта, и первая страница выглядит следующим образом:

// 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 ];

Вы можете скопировать содержимое каждого нужного вам файла в свой исходный код или прочитать его во время выполнения, чтобы объекты были доступны.

И файлы могут быть созданы с помощью следующего скрипта, который нормально работает в fontforge"встроенный" интерпретатор python 2.7.Этот скрипт предназначен для компьютера с Windows, поэтому сначала вам придется адаптировать свои пути!

#
# 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()

Я надеюсь, это может помочь.Большое вам спасибо за ваше внимание,

Ричард

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top