gnu_java_awt_peer_gtk_GdkGlyphVector.c [plain text]
#include "gdkfont.h"
#include "gnu_java_awt_peer_gtk_GdkGlyphVector.h"
struct state_table *native_glyphvector_state_table;
typedef struct {
double x;
double y;
double width;
double height;
} rect_t;
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initStaticState
(JNIEnv *env, jclass clazz)
{
NSA_GV_INIT (env, clazz);
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initState
(JNIEnv *env, jobject self, jobject font, jobject ctx)
{
struct glyphvec *vec = NULL;
struct peerfont *pfont = NULL;
gdk_threads_enter ();
g_assert (font != NULL);
pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
g_assert (pfont != NULL);
g_assert (pfont->ctx != NULL);
g_assert (pfont->desc != NULL);
g_assert (self != NULL);
vec = (struct glyphvec *) g_malloc0 (sizeof (struct glyphvec));
g_assert (vec != NULL);
vec->desc = pango_font_describe (pfont->font);
g_assert (vec->desc != NULL);
vec->font = pfont->font;
g_object_ref (vec->font);
vec->ctx = pfont->ctx;
g_object_ref (vec->ctx);
NSA_SET_GV_PTR (env, self, vec);
gdk_threads_leave ();
}
static void free_glyphitems (GList *list)
{
GList *i = NULL;
PangoGlyphItem *gi = NULL;
for (i = g_list_first (list); i != NULL; i = g_list_next (i))
{
g_assert (i->data != NULL);
gi = (PangoGlyphItem *)i->data;
if (gi->glyphs != NULL)
pango_glyph_string_free (gi->glyphs);
if (gi->item != NULL)
g_free (gi->item);
}
g_list_free (list);
}
static void seek_glyphstring_idx (GList *list, int idx,
int *nidx,
PangoGlyphString **gs,
PangoFont **fnt)
{
GList *i = NULL;
PangoGlyphItem *gi = NULL;
g_assert (list != NULL);
g_assert (gs != NULL);
g_assert (nidx != NULL);
int begin = 0;
for (i = g_list_first (list); i != NULL; i = g_list_next (i))
{
g_assert (i->data != NULL);
gi = (PangoGlyphItem *)i->data;
g_assert (gi->glyphs != NULL);
if (begin <= idx && idx < begin + gi->glyphs->num_glyphs)
{
*gs = gi->glyphs;
*nidx = idx - begin;
if (fnt && gi->item)
*fnt = gi->item->analysis.font;
return;
}
else
{
begin += gi->glyphs->num_glyphs;
}
}
*gs = NULL;
*nidx = -1;
}
static void seek_glyph_idx (GList *list, int idx,
PangoGlyphInfo **g,
PangoFont **fnt)
{
PangoGlyphString *gs = NULL;
int nidx = -1;
g_assert (list != NULL);
g_assert (g != NULL);
seek_glyphstring_idx (list, idx, &nidx, &gs, fnt);
g_assert (gs != NULL);
g_assert (nidx != -1);
g_assert (nidx < gs->num_glyphs);
g_assert (gs->glyphs != NULL);
*g = gs->glyphs + nidx;
}
static void union_rects (rect_t *r1,
const rect_t *r2)
{
rect_t r;
g_assert (r1 != NULL);
g_assert (r2 != NULL);
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) < (y) ? (y) : (x))
#endif
r.x = min(r1->x, r2->x);
r.y = min(r1->y, r2->y);
r.width = max(r1->x + r1->width,
r2->x + r2->width) - r.x;
r.height = max(r1->y + r1->height,
r2->y + r2->height) - r.y;
*r1 = r;
}
static jdoubleArray rect_to_array (JNIEnv *env, const rect_t *r)
{
jdoubleArray ret;
double *rp = NULL;
g_assert (r != NULL);
ret = (*env)->NewDoubleArray (env, 4);
rp = (*env)->GetDoubleArrayElements (env, ret, NULL);
g_assert (rp != NULL);
rp[0] = r->x;
rp[1] = r->y * -1;
rp[2] = r->width;
rp[3] = r->height;
(*env)->ReleaseDoubleArrayElements (env, ret, rp, 0);
return ret;
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_dispose
(JNIEnv *env, jobject self)
{
struct glyphvec *vec = NULL;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_DEL_GV_PTR (env, self);
g_assert (vec != NULL);
if (vec->glyphitems != NULL)
{
free_glyphitems (vec->glyphitems);
vec->glyphitems = NULL;
}
if (vec->desc != NULL)
pango_font_description_free (vec->desc);
if (vec->ctx != NULL)
g_object_unref (vec->ctx);
g_free (vec);
gdk_threads_leave ();
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setChars
(JNIEnv *env, jobject self, jstring chars)
{
struct glyphvec *vec = NULL;
gchar *str = NULL;
GList *items = NULL, *item = NULL;
PangoGlyphItem *gi;
PangoAttrList *attrs = NULL;
gint len = 0;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->desc != NULL);
g_assert (vec->ctx != NULL);
len = (*gdk_env)->GetStringUTFLength (env, chars);
str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL);
g_assert (str != NULL);
attrs = pango_attr_list_new ();
g_assert (attrs != NULL);
pango_context_set_font_description (vec->ctx, vec->desc);
items = pango_itemize (vec->ctx, str, 0, len, attrs, NULL);
g_assert (items != NULL);
if (vec->glyphitems != NULL)
{
free_glyphitems (vec->glyphitems);
vec->glyphitems = NULL;
}
for (item = g_list_first (items); item != NULL; item = g_list_next (item))
{
g_assert (item->data != NULL);
gi = NULL;
gi = g_malloc0 (sizeof(PangoGlyphItem));
g_assert (gi != NULL);
gi->item = (PangoItem *)item->data;
gi->glyphs = pango_glyph_string_new ();
g_assert (gi->glyphs != NULL);
pango_shape (str + gi->item->offset,
gi->item->length,
&(gi->item->analysis),
gi->glyphs);
vec->glyphitems = g_list_append (vec->glyphitems, gi);
}
g_list_free (items);
pango_attr_list_unref (attrs);
(*env)->ReleaseStringUTFChars (env, chars, str);
gdk_threads_leave ();
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setGlyphCodes
(JNIEnv *env, jobject self, jintArray codes)
{
struct glyphvec *vec = NULL;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
gdk_threads_leave ();
}
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCode
(JNIEnv *env, jobject self, jint idx)
{
struct glyphvec *vec = NULL;
PangoGlyphInfo *gi = NULL;
jint ret = 0;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->glyphitems != NULL);
seek_glyph_idx (vec->glyphitems, idx, &gi, NULL);
g_assert (gi != NULL);
ret = gi->glyph;
gdk_threads_leave ();
return (jint)(ret);
}
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_numGlyphs
(JNIEnv *env, jobject self)
{
GList *i = NULL;
PangoGlyphItem *gi = NULL;
struct glyphvec *vec = NULL;
jint count = 0;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
{
g_assert (i->data != NULL);
gi = (PangoGlyphItem *)i->data;
g_assert (gi->glyphs != NULL);
count += gi->glyphs->num_glyphs;
}
gdk_threads_leave ();
return count;
}
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCharIndex
(JNIEnv *env, jobject self, jint idx)
{
return idx;
}
static void
assume_pointsize_and_identity_transform(double pointsize,
FT_Face face)
{
FT_Matrix mat;
mat.xx = DOUBLE_TO_16_16(1);
mat.xy = DOUBLE_TO_16_16(0);
mat.yx = DOUBLE_TO_16_16(0);
mat.yy = DOUBLE_TO_16_16(1);
FT_Set_Transform(face, &mat, NULL);
FT_Set_Char_Size( face,
DOUBLE_TO_26_6 (pointsize),
DOUBLE_TO_26_6 (pointsize),
0, 0);
}
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents
(JNIEnv *env, jobject self)
{
struct glyphvec *vec = NULL;
int j;
GList *i;
PangoGlyphItem *gi = NULL;
rect_t rect = {0,0,0,0};
rect_t tmp;
jdoubleArray ret;
double x = 0, y = 0;
double pointsize;
FT_Face face;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->glyphitems != NULL);
pointsize = pango_font_description_get_size (vec->desc);
pointsize /= (double) PANGO_SCALE;
for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
{
g_assert (i->data != NULL);
gi = (PangoGlyphItem *)i->data;
g_assert (gi->glyphs != NULL);
face = pango_ft2_font_get_face (gi->item->analysis.font);
assume_pointsize_and_identity_transform (pointsize, face);
for (j = 0; j < gi->glyphs->num_glyphs; ++j)
{
FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
tmp.x = x + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
tmp.y = y + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
tmp.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
tmp.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
union_rects (&rect, &tmp);
x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
}
}
ret = rect_to_array (env, &rect);
gdk_threads_leave ();
return ret;
}
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents
(JNIEnv *env, jobject self)
{
struct glyphvec *vec = NULL;
int j;
GList *i;
PangoGlyphItem *gi = NULL;
rect_t rect = {0,0,0,0};
rect_t tmp;
jdoubleArray ret;
double x = 0, y = 0;
double pointsize;
FT_Face face;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->glyphitems != NULL);
pointsize = pango_font_description_get_size (vec->desc);
pointsize /= (double) PANGO_SCALE;
for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
{
g_assert (i->data != NULL);
gi = (PangoGlyphItem *)i->data;
g_assert (gi->glyphs != NULL);
face = pango_ft2_font_get_face (gi->item->analysis.font);
assume_pointsize_and_identity_transform (pointsize, face);
for (j = 0; j < gi->glyphs->num_glyphs; ++j)
{
FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
tmp.x = x;
tmp.y = y;
tmp.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
tmp.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
union_rects (&rect, &tmp);
x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
}
}
ret = rect_to_array (env, &rect);
gdk_threads_leave ();
return ret;
}
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphLogicalExtents
(JNIEnv *env, jobject self, jint idx)
{
struct glyphvec *vec = NULL;
rect_t rect = {0,0,0,0};
PangoGlyphInfo *gi = NULL;
PangoFont *font = NULL;
jdoubleArray ret;
double pointsize;
FT_Face face;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->glyphitems != NULL);
seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
g_assert (gi != NULL);
g_assert (font != NULL);
pointsize = pango_font_description_get_size (vec->desc);
pointsize /= (double) PANGO_SCALE;
face = pango_ft2_font_get_face (font);
assume_pointsize_and_identity_transform (pointsize, face);
FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
rect.x = 0;
rect.y = 0;
rect.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
rect.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
ret = rect_to_array (env, &rect);
gdk_threads_leave ();
return ret;
}
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphInkExtents
(JNIEnv *env, jobject self, jint idx)
{
struct glyphvec *vec = NULL;
rect_t rect = {0,0,0,0};
PangoGlyphInfo *gi = NULL;
PangoFont *font = NULL;
jdoubleArray ret;
double pointsize;
FT_Face face;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->glyphitems != NULL);
seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
g_assert (gi != NULL);
g_assert (font != NULL);
pointsize = pango_font_description_get_size (vec->desc);
pointsize /= (double) PANGO_SCALE;
face = pango_ft2_font_get_face (font);
assume_pointsize_and_identity_transform (pointsize, face);
FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
rect.x = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
rect.y = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
rect.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
rect.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
ret = rect_to_array (env, &rect);
gdk_threads_leave ();
return ret;
}
JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHorizontal
(JNIEnv *env, jobject self, jint idx)
{
struct glyphvec *vec = NULL;
PangoDirection dir;
gdk_threads_enter ();
g_assert (self != NULL);
vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
g_assert (vec != NULL);
g_assert (vec->desc != NULL);
g_assert (vec->ctx != NULL);
dir = pango_context_get_base_dir (vec->ctx);
gdk_threads_leave ();
return 1;
}
JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_isEqual
(JNIEnv *env, jobject self, jobject other)
{
struct glyphvec *vec1 = NULL, *vec2 = NULL;
jboolean eq = 0;
gdk_threads_enter ();
g_assert (self != NULL);
vec1 = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
vec2 = (struct glyphvec *)NSA_GET_GV_PTR (env, other);
g_assert (vec1 != NULL);
g_assert (vec2 != NULL);
eq = (vec1 == vec2);
gdk_threads_leave ();
return eq;
}