FreetypeGlyphVector.java (getKerning): Return result in a float[], not a Point2D.
[gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
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 <freetype/ftglyph.h>
46 #include <freetype/ftoutln.h>
47 #include "jcl.h"
48 #include "gdkfont.h"
49 #include "gnu_java_awt_peer_gtk_FreetypeGlyphVector.h"
50 #include "cairographics2d.h"
51
52 typedef struct gp
53 {
54 JNIEnv *env;
55 jobject obj;
56 double px;
57 double py;
58 double sx;
59 double sy;
60 } generalpath ;
61
62 static PangoFcFont *
63 getFont(JNIEnv *env, jobject obj)
64 {
65 jfieldID fid;
66 jobject data;
67 jclass cls;
68 struct peerfont *pfont;
69
70 cls = (*env)->GetObjectClass (env, obj);
71 fid = (*env)->GetFieldID (env, cls, "peer",
72 "Lgnu/java/awt/peer/gtk/GdkFontPeer;");
73 g_assert (fid != 0);
74
75 data = (*env)->GetObjectField (env, obj, fid);
76 g_assert (data != NULL);
77
78 pfont = (struct peerfont *) gtkpeer_get_font(env, data);
79 g_assert (pfont != NULL);
80 g_assert (pfont->font != NULL);
81
82 return (PangoFcFont *)pfont->font;
83 }
84
85 static PangoFontset *
86 getFontSet(JNIEnv *env, jobject obj)
87 {
88 jfieldID fid;
89 jobject data;
90 jclass cls;
91 struct peerfont *pfont;
92
93 cls = (*env)->GetObjectClass (env, obj);
94 fid = (*env)->GetFieldID (env, cls, "peer",
95 "Lgnu/java/awt/peer/gtk/GdkFontPeer;");
96 g_assert (fid != 0);
97
98 data = (*env)->GetObjectField (env, obj, fid);
99 g_assert (data != NULL);
100
101 pfont = (struct peerfont *) gtkpeer_get_font (env, data);
102 g_assert (pfont != NULL);
103 g_assert (pfont->font != NULL);
104
105 return (PangoFontset *)pfont->set;
106 }
107
108 JNIEXPORT void JNICALL
109 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs
110 (JNIEnv *env, jobject obj, jintArray codepoints, jintArray glyphs,
111 jlongArray fonts)
112 {
113 PangoFcFont *default_font, *current_font;
114 PangoFontset *pfs;
115 jint *cpvals;
116 jint length;
117 int i;
118
119 /* Set up default font and fontset */
120 default_font = getFont(env, obj);
121 current_font = default_font;
122 pfs = getFontSet(env, obj);
123
124 /* Retrieve string information */
125 length = (*env)->GetArrayLength (env, codepoints);
126 cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL);
127
128 jint *glyphArray = (*env)->GetIntArrayElements (env, glyphs, NULL);
129 jlong *fontArray = (*env)->GetLongArrayElements (env, fonts, NULL);
130
131 /* A design goal of Pango is to be threadsafe, but it's admitted that it is
132 * not actually threadsafe at the moment. Using gdk locking here to be safe,
133 * but I don't know if if actually helps at all... */
134 gdk_threads_enter();
135
136 for( i = 0; i < length; i++ )
137 {
138 /* Ensure the current font has the requested character; if it doesn't,
139 * try the default font before pulling a new font out of the fontset.
140 * Once chosen, a font will be used until a character not in the font is
141 * encountered. */
142 if (!pango_fc_font_has_char(current_font, cpvals[i]))
143 {
144 if (pango_fc_font_has_char(default_font, cpvals[i]))
145 {
146 current_font = default_font;
147 g_object_ref(current_font);
148 }
149 else
150 {
151 current_font = (PangoFcFont*)pango_fontset_get_font(pfs, cpvals[i]);
152 }
153 }
154 else
155 {
156 g_object_ref(current_font);
157 }
158
159 /* Get glyph, and store both glyph and pointer to font */
160 glyphArray[i] = (int)pango_fc_font_get_glyph(current_font,
161 (gunichar)cpvals[i]);
162 fontArray[i] = PTR_TO_JLONG(current_font);
163 }
164
165 gdk_threads_leave();
166
167 (*env)->ReleaseIntArrayElements (env, glyphs, glyphArray, 0);
168 (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0);
169 (*env)->ReleaseLongArrayElements (env, fonts, fontArray, 0);
170 }
171
172 JNIEXPORT void JNICALL
173 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning
174 (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph,
175 jint leftGlyph, jlong fnt, jfloatArray p)
176 {
177 FT_Face ft_face;
178 FT_Vector kern;
179 jclass cls;
180 jmethodID method;
181 jvalue values[2];
182 PangoFcFont *font;
183
184 font = JLONG_TO_PTR(PangoFcFont, fnt);
185 ft_face = pango_fc_font_lock_face( font );
186 g_assert (ft_face != NULL);
187 FT_Get_Kerning( ft_face, rightGlyph, leftGlyph, FT_KERNING_DEFAULT, &kern );
188
189 pango_fc_font_unlock_face( font );
190
191 jfloat *pelements = (*env)->GetPrimitiveArrayCritical(env, p, NULL);
192 pelements[0] = (jfloat)kern.x/64.0;
193 pelements[1] = (jfloat)kern.y/64.0;
194 (*env)->ReleasePrimitiveArrayCritical (env, p, pelements, 0);
195 }
196
197 JNIEXPORT jdoubleArray JNICALL
198 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative
199 (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
200 {
201 FT_Face ft_face;
202 jdouble *values;
203 jdoubleArray retArray = NULL;
204 PangoFcFont *font;
205
206 font = JLONG_TO_PTR(PangoFcFont, fnt);
207 ft_face = pango_fc_font_lock_face( font );
208
209 g_assert (ft_face != NULL);
210
211 FT_Set_Transform( ft_face, NULL, NULL );
212
213 if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 )
214 {
215 pango_fc_font_unlock_face( font );
216 printf("Couldn't load glyph %i\n", glyphIndex);
217 return NULL;
218 }
219
220 retArray = (*env)->NewDoubleArray (env, 8);
221 values = (*env)->GetDoubleArrayElements (env, retArray, NULL);
222
223 values[0] = 0;
224 values[1] = (jdouble)ft_face->glyph->advance.x/64.0;
225 values[2] = (jdouble)ft_face->glyph->advance.y/64.0;
226 values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0;
227 values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0;
228 values[5] = (jdouble)ft_face->glyph->metrics.width/64.0;
229 values[6] = (jdouble)ft_face->glyph->metrics.height/64.0;
230 values[7] = 0;
231
232 (*env)->ReleaseDoubleArrayElements (env, retArray, values, 0);
233 pango_fc_font_unlock_face( font );
234
235 return retArray;
236 }
237
238 /* GetOutline code follows ****************************/
239 /********* Freetype callback functions *****************************/
240
241 static int _moveTo( const FT_Vector* to,
242 void *p)
243 {
244 JNIEnv *env;
245 jobject obj;
246 jclass cls;
247 jmethodID method;
248 jvalue values[2];
249 generalpath *path = (generalpath *) p;
250
251 env = path->env;
252 obj = path->obj;
253
254 values[0].f = (jfloat)(to->x * path->sx + path->px);
255 values[1].f = (jfloat)(to->y * path->sy + path->py);
256
257 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
258 method = (*env)->GetMethodID (env, cls, "moveTo", "(FF)V");
259 (*env)->CallVoidMethodA(env, obj, method, values );
260
261 return 0;
262 }
263
264 static int _lineTo( const FT_Vector* to,
265 void *p)
266 {
267 JNIEnv *env;
268 jobject obj;
269 jclass cls;
270 jmethodID method;
271 jvalue values[2];
272 generalpath *path = (generalpath *) p;
273
274 env = path->env;
275 obj = path->obj;
276 values[0].f = (jfloat)(to->x * path->sx + path->px);
277 values[1].f = (jfloat)(to->y * path->sy + path->py);
278
279 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
280 method = (*env)->GetMethodID (env, cls, "lineTo", "(FF)V");
281 (*env)->CallVoidMethodA(env, obj, method, values );
282
283 return 0;
284 }
285
286 static int _quadTo( const FT_Vector* cp,
287 const FT_Vector* to,
288 void *p)
289 {
290 JNIEnv *env;
291 jobject obj;
292 jclass cls;
293 jmethodID method;
294 jvalue values[4];
295 generalpath *path = (generalpath *) p;
296
297 env = path->env;
298 obj = path->obj;
299 values[0].f = (jfloat)(cp->x * path->sx + path->px);
300 values[1].f = (jfloat)(cp->y * path->sy + path->py);
301 values[2].f = (jfloat)(to->x * path->sx + path->px);
302 values[3].f = (jfloat)(to->y * path->sy + path->py);
303
304 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
305 method = (*env)->GetMethodID (env, cls, "quadTo", "(FFFF)V");
306 (*env)->CallVoidMethodA(env, obj, method, values );
307
308 return 0;
309 }
310
311 static int _curveTo( const FT_Vector* cp1,
312 const FT_Vector* cp2,
313 const FT_Vector* to,
314 void *p)
315 {
316 JNIEnv *env;
317 jobject obj;
318 jclass cls;
319 jmethodID method;
320 jvalue values[6];
321 generalpath *path = (generalpath *) p;
322
323 env = path->env;
324 obj = path->obj;
325 values[0].f = (jfloat)(cp1->x * path->sx + path->px);
326 values[1].f = (jfloat)(cp1->y * path->sy + path->py);
327 values[2].f = (jfloat)(cp2->x * path->sx + path->px);
328 values[3].f = (jfloat)(cp2->y * path->sy + path->py);
329 values[4].f = (jfloat)(to->x * path->sx + path->px);
330 values[5].f = (jfloat)(to->y * path->sy + path->py);
331
332 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
333 method = (*env)->GetMethodID (env, cls, "curveTo", "(FFFFFF)V");
334 (*env)->CallVoidMethodA(env, obj, method, values );
335
336 return 0;
337 }
338
339
340 JNIEXPORT jobject JNICALL
341 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative
342 (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
343 {
344 generalpath *path;
345 jobject gp;
346 FT_Outline_Funcs ftCallbacks =
347 {
348 (FT_Outline_MoveToFunc) _moveTo,
349 (FT_Outline_LineToFunc) _lineTo,
350 (FT_Outline_ConicToFunc) _quadTo,
351 (FT_Outline_CubicToFunc) _curveTo,
352 0,
353 0
354 };
355 PangoFcFont *font;
356 FT_Face ft_face;
357 FT_Glyph glyph;
358
359 font = JLONG_TO_PTR(PangoFcFont, fnt);
360 ft_face = pango_fc_font_lock_face( font );
361
362 g_assert (ft_face != NULL);
363
364 path = g_malloc0 (sizeof (generalpath));
365 g_assert(path != NULL);
366 path->env = env;
367
368 path->px = path->py = 0.0;
369 path->sx = 1.0/64.0;
370 path->sy = -1.0/64.0;
371
372 { /* create a GeneralPath instance */
373 jclass cls;
374 jmethodID method;
375
376 cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
377 method = (*env)->GetMethodID (env, cls, "<init>", "()V");
378 gp = path->obj = (*env)->NewObject (env, cls, method);
379 }
380
381 if(FT_Load_Glyph(ft_face,
382 (FT_UInt)(glyphIndex),
383 FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0)
384 {
385 pango_fc_font_unlock_face( font );
386 g_free(path);
387 return NULL;
388 }
389
390 FT_Get_Glyph( ft_face->glyph, &glyph );
391 FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
392 &ftCallbacks, path);
393 FT_Done_Glyph( glyph );
394
395 pango_fc_font_unlock_face( font );
396
397 g_free(path);
398
399 return gp;
400 }
401
402 JNIEXPORT void JNICALL
403 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_dispose
404 (JNIEnv *env, jobject obj __attribute__((unused)), jlongArray fontset)
405 {
406 PangoFcFont *font;
407 jlong *fontArray;
408 int i, length;
409
410 length = (*env)->GetArrayLength (env, fontset);
411 fontArray = (*env)->GetLongArrayElements (env, fontset, NULL);
412
413 gdk_threads_enter();
414
415 for( i = 0; i < length; i++ )
416 {
417 font = JLONG_TO_PTR(PangoFcFont, fontArray[i]);
418 g_object_unref(font);
419 }
420
421 gdk_threads_leave();
422
423 (*env)->ReleaseLongArrayElements (env, fontset, fontArray, 0);
424 }
425
426 JNIEXPORT jlong JNICALL
427 Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getNativeFontPointer
428 (JNIEnv *env, jobject obj, jint n)
429 {
430 int i;
431 PangoFcFont *font = getFont(env, obj);
432
433 for (i = 0; i < n; i++)
434 g_object_ref(font);
435
436 return PTR_TO_JLONG(font);
437 }