86 * 87 * I'd expect that the majority of scripts use the default mapper for 88 * a particular font. Loading the hastable with 40 or so keys 30+ of 89 * which all map to the same object is unfortunate. It might be worth 90 * instead having a per-font list of 'scripts with non-default 91 * engines', e.g. the factory has a hashtable mapping fonts to 'script 92 * lists' (the factory has this since the design potentially has other 93 * factories, though I admit there's no client for this yet and no 94 * public api) and then the script list is queried for the script in 95 * question. it can be preloaded at creation time with all the 96 * scripts that don't have default engines-- either a list or a hash 97 * table, so a null return from the table means 'default' and not 'i 98 * don't know yet'. 99 * 100 * On the other hand, in most all cases the number of unique 101 * script/font combinations will be small, so a flat hashtable should 102 * suffice. 103 * */ 104 public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory { 105 private static native void initGVIDs(); 106 static { 107 FontManagerNativeLibrary.load(); 108 initGVIDs(); 109 } 110 111 private LayoutEngineKey key; 112 113 private static LayoutEngineFactory instance; 114 115 public static LayoutEngineFactory instance() { 116 if (instance == null) { 117 instance = new SunLayoutEngine(); 118 } 119 return instance; 120 } 121 122 private SunLayoutEngine() { 123 // actually a factory, key is null so layout cannot be called on it 124 } 125 126 public LayoutEngine getEngine(Font2D font, int script, int lang) { 127 return getEngine(new LayoutEngineKey(font, script, lang)); 128 } 133 if (cache == null) { 134 cache = new ConcurrentHashMap<>(); 135 cacheref = new SoftReference<>(cache); 136 } 137 138 LayoutEngine e = cache.get(key); 139 if (e == null) { 140 LayoutEngineKey copy = key.copy(); 141 e = new SunLayoutEngine(copy); 142 cache.put(copy, e); 143 } 144 return e; 145 } 146 private SoftReference<ConcurrentHashMap<LayoutEngineKey, LayoutEngine>> cacheref = 147 new SoftReference<>(null); 148 149 private SunLayoutEngine(LayoutEngineKey key) { 150 this.key = key; 151 } 152 153 public void layout(FontStrikeDesc desc, float[] mat, int gmask, 154 int baseIndex, TextRecord tr, int typo_flags, 155 Point2D.Float pt, GVData data) { 156 Font2D font = key.font(); 157 FontStrike strike = font.getStrike(desc); 158 long layoutTables = font.getLayoutTableCache(); 159 nativeLayout(font, strike, mat, gmask, baseIndex, 160 tr.text, tr.start, tr.limit, tr.min, tr.max, 161 key.script(), key.lang(), typo_flags, pt, data, 162 font.getUnitsPerEm(), layoutTables); 163 } 164 165 private static native void 166 nativeLayout(Font2D font, FontStrike strike, float[] mat, int gmask, 167 int baseIndex, char[] chars, int offset, int limit, 168 int min, int max, int script, int lang, int typo_flags, 169 Point2D.Float pt, GVData data, long upem, long layoutTables); 170 } | 86 * 87 * I'd expect that the majority of scripts use the default mapper for 88 * a particular font. Loading the hastable with 40 or so keys 30+ of 89 * which all map to the same object is unfortunate. It might be worth 90 * instead having a per-font list of 'scripts with non-default 91 * engines', e.g. the factory has a hashtable mapping fonts to 'script 92 * lists' (the factory has this since the design potentially has other 93 * factories, though I admit there's no client for this yet and no 94 * public api) and then the script list is queried for the script in 95 * question. it can be preloaded at creation time with all the 96 * scripts that don't have default engines-- either a list or a hash 97 * table, so a null return from the table means 'default' and not 'i 98 * don't know yet'. 99 * 100 * On the other hand, in most all cases the number of unique 101 * script/font combinations will be small, so a flat hashtable should 102 * suffice. 103 * */ 104 public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory { 105 private static native void initGVIDs(); 106 private static final boolean useICU; 107 static { 108 FontManagerNativeLibrary.load(); 109 initGVIDs(); 110 String le = java.security.AccessController.doPrivileged( 111 new sun.security.action. 112 GetPropertyAction("sun.font.layoutengine", "")); 113 useICU = le.equals("icu"); 114 String verbose = java.security.AccessController.doPrivileged( 115 new sun.security.action. 116 GetPropertyAction("sun.font.layoutengine.verbose", "")); 117 if ("true".equalsIgnoreCase(verbose)) { 118 System.out.println("Using " + (useICU ? "icu." : "harfbuzz.")); 119 } 120 } 121 122 private LayoutEngineKey key; 123 124 private static LayoutEngineFactory instance; 125 126 public static LayoutEngineFactory instance() { 127 if (instance == null) { 128 instance = new SunLayoutEngine(); 129 } 130 return instance; 131 } 132 133 private SunLayoutEngine() { 134 // actually a factory, key is null so layout cannot be called on it 135 } 136 137 public LayoutEngine getEngine(Font2D font, int script, int lang) { 138 return getEngine(new LayoutEngineKey(font, script, lang)); 139 } 144 if (cache == null) { 145 cache = new ConcurrentHashMap<>(); 146 cacheref = new SoftReference<>(cache); 147 } 148 149 LayoutEngine e = cache.get(key); 150 if (e == null) { 151 LayoutEngineKey copy = key.copy(); 152 e = new SunLayoutEngine(copy); 153 cache.put(copy, e); 154 } 155 return e; 156 } 157 private SoftReference<ConcurrentHashMap<LayoutEngineKey, LayoutEngine>> cacheref = 158 new SoftReference<>(null); 159 160 private SunLayoutEngine(LayoutEngineKey key) { 161 this.key = key; 162 } 163 164 private boolean isAAT(Font2D font) { 165 if (font instanceof TrueTypeFont) { 166 TrueTypeFont ttf = (TrueTypeFont)font; 167 return ttf.getDirectoryEntry(TrueTypeFont.morxTag) != null || 168 ttf.getDirectoryEntry(TrueTypeFont.mortTag) != null; 169 } else if (font instanceof PhysicalFont) { 170 PhysicalFont pf = (PhysicalFont)font; 171 return pf.getTableBytes(TrueTypeFont.morxTag) != null || 172 pf.getTableBytes(TrueTypeFont.mortTag) != null; 173 } 174 return false; 175 } 176 177 public void layout(FontStrikeDesc desc, float[] mat, int gmask, 178 int baseIndex, TextRecord tr, int typo_flags, 179 Point2D.Float pt, GVData data) { 180 Font2D font = key.font(); 181 FontStrike strike = font.getStrike(desc); 182 long layoutTables = font.getLayoutTableCache(); 183 if (useICU) { 184 nativeLayout(font, strike, mat, gmask, baseIndex, 185 tr.text, tr.start, tr.limit, tr.min, tr.max, 186 key.script(), key.lang(), typo_flags, pt, data, 187 font.getUnitsPerEm(), layoutTables); 188 } else { 189 long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX 190 // pScaler probably not needed long term. 191 long pScaler = 0L; 192 if (font instanceof FileFont) { 193 pScaler = ((FileFont)font).getScaler().nativeScaler; 194 } 195 shape(font, strike, mat, pScaler, pNativeFont, isAAT(font), 196 tr.text, data, key.script(), 197 tr.start, tr.limit, baseIndex, pt, 198 typo_flags, gmask); 199 } 200 } 201 202 /* Native method to invoke ICU layout engine */ 203 private static native void 204 nativeLayout(Font2D font, FontStrike strike, float[] mat, int gmask, 205 int baseIndex, char[] chars, int offset, int limit, 206 int min, int max, int script, int lang, int typo_flags, 207 Point2D.Float pt, GVData data, long upem, long layoutTables); 208 209 210 /* Native method to invoke harfbuzz layout engine */ 211 private static native boolean 212 shape(Font2D font, FontStrike strike, float[] mat, 213 long pscaler, long pNativeFont, boolean aat, 214 char[] chars, GVData data, 215 int script, int offset, int limit, 216 int baseIndex, Point2D.Float pt, int typo_flags, int slot); 217 } |