Загрузка некоторого шрифта TrueType из файла TTF в Java вызывает FontFormatException: имя шрифта не найдено

Я пытаюсь создать экземпляр java.awt.Font из файла TTF в своей системе, но только некоторые шрифты могут загружаться без ошибок. Код ниже — это тестовый код, который я нашел в Интернете. При запуске в моей системе он может успешно загрузить 285 шрифтов (например, Arial.ttf), но не может загрузить 83 шрифта (например, AmericanTypewriter.ttf).

Все ошибки имеют форму FontFormatException: Font name not found без встроенной причины.

Известны ли проблемы с java.awt.Font и совместимостью форматов? Я ничего не могу найти после долгих поисков в Google.

public static void main(String[] args) {
        String rootPath = "/Library/Fonts";

        File root = new File(rootPath);
        if (root.canRead()) {
            String[] fontFiles = root.list();

            Font font = null;
            for (String fontFile : fontFiles) {
                try {
                    System.out.println(fontFile);
                    font = Font.createFont(Font.TRUETYPE_FONT, new File(root + "/" + fontFile));
                    System.out.println(font);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

Моя среда — Java 7, OS X Mavericks (10.9.1).

java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

Любая помощь здесь будет принята с благодарностью.


person Nathan Smith    schedule 21.01.2014    source источник


Ответы (2)


Итак, после некоторого раскопок выясняется, что эта проблема связана с ошибкой (особенностью!) в реализации java.awt. А именно, загрузка физического шрифта TrueType завершается сбоем, если таблица имен файла шрифта не содержит записей фамилий и полных имен.

Чтобы определить проблему, я использовал GrepCode для обратной трассировки от соответствующего исключения в реализации OpenJDK AWT. Как только я обнаружил проблему с таблицей имен, я использовал ttx, простой редактор метаданных TrueType, чтобы добавить записи имен, которые ищет Java. Бывший:

<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
  American Typewriter
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
  American Typewriter
</namerecord>

Новые файлы TTF, сгенерированные ttx, теперь могут быть открыты Java. Ура!

person Nathan Smith    schedule 22.01.2014
comment
У меня была аналогичная проблема, но шрифт правильно загружался в Java6 (Eclipse), но не в Java7 (терминал). Кажется, есть разница в реализации между Java6 и 7... - person britzl; 01.04.2014

Это функция Oracle JDK/OpenJDK (ошибка).

Проблема вызвана sun.font.TrueTypeFont и отсутствием поддержки имен шрифтов Mac TrueType.

TrueTypeFont.java содержит проверку чтения таблицы имен шрифта TrueType для чтения только имени идентификатора платформы Microsoft (platformID == 3), а не идентификатора платформы Mac (platformID == 1). Во многих случаях шрифты TrueType, включенные в OSX, имеют только имена с platformID равным 1. Из-за этого метод initNames() не устанавливает значение ни для familyName, ни для fullName, а код после запуска initNames() проверяет, являются ли они нулевыми (что они, конечно, есть) и выдает исключение Font name not found.

В Apple JDK (1.6 и, возможно, 1.5?) Apple не использовала TrueTypeFont в качестве FontHandler. У них была собственная реализация, которая называется sun.font.AppleNativeFont. Вы даже не можете использовать sun.font.TrueTypeFont в Apple JDK, потому что он всегда будет использовать обработчик sun.font.AppleNativeFont, который поддерживает идентификаторы платформ Mac и Microsoft.

Похоже, что sun.font.AppleNativeFont не существует в OpenJDK или Oracle JDK, даже несмотря на то, что Apple «пожертвовала» код Oracle.

Было бы удобно с точки зрения непрерывности включить sun.font.AppleNativeFont в OpenJDK/Oracle JDK. Было бы еще лучше, если бы TrueTypeFont.java был улучшен, чтобы включить поддержку шрифтов Mac TrueType.

ОБНОВЛЕНИЕ: ВРЕМЕННОЕ РЕШЕНИЕ.

Один из патчей в комментариях ниже был отправлен в репозиторий OpenJDK. Если вы клонируете репозиторий с правильной версией, вы можете получить пропатченные файлы.

hg clone -r 8b05f9b91765 http://hg.openjdk.java.net/jdk7/jdk7/jdk

Скопируйте следующие файлы из jdk/src/shared/classes/sun/font:

TrueTypeFont.java
LCIDMap.java
AppleLangID.java

В тот же каталог в магистрали текущего JDK (я использовал jdk8-b132), скомпилируйте его, и у вас будет поддержка шрифтов Mac. Вы также можете применить этот патч, который был сделан после патча шрифта Mac:

http://hg.openjdk.java.net/jdk7/jdk7/jdk/rev/3dabb2f78e73

Вуаля!

person Roland Quast    schedule 27.06.2014
comment
В 2011 году несколько человек опубликовали исправления, которые так и не были включены. mail.openjdk.java.net/pipermail/2d- dev/2011-March/001922.html mail.openjdk.java.net/pipermail/jdk6-dev/2011-January/ А вот кто-то, кто попросил снова исправить это в 2014 году: mail.openjdk.java.net/pipermail/awt-dev/2014-January/ - person Roland Quast; 30.06.2014