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 #include "gdkfont.h"
39 #include "gnu_java_awt_peer_gtk_GdkFontPeer.h"
40 
41 struct state_table *cp_gtk_native_font_state_table;
42 
43 enum java_awt_font_style {
44   java_awt_font_PLAIN = 0,
45   java_awt_font_BOLD = 1,
46   java_awt_font_ITALIC = 2
47 };
48 
49 enum java_awt_font_baseline {
50   java_awt_font_ROMAN_BASELINE = 0,
51   java_awt_font_CENTER_BASELINE = 1,
52   java_awt_font_HANGING_BASELINE = 2
53 };
54 
55 static jmethodID glyphVector_ctor;
56 static jclass glyphVector_class;
57 static PangoAttrList *attrs = NULL;
58 
59 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState(JNIEnv * env,jclass clazz)60 Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState
61   (JNIEnv *env, jclass clazz)
62 {
63   NSA_FONT_INIT (env, clazz);
64 
65   glyphVector_class = (*env)->FindClass
66     (env, "gnu/java/awt/peer/gtk/GdkGlyphVector");
67 
68   glyphVector_ctor = (*env)->GetMethodID
69     (env, glyphVector_class, "<init>",
70      "([D[ILjava/awt/Font;Ljava/awt/font/FontRenderContext;)V");
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   NSA_SET_FONT_PTR (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 *)NSA_DEL_FONT_PTR (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->ctx != NULL)
105     g_object_unref (pfont->ctx);
106   if (pfont->desc != NULL)
107     pango_font_description_free (pfont->desc);
108   g_free (pfont);
109 
110   gdk_threads_leave ();
111 }
112 
113 
114 JNIEXPORT jobject JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector(JNIEnv * env,jobject self,jstring chars,jobject font,jobject fontRenderContext)115 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector
116   (JNIEnv *env, jobject self,
117    jstring chars,
118    jobject font,
119    jobject fontRenderContext)
120 {
121   struct peerfont *pfont = NULL;
122   GList *items = NULL;
123   GList *i = NULL;
124   gchar *str = NULL;
125   int len = 0;
126   int j = 0;
127   double *native_extents = NULL;
128   int *native_codes = NULL;
129   jintArray java_codes = NULL;
130   jdoubleArray java_extents = NULL;
131 
132   gdk_threads_enter ();
133 
134   pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
135   g_assert (pfont != NULL);
136 
137   len = (*cp_gtk_gdk_env())->GetStringUTFLength (env, chars);
138   str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL);
139   g_assert (str != NULL);
140 
141   if (attrs == NULL)
142     attrs = pango_attr_list_new ();
143 
144   if (len > 0 && str[len-1] == '\0')
145     len--;
146 
147   items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL);
148 
149   i = g_list_first (items);
150 
151   if (i == NULL)
152     {
153       java_extents = (*env)->NewDoubleArray (env, 0);
154       java_codes = (*env)->NewIntArray (env, 0);
155     }
156   else
157     {
158       PangoGlyphString *glyphs;
159       PangoItem *item = (PangoItem *)i->data;
160 
161       pango_context_set_font_description (pfont->ctx, pfont->desc);
162       pango_context_set_language (pfont->ctx, gtk_get_default_language());
163       pango_context_load_font (pfont->ctx, pfont->desc);
164 
165       glyphs = pango_glyph_string_new ();
166       g_assert (glyphs != NULL);
167 
168       pango_shape (str + item->offset, item->length,
169 		   &(item->analysis), glyphs);
170 
171       if (glyphs->num_glyphs > 0)
172 	{
173 	  int x = 0;
174 	  double scale = ((double) PANGO_SCALE);
175 
176 	  java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS);
177 	  java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs);
178 
179 	  native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL);
180 	  native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL);
181 
182 	  for (j = 0; j < glyphs->num_glyphs; ++j)
183 	    {
184 	      PangoRectangle ink;
185 	      PangoRectangle logical;
186 	      PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry;
187 
188 	      pango_font_get_glyph_extents (pfont->font,
189 					    glyphs->glyphs[j].glyph,
190 					    &ink, &logical);
191 
192 	      native_codes[j] = glyphs->glyphs[j].glyph;
193 
194 	      native_extents[ GLYPH_LOG_X(j)      ] = (logical.x)      / scale;
195 	      native_extents[ GLYPH_LOG_Y(j)      ] = (- logical.y)    / scale;
196 	      native_extents[ GLYPH_LOG_WIDTH(j)  ] = (logical.width)  / scale;
197 	      native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale;
198 
199 	      native_extents[ GLYPH_INK_X(j)      ] = (ink.x)       / scale;
200 	      native_extents[ GLYPH_INK_Y(j)      ] = (- ink.y)     / scale;
201 	      native_extents[ GLYPH_INK_WIDTH(j)  ] = (ink.width)   / scale;
202 	      native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height)  / scale;
203 
204 	      native_extents[ GLYPH_POS_X(j)      ] = (x + geom->x_offset)  / scale;
205 	      native_extents[ GLYPH_POS_Y(j)      ] = (  - geom->y_offset)  / scale;
206 
207 	      x += geom->width;
208 	    }
209 	  (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0);
210 	  (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
211 	}
212 
213       pango_glyph_string_free (glyphs);
214     }
215 
216   (*env)->ReleaseStringUTFChars (env, chars, str);
217 
218   for (i = g_list_first (items); i != NULL; i = g_list_next (i))
219     g_free (i->data);
220 
221   g_list_free (items);
222 
223   gdk_threads_leave ();
224 
225   return (*env)->NewObject (env,
226 			    glyphVector_class,
227 			    glyphVector_ctor,
228 			    java_extents, java_codes,
229 			    font, fontRenderContext);
230 }
231 
232 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics(JNIEnv * env,jobject java_font,jdoubleArray java_metrics)233 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics
234    (JNIEnv *env, jobject java_font, jdoubleArray java_metrics)
235 {
236   struct peerfont *pfont = NULL;
237   jdouble *native_metrics = NULL;
238   PangoFontMetrics *pango_metrics = NULL;
239 
240   gdk_threads_enter();
241 
242   pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font);
243   g_assert (pfont != NULL);
244 
245   pango_metrics
246     = pango_context_get_metrics (pfont->ctx, pfont->desc,
247 				 gtk_get_default_language ());
248 
249   native_metrics
250     = (*env)->GetDoubleArrayElements (env, java_metrics, NULL);
251 
252   g_assert (native_metrics != NULL);
253 
254   native_metrics[FONT_METRICS_ASCENT]
255     = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics));
256 
257   native_metrics[FONT_METRICS_MAX_ASCENT]
258     = native_metrics[FONT_METRICS_ASCENT];
259 
260   native_metrics[FONT_METRICS_DESCENT]
261     = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics));
262 
263   if (native_metrics[FONT_METRICS_DESCENT] < 0)
264     native_metrics[FONT_METRICS_DESCENT]
265       = - native_metrics[FONT_METRICS_DESCENT];
266 
267   native_metrics[FONT_METRICS_MAX_DESCENT]
268     = native_metrics[FONT_METRICS_DESCENT];
269 
270   native_metrics[FONT_METRICS_MAX_ADVANCE]
271     = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width
272 		    (pango_metrics));
273 
274   (*env)->ReleaseDoubleArrayElements (env,
275 				      java_metrics,
276 				      native_metrics, 0);
277 
278   pango_font_metrics_unref (pango_metrics);
279 
280   gdk_threads_leave();
281 }
282 
283 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics(JNIEnv * env,jobject java_font,jstring str,jdoubleArray java_metrics)284 Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics
285    (JNIEnv *env, jobject java_font, jstring str, jdoubleArray java_metrics)
286 {
287   struct peerfont *pfont = NULL;
288   const char *cstr = NULL;
289   jdouble *native_metrics = NULL;
290   PangoRectangle log;
291 
292   gdk_threads_enter();
293 
294   pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font);
295   g_assert (pfont != NULL);
296 
297   cstr = (*env)->GetStringUTFChars (env, str, NULL);
298   g_assert(cstr != NULL);
299 
300   pango_layout_set_text (pfont->layout, cstr, -1);
301   pango_layout_get_extents (pfont->layout, NULL, &log);
302 
303   (*env)->ReleaseStringUTFChars (env, str, cstr);
304   pango_layout_set_text (pfont->layout, "", -1);
305 
306   native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL);
307   g_assert (native_metrics != NULL);
308 
309   native_metrics[TEXT_METRICS_X_BEARING]
310     = PANGO_PIXELS( ((double)log.x) );
311 
312   native_metrics[TEXT_METRICS_Y_BEARING]
313     = PANGO_PIXELS( ((double)log.y) );
314 
315   native_metrics[TEXT_METRICS_WIDTH]
316     = PANGO_PIXELS( ((double)log.width) );
317 
318   native_metrics[TEXT_METRICS_HEIGHT]
319     = PANGO_PIXELS( ((double)log.height) );
320 
321   native_metrics[TEXT_METRICS_X_ADVANCE]
322     = PANGO_PIXELS( ((double) (log.x + log.width)) );
323 
324   native_metrics[TEXT_METRICS_Y_ADVANCE]
325     = PANGO_PIXELS( ((double) (log.y + log.height)) );
326 
327   (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0);
328 
329   gdk_threads_leave();
330 }
331 
332 
333 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont(JNIEnv * env,jobject self,jstring family_name_str,jint style_int,jint size,jboolean useGraphics2D)334 Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont
335   (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size, jboolean useGraphics2D)
336 {
337   struct peerfont *pfont = NULL;
338   char const *family_name = NULL;
339   enum java_awt_font_style style;
340   PangoFT2FontMap *ft2_map = NULL;
341 
342   gdk_threads_enter ();
343 
344   style = (enum java_awt_font_style) style_int;
345 
346   g_assert (self != NULL);
347   pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
348   g_assert (pfont != NULL);
349 
350   if (pfont->ctx != NULL)
351     g_object_unref (pfont->ctx);
352   if (pfont->font != NULL)
353     g_object_unref (pfont->font);
354   if (pfont->desc != NULL)
355     pango_font_description_free (pfont->desc);
356 
357   pfont->desc = pango_font_description_new ();
358   g_assert (pfont->desc != NULL);
359 
360   family_name = (*env)->GetStringUTFChars(env, family_name_str, 0);
361   g_assert (family_name != NULL);
362   pango_font_description_set_family (pfont->desc, family_name);
363   (*env)->ReleaseStringUTFChars(env, family_name_str, family_name);
364 
365 
366   if (style & java_awt_font_BOLD)
367     pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD);
368 
369   if (style & java_awt_font_ITALIC)
370     pango_font_description_set_style (pfont->desc, PANGO_STYLE_ITALIC);
371 
372   if (useGraphics2D)
373     {
374       pango_font_description_set_size (pfont->desc, size * PANGO_SCALE);
375       if (pfont->ctx == NULL)
376 	{
377 	  ft2_map = PANGO_FT2_FONT_MAP(pango_ft2_font_map_for_display ());
378 	  pfont->ctx = pango_ft2_font_map_create_context (ft2_map);
379 	}
380     }
381   else
382     {
383       /* GDK uses a slightly different DPI setting. */
384       pango_font_description_set_size (pfont->desc,
385 				   size * cp_gtk_dpi_conversion_factor);
386       if (pfont->ctx == NULL)
387 	pfont->ctx = gdk_pango_context_get();
388     }
389 
390   g_assert (pfont->ctx != NULL);
391 
392   if (pfont->font != NULL)
393     {
394       g_object_unref (pfont->font);
395       pfont->font = NULL;
396     }
397 
398   pango_context_set_font_description (pfont->ctx, pfont->desc);
399   pango_context_set_language (pfont->ctx, gtk_get_default_language());
400   pfont->font = pango_context_load_font (pfont->ctx, pfont->desc);
401   g_assert (pfont->font != NULL);
402 
403   if (pfont->layout == NULL)
404     pfont->layout = pango_layout_new (pfont->ctx);
405   g_assert (pfont->layout != NULL);
406 
407   gdk_threads_leave ();
408 }
409 
410 
411