cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
				      cairo_scaled_font_t		*scaled_font,
				      unsigned long			 scaled_font_glyph_index,
				      const char *			 utf8,
				      int				 utf8_len,
                                      cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
    cairo_sub_font_t key, *sub_font;
    cairo_scaled_glyph_t *scaled_glyph;
    cairo_font_face_t *font_face;
    cairo_matrix_t identity;
    cairo_font_options_t font_options;
    cairo_scaled_font_t	*unscaled_font;
    cairo_int_status_t status;
    int max_glyphs;
    cairo_bool_t type1_font;

    /* Lookup glyph in unscaled subsets */
    if (subsets->type != CAIRO_SUBSETS_SCALED) {
        key.is_scaled = FALSE;
        _cairo_sub_font_init_key (&key, scaled_font);
	sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
					     &key.base);
        if (sub_font != NULL) {
            status = _cairo_sub_font_lookup_glyph (sub_font,
						   scaled_font_glyph_index,
						   utf8, utf8_len,
						   subset_glyph);
	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
                return status;
        }
    }

    /* Lookup glyph in scaled subsets */
    key.is_scaled = TRUE;
    _cairo_sub_font_init_key (&key, scaled_font);
    sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
					 &key.base);
    if (sub_font != NULL) {
	status = _cairo_sub_font_lookup_glyph (sub_font,
					       scaled_font_glyph_index,
					       utf8, utf8_len,
					       subset_glyph);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    return status;
    }

    /* Glyph not found. Determine whether the glyph is outline or
     * bitmap and add to the appropriate subset.
     *
     * glyph_index 0 (the .notdef glyph) is a special case. Some fonts
     * will return CAIRO_INT_STATUS_UNSUPPORTED when doing a
     * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
     * empty glyphs in this case so we can put the glyph in a unscaled
     * subset. */
    if (scaled_font_glyph_index == 0 ||
	_cairo_font_face_is_user (scaled_font->font_face)) {
	status = CAIRO_STATUS_SUCCESS;
    } else {
	_cairo_scaled_font_freeze_cache (scaled_font);
	status = _cairo_scaled_glyph_lookup (scaled_font,
					     scaled_font_glyph_index,
					     CAIRO_SCALED_GLYPH_INFO_PATH,
					     &scaled_glyph);
	_cairo_scaled_font_thaw_cache (scaled_font);
    }
    if (_cairo_int_status_is_error (status))
        return status;

    if (status == CAIRO_INT_STATUS_SUCCESS &&
	subsets->type != CAIRO_SUBSETS_SCALED &&
	! _cairo_font_face_is_user (scaled_font->font_face))
    {
        /* Path available. Add to unscaled subset. */
        key.is_scaled = FALSE;
        _cairo_sub_font_init_key (&key, scaled_font);
	sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
					     &key.base);
        if (sub_font == NULL) {
            font_face = cairo_scaled_font_get_font_face (scaled_font);
            cairo_matrix_init_identity (&identity);
            _cairo_font_options_init_default (&font_options);
            cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
            cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
            unscaled_font = cairo_scaled_font_create (font_face,
                                                      &identity,
                                                      &identity,
                                                      &font_options);
	    if (unlikely (unscaled_font->status))
		return unscaled_font->status;

            subset_glyph->is_scaled = FALSE;
            type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
            if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
                max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
                subset_glyph->is_composite = TRUE;
            } else {
                max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
                subset_glyph->is_composite = FALSE;
            }

            status = _cairo_sub_font_create (subsets,
					     unscaled_font,
					     subsets->num_sub_fonts,
					     max_glyphs,
					     subset_glyph->is_scaled,
					     subset_glyph->is_composite,
					     &sub_font);

            if (unlikely (status)) {
		cairo_scaled_font_destroy (unscaled_font);
                return status;
	    }

            status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
                                               &sub_font->base);

            if (unlikely (status)) {
		_cairo_sub_font_destroy (sub_font);
                return status;
	    }
	    if (!subsets->unscaled_sub_fonts_list)
		subsets->unscaled_sub_fonts_list = sub_font;
	    else
		subsets->unscaled_sub_fonts_list_end->next = sub_font;
	    subsets->unscaled_sub_fonts_list_end = sub_font;
	    subsets->num_sub_fonts++;
        }
    } else {
        /* No path available. Add to scaled subset. */
        key.is_scaled = TRUE;
        _cairo_sub_font_init_key (&key, scaled_font);
	sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
					     &key.base);
        if (sub_font == NULL) {
            subset_glyph->is_scaled = TRUE;
            subset_glyph->is_composite = FALSE;
            if (subsets->type == CAIRO_SUBSETS_SCALED)
                max_glyphs = INT_MAX;
            else
                max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;

            status = _cairo_sub_font_create (subsets,
					     cairo_scaled_font_reference (scaled_font),
					     subsets->num_sub_fonts,
					     max_glyphs,
					     subset_glyph->is_scaled,
					     subset_glyph->is_composite,
					     &sub_font);
            if (unlikely (status)) {
		cairo_scaled_font_destroy (scaled_font);
                return status;
	    }

            status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
                                               &sub_font->base);
            if (unlikely (status)) {
		_cairo_sub_font_destroy (sub_font);
                return status;
	    }
	    if (!subsets->scaled_sub_fonts_list)
		subsets->scaled_sub_fonts_list = sub_font;
	    else
		subsets->scaled_sub_fonts_list_end->next = sub_font;
	    subsets->scaled_sub_fonts_list_end = sub_font;
	    subsets->num_sub_fonts++;
        }
    }

    return _cairo_sub_font_map_glyph (sub_font,
				      scaled_font_glyph_index,
				      utf8, utf8_len,
				      subset_glyph);
}
Example #2
0
void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
{
    cairo_font_options_t* options = getDefaultFontOptions();

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    // Scaling a font with width zero size leads to a failed cairo_scaled_font_t instantiations.
    // Instead we scale we scale the font to a very tiny size and just abort rendering later on.
    float realSize = m_size ? m_size : 1;

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, realSize, realSize);
    else {
        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // The matrix from FontConfig does not include the scale. 
        cairo_matrix_scale(&fontMatrix, realSize, realSize);
    }

    m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
    cairo_font_options_destroy(options);
}
FontPlatformData::FontPlatformData(GDIObject<HFONT> font, cairo_font_face_t* fontFace, float size, bool bold, bool oblique)
    : m_font(SharedGDIObject<HFONT>::create(WTFMove(font)))
    , m_size(size)
    , m_syntheticOblique(oblique)
{
    cairo_matrix_t fontMatrix;
    cairo_matrix_init_scale(&fontMatrix, size, size);
    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_font_options_t* options = cairo_font_options_create();

    // We force antialiasing and disable hinting to provide consistent
    // typographic qualities for custom fonts on all platforms.
    cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_BEST);

    if (syntheticOblique()) {
        static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
        cairo_matrix_t skew = {1, 0, syntheticObliqueSkew, 1, 0, 0};
        cairo_matrix_multiply(&fontMatrix, &skew, &fontMatrix);
    }

    m_scaledFont = adoptRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
    cairo_font_options_destroy(options);
}
Example #4
0
static int l_font_new(lua_State * L)
{
	const char * family = luaL_checkstring(L, 1);
	struct lfont_t * font = lua_newuserdata(L, sizeof(struct lfont_t));
	if(FT_Init_FreeType(&font->library))
		return 0;
	if(FT_New_Xfs_Face(font->library, family, 0, &font->fface))
	{
		FT_Done_FreeType(font->library);
		return 0;
	}
	font->face = cairo_ft_font_face_create_for_ft_face(font->fface, 0);
	if(font->face->status != CAIRO_STATUS_SUCCESS)
	{
		FT_Done_Face(font->fface);
		FT_Done_FreeType(font->library);
		cairo_font_face_destroy(font->face);
		return 0;
	}
	cairo_font_options_t * options = cairo_font_options_create();
	cairo_matrix_t identity;
	cairo_matrix_init_identity(&identity);
	font->sfont = cairo_scaled_font_create(font->face, &identity, &identity, options);
	cairo_font_options_destroy(options);
	if(cairo_scaled_font_status(font->sfont) != CAIRO_STATUS_SUCCESS)
	{
		FT_Done_Face(font->fface);
		FT_Done_FreeType(font->library);
		cairo_font_face_destroy(font->face);
		cairo_scaled_font_destroy(font->sfont);
		return 0;
	}
	luaL_setmetatable(L, MT_FONT);
	return 1;
}
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool oblique)
    : m_font(0)
    , m_size(size)
    , m_orientation(Horizontal)
    , m_textOrientation(TextOrientationVerticalRight)
    , m_widthVariant(RegularWidth)
    , m_scaledFont(0)
    , m_isColorBitmapFont(false)
    , m_syntheticBold(bold)
    , m_syntheticOblique(oblique)
    , m_useGDI(false)
{
   cairo_matrix_t fontMatrix;
   cairo_matrix_init_scale(&fontMatrix, size, size);
   cairo_matrix_t ctm;
   cairo_matrix_init_identity(&ctm);
   cairo_font_options_t* options = cairo_font_options_create();

   // We force antialiasing and disable hinting to provide consistent
   // typographic qualities for custom fonts on all platforms.
   cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
   cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);

   m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
   cairo_font_options_destroy(options);
}
Example #6
0
    explicit font_fc(cairo_t* cairo, FcPattern* pattern, double offset, double dpi_x, double dpi_y) : font(cairo, offset), m_pattern(pattern) {
      cairo_matrix_t fm;
      cairo_matrix_t ctm;
      cairo_matrix_init_scale(&fm, size(dpi_x), size(dpi_y));
      cairo_get_matrix(m_cairo, &ctm);

      auto fontface = cairo_ft_font_face_create_for_pattern(m_pattern);
      auto opts = cairo_font_options_create();
      m_scaled = cairo_scaled_font_create(fontface, &fm, &ctm, opts);
      cairo_font_options_destroy(opts);
      cairo_font_face_destroy(fontface);

      auto status = cairo_scaled_font_status(m_scaled);
      if (status != CAIRO_STATUS_SUCCESS) {
        throw application_error(sstream() << "cairo_scaled_font_create(): " << cairo_status_to_string(status));
      }

      auto lock = make_unique<utils::ft_face_lock>(m_scaled);
      auto face = static_cast<FT_Face>(*lock);

      if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) == FT_Err_Ok) {
        return;
      } else if (FT_Select_Charmap(face, FT_ENCODING_BIG5) == FT_Err_Ok) {
        return;
      } else if (FT_Select_Charmap(face, FT_ENCODING_SJIS) == FT_Err_Ok) {
        return;
      }

      lock.reset();
    }
