OSDN Git Service

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