1/*
2 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include "stdlib.h"
27#include "string.h"
28#include "gdefs.h"
29#include "jlong.h"
30#include "jni_util.h"
31#include "sunfontids.h"
32#include "fontscalerdefs.h"
33#include "sun_font_SunFontManager.h"
34#include "sun_font_NullFontScaler.h"
35#include "sun_font_StrikeCache.h"
36
37static void *theNullScalerContext = NULL;
38extern void AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph);
39
40/*
41 * Declare library specific JNI_Onload entry if static build
42 */
43DEF_STATIC_JNI_OnLoad
44
45JNIEXPORT jlong JNICALL
46Java_sun_font_NullFontScaler_getNullScalerContext
47 (JNIEnv *env, jclass scalerClass) {
48
49 if (theNullScalerContext == NULL) {
50 theNullScalerContext = malloc(1);
51 }
52 return ptr_to_jlong(theNullScalerContext);
53}
54
55int isNullScalerContext(void *context) {
56 return theNullScalerContext == context;
57}
58
59/* Eventually we may rework it to be a singleton.
60 * This will require additional checks in freeLongMemory/freeIntMemory
61 * and on other hand malformed fonts (main source of null glyph images)
62 * are supposed to be collected fast.
63 * But perhaps it is still right thing to do.
64 * Even better is to eliminate the need to have this native method
65 * but for this it is necessary to rework Strike and drawing logic
66 * to be able to live with NULL pointers without performance hit.
67 */
68JNIEXPORT jlong JNICALL Java_sun_font_NullFontScaler_getGlyphImage
69 (JNIEnv *env, jobject scaler, jlong pContext, jint glyphCode) {
70 void *nullscaler = calloc(sizeof(GlyphInfo), 1);
71 return ptr_to_jlong(nullscaler);
72}
73
74
75
76void initLCDGammaTables();
77
78/* placeholder for extern variable */
79static int initialisedFontIDs = 0;
80FontManagerNativeIDs sunFontIDs;
81
82static void initFontIDs(JNIEnv *env) {
83
84 jclass tmpClass;
85
86 if (initialisedFontIDs) {
87 return;
88 }
89 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont"));
90 CHECK_NULL(sunFontIDs.ttReadBlockMID =
91 (*env)->GetMethodID(env, tmpClass, "readBlock",
92 "(Ljava/nio/ByteBuffer;II)I"));
93 CHECK_NULL(sunFontIDs.ttReadBytesMID =
94 (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B"));
95
96 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Type1Font"));
97 CHECK_NULL(sunFontIDs.readFileMID =
98 (*env)->GetMethodID(env, tmpClass,
99 "readFile", "(Ljava/nio/ByteBuffer;)V"));
100
101 CHECK_NULL(tmpClass =
102 (*env)->FindClass(env, "java/awt/geom/Point2D$Float"));
103 sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
104 CHECK_NULL(sunFontIDs.pt2DFloatCtr =
105 (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V"));
106
107 CHECK_NULL(sunFontIDs.xFID =
108 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F"));
109 CHECK_NULL(sunFontIDs.yFID =
110 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F"));
111
112 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics"));
113 CHECK_NULL(sunFontIDs.strikeMetricsClass =
114 (jclass)(*env)->NewGlobalRef(env, tmpClass));
115
116 CHECK_NULL(sunFontIDs.strikeMetricsCtr =
117 (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass,
118 "<init>", "(FFFFFFFFFF)V"));
119
120 CHECK_NULL(tmpClass =
121 (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float"));
122 sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
123 CHECK_NULL(sunFontIDs.rect2DFloatCtr =
124 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V"));
125 CHECK_NULL(sunFontIDs.rect2DFloatCtr4 =
126 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass,
127 "<init>", "(FFFF)V"));
128 CHECK_NULL(sunFontIDs.rectF2DX =
129 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F"));
130 CHECK_NULL(sunFontIDs.rectF2DY =
131 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F"));
132 CHECK_NULL(sunFontIDs.rectF2DWidth =
133 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F"));
134 CHECK_NULL(sunFontIDs.rectF2DHeight =
135 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F"));
136
137 CHECK_NULL(tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath"));
138 sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
139 CHECK_NULL(sunFontIDs.gpCtr =
140 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V"));
141 CHECK_NULL(sunFontIDs.gpCtrEmpty =
142 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V"));
143
144 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Font2D"));
145 CHECK_NULL(sunFontIDs.f2dCharToGlyphMID =
146 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"));
147 CHECK_NULL(sunFontIDs.f2dCharToVariationGlyphMID =
148 (*env)->GetMethodID(env, tmpClass, "charToVariationGlyph", "(II)I"));
149 CHECK_NULL(sunFontIDs.getMapperMID =
150 (*env)->GetMethodID(env, tmpClass, "getMapper",
151 "()Lsun/font/CharToGlyphMapper;"));
152 CHECK_NULL(sunFontIDs.getTableBytesMID =
153 (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B"));
154 CHECK_NULL(sunFontIDs.canDisplayMID =
155 (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z"));
156
157 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper"));
158 CHECK_NULL(sunFontIDs.charToGlyphMID =
159 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"));
160
161 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike"));
162 CHECK_NULL(sunFontIDs.getGlyphMetricsMID =
163 (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics",
164 "(I)Ljava/awt/geom/Point2D$Float;"));
165 CHECK_NULL(sunFontIDs.getGlyphPointMID =
166 (*env)->GetMethodID(env, tmpClass, "getGlyphPoint",
167 "(II)Ljava/awt/geom/Point2D$Float;"));
168 CHECK_NULL(sunFontIDs.adjustPointMID =
169 (*env)->GetMethodID(env, tmpClass, "adjustPoint",
170 "(Ljava/awt/geom/Point2D$Float;)V"));
171 CHECK_NULL(sunFontIDs.pScalerContextFID =
172 (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J"));
173
174 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList"));
175 CHECK_NULL(sunFontIDs.glyphListX =
176 (*env)->GetFieldID(env, tmpClass, "x", "F"));
177 CHECK_NULL(sunFontIDs.glyphListY =
178 (*env)->GetFieldID(env, tmpClass, "y", "F"));
179 CHECK_NULL(sunFontIDs.glyphListLen =
180 (*env)->GetFieldID(env, tmpClass, "len", "I"));
181 CHECK_NULL(sunFontIDs.glyphImages =
182 (*env)->GetFieldID(env, tmpClass, "images", "[J"));
183 CHECK_NULL(sunFontIDs.glyphListUsePos =
184 (*env)->GetFieldID(env, tmpClass, "usePositions", "Z"));
185 CHECK_NULL(sunFontIDs.glyphListPos =
186 (*env)->GetFieldID(env, tmpClass, "positions", "[F"));
187 CHECK_NULL(sunFontIDs.lcdRGBOrder =
188 (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z"));
189 CHECK_NULL(sunFontIDs.lcdSubPixPos =
190 (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z"));
191
192 initLCDGammaTables();
193
194 initialisedFontIDs = 1;
195}
196
197JNIEXPORT void JNICALL
198Java_sun_font_SunFontManager_initIDs
199 (JNIEnv *env, jclass cls) {
200
201 initFontIDs(env);
202}
203
204JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv *env) {
205
206 initFontIDs(env);
207 return sunFontIDs;
208}
209
210/*
211 * Class: sun_font_StrikeCache
212 * Method: freeIntPointer
213 * Signature: (I)V
214 */
215JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer
216 (JNIEnv *env, jclass cacheClass, jint ptr) {
217
218 /* Note this is used for freeing a glyph which was allocated
219 * but never placed into the glyph cache. The caller holds the
220 * only reference, therefore it is unnecessary to invalidate any
221 * accelerated glyph cache cells as we do in freeInt/LongMemory().
222 */
223 if (ptr != 0) {
224 free((void*)((intptr_t)ptr));
225 }
226}
227
228/*
229 * Class: sun_font_StrikeCache
230 * Method: freeLongPointer
231 * Signature: (J)V
232 */
233JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer
234 (JNIEnv *env, jclass cacheClass, jlong ptr) {
235
236 /* Note this is used for freeing a glyph which was allocated
237 * but never placed into the glyph cache. The caller holds the
238 * only reference, therefore it is unnecessary to invalidate any
239 * accelerated glyph cache cells as we do in freeInt/LongMemory().
240 */
241 if (ptr != 0L) {
242 free(jlong_to_ptr(ptr));
243 }
244}
245
246/*
247 * Class: sun_font_StrikeCache
248 * Method: freeIntMemory
249 * Signature: ([I)V
250 */
251JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory
252 (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) {
253
254 int len = (*env)->GetArrayLength(env, jmemArray);
255 jint* ptrs =
256 (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL);
257 int i;
258
259 if (ptrs) {
260 for (i=0; i< len; i++) {
261 if (ptrs[i] != 0) {
262 GlyphInfo *ginfo = (GlyphInfo *)((intptr_t)ptrs[i]);
263 if (ginfo->cellInfo != NULL &&
264 ginfo->managed == MANAGED_GLYPH) {
265 // invalidate this glyph's accelerated cache cell
266 AccelGlyphCache_RemoveAllCellInfos(ginfo);
267 }
268 free(ginfo);
269 }
270 }
271 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT);
272 }
273 if (!isNullScalerContext(jlong_to_ptr(pContext))) {
274 free(jlong_to_ptr(pContext));
275 }
276}
277
278/*
279 * Class: sun_font_StrikeCache
280 * Method: freeLongMemory
281 * Signature: ([J)V
282 */
283JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory
284 (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) {
285
286 int len = (*env)->GetArrayLength(env, jmemArray);
287 jlong* ptrs =
288 (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL);
289 int i;
290
291 if (ptrs) {
292 for (i=0; i< len; i++) {
293 if (ptrs[i] != 0L) {
294 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]);
295 if (ginfo->cellInfo != NULL &&
296 ginfo->managed == MANAGED_GLYPH) {
297 AccelGlyphCache_RemoveAllCellInfos(ginfo);
298 }
299 free((void*)ginfo);
300 }
301 }
302 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT);
303 }
304 if (!isNullScalerContext(jlong_to_ptr(pContext))) {
305 free(jlong_to_ptr(pContext));
306 }
307}
308
309JNIEXPORT void JNICALL
310Java_sun_font_StrikeCache_getGlyphCacheDescription
311 (JNIEnv *env, jclass cls, jlongArray results) {
312
313 jlong* nresults;
314 GlyphInfo *info;
315 size_t baseAddr;
316
317 if ((*env)->GetArrayLength(env, results) < 13) {
318 return;
319 }
320
321 nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL);
322 if (nresults == NULL) {
323 return;
324 }
325 info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
326 if (info == NULL) {
327 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
328 return;
329 }
330 baseAddr = (size_t)info;
331 nresults[0] = sizeof(void*);
332 nresults[1] = sizeof(GlyphInfo);
333 nresults[2] = 0;
334 nresults[3] = (size_t)&(info->advanceY)-baseAddr;
335 nresults[4] = (size_t)&(info->width)-baseAddr;
336 nresults[5] = (size_t)&(info->height)-baseAddr;
337 nresults[6] = (size_t)&(info->rowBytes)-baseAddr;
338 nresults[7] = (size_t)&(info->topLeftX)-baseAddr;
339 nresults[8] = (size_t)&(info->topLeftY)-baseAddr;
340 nresults[9] = (size_t)&(info->image)-baseAddr;
341 nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */
342 nresults[11] = (size_t)&(info->cellInfo)-baseAddr;
343 nresults[12] = (size_t)&(info->managed)-baseAddr;
344
345 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
346}
347