14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 /*
27 *
28 * (C) Copyright IBM Corp. 2003 - All Rights Reserved
29 */
30
31 package sun.font;
32
33 import sun.font.GlyphLayout.*;
34 import java.awt.geom.Point2D;
35 import java.lang.ref.SoftReference;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.Locale;
38 import java.util.WeakHashMap;
39
40 /*
41 * different ways to do this
42 * 1) each physical font2d keeps a hashtable mapping scripts to layout
43 * engines, we query and fill this cache.
44 * 2) we keep a mapping independent of font using the key Most likely
45 * few fonts will be used, so option 2 seems better
46 *
47 * Once we know which engine to use for a font, we always know, so we
48 * shouldn't have to recheck each time we do layout. So the cache is
49 * ok.
50 *
51 * Should we reuse engines? We could instantiate an engine for each
52 * font/script pair. The engine would hold onto the table(s) from the
53 * font that it needs. If we have multiple threads using the same
54 * engine, we still need to keep the state separate, so the native
55 * engines would still need to be allocated for each call, since they
56 * keep their state in themselves. If they used the passed-in GVData
57 * arrays directly (with some checks for space) then since each GVData
133 cache = new ConcurrentHashMap<>();
134 cacheref = new SoftReference<>(cache);
135 }
136
137 LayoutEngine e = cache.get(key);
138 if (e == null) {
139 LayoutEngineKey copy = key.copy();
140 e = new SunLayoutEngine(copy);
141 cache.put(copy, e);
142 }
143 return e;
144 }
145 private SoftReference<ConcurrentHashMap<LayoutEngineKey, LayoutEngine>> cacheref =
146 new SoftReference<>(null);
147
148 private SunLayoutEngine(LayoutEngineKey key) {
149 this.key = key;
150 }
151
152 static WeakHashMap<Font2D, Boolean> aatInfo = new WeakHashMap<>();
153
154 private boolean isAAT(Font2D font) {
155 Boolean aatObj;
156 synchronized (aatInfo) {
157 aatObj = aatInfo.get(font);
158 }
159 if (aatObj != null) {
160 return aatObj.booleanValue();
161 }
162 boolean aat = false;
163 if (font instanceof TrueTypeFont) {
164 TrueTypeFont ttf = (TrueTypeFont)font;
165 aat = ttf.getDirectoryEntry(TrueTypeFont.morxTag) != null ||
166 ttf.getDirectoryEntry(TrueTypeFont.mortTag) != null;
167 } else if (font instanceof PhysicalFont) {
168 PhysicalFont pf = (PhysicalFont)font;
169 aat = pf.getTableBytes(TrueTypeFont.morxTag) != null ||
170 pf.getTableBytes(TrueTypeFont.mortTag) != null;
171 }
172 synchronized (aatInfo) {
173 aatInfo.put(font, Boolean.valueOf(aat));
174 }
175 return aat;
176 }
177
178 public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
179 int baseIndex, TextRecord tr, int typo_flags,
180 Point2D.Float pt, GVData data) {
181 Font2D font = key.font();
182 FontStrike strike = font.getStrike(desc);
183 long layoutTables = font.getLayoutTableCache();
184 long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX
185 // pScaler probably not needed long term.
186 long pScaler = 0L;
187 if (font instanceof FileFont) {
188 pScaler = ((FileFont)font).getScaler().nativeScaler;
189 }
190 shape(font, strike, ptSize, mat, pScaler, pNativeFont,
191 layoutTables, isAAT(font),
192 tr.text, data, key.script(),
193 tr.start, tr.limit, baseIndex, pt,
194 typo_flags, gmask);
195 }
196
197 /* Native method to invoke harfbuzz layout engine */
198 private static native boolean
199 shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
200 long pscaler, long pNativeFont, long layoutTables, boolean aat,
201 char[] chars, GVData data,
202 int script, int offset, int limit,
203 int baseIndex, Point2D.Float pt, int typo_flags, int slot);
204 }
|
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 /*
27 *
28 * (C) Copyright IBM Corp. 2003 - All Rights Reserved
29 */
30
31 package sun.font;
32
33 import sun.font.GlyphLayout.*;
34 import sun.java2d.Disposer;
35 import sun.java2d.DisposerRecord;
36
37 import java.awt.geom.Point2D;
38 import java.lang.ref.SoftReference;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.WeakHashMap;
41
42 /*
43 * different ways to do this
44 * 1) each physical font2d keeps a hashtable mapping scripts to layout
45 * engines, we query and fill this cache.
46 * 2) we keep a mapping independent of font using the key Most likely
47 * few fonts will be used, so option 2 seems better
48 *
49 * Once we know which engine to use for a font, we always know, so we
50 * shouldn't have to recheck each time we do layout. So the cache is
51 * ok.
52 *
53 * Should we reuse engines? We could instantiate an engine for each
54 * font/script pair. The engine would hold onto the table(s) from the
55 * font that it needs. If we have multiple threads using the same
56 * engine, we still need to keep the state separate, so the native
57 * engines would still need to be allocated for each call, since they
58 * keep their state in themselves. If they used the passed-in GVData
59 * arrays directly (with some checks for space) then since each GVData
135 cache = new ConcurrentHashMap<>();
136 cacheref = new SoftReference<>(cache);
137 }
138
139 LayoutEngine e = cache.get(key);
140 if (e == null) {
141 LayoutEngineKey copy = key.copy();
142 e = new SunLayoutEngine(copy);
143 cache.put(copy, e);
144 }
145 return e;
146 }
147 private SoftReference<ConcurrentHashMap<LayoutEngineKey, LayoutEngine>> cacheref =
148 new SoftReference<>(null);
149
150 private SunLayoutEngine(LayoutEngineKey key) {
151 this.key = key;
152 }
153
154 static WeakHashMap<Font2D, Boolean> aatInfo = new WeakHashMap<>();
155 private static final WeakHashMap<Font2D, FaceRef> facePtr =
156 new WeakHashMap<>();
157
158 private static boolean isAAT(Font2D font) {
159 Boolean aatObj;
160 synchronized (aatInfo) {
161 aatObj = aatInfo.get(font);
162 }
163 if (aatObj != null) {
164 return aatObj.booleanValue();
165 }
166 boolean aat = false;
167 if (font instanceof TrueTypeFont) {
168 TrueTypeFont ttf = (TrueTypeFont)font;
169 aat = ttf.getDirectoryEntry(TrueTypeFont.morxTag) != null ||
170 ttf.getDirectoryEntry(TrueTypeFont.mortTag) != null;
171 } else if (font instanceof PhysicalFont) {
172 PhysicalFont pf = (PhysicalFont)font;
173 aat = pf.getTableBytes(TrueTypeFont.morxTag) != null ||
174 pf.getTableBytes(TrueTypeFont.mortTag) != null;
175 }
176 synchronized (aatInfo) {
177 aatInfo.put(font, Boolean.valueOf(aat));
178 }
179 return aat;
180 }
181
182 private long getFacePtr(Font2D font2D) {
183 FaceRef ref;
184 synchronized (facePtr) {
185 ref = facePtr.computeIfAbsent(font2D, FaceRef::new);
186 }
187 return ref.getNativePtr();
188 }
189
190 public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
191 int baseIndex, TextRecord tr, int typo_flags,
192 Point2D.Float pt, GVData data) {
193 Font2D font = key.font();
194 FontStrike strike = font.getStrike(desc);
195 long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX
196 // pScaler probably not needed long term.
197 long pScaler = 0L;
198 if (font instanceof FileFont) {
199 pScaler = ((FileFont)font).getScaler().nativeScaler;
200 }
201 long pFace = getFacePtr(font);
202 if (pFace != 0) {
203 shape(font, strike, ptSize, mat, pScaler, pNativeFont,
204 pFace, isAAT(font),
205 tr.text, data, key.script(),
206 tr.start, tr.limit, baseIndex, pt,
207 typo_flags, gmask);
208 }
209 }
210
211 /* Native method to invoke harfbuzz layout engine */
212 private static native boolean
213 shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
214 long pscaler, long pNativeFont, long pFace, boolean aat,
215 char[] chars, GVData data,
216 int script, int offset, int limit,
217 int baseIndex, Point2D.Float pt, int typo_flags, int slot);
218
219 private static native long createFace(Font2D font,
220 boolean aat,
221 long platformNativeFontPtr,
222 long layoutTables);
223
224 private static native void disposeFace(long facePtr);
225
226 private static class FaceRef implements DisposerRecord {
227 private Font2D font;
228 private Long facePtr;
229
230 private FaceRef(Font2D font) {
231 this.font = font;
232 }
233
234 private synchronized long getNativePtr() {
235 if (facePtr == null) {
236 facePtr = createFace(font, isAAT(font),
237 font.getPlatformNativeFontPtr(),
238 font.getLayoutTableCache());
239 if (facePtr != 0) {
240 Disposer.addObjectRecord(font, this);
241 }
242 font = null;
243 }
244 return facePtr;
245 }
246
247 @Override
248 public void dispose() {
249 disposeFace(facePtr);
250 }
251 }
252 }
|