Example #7
0
void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
{
    cairo_font_options_t* options = cairo_font_options_copy(getDefaultFontOptions());

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
    else {
        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // The matrix from FontConfig does not include the scale.
        cairo_matrix_scale(&fontMatrix, m_size, m_size);
    }

    m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
    cairo_font_options_destroy(options);
}
void FontPlatformData::setOrientation(FontOrientation orientation)
{
    ASSERT(m_scaledFont);

    if (!m_scaledFont || (m_orientation == orientation))
        return;

    cairo_matrix_t transformationMatrix;
    cairo_matrix_init_identity(&transformationMatrix);

    cairo_matrix_t fontMatrix;
    cairo_scaled_font_get_font_matrix(m_scaledFont, &fontMatrix);

    cairo_font_options_t* options = getDefaultFontOptions();

    // In case of vertical orientation, rotate the transformation matrix.
    // Otherwise restore the horizontal orientation matrix.
    if (orientation == Vertical)
        rotateCairoMatrixForVerticalOrientation(&fontMatrix);
    else
        fontMatrix = m_horizontalOrientationMatrix;

    cairo_font_face_t* fontFace = cairo_scaled_font_get_font_face(m_scaledFont);
    cairo_scaled_font_destroy(m_scaledFont);
    m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &transformationMatrix, options);
    cairo_font_options_destroy(options);
    m_orientation = orientation;
}
Example #9
0
static PyObject *
scaled_font_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PycairoFontFace *ff;
    PycairoFontOptions *fo;
    PycairoMatrix *mx1, *mx2;

    if (!PyArg_ParseTuple(args, "O!O!O!O!:ScaledFont.__new__",
			  &PycairoFontFace_Type, &ff,
			  &PycairoMatrix_Type, &mx1,
			  &PycairoMatrix_Type, &mx2,
			  &PycairoFontOptions_Type, &fo))
	return NULL;

    PyObject *o = type->tp_alloc(type, 0);
    if (o != NULL) {
	cairo_scaled_font_t *scaled_font = cairo_scaled_font_create
	    (ff->font_face, &mx1->matrix, &mx2->matrix, fo->font_options);

	if (Pycairo_Check_Status (cairo_scaled_font_status (scaled_font))) {
	    cairo_scaled_font_destroy (scaled_font);
	    Py_DECREF(o);
	    return NULL;
	}
	((PycairoScaledFont *)o)->scaled_font = scaled_font;
    }
    return o;
}
Example #10
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_font_face_t *font_face;
    cairo_font_options_t *font_options;
    cairo_scaled_font_t *scaled_font;
    cairo_matrix_t identity;
    cairo_matrix_t zero;

    cairo_matrix_init_identity(&identity);

    zero = identity;
    cairo_matrix_scale(&zero, 0, 0);

    font_face = cairo_get_font_face (cr);
    font_options = cairo_font_options_create ();
    cairo_get_font_options (cr, font_options);
    scaled_font = cairo_scaled_font_create (font_face,
	    &identity,
	    &zero,
	    font_options);
    cairo_set_scaled_font (cr, scaled_font);
    cairo_show_text (cr, "Hello");
    cairo_scaled_font_destroy (scaled_font);
    cairo_font_options_destroy (font_options);

    return cairo_test_status_from_status (cairo_test_get_context (cr),
                                          cairo_status(cr));
}
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool oblique)
    : m_font(0)
    , m_size(size)
    , m_fontFace(fontFace)
    , m_scaledFont(0)
    , m_syntheticBold(bold)
    , m_syntheticOblique(oblique)
    , m_useGDI(false)
{
   cairo_matrix_t fontMatrix;
   cairo_matrix_init_scale(&fontMatrix, size, size);
   cairo_matrix_t ctm;
   cairo_matrix_init_identity(&ctm);
   cairo_font_options_t* options = cairo_font_options_create();

   // We force antialiasing and disable hinting to provide consistent
   // typographic qualities for custom fonts on all platforms.
#if PLATFORM(APOLLO)
   // In Apollo use the anti-aliasing mode selected by the user. See bug 2404418.
   cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_DEFAULT);
