📄 cairo-gstate.c
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California * Copyright © 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is University of Southern * California. * * Contributor(s): * Carl D. Worth <cworth@cworth.org> */#include <stdlib.h>#include "cairoint.h"#include "cairo-clip-private.h"#include "cairo-gstate-private.h"static cairo_status_t_cairo_gstate_init (cairo_gstate_t *gstate, cairo_surface_t *target);static cairo_status_t_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);static void_cairo_gstate_fini (cairo_gstate_t *gstate);static cairo_status_t_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);static cairo_status_t_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);static void_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);/** * _cairo_gstate_create: * @target: a #cairo_surface_t, not NULL * * Create a new #cairo_gstate_t to draw to target with all graphics * state parameters set to defaults. gstate->next will be set to NULL * and may be used by the caller to chain #cairo_gstate_t objects * together. * * Return value: a new #cairo_gstate_t or NULL if there is * insufficient memory. **/cairo_gstate_t *_cairo_gstate_create (cairo_surface_t *target){ cairo_status_t status; cairo_gstate_t *gstate; assert (target != NULL); gstate = malloc (sizeof (cairo_gstate_t)); if (gstate == NULL) return NULL; status = _cairo_gstate_init (gstate, target); if (status) { free (gstate); return NULL; } return gstate;}static cairo_status_t_cairo_gstate_init (cairo_gstate_t *gstate, cairo_surface_t *target){ gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT; gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT; gstate->antialias = CAIRO_ANTIALIAS_DEFAULT; _cairo_stroke_style_init (&gstate->stroke_style); gstate->fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT; gstate->font_face = NULL; gstate->scaled_font = NULL; cairo_matrix_init_scale (&gstate->font_matrix, CAIRO_GSTATE_DEFAULT_FONT_SIZE, CAIRO_GSTATE_DEFAULT_FONT_SIZE); _cairo_font_options_init_default (&gstate->font_options); _cairo_clip_init (&gstate->clip, target); gstate->target = cairo_surface_reference (target); gstate->parent_target = NULL; gstate->original_target = cairo_surface_reference (target); _cairo_gstate_identity_matrix (gstate); gstate->source_ctm_inverse = gstate->ctm_inverse; gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK); if (gstate->source->status) return CAIRO_STATUS_NO_MEMORY; gstate->next = NULL; return CAIRO_STATUS_SUCCESS;}/** * _cairo_gstate_init_copy: * * Initialize @gstate by performing a deep copy of state fields from * @other. Note that gstate->next is not copied but is set to NULL by * this function. **/static cairo_status_t_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other){ cairo_status_t status; gstate->op = other->op; gstate->tolerance = other->tolerance; gstate->antialias = other->antialias; status = _cairo_stroke_style_init_copy (&gstate->stroke_style, &other->stroke_style); if (status) return status; gstate->fill_rule = other->fill_rule; gstate->font_face = cairo_font_face_reference (other->font_face); gstate->scaled_font = cairo_scaled_font_reference (other->scaled_font); gstate->font_matrix = other->font_matrix; _cairo_font_options_init_copy (&gstate->font_options , &other->font_options); _cairo_clip_init_copy (&gstate->clip, &other->clip); gstate->target = cairo_surface_reference (other->target); /* parent_target is always set to NULL; it's only ever set by redirect_target */ gstate->parent_target = NULL; gstate->original_target = cairo_surface_reference (other->original_target); gstate->ctm = other->ctm; gstate->ctm_inverse = other->ctm_inverse; gstate->source_ctm_inverse = other->source_ctm_inverse; gstate->source = cairo_pattern_reference (other->source); gstate->next = NULL; return CAIRO_STATUS_SUCCESS;}static void_cairo_gstate_fini (cairo_gstate_t *gstate){ _cairo_stroke_style_fini (&gstate->stroke_style); cairo_font_face_destroy (gstate->font_face); gstate->font_face = NULL; cairo_scaled_font_destroy (gstate->scaled_font); gstate->scaled_font = NULL; _cairo_clip_fini (&gstate->clip); cairo_surface_destroy (gstate->target); gstate->target = NULL; cairo_surface_destroy (gstate->parent_target); gstate->parent_target = NULL; cairo_surface_destroy (gstate->original_target); gstate->target = NULL; cairo_pattern_destroy (gstate->source); gstate->source = NULL;}void_cairo_gstate_destroy (cairo_gstate_t *gstate){ if (gstate == NULL) return; _cairo_gstate_fini (gstate); free (gstate);}/** * _cairo_gstate_clone: * @other: a #cairo_gstate_t to be copied, not NULL. * * Create a new #cairo_gstate_t setting all graphics state parameters * to the same values as contained in @other. gstate->next will be set * to NULL and may be used by the caller to chain cairo_gstate_t * objects together. * * Return value: a new cairo_gstate_t or NULL if there is insufficient * memory. **/cairo_gstate_t*_cairo_gstate_clone (cairo_gstate_t *other){ cairo_status_t status; cairo_gstate_t *gstate; assert (other != NULL); gstate = malloc (sizeof (cairo_gstate_t)); if (gstate == NULL) return NULL; status = _cairo_gstate_init_copy (gstate, other); if (status) { free (gstate); return NULL; } return gstate;}static cairo_status_t_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate, cairo_clip_path_t *cpath){ cairo_status_t status; if (cpath == NULL) return CAIRO_STATUS_SUCCESS; status = _cairo_gstate_recursive_apply_clip_path (gstate, cpath->prev); if (status) return status; return _cairo_clip_clip (&gstate->clip, &cpath->path, cpath->fill_rule, cpath->tolerance, cpath->antialias, gstate->target);}/** * _cairo_gstate_redirect_target: * @gstate: a #cairo_gstate_t * @child: the new child target * * Redirect @gstate rendering to a "child" target. The original * "parent" target with which the gstate was created will not be * affected. See _cairo_gstate_get_target(). * * Unless the redirected target has the same device offsets as the * original #cairo_t target, the clip will be INVALID after this call, * and the caller should either recreate or reset the clip. **/void_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child){ /* If this gstate is already redirected, this is an error; we need a * new gstate to be able to redirect */ assert (gstate->parent_target == NULL); /* Set up our new parent_target based on our current target; * gstate->parent_target will take the ref that is held by gstate->target */ cairo_surface_destroy (gstate->parent_target); gstate->parent_target = gstate->target; /* Now set up our new target; we overwrite gstate->target directly, * since its ref is now owned by gstate->parent_target */ gstate->target = cairo_surface_reference (child); _cairo_clip_fini (&gstate->clip); _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child); /* The clip is in surface backend coordinates for the previous target; * translate it into the child's backend coordinates. */ _cairo_clip_translate (&gstate->clip, _cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0), _cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));}/** * _cairo_gstate_is_redirected * @gstate: a #cairo_gstate_t * * Return value: TRUE if the gstate is redirected to a traget * different than the original, FALSE otherwise. **/cairo_bool_t_cairo_gstate_is_redirected (cairo_gstate_t *gstate){ return (gstate->target != gstate->original_target);}/** * _cairo_gstate_get_target: * @gstate: a #cairo_gstate_t * * Return the current drawing target; if drawing is not redirected, * this will be the same as _cairo_gstate_get_original_target(). * * Return value: the current target surface **/cairo_surface_t *_cairo_gstate_get_target (cairo_gstate_t *gstate){ return gstate->target;}/** * _cairo_gstate_get_parent_target: * @gstate: a #cairo_gstate_t * * Return the parent surface of the current drawing target surface; * if this particular gstate isn't a redirect gstate, this will return NULL. **/cairo_surface_t *_cairo_gstate_get_parent_target (cairo_gstate_t *gstate){ return gstate->parent_target;}/** * _cairo_gstate_get_original_target: * @gstate: a #cairo_gstate_t * * Return the original target with which @gstate was created. This * function always returns the original target independent of any * child target that may have been set with * _cairo_gstate_redirect_target. * * Return value: the original target surface **/cairo_surface_t *_cairo_gstate_get_original_target (cairo_gstate_t *gstate){ return gstate->original_target;}/** * _cairo_gstate_get_clip: * @gstate: a #cairo_gstate_t * * Return value: a pointer to the gstate's cairo_clip_t structure. */cairo_clip_t *_cairo_gstate_get_clip (cairo_gstate_t *gstate){ return &gstate->clip;}cairo_status_t_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source){ if (source->status) return source->status; cairo_pattern_reference (source); cairo_pattern_destroy (gstate->source); gstate->source = source; gstate->source_ctm_inverse = gstate->ctm_inverse; return CAIRO_STATUS_SUCCESS;}cairo_pattern_t *_cairo_gstate_get_source (cairo_gstate_t *gstate){ if (gstate == NULL) return NULL; return gstate->source;}cairo_status_t_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op){ gstate->op = op; return CAIRO_STATUS_SUCCESS;}cairo_operator_t_cairo_gstate_get_operator (cairo_gstate_t *gstate){ return gstate->op;}cairo_status_t_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance){ gstate->tolerance = tolerance; return CAIRO_STATUS_SUCCESS;}double_cairo_gstate_get_tolerance (cairo_gstate_t *gstate){ return gstate->tolerance;}cairo_status_t_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule){ gstate->fill_rule = fill_rule; return CAIRO_STATUS_SUCCESS;}cairo_fill_rule_t_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate){ return gstate->fill_rule;}cairo_status_t_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width){ gstate->stroke_style.line_width = width; return CAIRO_STATUS_SUCCESS;}double_cairo_gstate_get_line_width (cairo_gstate_t *gstate){ return gstate->stroke_style.line_width;}cairo_status_t_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap){ gstate->stroke_style.line_cap = line_cap; return CAIRO_STATUS_SUCCESS;}cairo_line_cap_t_cairo_gstate_get_line_cap (cairo_gstate_t *gstate){ return gstate->stroke_style.line_cap;}cairo_status_t_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join){ gstate->stroke_style.line_join = line_join; return CAIRO_STATUS_SUCCESS;}cairo_line_join_t_cairo_gstate_get_line_join (cairo_gstate_t *gstate){ return gstate->stroke_style.line_join;}cairo_status_t_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset){ int i; double dash_total; if (gstate->stroke_style.dash) free (gstate->stroke_style.dash); gstate->stroke_style.num_dashes = num_dashes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -