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)
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
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
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. */
39 #include "gnu_java_awt_peer_gtk_GdkGlyphVector.h"
41 struct state_table
*native_glyphvector_state_table
;
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
;
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
);
91 static void free_glyphitems (GList
*list
)
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
)
110 static void seek_glyphstring_idx (GList
*list
, int idx
,
112 PangoGlyphString
**gs
,
116 PangoGlyphItem
*gi
= NULL
;
118 g_assert (list
!= NULL
);
119 g_assert (gs
!= NULL
);
120 g_assert (nidx
!= NULL
);
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
)
135 *fnt
= gi
->item
->analysis
.font
;
140 begin
+= gi
->glyphs
->num_glyphs
;
147 static void seek_glyph_idx (GList
*list
, int idx
,
151 PangoGlyphString
*gs
= NULL
;
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
,
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
181 #define min(x,y) ((x) < (y) ? (x) : (y))
185 #define max(x,y) ((x) < (y) ? (y) : (x))
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
;
201 static jdoubleArray
rect_to_array (JNIEnv
*env
, const rect_t
*r
)
203 /* We often return rectangles as arrays : { x, y, w, h } */
206 g_assert (r
!= NULL
);
207 ret
= (*env
)->NewDoubleArray (env
, 4);
208 rp
= (*env
)->GetDoubleArrayElements (env
, ret
, NULL
);
209 g_assert (rp
!= NULL
);
211 /* freetype and pango's view of space is upside down from java2d's */
215 (*env
)->ReleaseDoubleArrayElements (env
, ret
, rp
, 0);
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
);
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
;
252 GList
*items
= NULL
, *item
= NULL
;
254 PangoAttrList
*attrs
= NULL
;
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
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
);
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
,
305 &(gi
->item
->analysis
),
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.
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
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
;
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
);
360 gdk_threads_leave ();
366 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_numGlyphs
367 (JNIEnv
*env
, jobject self
)
370 PangoGlyphItem
*gi
= NULL
;
371 struct glyphvec
*vec
= NULL
;
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 ();
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.
406 assume_pointsize_and_identity_transform(double pointsize
,
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
),
421 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents
422 (JNIEnv
*env
, jobject self
)
424 struct glyphvec
*vec
= NULL
;
427 PangoGlyphItem
*gi
= NULL
;
428 rect_t rect
= {0,0,0,0};
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 ();
473 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents
474 (JNIEnv
*env
, jobject self
)
476 struct glyphvec
*vec
= NULL
;
479 PangoGlyphItem
*gi
= NULL
;
480 rect_t rect
= {0,0,0,0};
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. */
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 ();
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
;
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. */
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 ();
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
;
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 ();
615 JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHorizontal
616 (JNIEnv
*env
, jobject self
, jint idx
)
618 struct glyphvec
*vec
= NULL
;
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 ();
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
;
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
665 gdk_threads_leave ();