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