#else
   cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
   cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
#endif

   m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
   cairo_font_options_destroy(options);
}
Example #12
0
static cairo_status_t
cairo_type1_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                         cairo_type1_font_t         **subset_return,
                         cairo_bool_t                 hex_encode)
{
    cairo_type1_font_t *font;
    cairo_font_face_t *font_face;
    cairo_matrix_t font_matrix;
    cairo_matrix_t ctm;
    cairo_font_options_t font_options;
    cairo_status_t status;

    font = calloc (1, sizeof (cairo_type1_font_t));
    if (font == NULL)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    font->widths = calloc (scaled_font_subset->num_glyphs,
                           sizeof (int));
    if (font->widths == NULL) {
	free (font);
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    font->scaled_font_subset = scaled_font_subset;
    font->hex_encode = hex_encode;

    font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);

    cairo_matrix_init_scale (&font_matrix, 1000, -1000);
    cairo_matrix_init_identity (&ctm);

    _cairo_font_options_init_default (&font_options);
    cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);

    font->type1_scaled_font = cairo_scaled_font_create (font_face,
							&font_matrix,
							&ctm,
							&font_options);
    status = font->type1_scaled_font->status;
    if (status)
        goto fail;

    _cairo_array_init (&font->contents, sizeof (unsigned char));
    font->output = NULL;

    *subset_return = font;

    return CAIRO_STATUS_SUCCESS;

