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; }
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))); }
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); }
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); }
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())); }
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); }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
FontFace* ScaledFont::getFontFace() { return new FontFace( cairo_scaled_font_get_font_face( mCairoScaledFont ) ); }