Пример #1
0
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);
}
Пример #2
0
static VALUE
rg_load_font(VALUE self, VALUE context, VALUE desc)
{
    return GOBJ2RVAL(pango_font_map_load_font(_SELF(self), 
                                              RVAL2PANGOCONTEXT(context),
                                              RVAL2PANGOFONTDESCRIPTION(desc)));
}
Пример #3
0
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);
}
Пример #4
0
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 ();
}
Пример #6
0
// 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;
}
Пример #7
0
/* 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;
}
Пример #8
0
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_);
}
Пример #9
0
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);
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;

}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #17
0
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;
}
Пример #18
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;
}