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 unicodeSetFont(char *fontName, int fontSize, int boldFlag, int italicFlag, int antiAliasFlag) { char description[200]; g_sprintf(description, "%s, %s %s %dpx", fontName, (boldFlag ? "bold" : ""), (italicFlag ? "italic" : ""), fontSize); if (fontDescr != NULL) pango_font_description_free(fontDescr); fontDescr = pango_font_description_from_string(description); if (fontOptions == NULL) { fontOptions = cairo_font_options_create(); // Note: On Mac OS, the default hint style and metrics looked the best. Also, using // the default allows the user to control the look via the OS settings. /* styles: CAIRO_HINT_STYLE_DEFAULT Use the default hint style for for font backend and target device CAIRO_HINT_STYLE_NONE Do not hint outlines CAIRO_HINT_STYLE_SLIGHT Hint outlines slightly to improve contrast while retaining good fidelity to the original shapes. CAIRO_HINT_STYLE_MEDIUM Hint outlines with medium strength giving a compromise between fidelity to the original shapes and contrast CAIRO_HINT_STYLE_FULL Hint outlines to maximize contrast metrics: CAIRO_HINT_METRICS_DEFAULT Hint metrics in the default manner for the font backend and target device CAIRO_HINT_METRICS_OFF Do not hint font metrics CAIRO_HINT_METRICS_ON Hint font metrics */ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_DEFAULT); cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_DEFAULT); } cairo_font_options_set_antialias(fontOptions, antiAliasFlag ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE); }
static VALUE cr_options_set_hint_metrics (VALUE self, VALUE hint_metrics) { cairo_font_options_set_hint_metrics (_SELF (self), RVAL2CRHINTMETRICS (hint_metrics)); return self; }
ttext::ttext() : #if PANGO_VERSION_CHECK(1,22,0) context_(pango_font_map_create_context(pango_cairo_font_map_get_default())), #else context_(pango_cairo_font_map_create_context(( reinterpret_cast<PangoCairoFontMap*>(pango_cairo_font_map_get_default())))), #endif layout_(pango_layout_new(context_)), rect_(), surface_(), #ifdef SDL_GPU texture_(), #endif text_(), markedup_text_(false), link_aware_(false), link_color_(), font_class_(font::FONT_SANS_SERIF), font_size_(14), font_style_(STYLE_NORMAL), foreground_color_(0xFFFFFFFF), // solid white maximum_width_(-1), characters_per_line_(0), maximum_height_(-1), ellipse_mode_(PANGO_ELLIPSIZE_END), alignment_(PANGO_ALIGN_LEFT), maximum_length_(std::string::npos), calculation_dirty_(true), length_(0), surface_dirty_(true), surface_buffer_(nullptr) { // With 72 dpi the sizes are the same as with SDL_TTF so hardcoded. pango_cairo_context_set_resolution(context_, 72.0); pango_layout_set_ellipsize(layout_, ellipse_mode_); pango_layout_set_alignment(layout_, alignment_); pango_layout_set_wrap(layout_, PANGO_WRAP_WORD_CHAR); /* * Set the pango spacing a bit bigger since the default is deemed to small * http://www.wesnoth.org/forum/viewtopic.php?p=358832#p358832 */ pango_layout_set_spacing(layout_, 2 * PANGO_SCALE); cairo_font_options_t *fo = cairo_font_options_create(); cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(fo, CAIRO_HINT_METRICS_ON); #ifdef _WIN32 // Cairo on Windows (at least the latest available version from gtk.org // as of 2014-02-22, version 1.10.2) has issues with ClearType resulting // in glitchy anti-aliasing with CAIRO_ANTIALIAS_SUBPIXEL or // CAIRO_ANTIALIAS_DEFAULT, but not CAIRO_ANTIALIAS_GRAY, so we use that // as a workaround until the Windows package is updated to use a newer // version of Cairo (see Wesnoth bug #21648). cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); #endif pango_cairo_context_set_font_options(context_, fo); cairo_font_options_destroy(fo); }
static void _cairo_image_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options) { _cairo_font_options_init_default (options); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); }
void _cairo_image_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options) { _cairo_font_options_init_default (options); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_text_extents_t extents; cairo_font_options_t *font_options; const char text[] = "cairo"; int x_off, y_off; cairo_matrix_t m; /* paint white so we don't need separate ref images for * RGB24 and ARGB32 */ cairo_set_source_rgb (cr, 1., 1., 1.); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0, 0, 0); cairo_translate (cr, WIDTH/2.0, HEIGHT/2.0); cairo_text_extents (cr, text, &extents); if (NUM_TEXT == 1) { x_off = y_off = 0; } else { y_off = - floor (0.5 + extents.height / 2.0); x_off = floor (0.5 + (extents.height+1) / (2 * tan (M_PI/NUM_TEXT))); } cairo_save (cr); cairo_matrix_init_identity (&m); draw_quadrant (cr, text, &extents, &m, x_off, y_off); cairo_matrix_init (&m, 0, 1, -1, 0, 0, 0); draw_quadrant (cr, text, &extents, &m, x_off, y_off); cairo_restore (cr); cairo_save (cr); cairo_scale (cr, -1, -1); cairo_matrix_init_identity (&m); draw_quadrant (cr, text, &extents, &m, x_off, y_off); cairo_matrix_init (&m, 0, 1, -1, 0, 0, 0); draw_quadrant (cr, text, &extents, &m, x_off, y_off); cairo_restore (cr); return CAIRO_TEST_SUCCESS; }
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 PyObject * font_options_set_hint_metrics (PycairoFontOptions *o, PyObject *args) { cairo_hint_metrics_t hm = CAIRO_HINT_METRICS_DEFAULT; if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_metrics", &hm)) return NULL; cairo_font_options_set_hint_metrics (o->font_options, hm); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; }
static PyObject * font_options_set_hint_metrics (PycairoFontOptions *o, PyObject *args) { cairo_hint_metrics_t hm = CAIRO_HINT_METRICS_DEFAULT; if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_metrics", &hm)) return NULL; cairo_font_options_set_hint_metrics (o->font_options, hm); if (Pycairo_Check_Status (cairo_font_options_status (o->font_options))) return NULL; Py_RETURN_NONE; }
ttext::ttext() : #if PANGO_VERSION_CHECK(1,22,0) context_(pango_font_map_create_context(pango_cairo_font_map_get_default())), #else context_(pango_cairo_font_map_create_context(( reinterpret_cast<PangoCairoFontMap*>(pango_cairo_font_map_get_default())))), #endif layout_(pango_layout_new(context_)), rect_(), surface_(), text_(), markedup_text_(false), link_aware_(false), link_color_(), font_class_(font::FONT_SANS_SERIF), font_size_(14), font_style_(STYLE_NORMAL), foreground_color_(0xFFFFFFFF), // solid white maximum_width_(-1), characters_per_line_(0), maximum_height_(-1), ellipse_mode_(PANGO_ELLIPSIZE_END), alignment_(PANGO_ALIGN_LEFT), maximum_length_(std::string::npos), calculation_dirty_(true), length_(0), surface_dirty_(true), surface_buffer_(nullptr) { // With 72 dpi the sizes are the same as with SDL_TTF so hardcoded. pango_cairo_context_set_resolution(context_, 72.0); pango_layout_set_ellipsize(layout_, ellipse_mode_); pango_layout_set_alignment(layout_, alignment_); pango_layout_set_wrap(layout_, PANGO_WRAP_WORD_CHAR); /* * Set the pango spacing a bit bigger since the default is deemed to small * http://www.wesnoth.org/forum/viewtopic.php?p=358832#p358832 */ pango_layout_set_spacing(layout_, 4 * PANGO_SCALE); cairo_font_options_t *fo = cairo_font_options_create(); cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(fo, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_DEFAULT); pango_cairo_context_set_font_options(context_, fo); cairo_font_options_destroy(fo); }
static void lsm_dom_view_set_cairo_context (LsmDomView *view, cairo_t *cairo) { PangoContext *context; cairo_font_options_t *font_options; const cairo_font_options_t *current_font_options; cairo_surface_t *surface; cairo_surface_type_t type; g_return_if_fail (LSM_IS_DOM_VIEW (view)); if (view->cairo == cairo) return; if (view->cairo != NULL) { cairo_destroy (view->cairo); g_object_unref (view->pango_layout); } if (cairo == NULL) { view->cairo = NULL; view->pango_layout = NULL; return; } cairo_reference (cairo); view->cairo = cairo; view->pango_layout = pango_cairo_create_layout (cairo); surface = cairo_get_target (cairo); type = cairo_surface_get_type (surface); view->is_vector = (type == CAIRO_SURFACE_TYPE_SVG || type == CAIRO_SURFACE_TYPE_PDF || type == CAIRO_SURFACE_TYPE_PS); context = pango_layout_get_context (view->pango_layout); pango_cairo_context_set_resolution (context, 72); current_font_options = pango_cairo_context_get_font_options (context); if (current_font_options == NULL) font_options = cairo_font_options_create (); else font_options = cairo_font_options_copy (current_font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); pango_cairo_context_set_font_options (context, font_options); cairo_font_options_destroy (font_options); }
static inline void _SetUpDrawingTools(const CNFORenderer* r, cairo_surface_t* a_surface, cairo_t** pcr, cairo_font_options_t** pcfo) { cairo_t* cr = cairo_create(a_surface); cairo_font_options_t *cfo = cairo_font_options_create(); cairo_font_options_set_antialias(cfo, (r->GetFontAntiAlias() ? CAIRO_ANTIALIAS_SUBPIXEL : CAIRO_ANTIALIAS_NONE)); cairo_font_options_set_hint_style(cfo, (r->IsClassicMode() ? CAIRO_HINT_STYLE_DEFAULT : CAIRO_HINT_STYLE_NONE)); cairo_font_options_set_hint_metrics(cfo, (r->IsClassicMode() ? CAIRO_HINT_METRICS_ON : CAIRO_HINT_METRICS_OFF)); const std::string l_font #ifdef _UNICODE = CUtil::FromWideStr(r->GetFontFace(), CP_UTF8); #else = r->GetFontFace();
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_font_options_t *font_options; cairo_scaled_font_t *scaled_font; FT_Face face; FT_ULong charcode; FT_UInt idx; int i = 0; cairo_glyph_t glyphs[NUM_GLYPHS]; /* paint white so we don't need separate ref images for * RGB24 and ARGB32 */ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); scaled_font = cairo_get_scaled_font (cr); face = cairo_ft_scaled_font_lock_face (scaled_font); { charcode = FT_Get_First_Char(face, &idx); while (idx && (i < NUM_GLYPHS)) { glyphs[i] = (cairo_glyph_t) {idx, PAD + GRID_SIZE * (i/GRID_ROWS), PAD + TEXT_SIZE + GRID_SIZE * (i%GRID_ROWS)}; i++; charcode = FT_Get_Next_Char(face, charcode, &idx); } } cairo_ft_scaled_font_unlock_face (scaled_font); cairo_show_glyphs(cr, glyphs, i); return CAIRO_TEST_SUCCESS; }
static void lsm_dom_view_init (LsmDomView *view) { PangoFontMap *font_map; PangoContext *pango_context; cairo_font_options_t *font_options; view->resolution_ppi = LSM_DOM_VIEW_DEFAULT_RESOLUTION; view->viewport_pt.x = 0; view->viewport_pt.y = 0; view->viewport_pt.width = LSM_DOM_VIEW_DEFAULT_VIEWBOX_WIDTH; view->viewport_pt.height = LSM_DOM_VIEW_DEFAULT_VIEWBOX_HEIGHT; view->font_description = pango_font_description_new (); font_map = pango_cairo_font_map_get_default (); #if PANGO_VERSION_CHECK(1,22,0) pango_context = pango_font_map_create_context (font_map); #else pango_context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (font_map)); #endif pango_cairo_context_set_resolution (pango_context, 72.0); view->measure_pango_layout = pango_layout_new (pango_context); font_options = cairo_font_options_create (); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); pango_cairo_context_set_font_options (pango_context, font_options); cairo_font_options_destroy (font_options); g_object_unref (pango_context); view->pango_layout = NULL; view->cairo = NULL; view->is_vector = FALSE; }
// Create and add a placement to the current lithograph if it doesn't overlap // with current labels. void simplet_lithograph_add_placement(simplet_lithograph_t *litho, OGRFeatureH feature, simplet_list_t *styles, cairo_t *proj_ctx) { simplet_style_t *field = simplet_lookup_style(styles, "text-field"); if(!field) return; OGRFeatureDefnH defn; if(!(defn = OGR_F_GetDefnRef(feature))) return; int idx = OGR_FD_GetFieldIndex(defn, (const char*) field->arg); if(idx < 0) return; // Find the largest sub geometry of a particular multi-geometry. OGRGeometryH super = OGR_F_GetGeometryRef(feature); OGRGeometryH geom = super; double area = 0.0; switch(wkbFlatten(OGR_G_GetGeometryType(super))) { case wkbMultiPolygon: case wkbGeometryCollection: for(int i = 0; i < OGR_G_GetGeometryCount(super); i++) { OGRGeometryH subgeom = OGR_G_GetGeometryRef(super, i); if(subgeom == NULL) continue; double ar = OGR_G_Area(subgeom); if(ar > area) { geom = subgeom; area = ar; } } break; default: ; } // Find the center of our geometry. This sometimes throws an invalid geometry // error, so there is a slight bug here somehow. OGRGeometryH center; if(!(center = OGR_G_CreateGeometry(wkbPoint))) return; if(OGR_G_Centroid(geom, center) == OGRERR_FAILURE) { OGR_G_DestroyGeometry(center); return; } // Turn font hinting off cairo_font_options_t *opts; if(!(opts = cairo_font_options_create())){ OGR_G_DestroyGeometry(center); return; } cairo_font_options_set_hint_style(opts, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics(opts, CAIRO_HINT_METRICS_OFF); pango_cairo_context_set_font_options(litho->pango_ctx, opts); cairo_font_options_destroy(opts); // Get the field containing the text for the label. char *txt = simplet_copy_string(OGR_F_GetFieldAsString(feature, idx)); PangoLayout *layout = pango_layout_new(litho->pango_ctx); pango_layout_set_text(layout, txt, -1); free(txt); // Grab the font to use and apply tracking. simplet_style_t *font = simplet_lookup_style(styles, "font"); simplet_apply_styles(layout, styles, "letter-spacing", NULL); const char *font_family; if(!font) font_family = "helvetica 12px"; else font_family = font->arg; PangoFontDescription *desc = pango_font_description_from_string(font_family); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); double x = OGR_G_GetX(center, 0), y = OGR_G_GetY(center, 0); cairo_user_to_device(proj_ctx, &x, &y); // Finally try the placement and test for overlaps. try_and_insert_placement(litho, layout, x, y); OGR_G_DestroyGeometry(center); }
void lime_cairo_font_options_set_hint_metrics (value handle, int v) { cairo_font_options_set_hint_metrics ((cairo_font_options_t*)val_data (handle), (cairo_hint_metrics_t)v); }
static boolean pango_textlayout(textpara_t * para, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, para->fontname) != 0 || fontsize != para->fontsize) { fontname = para->fontname; fontsize = para->fontsize; pango_font_description_free (desc); if (para->postscript_alias) { psfnt = fnt = gv_fmap[para->postscript_alias->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (para->postscript_alias); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((para->font) && (flags = para->font->flags)) { char* markup = N_NEW(strlen(para->str) + sizeof(FULL_MARKUP), char); strcpy(markup,"<span"); if (flags & HTML_BF) strcat(markup," weight=\"bold\""); if (flags & HTML_IF) strcat(markup," style=\"italic\""); if (flags & HTML_UL) strcat(markup," underline=\"single\""); strcat (markup,">"); if (flags & HTML_SUP) strcat(markup,"<sup>"); if (flags & HTML_SUB) strcat(markup,"<sub>"); strcat (markup,para->str); if (flags & HTML_SUB) strcat(markup,"</sub>"); if (flags & HTML_SUP) strcat(markup,"</sup>"); strcat (markup,"</span>"); if (!pango_parse_markup (markup, -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = para->str; attrs = NULL; } free (markup); }
/* * render functions */ static void begin_render(DiaRenderer *self, const Rectangle *update) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); real onedu = 0.0; real lmargin = 0.0, tmargin = 0.0; gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */ cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page; if (renderer->surface && !renderer->cr) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); /* remember current state, so we can start from new with every page */ cairo_save (renderer->cr); if (paginated && renderer->dia) { DiagramData *data = renderer->dia; /* Dia's paper.width already contains the scale, cairo needs it without * Similar for margins, Dia's without, but cairo wants them? */ real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin) * (72.0 / 2.54) + 0.5; real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin) * (72.0 / 2.54) + 0.5; /* "Changes the size of a PDF surface for the current (and * subsequent) pages." Pagination setup? */ cairo_pdf_surface_set_size (renderer->surface, width, height); lmargin = data->paper.lmargin / data->paper.scaling; tmargin = data->paper.tmargin / data->paper.scaling; } cairo_scale (renderer->cr, renderer->scale, renderer->scale); /* to ensure no clipping at top/left we need some extra gymnastics, * otherwise a box with a line witdh one one pixel might loose the * top/left border as in bug #147386 */ ensure_minimum_one_device_unit (renderer, &onedu); if (update && paginated) { cairo_rectangle (renderer->cr, lmargin, tmargin, update->right - update->left, update->bottom - update->top); cairo_clip (renderer->cr); cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin); } else cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu); /* no more blurred UML diagrams */ cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
static inline void settings_update_font_options (ClutterSettings *self) { cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE; cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_GRAY; cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; cairo_font_options_t *options; if (self->backend == NULL) return; options = cairo_font_options_create (); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); if (self->xft_hinting >= 0 && self->xft_hint_style == NULL) { hint_style = CAIRO_HINT_STYLE_NONE; } else if (self->xft_hint_style != NULL) { if (strcmp (self->xft_hint_style, "hintnone") == 0) hint_style = CAIRO_HINT_STYLE_NONE; else if (strcmp (self->xft_hint_style, "hintslight") == 0) hint_style = CAIRO_HINT_STYLE_SLIGHT; else if (strcmp (self->xft_hint_style, "hintmedium") == 0) hint_style = CAIRO_HINT_STYLE_MEDIUM; else if (strcmp (self->xft_hint_style, "hintfull") == 0) hint_style = CAIRO_HINT_STYLE_FULL; } cairo_font_options_set_hint_style (options, hint_style); if (self->xft_rgba) { if (strcmp (self->xft_rgba, "rgb") == 0) subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; else if (strcmp (self->xft_rgba, "bgr") == 0) subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; else if (strcmp (self->xft_rgba, "vrgb") == 0) subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; else if (strcmp (self->xft_rgba, "vbgr") == 0) subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; } cairo_font_options_set_subpixel_order (options, subpixel_order); if (self->xft_antialias >= 0 && !self->xft_antialias) antialias_mode = CAIRO_ANTIALIAS_NONE; else if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL; else if (self->xft_antialias >= 0) antialias_mode = CAIRO_ANTIALIAS_GRAY; cairo_font_options_set_antialias (options, antialias_mode); CLUTTER_NOTE (BACKEND, "New font options:\n" " - font-name: %s\n" " - antialias: %d\n" " - hinting: %d\n" " - hint-style: %s\n" " - rgba: %s\n", self->font_name != NULL ? self->font_name : DEFAULT_FONT_NAME, self->xft_antialias, self->xft_hinting, self->xft_hint_style != NULL ? self->xft_hint_style : "<null>", self->xft_rgba != NULL ? self->xft_rgba : "<null>"); clutter_backend_set_font_options (self->backend, options); cairo_font_options_destroy (options); }
static void update_font_options (GtkSettings *settings) { StThemeContext *context; ClutterStage *stage; ClutterBackend *backend; gint dpi; gint hinting; gchar *hint_style_str; cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE; gint antialias; cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE; cairo_font_options_t *options; g_object_get (settings, "gtk-xft-dpi", &dpi, "gtk-xft-antialias", &antialias, "gtk-xft-hinting", &hinting, "gtk-xft-hintstyle", &hint_style_str, NULL); stage = CLUTTER_STAGE (clutter_stage_get_default ()); context = st_theme_context_get_for_stage (stage); if (dpi != -1) /* GTK stores resolution as 1024 * dots/inch */ st_theme_context_set_resolution (context, dpi / 1024); else st_theme_context_set_default_resolution (context); st_tooltip_set_constrain_func (stage, constrain_tooltip, NULL, NULL); /* Clutter (as of 0.9) passes comprehensively wrong font options * override whatever set_font_flags() did above. * * http://bugzilla.openedhand.com/show_bug.cgi?id=1456 */ backend = clutter_get_default_backend (); options = cairo_font_options_create (); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); if (hinting >= 0 && !hinting) { hint_style = CAIRO_HINT_STYLE_NONE; } else if (hint_style_str) { if (strcmp (hint_style_str, "hintnone") == 0) hint_style = CAIRO_HINT_STYLE_NONE; else if (strcmp (hint_style_str, "hintslight") == 0) hint_style = CAIRO_HINT_STYLE_SLIGHT; else if (strcmp (hint_style_str, "hintmedium") == 0) hint_style = CAIRO_HINT_STYLE_MEDIUM; else if (strcmp (hint_style_str, "hintfull") == 0) hint_style = CAIRO_HINT_STYLE_FULL; } g_free (hint_style_str); cairo_font_options_set_hint_style (options, hint_style); /* We don't want to turn on subpixel anti-aliasing; since Clutter * doesn't currently have the code to support ARGB masks, * generating them then squashing them back to A8 is pointless. */ antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE; cairo_font_options_set_antialias (options, antialias_mode); clutter_backend_set_font_options (backend, options); cairo_font_options_destroy (options); }
void lime_cairo_font_options_set_hint_metrics (double handle, int v) { cairo_font_options_set_hint_metrics ((cairo_font_options_t*)(intptr_t)handle, (cairo_hint_metrics_t)v); }
static cairo_test_status_t cairo_test_for_target (cairo_test_context_t *ctx, const cairo_boilerplate_target_t *target, int dev_offset, cairo_bool_t similar) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; const char *empty_str = ""; char *offset_str; char *base_name, *base_path; char *out_png_path; char *ref_path = NULL, *ref_png_path, *cmp_png_path = NULL; char *new_path = NULL, *new_png_path; char *xfail_path = NULL, *xfail_png_path; char *base_ref_png_path; char *base_new_png_path; char *base_xfail_png_path; char *diff_png_path; char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL; cairo_test_status_t ret; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; cairo_bool_t have_output = FALSE; cairo_bool_t have_result = FALSE; void *closure; double width, height; cairo_bool_t have_output_dir; #if HAVE_MEMFAULT int malloc_failure_iterations = ctx->malloc_failure; int last_fault_count = 0; #endif /* Get the strings ready that we'll need. */ format = cairo_boilerplate_content_name (target->content); if (dev_offset) xasprintf (&offset_str, ".%d", dev_offset); else offset_str = (char *) empty_str; xasprintf (&base_name, "%s.%s.%s%s%s", ctx->test_name, target->name, format, similar ? ".similar" : "", offset_str); if (offset_str != empty_str) free (offset_str); ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (target->file_extension != NULL) { ref_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, target->file_extension); new_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, target->file_extension); xfail_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, target->file_extension); } have_output_dir = _cairo_test_mkdir (ctx->output); xasprintf (&base_path, "%s/%s", have_output_dir ? ctx->output : ".", base_name); xasprintf (&out_png_path, "%s" CAIRO_TEST_OUT_PNG, base_path); xasprintf (&diff_png_path, "%s" CAIRO_TEST_DIFF_PNG, base_path); if (ctx->test->requirements != NULL) { const char *required; required = target->is_vector ? "target=raster" : "target=vector"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_vector ? "vector" : "raster", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } required = target->is_recording ? "target=!recording" : "target=recording"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_recording ? "recording" : "non-recording", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } width = ctx->test->width; height = ctx->test->height; if (width && height) { width += dev_offset; height += dev_offset; } #if HAVE_MEMFAULT REPEAT: MEMFAULT_CLEAR_FAULTS (); MEMFAULT_RESET_LEAKS (); ctx->last_fault_count = 0; last_fault_count = MEMFAULT_COUNT_FAULTS (); /* Pre-initialise fontconfig so that the configuration is loaded without * malloc failures (our primary goal is to test cairo fault tolerance). */ #if HAVE_FCINIT FcInit (); #endif MEMFAULT_ENABLE_FAULTS (); #endif have_output = FALSE; have_result = FALSE; /* Run the actual drawing code. */ ret = CAIRO_TEST_SUCCESS; surface = (target->create_surface) (base_path, target->content, width, height, ctx->test->width + 25 * NUM_DEVICE_OFFSETS, ctx->test->height + 25 * NUM_DEVICE_OFFSETS, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) { cairo_test_log (ctx, "Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } #if HAVE_MEMFAULT if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY) { goto REPEAT; } #endif if (cairo_surface_status (surface)) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created an error surface: %s\n", cairo_status_to_string (cairo_surface_status (surface))); ret = CAIRO_TEST_FAILURE; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_UNTESTED; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the artificial CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = cairo_boilerplate_content (target->content); if (cairo_surface_get_content (surface) != expected_content) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } if (cairo_surface_set_user_data (surface, &cairo_boilerplate_output_basename_key, base_path, NULL)) { #if HAVE_MEMFAULT cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; #endif } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); if (cairo_set_user_data (cr, &_cairo_test_context_key, (void*) ctx, NULL)) { #if HAVE_MEMFAULT cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; #endif } if (similar) cairo_push_group_with_content (cr, expected_content); /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); /* Set all components of font_options to avoid backend differences * and reduce number of needed reference images. */ font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_save (cr); alarm (ctx->timeout); status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height); alarm (0); cairo_restore (cr); if (similar) { cairo_pop_group_to_source (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); } #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); /* repeat test after malloc failure injection */ if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && (status == CAIRO_TEST_NO_MEMORY || cairo_status (cr) == CAIRO_STATUS_NO_MEMORY || cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log (ctx, "Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } #if HAVE_MEMFAULT if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && MEMFAULT_HAS_FAULTS ()) { VALGRIND_PRINTF ("Unreported memfaults..."); MEMFAULT_PRINT_FAULTS (); } #endif if (target->finish_surface != NULL) { #if HAVE_MEMFAULT /* We need to re-enable faults as most recording-surface processing * is done during cairo_surface_finish(). */ MEMFAULT_CLEAR_FAULTS (); last_fault_count = MEMFAULT_COUNT_FAULTS (); MEMFAULT_ENABLE_FAULTS (); #endif /* also check for infinite loops whilst replaying */ alarm (ctx->timeout); status = target->finish_surface (surface); alarm (0); #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && status == CAIRO_STATUS_NO_MEMORY) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif if (status) { cairo_test_log (ctx, "Error: Failed to finish surface: %s\n", cairo_status_to_string (status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* Skip image check for tests with no image (width,height == 0,0) */ if (ctx->test->width != 0 && ctx->test->height != 0) { cairo_surface_t *ref_image; cairo_surface_t *test_image; cairo_surface_t *diff_image; buffer_diff_result_t result; cairo_status_t diff_status; if (ref_png_path == NULL) { cairo_test_log (ctx, "Error: Cannot find reference image for %s\n", base_name); /* we may be running this test to generate reference images */ _xunlink (ctx, out_png_path); /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); diff_status = cairo_surface_write_to_png (test_image, out_png_path); cairo_surface_destroy (test_image); if (diff_status) { if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); } have_output = TRUE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (target->file_extension != NULL) { /* compare vector surfaces */ char *filenames[] = { ref_png_path, ref_path, new_png_path, new_path, xfail_png_path, xfail_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s.out%s", base_path, target->file_extension); xasprintf (&pass_filename, "%s.pass%s", base_path, target->file_extension); xasprintf (&fail_filename, "%s.fail%s", base_path, target->file_extension); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (out_png_path, ref_path)) { cairo_test_log (ctx, "Vector surface matches reference.\n"); have_output = FALSE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_path)) { cairo_test_log (ctx, "Vector surface matches current failure.\n"); have_output = FALSE; ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_path)) { cairo_test_log (ctx, "Vector surface matches known failure.\n"); have_output = FALSE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, pass_filename)) { /* identical output as last known PASS */ cairo_test_log (ctx, "Vector surface matches last pass.\n"); have_output = TRUE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { /* identical output as last known FAIL, fail */ cairo_test_log (ctx, "Vector surface matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ have_output = TRUE; ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); if (cairo_surface_status (test_image)) { cairo_test_log (ctx, "Error: Failed to extract image: %s\n", cairo_status_to_string (cairo_surface_status (test_image))); if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_surface_destroy (test_image); goto UNWIND_CAIRO; } _xunlink (ctx, out_png_path); diff_status = cairo_surface_write_to_png (test_image, out_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } have_output = TRUE; /* binary compare png files (no decompression) */ if (target->file_extension == NULL) { char *filenames[] = { ref_png_path, new_png_path, xfail_png_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s", out_png_path); xasprintf (&pass_filename, "%s.pass.png", base_path); xasprintf (&fail_filename, "%s.fail.png", base_path); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (test_filename, pass_filename)) { cairo_test_log (ctx, "PNG file exactly matches last pass.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { cairo_test_log (ctx, "PNG file exactly matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } else { if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } } if (cairo_test_files_equal (out_png_path, base_ref_png_path)) { cairo_test_log (ctx, "PNG file exactly reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_new_png_path)) { cairo_test_log (ctx, "PNG file exactly current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } /* first compare against the ideal reference */ ref_image = cairo_test_get_reference_image (ctx, base_ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", base_ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ctx->test->width, ctx->test->height); cmp_png_path = base_ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); _xunlink (ctx, diff_png_path); if (diff_status || image_diff_is_failure (&result, target->error_tolerance)) { /* that failed, so check against the specific backend */ ref_image = cairo_test_get_reference_image (ctx, ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cmp_png_path = ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status) { cairo_test_log (ctx, "Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; } else if (image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_FAILURE; diff_status = cairo_surface_write_to_png (diff_image, diff_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write differences image: %s\n", cairo_status_to_string (diff_status)); } else { have_result = TRUE; } cairo_test_copy_file (test_filename, fail_filename); } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } /* If failed, compare against the current image output, * and attempt to detect systematic failures. */ if (ret == CAIRO_TEST_FAILURE) { char *image_out_path; image_out_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, "image", "image", format, CAIRO_TEST_OUT_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (image_out_path != NULL) { if (cairo_test_files_equal (out_png_path, image_out_path)) { ret = CAIRO_TEST_XFAILURE; } else { ref_image = cairo_image_surface_create_from_png (image_out_path); if (cairo_surface_status (ref_image) == CAIRO_STATUS_SUCCESS) { diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status == CAIRO_STATUS_SUCCESS && !image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_XFAILURE; } cairo_surface_destroy (ref_image); } } free (image_out_path); } } cairo_surface_destroy (test_image); cairo_surface_destroy (diff_image); } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_ERROR; goto UNWIND_CAIRO; } UNWIND_CAIRO: free (test_filename); free (fail_filename); free (pass_filename); test_filename = fail_filename = pass_filename = NULL; #if HAVE_MEMFAULT if (ret == CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); #endif cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); #if HAVE_MEMFAULT cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { if (ret != CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } if (ret == CAIRO_TEST_SUCCESS && --malloc_failure_iterations > 0) goto REPEAT; #endif if (have_output) cairo_test_log (ctx, "OUTPUT: %s\n", out_png_path); if (have_result) { if (cmp_png_path == NULL) { /* XXX presume we matched the normal ref last time */ cmp_png_path = ref_png_path; } cairo_test_log (ctx, "REFERENCE: %s\nDIFFERENCE: %s\n", cmp_png_path, diff_png_path); } UNWIND_STRINGS: free (out_png_path); free (ref_png_path); free (base_ref_png_path); free (ref_path); free (new_png_path); free (base_new_png_path); free (new_path); free (xfail_png_path); free (base_xfail_png_path); free (xfail_path); free (diff_png_path); free (base_path); free (base_name); return ret; }
static cairo_test_status_t cairo_test_for_target (cairo_test_t *test, cairo_boilerplate_target_t *target, int dev_offset) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; char *png_name, *ref_name, *diff_name, *offset_str; cairo_test_status_t ret = CAIRO_TEST_SUCCESS; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; /* Get the strings ready that we'll need. */ format = cairo_boilerplate_content_name (target->content); if (dev_offset) xasprintf (&offset_str, "-%d", dev_offset); else offset_str = strdup(""); xasprintf (&png_name, "%s-%s-%s%s%s", test->name, target->name, format, offset_str, CAIRO_TEST_PNG_SUFFIX); ref_name = cairo_ref_name_for_test_target_format (test->name, target->name, format); xasprintf (&diff_name, "%s-%s-%s%s%s", test->name, target->name, format, offset_str, CAIRO_TEST_DIFF_SUFFIX); if (target->is_vector) { int i; for (i = 0; vector_ignored_tests[i] != NULL; i++) if (strcmp (test->name, vector_ignored_tests[i]) == 0) { cairo_test_log ("Error: Skipping for vector target %s\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } if (ret == CAIRO_TEST_SUCCESS) { /* Run the actual drawing code. */ if (test->width && test->height) { test->width += dev_offset; test->height += dev_offset; } surface = (target->create_surface) (test->name, target->content, test->width, test->height, CAIRO_BOILERPLATE_MODE_TEST, &target->closure); if (test->width && test->height) { test->width -= dev_offset; test->height -= dev_offset;; } } if (surface == NULL) { cairo_test_log ("Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { cairo_test_log ("Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the articifical * CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = target->content; if (expected_content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) expected_content = CAIRO_CONTENT_COLOR_ALPHA; if (cairo_surface_get_content (surface) != expected_content) { cairo_test_log ("Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); /* Set all components of font_options to avoid backend differences * and reduce number of needed reference images. */ font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); status = (test->draw) (cr, test->width, test->height); /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log ("Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } /* Skip image check for tests with no image (width,height == 0,0) */ if (test->width != 0 && test->height != 0) { buffer_diff_result_t result; cairo_status_t diff_status; xunlink (png_name); (target->write_to_png) (surface, png_name); if (!ref_name) { cairo_test_log ("Error: Cannot find reference image for %s/%s-%s-%s%s\n",srcdir, test->name, target->name, format, CAIRO_TEST_REF_SUFFIX); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cairo_test_log ("Comparing result against reference image: %s\n", ref_name); if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) { diff_status= image_diff_flattened (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0, &result); } else { diff_status = image_diff (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0, &result); } if (diff_status) { cairo_test_log ("Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } if (result.pixels_changed && result.max_diff > target->error_tolerance) { ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } UNWIND_CAIRO: cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); cairo_debug_reset_static_data (); if (target->cleanup) target->cleanup (target->closure); UNWIND_STRINGS: if (png_name) free (png_name); if (ref_name) free (ref_name); if (diff_name) free (diff_name); if (offset_str) free (offset_str); return ret; }
void FontOptions::setHintMetrics( int32_t hint_metrics ) { cairo_font_options_set_hint_metrics( mCairoFontOptions, static_cast<cairo_hint_metrics_t>( hint_metrics ) ); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); FcPattern *pattern; cairo_font_face_t *font_face; cairo_font_extents_t font_extents; cairo_font_options_t *font_options; cairo_status_t status; char *filename; int face_count; struct stat stat_buf; xasprintf (&filename, "%s/%s", ctx->srcdir, FONT); if (stat (filename, &stat_buf) || ! S_ISREG (stat_buf.st_mode)) { cairo_test_log (ctx, "Error finding font: %s: file not found?\n", filename); return CAIRO_TEST_FAILURE; } pattern = FcFreeTypeQuery ((unsigned char *)filename, 0, NULL, &face_count); free (filename); if (! pattern) { cairo_test_log (ctx, "FcFreeTypeQuery failed.\n"); return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY); } font_face = cairo_ft_font_face_create_for_pattern (pattern); FcPatternDestroy (pattern); status = cairo_font_face_status (font_face); if (status) { cairo_test_log (ctx, "Error creating font face for %s: %s\n", filename, cairo_status_to_string (status)); return cairo_test_status_from_status (ctx, status); } if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) { cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n", cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT); cairo_font_face_destroy (font_face); return CAIRO_TEST_FAILURE; } cairo_set_font_face (cr, font_face); cairo_font_face_destroy (font_face); font_options = cairo_font_options_create (); #define CHECK_FONT_EXTENTS(comment) do {\ cairo_test_status_t test_status; \ test_status = check_font_extents (ctx, cr, (comment)); \ if (test_status != CAIRO_TEST_SUCCESS) { \ cairo_font_options_destroy (font_options); \ return test_status; \ } \ } while (0) cairo_font_extents (cr, &font_extents); CHECK_FONT_EXTENTS ("default"); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON"); cairo_move_to (cr, 1, font_extents.ascent - 1); cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_MEDIUM"); cairo_show_text (cr, "brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); /* Switch from show_text to text_path/fill to exercise bug #7889 */ cairo_text_path (cr, " jumps over a lazy dog"); cairo_fill (cr); /* And test it rotated as well for the sake of bug #7888 */ cairo_translate (cr, width, height); cairo_rotate (cr, M_PI); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_DEFAULT); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF"); cairo_move_to (cr, 1, font_extents.height - font_extents.descent - 1); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_MEDIUM"); cairo_show_text (cr, " brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); cairo_text_path (cr, " jumps over"); cairo_text_path (cr, " a lazy dog"); cairo_fill (cr); cairo_font_options_destroy (font_options); return CAIRO_TEST_SUCCESS; }
int main(int argc, char** argv) { int c; float col_r, col_g, col_b = -1.0f; Options opt; while ((c = getopt(argc, argv, "a:x:y:f:s:t:n:w:r:g:b:c:h:i:j:o:v")) != -1) { switch(c) { /* verbose */ /* ------------------------------------------------------- */ case 'v': { opt.verbose = 0; break; } /* color */ /* ------------------------------------------------------- */ case 'r': { col_r = convert_type<float>(optarg); break; } case 'g': { col_g = convert_type<float>(optarg); break; } case 'b': { col_b = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* hashtag */ case 'h': { opt.hashtag = convert_type<std::string>(optarg); break; } case 'i': { opt.hashtag_x = convert_type<int>(optarg); break; } case 'j': { opt.hashtag_y = convert_type<int>(optarg); break; } /* ------------------------------------------------------- */ /* foreground */ case 'c': { opt.foreground_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* background */ case 'x': { opt.background_x = convert_type<int>(optarg); break; } case 'y': { opt.background_y = convert_type<int>(optarg); break; } case 'f': { opt.background_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* visible size */ case 'a': { opt.visible_size = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* output */ case 'o': { opt.output_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* name */ case 'n': { opt.name = convert_type<std::string>(optarg); /* we expect that r,g,b has been set */ if (0 > col_r) { printf("Error: you haven't set -r -g -b for the name.\n"); exit(EXIT_FAILURE); } opt.name_r = col_r; opt.name_g = col_g; opt.name_b = col_b; break; } /* name x position */ case 's': { opt.name_x = convert_type<int>(optarg); break; } /* name y position */ case 't': { opt.name_y = convert_type<int>(optarg); break; } /* name font size */ case 'w': { opt.name_font_size = convert_type<float>(optarg); break; } default: { printf("Unkown option\n"); break; } } } if (false == opt.validate()) { printf("+ error: cannot validate the given options.\n"); exit(EXIT_FAILURE); } opt.print(); /* ------------------------------------------------------------------------------------ */ Image img; std::string path; std::string ext; cairo_surface_t* surf_bg = NULL; cairo_format_t img_format = CAIRO_FORMAT_INVALID; path = opt.foreground_file; if (false == rx_file_exists(path)) { printf("+ error: cannot find the file: %s\n", path.c_str()); exit(EXIT_FAILURE); } cairo_surface_t* surf_overlay = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_overlay) { printf("Error: cannot create s1\n"); exit(EXIT_FAILURE); } path = opt.background_file; if (false == rx_file_exists(path)) { printf("Error: file doesn't exist: %s\n", path.c_str()); exit(EXIT_FAILURE); } /* check what file type was given. */ ext = rx_get_file_ext(path); if (ext == "jpg") { printf("+ warning: jpg as input doesn't seem to work\n"); /* cairo doesn't have support for PNG? */ if (0 > rx_load_jpg(path, &img.pixels, img.width, img.height, img.channels)) { printf("Error: failed to load: %s\n", path.c_str()); exit(EXIT_FAILURE); } if (0 == img.width || 0 == img.height || 0 == img.channels) { printf("Error: image has invalid flags: %d x %d, channels: %d\n", img.width, img.height, img.channels); exit(EXIT_FAILURE); } if (3 == img.channels) { img_format = CAIRO_FORMAT_RGB24; printf("+ Using RGB24\n"); } else if(4 == img.channels) { img_format = CAIRO_FORMAT_ARGB32; printf("+ Using ARGB32\n"); } else { printf("Error: unsupported number of channels: %d.\n", img.channels); exit(EXIT_FAILURE); } if (NULL != img.pixels && NULL == surf_bg) { printf("Stride: %d\n", cairo_format_stride_for_width(img_format, img.width)); printf("Info: creating %d x %d, channels: %d\n", img.width, img.height, img.channels); surf_bg = cairo_image_surface_create_for_data(img.pixels, img_format, img.width, img.height, cairo_format_stride_for_width(img_format, img.width)); #if 0 /* TESTING */ cairo_t* cr = cairo_create(surf_bg); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } path = rx_get_exe_path() +"/generated_polaroid.png"; cairo_surface_write_to_png(surf_bg, path.c_str()); printf("Created\n"); exit(0); /* END TESTING */ #endif } } else if (ext == "png") { /* use cairo png load feature. */ surf_bg = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_bg) { printf("Error: cannot create s2\n"); exit(EXIT_FAILURE); } } else { printf("Error: unsupported file format: %s\n", ext.c_str()); exit(EXIT_FAILURE); } /* make sure the background is loaded correctly (aka the photo) */ if (NULL == surf_bg) { printf("Error: cannot create background surface.\n"); exit(EXIT_FAILURE); } if (CAIRO_STATUS_SUCCESS != cairo_surface_status(surf_bg)) { printf("Error: something went wrong: %d\n", cairo_surface_status(surf_bg)); exit(EXIT_FAILURE); } float source_width = cairo_image_surface_get_width(surf_bg); float source_height = cairo_image_surface_get_height(surf_bg); /* create output */ int dest_width = cairo_image_surface_get_width(surf_overlay); int dest_height = cairo_image_surface_get_height(surf_overlay); if (0 == opt.verbose) { printf("+ Output size: %d x %d\n", dest_width, dest_height); } cairo_surface_t* surf_out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_width, dest_height); if (NULL == surf_out) { printf("Error: cannot create cairo_surface_t\n"); exit(EXIT_FAILURE); } if (0 == opt.verbose) { printf("+ Info: creating output surface: %d x %d\n", dest_width, dest_height); } cairo_t* cr = cairo_create(surf_out); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } float scale_factor = opt.visible_size / source_width; if (0 == opt.verbose) { printf("+ Scale factor: %f\n", scale_factor); } /* paint background */ cairo_save(cr); cairo_scale(cr, scale_factor, scale_factor); cairo_set_source_surface(cr, surf_bg, opt.background_x, opt.background_y); cairo_rectangle(cr, 0, 0, img.width, img.height); cairo_paint(cr); cairo_restore(cr); /* paint overlay */ cairo_set_source_surface(cr, surf_overlay, 0, 0); cairo_paint(cr); cairo_surface_flush(surf_out); /* font settings. */ cairo_font_options_t* font_options = cairo_font_options_create(); if (NULL == font_options) { printf("+ Error: cannot create font options. Cannot create polaroid.\n"); exit(EXIT_FAILURE); } cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_BEST); cairo_font_options_set_hint_metrics(font_options, CAIRO_HINT_METRICS_DEFAULT); cairo_set_font_options (cr, font_options); cairo_select_font_face(cr, "Platform", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_source_rgba(cr, opt.name_r, opt.name_g, opt.name_b, 1.0); /* name */ if (0 != opt.name.size()) { cairo_move_to(cr, opt.name_x, opt.name_y); cairo_set_font_size(cr, opt.name_font_size); cairo_show_text(cr, opt.name.c_str()); cairo_stroke(cr); cairo_fill(cr); } /* hashtag */ if (0 != opt.hashtag.size()) { cairo_select_font_face(cr, "Platform", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_move_to(cr, opt.hashtag_x, opt.hashtag_y); cairo_set_font_size(cr, opt.name_font_size); cairo_show_text(cr, opt.hashtag.c_str()); cairo_stroke(cr); cairo_fill(cr); } cairo_surface_flush(surf_out); /* write out */ path = opt.output_file; cairo_surface_write_to_png(surf_out, path.c_str()); /* cleanup */ cairo_surface_destroy(surf_out); cairo_surface_destroy(surf_bg); cairo_surface_destroy(surf_overlay); cairo_destroy(cr); if (0 == opt.verbose) { printf("\n"); } return 0; }
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_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); glyph_array_t glyphs; cairo_font_options_t *font_options; cairo_status_t status; /* paint white so we don't need separate ref images for * RGB24 and ARGB32 */ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_select_font_face (cr, "Bitstream Vera Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, TEXT_SIZE); font_options = cairo_font_options_create (); cairo_get_font_options (cr, font_options); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); glyph_array_init (&glyphs, 1, TEXT_SIZE); status = glyph_array_add_text(&glyphs, cr, "AWAY again", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1, 0.0); status = glyph_array_add_text(&glyphs, cr, "character space", TEXT_SIZE*0.3); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_show (&glyphs, cr); glyph_array_init (&glyphs, 1, TEXT_SIZE*2 + 4); status = glyph_array_add_text(&glyphs, cr, "Increasing", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*0.5, 0.0); status = glyph_array_add_text(&glyphs, cr, "space", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1.0, 0.0); status = glyph_array_add_text(&glyphs, cr, "between", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_rel_move_to (&glyphs, TEXT_SIZE*1.5, 0.0); status = glyph_array_add_text(&glyphs, cr, "words", 0.0); if (status) return cairo_test_status_from_status (ctx, status); glyph_array_show (&glyphs, cr); return CAIRO_TEST_SUCCESS; }
static void _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info) { cairo_bool_t xft_hinting; cairo_bool_t xft_antialias; int xft_hintstyle; int xft_rgba; cairo_antialias_t antialias; cairo_subpixel_order_t subpixel_order; cairo_hint_style_t hint_style; if (!get_boolean_default (dpy, "antialias", &xft_antialias)) xft_antialias = TRUE; if (!get_boolean_default (dpy, "hinting", &xft_hinting)) xft_hinting = TRUE; if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle)) xft_hintstyle = FC_HINT_FULL; if (!get_integer_default (dpy, "rgba", &xft_rgba)) { xft_rgba = FC_RGBA_UNKNOWN; #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 if (info->has_render) { int render_order = XRenderQuerySubpixelOrder (dpy, XScreenNumberOfScreen (info->screen)); switch (render_order) { default: case SubPixelUnknown: xft_rgba = FC_RGBA_UNKNOWN; break; case SubPixelHorizontalRGB: xft_rgba = FC_RGBA_RGB; break; case SubPixelHorizontalBGR: xft_rgba = FC_RGBA_BGR; break; case SubPixelVerticalRGB: xft_rgba = FC_RGBA_VRGB; break; case SubPixelVerticalBGR: xft_rgba = FC_RGBA_VBGR; break; case SubPixelNone: xft_rgba = FC_RGBA_NONE; break; } } #endif } if (xft_hinting) { switch (xft_hintstyle) { case FC_HINT_NONE: hint_style = CAIRO_HINT_STYLE_NONE; break; case FC_HINT_SLIGHT: hint_style = CAIRO_HINT_STYLE_SLIGHT; break; case FC_HINT_MEDIUM: hint_style = CAIRO_HINT_STYLE_MEDIUM; break; case FC_HINT_FULL: hint_style = CAIRO_HINT_STYLE_FULL; break; default: hint_style = CAIRO_HINT_STYLE_DEFAULT; } } else { hint_style = CAIRO_HINT_STYLE_NONE; } switch (xft_rgba) { case FC_RGBA_RGB: subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; break; case FC_RGBA_BGR: subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; break; case FC_RGBA_VRGB: subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; break; case FC_RGBA_VBGR: subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; break; case FC_RGBA_UNKNOWN: case FC_RGBA_NONE: default: subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; } if (xft_antialias) { if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT) antialias = CAIRO_ANTIALIAS_GRAY; else antialias = CAIRO_ANTIALIAS_SUBPIXEL; } else { antialias = CAIRO_ANTIALIAS_NONE; } cairo_font_options_set_hint_style (&info->font_options, hint_style); cairo_font_options_set_antialias (&info->font_options, antialias); cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order); cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON); }