OSDN Git Service

2013-11-29 Matthias Klose <doko@ubuntu.com>
[pf3gnuchains/gcc-fork.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 <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 *
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 *
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 
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 
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 
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
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
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
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
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 
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 
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 
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 }