fail:
    free (font->widths);
    free (font);

    return status;
}
Example #13
0
void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace, const FontDescription& fontDescription)
{
    cairo_font_options_t* options = getDefaultFontOptions();

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    // Scaling a font with width zero size leads to a failed cairo_scaled_font_t instantiations.
    // Instead we scale we scale the font to a very tiny size and just abort rendering later on.
    float realSize = m_size ? m_size : 1;

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, realSize, realSize);
    else {

        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
        int actualFontSlant;
        if (fontDescription.italic() && FcPatternGetInteger(m_pattern.get(), FC_SLANT, 0, &actualFontSlant) == FcResultMatch)
            m_syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;

        // The matrix from FontConfig does not include the scale. 
        cairo_matrix_scale(&fontMatrix, realSize, realSize);

    }

    if (syntheticOblique()) {
        static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
        cairo_matrix_t skew = {1, 0, syntheticObliqueSkew, 1, 0, 0};
        cairo_matrix_multiply(&fontMatrix, &skew, &fontMatrix);
    }

    m_horizontalOrientationMatrix = fontMatrix;
    if (m_orientation == Vertical)
        rotateCairoMatrixForVerticalOrientation(&fontMatrix);

    m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
    cairo_font_options_destroy(options);
}
static cairo_scaled_font_t *
create_scaled_font (cairo_t * cr)
{
    FcPattern *pattern, *resolved;
    FcResult result;
    cairo_font_face_t *font_face;
    cairo_scaled_font_t *scaled_font;
    cairo_font_options_t *font_options;
    cairo_matrix_t font_matrix, ctm;
    double pixel_size;

    font_options = cairo_font_options_create ();

    cairo_get_font_options (cr, font_options);

    pattern = FcPatternCreate ();

    FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *)"Bitstream Vera Sans");
    FcPatternAddDouble (pattern, FC_PIXEL_SIZE, TEXT_SIZE);
    FcConfigSubstitute (NULL, pattern, FcMatchPattern);

    cairo_ft_font_options_substitute (font_options, pattern);

    FcDefaultSubstitute (pattern);
    resolved = FcFontMatch (NULL, pattern, &result);

    /* set layout to vertical */
    FcPatternDel (resolved, FC_VERTICAL_LAYOUT);
    FcPatternAddBool (resolved, FC_VERTICAL_LAYOUT, FcTrue);

    FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size);

    font_face = cairo_ft_font_face_create_for_pattern (resolved);

    cairo_matrix_init_translate (&font_matrix, 10, 30);
    cairo_matrix_rotate (&font_matrix, M_PI_2/3);
    cairo_matrix_scale (&font_matrix, pixel_size, pixel_size);

    cairo_get_matrix (cr, &ctm);

    scaled_font = cairo_scaled_font_create (font_face,
					    &font_matrix,
					    &ctm,
					    font_options);

    cairo_font_options_destroy (font_options);
    cairo_font_face_destroy (font_face);
    FcPatternDestroy (pattern);
    FcPatternDestroy (resolved);

    return scaled_font;
}
Example #15
0
static PyObject *
scaled_font_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
  PycairoFontFace *ff;
  PycairoFontOptions *fo;
  PycairoMatrix *mx1, *mx2;

  if (!PyArg_ParseTuple(args, "O!O!O!O!:ScaledFont.__new__",
			&PycairoFontFace_Type, &ff,
			&PycairoMatrix_Type, &mx1,
			&PycairoMatrix_Type, &mx2,
			&PycairoFontOptions_Type, &fo))
    return NULL;
  return PycairoScaledFont_FromScaledFont (
               cairo_scaled_font_create (ff->font_face, &mx1->matrix,
					 &mx2->matrix, fo->font_options));
}
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
{
    m_fontFace = cairo_win32_font_face_create_for_hfont(font);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, size, size);

    static cairo_font_options_t* fontOptions = 0;
    if (!fontOptions) {
       fontOptions = cairo_font_options_create();
       cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
    }

    m_scaledFont = cairo_scaled_font_create(m_fontFace, &sizeMatrix, &ctm, fontOptions);
}
Example #17
0
void FontSysData::Init(Font font, int angle)
{
	LLOG("FontSysData::Init " << font << ", " << angle);
	FcPattern *p = CreateFcPattern(font);
	cairo_font_face_t *font_face = cairo_ft_font_face_create_for_pattern(p);
	FcPatternDestroy(p);
	
	cairo_matrix_t font_matrix[1], ctm[1];
	cairo_matrix_init_identity(ctm);
	cairo_matrix_init_scale(font_matrix, font.GetHeight(), font.GetHeight());
	if(angle)
		cairo_matrix_rotate(font_matrix, -angle * M_2PI / 3600);
	cairo_font_options_t *opt = cairo_font_options_create();
	scaled_font = cairo_scaled_font_create(font_face, font_matrix, ctm, opt);

	cairo_font_options_destroy(opt);
 	cairo_font_face_destroy(font_face);
}
static int new_Win32ScaledFont (lua_State *L)
{
    cairo_font_face_t *font_face;
    const cairo_matrix_t *font_matrix;
    const cairo_matrix_t *ctm;
    const cairo_font_options_t *options;
    cairo_scaled_font_t *sf;

    lua_remove(L, 1); // remove cairo.Win32ScaledFont

    font_face = get_cairo_font_face_t (L, 1);
    font_matrix = get_cairo_matrix_t (L, 2);
    ctm = get_cairo_matrix_t (L, 3);
    options = get_cairo_font_options_t (L, 4);
    sf = cairo_scaled_font_create (font_face, font_matrix, ctm, options);

    return new_ScaledFont(L, LUACAIRO ".Win32ScaledFont.mt", sf, 1, 1);
}
Example #19
0
cairo_scaled_font_t *
gfxDWriteFont::CairoScaledFont()
{
    if (!mCairoScaledFont) {
        cairo_matrix_t sizeMatrix;
        cairo_matrix_t identityMatrix;

        cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);
        cairo_matrix_init_identity(&identityMatrix);

        cairo_font_options_t *fontOptions = cairo_font_options_create();
        if (mNeedsOblique) {
            double skewfactor = OBLIQUE_SKEW_FACTOR;

            cairo_matrix_t style;
            cairo_matrix_init(&style,
                              1,                //xx
                              0,                //yx
                              -1 * skewfactor,  //xy
                              1,                //yy
                              0,                //x0
                              0);               //y0
            cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
        }

        if (mAntialiasOption != kAntialiasDefault) {
            cairo_font_options_set_antialias(fontOptions,
                GetCairoAntialiasOption(mAntialiasOption));
        }

        mCairoScaledFont = cairo_scaled_font_create(CairoFontFace(),
                                                    &sizeMatrix,
                                                    &identityMatrix,
                                                    fontOptions);
        cairo_font_options_destroy(fontOptions);
    }

    NS_ASSERTION(mAdjustedSize == 0.0 ||
                 cairo_scaled_font_status(mCairoScaledFont) 
                   == CAIRO_STATUS_SUCCESS,
                 "Failed to make scaled font");

    return mCairoScaledFont;
}
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
{
    cairo_font_face_t* fontFace = cairo_win32_font_face_create_for_hfont(font);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, size, size);

    static cairo_font_options_t* fontOptions = nullptr;
    if (!fontOptions) {
       fontOptions = cairo_font_options_create();
       cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
    }

    m_scaledFont = adoptRef(cairo_scaled_font_create(fontFace, &sizeMatrix, &ctm, fontOptions));
    cairo_font_face_destroy(fontFace);

    if (!m_useGDI && m_size)
        m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
}
static cairo_int_status_t
_cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
					cairo_operator_t      op,
					cairo_pattern_t	     *source,
					cairo_glyph_t        *glyphs,
					int		      num_glyphs,
					cairo_scaled_font_t  *scaled_font,
					int		     *remaining_glyphs)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;
    cairo_int_status_t status;
    cairo_scaled_font_t *font;
    cairo_matrix_t new_ctm, ctm_inverse;
    int i;

    for (i = 0; i < num_glyphs; i++)
	cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);

    /* We require the matrix to be invertable. */
    ctm_inverse = scaled_font->ctm;
    status = cairo_matrix_invert (&ctm_inverse);
    if (status)
	return CAIRO_INT_STATUS_IMAGE_FALLBACK;

    cairo_matrix_multiply (&new_ctm, &scaled_font->ctm, &ctm_inverse);
    font = cairo_scaled_font_create (scaled_font->font_face,
				     &scaled_font->font_matrix,
				     &new_ctm,
				     &scaled_font->options);

    status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
						    NULL, 0,
						    glyphs, num_glyphs,
						    NULL, 0,
						    FALSE,
						    font);

    cairo_scaled_font_destroy (font);

    return status;
}
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
{
    m_fontFace = cairo_win32_font_face_create_for_hfont(font);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, size, size);

    static cairo_font_options_t* fontOptions = 0;
    if (!fontOptions) {
       fontOptions = cairo_font_options_create();
#if PLATFORM(APOLLO)
        // In Apollo use the anti-aliasing mode selected by the user. See bug 2404418.
	    cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_DEFAULT);
