Java Swing 2D. Шрифты

Помечено: , , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 1 месяц, 3 нед. назад.

  • Автор
    Сообщения
  • #5248
    @admin

    Java различает два типа шрифтов: физические и логические.

    Физический шрифт является библиотекой содержащей образы символов (т.е. глифы) и таблицы отображения последовательности символов в последовательность глифов. Всегда гарантировано отображение TrueType шрифтов, поддержка других технологий зависит от реализации java.

    Также гарантировано отображение пяти логических шрифтов обозначающих пять семейств шрифтов: Serif, SansSerif, Monospaced, Dialog и DialogInput. В отличие от физических шрифтов они не содержат образы символов, а используют физические шрифты для их отображения. По этой причине логические шрифты могут выглядеть по разному.

    Сам шрифт описывается классом Font. Ниже приведено простое использование шрифта.

    public class MyComponent extends JComponent {
    
        private static final long serialVersionUID = 1L;
        private Font f1 = new Font("TimesRoman", Font.BOLD, 22), 
                f2 = new Font("Courier", Font.ITALIC, 10), 
                f3 = new Font("Arial", Font.BOLD + Font.ITALIC, 16); 
        private String str = "Hello World";
    
        public MyComponent() {
        }
    
        @Override
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            Dimension d = getSize(null);
            g2.setBackground(Color.gray);
            g2.clearRect(0, 0, d.width, d.height);
            g2.setColor(Color.cyan);
    
            // выводим строку тремя разными шрифтами
            g2.setFont(f1);
            g2.drawString(str, 10, 30);
            g2.setFont(f2);        
            g2.drawString(str, 10, 60);
            g2.setFont(f3);        
            g2.drawString(str, 10, 90);
        }
    }
    

    имя шрифта

    Шрифт может иметь несколько обликов как жирный, наклонный, готический или обычный. Все эти облики имеют одинаковый типографический дизайн. Таким образом, к шрифту применимо три имени: логическое имя шрифта, имя облика шрифта или попросту имя шрифта (например, Helvetica Bold), и имя семейства шрифтов, определяющее типографический дизайн (например, Helvetica). Для получения имен в классе Font определены следующие методы:

    • getFamily() — имя семейства данного шрифта;
    • getFamily(Locale l) — локализованное имя семейства данного шрифта;
    • getFontName() — имя облика шрифта;
    • getFontName(Locale l) — локализованное имя облика шрифта;
    • getName() — логическое имя шрифта;
    • getPSName() — посткрипт имя шрифта.

    создание шрифтов

    Помимо конструкторов класс Font имеет дополнительные методы для создания новых шрифтов:

    • decode(String str) — статический метод создающий шрифт по строке описания, например вызов с аргументом «Arial-BOLD-18» аналогично конструктору new Font(«Arial», Font.BOLD, 18). Строка может принимать один из следующий форматов:
      • имя_шрифта-стиль-размер
      • имя_шрифта-стиль
      • имя_шрифта-размер
      • имя_шрифта стиль размер
      • имя_шрифта стиль
      • имя_шрифта размер
      • имя_шрифта
    • getFont(String nm) — статический метод для получения шрифта из системного списка свойств (см. System.getProperties()), значение того свойства будет интерпретироваться как объект типа Font через метод decode;
    • getFont(String nm, Font font) — аналогично предыдущему, но если свойство не найдено то будет возвращен указанный шрифт;
    • deriveFont(AffineTransform trans) — создает из текущего шрифта новый, применяя указанную трансформацию;
    • deriveFont(float size) — создает из текущего шрифта новый, применяя указанный размер;
    • deriveFont(int style) — создает из текущего шрифта новый, применяя указанный стиль;
    • deriveFont(int style, AffineTransform trans) — создает из текущего шрифта новый, применяя указанные стиль и трансформацию;
    • deriveFont(int style, float size) — создает из текущего шрифта новый, применяя указанные стиль и размер;
    • deriveFont(Map<? extends AttributedCharacterIterator.Attribute,?> attributes) — создает из текущего шрифта новый, применяя указанные атрибуты;
    • getFont(Map<? extends AttributedCharacterIterator.Attribute,?> attributes) — статический метод создающий шрифт с указанными атрибутами;
    • createFont(int fontFormat, File fontFile) — статический метод, создающий шрифт указанного типа (значение FONT.TRUETYPE) из указанного файла.

    стиль, размер и аффинное преобразование

    • getItalicAngle() — угол наклона;
    • getSize() — размер точки данного шрифта как число типа int;
    • getSize2D() — размер точки данного шрифта как число типа float;
    • getStyle() — текущий стиль шрифта;
    • getTransform() — текущее преобразование связанное с данным шрифтом;
    • isBold() — имеет ли шрифт стиль BOLD;
    • isItalic() — имеет ли шрифт стиль ITALIC;
    • isPlain() — имеет ли шрифт стиль PLAIN;
    • isTransformed() — применено ли аффинное преобразование к данному шрифту.

    атрибуты шрифта

    • getAttributes() — получить атрибуты шрифта в виде объекта типа Map;
    • getAvailableAttributes() — получить массив ключей для всех атрибутов поддерживаемых данным шрифтом;
    • hasLayoutAttributes() — содержит ли шрифт атрибуты требующих дополнительной обработки расположения.

    метрические линии

    Для вывода символов используются ряд линий вдоль которых и распологаются символы. Например, базовая линии определяет месторасположения символов не имеющих подстрочной части как символ o. Информация о них содержится в абстрактном классе LineMetrics. Один и тот же шрифт может иметь различные метрики для различных диапазонов символов. Для получения значений этих линий для указанного текста в классе Font предусмотрено четыре метода, различающихся способом задания текста:

    • getLineMetrics(char[] chars, int beginIndex, int limit, FontRenderContext frc);
    • getLineMetrics(CharacterIterator ci, int beginIndex, int limit, FontRenderContext frc);
    • getLineMetrics(String str, FontRenderContext frc);
    • getLineMetrics(String str, int beginIndex, int limit, FontRenderContext frc);
    • getBaselineFor(char c) — базовая линия для отображения указанного символа;
    • hasUniformLineMetrics() — имеет ли шрифт однородные метрические линии. Разнородность может появиться если логический шрифт для отображения символов использует несколько различных физических шрифтов.

    Ниже приведены методы класса LineMetrics:

    • getAscent() — верхняя граница до которой доходит надстрочная часть образа символа
      (например, в d и t), обычно определяет высоту заглавной буквы;
    • getDescent() — нижняя граница до которой доходит подстрочная часть образа символа
      (например, в q и g);
    • getHeight() — высота текста;
    • getLeading() — межстрочное расстояние — рекомендуемое расстояние от нижней границы
      одной строки текста до верхней границы следующей;
    • getNumChars() — число символов в тексте для которого были вычислены метрики;
    • getBaselineIndex() — индекс базовой линии текста:
      • ROMAN_BASELINE — базовая линия, используемая в большинстве романских алфавитов;
      • CENTER_BASELINE — базовая линия, используемая в алфавитах с иероглифами как японский;
      • HANGING_BASELINE — базовая линия, используемая в алфавитах сходных с деванагари;
    • getBaselineOffsets() — массив смещений всех типов базовых линий относительно
      базовой линии текста. Например, если базовая линия текста CENTER_BASELINE, то
      getBaselineOffsets()[CENTER_BASELINE] будет равно 0 т.е. нулевое смещение;
    • getStrikethroughOffset() — смещение зачеркивающей линии относительно базовой линии;
    • getStrikethroughThickness() — толщина зачеркивающей линии;
    • getUnderlineOffset() — смещение линии подчеркивания относительно базовой линии;
    • getUnderlineThickness() — толщина линии подчеркивания.

    В следующем примере выводится текст и некоторые соответствующие ему линии.

    public class MyComponent extends JComponent {
    
        private static final long serialVersionUID = 1L;
        private Font f = new Font("TimesRoman", Font.PLAIN, 42); 
        private String str = "replica: Hello world";
    
        public MyComponent() {
        }
    
        @Override
        public void paint(Graphics g) {
            float x = 10, y = 60;        
            Graphics2D g2 = (Graphics2D) g;
            
            // очищаем фон
            Dimension d = getSize(null);
            g2.setBackground(Color.white);
            g2.clearRect(0, 0, d.width, d.height);
    
            
            // получаем контекст отображения шрифта
            FontRenderContext frc = g2.getFontRenderContext();
            // получаем метрики шрифта
            LineMetrics lm = f.getLineMetrics(str, frc);
            
            // устанавливаем шрифт
            g2.setFont(f);
    
            // вывод базовой линия шрифта        
            double width = f.getStringBounds(str, frc).getWidth();
            g2.setColor(Color.cyan);
            g2.draw(new Line2D.Double(x, y, x + width, y));
    
            // вывод верхней границы
            g2.setColor(Color.red);        
            g2.draw(new Line2D.Double(x, y - lm.getAscent(), x + width, y
                    - lm.getAscent()));
    
            // вывод нижней границы
            g2.setColor(Color.green);
            g2.draw(new Line2D.Double(x, y + lm.getDescent(), x + width, y
                    + lm.getDescent()));
    
            // вывод межстрочного расстояния
            g2.setColor(Color.blue );
            g2.draw(new Line2D.Double(x, y + lm.getDescent()
                    + lm.getLeading(), x + width, y + lm.getDescent()
                    + lm.getLeading()));
    
            g2.setColor(Color.black );
            g2.drawString(str, x, y);
        }
    }
    

    глифы

    Информацию о глифах можно получить следующими методами класса Font:

    • canDisplay(char c) — есть ли в шрифте образ для указанного символа;
    • canDisplay(int codePoint) — есть ли в шрифте образ для указанного символа;
    • canDisplayUpTo(char[] txt, int start, int limit) — может ли шрифт отобразить символы в указанной части строки. Возвращаемое значение >0 указывает индекс первого не отображаемого символа, -1 если все символы могут быть отображены;
    • canDisplayUpTo(CharacterIterator it, int start, int limit) — аналогично предыдущему для диапазона символов;
    • canDisplayUpTo(String str) — аналогично предыдущему для символов строки;
    • getStringBounds(char[] chars, int beginIndex, int limit, FontRenderContext frc) — логические границы для указанного текста в указанном контексте отображения шрифта. Как и в canDisplayUpTo текст можно указать различными способами;
    • getNumGlyphs() — число глифов в данном шрифте;
    • getMissingGlyphCode() — код глифа, используемого по умолчанию, когда нет нужного глифа;
    • createGlyphVector(FontRenderContext frc, char[] chars) — получить глифы указанных символов;
    • createGlyphVector(FontRenderContext frc, CharacterIterator ci) — получить глифы указанных символов;
    • createGlyphVector(FontRenderContext frc, String str) — получить глифы указанных символов;
    • layoutGlyphVector(FontRenderContext frc, char[] text, int start, int limit, int flags) — получить глифы, выполняя повозможности полное расположение текста. Метод нужен для языков со сложным алфавитом как арабский и хинди.

Для ответа в этой теме необходимо авторизоваться.