Esempio n. 1
1
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);
}
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;
}
Esempio n. 3
0
static PyObject *
scaled_font_get_font_face (PycairoScaledFont *o)
{
    return PycairoFontFace_FromFontFace (
               cairo_font_face_reference (
		   cairo_scaled_font_get_font_face (o->scaled_font)));
}
Esempio n. 4
0
static cairo_status_t font_init_cb (cairo_scaled_font_t  *scaled_font,
                                    cairo_t */*cairo*/, cairo_font_extents_t *metrics){
    cairo_font_face_t*  face;
    face = cairo_scaled_font_get_font_face(scaled_font);
    SvgFont* instance = (SvgFont*) cairo_font_face_get_user_data(face, &key);
    return instance->scaled_font_init(scaled_font, metrics);
}
Esempio n. 5
0
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    ASSERT(m_platformData.scaledFont());
    return SimpleFontData::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
                                                        scaleFactor * fontDescription.computedSize(),
                                                        m_platformData.syntheticBold(),
                                                        m_platformData.syntheticOblique()), isCustomFont(), false);
}
Esempio n. 6
0
FontPlatformData::FontPlatformData(const FontPlatformData& other, float size)
{
    *this = other;

    // We need to reinitialize the instance, because the difference in size 
    // necessitates a new scaled font instance.
    m_size = size;
    initializeWithFontFace(cairo_scaled_font_get_font_face(m_scaledFont.get()));
}
Esempio n. 7
0
static cairo_status_t font_render_glyph_cb (cairo_scaled_font_t  *scaled_font,
                                            unsigned long         glyph,
                                            cairo_t              *cr,
                                            cairo_text_extents_t *metrics){
    cairo_font_face_t*  face;
    face = cairo_scaled_font_get_font_face(scaled_font);
    SvgFont* instance = (SvgFont*) cairo_font_face_get_user_data(face, &key);
    return instance->scaled_font_render_glyph(scaled_font, glyph, cr, metrics);
}
Esempio n. 8
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;
}
static cairo_quartz_font_face_t *
_cairo_quartz_scaled_to_face (void *abstract_font)
{
    cairo_quartz_scaled_font_t *sfont = (cairo_quartz_scaled_font_t*) abstract_font;
    cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (&sfont->base);
    if (!font_face || font_face->backend->type != CAIRO_FONT_TYPE_QUARTZ)
	return NULL;

    return (cairo_quartz_font_face_t*) font_face;
}
Esempio n. 10
0
static cairo_status_t font_text_to_glyphs_cb ( cairo_scaled_font_t  *scaled_font,
                                               const char           *utf8,
                                               int                  utf8_len,
                                               cairo_glyph_t        **glyphs,
                                               int                  *num_glyphs,
                                               cairo_text_cluster_t **clusters,
                                               int                  *num_clusters,
                                               cairo_text_cluster_flags_t *flags){
    cairo_font_face_t*  face;
    face = cairo_scaled_font_get_font_face(scaled_font);
    SvgFont* instance = (SvgFont*) cairo_font_face_get_user_data(face, &key);
    return instance->scaled_font_text_to_glyphs(scaled_font, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, flags);
}
Esempio n. 11
0
static cairo_status_t
cr_user_font_face_unicode_to_glyph_func (cairo_scaled_font_t *scaled_font,
                                         unsigned long unicode,
                                         unsigned long *glyph_index)
{
  cairo_status_t status = CAIRO_STATUS_SUCCESS;
  cairo_font_face_t *face;
  VALUE self;
  VALUE receiver = Qnil;
  ID id_method_name = cr_id_call;

  face = cairo_scaled_font_get_font_face (scaled_font);
  self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
  receiver = rb_ivar_get (self, cr_id_unicode_to_glyph);
  if (NIL_P (receiver) &&
      rb_obj_respond_to (self, cr_id_unicode_to_glyph, Qtrue))
    {
      receiver = self;
      id_method_name = cr_id_unicode_to_glyph;
    }

  if (NIL_P (receiver))
    {
      *glyph_index = unicode;
    }
  else
    {
      cr_user_font_face_invoke_data_t data;
      VALUE argv[2];

      argv[0] = CRSCALEDFONT2RVAL (scaled_font);
      argv[1] = ULONG2NUM (unicode);

      data.receiver = receiver;
      data.method = id_method_name;
      data.argc = 2;
      data.argv = argv;
      data.status = &status;
      data.after_hook = cr_user_font_face_unicode_to_glyph_func_after;
      data.after_hook_data = glyph_index;

      rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
    }

  return status;
}
Esempio n. 12
0
static cairo_status_t
twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
				     cairo_t           *cr)
{
    cairo_status_t status;
    twin_scaled_properties_t *props;

    props = malloc (sizeof (twin_scaled_properties_t));
    if (unlikely (props == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);


    props->face_props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
						       &twin_properties_key);

    props->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;

    /* weight */
    props->weight = props->face_props->weight * (F (4) / TWIN_WEIGHT_NORMAL);

    /* pen & margins */
    props->penx = props->peny = props->weight;
    props->marginl = props->marginr = F (4);
    if (scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT)
	twin_hint_pen_and_margins(cr,
				  &props->penx, &props->peny,
				  &props->marginl, &props->marginr);

    /* stretch */
    props->stretch = 1 + .1 * ((int) props->face_props->stretch - (int) TWIN_STRETCH_NORMAL);


    /* Save it */
    status = cairo_scaled_font_set_user_data (scaled_font,
					      &twin_properties_key,
					      props, free);
    if (unlikely (status))
	goto FREE_PROPS;

    return CAIRO_STATUS_SUCCESS;

FREE_PROPS:
    free (props);
    return status;
}
Esempio n. 13
0
SkTypeface* SkCreateTypefaceFromCairoFTFontWithFontconfig(cairo_scaled_font_t* scaledFont, FcPattern* pattern)
{
    cairo_font_face_t* fontFace = cairo_scaled_font_get_font_face(scaledFont);
    SkASSERT(cairo_font_face_status(fontFace) == CAIRO_STATUS_SUCCESS);

    SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey));
    if (typeface) {
        typeface->ref();
    } else {
        CairoLockedFTFace faceLock(scaledFont);
        if (FT_Face face = faceLock.getFace()) {
            typeface = SkCairoFTTypeface::CreateTypeface(fontFace, face, pattern);
            SkTypefaceCache::Add(typeface, typeface->fontStyle());
        }
    }

    return typeface;
}
Esempio n. 14
0
static cairo_status_t
test_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
				   unsigned long        unicode,
				   unsigned long       *glyph)
{
    test_scaled_font_glyph_t *glyphs = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
								      &test_font_face_glyphs_key);
    int i;

    for (i = 0; glyphs[i].ucs4 != (unsigned long) -1; i++)
	if (glyphs[i].ucs4 == unicode) {
	    *glyph = i;
	    return CAIRO_STATUS_SUCCESS;
	}

    /* Not found.  Default to glyph 0 */
    return CAIRO_STATUS_SUCCESS;
}
Esempio n. 15
0
static cairo_status_t
test_scaled_font_init (cairo_scaled_font_t  *scaled_font,
		       cairo_t              *cr,
		       cairo_font_extents_t *extents)
{
    cairo_set_font_face (cr,
			 cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
							&fallback_font_key));

    cairo_scaled_font_set_user_data (scaled_font,
				     &fallback_font_key,
				     cairo_scaled_font_reference (cairo_get_scaled_font (cr)),
				     (cairo_destroy_func_t) cairo_scaled_font_destroy);

    cairo_font_extents (cr, extents);

    return CAIRO_STATUS_SUCCESS;
}
Esempio n. 16
0
static cairo_status_t
cr_user_font_face_render_glyph_func (cairo_scaled_font_t *scaled_font,
                                     unsigned long glyph,
                                     cairo_t *cr,
                                     cairo_text_extents_t *extents)
{
  cairo_status_t status = CAIRO_STATUS_SUCCESS;
  cairo_font_face_t *face;
  VALUE self;
  VALUE receiver = Qnil;
  ID id_method_name = cr_id_call;

  face = cairo_scaled_font_get_font_face (scaled_font);
  self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
  receiver = rb_ivar_get (self, cr_id_render_glyph);
  if (NIL_P (receiver) && rb_obj_respond_to (self, cr_id_render_glyph, Qtrue))
    {
      receiver = self;
      id_method_name = cr_id_render_glyph;
    }

  if (!NIL_P (receiver))
    {
      cr_user_font_face_invoke_data_t data;
      VALUE argv[4];

      argv[0] = CRSCALEDFONT2RVAL (scaled_font);
      argv[1] = ULONG2NUM (glyph);
      argv[2] = CRCONTEXT2RVAL (cr);
      argv[3] = CRTEXTEXTENTS2RVAL (extents);

      data.receiver = receiver;
      data.method = id_method_name;
      data.argc = 4;
      data.argv = argv;
      data.status = &status;
      data.after_hook = cr_user_font_face_render_glyph_func_after;
      data.after_hook_data = extents;

      rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
    }

  return status;
}
Esempio n. 17
0
static cairo_status_t
test_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
			       unsigned long         glyph,
			       cairo_t              *cr,
			       cairo_text_extents_t *extents)
{
    cairo_glyph_t cairo_glyph;

    cairo_glyph.index = glyph;
    cairo_glyph.x = 0;
    cairo_glyph.y = 0;

    cairo_set_font_face (cr,
			 cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
							&fallback_font_key));

    cairo_show_glyphs (cr, &cairo_glyph, 1);
    cairo_glyph_extents (cr, &cairo_glyph, 1, extents);

    return CAIRO_STATUS_SUCCESS;
}
Esempio n. 18
0
static cairo_status_t
test_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
			       unsigned long         glyph,
			       cairo_t              *cr,
			       cairo_text_extents_t *metrics)
{
    test_scaled_font_glyph_t *glyphs = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
								      &test_font_face_glyphs_key);
    int i;
    unsigned char *data;
    cairo_surface_t *image;
    cairo_pattern_t *pattern;
    cairo_matrix_t matrix;
    uint8_t byte;

    /* FIXME: We simply crash on out-of-bound glyph indices */

    metrics->x_advance = (glyphs[glyph].width + 1) / 8.0;

    image = cairo_image_surface_create (CAIRO_FORMAT_A1, glyphs[glyph].width, 8);
    data = cairo_image_surface_get_data (image);
    for (i = 0; i < 8; i++) {
	byte = glyphs[glyph].data[i];
	*data = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (byte);
	data += cairo_image_surface_get_stride (image);
    }

    pattern = cairo_pattern_create_for_surface (image);
    cairo_matrix_init_identity (&matrix);
    cairo_matrix_scale (&matrix, 1.0/8.0, 1.0/8.0);
    cairo_matrix_translate (&matrix, 0, -8);
    cairo_matrix_invert (&matrix);
    cairo_pattern_set_matrix (pattern, &matrix);
    cairo_set_source (cr, pattern);
    cairo_mask (cr, pattern);
    cairo_pattern_destroy (pattern);
    cairo_surface_destroy (image);

    return CAIRO_STATUS_SUCCESS;
}
cairo_private 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,
                                      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_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);
        if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
                                        (cairo_hash_entry_t **) &sub_font))
        {
            status = _cairo_sub_font_lookup_glyph (sub_font,
                                                   scaled_font_glyph_index,
                                                   subset_glyph);
            if (status == CAIRO_STATUS_SUCCESS)
                return CAIRO_STATUS_SUCCESS;
        }
    }

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

    /* Glyph not found. Determine whether the glyph is outline or
     * bitmap and add to the appropriate subset */
    status = _cairo_scaled_glyph_lookup (scaled_font,
                                         scaled_font_glyph_index,
					 CAIRO_SCALED_GLYPH_INFO_PATH,
                                         &scaled_glyph);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
        return status;

    if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
        /* Path available. Add to unscaled subset. */
        key.is_scaled = FALSE;
        _cairo_sub_font_init_key (&key, scaled_font);
        if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
                                        (cairo_hash_entry_t **) &sub_font))
        {
            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 (unscaled_font->status)
		return unscaled_font->status;

            subset_glyph->is_scaled = FALSE;
            type1_font = FALSE;
#if CAIRO_HAS_FT_FONT
            type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
#endif
            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;
            }

            sub_font = _cairo_sub_font_create (subsets,
                                               unscaled_font,
                                               subsets->num_sub_fonts++,
                                               max_glyphs,
                                               subset_glyph->is_scaled,
                                               subset_glyph->is_composite);
            if (sub_font == NULL) {
		cairo_scaled_font_destroy (unscaled_font);
                return CAIRO_STATUS_NO_MEMORY;
	    }

            status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
                                               &sub_font->base);
            if (status) {
		_cairo_sub_font_destroy (sub_font);
                return status;
	    }
        }
    } else {
        /* No path available. Add to scaled subset. */
        key.is_scaled = TRUE;
        _cairo_sub_font_init_key (&key, scaled_font);
        if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
                                        (cairo_hash_entry_t **) &sub_font))
        {
            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;

            sub_font = _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);
            if (sub_font == NULL) {
		cairo_scaled_font_destroy (scaled_font);
                return CAIRO_STATUS_NO_MEMORY;
	    }

            status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
                                               &sub_font->base);
            if (status) {
		_cairo_sub_font_destroy (sub_font);
                return status;
	    }
        }
    }

    return _cairo_sub_font_map_glyph (sub_font,
                                      scaled_font_glyph_index,
                                      subset_glyph);
}
Esempio n. 20
0
static cairo_status_t
cr_user_font_face_text_to_glyphs_func (cairo_scaled_font_t *scaled_font,
                                       const char *utf8, int utf8_len,
                                       cairo_glyph_t **glyphs, int *num_glyphs,
                                       cairo_text_cluster_t **clusters,
                                       int *num_clusters,
                                       cairo_text_cluster_flags_t *cluster_flags)
{
  cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
  cairo_font_face_t *face;
  VALUE self;
  VALUE receiver = Qnil;
  ID id_method_name = cr_id_call;

  face = cairo_scaled_font_get_font_face (scaled_font);
  self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
  receiver = rb_ivar_get (self, cr_id_text_to_glyphs);
  if (NIL_P (receiver) && rb_obj_respond_to (self, cr_id_text_to_glyphs, Qtrue))
    {
      receiver = self;
      id_method_name = cr_id_text_to_glyphs;
    }

  if (NIL_P (receiver))
    {
      if (num_glyphs)
        *num_glyphs = -1;
    }
  else
    {
      cr_user_font_face_invoke_data_t data;
      cr_text_to_glyphs_after_hook_data_t after_hook_data;
      VALUE text_to_glyphs_data;
      VALUE argv[3];

      argv[0] = CRSCALEDFONT2RVAL (scaled_font);
      argv[1] = rb_str_new (utf8, utf8_len);
      text_to_glyphs_data = rb_funcall (rb_cCairo_UserFontFace_TextToGlyphsData,
                                        cr_id_new,
                                        3,
                                        CBOOL2RVAL (glyphs != NULL),
                                        CBOOL2RVAL (clusters != NULL),
                                        CBOOL2RVAL (cluster_flags != NULL));
      argv[2] = text_to_glyphs_data;

      data.receiver = receiver;
      data.method = id_method_name;
      data.argc = 3;
      data.argv = argv;
      data.status = &status;
      data.after_hook = cr_user_font_face_text_to_glyphs_func_after;
      data.after_hook_data = &after_hook_data;

      after_hook_data.text_to_glyphs_data = text_to_glyphs_data;
      after_hook_data.glyphs = glyphs;
      after_hook_data.num_glyphs = num_glyphs;
      after_hook_data.clusters = clusters;
      after_hook_data.num_clusters = num_clusters;
      after_hook_data.cluster_flags = cluster_flags;

      rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
    }

  return status;
}
Esempio n. 21
0
PRUint32
gfxFT2FontBase::GetGlyph(PRUint32 aCharCode)
{
    // FcFreeTypeCharIndex needs to lock the FT_Face and can end up searching
    // through all the postscript glyph names in the font.  Therefore use a
    // lightweight cache, which is stored on the cairo_font_face_t.

    cairo_font_face_t *face =
        cairo_scaled_font_get_font_face(CairoScaledFont());

    if (cairo_font_face_status(face) != CAIRO_STATUS_SUCCESS)
        return 0;

    // This cache algorithm and size is based on what is done in
    // cairo_scaled_font_text_to_glyphs and pango_fc_font_real_get_glyph.  I
    // think the concept is that adjacent characters probably come mostly from
    // one Unicode block.  This assumption is probably not so valid with
    // scripts with large character sets as used for East Asian languages.

    struct CmapCacheSlot {
        PRUint32 mCharCode;
        PRUint32 mGlyphIndex;
    };
    const PRUint32 kNumSlots = 256;
    static cairo_user_data_key_t sCmapCacheKey;

    CmapCacheSlot *slots = static_cast<CmapCacheSlot*>
        (cairo_font_face_get_user_data(face, &sCmapCacheKey));

    if (!slots) {
        // cairo's caches can keep some cairo_font_faces alive past our last
        // destroy, so the destroy function (free) for the cache must be
        // callable from cairo without any assumptions about what other
        // modules have not been shutdown.
        slots = static_cast<CmapCacheSlot*>
            (calloc(kNumSlots, sizeof(CmapCacheSlot)));
        if (!slots)
            return 0;

        cairo_status_t status =
            cairo_font_face_set_user_data(face, &sCmapCacheKey, slots, free);
        if (status != CAIRO_STATUS_SUCCESS) { // OOM
            free(slots);
            return 0;
        }

        // Invalidate slot 0 by setting its char code to something that would
        // never end up in slot 0.  All other slots are already invalid
        // because they have mCharCode = 0 and a glyph for char code 0 will
        // always be in the slot 0.
        slots[0].mCharCode = 1;
    }

    CmapCacheSlot *slot = &slots[aCharCode % kNumSlots];
    if (slot->mCharCode != aCharCode) {
        slot->mCharCode = aCharCode;
        slot->mGlyphIndex = gfxFT2LockedFace(this).GetGlyph(aCharCode);
    }

    return slot->mGlyphIndex;
}
Esempio n. 22
0
FontFace* ScaledFont::getFontFace()
{
	return new FontFace( cairo_scaled_font_get_font_face( mCairoScaledFont ) );
}