📄 cairo-gstate.c
字号:
*inside_ret = _cairo_traps_contain (&traps, x, y);BAIL: _cairo_traps_fini (&traps); return status;}cairo_status_t_cairo_gstate_copy_page (cairo_gstate_t *gstate){ cairo_int_status_t status; status = _cairo_surface_copy_page (gstate->target); /* It's fine if some surfaces just don't support this. */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) return CAIRO_STATUS_SUCCESS; return status;}cairo_status_t_cairo_gstate_show_page (cairo_gstate_t *gstate){ cairo_int_status_t status; status = _cairo_surface_show_page (gstate->target); /* It's fine if some surfaces just don't support this. */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) return CAIRO_STATUS_SUCCESS; return status;}cairo_status_t_cairo_gstate_stroke_extents (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double *x1, double *y1, double *x2, double *y2){ cairo_status_t status; cairo_traps_t traps; cairo_box_t extents; _cairo_traps_init (&traps); status = _cairo_path_fixed_stroke_to_traps (path, &gstate->stroke_style, &gstate->ctm, &gstate->ctm_inverse, gstate->tolerance, &traps); if (status) goto BAIL; _cairo_traps_extents (&traps, &extents); *x1 = _cairo_fixed_to_double (extents.p1.x); *y1 = _cairo_fixed_to_double (extents.p1.y); *x2 = _cairo_fixed_to_double (extents.p2.x); *y2 = _cairo_fixed_to_double (extents.p2.y); _cairo_gstate_backend_to_user (gstate, x1, y1); _cairo_gstate_backend_to_user (gstate, x2, y2);BAIL: _cairo_traps_fini (&traps); return status;}cairo_status_t_cairo_gstate_fill_extents (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double *x1, double *y1, double *x2, double *y2){ cairo_status_t status; cairo_traps_t traps; cairo_box_t extents; _cairo_traps_init (&traps); status = _cairo_path_fixed_fill_to_traps (path, gstate->fill_rule, gstate->tolerance, &traps); if (status) goto BAIL; _cairo_traps_extents (&traps, &extents); *x1 = _cairo_fixed_to_double (extents.p1.x); *y1 = _cairo_fixed_to_double (extents.p1.y); *x2 = _cairo_fixed_to_double (extents.p2.x); *y2 = _cairo_fixed_to_double (extents.p2.y); _cairo_gstate_backend_to_user (gstate, x1, y1); _cairo_gstate_backend_to_user (gstate, x2, y2);BAIL: _cairo_traps_fini (&traps); return status;}cairo_status_t_cairo_gstate_reset_clip (cairo_gstate_t *gstate){ return _cairo_clip_reset (&gstate->clip);}cairo_status_t_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path){ return _cairo_clip_clip (&gstate->clip, path, gstate->fill_rule, gstate->tolerance, gstate->antialias, gstate->target);}static void_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate){ if (gstate->scaled_font) { cairo_scaled_font_destroy (gstate->scaled_font); gstate->scaled_font = NULL; }}cairo_status_t_cairo_gstate_select_font_face (cairo_gstate_t *gstate, const char *family, cairo_font_slant_t slant, cairo_font_weight_t weight){ cairo_font_face_t *font_face; font_face = _cairo_toy_font_face_create (family, slant, weight); if (font_face->status) return font_face->status; _cairo_gstate_set_font_face (gstate, font_face); cairo_font_face_destroy (font_face); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_set_font_size (cairo_gstate_t *gstate, double size){ _cairo_gstate_unset_scaled_font (gstate); cairo_matrix_init_scale (&gstate->font_matrix, size, size); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate, const cairo_matrix_t *matrix){ _cairo_gstate_unset_scaled_font (gstate); gstate->font_matrix = *matrix; return CAIRO_STATUS_SUCCESS;}void_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix){ *matrix = gstate->font_matrix;}cairo_status_t_cairo_gstate_set_font_options (cairo_gstate_t *gstate, const cairo_font_options_t *options){ _cairo_gstate_unset_scaled_font (gstate); gstate->font_options = *options; return CAIRO_STATUS_SUCCESS;}void_cairo_gstate_get_font_options (cairo_gstate_t *gstate, cairo_font_options_t *options){ *options = gstate->font_options;}cairo_status_t_cairo_gstate_get_font_face (cairo_gstate_t *gstate, cairo_font_face_t **font_face){ cairo_status_t status; status = _cairo_gstate_ensure_font_face (gstate); if (status) return status; *font_face = gstate->font_face; return CAIRO_STATUS_SUCCESS;}/* * Like everything else in this file, fonts involve Too Many Coordinate Spaces; * it is easy to get confused about what's going on. * * The user's view * --------------- * * Users ask for things in user space. When cairo starts, a user space unit * is about 1/96 inch, which is similar to (but importantly different from) * the normal "point" units most users think in terms of. When a user * selects a font, its scale is set to "one user unit". The user can then * independently scale the user coordinate system *or* the font matrix, in * order to adjust the rendered size of the font. * * Metrics are returned in user space, whether they are obtained from * the currently selected font in a #cairo_t or from a #cairo_scaled_font_t * which is a font specialized to a particular scale matrix, CTM, and target * surface. * * The font's view * --------------- * * Fonts are designed and stored (in say .ttf files) in "font space", which * describes an "EM Square" (a design tile) and has some abstract number * such as 1000, 1024, or 2048 units per "EM". This is basically an * uninteresting space for us, but we need to remember that it exists. * * Font resources (from libraries or operating systems) render themselves * to a particular device. Since they do not want to make most programmers * worry about the font design space, the scaling API is simplified to * involve just telling the font the required pixel size of the EM square * (that is, in device space). * * * Cairo's gstate view * ------------------- * * In addition to the CTM and CTM inverse, we keep a matrix in the gstate * called the "font matrix" which describes the user's most recent * font-scaling or font-transforming request. This is kept in terms of an * abstract scale factor, composed with the CTM and used to set the font's * pixel size. So if the user asks to "scale the font by 12", the matrix * is: * * [ 12.0, 0.0, 0.0, 12.0, 0.0, 0.0 ] * * It is an affine matrix, like all cairo matrices, but its tx and ty * components are always set to zero; we don't permit "nudging" fonts * around. * * In order to perform any action on a font, we must build an object * called a cairo_font_scale_t; this contains the central 2x2 matrix * resulting from "font matrix * CTM". * * We pass this to the font when making requests of it, which causes it to * reply for a particular [user request, device] combination, under the CTM * (to accomodate the "zoom in" == "bigger fonts" issue above). * * The other terms in our communication with the font are therefore in * device space. When we ask it to perform text->glyph conversion, it will * produce a glyph string in device space. Glyph vectors we pass to it for * measuring or rendering should be in device space. The metrics which we * get back from the font will be in device space. The contents of the * global glyph image cache will be in device space. * * * Cairo's public view * ------------------- * * Since the values entering and leaving via public API calls are in user * space, the gstate functions typically need to multiply arguments by the * CTM (for user-input glyph vectors), and return values by the CTM inverse * (for font responses such as metrics or glyph vectors). * */static cairo_status_t_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate){ if (!gstate->font_face) { cairo_font_face_t *font_face; font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT, CAIRO_FONT_SLANT_DEFAULT, CAIRO_FONT_WEIGHT_DEFAULT); if (font_face->status) return font_face->status; else gstate->font_face = font_face; } return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate){ cairo_status_t status; cairo_font_options_t options; if (gstate->scaled_font) return CAIRO_STATUS_SUCCESS; status = _cairo_gstate_ensure_font_face (gstate); if (status) return status; cairo_surface_get_font_options (gstate->target, &options); cairo_font_options_merge (&options, &gstate->font_options); gstate->scaled_font = cairo_scaled_font_create (gstate->font_face, &gstate->font_matrix, &gstate->ctm, &options); if (!gstate->scaled_font) return CAIRO_STATUS_NO_MEMORY; return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_get_font_extents (cairo_gstate_t *gstate, cairo_font_extents_t *extents){ cairo_status_t status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; cairo_scaled_font_extents (gstate->scaled_font, extents); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, const char *utf8, double x, double y, cairo_glyph_t **glyphs, int *num_glyphs){ cairo_status_t status; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, utf8, glyphs, num_glyphs); if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs)) return status; return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_set_font_face (cairo_gstate_t *gstate, cairo_font_face_t *font_face){ if (font_face && font_face->status) return font_face->status; if (font_face != gstate->font_face) { cairo_font_face_destroy (gstate->font_face); gstate->font_face = cairo_font_face_reference (font_face); } _cairo_gstate_unset_scaled_font (gstate); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_glyph_extents (cairo_gstate_t *gstate, cairo_glyph_t *glyphs, int num_glyphs, cairo_text_extents_t *extents){ cairo_status_t status; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; cairo_scaled_font_glyph_extents (gstate->scaled_font, glyphs, num_glyphs, extents); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_show_glyphs (cairo_gstate_t *gstate, cairo_glyph_t *glyphs, int num_glyphs){ cairo_status_t status; cairo_pattern_union_t source_pattern; cairo_glyph_t *transformed_glyphs; int i; if (gstate->source->status) return gstate->source->status; status = _cairo_surface_set_clip (gstate->target, &gstate->clip); if (status) return status; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); if (transformed_glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; for (i = 0; i < num_glyphs; ++i) { transformed_glyphs[i] = glyphs[i]; _cairo_gstate_user_to_device (gstate, &transformed_glyphs[i].x, &transformed_glyphs[i].y); } _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); status = _cairo_surface_show_glyphs (gstate->target, gstate->op, &source_pattern.base, transformed_glyphs, num_glyphs, gstate->scaled_font); _cairo_pattern_fini (&source_pattern.base); free (transformed_glyphs); return status;}cairo_status_t_cairo_gstate_glyph_path (cairo_gstate_t *gstate, cairo_glyph_t *glyphs, int num_glyphs, cairo_path_fixed_t *path){ cairo_status_t status; int i; cairo_glyph_t *transformed_glyphs = NULL; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t)); if (transformed_glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; for (i = 0; i < num_glyphs; ++i) { transformed_glyphs[i] = glyphs[i]; _cairo_gstate_user_to_backend (gstate, &(transformed_glyphs[i].x), &(transformed_glyphs[i].y)); } status = _cairo_scaled_font_glyph_path (gstate->scaled_font, transformed_glyphs, num_glyphs, path); free (transformed_glyphs); return status;}cairo_status_t_cairo_gstate_set_antialias (cairo_gstate_t *gstate, cairo_antialias_t antialias){ gstate->antialias = antialias; return CAIRO_STATUS_SUCCESS;}cairo_antialias_t_cairo_gstate_get_antialias (cairo_gstate_t *gstate){ return gstate->antialias;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -