1 /*
2 * Copyright (c) 2003, 2012, 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 /*
27 * Important note : All AWTxxx functions are defined in font.h.
28 * These were added to remove the dependency of this file on X11.
29 * These functions are used to perform X11 operations and should
30 * be "stubbed out" in environments that do not support X11.
31 * The implementation of these functions has been moved from this file
32 * into X11FontScaler_md.c, which is compiled into another library.
33 */
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <sys/utsname.h>
38
39 #include <jni.h>
40 #include <jni_util.h>
41
42 #include "sun_font_NativeFont.h"
43 #include "sun_font_NativeStrike.h"
44 #include "sun_font_NativeStrikeDisposer.h"
45 #include "sunfontids.h"
46 #include "fontscalerdefs.h"
47 #include "X11FontScaler.h"
48
49 JNIEXPORT void JNICALL
Java_sun_font_NativeStrikeDisposer_freeNativeScalerContext(JNIEnv * env,jobject disposer,jlong pScalerContext)50 Java_sun_font_NativeStrikeDisposer_freeNativeScalerContext
51 (JNIEnv *env, jobject disposer, jlong pScalerContext) {
52
53 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
54
55 if (context != NULL) {
56 if (context->xFont != NULL) {
57 AWTFreeFont(context->xFont);
58 }
59 free(context);
60 }
61 }
62
63 JNIEXPORT jlong JNICALL
Java_sun_font_NativeStrike_createNullScalerContext(JNIEnv * env,jobject strike)64 Java_sun_font_NativeStrike_createNullScalerContext
65 (JNIEnv *env, jobject strike) {
66
67 NativeScalerContext *context =
68 (NativeScalerContext*)malloc(sizeof(NativeScalerContext));
69 context->xFont = NULL;
70 context->minGlyph = 0;
71 context->maxGlyph = 0;
72 context->numGlyphs = 0;
73 context->defaultGlyph = 0;
74 context->ptSize = NO_POINTSIZE;
75 return (jlong)(uintptr_t)context;
76 }
77
78 JNIEXPORT jlong JNICALL
Java_sun_font_NativeStrike_createScalerContext(JNIEnv * env,jobject strike,jbyteArray xlfdBytes,jint ptSize,jdouble scale)79 Java_sun_font_NativeStrike_createScalerContext
80 (JNIEnv *env, jobject strike, jbyteArray xlfdBytes,
81 jint ptSize, jdouble scale) {
82
83 NativeScalerContext *context;
84 int len = (*env)->GetArrayLength(env, xlfdBytes);
85
86 char* xlfd = (char*)malloc(len+1);
87
88 if (xlfd == NULL) {
89 return (jlong)(uintptr_t)0L;
90 }
91
92 (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
93 xlfd[len] = '\0';
94 context = (NativeScalerContext*)malloc(sizeof(NativeScalerContext));
95
96 AWTLoadFont (xlfd, &(context->xFont));
97 free(xlfd);
98
99 if (context->xFont == NULL) { /* NULL means couldn't find the font */
100 free(context);
101 context = NULL;
102 } else {
103 /* numGlyphs is an estimate : X11 doesn't provide a quick way to
104 * discover which glyphs are valid: just the range that contains all
105 * the valid glyphs, and this range may have holes.
106 */
107 context->minGlyph = (AWTFontMinByte1(context->xFont) << 8) +
108 AWTFontMinCharOrByte2(context->xFont);
109 context->maxGlyph = (AWTFontMaxByte1(context->xFont) << 8) +
110 AWTFontMaxCharOrByte2(context->xFont);
111 context->numGlyphs = context->maxGlyph - context->minGlyph + 1;
112 context->defaultGlyph = AWTFontDefaultChar(context->xFont);
113 /* Sometimes the default_char field of the XFontStruct isn't
114 * initialized to anything, so it can be a large number. So,
115 * check to see if its less than the largest possible value
116 * and if so, then use it. Otherwise, just use the minGlyph.
117 */
118 if (context->defaultGlyph < context->minGlyph ||
119 context->defaultGlyph > context->maxGlyph) {
120 context->defaultGlyph = context->minGlyph;
121 }
122 context->ptSize = ptSize;
123 context->scale = scale;
124 }
125
126 /*
127 * REMIND: freeing of native resources? XID, XFontStruct etc??
128 */
129 return (jlong)(uintptr_t)context;
130 }
131
132
133 /* JNIEXPORT jint JNICALL */
134 /* Java_sun_font_NativeFont_getItalicAngle */
135 /* (JNIEnv *env, jobject font) { */
136
137 /* UInt32 angle; */
138 /* AWTGetFontItalicAngle(xFont, &angle); */
139 /*X11 reports italic angle as 1/64ths of a degree, relative to 3 o'clock
140 * with anti-clockwise being the +ve rotation direction.
141 * We return
142 XGetFontProperty(xFont,XA_ITALIC_ANGLE, &angle);
143 */
144
145 /* return (jint)angle; */
146 /* } */
147
148 JNIEXPORT jboolean JNICALL
Java_sun_font_NativeFont_fontExists(JNIEnv * env,jclass fontClass,jbyteArray xlfdBytes)149 Java_sun_font_NativeFont_fontExists
150 (JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) {
151
152 int count = 0;
153 int len = (*env)->GetArrayLength(env, xlfdBytes);
154 char* xlfd = (char*)malloc(len+1);
155
156 if (xlfd == NULL) {
157 return JNI_FALSE;
158 }
159
160 (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
161 xlfd[len] = '\0';
162
163 count = AWTCountFonts(xlfd);
164 free(xlfd);
165 if (count > 0) {
166 return JNI_TRUE;
167 } else {
168 return JNI_FALSE;
169 }
170 }
171
172 JNIEXPORT jboolean JNICALL
Java_sun_font_NativeFont_haveBitmapFonts(JNIEnv * env,jclass fontClass,jbyteArray xlfdBytes)173 Java_sun_font_NativeFont_haveBitmapFonts
174 (JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) {
175
176 int count = 0;
177 int len = (*env)->GetArrayLength(env, xlfdBytes);
178 char* xlfd = (char*)malloc(len+1);
179
180 if (xlfd == NULL) {
181 return JNI_FALSE;
182 }
183
184 (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
185 xlfd[len] = '\0';
186
187 count = AWTCountFonts(xlfd);
188 free(xlfd);
189 if (count > 2) {
190 return JNI_TRUE;
191 } else {
192 return JNI_FALSE;
193 }
194 }
195
196 // CountGlyphs doubles as way of getting a native font reference
197 // and telling if its valid. So far as I can tell GenerateImage etc
198 // just return if this "initialisation method" hasn't been called.
199 // So clients of this class need to call CountGlyphs() right after
200 // construction to be safe.
201 JNIEXPORT jint JNICALL
Java_sun_font_NativeFont_countGlyphs(JNIEnv * env,jobject font,jbyteArray xlfdBytes,jint ptSize)202 Java_sun_font_NativeFont_countGlyphs
203 (JNIEnv *env, jobject font, jbyteArray xlfdBytes, jint ptSize) {
204
205 NativeScalerContext *context = (NativeScalerContext*)
206 Java_sun_font_NativeStrike_createScalerContext
207 (env, NULL, xlfdBytes, ptSize, 1);
208
209 if (context == NULL) {
210 return 0;
211 } else {
212 int numGlyphs = context->numGlyphs;
213 AWTFreeFont(context->xFont);
214 free(context);
215 return numGlyphs;
216 }
217 }
218
219 JNIEXPORT jint JNICALL
Java_sun_font_NativeStrike_getMaxGlyph(JNIEnv * env,jobject strike,jlong pScalerContext)220 Java_sun_font_NativeStrike_getMaxGlyph
221 (JNIEnv *env, jobject strike, jlong pScalerContext) {
222
223 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
224 if (context == NULL) {
225 return (jint)0;
226 } else {
227 return (jint)context->maxGlyph+1;
228 }
229 }
230
231 JNIEXPORT jfloat JNICALL
Java_sun_font_NativeFont_getGlyphAdvance(JNIEnv * env,jobject font2D,jlong pScalerContext,jint glyphCode)232 Java_sun_font_NativeFont_getGlyphAdvance
233 (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
234
235 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
236 AWTFont xFont = (AWTFont)context->xFont;
237 AWTChar xcs = NULL;
238 jfloat advance = 0.0f;
239
240 if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
241 return advance;
242 }
243
244 if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
245 glyphCode = context->defaultGlyph;
246 }
247
248 /* If number of glyphs is 256 or less, the metrics are
249 * stored correctly in the XFontStruct for each
250 * character. If the # characters is more (double byte
251 * case), then these metrics seem flaky and there's no
252 * way to determine if they have been set or not.
253 */
254 if ((context->maxGlyph <= 256) && (AWTFontPerChar(xFont, 0) != NULL)) {
255 xcs = AWTFontPerChar(xFont, glyphCode - context->minGlyph);
256 advance = AWTCharAdvance(xcs);
257 } else {
258 int direction, ascent, descent;
259 AWTChar2b xChar;
260
261 xChar.byte1 = (unsigned char) (glyphCode >> 8);
262 xChar.byte2 = (unsigned char) glyphCode;
263 AWTFontTextExtents16(xFont, &xChar, &xcs);
264 advance = AWTCharAdvance(xcs);
265 AWTFreeChar(xcs);
266 }
267 return (jfloat)(advance/context->scale);
268 }
269
270 JNIEXPORT jlong JNICALL
Java_sun_font_NativeFont_getGlyphImageNoDefault(JNIEnv * env,jobject font2D,jlong pScalerContext,jint glyphCode)271 Java_sun_font_NativeFont_getGlyphImageNoDefault
272 (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
273
274 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
275 AWTFont xFont = context->xFont;
276 AWTChar2b xChar;
277
278 if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
279 return (jlong)0;
280 }
281
282 if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
283 return (jlong)0;
284 }
285
286 xChar.byte1 = (unsigned char)(glyphCode >> 8);
287 xChar.byte2 = (unsigned char)glyphCode;
288 return AWTFontGenerateImage(xFont, &xChar);
289 }
290
291 JNIEXPORT jlong JNICALL
Java_sun_font_NativeFont_getGlyphImage(JNIEnv * env,jobject font2D,jlong pScalerContext,jint glyphCode)292 Java_sun_font_NativeFont_getGlyphImage
293 (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
294
295 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
296 AWTFont xFont = context->xFont;
297 AWTChar2b xChar;
298
299 if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
300 return (jlong)0;
301 }
302
303 if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
304 glyphCode = context->defaultGlyph;
305 }
306
307 xChar.byte1 = (unsigned char)(glyphCode >> 8);
308 xChar.byte2 = (unsigned char)glyphCode;
309 return AWTFontGenerateImage(xFont, &xChar);
310 }
311
312 JNIEXPORT jobject JNICALL
Java_sun_font_NativeFont_getFontMetrics(JNIEnv * env,jobject font2D,jlong pScalerContext)313 Java_sun_font_NativeFont_getFontMetrics
314 (JNIEnv *env, jobject font2D, jlong pScalerContext) {
315
316 NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
317 AWTFont xFont = (AWTFont)context->xFont;
318 jfloat j0=0, j1=1, ay=j0, dy=j0, mx=j0;
319 jobject metrics;
320
321 if (xFont == NULL) {
322 return NULL;
323 }
324
325 /* the commented out lines are the old 1.4.x behaviour which used max
326 * bounds instead of the font's designed ascent/descent */
327 /* ay = (jfloat)-AWTCharAscent(AWTFontMaxBounds(xFont)); */
328 /* dy = (jfloat)AWTCharDescent(AWTFontMaxBounds(xFont)); */
329
330 ay = (jfloat)-AWTFontAscent(xFont);
331 dy = (jfloat)AWTFontDescent(xFont);
332 mx = (jfloat)AWTCharAdvance(AWTFontMaxBounds(xFont));
333
334 /* ascent : no need to set ascentX - it will be zero
335 * descent : no need to set descentX - it will be zero
336 * baseline : old releases "made up" a number and also seemed to
337 * make it up for "X" and set "Y" to 0.
338 * leadingX : no need to set leadingX - it will be zero.
339 * leadingY : made-up number, but being compatible with what 1.4.x did
340 * advance : no need to set yMaxLinearAdvanceWidth - it will be zero.
341 */
342 metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass,
343 sunFontIDs.strikeMetricsCtr,
344 j0, ay, j0, dy, j1, j0, j0, j1, mx, j0);
345 /* printf("X11 asc=%f dsc=%f adv=%f scale=%f\n", */
346 /* ay, dy, mx, (float)context->scale); */
347 return metrics;
348 }
349