static cairo_status_t _cairo_user_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **scaled_font) { cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_user_font_face_t *font_face = abstract_face; cairo_user_scaled_font_t *user_scaled_font = NULL; cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.}; font_face->immutable = TRUE; user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t)); if (user_scaled_font == NULL) return CAIRO_STATUS_NO_MEMORY; status = _cairo_scaled_font_init (&user_scaled_font->base, &font_face->base, font_matrix, ctm, options, &cairo_user_scaled_font_backend); if (status) { free (user_scaled_font); return status; } /* XXX metrics hinting? */ /* compute a normalized version of font scale matrix to compute * extents in. This is to minimize error caused by the cairo_fixed_t * representation. */ { double fixed_scale, x_scale, y_scale; user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse; status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale, &x_scale, &y_scale, 1); if (status == CAIRO_STATUS_SUCCESS) { if (x_scale == 0) x_scale = 1.; if (y_scale == 0) y_scale = 1.; user_scaled_font->snap_x_scale = x_scale; user_scaled_font->snap_y_scale = y_scale; /* since glyphs are pretty much 1.0x1.0, we can reduce error by * scaling to a larger square. say, 1024.x1024. */ fixed_scale = 1024.; x_scale /= fixed_scale; y_scale /= fixed_scale; cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale); user_scaled_font->extent_x_scale = x_scale; user_scaled_font->extent_y_scale = y_scale; } } if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) { cairo_t *cr; /* Lock the scaled_font mutex such that user doesn't accidentally try * to use it just yet. */ CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex); /* Give away fontmap lock such that user-font can use other fonts */ _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font); status = font_face->scaled_font_methods.init (&user_scaled_font->base, cr, &font_extents); if (status == CAIRO_STATUS_SUCCESS) status = cairo_status (cr); cairo_destroy (cr); _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base); CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex); } if (status == CAIRO_STATUS_SUCCESS) status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents); if (status != CAIRO_STATUS_SUCCESS) { _cairo_scaled_font_fini (&user_scaled_font->base); free (user_scaled_font); } else { user_scaled_font->default_glyph_extents.x_bearing = 0.; user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent; user_scaled_font->default_glyph_extents.width = 0.; user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent; user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance; user_scaled_font->default_glyph_extents.y_advance = 0.; *scaled_font = &user_scaled_font->base; } return status; }
static cairo_status_t _cairo_quartz_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **font_out) { cairo_quartz_font_face_t *font_face = abstract_face; cairo_quartz_scaled_font_t *font = NULL; cairo_status_t status; cairo_font_extents_t fs_metrics; double ems; CGRect bbox; quartz_font_ensure_symbols(); if (!_cairo_quartz_font_symbols_present) return _cairo_error (CAIRO_STATUS_NO_MEMORY); font = malloc(sizeof(cairo_quartz_scaled_font_t)); if (font == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memset (font, 0, sizeof(cairo_quartz_scaled_font_t)); status = _cairo_scaled_font_init (&font->base, &font_face->base, font_matrix, ctm, options, &_cairo_quartz_scaled_font_backend); if (status) goto FINISH; ems = CGFontGetUnitsPerEmPtr (font_face->cgFont); /* initialize metrics */ if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) { fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems); fs_metrics.descent = - (CGFontGetDescentPtr (font_face->cgFont) / ems); fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (CGFontGetLeadingPtr (font_face->cgFont) / ems); bbox = CGFontGetFontBBoxPtr (font_face->cgFont); fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; fs_metrics.max_y_advance = 0.0; } else { CGGlyph wGlyph; UniChar u; quartz_CGFontMetrics *m; m = CGFontGetHMetricsPtr (font_face->cgFont); /* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */ if (!m) { status = _cairo_error(CAIRO_STATUS_NULL_POINTER); goto FINISH; } fs_metrics.ascent = (m->ascent / ems); fs_metrics.descent = - (m->descent / ems); fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems); /* We kind of have to guess here; W's big, right? */ u = (UniChar) 'W'; CGFontGetGlyphsForUnicharsPtr (font_face->cgFont, &u, &wGlyph, 1); if (wGlyph && CGFontGetGlyphBBoxesPtr (font_face->cgFont, &wGlyph, 1, &bbox)) { fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; fs_metrics.max_y_advance = 0.0; } else { fs_metrics.max_x_advance = 0.0; fs_metrics.max_y_advance = 0.0; } } status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics); FINISH: if (status != CAIRO_STATUS_SUCCESS) { free (font); } else { *font_out = (cairo_scaled_font_t*) font; } return status; }
static cairo_status_t _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **font) { cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face); // Must do malloc and not C++ new, since Cairo frees this. cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t)); *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont); _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend); cairo_font_extents_t extents; DWRITE_FONT_METRICS metrics; font_face->dwriteface->GetMetrics(&metrics); extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm; extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm; extents.height = (FLOAT)(metrics.ascent + metrics.descent + metrics.lineGap) / metrics.designUnitsPerEm; extents.max_x_advance = 14.0; extents.max_y_advance = 0.0; dwriteFont->mat = dwriteFont->base.ctm; cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix); dwriteFont->mat_inverse = dwriteFont->mat; cairo_matrix_invert (&dwriteFont->mat_inverse); cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL; dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL; // The following code detects the system quality at scaled_font creation time, // this means that if cleartype settings are changed but the scaled_fonts // are re-used, they might not adhere to the new system setting until re- // creation. switch (_cairo_win32_get_system_text_quality()) { case CLEARTYPE_QUALITY: default_quality = CAIRO_ANTIALIAS_SUBPIXEL; break; case ANTIALIASED_QUALITY: default_quality = CAIRO_ANTIALIAS_GRAY; dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC; break; case DEFAULT_QUALITY: // _get_system_quality() seems to think aliased is default! default_quality = CAIRO_ANTIALIAS_NONE; dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC; break; } if (default_quality == CAIRO_ANTIALIAS_GRAY) { if (!do_grayscale(font_face->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) { default_quality = CAIRO_ANTIALIAS_NONE; } } if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) { dwriteFont->antialias_mode = default_quality; } else { dwriteFont->antialias_mode = options->antialias; } dwriteFont->manual_show_glyphs_allowed = TRUE; return _cairo_scaled_font_set_metrics (*font, &extents); }
static cairo_status_t _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **font_out) { cairo_atsui_font_t *font = NULL; ATSUStyle style; ATSUFontID fontID; OSStatus err; Boolean isItalic, isBold; cairo_matrix_t scale; const char *family = toy_face->family; err = ATSUCreateStyle(&style); switch (toy_face->weight) { case CAIRO_FONT_WEIGHT_BOLD: isBold = true; break; case CAIRO_FONT_WEIGHT_NORMAL: default: isBold = false; break; } switch (toy_face->slant) { case CAIRO_FONT_SLANT_ITALIC: isItalic = true; break; case CAIRO_FONT_SLANT_OBLIQUE: isItalic = false; break; case CAIRO_FONT_SLANT_NORMAL: default: isItalic = false; break; } err = ATSUFindFontFromName(family, strlen(family), kFontFamilyName, kFontNoPlatformCode, kFontRomanScript, kFontNoLanguageCode, &fontID); if (err != noErr) { // couldn't get the font - remap css names and try again if (!strcmp(family, "serif")) family = "Times"; else if (!strcmp(family, "sans-serif")) family = "Helvetica"; else if (!strcmp(family, "cursive")) family = "Apple Chancery"; else if (!strcmp(family, "fantasy")) family = "Gadget"; else if (!strcmp(family, "monospace")) family = "Courier"; else // anything else - return error instead? family = "Courier"; err = ATSUFindFontFromName(family, strlen(family), kFontFamilyName, kFontNoPlatformCode, kFontRomanScript, kFontNoLanguageCode, &fontID); } ATSUAttributeTag styleTags[] = { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag }; ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID }; ByteCount styleSizes[] = { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) }; err = ATSUSetAttributes(style, sizeof(styleTags) / sizeof(styleTags[0]), styleTags, styleSizes, styleValues); font = malloc(sizeof(cairo_atsui_font_t)); _cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options, &cairo_atsui_scaled_font_backend); cairo_matrix_multiply(&scale, font_matrix, ctm); font->style = CreateSizedCopyOfStyle(style, &scale); Fixed theSize = FloatToFixed(1.0); const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; err = ATSUSetAttributes(style, sizeof(theFontStyleTags) / sizeof(ATSUAttributeTag), theFontStyleTags, theFontStyleSizes, theFontStyleValues); font->unscaled_style = style; font->fontID = fontID; font->scale = scale; *font_out = &font->base; return CAIRO_STATUS_SUCCESS; }