This commit was manufactured by cvs2svn to create branch 'gomp-branch'.
[official-gcc.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GdkGlyphVector.c
blob5e8562455a4d72f9408164e7c24a90d4cfeeebfa
1 /* gdkglyphvector.c
2 Copyright (C) 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
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.
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. */
38 #include "gdkfont.h"
39 #include "gnu_java_awt_peer_gtk_GdkGlyphVector.h"
41 struct state_table *native_glyphvector_state_table;
43 typedef struct {
44 double x;
45 double y;
46 double width;
47 double height;
48 } rect_t;
50 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
51 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
52 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
53 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
55 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initStaticState
56 (JNIEnv *env, jclass clazz)
58 NSA_GV_INIT (env, clazz);
61 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initState
62 (JNIEnv *env, jobject self, jobject font, jobject ctx)
64 struct glyphvec *vec = NULL;
65 struct peerfont *pfont = NULL;
67 gdk_threads_enter ();
68 g_assert (font != NULL);
69 pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
70 g_assert (pfont != NULL);
71 g_assert (pfont->ctx != NULL);
72 g_assert (pfont->desc != NULL);
74 g_assert (self != NULL);
75 vec = (struct glyphvec *) g_malloc0 (sizeof (struct glyphvec));
76 g_assert (vec != NULL);
78 vec->desc = pango_font_describe (pfont->font);
79 g_assert (vec->desc != NULL);
81 vec->font = pfont->font;
82 g_object_ref (vec->font);
84 vec->ctx = pfont->ctx;
85 g_object_ref (vec->ctx);
87 NSA_SET_GV_PTR (env, self, vec);
88 gdk_threads_leave ();
91 static void free_glyphitems (GList *list)
93 GList *i = NULL;
94 PangoGlyphItem *gi = NULL;
96 for (i = g_list_first (list); i != NULL; i = g_list_next (i))
98 g_assert (i->data != NULL);
99 gi = (PangoGlyphItem *)i->data;
101 if (gi->glyphs != NULL)
102 pango_glyph_string_free (gi->glyphs);
104 if (gi->item != NULL)
105 g_free (gi->item);
107 g_list_free (list);
110 static void seek_glyphstring_idx (GList *list, int idx,
111 int *nidx,
112 PangoGlyphString **gs,
113 PangoFont **fnt)
115 GList *i = NULL;
116 PangoGlyphItem *gi = NULL;
118 g_assert (list != NULL);
119 g_assert (gs != NULL);
120 g_assert (nidx != NULL);
122 int begin = 0;
123 for (i = g_list_first (list); i != NULL; i = g_list_next (i))
125 g_assert (i->data != NULL);
126 gi = (PangoGlyphItem *)i->data;
128 g_assert (gi->glyphs != NULL);
130 if (begin <= idx && idx < begin + gi->glyphs->num_glyphs)
132 *gs = gi->glyphs;
133 *nidx = idx - begin;
134 if (fnt && gi->item)
135 *fnt = gi->item->analysis.font;
136 return;
138 else
140 begin += gi->glyphs->num_glyphs;
143 *gs = NULL;
144 *nidx = -1;
147 static void seek_glyph_idx (GList *list, int idx,
148 PangoGlyphInfo **g,
149 PangoFont **fnt)
151 PangoGlyphString *gs = NULL;
152 int nidx = -1;
154 g_assert (list != NULL);
155 g_assert (g != NULL);
157 seek_glyphstring_idx (list, idx, &nidx, &gs, fnt);
159 g_assert (gs != NULL);
160 g_assert (nidx != -1);
161 g_assert (nidx < gs->num_glyphs);
162 g_assert (gs->glyphs != NULL);
164 *g = gs->glyphs + nidx;
167 static void union_rects (rect_t *r1,
168 const rect_t *r2)
170 rect_t r;
172 g_assert (r1 != NULL);
173 g_assert (r2 != NULL);
176 x is the left edge of the rect,
177 y is the top edge of the rect
180 #ifndef min
181 #define min(x,y) ((x) < (y) ? (x) : (y))
182 #endif
184 #ifndef max
185 #define max(x,y) ((x) < (y) ? (y) : (x))
186 #endif
188 r.x = min(r1->x, r2->x);
190 r.y = min(r1->y, r2->y);
192 r.width = max(r1->x + r1->width,
193 r2->x + r2->width) - r.x;
195 r.height = max(r1->y + r1->height,
196 r2->y + r2->height) - r.y;
198 *r1 = r;
201 static jdoubleArray rect_to_array (JNIEnv *env, const rect_t *r)
203 /* We often return rectangles as arrays : { x, y, w, h } */
204 jdoubleArray ret;
205 double *rp = NULL;
206 g_assert (r != NULL);
207 ret = (*env)->NewDoubleArray (env, 4);
208 rp = (*env)->GetDoubleArrayElements (env, ret, NULL);
209 g_assert (rp != NULL);
210 rp[0] = r->x;
211 /* freetype and pango's view of space is upside down from java2d's */
212 rp[1] = r->y * -1;
213 rp[2] = r->width;
214 rp[3] = r->height;
215 (*env)->ReleaseDoubleArrayElements (env, ret, rp, 0);
216 return ret;
220 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_dispose
221 (JNIEnv *env, jobject self)
223 struct glyphvec *vec = NULL;
225 gdk_threads_enter ();
226 g_assert (self != NULL);
227 vec = (struct glyphvec *)NSA_DEL_GV_PTR (env, self);
228 g_assert (vec != NULL);
230 if (vec->glyphitems != NULL)
232 free_glyphitems (vec->glyphitems);
233 vec->glyphitems = NULL;
236 if (vec->desc != NULL)
237 pango_font_description_free (vec->desc);
239 if (vec->ctx != NULL)
240 g_object_unref (vec->ctx);
242 g_free (vec);
243 gdk_threads_leave ();
247 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setChars
248 (JNIEnv *env, jobject self, jstring chars)
250 struct glyphvec *vec = NULL;
251 gchar *str = NULL;
252 GList *items = NULL, *item = NULL;
253 PangoGlyphItem *gi;
254 PangoAttrList *attrs = NULL;
255 gint len = 0;
257 gdk_threads_enter ();
258 g_assert (self != NULL);
259 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
260 g_assert (vec != NULL);
261 g_assert (vec->desc != NULL);
262 g_assert (vec->ctx != NULL);
264 len = (*gdk_env)->GetStringUTFLength (env, chars);
265 str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL);
266 g_assert (str != NULL);
268 /* step 1: set our FontFescription in the context, then "itemize" the
269 text */
271 attrs = pango_attr_list_new ();
272 g_assert (attrs != NULL);
274 pango_context_set_font_description (vec->ctx, vec->desc);
276 items = pango_itemize (vec->ctx, str, 0, len, attrs, NULL);
277 g_assert (items != NULL);
280 step 2: for each item:
281 - shape the item into a glyphstring
282 - store the (item, glyphstring) pair in the vec->glyphitems list
285 if (vec->glyphitems != NULL)
287 free_glyphitems (vec->glyphitems);
288 vec->glyphitems = NULL;
291 for (item = g_list_first (items); item != NULL; item = g_list_next (item))
293 g_assert (item->data != NULL);
295 gi = NULL;
296 gi = g_malloc0 (sizeof(PangoGlyphItem));
297 g_assert (gi != NULL);
299 gi->item = (PangoItem *)item->data;
300 gi->glyphs = pango_glyph_string_new ();
301 g_assert (gi->glyphs != NULL);
303 pango_shape (str + gi->item->offset,
304 gi->item->length,
305 &(gi->item->analysis),
306 gi->glyphs);
308 vec->glyphitems = g_list_append (vec->glyphitems, gi);
312 ownership of each item has been transferred to glyphitems,
313 but the list should be freed.
316 g_list_free (items);
317 pango_attr_list_unref (attrs);
319 (*env)->ReleaseStringUTFChars (env, chars, str);
320 gdk_threads_leave ();
324 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setGlyphCodes
325 (JNIEnv *env, jobject self, jintArray codes)
327 struct glyphvec *vec = NULL;
329 gdk_threads_enter ();
330 g_assert (self != NULL);
331 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
332 g_assert (vec != NULL);
335 FIXME: setting glyph codes doesn't seem particularly plausible at the
336 moment.
339 gdk_threads_leave ();
344 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCode
345 (JNIEnv *env, jobject self, jint idx)
347 struct glyphvec *vec = NULL;
348 PangoGlyphInfo *gi = NULL;
349 jint ret = 0;
351 gdk_threads_enter ();
352 g_assert (self != NULL);
353 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
354 g_assert (vec != NULL);
355 g_assert (vec->glyphitems != NULL);
357 seek_glyph_idx (vec->glyphitems, idx, &gi, NULL);
358 g_assert (gi != NULL);
359 ret = gi->glyph;
360 gdk_threads_leave ();
362 return (jint)(ret);
366 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_numGlyphs
367 (JNIEnv *env, jobject self)
369 GList *i = NULL;
370 PangoGlyphItem *gi = NULL;
371 struct glyphvec *vec = NULL;
372 jint count = 0;
374 gdk_threads_enter ();
375 g_assert (self != NULL);
376 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
377 g_assert (vec != NULL);
379 for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
381 g_assert (i->data != NULL);
382 gi = (PangoGlyphItem *)i->data;
383 g_assert (gi->glyphs != NULL);
384 count += gi->glyphs->num_glyphs;
386 gdk_threads_leave ();
388 return count;
392 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCharIndex
393 (JNIEnv *env, jobject self, jint idx)
396 FIXME: this is not correct, rather it assumes a (broken) 1:1
397 glyph:char model. it can be implemented in terms of bytes (also
398 broken) using pango's current interface, or perhaps in terms of
399 characters if some better byte->character conversion operator is
400 found. for the time being we leave it broken.
402 return idx;
405 static void
406 assume_pointsize_and_identity_transform(double pointsize,
407 FT_Face face)
409 FT_Matrix mat;
410 mat.xx = DOUBLE_TO_16_16(1);
411 mat.xy = DOUBLE_TO_16_16(0);
412 mat.yx = DOUBLE_TO_16_16(0);
413 mat.yy = DOUBLE_TO_16_16(1);
414 FT_Set_Transform(face, &mat, NULL);
415 FT_Set_Char_Size( face,
416 DOUBLE_TO_26_6 (pointsize),
417 DOUBLE_TO_26_6 (pointsize),
418 0, 0);
421 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents
422 (JNIEnv *env, jobject self)
424 struct glyphvec *vec = NULL;
425 int j;
426 GList *i;
427 PangoGlyphItem *gi = NULL;
428 rect_t rect = {0,0,0,0};
429 rect_t tmp;
430 jdoubleArray ret;
431 double x = 0, y = 0;
432 double pointsize;
433 FT_Face face;
435 gdk_threads_enter ();
436 g_assert (self != NULL);
437 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
438 g_assert (vec != NULL);
439 g_assert (vec->glyphitems != NULL);
441 pointsize = pango_font_description_get_size (vec->desc);
442 pointsize /= (double) PANGO_SCALE;
444 for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
446 g_assert (i->data != NULL);
447 gi = (PangoGlyphItem *)i->data;
448 g_assert (gi->glyphs != NULL);
450 face = pango_ft2_font_get_face (gi->item->analysis.font);
451 assume_pointsize_and_identity_transform (pointsize, face);
453 for (j = 0; j < gi->glyphs->num_glyphs; ++j)
455 FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
456 /* FIXME: this needs to change for vertical layouts */
457 tmp.x = x + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
458 tmp.y = y + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
459 tmp.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
460 tmp.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
461 union_rects (&rect, &tmp);
462 x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
463 y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
467 ret = rect_to_array (env, &rect);
468 gdk_threads_leave ();
469 return ret;
473 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents
474 (JNIEnv *env, jobject self)
476 struct glyphvec *vec = NULL;
477 int j;
478 GList *i;
479 PangoGlyphItem *gi = NULL;
480 rect_t rect = {0,0,0,0};
481 rect_t tmp;
482 jdoubleArray ret;
483 double x = 0, y = 0;
484 double pointsize;
485 FT_Face face;
487 gdk_threads_enter ();
488 g_assert (self != NULL);
489 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
490 g_assert (vec != NULL);
491 g_assert (vec->glyphitems != NULL);
493 pointsize = pango_font_description_get_size (vec->desc);
494 pointsize /= (double) PANGO_SCALE;
496 for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
498 g_assert (i->data != NULL);
499 gi = (PangoGlyphItem *)i->data;
500 g_assert (gi->glyphs != NULL);
502 face = pango_ft2_font_get_face (gi->item->analysis.font);
503 assume_pointsize_and_identity_transform (pointsize, face);
505 for (j = 0; j < gi->glyphs->num_glyphs; ++j)
507 FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
509 /* FIXME: also, this is probably not the correct set of metrics;
510 the "logical bounds" are some fancy combination of hori
511 advance and height such that it's good for inverting as a
512 highlight. revisit. */
514 tmp.x = x;
515 tmp.y = y;
516 tmp.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
517 tmp.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
518 union_rects (&rect, &tmp);
519 x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
520 y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
524 ret = rect_to_array (env, &rect);
525 gdk_threads_leave ();
526 return ret;
530 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphLogicalExtents
531 (JNIEnv *env, jobject self, jint idx)
533 struct glyphvec *vec = NULL;
534 rect_t rect = {0,0,0,0};
535 PangoGlyphInfo *gi = NULL;
536 PangoFont *font = NULL;
537 jdoubleArray ret;
538 double pointsize;
539 FT_Face face;
541 gdk_threads_enter ();
542 g_assert (self != NULL);
543 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
544 g_assert (vec != NULL);
545 g_assert (vec->glyphitems != NULL);
547 seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
548 g_assert (gi != NULL);
549 g_assert (font != NULL);
551 pointsize = pango_font_description_get_size (vec->desc);
552 pointsize /= (double) PANGO_SCALE;
553 face = pango_ft2_font_get_face (font);
555 assume_pointsize_and_identity_transform (pointsize, face);
557 FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
559 /* FIXME: this is probably not the correct set of metrics;
560 the "logical bounds" are some fancy combination of hori
561 advance and height such that it's good for inverting as a
562 highlight. revisit. */
564 rect.x = 0;
565 rect.y = 0;
566 rect.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
567 rect.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
569 ret = rect_to_array (env, &rect);
570 gdk_threads_leave ();
571 return ret;
575 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphInkExtents
576 (JNIEnv *env, jobject self, jint idx)
578 struct glyphvec *vec = NULL;
579 rect_t rect = {0,0,0,0};
580 PangoGlyphInfo *gi = NULL;
581 PangoFont *font = NULL;
582 jdoubleArray ret;
583 double pointsize;
584 FT_Face face;
586 gdk_threads_enter ();
587 g_assert (self != NULL);
588 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
589 g_assert (vec != NULL);
590 g_assert (vec->glyphitems != NULL);
592 seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
593 g_assert (gi != NULL);
594 g_assert (font != NULL);
596 pointsize = pango_font_description_get_size (vec->desc);
597 pointsize /= (double) PANGO_SCALE;
598 face = pango_ft2_font_get_face (font);
600 assume_pointsize_and_identity_transform (pointsize, face);
602 FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
603 /* FIXME: this needs to change for vertical layouts */
604 rect.x = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
605 rect.y = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
606 rect.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
607 rect.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
609 ret = rect_to_array (env, &rect);
610 gdk_threads_leave ();
611 return ret;
615 JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHorizontal
616 (JNIEnv *env, jobject self, jint idx)
618 struct glyphvec *vec = NULL;
619 PangoDirection dir;
621 gdk_threads_enter ();
622 g_assert (self != NULL);
623 vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
624 g_assert (vec != NULL);
625 g_assert (vec->desc != NULL);
626 g_assert (vec->ctx != NULL);
629 FIXME: this is an approximation; it's not clear to me whether
630 glyphs themselves are horizontal or vertical so much as the
631 writing system or writing context. pango thinks it's a context
632 issue, so we use that for now.
635 dir = pango_context_get_base_dir (vec->ctx);
637 gdk_threads_leave ();
639 return 1;
640 /* FIXME: Pango doesn't seem to have decided how it will deal
641 with vertical text. for the time being we inherit this limitation.
642 ((dir == PANGO_DIRECTION_LTR) ||
643 (dir == PANGO_DIRECTION_RTL));
648 JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_isEqual
649 (JNIEnv *env, jobject self, jobject other)
651 struct glyphvec *vec1 = NULL, *vec2 = NULL;
652 jboolean eq = 0;
654 gdk_threads_enter ();
655 g_assert (self != NULL);
656 vec1 = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
657 vec2 = (struct glyphvec *)NSA_GET_GV_PTR (env, other);
658 g_assert (vec1 != NULL);
659 g_assert (vec2 != NULL);
661 /* FIXME: is there some more advantageous definition of equality for
662 glyph vectors? */
663 eq = (vec1 == vec2);
665 gdk_threads_leave ();
666 return eq;