#else
        cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
#endif
    }

    m_scaledFont = cairo_scaled_font_create(m_fontFace, &sizeMatrix, &ctm, fontOptions);
}
Example #23
0
static cairo_int_status_t
_cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
					cairo_operator_t      op,
					const cairo_pattern_t *source,
					cairo_glyph_t        *glyphs,
					int		      num_glyphs,
					cairo_scaled_font_t  *scaled_font,
					cairo_clip_t	     *clip,
					int		     *remaining_glyphs)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;
    cairo_int_status_t status;
    cairo_scaled_font_t *font;
    cairo_matrix_t new_ctm, invert_y_axis;

    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
    if (unlikely (status))
	return status;

    cairo_matrix_init_scale (&invert_y_axis, 1, -1);
    cairo_matrix_multiply (&new_ctm, &invert_y_axis, &scaled_font->ctm);
    cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &new_ctm);
    font = cairo_scaled_font_create (scaled_font->font_face,
				     &scaled_font->font_matrix,
				     &new_ctm,
				     &scaled_font->options);
    if (unlikely (font->status))
	return font->status;

    status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
						    NULL, 0,
						    glyphs, num_glyphs,
						    NULL, 0,
						    FALSE,
						    font);

    cairo_scaled_font_destroy (font);

    return status;
}
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic)
    : m_context(0)
    , m_font(0)
    , m_size(size)
    , m_syntheticBold(bold)
    , m_syntheticOblique(italic)
    , m_scaledFont(0)
{
    cairo_matrix_t fontMatrix;
    cairo_matrix_init_scale(&fontMatrix, size, size);
    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_font_options_t* options = cairo_font_options_create();

    // We force antialiasing and disable hinting to provide consistent
    // typographic qualities for custom fonts on all platforms.
    cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);

    m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
    cairo_font_options_destroy(options);
}
Example #25
0
void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
{
    cairo_font_options_t* options = 0;
#if !PLATFORM(CLUTTER) && (!PLATFORM(EFL) || ENABLE(GLIB_SUPPORT))
    if (GdkScreen* screen = gdk_screen_get_default())
        options = cairo_font_options_copy(gdk_screen_get_font_options(screen));
#endif
    // gdk_screen_get_font_options() returns null if no default
    // options are set, so we always have to check.
    if (!options)
        options = cairo_font_options_create();

    cairo_matrix_t ctm;
    cairo_matrix_init_identity(&ctm);

    cairo_matrix_t fontMatrix;
    if (!m_pattern)
        cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
    else {
        setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());

        // FontConfig may return a list of transformation matrices with the pattern, for instance,
        // for fonts that are oblique. We use that to initialize the cairo font matrix.
        FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
        FcMatrixInit(&fontConfigMatrix);

        // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
        for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
            FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
        cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
                          -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);

        // The matrix from FontConfig does not include the scale.
        cairo_matrix_scale(&fontMatrix, m_size, m_size);
    }

    m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
    cairo_font_options_destroy(options);
}
bool
ScaledFontBase::PopulateCairoScaledFont()
{
  cairo_font_face_t* cairoFontFace = GetCairoFontFace();
  if (!cairoFontFace) {
    return false;
  }

  cairo_matrix_t sizeMatrix;
  cairo_matrix_t identityMatrix;

  cairo_matrix_init_scale(&sizeMatrix, mSize, mSize);
  cairo_matrix_init_identity(&identityMatrix);

  cairo_font_options_t *fontOptions = cairo_font_options_create();

  mScaledFont = cairo_scaled_font_create(cairoFontFace, &sizeMatrix,
    &identityMatrix, fontOptions);

  cairo_font_options_destroy(fontOptions);
  cairo_font_face_destroy(cairoFontFace);

  return (cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS);
}
Example #27
0
static cairo_scaled_font_t *
pango_cairo_win32_font_get_scaled_font (PangoCairoFont *font)
{
  PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font);

  if (!cwfont->scaled_font)
    {
      cairo_font_face_t *font_face;

      font_face = pango_cairo_win32_font_get_font_face (font);
      cwfont->scaled_font = cairo_scaled_font_create (font_face,
						      &cwfont->font_matrix,
						      &cwfont->ctm,
						      cwfont->options);

      /* Failure of the above should only occur for out of memory,
       * we can't proceed at that point
       */
      if (!cwfont->scaled_font)
	g_error ("Unable to create Win32 cairo scaled font.\nThis means out of memory or a cairo/fontconfig/FreeType bug");
    }
  
  return cwfont->scaled_font;
}
Example #28
0
cairo_status_t
_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
					 cairo_operator_t	     op,
					 const cairo_pattern_t	    *source,
					 const char		    *utf8,
					 int			     utf8_len,
					 const cairo_glyph_t	    *glyphs,
					 int			     num_glyphs,
					 const cairo_text_cluster_t *clusters,
					 int			     num_clusters,
					 cairo_text_cluster_flags_t  cluster_flags,
					 cairo_scaled_font_t	    *scaled_font,
					 const cairo_clip_t	    *clip)
{
    cairo_status_t status;
    cairo_clip_t *dev_clip;
    cairo_glyph_t stack_glyphs [CAIRO_STACK_ARRAY_LENGTH(cairo_glyph_t)];
    cairo_glyph_t *dev_glyphs = stack_glyphs;
    cairo_scaled_font_t *dev_scaled_font = scaled_font;
    cairo_pattern_union_t source_copy;
    cairo_font_options_t options;

    if (unlikely (wrapper->target->status))
	return wrapper->target->status;

    dev_clip = _cairo_surface_wrapper_get_clip (wrapper, clip);
    if (_cairo_clip_is_all_clipped (dev_clip))
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    cairo_surface_get_font_options (wrapper->target, &options);
    cairo_font_options_merge (&options, &scaled_font->options);

    if (wrapper->needs_transform) {
	cairo_matrix_t m;
	int i;

	_cairo_surface_wrapper_get_transform (wrapper, &m);

	if (! _cairo_matrix_is_translation (&wrapper->transform)) {
	    cairo_matrix_t ctm;

	    /* XXX No device-transform? A bug in the tangle of layers? */
	    _cairo_matrix_multiply (&ctm,
				    &wrapper->transform,
				    &scaled_font->ctm);
	    dev_scaled_font = cairo_scaled_font_create (scaled_font->font_face,
							&scaled_font->font_matrix,
							&ctm, &options);
	}

	if (num_glyphs > ARRAY_LENGTH (stack_glyphs)) {
	    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
	    if (unlikely (dev_glyphs == NULL)) {
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
		goto FINISH;
	    }
	}

	for (i = 0; i < num_glyphs; i++) {
	    dev_glyphs[i] = glyphs[i];
	    cairo_matrix_transform_point (&m,
					  &dev_glyphs[i].x,
					  &dev_glyphs[i].y);
	}

	status = cairo_matrix_invert (&m);
	assert (status == CAIRO_STATUS_SUCCESS);

	_copy_transformed_pattern (&source_copy.base, source, &m);
	source = &source_copy.base;
    } else {
	if (! cairo_font_options_equal (&options, &scaled_font->options)) {
	    dev_scaled_font = cairo_scaled_font_create (scaled_font->font_face,
							&scaled_font->font_matrix,
							&scaled_font->ctm,
							&options);
	}

	/* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
	 * to modify the glyph array that's passed in.  We must always
	 * copy the array before handing it to the backend.
	 */
	if (num_glyphs > ARRAY_LENGTH (stack_glyphs)) {
	    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
	    if (unlikely (dev_glyphs == NULL)) {
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
		goto FINISH;
	    }
	}

	memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
    }

    status = _cairo_surface_show_text_glyphs (wrapper->target, op, source,
					      utf8, utf8_len,
					      dev_glyphs, num_glyphs,
					      clusters, num_clusters,
					      cluster_flags,
					      dev_scaled_font,
					      dev_clip);
 FINISH:
    _cairo_clip_destroy (dev_clip);
    if (dev_glyphs != stack_glyphs)
	free (dev_glyphs);
    if (dev_scaled_font != scaled_font)
	cairo_scaled_font_destroy (dev_scaled_font);
    return status;
}
static cairo_status_t
create_scaled_font (cairo_t * cr,
		    cairo_scaled_font_t **out)
{
    FcPattern *pattern, *resolved;
    FcResult result;
    cairo_font_face_t *font_face;
    cairo_scaled_font_t *scaled_font;
    cairo_font_options_t *font_options;
    cairo_matrix_t font_matrix, ctm;
    cairo_status_t status;
    double pixel_size;

    font_options = cairo_font_options_create ();

    cairo_get_font_options (cr, font_options);

    pattern = FcPatternCreate ();
    if (pattern == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *)CAIRO_TEST_FONT_FAMILY " Sans");
    FcPatternAddDouble (pattern, FC_PIXEL_SIZE, TEXT_SIZE);
    FcConfigSubstitute (NULL, pattern, FcMatchPattern);

    cairo_ft_font_options_substitute (font_options, pattern);

    FcDefaultSubstitute (pattern);
    resolved = FcFontMatch (NULL, pattern, &result);
    if (resolved == NULL) {
	FcPatternDestroy (pattern);
	return CAIRO_STATUS_NO_MEMORY;
    }

    /* set layout to vertical */
    FcPatternDel (resolved, FC_VERTICAL_LAYOUT);
    FcPatternAddBool (resolved, FC_VERTICAL_LAYOUT, FcTrue);

    FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size);

    font_face = cairo_ft_font_face_create_for_pattern (resolved);

    cairo_matrix_init_translate (&font_matrix, 10, 30);
    cairo_matrix_rotate (&font_matrix, M_PI_2/3);
    cairo_matrix_scale (&font_matrix, pixel_size, pixel_size);

    cairo_get_matrix (cr, &ctm);

    scaled_font = cairo_scaled_font_create (font_face,
					    &font_matrix,
					    &ctm,
					    font_options);

    cairo_font_options_destroy (font_options);
    cairo_font_face_destroy (font_face);
    FcPatternDestroy (pattern);
    FcPatternDestroy (resolved);

    status = cairo_scaled_font_status (scaled_font);
    if (status) {
	cairo_scaled_font_destroy (scaled_font);
	return status;
    }

    *out = scaled_font;
    return CAIRO_STATUS_SUCCESS;
}
Example #30
0
void
gfxGDIFont::Initialize()
{
    NS_ASSERTION(!mMetrics, "re-creating metrics? this will leak");

    LOGFONTW logFont;

    // Figure out if we want to do synthetic oblique styling.
    GDIFontEntry* fe = static_cast<GDIFontEntry*>(GetFontEntry());
    bool wantFakeItalic =
        (mStyle.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) &&
        !fe->IsItalic();

    // If the font's family has an actual italic face (but font matching
    // didn't choose it), we have to use a cairo transform instead of asking
    // GDI to italicize, because that would use a different face and result
    // in a possible glyph ID mismatch between shaping and rendering.
    //
    // We use the mFamilyHasItalicFace flag in the entry in case of user fonts,
    // where the *CSS* family may not know about italic faces that are present
    // in the *GDI* family, and which GDI would use if we asked it to perform
    // the "italicization".
    bool useCairoFakeItalic = wantFakeItalic && fe->mFamilyHasItalicFace;

    if (mAdjustedSize == 0.0) {
        mAdjustedSize = mStyle.size;
        if (mStyle.sizeAdjust != 0.0 && mAdjustedSize > 0.0) {
            // to implement font-size-adjust, we first create the "unadjusted" font
            FillLogFont(logFont, mAdjustedSize,
                        wantFakeItalic && !useCairoFakeItalic);
            mFont = ::CreateFontIndirectW(&logFont);

            // initialize its metrics so we can calculate size adjustment
            Initialize();

            // calculate the properly adjusted size, and then proceed
            // to recreate mFont and recalculate metrics
            gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
            mAdjustedSize = mStyle.GetAdjustedSize(aspect);

            // delete the temporary font and metrics
            ::DeleteObject(mFont);
            mFont = nullptr;
            delete mMetrics;
            mMetrics = nullptr;
        }
    }

    // (bug 724231) for local user fonts, we don't use GDI's synthetic bold,
    // as it could lead to a different, incompatible face being used
    // but instead do our own multi-striking
    if (mNeedsBold && GetFontEntry()->IsLocalUserFont()) {
        mApplySyntheticBold = true;
    }

    // this may end up being zero
    mAdjustedSize = ROUND(mAdjustedSize);
    FillLogFont(logFont, mAdjustedSize, wantFakeItalic && !useCairoFakeItalic);
    mFont = ::CreateFontIndirectW(&logFont);

    mMetrics = new gfxFont::Metrics;
    ::memset(mMetrics, 0, sizeof(*mMetrics));

    AutoDC dc;
    SetGraphicsMode(dc.GetDC(), GM_ADVANCED);
    AutoSelectFont selectFont(dc.GetDC(), mFont);

    // Get font metrics if size > 0
    if (mAdjustedSize > 0.0) {

        OUTLINETEXTMETRIC oMetrics;
        TEXTMETRIC& metrics = oMetrics.otmTextMetrics;

        if (0 < GetOutlineTextMetrics(dc.GetDC(), sizeof(oMetrics), &oMetrics)) {
            mMetrics->superscriptOffset = (double)oMetrics.otmptSuperscriptOffset.y;
            // Some fonts have wrong sign on their subscript offset, bug 410917.
            mMetrics->subscriptOffset = fabs((double)oMetrics.otmptSubscriptOffset.y);
            mMetrics->strikeoutSize = (double)oMetrics.otmsStrikeoutSize;
            mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
            mMetrics->underlineSize = (double)oMetrics.otmsUnderscoreSize;
            mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;

            const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
            GLYPHMETRICS gm;
            DWORD len = GetGlyphOutlineW(dc.GetDC(), PRUnichar('x'), GGO_METRICS, &gm, 0, nullptr, &kIdentityMatrix);
            if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
                // 56% of ascent, best guess for true type
                mMetrics->xHeight =
                    ROUND((double)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
            } else {
                mMetrics->xHeight = gm.gmptGlyphOrigin.y;
            }
            mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
            gfxFloat typEmHeight = (double)oMetrics.otmAscent - (double)oMetrics.otmDescent;
            mMetrics->emAscent = ROUND(mMetrics->emHeight * (double)oMetrics.otmAscent / typEmHeight);
            mMetrics->emDescent = mMetrics->emHeight - mMetrics->emAscent;
            if (oMetrics.otmEMSquare > 0) {
                mFUnitsConvFactor = float(mAdjustedSize / oMetrics.otmEMSquare);
            }
        } else {
            // Make a best-effort guess at extended metrics
            // this is based on general typographic guidelines

            // GetTextMetrics can fail if the font file has been removed
            // or corrupted recently.
            BOOL result = GetTextMetrics(dc.GetDC(), &metrics);
            if (!result) {
                NS_WARNING("Missing or corrupt font data, fasten your seatbelt");
                mIsValid = false;
                memset(mMetrics, 0, sizeof(*mMetrics));
                return;
            }

            mMetrics->xHeight =
                ROUND((float)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
            mMetrics->superscriptOffset = mMetrics->xHeight;
            mMetrics->subscriptOffset = mMetrics->xHeight;
            mMetrics->strikeoutSize = 1;
            mMetrics->strikeoutOffset = ROUND(mMetrics->xHeight * 0.5f); // 50% of xHeight
            mMetrics->underlineSize = 1;
            mMetrics->underlineOffset = -ROUND((float)metrics.tmDescent * 0.30f); // 30% of descent
            mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
            mMetrics->emAscent = metrics.tmAscent - metrics.tmInternalLeading;
            mMetrics->emDescent = metrics.tmDescent;
        }

        mMetrics->internalLeading = metrics.tmInternalLeading;
        mMetrics->externalLeading = metrics.tmExternalLeading;
        mMetrics->maxHeight = metrics.tmHeight;
        mMetrics->maxAscent = metrics.tmAscent;
        mMetrics->maxDescent = metrics.tmDescent;
        mMetrics->maxAdvance = metrics.tmMaxCharWidth;
        mMetrics->aveCharWidth = NS_MAX<gfxFloat>(1, metrics.tmAveCharWidth);
        // The font is monospace when TMPF_FIXED_PITCH is *not* set!
        // See http://msdn2.microsoft.com/en-us/library/ms534202(VS.85).aspx
        if (!(metrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
            mMetrics->maxAdvance = mMetrics->aveCharWidth;
        }

        // Cache the width of a single space.
        SIZE size;
        GetTextExtentPoint32W(dc.GetDC(), L" ", 1, &size);
        mMetrics->spaceWidth = ROUND(size.cx);

        // Cache the width of digit zero.
        // XXX MSDN (http://msdn.microsoft.com/en-us/library/ms534223.aspx)
        // does not say what the failure modes for GetTextExtentPoint32 are -
        // is it safe to assume it will fail iff the font has no '0'?
        if (GetTextExtentPoint32W(dc.GetDC(), L"0", 1, &size)) {
            mMetrics->zeroOrAveCharWidth = ROUND(size.cx);
        } else {
            mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
        }

        mSpaceGlyph = 0;
        if (metrics.tmPitchAndFamily & TMPF_TRUETYPE) {
            WORD glyph;
            DWORD ret = GetGlyphIndicesW(dc.GetDC(), L" ", 1, &glyph,
                                         GGI_MARK_NONEXISTING_GLYPHS);
            if (ret != GDI_ERROR && glyph != 0xFFFF) {
                mSpaceGlyph = glyph;
            }
        }

        SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
    }

    if (IsSyntheticBold()) {
        mMetrics->aveCharWidth += GetSyntheticBoldOffset();
        mMetrics->maxAdvance += GetSyntheticBoldOffset();
    }

    mFontFace = cairo_win32_font_face_create_for_logfontw_hfont(&logFont,
                                                                mFont);

    cairo_matrix_t sizeMatrix, ctm;
    cairo_matrix_init_identity(&ctm);
    cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);

    if (useCairoFakeItalic) {
        // Skew the matrix to do fake italic if it wasn't already applied
        // via the LOGFONT
        double skewfactor = OBLIQUE_SKEW_FACTOR;
        cairo_matrix_t style;
        cairo_matrix_init(&style,
                          1,                //xx
                          0,                //yx
                          -1 * skewfactor,  //xy
                          1,                //yy
                          0,                //x0
                          0);               //y0
        cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
    }

    cairo_font_options_t *fontOptions = cairo_font_options_create();
    if (mAntialiasOption != kAntialiasDefault) {
        cairo_font_options_set_antialias(fontOptions,
            GetCairoAntialiasOption(mAntialiasOption));
    }
    mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix,
                                           &ctm, fontOptions);
    cairo_font_options_destroy(fontOptions);

    if (!mScaledFont ||
        cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
#ifdef DEBUG
        char warnBuf[1024];
        sprintf(warnBuf, "Failed to create scaled font: %s status: %d",
                NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(),
                mScaledFont ? cairo_scaled_font_status(mScaledFont) : 0);
        NS_WARNING(warnBuf);
#endif
        mIsValid = false;
    } else {
        mIsValid = true;
    }

#if 0
    printf("Font: %p (%s) size: %f adjusted size: %f valid: %s\n", this,
           NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size, mAdjustedSize, (mIsValid ? "yes" : "no"));
    printf("    emHeight: %f emAscent: %f emDescent: %f\n", mMetrics->emHeight, mMetrics->emAscent, mMetrics->emDescent);
    printf("    maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics->maxAscent, mMetrics->maxDescent, mMetrics->maxAdvance);
    printf("    internalLeading: %f externalLeading: %f\n", mMetrics->internalLeading, mMetrics->externalLeading);
    printf("    spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics->spaceWidth, mMetrics->aveCharWidth, mMetrics->xHeight);
    printf("    uOff: %f uSize: %f stOff: %f stSize: %f supOff: %f subOff: %f\n",
           mMetrics->underlineOffset, mMetrics->underlineSize, mMetrics->strikeoutOffset, mMetrics->strikeoutSize,
           mMetrics->superscriptOffset, mMetrics->subscriptOffset);
#endif
}