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, float ptSize, 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, ptSize, 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 ptSize, 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 }
|