FontSupport::FontMatch FontSupport::matchFont(const WFont& f) const { for (MatchCache::iterator i = cache_.begin(); i != cache_.end(); ++i) { if (i->font == f) { cache_.splice(cache_.begin(), cache_, i); // implement LRU return FontMatch(i->match, i->desc); } } PANGO_LOCK; enabledFontFormats = enabledFontFormats_; PangoFontDescription *desc = createFontDescription(f); PangoFont *match = pango_font_map_load_font(pangoFontMap, context_, desc); pango_context_set_font_description(context_, desc); // for layoutText() if (cache_.back().match) { g_object_unref(cache_.back().match); pango_font_description_free(cache_.back().desc); } cache_.pop_back(); cache_.push_front(Matched(f, match, desc)); return FontMatch(match, desc); }
static VALUE rg_load_font(VALUE self, VALUE context, VALUE desc) { return GOBJ2RVAL(pango_font_map_load_font(_SELF(self), RVAL2PANGOCONTEXT(context), RVAL2PANGOFONTDESCRIPTION(desc))); }
static struct font_engine_font_t *do_font_load(const char *name) { struct font_engine_font_t *fef = NULL; PangoFontDescription *desc; if( (name) && (desc = pango_font_description_from_string(name)) ) { fef = calloc_2(1, sizeof(struct font_engine_font_t)); fef->desc = desc; fef->font = pango_font_map_load_font( pango_cairo_font_map_get_default(), GLOBALS->fonts_context, fef->desc); fef->metrics=pango_font_get_metrics(fef->font, NULL /*pango_language_get_default()*/ ); fef->ascent = pango_font_metrics_get_ascent(fef->metrics) / 1000; fef->descent = pango_font_metrics_get_descent(fef->metrics) / 1000; fef->is_pango = 1; if(!strncmp(name, "Monospace", 9)) { int i_width = font_engine_string_measure(fef, "i"); fef->mono_width = font_engine_string_measure(fef, "O"); fef->is_mono = (i_width == fef->mono_width); } } return(fef); }
static PangoFont * gdk_gl_font_use_pango_font_common (PangoFontMap *font_map, const PangoFontDescription *font_desc, int first, int count, int list_base) { PangoFont *font = NULL; gchar *charset = NULL; PangoXSubfont subfont_id; gchar *xlfd = NULL; PangoXFontCache *font_cache; XFontStruct *fs; GDK_GL_NOTE_FUNC_PRIVATE (); font = pango_font_map_load_font (font_map, NULL, font_desc); if (font == NULL) { g_warning ("cannot load PangoFont"); goto FAIL; } charset = gdk_gl_font_charset_for_locale (); if (!pango_x_find_first_subfont (font, &charset, 1, &subfont_id)) { g_warning ("cannot find PangoXSubfont"); font = NULL; goto FAIL; } xlfd = pango_x_font_subfont_xlfd (font, subfont_id); if (xlfd == NULL) { g_warning ("cannot get XLFD"); font = NULL; goto FAIL; } font_cache = pango_x_font_map_get_font_cache (font_map); fs = pango_x_font_cache_load (font_cache, xlfd); glXUseXFont (fs->fid, first, count, list_base); pango_x_font_cache_unload (font_cache, fs); FAIL: if (charset != NULL) g_free (charset); if (xlfd != NULL) g_free (xlfd); return font; }
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_setFont (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size) { struct peerfont *pfont = NULL; PangoFontMap *map = NULL; char const *family_name = NULL; gdk_threads_enter (); enum java_awt_font_style 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); pango_font_description_set_size (pfont->desc, size * PANGO_SCALE); 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); /* FIXME: these are possibly wrong, and should in any case probably be cached between calls. */ map = pango_ft2_font_map_for_display (); g_assert (map != NULL); if (pfont->ctx == NULL) pfont->ctx = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (map)); g_assert (pfont->ctx != NULL); if (pfont->font != NULL) g_object_unref (pfont->font); pfont->font = pango_font_map_load_font (map, pfont->ctx, pfont->desc); g_assert (pfont->font != NULL); gdk_threads_leave (); }
// Returns the PangoFont structure corresponding to the closest available font // in the font map. Note that if the font is wholly missing, this could // correspond to a completely different font family and face. PangoFont* PangoFontInfo::ToPangoFont() const { InitFontconfig(); PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_context_new(); pango_cairo_context_set_resolution(context, resolution_); pango_context_set_font_map(context, font_map); PangoFont* font = NULL; { DISABLE_HEAP_LEAK_CHECK; font = pango_font_map_load_font(font_map, context, desc_); } g_object_unref(context); return font; }
/* 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; }
FontSupport::FontMatch FontSupport::matchFont(const WFont& f) const { if (wtFont_ == f) return FontMatch(matchFont_); wtFont_ = f; PANGO_LOCK; PangoFontDescription *desc = createFontDescription(f); if (matchFont_) g_object_unref(matchFont_); matchFont_ = pango_font_map_load_font(pangoFontMap, context_, desc); pango_font_description_free(desc); return FontMatch(matchFont_); }
void ttext::recalculate(const bool force) const { if(calculation_dirty_ || force) { assert(layout_); calculation_dirty_ = false; surface_dirty_ = true; tfont font(get_font_families(font_class_), font_size_, font_style_); pango_layout_set_font_description(layout_, font.get()); if(font_style_ & ttext::STYLE_UNDERLINE) { PangoAttrList *attribute_list = pango_attr_list_new(); pango_attr_list_insert(attribute_list , pango_attr_underline_new(PANGO_UNDERLINE_SINGLE)); pango_layout_set_attributes (layout_, attribute_list); pango_attr_list_unref(attribute_list); } int maximum_width = 0; if(characters_per_line_ != 0) { PangoFont* f = pango_font_map_load_font( pango_cairo_font_map_get_default() , context_ , font.get()); PangoFontMetrics* m = pango_font_get_metrics(f, nullptr); int w = pango_font_metrics_get_approximate_char_width(m); w *= characters_per_line_; maximum_width = ceil(pango_units_to_double(w)); } else { maximum_width = maximum_width_; } if(maximum_width_ != -1) { maximum_width = std::min(maximum_width, maximum_width_); } /* * See set_maximum_width for some more background info as well. * In order to fix the problem first set a width which seems to render * correctly then lower it to fit. For the campaigns the 4 does "the * right thing" for the terrain labels it should use the value 0 to set * the ellipse properly. Need to see whether this is a bug in pango or * a bug in my understanding of the pango api. */ int hack = 4; do { pango_layout_set_width(layout_, maximum_width == -1 ? -1 : (maximum_width + hack) * PANGO_SCALE); pango_layout_get_pixel_extents(layout_, nullptr, &rect_); DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << "' maximum_width " << maximum_width << " hack " << hack << " width " << rect_.x + rect_.width << ".\n"; --hack; } while(maximum_width != -1 && hack >= 0 && rect_.x + rect_.width > maximum_width); DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << "' font_size " << font_size_ << " markedup_text " << markedup_text_ << " font_style " << std::hex << font_style_ << std::dec << " maximum_width " << maximum_width << " maximum_height " << maximum_height_ << " result " << rect_ << ".\n"; if(maximum_width != -1 && rect_.x + rect_.width > maximum_width) { DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << " ' width " << rect_.x + rect_.width << " greater as the wanted maximum of " << maximum_width << ".\n"; } } }
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName) : m_context(0) , m_font(0) , m_size(fontDescription.computedSize()) , m_syntheticBold(false) , m_syntheticOblique(false) , m_scaledFont(0) { FontPlatformData::init(); CString stored_family = familyName.string().utf8(); char const* families[] = { stored_family.data(), NULL }; switch (fontDescription.genericFamily()) { case FontDescription::SerifFamily: families[1] = "serif"; break; case FontDescription::SansSerifFamily: families[1] = "sans"; break; case FontDescription::MonospaceFamily: families[1] = "monospace"; break; case FontDescription::NoFamily: case FontDescription::StandardFamily: default: families[1] = "sans"; break; } PangoFontDescription* description = pango_font_description_new(); pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE); // FIXME: Map all FontWeight values to Pango font weights. if (fontDescription.weight() >= FontWeight600) pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD); if (fontDescription.italic()) pango_font_description_set_style(description, PANGO_STYLE_ITALIC); #if PANGO_VERSION_CHECK(1,21,5) // deprecated in 1.21 m_context = pango_font_map_create_context(m_fontMap); #else m_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(m_fontMap)); #endif for (unsigned int i = 0; !m_font && i < G_N_ELEMENTS(families); i++) { pango_font_description_set_family(description, families[i]); pango_context_set_font_description(m_context, description); m_font = pango_font_map_load_font(m_fontMap, m_context, description); } #if PANGO_VERSION_CHECK(1,18,0) if (m_font) m_scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(m_font))); #else // This compatibility code for older versions of Pango is not well-tested. if (m_font) { PangoFcFont* fcfont = PANGO_FC_FONT(m_font); cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(fcfont->font_pattern); double size; if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch) size = 12.0; cairo_matrix_t fontMatrix; cairo_matrix_init_scale(&fontMatrix, size, size); cairo_font_options_t* fontOptions; if (pango_cairo_context_get_font_options(m_context)) fontOptions = cairo_font_options_copy(pango_cairo_context_get_font_options(m_context)); else fontOptions = cairo_font_options_create(); cairo_matrix_t ctm; cairo_matrix_init_identity(&ctm); m_scaledFont = cairo_scaled_font_create(face, &fontMatrix, &ctm, fontOptions); cairo_font_options_destroy(fontOptions); cairo_font_face_destroy(face); } #endif pango_font_description_free(description); }
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; }
font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) { #ifdef USE_PANGO_WIN32 // damn Pango fudges the size, so we need to unfudge. See source of pango_win32_font_map_init() pango_font_description_set_size(descr, (int) (fontSize*PANGO_SCALE*72/GetDeviceCaps(pango_win32_get_dc(),LOGPIXELSY))); // mandatory huge size (hinting workaround) #else pango_font_description_set_size(descr, (int) (fontSize*PANGO_SCALE)); // mandatory huge size (hinting workaround) #endif font_instance *res = NULL; FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr); if ( loadedFaces.find(descr) == loadedFaces.end() ) { // not yet loaded PangoFont *nFace = NULL; // workaround for bug #1025565. // fonts without families blow up Pango. if (sp_font_description_get_family(descr) != NULL) { nFace = pango_font_map_load_font(fontServer,fontContext,descr); } else { g_warning("%s", _("Ignoring font without family that will crash Pango")); } if ( nFace ) { // duplicate FcPattern, the hard way res = new font_instance(); // store the descr of the font we asked for, since this is the key where we intend // to put the font_instance at in the unordered_map. the descr of the returned // pangofont may differ from what was asked, so we don't know (at this // point) whether loadedFaces[that_descr] is free or not (and overwriting // an entry will bring deallocation problems) res->descr = pango_font_description_copy(descr); res->parent = this; res->InstallFace(nFace); if ( res->pFont == NULL ) { // failed to install face -> bitmap font // printf("face failed\n"); res->parent = NULL; delete res; res = NULL; if ( canFail ) { char *tc = pango_font_description_to_string(descr); PANGO_DEBUG("falling back from %s to 'sans-serif' because InstallFace failed\n",tc); g_free(tc); pango_font_description_set_family(descr,"sans-serif"); res = Face(descr,false); } } else { loadedFaces[res->descr]=res; res->Ref(); AddInCache(res); } } else { // no match if ( canFail ) { PANGO_DEBUG("falling back to 'sans-serif'\n"); descr = pango_font_description_new(); pango_font_description_set_family(descr,"sans-serif"); res = Face(descr,false); pango_font_description_free(descr); } } } else { // already here res = loadedFaces[descr]; res->Ref(); AddInCache(res); } if (res) { res->InitTheFace(); } return res; }
guac_terminal_display* guac_terminal_display_alloc(guac_client* client, const char* font_name, int font_size, int dpi, int foreground, int background) { PangoFontMap* font_map; PangoFont* font; PangoFontMetrics* metrics; PangoContext* context; /* Allocate display */ guac_terminal_display* display = malloc(sizeof(guac_terminal_display)); display->client = client; /* Create default surface */ display->display_layer = guac_client_alloc_layer(client); display->select_layer = guac_client_alloc_layer(client); display->display_surface = guac_common_surface_alloc(client, client->socket, display->display_layer, 0, 0); /* Select layer is a child of the display layer */ guac_protocol_send_move(client->socket, display->select_layer, display->display_layer, 0, 0, 0); /* Get font */ display->font_desc = pango_font_description_new(); pango_font_description_set_family(display->font_desc, font_name); pango_font_description_set_weight(display->font_desc, PANGO_WEIGHT_NORMAL); pango_font_description_set_size(display->font_desc, font_size * PANGO_SCALE * dpi / 96); font_map = pango_cairo_font_map_get_default(); context = pango_font_map_create_context(font_map); font = pango_font_map_load_font(font_map, context, display->font_desc); if (font == NULL) { guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to get font \"%s\"", font_name); return NULL; } metrics = pango_font_get_metrics(font, NULL); if (metrics == NULL) { guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to get font metrics for font \"%s\"", font_name); return NULL; } display->default_foreground = display->glyph_foreground = foreground; display->default_background = display->glyph_background = background; /* Calculate character dimensions */ display->char_width = pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE; display->char_height = (pango_font_metrics_get_descent(metrics) + pango_font_metrics_get_ascent(metrics)) / PANGO_SCALE; /* Initially empty */ display->width = 0; display->height = 0; display->operations = NULL; /* Initially nothing selected */ display->text_selected = display->selection_committed = false; return display; }
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; }
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); }
static PangoCairoFontHexBoxInfo * _pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv) { static const char hexdigits[] = "0123456789ABCDEF"; char c[2] = {0, 0}; PangoFont *mini_font; PangoCairoFontHexBoxInfo *hbi; /* for metrics hinting */ double scale_x = 1., scale_x_inv = 1., scale_y = 1., scale_y_inv = 1.; gboolean is_hinted; int i; int rows; double pad; double width = 0; double height = 0; cairo_font_options_t *font_options; cairo_font_extents_t font_extents; double size, mini_size; PangoFontDescription *desc; cairo_scaled_font_t *scaled_font, *scaled_mini_font; PangoMatrix pango_ctm; cairo_matrix_t cairo_ctm; PangoGravity gravity; if (!cf_priv) return NULL; if (cf_priv->hbi) return cf_priv->hbi; scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv); if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) return NULL; is_hinted = cf_priv->is_hinted; font_options = cairo_font_options_create (); desc = pango_font_describe_with_absolute_size ((PangoFont *)cf_priv->cfont); size = pango_font_description_get_size (desc) / (1.*PANGO_SCALE); gravity = pango_font_description_get_gravity (desc); cairo_scaled_font_get_ctm (scaled_font, &cairo_ctm); cairo_scaled_font_get_font_options (scaled_font, font_options); /* I started adding support for vertical hexboxes here, but it's too much * work. Easier to do with cairo user fonts and vertical writing mode * support in cairo. */ /*cairo_matrix_rotate (&cairo_ctm, pango_gravity_to_rotation (gravity));*/ pango_ctm.xx = cairo_ctm.xx; pango_ctm.yx = cairo_ctm.yx; pango_ctm.xy = cairo_ctm.xy; pango_ctm.yy = cairo_ctm.yy; pango_ctm.x0 = cairo_ctm.x0; pango_ctm.y0 = cairo_ctm.y0; if (is_hinted) { /* prepare for some hinting */ double x, y; x = 1.; y = 0.; cairo_matrix_transform_distance (&cairo_ctm, &x, &y); scale_x = sqrt (x*x + y*y); scale_x_inv = 1 / scale_x; x = 0.; y = 1.; cairo_matrix_transform_distance (&cairo_ctm, &x, &y); scale_y = sqrt (x*x + y*y); scale_y_inv = 1 / scale_y; } /* we hint to the nearest device units */ #define HINT(value, scale, scale_inv) (ceil ((value-1e-5) * scale) * scale_inv) #define HINT_X(value) HINT ((value), scale_x, scale_x_inv) #define HINT_Y(value) HINT ((value), scale_y, scale_y_inv) /* create mini_font description */ { PangoFontMap *fontmap; PangoContext *context; /* XXX this is racy. need a ref'ing getter... */ fontmap = pango_font_get_font_map ((PangoFont *)cf_priv->cfont); if (!fontmap) return NULL; fontmap = g_object_ref (fontmap); /* we inherit most font properties for the mini font. just * change family and size. means, you get bold hex digits * in the hexbox for a bold font. */ /* We should rotate the box, not glyphs */ pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY); pango_font_description_set_family_static (desc, "monospace"); rows = 2; mini_size = size / 2.2; if (is_hinted) { mini_size = HINT_Y (mini_size); if (mini_size < 6.0) { rows = 1; mini_size = MIN (MAX (size - 1, 0), 6.0); } } pango_font_description_set_absolute_size (desc, pango_units_from_double (mini_size)); /* load mini_font */ context = pango_font_map_create_context (fontmap); pango_context_set_matrix (context, &pango_ctm); pango_context_set_language (context, pango_script_get_sample_language (PANGO_SCRIPT_LATIN)); pango_cairo_context_set_font_options (context, font_options); mini_font = pango_font_map_load_font (fontmap, context, desc); g_object_unref (context); g_object_unref (fontmap); } pango_font_description_free (desc); cairo_font_options_destroy (font_options); scaled_mini_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *) mini_font); for (i = 0 ; i < 16 ; i++) { cairo_text_extents_t extents; c[0] = hexdigits[i]; cairo_scaled_font_text_extents (scaled_mini_font, c, &extents); width = MAX (width, extents.width); height = MAX (height, extents.height); } cairo_scaled_font_extents (scaled_font, &font_extents); if (font_extents.ascent + font_extents.descent <= 0) { font_extents.ascent = PANGO_UNKNOWN_GLYPH_HEIGHT; font_extents.descent = 0; } pad = (font_extents.ascent + font_extents.descent) / 43; pad = MIN (pad, mini_size); hbi = g_slice_new (PangoCairoFontHexBoxInfo); hbi->font = (PangoCairoFont *) mini_font; hbi->rows = rows; hbi->digit_width = width; hbi->digit_height = height; hbi->pad_x = pad; hbi->pad_y = pad; if (is_hinted) { hbi->digit_width = HINT_X (hbi->digit_width); hbi->digit_height = HINT_Y (hbi->digit_height); hbi->pad_x = HINT_X (hbi->pad_x); hbi->pad_y = HINT_Y (hbi->pad_y); } hbi->line_width = MIN (hbi->pad_x, hbi->pad_y); hbi->box_height = 3 * hbi->pad_y + rows * (hbi->pad_y + hbi->digit_height); if (rows == 1 || hbi->box_height <= font_extents.ascent) { hbi->box_descent = 2 * hbi->pad_y; } else if (hbi->box_height <= font_extents.ascent + font_extents.descent - 2 * hbi->pad_y) { hbi->box_descent = 2 * hbi->pad_y + hbi->box_height - font_extents.ascent; } else { hbi->box_descent = font_extents.descent * hbi->box_height / (font_extents.ascent + font_extents.descent); } if (is_hinted) { hbi->box_descent = HINT_Y (hbi->box_descent); } cf_priv->hbi = hbi; return hbi; }
int main(int argc, const char* argv[]) { size_t tex_side =(argc>1)? std::atoi(argv[1]) : 512; const char* font_desc_str = (argc>2)? argv[2] : "Sans 18"; unsigned plane = (argc>3)? std::atoi(argv[3]) : 0; cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_A8, tex_side, tex_side ); cairo_t *cr = cairo_create(surface); PangoFontDescription *font_desc = pango_font_description_from_string( font_desc_str ); PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_font_map_create_context(font_map); PangoFont* font = pango_font_map_load_font( font_map, context, font_desc ); PangoFontMetrics* font_metrics = pango_font_get_metrics(font, nullptr); // The Bitmap Glyph Metrics file std::ofstream bgm((argc>5) ? argv[5] : "out.bgm"); unsigned step = tex_side / 16; for(unsigned y=0; y!=16; ++y) { for(unsigned x=0; x!=16; ++x) { render_glyph( cr, font_desc, font, 256*plane + y*16 + x, x, y, step, tex_side, pango_font_metrics_get_ascent(font_metrics), pango_font_metrics_get_descent(font_metrics), bgm ); } } bgm.close(); pango_font_metrics_unref(font_metrics); pango_font_description_free(font_desc); g_object_unref(context); cairo_destroy(cr); cairo_status_t status = cairo_surface_write_to_png( surface, (argc>4) ? argv[4] : "out.png" ); cairo_surface_destroy(surface); return 0; }
PangoFont* createPangoFontForFont(const wxFont* wxfont) { ASSERT(wxfont && wxfont->Ok()); const char* face = wxfont->GetFaceName().mb_str(wxConvUTF8); char const* families[] = { face, 0 }; switch (wxfont->GetFamily()) { case wxFONTFAMILY_ROMAN: families[1] = "serif"; break; case wxFONTFAMILY_SWISS: families[1] = "sans"; break; case wxFONTFAMILY_MODERN: families[1] = "monospace"; break; default: families[1] = "sans"; } PangoFontDescription* description = pango_font_description_new(); pango_font_description_set_absolute_size(description, wxfont->GetPointSize() * PANGO_SCALE); PangoFont* pangoFont = 0; PangoContext* pangoContext = 0; switch (wxfont->GetWeight()) { case wxFONTWEIGHT_LIGHT: pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT); break; case wxFONTWEIGHT_NORMAL: pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL); break; case wxFONTWEIGHT_BOLD: pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD); break; } switch (wxfont->GetStyle()) { case wxFONTSTYLE_NORMAL: pango_font_description_set_style(description, PANGO_STYLE_NORMAL); break; case wxFONTSTYLE_ITALIC: pango_font_description_set_style(description, PANGO_STYLE_ITALIC); break; case wxFONTSTYLE_SLANT: pango_font_description_set_style(description, PANGO_STYLE_OBLIQUE); break; } PangoFontMap* fontMap = pangoFontMap(); pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(fontMap)); for (unsigned i = 0; !pangoFont && i < G_N_ELEMENTS(families); i++) { pango_font_description_set_family(description, families[i]); pango_context_set_font_description(pangoContext, description); pangoFont = pango_font_map_load_font(fontMap, pangoContext, description); } pango_font_description_free(description); return pangoFont; }