blob: de06401f671c65b37285a8debf8bfb536211e1f9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 <malloc.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
49JNIEXPORT void JNICALL
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
63JNIEXPORT jlong JNICALL
64Java_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
78JNIEXPORT jlong JNICALL
79Java_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
142XGetFontProperty(xFont,XA_ITALIC_ANGLE, &angle);
143*/
144
145/* return (jint)angle; */
146/* } */
147
148JNIEXPORT jboolean JNICALL
149Java_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
172JNIEXPORT jboolean JNICALL
173Java_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.
201JNIEXPORT jint JNICALL
202Java_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
219JNIEXPORT jint JNICALL
220Java_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
231JNIEXPORT jfloat JNICALL
232Java_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;
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
270JNIEXPORT jlong JNICALL
271Java_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
291JNIEXPORT jlong JNICALL
292Java_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
312JNIEXPORT jobject JNICALL
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}