OSDN Git Service

b172397506aafb2550e3d6b3f95a5b77ebd3f326
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GdkFontPeer.c
1 /* gnu_java_awt_GdkFont.c
2    Copyright (C) 2003, 2004 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 <pango/pango.h>
40 #include <pango/pangoft2.h>
41 #include <pango/pangofc-font.h>
42 #include <ft2build.h>
43 #include FT_GLYPH_H
44 #include FT_OUTLINE_H
45 #include FT_TYPES_H
46 #include FT_TRUETYPE_TABLES_H
47 #include "gdkfont.h"
48 #include "gtkpeer.h"
49 #include "gnu_java_awt_peer_gtk_GdkFontPeer.h"
50
51 enum java_awt_font_style {
52   java_awt_font_PLAIN = 0,
53   java_awt_font_BOLD = 1,
54   java_awt_font_ITALIC = 2
55 };
56
57 enum java_awt_font_baseline {
58   java_awt_font_ROMAN_BASELINE = 0,
59   java_awt_font_CENTER_BASELINE = 1,
60   java_awt_font_HANGING_BASELINE = 2
61 };
62
63 static PangoFT2FontMap *ft2_map = NULL;
64
65 JNIEXPORT void JNICALL
66 Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState 
67   (JNIEnv *env, jclass clazz __attribute__((unused)))
68 {
69   gtkpeer_init_font_IDs(env);
70   ft2_map = PANGO_FT2_FONT_MAP(pango_ft2_font_map_new());
71 }
72
73 JNIEXPORT void JNICALL
74 Java_gnu_java_awt_peer_gtk_GdkFontPeer_initState
75   (JNIEnv *env, jobject self)
76 {
77   struct peerfont *pfont = NULL;
78
79   gdk_threads_enter ();
80
81   g_assert (self != NULL);
82   pfont = (struct peerfont *) g_malloc0 (sizeof (struct peerfont));
83   g_assert (pfont != NULL);
84   gtkpeer_set_font (env, self, pfont);
85
86   gdk_threads_leave ();
87 }
88
89
90 JNIEXPORT void JNICALL
91 Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose
92   (JNIEnv *env, jobject self)
93 {
94   struct peerfont *pfont = NULL;
95
96   gdk_threads_enter ();
97
98   pfont = (struct peerfont *) gtkpeer_get_font (env, self);
99   g_assert (pfont != NULL);
100   if (pfont->layout != NULL)
101     g_object_unref (pfont->layout);
102   if (pfont->font != NULL)
103     g_object_unref (pfont->font);
104   if (pfont->set != NULL)
105     g_object_unref (pfont->set);
106   if (pfont->ctx != NULL)
107     g_object_unref (pfont->ctx);
108   if (pfont->desc != NULL)
109     pango_font_description_free (pfont->desc);
110   g_free (pfont);
111
112   gdk_threads_leave ();
113 }
114
115
116 JNIEXPORT void JNICALL
117 Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource
118    (JNIEnv *env, jobject java_font)
119 {
120   struct peerfont *pfont = NULL;
121
122   gdk_threads_enter();
123
124   pfont = (struct peerfont *) gtkpeer_get_font (env, java_font);
125   g_assert (pfont != NULL);
126   if (pfont->graphics_resource != NULL)
127     {
128       cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource);
129       pfont->graphics_resource = NULL;
130     }
131
132   gdk_threads_leave();
133 }
134
135
136 JNIEXPORT void JNICALL
137 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics
138 (JNIEnv *env, jobject java_font, jdoubleArray java_metrics)
139 {
140   FT_Face face;
141   struct peerfont *pfont = NULL;
142   jdouble *native_metrics = NULL;
143   short x_ppem;
144   short y_ppem;
145   short units_per_em;
146   double factorx;
147   double factory;
148
149   gdk_threads_enter();
150
151   pfont = (struct peerfont *) gtkpeer_get_font (env, java_font);
152   g_assert (pfont != NULL);
153   face = pango_fc_font_lock_face ((PangoFcFont *)pfont->font);
154
155   native_metrics 
156     = (*env)->GetDoubleArrayElements (env, java_metrics, NULL);
157
158   g_assert (native_metrics != NULL);
159
160   x_ppem = face->size->metrics.x_ppem;
161   y_ppem = face->size->metrics.y_ppem;
162   units_per_em = face->units_per_EM;
163   factorx = units_per_em / x_ppem;
164   factory = units_per_em / y_ppem;
165   native_metrics[FONT_METRICS_ASCENT] = face->ascender / factory;
166   native_metrics[FONT_METRICS_MAX_ASCENT] = face->bbox.yMax / factory;
167   native_metrics[FONT_METRICS_DESCENT] = - face->descender / factory;
168   native_metrics[FONT_METRICS_MAX_DESCENT] = - face->bbox.yMin / factory;
169   native_metrics[FONT_METRICS_MAX_ADVANCE] = face->max_advance_width / factorx;
170   native_metrics[FONT_METRICS_HEIGHT] = face->height / factory;
171   native_metrics[FONT_METRICS_UNDERLINE_OFFSET] =
172     face->underline_position / factory;
173   native_metrics[FONT_METRICS_UNDERLINE_THICKNESS] =
174     face->underline_thickness / factory;
175     
176   pango_fc_font_unlock_face((PangoFcFont *)pfont->font);
177
178   (*env)->ReleaseDoubleArrayElements (env, 
179                                       java_metrics, 
180                                       native_metrics, 0);
181
182   gdk_threads_leave();
183 }
184
185 JNIEXPORT void JNICALL
186 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics
187    (JNIEnv *env, jobject java_font, jstring str, jdoubleArray java_metrics)
188 {
189   struct peerfont *pfont = NULL;
190   const char *cstr = NULL;
191   jdouble *native_metrics = NULL;  
192   PangoRectangle log;
193   PangoRectangle log2;
194   int line_count = 0;
195   int i = 0;
196   int width = 0;
197
198   gdk_threads_enter();
199
200   pfont = (struct peerfont *) gtkpeer_get_font(env, java_font);
201   g_assert (pfont != NULL);
202
203   cstr = (*env)->GetStringUTFChars (env, str, NULL);
204   g_assert(cstr != NULL);
205   
206   pango_layout_set_text (pfont->layout, cstr, -1);
207   pango_layout_get_extents (pfont->layout, NULL, &log);
208   
209   line_count = pango_layout_get_line_count (pfont->layout);
210   for (i = 0; i < line_count; i++)
211    {
212      pango_layout_line_get_extents (pango_layout_get_line (pfont->layout, i), 
213        NULL, &log2);
214      width += log2.width;
215    }
216
217   (*env)->ReleaseStringUTFChars (env, str, cstr);  
218   pango_layout_set_text (pfont->layout, "", -1);
219
220   native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL);
221   g_assert (native_metrics != NULL);
222
223   native_metrics[TEXT_METRICS_X_BEARING] 
224     = PANGO_PIXELS( ((double)log.x) );
225
226   native_metrics[TEXT_METRICS_Y_BEARING] 
227     = PANGO_PIXELS( ((double)log.y) );
228
229   native_metrics[TEXT_METRICS_HEIGHT] 
230     = PANGO_PIXELS( ((double)log.height) );
231
232   native_metrics[TEXT_METRICS_WIDTH]
233     = PANGO_PIXELS( ((double)width) );
234
235   native_metrics[TEXT_METRICS_X_ADVANCE] 
236     = PANGO_PIXELS( ((double) (log.x + log.width)) );
237
238   native_metrics[TEXT_METRICS_Y_ADVANCE] 
239     = PANGO_PIXELS( ((double) (log.y + log.height)) );
240          
241   (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0);
242
243   gdk_threads_leave();
244 }
245
246
247 JNIEXPORT void JNICALL
248 Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont
249   (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size)
250 {
251   struct peerfont *pfont = NULL;
252   char const *family_name = NULL;
253   enum java_awt_font_style style;
254
255   gdk_threads_enter ();
256
257   style = (enum java_awt_font_style) style_int;
258
259   g_assert (self != NULL);
260   pfont = (struct peerfont *) gtkpeer_get_font(env, self);
261   g_assert (pfont != NULL);
262
263   /* Clear old font information */
264   if (pfont->ctx != NULL)
265     g_object_unref (pfont->ctx);
266   if (pfont->font != NULL)
267     g_object_unref (pfont->font);
268   if (pfont->set != NULL)
269     g_object_unref (pfont->set);
270   if (pfont->desc != NULL)
271     pango_font_description_free (pfont->desc);
272
273   /* Set new description information */
274   pfont->desc = pango_font_description_new ();
275   g_assert (pfont->desc != NULL);
276
277   family_name = (*env)->GetStringUTFChars(env, family_name_str, 0);
278   g_assert (family_name != NULL);
279   pango_font_description_set_family (pfont->desc, family_name);
280   (*env)->ReleaseStringUTFChars(env, family_name_str, family_name);
281
282   if (style & java_awt_font_BOLD)
283     pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD);
284
285   if (style & java_awt_font_ITALIC)
286     pango_font_description_set_style (pfont->desc, PANGO_STYLE_ITALIC);
287
288   pango_font_description_set_size (pfont->desc, size * PANGO_SCALE);
289   
290   /* Create new context */
291   pfont->ctx = pango_ft2_font_map_create_context (ft2_map);
292   g_assert (pfont->ctx != NULL);
293   
294   pango_context_set_font_description (pfont->ctx, pfont->desc);
295   pango_context_set_language (pfont->ctx, gtk_get_default_language());
296   
297   /* Create new fontset and default font */
298   pfont->set = pango_context_load_fontset(pfont->ctx, pfont->desc,
299                                                                                   gtk_get_default_language());
300   pfont->font = pango_context_load_font (pfont->ctx, pfont->desc);
301   g_assert (pfont->font != NULL);
302
303   if (pfont->layout == NULL)
304     pfont->layout = pango_layout_new (pfont->ctx);
305   g_assert (pfont->layout != NULL);
306
307   gdk_threads_leave ();
308 }
309
310
311 JNIEXPORT jbyteArray JNICALL 
312 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable 
313   (JNIEnv *env, jobject self, jbyte n, jbyte a, jbyte m, jbyte e)
314 {
315   struct peerfont *pfont = NULL;
316   FT_Face face;
317   FT_ULong length = 0;
318   FT_ULong tag;
319   int error;
320   FT_Byte *buffer;
321   jbyteArray result_array;
322   jbyte *rbuf;
323
324   pfont = (struct peerfont *) gtkpeer_get_font(env, self);
325   if(pfont == NULL)
326     return NULL;
327
328   gdk_threads_enter ();
329   face = pango_fc_font_lock_face ((PangoFcFont *)pfont->font);
330   tag = FT_MAKE_TAG( n, a, m, e );
331
332   /* Get the length of the table requested */
333   error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
334   if ( error ) 
335     {
336       pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
337       gdk_threads_leave ();
338       return NULL;
339     }
340
341   buffer = (FT_Byte *)g_malloc0( length );
342   if ( buffer == NULL ) 
343     {
344       pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
345       gdk_threads_leave ();
346       return NULL;
347     }
348   /* get the table data */
349   error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
350   if ( error ) 
351     {
352       pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
353       g_free(buffer);
354       gdk_threads_leave ();
355       return NULL;
356     }
357
358   /* copy to a jbytearray */
359   result_array = (*env)->NewByteArray (env, length);
360
361   rbuf = (*env)->GetByteArrayElements (env, result_array, NULL);
362   memcpy(rbuf, buffer, length);
363   (*env)->ReleaseByteArrayElements (env, result_array, rbuf, 0);
364
365   g_free(buffer);
366   pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
367   gdk_threads_leave ();
368
369   /* done */
370   return result_array;
371 }