static PangoGlyph pango_font_get_glyph(PangoFont* font, PangoContext* context, gunichar wc) { PangoGlyph result = 0; gchar buffer[7]; gint length = g_unichar_to_utf8(wc, buffer); g_return_val_if_fail(length, 0); GList* items = pango_itemize(context, buffer, 0, length, NULL, NULL); if (g_list_length(items) == 1) { PangoItem* item = reinterpret_cast<PangoItem*>(items->data); PangoFont* tmpFont = item->analysis.font; item->analysis.font = font; PangoGlyphString* glyphs = pango_glyph_string_new(); pango_shape(buffer, length, &item->analysis, glyphs); item->analysis.font = tmpFont; if (glyphs->num_glyphs == 1) result = glyphs->glyphs[0].glyph; else g_warning("didn't get 1 glyph but %d", glyphs->num_glyphs); pango_glyph_string_free(glyphs); } g_list_foreach(items, (GFunc)pango_item_free, NULL); g_list_free(items); return result; }
static VALUE rpango_shape_ensure(VALUE value) { pango_glyph_string_free((PangoGlyphString *)value); return Qnil; }
/// Free upto a max of cGlyphs or upto first NULL. void FreeGlyphs(WORD *pwGlyphs, int cGlyphs) { PangoGlyphString ** glyphString = reinterpret_cast<PangoGlyphString**>(pwGlyphs); for(int i = 0 ; i < cGlyphs; ++i) { if (glyphString[i] == NULL) break; pango_glyph_string_free(glyphString[i]); } }
static VALUE rpango_shape(VALUE self, VALUE text, VALUE analysis) { VALUE ret; PangoGlyphString* glyphs = pango_glyph_string_new(); StringValue(text); pango_shape(RSTRING_PTR(text), RSTRING_LEN(text), RVAL2BOXED(analysis, PANGO_TYPE_ANALYSIS), glyphs); ret = BOXED2RVAL(glyphs, PANGO_TYPE_GLYPH_STRING); pango_glyph_string_free (glyphs); return ret; }
void _HYPlatformGraphicPane::_ResetCharGlyphs(void) { if (charCachePangoItems) { g_list_free (charCachePangoItems); charCachePangoItems = NULL; } for (long k=0; k<=60; k=k+1) if (cachedCharacterGlyphs[k]) { pango_glyph_string_free ((PangoGlyphString* )cachedCharacterGlyphs[k]); cachedCharacterGlyphs[k] = NULL; } }
GtkPaintContext::~GtkPaintContext() { if (myPixmap != 0) { gdk_pixmap_unref(myPixmap); } if (myTextGC) { gdk_gc_unref(myTextGC); gdk_gc_unref(myFillGC); } pango_glyph_string_free(myString); if (myFontDescription != 0) { pango_font_description_free(myFontDescription); } if (myContext != 0) { g_object_unref(myContext); } }
// Helper function used in the implementation of ScriptShape HRESULT PangoCharsToGlyph(SCRIPT_CACHE *psc, const char * chars, int cInChars, int cMaxItems, PangoGlyphString **pGlpyhs, int * pcItems) { ScriptCacheImplementation * cache = reinterpret_cast<ScriptCacheImplementation*>(*psc); PangoContext * pangoContext; cache->m_vwGraphics->GetTextStyleContext(reinterpret_cast<HDC*>(&pangoContext)); PangoAttrList * attributes_list = pango_attr_list_new(); GList * items = pango_itemize(pangoContext, chars, 0, cInChars, attributes_list, NULL); int length = g_list_length(items); int glyphsCount = 0; pGlpyhs[0] = NULL; for(int i = 0; i < length; ++i) { PangoItem* item = static_cast<PangoItem*>(g_list_nth_data(items, i)); PangoGlyphString * ptrPangoGlyphString = pango_glyph_string_new(); pango_shape(chars + item->offset, item->length, &item->analysis, ptrPangoGlyphString); glyphsCount += ptrPangoGlyphString->num_glyphs; if (glyphsCount > cMaxItems) { pango_glyph_string_free(ptrPangoGlyphString); FreeGlyphs(reinterpret_cast<WORD*>(pGlpyhs), cMaxItems); pango_item_free(item); pango_attr_list_unref(attributes_list); g_list_free(items); return E_OUTOFMEMORY; } pGlpyhs[i] = ptrPangoGlyphString; if (i < (cMaxItems - 1)) pGlpyhs[i + 1] = NULL; // null term the list (used for deleting etc.) pango_item_free(item); } pango_attr_list_unref(attributes_list); g_list_free(items); *pcItems = glyphsCount; return S_OK; }
void FontSupport::drawText(const WFont& font, const WRectF& rect, const WTransform& transform, Bitmap& bitmap, WFlags<AlignmentFlag> flags, const WString& text) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; PangoMatrix matrix; matrix.xx = transform.m11(); matrix.xy = transform.m21(); matrix.yx = transform.m12(); matrix.yy = transform.m22(); matrix.x0 = transform.dx(); matrix.y0 = transform.dy(); std::string utf8 = text.toUTF8(); std::vector<PangoGlyphString *> glyphs; int width; pango_context_set_matrix(context_, &matrix); /* * Oh my god, somebody explain me why we need to do this... */ WFont f = font; f.setSize(font.sizeLength().toPixels() / pango_matrix_get_font_scale_factor(&matrix)); GList *items = layoutText(f, utf8, glyphs, width); pango_context_set_matrix(context_, nullptr); AlignmentFlag hAlign = flags & AlignHorizontalMask; /* FIXME handle bidi ! */ double x; switch (hAlign) { case AlignmentFlag::Left: x = rect.left(); break; case AlignmentFlag::Right: x = rect.right() - pangoUnitsToDouble(width); break; case AlignmentFlag::Center: x = rect.center().x() - pangoUnitsToDouble(width/2); break; default: x = 0; } AlignmentFlag vAlign = flags & AlignVerticalMask; PangoFont *pangoFont = matchFont(font).pangoFont(); PangoFontMetrics *metrics = pango_font_get_metrics(pangoFont, nullptr); double ascent = pangoUnitsToDouble(pango_font_metrics_get_ascent(metrics)); double descent = pangoUnitsToDouble(pango_font_metrics_get_descent(metrics)); pango_font_metrics_unref(metrics); double baseline = ascent; double height = ascent + descent; double y; switch (vAlign) { case AlignmentFlag::Top: y = rect.top() + baseline; break; case AlignmentFlag::Middle: y = rect.center().y() - height / 2 + baseline; break; case AlignmentFlag::Bottom: y = rect.bottom() - height + baseline; break; default: y = 0; } FT_Bitmap bmp; bmp.buffer = bitmap.buffer(); bmp.width = bitmap.width(); bmp.rows = bitmap.height(); bmp.pitch = bitmap.pitch(); bmp.pixel_mode = FT_PIXEL_MODE_GRAY; bmp.num_grays = 16; // ??? GList *elem; unsigned i = 0; for (elem = items; elem; elem = elem->next) { PangoItem *item = (PangoItem *)elem->data; PangoAnalysis *analysis = &item->analysis; PangoGlyphString *gl = glyphs[i++]; pango_ft2_render_transformed(&bmp, &matrix, analysis->font, gl, pangoUnitsFromDouble(x), pangoUnitsFromDouble(y)); x += pangoUnitsToDouble(pango_glyph_string_get_width(gl)); pango_glyph_string_free(gl); pango_item_free(item); } g_list_free(items); }
WTextItem FontSupport::measureText(const WFont& font, const WString& text, double maxWidth, bool wordWrap) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; /* * Note: accurate measuring on a bitmap requires that the transformation * is applied, because hinting may push chars to boundaries e.g. when * rotated (or scaled too?) */ std::string utf8 = text.toUTF8(); const char *s = utf8.c_str(); if (wordWrap) { int utflen = g_utf8_strlen(s, -1); PangoLogAttr *attrs = new PangoLogAttr[utflen + 1]; PangoLanguage *language = pango_language_from_string("en-US"); pango_get_log_attrs(s, utf8.length(), -1, language, attrs, utflen + 1); double w = 0, nextW = -1; int current = 0; int measured = 0; int end = 0; bool maxWidthReached = false; for (int i = 0; i < utflen + 1; ++i) { if (i == utflen || attrs[i].is_line_break) { int cend = g_utf8_offset_to_pointer(s, end) - s; WTextItem ti = measureText(font, WString::fromUTF8(utf8.substr(measured, cend - measured)), -1, false); if (isEpsilonMore(w + ti.width(), maxWidth)) { nextW = ti.width(); maxWidthReached = true; break; } else { measured = cend; current = g_utf8_offset_to_pointer(s, i) - s; w += ti.width(); if (i == utflen) { w += measureText(font, WString::fromUTF8(utf8.substr(measured)), -1, false).width(); measured = utf8.length(); } } } if (!attrs[i].is_white) end = i + 1; } delete[] attrs; if (maxWidthReached) { return WTextItem(WString::fromUTF8(utf8.substr(0, current)), w, nextW); } else { /* * For some reason, the sum of the individual widths is a bit less * (for longer stretches of text), so we re-measure it ! */ w = measureText(font, WString::fromUTF8(utf8.substr(0, measured)), -1, false).width(); return WTextItem(text, w); } } else { std::vector<PangoGlyphString *> glyphs; int width; GList *items = layoutText(font, utf8, glyphs, width); double w = pangoUnitsToDouble(width); for (unsigned i = 0; i < glyphs.size(); ++i) pango_glyph_string_free(glyphs[i]); g_list_foreach(items, (GFunc) pango_item_free, nullptr); g_list_free(items); return WTextItem(text, w); } }
void FontSupport::drawText(const WFont& font, const WRectF& rect, WFlags<AlignmentFlag> flags, const WString& text) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; std::string utf8 = text.toUTF8(); std::vector<PangoGlyphString *> glyphs; int width; GList *items = layoutText(font, utf8, glyphs, width); AlignmentFlag hAlign = flags & AlignHorizontalMask; AlignmentFlag vAlign = flags & AlignVerticalMask; /* FIXME handle bidi ! */ double x; switch (hAlign) { case AlignmentFlag::Left: x = rect.left(); break; case AlignmentFlag::Right: x = rect.right() - pangoUnitsToDouble(width); break; case AlignmentFlag::Center: x = rect.center().x() - pangoUnitsToDouble(width/2); break; default: x = 0; } unsigned i = 0; for (GList *elem = items; elem; elem = elem->next) { PangoItem *item = (PangoItem *)elem->data; PangoAnalysis *analysis = &item->analysis; PangoGlyphString *gl = glyphs[i++]; currentFont_ = analysis->font; /* * Note, we are actually ignoring the selected glyphs here, which * is a pitty and possibly wrong if the device does not make the * same selection ! */ WString s = WString::fromUTF8(utf8.substr(item->offset, item->length)); device_->drawText(WRectF(x, rect.y(), 1000, rect.height()), AlignmentFlag::Left | vAlign, TextFlag::SingleLine, s, nullptr); WTextItem textItem = device_->measureText(s, -1, false); x += textItem.width(); pango_item_free(item); pango_glyph_string_free(gl); } g_list_free(items); currentFont_ = nullptr; }
JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector (JNIEnv *env, jobject self, jstring chars, jobject font, jobject fontRenderContext) { struct peerfont *pfont = NULL; GList *items = NULL, *i = NULL; gchar *str = NULL; int len, j; double *native_extents; int *native_codes; jintArray java_codes = NULL; jdoubleArray java_extents = NULL; gdk_threads_enter (); pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); g_assert (pfont != NULL); len = (*gdk_env())->GetStringUTFLength (env, chars); str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL); g_assert (str != NULL); if (attrs == NULL) attrs = pango_attr_list_new (); if (len > 0 && str[len-1] == '\0') len--; items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL); i = g_list_first (items); if (i == NULL) { java_extents = (*env)->NewDoubleArray (env, 0); java_codes = (*env)->NewIntArray (env, 0); } else { PangoGlyphString *glyphs; PangoItem *item = (PangoItem *)i->data; pango_context_set_font_description (pfont->ctx, pfont->desc); pango_context_set_language (pfont->ctx, gtk_get_default_language()); pango_context_load_font (pfont->ctx, pfont->desc); glyphs = pango_glyph_string_new (); g_assert (glyphs != NULL); pango_shape (str + item->offset, item->length, &(item->analysis), glyphs); if (glyphs->num_glyphs > 0) { int x = 0; double scale = ((double) PANGO_SCALE); java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS); java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs); native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL); native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); for (j = 0; j < glyphs->num_glyphs; ++j) { PangoRectangle ink; PangoRectangle logical; PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry; pango_font_get_glyph_extents (pfont->font, glyphs->glyphs[j].glyph, &ink, &logical); native_codes[j] = glyphs->glyphs[j].glyph; native_extents[ GLYPH_LOG_X(j) ] = (logical.x) / scale; native_extents[ GLYPH_LOG_Y(j) ] = (- logical.y) / scale; native_extents[ GLYPH_LOG_WIDTH(j) ] = (logical.width) / scale; native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale; native_extents[ GLYPH_INK_X(j) ] = (ink.x) / scale; native_extents[ GLYPH_INK_Y(j) ] = (- ink.y) / scale; native_extents[ GLYPH_INK_WIDTH(j) ] = (ink.width) / scale; native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height) / scale; native_extents[ GLYPH_POS_X(j) ] = (x + geom->x_offset) / scale; native_extents[ GLYPH_POS_Y(j) ] = ( - geom->y_offset) / scale; x += geom->width; } (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0); (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); } pango_glyph_string_free (glyphs); } (*env)->ReleaseStringUTFChars (env, chars, str); for (i = g_list_first (items); i != NULL; i = g_list_next (i)) g_free (i->data); g_list_free (items); gdk_threads_leave (); return (*env)->NewObject (env, glyphVector_class, glyphVector_ctor, java_extents, java_codes, font, fontRenderContext); }