| /* gnu_java_awt_GdkFont.c |
| Copyright (C) 2003, 2004 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| #include <pango/pango.h> |
| #include <pango/pangoft2.h> |
| #include <pango/pangofc-font.h> |
| #include <freetype/ftglyph.h> |
| #include <freetype/ftoutln.h> |
| #include <freetype/fttypes.h> |
| #include <freetype/tttables.h> |
| #include "gdkfont.h" |
| #include "gnu_java_awt_peer_gtk_GdkFontPeer.h" |
| |
| struct state_table *cp_gtk_native_font_state_table; |
| |
| enum java_awt_font_style { |
| java_awt_font_PLAIN = 0, |
| java_awt_font_BOLD = 1, |
| java_awt_font_ITALIC = 2 |
| }; |
| |
| enum java_awt_font_baseline { |
| java_awt_font_ROMAN_BASELINE = 0, |
| java_awt_font_CENTER_BASELINE = 1, |
| java_awt_font_HANGING_BASELINE = 2 |
| }; |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState |
| (JNIEnv *env, jclass clazz) |
| { |
| NSA_FONT_INIT (env, clazz); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_initState |
| (JNIEnv *env, jobject self) |
| { |
| struct peerfont *pfont = NULL; |
| |
| gdk_threads_enter (); |
| |
| g_assert (self != NULL); |
| pfont = (struct peerfont *) g_malloc0 (sizeof (struct peerfont)); |
| g_assert (pfont != NULL); |
| NSA_SET_FONT_PTR (env, self, pfont); |
| |
| gdk_threads_leave (); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose |
| (JNIEnv *env, jobject self) |
| { |
| struct peerfont *pfont = NULL; |
| |
| gdk_threads_enter (); |
| |
| pfont = (struct peerfont *)NSA_DEL_FONT_PTR (env, self); |
| g_assert (pfont != NULL); |
| if (pfont->layout != NULL) |
| g_object_unref (pfont->layout); |
| if (pfont->font != NULL) |
| g_object_unref (pfont->font); |
| if (pfont->ctx != NULL) |
| g_object_unref (pfont->ctx); |
| if (pfont->desc != NULL) |
| pango_font_description_free (pfont->desc); |
| g_free (pfont); |
| |
| gdk_threads_leave (); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource |
| (JNIEnv *env, jobject java_font) |
| { |
| struct peerfont *pfont = NULL; |
| |
| gdk_threads_enter(); |
| |
| pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); |
| g_assert (pfont != NULL); |
| if (pfont->graphics_resource != NULL) |
| { |
| cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); |
| pfont->graphics_resource = NULL; |
| } |
| |
| gdk_threads_leave(); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics |
| (JNIEnv *env, jobject java_font, jdoubleArray java_metrics) |
| { |
| struct peerfont *pfont = NULL; |
| jdouble *native_metrics = NULL; |
| PangoFontMetrics *pango_metrics = NULL; |
| PangoLayout* layout = NULL; |
| PangoRectangle ink_rect; |
| PangoRectangle logical_rect; |
| PangoLayoutIter* iter = NULL; |
| int pango_ascent = 0; |
| int pango_descent = 0; |
| int pango_ink_ascent = 0; |
| int pango_ink_descent = 0; |
| int baseline = 0; |
| int java_ascent = 0; |
| int java_descent = 0; |
| |
| gdk_threads_enter(); |
| |
| pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); |
| g_assert (pfont != NULL); |
| |
| pango_metrics |
| = pango_context_get_metrics (pfont->ctx, pfont->desc, |
| gtk_get_default_language ()); |
| |
| native_metrics |
| = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); |
| |
| g_assert (native_metrics != NULL); |
| |
| pango_ascent = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics)); |
| pango_descent = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics)); |
| |
| layout = pango_layout_new (pfont->ctx); |
| |
| /* Pango seems to produce ascent and descent values larger than |
| those that Sun produces for the same-sized font. It turns out |
| that an average of the "ink ascent" and "logical ascent" closely |
| approximates Sun's ascent values. Likewise for descent values. |
| This is expensive but we cache GdkFontMetrics so this should only |
| run once per Font instance. */ |
| pango_layout_set_text (layout, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL" |
| "MNOPQRSTUVWXYZ0123456789", -1); |
| pango_layout_set_font_description (layout, pfont->desc); |
| |
| pango_layout_get_pixel_extents (layout, &ink_rect, &logical_rect); |
| |
| iter = pango_layout_get_iter (layout); |
| |
| baseline = PANGO_PIXELS (pango_layout_iter_get_baseline (iter)); |
| |
| pango_ink_ascent = baseline - ink_rect.y; |
| pango_ink_descent = ink_rect.y + ink_rect.height - baseline; |
| |
| java_ascent = (pango_ascent + pango_ink_ascent) >> 1; |
| java_descent = (pango_descent + pango_ink_descent) >> 1; |
| |
| java_ascent = MAX(0, java_ascent); |
| java_descent = MAX(0, java_descent); |
| |
| pango_ascent = MAX(0, pango_ascent); |
| pango_descent = MAX(0, pango_descent); |
| |
| /* Pango monospaced fonts have smaller ascent metrics than Sun's so |
| we return the logical ascent for monospaced fonts. */ |
| if (!strcmp (pango_font_description_get_family (pfont->desc), |
| "Courier")) |
| native_metrics[FONT_METRICS_ASCENT] = pango_ascent; |
| else |
| native_metrics[FONT_METRICS_ASCENT] = java_ascent; |
| |
| native_metrics[FONT_METRICS_MAX_ASCENT] = pango_ascent; |
| |
| native_metrics[FONT_METRICS_DESCENT] = java_descent; |
| |
| native_metrics[FONT_METRICS_MAX_DESCENT] = pango_descent; |
| |
| native_metrics[FONT_METRICS_MAX_ADVANCE] |
| = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width |
| (pango_metrics)); |
| |
| (*env)->ReleaseDoubleArrayElements (env, |
| java_metrics, |
| native_metrics, 0); |
| |
| pango_font_metrics_unref (pango_metrics); |
| |
| gdk_threads_leave(); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics |
| (JNIEnv *env, jobject java_font, jstring str, jdoubleArray java_metrics) |
| { |
| struct peerfont *pfont = NULL; |
| const char *cstr = NULL; |
| jdouble *native_metrics = NULL; |
| PangoRectangle log; |
| PangoRectangle log2; |
| int line_count = 0; |
| int i = 0; |
| int width = 0; |
| |
| gdk_threads_enter(); |
| |
| pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); |
| g_assert (pfont != NULL); |
| |
| cstr = (*env)->GetStringUTFChars (env, str, NULL); |
| g_assert(cstr != NULL); |
| |
| pango_layout_set_text (pfont->layout, cstr, -1); |
| pango_layout_get_extents (pfont->layout, NULL, &log); |
| |
| line_count = pango_layout_get_line_count (pfont->layout); |
| for (i = 0; i < line_count; i++) |
| { |
| pango_layout_line_get_extents (pango_layout_get_line (pfont->layout, i), |
| NULL, &log2); |
| width += log2.width; |
| } |
| |
| (*env)->ReleaseStringUTFChars (env, str, cstr); |
| pango_layout_set_text (pfont->layout, "", -1); |
| |
| native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); |
| g_assert (native_metrics != NULL); |
| |
| native_metrics[TEXT_METRICS_X_BEARING] |
| = PANGO_PIXELS( ((double)log.x) ); |
| |
| native_metrics[TEXT_METRICS_Y_BEARING] |
| = PANGO_PIXELS( ((double)log.y) ); |
| |
| native_metrics[TEXT_METRICS_HEIGHT] |
| = PANGO_PIXELS( ((double)log.height) ); |
| |
| native_metrics[TEXT_METRICS_WIDTH] |
| = PANGO_PIXELS( ((double)width) ); |
| |
| native_metrics[TEXT_METRICS_X_ADVANCE] |
| = PANGO_PIXELS( ((double) (log.x + log.width)) ); |
| |
| native_metrics[TEXT_METRICS_Y_ADVANCE] |
| = PANGO_PIXELS( ((double) (log.y + log.height)) ); |
| |
| (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); |
| |
| gdk_threads_leave(); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont |
| (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size) |
| { |
| struct peerfont *pfont = NULL; |
| char const *family_name = NULL; |
| enum java_awt_font_style style; |
| PangoFT2FontMap *ft2_map = NULL; |
| |
| gdk_threads_enter (); |
| |
| style = (enum java_awt_font_style) style_int; |
| |
| g_assert (self != NULL); |
| pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); |
| g_assert (pfont != NULL); |
| |
| if (pfont->ctx != NULL) |
| g_object_unref (pfont->ctx); |
| if (pfont->font != NULL) |
| g_object_unref (pfont->font); |
| if (pfont->desc != NULL) |
| pango_font_description_free (pfont->desc); |
| |
| pfont->desc = pango_font_description_new (); |
| g_assert (pfont->desc != NULL); |
| |
| family_name = (*env)->GetStringUTFChars(env, family_name_str, 0); |
| g_assert (family_name != NULL); |
| pango_font_description_set_family (pfont->desc, family_name); |
| (*env)->ReleaseStringUTFChars(env, family_name_str, family_name); |
| |
| |
| if (style & java_awt_font_BOLD) |
| pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD); |
| |
| if (style & java_awt_font_ITALIC) |
| pango_font_description_set_style (pfont->desc, PANGO_STYLE_ITALIC); |
| |
| pango_font_description_set_size (pfont->desc, size * PANGO_SCALE); |
| if (pfont->ctx == NULL) |
| { |
| ft2_map = PANGO_FT2_FONT_MAP(pango_ft2_font_map_for_display ()); |
| pfont->ctx = pango_ft2_font_map_create_context (ft2_map); |
| } |
| |
| g_assert (pfont->ctx != NULL); |
| |
| if (pfont->font != NULL) |
| { |
| g_object_unref (pfont->font); |
| pfont->font = NULL; |
| } |
| |
| pango_context_set_font_description (pfont->ctx, pfont->desc); |
| pango_context_set_language (pfont->ctx, gtk_get_default_language()); |
| pfont->font = pango_context_load_font (pfont->ctx, pfont->desc); |
| g_assert (pfont->font != NULL); |
| |
| if (pfont->layout == NULL) |
| pfont->layout = pango_layout_new (pfont->ctx); |
| g_assert (pfont->layout != NULL); |
| |
| gdk_threads_leave (); |
| } |
| |
| |
| JNIEXPORT jbyteArray JNICALL |
| Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable |
| (JNIEnv *env, jobject self, jbyte n, jbyte a, jbyte m, jbyte e) |
| { |
| struct peerfont *pfont = NULL; |
| FT_Face face; |
| FT_ULong length = 0; |
| FT_ULong tag; |
| int error; |
| FT_Byte *buffer; |
| jbyteArray result_array; |
| jbyte *rbuf; |
| |
| pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); |
| if(pfont == NULL) |
| return NULL; |
| |
| gdk_threads_enter (); |
| face = pango_fc_font_lock_face ((PangoFcFont *)pfont->font); |
| tag = FT_MAKE_TAG( n, a, m, e ); |
| |
| /* Get the length of the table requested */ |
| error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); |
| if ( error ) |
| { |
| pango_fc_font_unlock_face ((PangoFcFont *)pfont->font); |
| gdk_threads_leave (); |
| return NULL; |
| } |
| |
| buffer = (FT_Byte *)g_malloc0( length ); |
| if ( buffer == NULL ) |
| { |
| pango_fc_font_unlock_face ((PangoFcFont *)pfont->font); |
| gdk_threads_leave (); |
| return NULL; |
| } |
| /* get the table data */ |
| error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); |
| if ( error ) |
| { |
| pango_fc_font_unlock_face ((PangoFcFont *)pfont->font); |
| g_free(buffer); |
| gdk_threads_leave (); |
| return NULL; |
| } |
| |
| /* copy to a jbytearray */ |
| result_array = (*env)->NewByteArray (env, length); |
| |
| rbuf = (*env)->GetByteArrayElements (env, result_array, NULL); |
| memcpy(rbuf, buffer, length); |
| (*env)->ReleaseByteArrayElements (env, result_array, rbuf, 0); |
| |
| g_free(buffer); |
| pango_fc_font_unlock_face ((PangoFcFont *)pfont->font); |
| gdk_threads_leave (); |
| |
| /* done */ |
| return result_array; |
| } |