bool FontPlatformData::operator==(const FontPlatformData& other) const { if (m_font == other.m_font) return true; if (m_font == 0 || m_font == reinterpret_cast<PangoFont*>(-1) || other.m_font == 0 || other.m_font == reinterpret_cast<PangoFont*>(-1)) return false; PangoFontDescription* thisDesc = pango_font_describe(m_font); PangoFontDescription* otherDesc = pango_font_describe(other.m_font); bool result = pango_font_description_equal(thisDesc, otherDesc); pango_font_description_free(otherDesc); pango_font_description_free(thisDesc); return result; }
static VALUE rg_describe(int argc, VALUE *argv, VALUE self) { VALUE desc, absolute_size; rb_scan_args(argc, argv, "01", &absolute_size); if (NIL_P(absolute_size) || ! RVAL2CBOOL(absolute_size)) { desc = PANGOFONTDESCRIPTION2RVAL(pango_font_describe(_SELF(self))); } else { #if PANGO_CHECK_VERSION(1,14,0) desc = PANGOFONTDESCRIPTION2RVAL(pango_font_describe_with_absolute_size(_SELF(self))); #else rb_warning("Pango::Font#describe(absolute) has been supported since GTK+-2.10.x. Use Pango::Font#describe() instead."); desc = PANGOFONTDESCRIPTION2RVAL(pango_font_describe(_SELF(self))); #endif } return desc; }
void text_wrapper::MakeVertical(void) { if ( glyph_length <= 0 ) return; font_factory *font_src = font_factory::Default(); // explanation: when laying out text vertically, you must keep the glyphs of a single letter together double baseY = glyph_text[0].y; double lastY = baseY; int g_st = 0, g_en = 0; int nbLetter = 0; PangoFont *curPF = NULL; font_instance *curF = NULL; do { // move to the next letter boundary g_st = g_en; do { g_en++; } while ( g_en < glyph_length && glyph_text[g_en].char_start == false ); // got a letter if ( g_st < g_en && g_en <= glyph_length ) { // we need to compute the letter's width (in case sometimes we implement the flushleft and flushright) // and the total height for this letter. for example accents usually have 0 width, so this is not // stupid double n_adv = 0; double minX = glyph_text[g_st].x, maxX = glyph_text[g_st].x; for (int i = g_st; i < g_en; i++) { if ( glyph_text[i].font != curPF ) { // font is not the same as the one of the previous glyph // so we need to update curF if ( curF ) curF->Unref(); curF = NULL; curPF = glyph_text[i].font; if ( curPF ) { PangoFontDescription *pfd = pango_font_describe(curPF); curF = font_src->Face(pfd); pango_font_description_free(pfd); } } double x = ( curF ? curF->Advance(glyph_text[i].gl, true) : 0 ); if ( x > n_adv ) n_adv = x; if ( glyph_text[i].x < minX ) minX = glyph_text[i].x; if ( glyph_text[i].x > maxX ) maxX = glyph_text[i].x; } lastY += n_adv; // and put the glyphs of this letter at their new position for (int i = g_st; i < g_en; i++) { glyph_text[i].x -= minX; glyph_text[i].y += lastY; } g_st = g_en; } nbLetter++; } while ( g_st < glyph_length ); if ( curF ) curF->Unref(); }
bool FontPlatformData::isFixedPitch() { PangoFontDescription* description = pango_font_describe(m_font); PangoFontFamily* family = reinterpret_cast<PangoFontFamily*>(g_hash_table_lookup(m_hashTable, pango_font_description_get_family(description))); ASSERT(family); if(!family) return false; pango_font_description_free(description); return pango_font_family_is_monospace(family); }
static PangoFontDescription * pango_cairo_core_text_font_describe_absolute (PangoFont *font) { PangoFontDescription *desc; PangoCairoCoreTextFont *cafont = (PangoCairoCoreTextFont *) font; desc = pango_font_describe (font); pango_font_description_set_absolute_size (desc, cafont->abs_size); return desc; }
static gchar * font_name (PangoFont *font) { PangoFontDescription *desc; gchar *name; desc = pango_font_describe (font); name = pango_font_description_to_string (desc); pango_font_description_free (desc); return name; }
const std::string ZLGtkPaintContext::realFontFamilyName(std::string &fontFamily) const { if (myContext == 0) { return fontFamily; } PangoFontDescription *description = pango_font_description_new(); pango_font_description_set_family(description, fontFamily.c_str()); pango_font_description_set_size(description, 12); PangoFont *font = pango_context_load_font(myContext, description); pango_font_description_free(description); description = pango_font_describe(font); std::string realFamily = pango_font_description_get_family(description); pango_font_description_free(description); return realFamily; }
Glib::ustring FontSubstitution::getSubstituteFontName (Glib::ustring font) { Glib::ustring out = font; PangoFontDescription *descr = pango_font_description_new(); pango_font_description_set_family(descr,font.c_str()); font_instance *res = (font_factory::Default())->Face(descr); if (res->pFont) { PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont); out = sp_font_description_get_family(nFaceDesc); } pango_font_description_free(descr); return out; }
/* static */ bool FontUtils::IsAvailableFont(const char* input_query_desc) { string query_desc(input_query_desc); if (PANGO_VERSION <= 12005) { // Strip commas and any ' Medium' substring in the name. query_desc.erase(std::remove(query_desc.begin(), query_desc.end(), ','), query_desc.end()); const string kMediumStr = " Medium"; std::size_t found = query_desc.find(kMediumStr); if (found != std::string::npos) { query_desc.erase(found, kMediumStr.length()); } } PangoFontDescription *desc = pango_font_description_from_string( query_desc.c_str()); PangoFont* selected_font = NULL; { InitFontconfig(); PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_context_new(); pango_context_set_font_map(context, font_map); { DISABLE_HEAP_LEAK_CHECK; selected_font = pango_font_map_load_font(font_map, context, desc); } g_object_unref(context); } PangoFontDescription* selected_desc = pango_font_describe(selected_font); bool equal = pango_font_description_equal(desc, selected_desc); tlog(3, "query weight = %d \t selected weight =%d\n", pango_font_description_get_weight(desc), pango_font_description_get_weight(selected_desc)); char* selected_desc_str = pango_font_description_to_string(selected_desc); tlog(2, "query_desc: '%s' Selected: 's'\n", query_desc.c_str(), selected_desc_str); g_free(selected_desc_str); pango_font_description_free(selected_desc); pango_font_description_free(desc); return equal; }
static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout) { #if USE(FREETYPE) if (font->primaryFont()->platformData().m_pattern) { PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->platformData().m_pattern.get(), FALSE); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); } #elif USE(PANGO) if (font->primaryFont()->platformData().m_font) { PangoFontDescription* desc = pango_font_describe(font->primaryFont()->platformData().m_font); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); } #endif pango_layout_set_auto_dir(layout, FALSE); PangoContext* pangoContext = pango_layout_get_context(layout); PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; pango_context_set_base_dir(pangoContext, direction); PangoAttrList* list = pango_attr_list_new(); PangoAttribute* attr; attr = pango_attr_size_new_absolute(font->pixelSize() * PANGO_SCALE); attr->end_index = G_MAXUINT; pango_attr_list_insert_before(list, attr); if (!run.spacingDisabled()) { attr = pango_attr_letter_spacing_new(font->letterSpacing() * PANGO_SCALE); attr->end_index = G_MAXUINT; pango_attr_list_insert_before(list, attr); } // Pango does not yet support synthesising small caps // See http://bugs.webkit.org/show_bug.cgi?id=15610 pango_layout_set_attributes(layout, list); pango_attr_list_unref(list); }
void text_wrapper::MeasureBoxes(void) { font_factory *f_src = font_factory::Default(); for (int i = 0; i < nbBox; i++) { boxes[i].ascent = 0; boxes[i].descent = 0; boxes[i].leading = 0; boxes[i].width = 0; PangoFont *curPF = glyph_text[boxes[i].g_st].font; if ( curPF ) { PangoFontDescription *pfd = pango_font_describe(curPF); font_instance *curF = f_src->Face(pfd); if ( curF ) { curF->FontMetrics(boxes[i].ascent, boxes[i].descent, boxes[i].leading); curF->Unref(); } pango_font_description_free(pfd); boxes[i].width = glyph_text[boxes[i].g_en].x - glyph_text[boxes[i].g_st].x; } } }
bool PangoFontInfo::CanRenderString(const char* utf8_word, int len, vector<string>* graphemes) const { if (graphemes) graphemes->clear(); // We check for font coverage of the text first, as otherwise Pango could // (undesirably) fall back to another font that does have the required // coverage. if (!CoversUTF8Text(utf8_word, len)) { return false; } // U+25CC dotted circle character that often (but not always) gets rendered // when there is an illegal grapheme sequence. const char32 kDottedCircleGlyph = 9676; bool bad_glyph = false; PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_context_new(); pango_context_set_font_map(context, font_map); PangoLayout* layout; { // Pango is not relasing the cached layout. DISABLE_HEAP_LEAK_CHECK; layout = pango_layout_new(context); } if (desc_) { pango_layout_set_font_description(layout, desc_); } else { PangoFontDescription *desc = pango_font_description_from_string( DescriptionName().c_str()); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); } pango_layout_set_text(layout, utf8_word, len); PangoLayoutIter* run_iter = NULL; { // Fontconfig caches some information here that is not freed before exit. DISABLE_HEAP_LEAK_CHECK; run_iter = pango_layout_get_iter(layout); } do { PangoLayoutRun* run = pango_layout_iter_get_run_readonly(run_iter); if (!run) { tlog(2, "Found end of line NULL run marker\n"); continue; } PangoGlyph dotted_circle_glyph; PangoFont* font = run->item->analysis.font; dotted_circle_glyph = pango_fc_font_get_glyph( reinterpret_cast<PangoFcFont*>(font), kDottedCircleGlyph); if (TLOG_IS_ON(2)) { PangoFontDescription* desc = pango_font_describe(font); char* desc_str = pango_font_description_to_string(desc); tlog(2, "Desc of font in run: %s\n", desc_str); g_free(desc_str); pango_font_description_free(desc); } PangoGlyphItemIter cluster_iter; gboolean have_cluster; for (have_cluster = pango_glyph_item_iter_init_start(&cluster_iter, run, utf8_word); have_cluster && !bad_glyph; have_cluster = pango_glyph_item_iter_next_cluster(&cluster_iter)) { const int start_byte_index = cluster_iter.start_index; const int end_byte_index = cluster_iter.end_index; int start_glyph_index = cluster_iter.start_glyph; int end_glyph_index = cluster_iter.end_glyph; string cluster_text = string(utf8_word + start_byte_index, end_byte_index - start_byte_index); if (graphemes) graphemes->push_back(cluster_text); if (IsUTF8Whitespace(cluster_text.c_str())) { tlog(2, "Skipping whitespace\n"); continue; } if (TLOG_IS_ON(2)) { printf("start_byte=%d end_byte=%d start_glyph=%d end_glyph=%d ", start_byte_index, end_byte_index, start_glyph_index, end_glyph_index); } for (int i = start_glyph_index, step = (end_glyph_index > start_glyph_index) ? 1 : -1; !bad_glyph && i != end_glyph_index; i+= step) { const bool unknown_glyph = (cluster_iter.glyph_item->glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG); const bool illegal_glyph = (cluster_iter.glyph_item->glyphs->glyphs[i].glyph == dotted_circle_glyph); bad_glyph = unknown_glyph || illegal_glyph; if (TLOG_IS_ON(2)) { printf("(%d=%d)", cluster_iter.glyph_item->glyphs->glyphs[i].glyph, bad_glyph ? 1 : 0); } } if (TLOG_IS_ON(2)) { printf(" '%s'\n", cluster_text.c_str()); } if (bad_glyph) tlog(1, "Found illegal glyph!\n"); } } while (!bad_glyph && pango_layout_iter_next_run(run_iter)); pango_layout_iter_free(run_iter); g_object_unref(context); g_object_unref(layout); if (bad_glyph && graphemes) graphemes->clear(); return !bad_glyph; }
static boolean pango_textlayout(textpara_t * para, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, para->fontname) != 0 || fontsize != para->fontsize) { fontname = para->fontname; fontsize = para->fontsize; pango_font_description_free (desc); if (para->postscript_alias) { psfnt = fnt = gv_fmap[para->postscript_alias->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (para->postscript_alias); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((para->font) && (flags = para->font->flags)) { char* markup = N_NEW(strlen(para->str) + sizeof(FULL_MARKUP), char); strcpy(markup,"<span"); if (flags & HTML_BF) strcat(markup," weight=\"bold\""); if (flags & HTML_IF) strcat(markup," style=\"italic\""); if (flags & HTML_UL) strcat(markup," underline=\"single\""); strcat (markup,">"); if (flags & HTML_SUP) strcat(markup,"<sup>"); if (flags & HTML_SUB) strcat(markup,"<sub>"); strcat (markup,para->str); if (flags & HTML_SUB) strcat(markup,"</sub>"); if (flags & HTML_SUP) strcat(markup,"</sup>"); strcat (markup,"</span>"); if (!pango_parse_markup (markup, -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = para->str; attrs = NULL; } free (markup); }
/* postscript_draw_contour() dumps out the information of a line. It shows how to access the ft font information out of the pango font info. */ void postscript_draw_contour(DiaPsRenderer *renderer, int dpi_x, PangoLayoutLine *pango_line, double line_start_pos_x, double line_start_pos_y) { GSList *runs_list; int num_runs = 0; /* First calculate number of runs in text */ runs_list = pango_line->runs; while(runs_list) { num_runs++; runs_list = runs_list->next; } /* Loop over the runs and output font info */ runs_list = pango_line->runs; while(runs_list) { PangoLayoutRun *run = runs_list->data; PangoItem *item = run->item; PangoGlyphString *glyphs = run->glyphs; PangoAnalysis *analysis = &item->analysis; PangoFont *font = analysis->font; FT_Face ft_face; int bidi_level; int num_glyphs; int glyph_idx; if (font == NULL) { fprintf(stderr, "No font found\n"); continue; } ft_face = pango_ft2_font_get_face(font); if (ft_face == NULL) { fprintf(stderr, "Failed to get face for font %s\n", pango_font_description_to_string(pango_font_describe(font))); continue; } /* printf("Got face %s (PS %s) for font %s (diafont %s)\n", ft_face->family_name, FT_Get_Postscript_Name(ft_face), pango_font_description_to_string(pango_font_describe(font)), dia_font_get_family(renderer->current_font)); */ bidi_level = item->analysis.level; num_glyphs = glyphs->num_glyphs; for (glyph_idx=0; glyph_idx<num_glyphs; glyph_idx++) { PangoGlyphGeometry geometry = glyphs->glyphs[glyph_idx].geometry; double pos_x; double pos_y; double scale = 2.54/PANGO_SCALE/dpi_x;/*72.0 / PANGO_SCALE / dpi_x;*/ pos_x = line_start_pos_x + 1.0* geometry.x_offset * scale; pos_y = line_start_pos_y - 1.0*geometry.y_offset * scale; line_start_pos_x += 1.0 * geometry.width * scale; /* printf("Drawing glyph %d: index %d at %f, %f (w %d)\n", glyph_idx, glyphs->glyphs[glyph_idx].glyph, pos_x, pos_y, geometry.width); */ draw_bezier_outline(renderer, dpi_x, ft_face, (FT_UInt)(glyphs->glyphs[glyph_idx].glyph), pos_x, pos_y ); } runs_list = runs_list->next; } }
bool TextAsset::load() { // Set up a temporary Cairo surface/context for text measurement cairo_surface_t* probeSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); if (cairo_surface_status(probeSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* probeContext = cairo_create(probeSurface); if (cairo_status(probeContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Text rectangle drawn within border const int idealWidth = _maxSize.width - _marginLeft - _marginRight; const Size textRegion(idealWidth, _maxSize.height - _marginTop - _marginBottom); const float fontSize = primaryFontSize(probeContext, textRegion); const std::string fontDesc = _fontName + " " + boost::lexical_cast<std::string>(fontSize); PangoFontDescription* fontDescription = pango_font_description_from_string(fontDesc.c_str()); const std::string req_desc_str(pango_font_description_to_string(fontDescription)); PangoFontMap* fontMap = pango_cairo_font_map_new_for_font_type(CAIRO_FONT_TYPE_FT); PangoContext* pango_context = pango_font_map_create_context(fontMap); // TODO: Does this need to be freed or does the context take it with it? PangoFont* pangoFont = pango_font_map_load_font(fontMap, pango_context, fontDescription); PangoFontDescription* reverseDescription = pango_font_describe(pangoFont); const std::string match_desc_str(pango_font_description_to_string(reverseDescription)); pango_font_description_free(reverseDescription); g_object_unref(pango_context); if (req_desc_str.find(match_desc_str) == std::string::npos) { fprintf(stderr, "Warning: Unable to correctly match font \"%s\", using " "\"%s\" instead.\n", req_desc_str.c_str(), match_desc_str.c_str()); } float shadowXOffset = 0; float shadowYOffset = 0; if (_dropShadow) { shadowXOffset = _dropShadowOffset.x() * CLIENT_TO_SERVER_SCALE * fontSize; shadowYOffset = _dropShadowOffset.y() * CLIENT_TO_SERVER_SCALE * fontSize; } Rect tight; const Size textSize = computeSizeOfText(probeContext, _textContent, idealWidth, fontDescription, &tight); const Size imageSize = imageSizeForTextSize(tight.size, shadowXOffset, shadowYOffset); // Tear down scratch contexts cairo_destroy(probeContext); cairo_surface_destroy(probeSurface); const int width = imageSize.width; const int height = imageSize.height; // Configure the actual Cairo drawing surface/context now that we know the final resolution cairo_surface_t* cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* cairoContext = cairo_create(cairoSurface); // Flip the context like in the iOS version. // This fixes flipped filters associated with text assets. cairo_translate(cairoContext, 0.0, height); cairo_scale(cairoContext, 1.0, -1.0); if (cairo_status(cairoContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Fill the box with the background color cairo_save(cairoContext); cairo_set_operator(cairoContext, CAIRO_OPERATOR_SOURCE); const mf::Color& bgColor(_style->getBackgroundColor()); cairo_set_source_rgba(cairoContext, bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha); if (_shape == 0) { if (_cornerWidth > 0 && _cornerHeight > 0) { // TODO: Support independent corner width and height drawRoundedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _cornerWidth); } else { cairo_paint(cairoContext); if (_strokeThickness > 0.0f) { drawStrokedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } } } else if (_shape == 1) { strokeFillBezier(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } cairo_restore(cairoContext); const Rect textRect = textRectForTextSize(textSize, imageSize, tight); if (_dropShadow) { const Rect shadowRect(textRect.x + shadowXOffset, textRect.y + shadowYOffset, textRect.size.width, textRect.size.height); cairo_set_source_rgba(cairoContext, _dropShadowColor.red, _dropShadowColor.green, _dropShadowColor.blue, _dropShadowColor.alpha); drawText(cairoContext, _textContent, shadowRect, fontDescription, false); } cairo_set_source_rgba(cairoContext, _textColor.red, _textColor.green, _textColor.blue, _textColor.alpha); if (_textColor.alpha > 0.0) { drawText(cairoContext, _textContent, textRect, fontDescription, true); } // DEBUG: Dump rendered text to an image // cairo_surface_write_to_png(cairoSurface, "text.png"); // Transfer Cairo surface to OpenGL texture GLubyte* imageData = static_cast<GLubyte *>(cairo_image_surface_get_data(cairoSurface)); glGenTextures(1, &_texture.textureID); glBindTexture(GL_TEXTURE_2D, _texture.textureID); _texture.width = width; _texture.height = height; _texture.s = 1.0; _texture.t = 1.0; _texture.aspect = static_cast<GLfloat>(_texture.width) / _texture.height; _texture.flipImage = true; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_BGRA // Allocate and transfer data into texture (allow OpenGL swizzling) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData); #else // Cairo uses a BGRA layout, OpenGL ES 2.0 does not support GL_BGRA as a // source format so manually perform swizzling. for (size_t i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) { std::swap(imageData[i], imageData[i + 2]); } // Allocate and transfer data into texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); #endif // Clean up pango_font_description_free(fontDescription); cairo_destroy(cairoContext); cairo_surface_destroy(cairoSurface); g_object_unref(pangoFont); _loading = false; _loaded = !_loading && !_error; return true; }
cairo_scaled_font_t * _pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv) { cairo_font_face_t *font_face; if (G_LIKELY (cf_priv->scaled_font)) return cf_priv->scaled_font; /* need to create it */ if (G_UNLIKELY (cf_priv->data == NULL)) { /* we have tried to create and failed before */ return NULL; } font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont); if (G_UNLIKELY (font_face == NULL)) goto done; cf_priv->scaled_font = cairo_scaled_font_create (font_face, &cf_priv->data->font_matrix, &cf_priv->data->ctm, cf_priv->data->options); cairo_font_face_destroy (font_face); done: if (G_UNLIKELY (cf_priv->scaled_font == NULL || cairo_scaled_font_status (cf_priv->scaled_font) != CAIRO_STATUS_SUCCESS)) { cairo_scaled_font_t *scaled_font = cf_priv->scaled_font; PangoFont *font = PANGO_FONT (cf_priv->cfont); static GQuark warned_quark = 0; if (!warned_quark) warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned"); if (!g_object_get_qdata (G_OBJECT (font), warned_quark)) { PangoFontDescription *desc; char *s; desc = pango_font_describe (font); s = pango_font_description_to_string (desc); pango_font_description_free (desc); g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'", font_face ? "scaled font" : "font face", s); if (!font_face) g_warning ("font_face is NULL"); else g_warning ("font_face status is: %s", cairo_status_to_string (cairo_font_face_status (font_face))); if (!scaled_font) g_warning ("scaled_font is NULL"); else g_warning ("scaled_font status is: %s", cairo_status_to_string (cairo_scaled_font_status (scaled_font))); g_free (s); g_object_set_qdata_full (G_OBJECT (font), warned_quark, GINT_TO_POINTER (1), NULL); } } _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data); cf_priv->data = NULL; return cf_priv->scaled_font; }
void doDrawGlyphs(PangoRenderer* renderer, PangoFont* font, PangoGlyphString* glyphs, int px, int py) { Renderer* ren = RENDERER(renderer); if (!ren->m_runs) return; std::vector<ViewdoTextRun>& runs = *(ren->m_runs); const float s = ren->m_scale; PangoColor* fg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_FOREGROUND); //PangoColor* bg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_BACKGROUND); float red = !fg ? 0.0f : fg->red / 65536.0f; float green = !fg ? 0.0f : fg->green / 65536.0f; float blue = !fg ? 0.0f : fg->blue / 65536.0f; PangoFontDescription* desc = pango_font_describe(font); unsigned int fontHash = pango_font_description_hash(desc); pango_font_description_free(desc); FT_Face face = pango_fc_font_lock_face((PangoFcFont*) font); PangoGlyphUnit layoutX = px; PangoGlyphUnit layoutY = py; ViewdoGlyphCache& cache = ViewdoGlyphCache::instance(); for (int i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo* gi = glyphs->glyphs + i; if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) { // XXX: Draw the fallback square. continue; } unsigned int glyph = gi->glyph; PangoRectangle r; pango_font_get_glyph_extents(font, glyph, &r, 0); pango_extents_to_pixels(&r, 0); float w = r.width; float h = r.height; if (w <= 0.f && h <= 0.f) { // Space. layoutX += gi->geometry.width; continue; } // Load and render the glyph. We probably need to just tell the font to cache it // and then grab the coordinates of it. const ViewdoGlyph& cachedGlyph = cache.findOrCreate(gi->glyph, fontHash, face); // Walk our existing runs and try to find one with the same color and page. // XXX: Fastpath try and use the run from the last glyph. ViewdoTextRun* run = nullptr; for (auto i = runs.begin(); i != runs.end(); i++) { if (i->m_page == cachedGlyph.m_page && i->m_red == red && i->m_green == green && i->m_blue == blue) { run = &(*i); break; } } if (!run) { runs.push_back(ViewdoTextRun(cachedGlyph.m_page, red, green, blue)); run = &(runs[runs.size() - 1]); } float x = PANGO_PIXELS(layoutX + gi->geometry.x_offset) + cachedGlyph.m_offsetLeft; float y = PANGO_PIXELS(layoutY + gi->geometry.y_offset) - cachedGlyph.m_offsetTop; // Append ourselves onto this run. addPoint(run->m_geometry, x, y, cachedGlyph.m_x0, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); // Triangle 2. addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y + cachedGlyph.m_height, cachedGlyph.m_x1, cachedGlyph.m_y1, s); layoutX += gi->geometry.width; } pango_fc_font_unlock_face((PangoFcFont*) font); }
/** * pango_shape: * @text: the text to process * @length: the length (in bytes) of @text * @analysis: #PangoAnalysis structure from pango_itemize() * @glyphs: glyph string in which to store results * * Given a segment of text and the corresponding * #PangoAnalysis structure returned from pango_itemize(), * convert the characters into glyphs. You may also pass * in only a substring of the item from pango_itemize(). */ void pango_shape (const gchar *text, gint length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { int i; int last_cluster; glyphs->num_glyphs = 0; if (G_LIKELY (analysis->shape_engine && analysis->font)) { _pango_engine_shape_shape (analysis->shape_engine, analysis->font, text, length, analysis, glyphs); if (G_UNLIKELY (glyphs->num_glyphs == 0)) { /* If a font has been correctly chosen, but no glyphs are output, * there's probably something wrong with the shaper, or the font. * * Trying to be informative, we print out the font description, * shaper name, and the text, but to not flood the terminal with * zillions of the message, we set a flag to only err once per * font/engine pair. * * To do the flag fast, we use the engine qname to qflag the font, * but also the font description to flag the engine. This is * supposed to be fast to check, but also avoid writing out * duplicate warnings when a new PangoFont is created. */ GType engine_type = G_OBJECT_TYPE (analysis->shape_engine); GQuark warned_quark = g_type_qname (engine_type); if (!g_object_get_qdata (G_OBJECT (analysis->font), warned_quark)) { PangoFontDescription *desc; char *font_name; const char *engine_name; desc = pango_font_describe (analysis->font); font_name = pango_font_description_to_string (desc); pango_font_description_free (desc); if (!g_object_get_data (G_OBJECT (analysis->shape_engine), font_name)) { engine_name = g_type_name (engine_type); if (!engine_name) engine_name = "(unknown)"; g_warning ("shaping failure, expect ugly output. shape-engine='%s', font='%s', text='%.*s'", engine_name, font_name, length == -1 ? (gint) strlen (text) : length, text); g_object_set_data_full (G_OBJECT (analysis->shape_engine), font_name, GINT_TO_POINTER (1), NULL); } g_free (font_name); g_object_set_qdata_full (G_OBJECT (analysis->font), warned_quark, GINT_TO_POINTER (1), NULL); } } } else glyphs->num_glyphs = 0; if (!glyphs->num_glyphs) { PangoEngineShape *fallback_engine = _pango_get_fallback_shaper (); _pango_engine_shape_shape (fallback_engine, analysis->font, text, length, analysis, glyphs); } /* make sure last_cluster is invalid */ last_cluster = glyphs->log_clusters[0] - 1; for (i = 0; i < glyphs->num_glyphs; i++) { /* Set glyphs[i].attr.is_cluster_start based on log_clusters[] */ if (glyphs->log_clusters[i] != last_cluster) { glyphs->glyphs[i].attr.is_cluster_start = TRUE; last_cluster = glyphs->log_clusters[i]; } else glyphs->glyphs[i].attr.is_cluster_start = FALSE; /* Shift glyph if width is negative, and negate width. * This is useful for rotated font matrices and shouldn't * harm in normal cases. */ if (glyphs->glyphs[i].geometry.width < 0) { glyphs->glyphs[i].geometry.width = -glyphs->glyphs[i].geometry.width; glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width; } } }
static boolean pango_textlayout(textspan_t * span, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; PostscriptAlias *pA; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); #ifdef HAVE_PANGO_FONT_MAP_CREATE_CONTEXT context = pango_font_map_create_context (fontmap); #else context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); #endif options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, span->font->name) != 0 || fontsize != span->font->size) { fontname = span->font->name; fontsize = span->font->size; pango_font_description_free (desc); pA = span->font->postscript_alias; if (pA) { psfnt = fnt = gv_fmap[pA->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (pA); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((span->font) && (flags = span->font->flags)) { unsigned char buf[BUFSIZ]; agxbuf xb; agxbinit(&xb, BUFSIZ, buf); agxbput(&xb,"<span"); if (flags & HTML_BF) agxbput(&xb," weight=\"bold\""); if (flags & HTML_IF) agxbput(&xb," style=\"italic\""); if (flags & HTML_UL) agxbput(&xb," underline=\"single\""); if (flags & HTML_S) agxbput(&xb," strikethrough=\"true\""); agxbput (&xb,">"); if (flags & HTML_SUP) agxbput(&xb,"<sup>"); if (flags & HTML_SUB) agxbput(&xb,"<sub>"); agxbput (&xb,xml_string0(span->str, TRUE)); if (flags & HTML_SUB) agxbput(&xb,"</sub>"); if (flags & HTML_SUP) agxbput(&xb,"</sup>"); agxbput (&xb,"</span>"); if (!pango_parse_markup (agxbuse(&xb), -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = span->str; attrs = NULL; } agxbfree (&xb); } else { text = span->str; attrs = NULL; } #else text = span->str; #endif layout = pango_layout_new (context); span->layout = (void *)layout; /* layout free with textspan - see labels.c */ span->free_layout = pango_free_layout; /* function for freeing pango layout */ pango_layout_set_text (layout, text, -1); pango_layout_set_font_description (layout, desc); #ifdef ENABLE_PANGO_MARKUP if (attrs) pango_layout_set_attributes (layout, attrs); #endif pango_layout_get_extents (layout, NULL, &logical_rect); /* if pango doesn't like the font then it sets width=0 but height = garbage */ if (logical_rect.width == 0) logical_rect.height = 0; textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE); span->size.x = (int)(logical_rect.width * textlayout_scale + 1); /* round up so that width/height are never too small */ span->size.y = (int)(logical_rect.height * textlayout_scale + 1); /* FIXME -- Horrible kluge !!! */ /* For now we are using pango for single line blocks only. * The logical_rect.height seems to be too high from the font metrics on some platforms. * Use an assumed height based on the point size. */ span->size.y = (int)(span->font->size * 1.1 + .5); /* The y offset from baseline to 0,0 of the bitmap representation */ #if !defined(WIN32) && defined PANGO_VERSION_MAJOR && (PANGO_VERSION_MAJOR >= 1) span->yoffset_layout = pango_layout_get_baseline (layout) * textlayout_scale; #else { /* do it the hard way on rhel5/centos5 */ PangoLayoutIter *iter = pango_layout_get_iter (layout); span->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale; } #endif /* The distance below midline for y centering of text strings */ span->yoffset_centerline = 0.2 * span->font->size; if (logical_rect.width == 0) return FALSE; return TRUE; }