1 /* gnu_java_awt_FreetypeGlyphVector.c
2 Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #define PANGO_ENABLE_ENGINE
39 #include <jni.h>
40 #include <gtk/gtk.h>
41 #include <string.h>
42 #include <pango/pango.h>
43 #include <pango/pangoft2.h>
44 #include <pango/pangofc-font.h>
45 #include <ft2build.h>
46 #include FT_GLYPH_H
47 #include FT_OUTLINE_H
48 #include "jcl.h"
49 #include "gdkfont.h"
50 #include "gnu_java_awt_peer_gtk_FreetypeGlyphVector.h"
51 #include "cairographics2d.h"
52
53 typedef struct gp
54 {
55 JNIEnv *env;
56 jobject obj;
57 double px;
58 double py;
59 double sx;
60 double sy;
61 } generalpath ;
62
63 static PangoFcFont *
getFont(JNIEnv * env,jobject obj)64 getFont(JNIEnv *env, jobject obj)
65 {
66 jfieldID fid;
67 jobject data;
68 jclass cls;
69 struct peerfont *pfont;
70
71 cls = (*env)->GetObjectClass (env, obj);
72 fid = (*env)->GetFieldID (env, cls, "peer",
73 "Lgnu/java/awt/peer/gtk/GdkFontPeer;");
74 g_assert (fid != 0);
75
76 data = (*env)->GetObjectField (env, obj, fid);
77 g_assert (data != NULL);
78
79 pfont = (struct peerfont *) gtkpeer_get_font(env, data);
80 g_assert (pfont != NULL);
81 g_assert (pfont->font != NULL);
82
83 return (PangoFcFont *)pfont->font;
84 }
85
86 static PangoFontset *
getFontSet(JNIEnv * env,jobject obj)87 getFontSet(JNIEnv *env, jobject obj)
88 {
89 jfieldID fid;
90 jobject data;
91 jclass cls;
92 struct peerfont *pfont;
93
94 cls = (*env)->GetObjectClass (env, obj);
95 fid = (*env)->GetFieldID (env, cls, "peer",
96 "Lgnu/java/awt/peer/gtk/GdkFontPeer;");
97 g_assert (fid != 0);
98
99 data = (*env)->GetObjectField (env, obj, fid);
100 g_assert (data != NULL);
101
102 pfont = (struct peerfont *) gtkpeer_get_font (env, data);
103 g_assert (pfont != NULL);
104 g_assert (pfont->font != NULL);
105
106 return (PangoFontset *)pfont->set;
107 }
108
109 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs(JNIEnv * env,jobject obj,jintArray codepoints,jintArray glyphs,jlongArray fonts)110 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs
111 (JNIEnv *env, jobject obj, jintArray codepoints, jintArray glyphs,
112 jlongArray fonts)
113 {
114 PangoFcFont *default_font, *current_font;
115 PangoFontset *pfs;
116 jint *cpvals;
117 jint length;
118 int i;
119
120 /* Set up default font and fontset */
121 default_font = getFont(env, obj);
122 current_font = default_font;
123 pfs = getFontSet(env, obj);
124
125 /* Retrieve string information */
126 length = (*env)->GetArrayLength (env, codepoints);
127 cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL);
128
129 jint *glyphArray = (*env)->GetIntArrayElements (env, glyphs, NULL);
130 jlong *fontArray = (*env)->GetLongArrayElements (env, fonts, NULL);
131
132 /* A design goal of Pango is to be threadsafe, but it's admitted that it is
133 * not actually threadsafe at the moment. Using gdk locking here to be safe,
134 * but I don't know if if actually helps at all... */
135 gdk_threads_enter();
136
137 for( i = 0; i < length; i++ )
138 {
139 /* Ensure the current font has the requested character; if it doesn't,
140 * try the default font before pulling a new font out of the fontset.
141 * Once chosen, a font will be used until a character not in the font is
142 * encountered. */
143 if (!pango_fc_font_has_char(current_font, cpvals[i]))
144 {
145 if (pango_fc_font_has_char(default_font, cpvals[i]))
146 {
147 current_font = default_font;
148 g_object_ref(current_font);
149 }
150 else
151 {
152 current_font = (PangoFcFont*)pango_fontset_get_font(pfs, cpvals[i]);
153 }
154 }
155 else
156 {
157 g_object_ref(current_font);
158 }
159
160 /* Get glyph, and store both glyph and pointer to font */
161 glyphArray[i] = (int)pango_fc_font_get_glyph(current_font,
162 (gunichar)cpvals[i]);
163 fontArray[i] = PTR_TO_JLONG(current_font);
164 }
165
166 gdk_threads_leave();
167
168 (*env)->ReleaseIntArrayElements (env, glyphs, glyphArray, 0);
169 (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0);
170 (*env)->ReleaseLongArrayElements (env, fonts, fontArray, 0);
171 }
172
173 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning(JNIEnv * env,jobject obj,jint rightGlyph,jint leftGlyph,jlong fnt,jfloatArray p)174 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning
175 (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph,
176 jint leftGlyph, jlong fnt, jfloatArray p)
177 {
178 FT_Face ft_face;
179 FT_Vector kern;
180 PangoFcFont *font;
181
182 font = JLONG_TO_PTR(PangoFcFont, fnt);
183 ft_face = pango_fc_font_lock_face( font );
184 g_assert (ft_face != NULL);
185 FT_Get_Kerning( ft_face, rightGlyph, leftGlyph, FT_KERNING_DEFAULT, &kern );
186
187 pango_fc_font_unlock_face( font );
188
189 jfloat *pelements = (*env)->GetPrimitiveArrayCritical(env, p, NULL);
190 pelements[0] = (jfloat)kern.x/64.0;
191 pelements[1] = (jfloat)kern.y/64.0;
192 (*env)->ReleasePrimitiveArrayCritical (env, p, pelements, 0);
193 }
194
195 JNIEXPORT jdoubleArray JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative(JNIEnv * env,jobject obj,jint glyphIndex,jlong fnt)196 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative
197 (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
198 {
199 FT_Face ft_face;
200 jdouble *values;
201 jdoubleArray retArray = NULL;
202 PangoFcFont *font;
203
204 font = JLONG_TO_PTR(PangoFcFont, fnt);
205 ft_face = pango_fc_font_lock_face( font );
206
207 g_assert (ft_face != NULL);
208
209 FT_Set_Transform( ft_face, NULL, NULL );
210
211 if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 )
212 {
213 pango_fc_font_unlock_face( font );
214 printf("Couldn't load glyph %i\n", glyphIndex);
215 return NULL;
216 }
217
218 retArray = (*env)->NewDoubleArray (env, 8);
219 values = (*env)->GetDoubleArrayElements (env, retArray, NULL);
220
221 values[0] = 0;
222 values[1] = (jdouble)ft_face->glyph->advance.x/64.0;
223 values[2] = (jdouble)ft_face->glyph->advance.y/64.0;
224 values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0;
225 values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0;
226 values[5] = (jdouble)ft_face->glyph->metrics.width/64.0;
227 values[6] = (jdouble)ft_face->glyph->metrics.height/64.0;
228 values[7] = 0;
229
230 (*env)->ReleaseDoubleArrayElements (env, retArray, values, 0);
231 pango_fc_font_unlock_face( font );
232
233 return retArray;
234 }
235
236 /* GetOutline code follows ****************************/
237 /********* Freetype callback functions *****************************/
238
_moveTo(const FT_Vector * to,void * p)239 static int _moveTo( const FT_Vector* to,
240 void *p)
241 {
242 JNIEnv *env;
243 jobject obj;
244 jclass cls;
245 jmethodID method;
246 jvalue values[2];
247 generalpath *path = (generalpath *) p;
248
249 env = path->env;
250 obj = path->obj;
251
252 values[0].f = (jfloat)(to->x * path->sx + path->px);
253 values[1].f = (jfloat)(to->y * path->sy + path->py);
254
255 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
256 method = (*env)->GetMethodID (env, cls, "moveTo", "(FF)V");
257 (*env)->CallVoidMethodA(env, obj, method, values );
258
259 return 0;
260 }
261
_lineTo(const FT_Vector * to,void * p)262 static int _lineTo( const FT_Vector* to,
263 void *p)
264 {
265 JNIEnv *env;
266 jobject obj;
267 jclass cls;
268 jmethodID method;
269 jvalue values[2];
270 generalpath *path = (generalpath *) p;
271
272 env = path->env;
273 obj = path->obj;
274 values[0].f = (jfloat)(to->x * path->sx + path->px);
275 values[1].f = (jfloat)(to->y * path->sy + path->py);
276
277 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
278 method = (*env)->GetMethodID (env, cls, "lineTo", "(FF)V");
279 (*env)->CallVoidMethodA(env, obj, method, values );
280
281 return 0;
282 }
283
_quadTo(const FT_Vector * cp,const FT_Vector * to,void * p)284 static int _quadTo( const FT_Vector* cp,
285 const FT_Vector* to,
286 void *p)
287 {
288 JNIEnv *env;
289 jobject obj;
290 jclass cls;
291 jmethodID method;
292 jvalue values[4];
293 generalpath *path = (generalpath *) p;
294
295 env = path->env;
296 obj = path->obj;
297 values[0].f = (jfloat)(cp->x * path->sx + path->px);
298 values[1].f = (jfloat)(cp->y * path->sy + path->py);
299 values[2].f = (jfloat)(to->x * path->sx + path->px);
300 values[3].f = (jfloat)(to->y * path->sy + path->py);
301
302 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
303 method = (*env)->GetMethodID (env, cls, "quadTo", "(FFFF)V");
304 (*env)->CallVoidMethodA(env, obj, method, values );
305
306 return 0;
307 }
308
_curveTo(const FT_Vector * cp1,const FT_Vector * cp2,const FT_Vector * to,void * p)309 static int _curveTo( const FT_Vector* cp1,
310 const FT_Vector* cp2,
311 const FT_Vector* to,
312 void *p)
313 {
314 JNIEnv *env;
315 jobject obj;
316 jclass cls;
317 jmethodID method;
318 jvalue values[6];
319 generalpath *path = (generalpath *) p;
320
321 env = path->env;
322 obj = path->obj;
323 values[0].f = (jfloat)(cp1->x * path->sx + path->px);
324 values[1].f = (jfloat)(cp1->y * path->sy + path->py);
325 values[2].f = (jfloat)(cp2->x * path->sx + path->px);
326 values[3].f = (jfloat)(cp2->y * path->sy + path->py);
327 values[4].f = (jfloat)(to->x * path->sx + path->px);
328 values[5].f = (jfloat)(to->y * path->sy + path->py);
329
330 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
331 method = (*env)->GetMethodID (env, cls, "curveTo", "(FFFFFF)V");
332 (*env)->CallVoidMethodA(env, obj, method, values );
333
334 return 0;
335 }
336
337
338 JNIEXPORT jobject JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative(JNIEnv * env,jobject obj,jint glyphIndex,jlong fnt)339 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative
340 (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
341 {
342 generalpath *path;
343 jobject gp;
344 FT_Outline_Funcs ftCallbacks =
345 {
346 (FT_Outline_MoveToFunc) _moveTo,
347 (FT_Outline_LineToFunc) _lineTo,
348 (FT_Outline_ConicToFunc) _quadTo,
349 (FT_Outline_CubicToFunc) _curveTo,
350 0,
351 0
352 };
353 PangoFcFont *font;
354 FT_Face ft_face;
355 FT_Glyph glyph;
356
357 font = JLONG_TO_PTR(PangoFcFont, fnt);
358 ft_face = pango_fc_font_lock_face( font );
359
360 g_assert (ft_face != NULL);
361
362 path = g_malloc0 (sizeof (generalpath));
363 g_assert(path != NULL);
364 path->env = env;
365
366 path->px = path->py = 0.0;
367 path->sx = 1.0/64.0;
368 path->sy = -1.0/64.0;
369
370 { /* create a GeneralPath instance */
371 jclass cls;
372 jmethodID method;
373
374 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
375 method = (*env)->GetMethodID (env, cls, "<init>", "()V");
376 gp = path->obj = (*env)->NewObject (env, cls, method);
377 }
378
379 if(FT_Load_Glyph(ft_face,
380 (FT_UInt)(glyphIndex),
381 FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0)
382 {
383 pango_fc_font_unlock_face( font );
384 g_free(path);
385 return NULL;
386 }
387
388 FT_Get_Glyph( ft_face->glyph, &glyph );
389 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
390 {
391 FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
392 &ftCallbacks, path);
393 }
394 else
395 {
396 char format[5];
397
398 format[0] = (glyph->format & 0xFF000000) >> 24;
399 format[1] = (glyph->format & 0x00FF0000) >> 16;
400 format[2] = (glyph->format & 0x0000FF00) >> 8;
401 format[3] = (glyph->format & 0x000000FF);
402 format[4] = '\0';
403 printf("WARNING: Unable to create outline for font %s %s of format %s\n",
404 ft_face->family_name, ft_face->style_name, format);
405 }
406 FT_Done_Glyph( glyph );
407
408 pango_fc_font_unlock_face( font );
409
410 g_free(path);
411
412 return gp;
413 }
414
415 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_dispose(JNIEnv * env,jobject obj,jlongArray fontset)416 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_dispose
417 (JNIEnv *env, jobject obj __attribute__((unused)), jlongArray fontset)
418 {
419 PangoFcFont *font;
420 jlong *fontArray;
421 int i, length;
422
423 length = (*env)->GetArrayLength (env, fontset);
424 fontArray = (*env)->GetLongArrayElements (env, fontset, NULL);
425
426 gdk_threads_enter();
427
428 for( i = 0; i < length; i++ )
429 {
430 font = JLONG_TO_PTR(PangoFcFont, fontArray[i]);
431 g_object_unref(font);
432 }
433
434 gdk_threads_leave();
435
436 (*env)->ReleaseLongArrayElements (env, fontset, fontArray, 0);
437 }
438
439 JNIEXPORT jlong JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getNativeFontPointer(JNIEnv * env,jobject obj,jint n)440 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getNativeFontPointer
441 (JNIEnv *env, jobject obj, jint n)
442 {
443 int i;
444 PangoFcFont *font = getFont(env, obj);
445
446 for (i = 0; i < n; i++)
447 g_object_ref(font);
448
449 return PTR_TO_JLONG(font);
450 }
451