Java examples for 2D Graphics:Font
Gets all kerning pairs of a Font.
/*/*from w w w . j a v a2s. c o m*/ * Copyright (C) 2010-2015 JPEXS, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.font.TextAttribute; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.text.AttributedCharacterIterator; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.swing.JPanel; public class Main{ /** * Gets all kerning pairs of a Font. It is very slow. * * @param font * @param size * @return */ public static List<KerningPair> getFontKerningPairs(Font font, int size) { File fontFile = getFontFile(font); if (fontFile != null && fontFile.getName().toLowerCase().endsWith(".ttf")) { KerningLoader k = new KerningLoader(); try { return k.loadFromTTF(fontFile, size); } catch (IOException | FontFormatException ex) { // ignore } } List<KerningPair> ret = new ArrayList<>(); List<Character> availableChars = new ArrayList<>(); for (char c1 = 0; c1 < Character.MAX_VALUE; c1++) { if (font.canDisplay((int) c1)) { availableChars.add(c1); } } for (char c1 : availableChars) { ret.addAll(getFontKerningPairsOneChar(availableChars, font, c1)); } return ret; } public static File getFontFile(Font f) { try { Class pfClass = Class.forName("sun.font.PhysicalFont"); Field platName = pfClass.getDeclaredField("platName"); platName.setAccessible(true); String fontPath = (String) platName.get(getFont2d(f)); platName.setAccessible(false); return new File(fontPath); } catch (Throwable e) { return null; } } private static List<KerningPair> getFontKerningPairsOneChar( List<Character> availableChars, Font font, char firstChar) { List<KerningPair> ret = new ArrayList<>(); char[] chars = new char[availableChars.size() * 2]; for (int i = 0; i < availableChars.size(); i++) { chars[i * 2] = firstChar; chars[i * 2 + 1] = availableChars.get(i); } Map<AttributedCharacterIterator.Attribute, Object> withKerningAttrs = new HashMap<>(); withKerningAttrs.put(TextAttribute.FONT, font); withKerningAttrs.put(TextAttribute.KERNING, TextAttribute.KERNING_ON); Font withKerningFont = Font.getFont(withKerningAttrs); GlyphVector withKerningVector = withKerningFont.layoutGlyphVector( getFontRenderContext(withKerningFont), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT); int withKerningX[] = new int[availableChars.size()]; for (int i = 0; i < availableChars.size(); i++) { withKerningX[i] = withKerningVector.getGlyphLogicalBounds( i * 2 + 1).getBounds().x; } Map<AttributedCharacterIterator.Attribute, Object> noKerningAttrs = new HashMap<>(); noKerningAttrs.put(TextAttribute.FONT, font); noKerningAttrs.put(TextAttribute.KERNING, 0); Font noKerningFont = Font.getFont(noKerningAttrs); GlyphVector noKerningVector = noKerningFont.layoutGlyphVector( getFontRenderContext(noKerningFont), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT); for (int i = 0; i < availableChars.size(); i++) { int noKerningX = noKerningVector.getGlyphLogicalBounds( i * 2 + 1).getBounds().x; int kerning = withKerningX[i] - noKerningX; if (kerning > 0) { ret.add(new KerningPair(firstChar, availableChars.get(i), kerning)); } } return ret; } private static Object getFont2d(Font f) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Object fm = getFontManager(); return Class .forName("sun.font.FontManager") .getDeclaredMethod("findFont2D", String.class, int.class, int.class) .invoke(fm, f.getFontName(), f.getStyle(), 2/*LOGICAL_FALLBACK*/); } private static FontRenderContext getFontRenderContext(Font font) { return (new JPanel()).getFontMetrics(font).getFontRenderContext(); } private static Object getFontManager() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class<?> clFmFactory = Class.forName("sun.font.FontManagerFactory"); return clFmFactory.getDeclaredMethod("getInstance").invoke(null); } }