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 PangoFontMap *font_map = NULL;
64 
65 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState(JNIEnv * env,jclass clazz)66 Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState
67   (JNIEnv *env, jclass clazz __attribute__((unused)))
68 {
69   gtkpeer_init_font_IDs(env);
70   font_map = pango_ft2_font_map_new();
71 }
72 
73 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_initState(JNIEnv * env,jobject self)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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose(JNIEnv * env,jobject self)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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource(JNIEnv * env,jobject java_font)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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics(JNIEnv * env,jobject java_font,jdoubleArray java_metrics)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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics(JNIEnv * env,jobject java_font,jstring str,jdoubleArray java_metrics)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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont(JNIEnv * env,jobject self,jstring family_name_str,jint style_int,jint size)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_font_map_create_context (font_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
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable(JNIEnv * env,jobject self,jbyte n,jbyte a,jbyte m,jbyte e)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 }
372