Java: шрифт .ttf пустой, ширина ‹=0, системные шрифты работают

Я пытаюсь создать bufferedImage размера данного текста. При использовании системного шрифта проблем нет. Я трижды проверил местоположение, так что это не должно быть моей ошибкой. Я могу загрузить шрифт куда-нибудь, если нужно.

font = Font.createFont(Font.TRUETYPE_FONT, ttfStream);

При использовании файла .ttf я получаю ошибки, указывающие на то, что там нет данных.

font = Font.createFont(Font.TRUETYPE_FONT, ttfStream);

Ошибка говорит:

Exception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (1) cannot be <= 0
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:340)
at ErrorExample.stringToBufferedImage(Untitled.java:64)
at ErrorExample.main(Untitled.java:35)

Пример кода:

class ErrorExample {
    static boolean dontwork = true;

    public static void main(String[] args) throws IOException, FontFormatException{
        InputStream ttfStream = new BufferedInputStream(new FileInputStream("/test/monofont.ttf"));
         Font font;
        if(dontwork == true){ //here the fun seems to be.
            font = Font.createFont(Font.TRUETYPE_FONT, ttfStream);
        }else{
            font = new Font( "Verdana", Font.BOLD, 20 );
        }
        BufferedImage img = stringToBufferedImage(font, "sdf");

    System.out.println("Done.");
    }


    /**
         * Modiefied from http://stackoverflow.com/a/17301696/3423324
         * @param font 
         */
        public static BufferedImage stringToBufferedImage(Font f, String s) {
            //First, we have to calculate the string's width and height

            BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics g = img.getGraphics();

            //Set the font to be used when drawing the string
            //f = new Font("Tahoma", Font.PLAIN, 48);
            g.setFont(f);

            //Get the string visual bounds
            FontRenderContext frc = g.getFontMetrics().getFontRenderContext();
            Rectangle2D rect = f.getStringBounds(s, frc);
            //Release resources
            g.dispose();

            //Then, we have to draw the string on the final image

            //Create a new image where to print the character
            img = new BufferedImage((int) Math.ceil(rect.getWidth()), (int) Math.ceil(rect.getHeight()), BufferedImage.TYPE_INT_ARGB);
            //Graphics2D g2d = img.;
            //g2d.setColor(Color.black); // Otherwise the text would be white

            g = img.getGraphics();
            Graphics2D g2d = (Graphics2D) g;
            g.setColor(Color.black); //Otherwise the text would be white
            g2d.setColor(Color.black); //Otherwise the text would be white
            g2d.setFont(f);

            //Calculate x and y for that string
            FontMetrics fm = g.getFontMetrics();
            int x = 0;
            int y = fm.getAscent(); //getAscent() = baseline
            g2d.drawString(s, x, y);

            //Release resources
            g.dispose();

            //Return the image
            return img;
        }

}

person luckydonald    schedule 03.07.2014    source источник
comment
Некоторые шрифты TTF содержат контуры шрифта Type 1 (PostScript) вместо инструкций TrueType. Можете ли вы (а) проверить это для своего шрифта (посмотрите на первые несколько байтов) и (б) попробовать с файлом шрифта, который, как вы уверены, «является» истинным TrueType?   -  person Jongware    schedule 03.07.2014
comment
@Jongware Я проверил шрифт с помощью книги шрифтов на MacOSX и получил следующее: pic.flutterb.at/ view/28d439.png может вам поможет?   -  person luckydonald    schedule 04.07.2014
comment
Сейчас еще и ттф из интернета проверил, при этом такой ошибки по факту не выдавал.   -  person luckydonald    schedule 04.07.2014
comment
Хорошо, FontBook говорит, что это настоящий TTF (таким образом опровергая мое предыдущее предположение), но он содержит некоторую ошибку. Предположительно, именно здесь происходит сбой обработки шрифтов в Java. Так что, похоже, в вашем коде все в порядке.   -  person Jongware    schedule 04.07.2014


Ответы (1)


Проблема заключалась в следующем: недавно загруженный шрифт не имеет встроенной информации о размере. Из Javadoc:

Эти шрифты возвращаются как объекты Font с размером 1, преобразованием идентичности и функциями шрифта по умолчанию. Затем эти базовые шрифты можно использовать для получения новых объектов Font с различными размерами, стилями, преобразованиями и функциями шрифта с помощью методов deriveFont в этом классе.

http://docs.oracle.com/javase/7/docs/api/java/awt/Font.html

При использовании системных шрифтов размер уже задан в данных аргументах.

Однако при использовании ttf это не так, и размер необходимо задавать вручную:

font = font.deriveFont( 20f );

Также обратите внимание, что это значение с плавающей запятой, потому что функция deriveFont перегружена значением int, которое устанавливает стиль, а не размер.

person luckydonald    schedule 04.07.2014