📄 cairo-gstate.c
字号:
if (gstate->stroke_style.num_dashes == 0) { gstate->stroke_style.dash = NULL; gstate->stroke_style.dash_offset = 0.0; return CAIRO_STATUS_SUCCESS; } gstate->stroke_style.dash = malloc (gstate->stroke_style.num_dashes * sizeof (double)); if (gstate->stroke_style.dash == NULL) { gstate->stroke_style.num_dashes = 0; return CAIRO_STATUS_NO_MEMORY; } memcpy (gstate->stroke_style.dash, dash, gstate->stroke_style.num_dashes * sizeof (double)); dash_total = 0.0; for (i = 0; i < gstate->stroke_style.num_dashes; i++) { if (gstate->stroke_style.dash[i] < 0) return CAIRO_STATUS_INVALID_DASH; dash_total += gstate->stroke_style.dash[i]; } if (dash_total == 0.0) return CAIRO_STATUS_INVALID_DASH; /* A single dash value indicate symmetric repeating, so the total * is twice as long. */ if (gstate->stroke_style.num_dashes == 1) dash_total *= 2; /* The dashing code doesn't like a negative offset, so we compute * the equivalent positive offset. */ if (offset < 0) offset += ceil (-offset / dash_total + 0.5) * dash_total; gstate->stroke_style.dash_offset = offset; return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit){ gstate->stroke_style.miter_limit = limit; return CAIRO_STATUS_SUCCESS;}double_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate){ return gstate->stroke_style.miter_limit;}void_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix){ *matrix = gstate->ctm;}cairo_status_t_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty){ cairo_matrix_t tmp; _cairo_gstate_unset_scaled_font (gstate); cairo_matrix_init_translate (&tmp, tx, ty); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); cairo_matrix_init_translate (&tmp, -tx, -ty); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy){ cairo_matrix_t tmp; if (sx == 0 || sy == 0) return CAIRO_STATUS_INVALID_MATRIX; _cairo_gstate_unset_scaled_font (gstate); cairo_matrix_init_scale (&tmp, sx, sy); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); cairo_matrix_init_scale (&tmp, 1/sx, 1/sy); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle){ cairo_matrix_t tmp; _cairo_gstate_unset_scaled_font (gstate); cairo_matrix_init_rotate (&tmp, angle); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); cairo_matrix_init_rotate (&tmp, -angle); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_transform (cairo_gstate_t *gstate, const cairo_matrix_t *matrix){ cairo_matrix_t tmp; _cairo_gstate_unset_scaled_font (gstate); tmp = *matrix; cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); cairo_matrix_invert (&tmp); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_set_matrix (cairo_gstate_t *gstate, const cairo_matrix_t *matrix){ cairo_status_t status; _cairo_gstate_unset_scaled_font (gstate); gstate->ctm = *matrix; gstate->ctm_inverse = *matrix; status = cairo_matrix_invert (&gstate->ctm_inverse); if (status) return status; return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_identity_matrix (cairo_gstate_t *gstate){ _cairo_gstate_unset_scaled_font (gstate); cairo_matrix_init_identity (&gstate->ctm); cairo_matrix_init_identity (&gstate->ctm_inverse); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y){ cairo_matrix_transform_point (&gstate->ctm, x, y); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate, double *dx, double *dy){ cairo_matrix_transform_distance (&gstate->ctm, dx, dy); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y){ cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, double *dx, double *dy){ cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy); return CAIRO_STATUS_SUCCESS;}void_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y){ cairo_matrix_transform_point (&gstate->ctm, x, y); cairo_matrix_transform_point (&gstate->target->device_transform, x, y);}void_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y){ cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y); cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);}/* XXX: NYIcairo_status_t_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate){ cairo_status_t status; _cairo_pen_init (&gstate); return CAIRO_STATUS_SUCCESS;}*/static void_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern, cairo_pattern_t *original, cairo_matrix_t *ctm_inverse){ cairo_surface_pattern_t *surface_pattern; cairo_surface_t *surface; _cairo_pattern_init_copy (pattern, original); _cairo_pattern_transform (pattern, ctm_inverse); if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) { surface_pattern = (cairo_surface_pattern_t *) original; surface = surface_pattern->surface; if (_cairo_surface_has_device_transform (surface)) _cairo_pattern_transform (pattern, &surface->device_transform); }}static void_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate, cairo_pattern_t *pattern){ _cairo_gstate_copy_transformed_pattern (gstate, pattern, gstate->source, &gstate->source_ctm_inverse);}static void_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate, cairo_pattern_t *pattern, cairo_pattern_t *mask){ _cairo_gstate_copy_transformed_pattern (gstate, pattern, mask, &gstate->ctm_inverse);}cairo_status_t_cairo_gstate_paint (cairo_gstate_t *gstate){ cairo_status_t status; cairo_pattern_union_t pattern; if (gstate->source->status) return gstate->source->status; status = _cairo_surface_set_clip (gstate->target, &gstate->clip); if (status) return status; _cairo_gstate_copy_transformed_source (gstate, &pattern.base); status = _cairo_surface_paint (gstate->target, gstate->op, &pattern.base); _cairo_pattern_fini (&pattern.base); return status;}/** * _cairo_operator_bounded_by_mask: * @op: a #cairo_operator_t * * A bounded operator is one where mask pixel * of zero results in no effect on the destination image. * * Unbounded operators often require special handling; if you, for * example, draw trapezoids with an unbounded operator, the effect * extends past the bounding box of the trapezoids. * * Return value: %TRUE if the operator is bounded by the mask operand **/cairo_bool_t_cairo_operator_bounded_by_mask (cairo_operator_t op){ switch (op) { case CAIRO_OPERATOR_CLEAR: case CAIRO_OPERATOR_SOURCE: case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_DEST_OVER: case CAIRO_OPERATOR_DEST_OUT: case CAIRO_OPERATOR_XOR: case CAIRO_OPERATOR_ADD: case CAIRO_OPERATOR_SATURATE: return TRUE; case CAIRO_OPERATOR_OUT: case CAIRO_OPERATOR_IN: case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_ATOP: return FALSE; } ASSERT_NOT_REACHED; return FALSE;}/** * _cairo_operator_bounded_by_source: * @op: a #cairo_operator_t * * A bounded operator is one where source pixels of zero * (in all four components, r, g, b and a) effect no change * in the resulting destination image. * * Unbounded operators often require special handling; if you, for * example, copy a surface with the SOURCE operator, the effect * extends past the bounding box of the source surface. * * Return value: %TRUE if the operator is bounded by the source operand **/cairo_bool_t_cairo_operator_bounded_by_source (cairo_operator_t op){ switch (op) { case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_DEST_OVER: case CAIRO_OPERATOR_DEST_OUT: case CAIRO_OPERATOR_XOR: case CAIRO_OPERATOR_ADD: case CAIRO_OPERATOR_SATURATE: return TRUE; case CAIRO_OPERATOR_CLEAR: case CAIRO_OPERATOR_SOURCE: case CAIRO_OPERATOR_OUT: case CAIRO_OPERATOR_IN: case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_ATOP: return FALSE; } ASSERT_NOT_REACHED; return FALSE;}cairo_status_t_cairo_gstate_mask (cairo_gstate_t *gstate, cairo_pattern_t *mask){ cairo_status_t status; cairo_pattern_union_t source_pattern, mask_pattern; if (mask->status) return mask->status; if (gstate->source->status) return gstate->source->status; status = _cairo_surface_set_clip (gstate->target, &gstate->clip); if (status) return status; _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); status = _cairo_surface_mask (gstate->target, gstate->op, &source_pattern.base, &mask_pattern.base); _cairo_pattern_fini (&source_pattern.base); _cairo_pattern_fini (&mask_pattern.base); return status;}cairo_status_t_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path){ cairo_status_t status; cairo_pattern_union_t source_pattern; if (gstate->source->status) return gstate->source->status; if (gstate->stroke_style.line_width <= 0.0) return CAIRO_STATUS_SUCCESS; status = _cairo_surface_set_clip (gstate->target, &gstate->clip); if (status) return status; _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); status = _cairo_surface_stroke (gstate->target, gstate->op, &source_pattern.base, path, &gstate->stroke_style, &gstate->ctm, &gstate->ctm_inverse, gstate->tolerance, gstate->antialias); _cairo_pattern_fini (&source_pattern.base); return status;}cairo_status_t_cairo_gstate_in_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double x, double y, cairo_bool_t *inside_ret){ cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_traps_t traps; _cairo_gstate_user_to_backend (gstate, &x, &y); _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; *inside_ret = _cairo_traps_contain (&traps, x, y);BAIL: _cairo_traps_fini (&traps); return status;}cairo_status_t_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path){ cairo_status_t status; cairo_pattern_union_t pattern; if (gstate->source->status) return gstate->source->status; status = _cairo_surface_set_clip (gstate->target, &gstate->clip); if (status) return status; _cairo_gstate_copy_transformed_source (gstate, &pattern.base); status = _cairo_surface_fill (gstate->target, gstate->op, &pattern.base, path, gstate->fill_rule, gstate->tolerance, gstate->antialias); _cairo_pattern_fini (&pattern.base); return status;}cairo_status_t_cairo_gstate_in_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path, double x, double y, cairo_bool_t *inside_ret){ cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_traps_t traps; _cairo_gstate_user_to_backend (gstate, &x, &y); _cairo_traps_init (&traps); status = _cairo_path_fixed_fill_to_traps (path, gstate->fill_rule, gstate->tolerance, &traps); if (status) goto BAIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -