📄 cairo-surface-fallback.c
字号:
src, dst, 0, 0, extents); } if (src == &solid_pattern.base) _cairo_pattern_fini (&solid_pattern.base); return status;}/* Composites a region representing a set of trapezoids. */static cairo_status_t_composite_trap_region (cairo_clip_t *clip, cairo_pattern_t *src, cairo_operator_t op, cairo_surface_t *dst, pixman_region16_t *trap_region, cairo_rectangle_int16_t *extents){ cairo_status_t status; cairo_pattern_union_t solid_pattern; cairo_pattern_union_t mask; int num_rects = pixman_region_num_rects (trap_region); unsigned int clip_serial; cairo_surface_t *clip_surface = clip ? clip->surface : NULL; if (clip_surface && op == CAIRO_OPERATOR_CLEAR) { _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE); src = &solid_pattern.base; op = CAIRO_OPERATOR_DEST_OUT; } if (num_rects == 0) return CAIRO_STATUS_SUCCESS; if (num_rects > 1) { if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION) return CAIRO_INT_STATUS_UNSUPPORTED; clip_serial = _cairo_surface_allocate_clip_serial (dst); status = _cairo_surface_set_clip_region (dst, trap_region, clip_serial); if (status) return status; } if (clip_surface) _cairo_pattern_init_for_surface (&mask.surface, clip_surface); status = _cairo_surface_composite (op, src, clip_surface ? &mask.base : NULL, dst, extents->x, extents->y, extents->x - (clip_surface ? clip->surface_rect.x : 0), extents->y - (clip_surface ? clip->surface_rect.y : 0), extents->x, extents->y, extents->width, extents->height); /* Restore the original clip if we modified it temporarily. */ if (num_rects >1) _cairo_surface_set_clip (dst, clip); if (clip_surface) _cairo_pattern_fini (&mask.base); if (src == &solid_pattern.base) _cairo_pattern_fini (&solid_pattern.base); return status;}typedef struct { cairo_traps_t *traps; cairo_antialias_t antialias;} cairo_composite_traps_info_t;static cairo_status_t_composite_traps_draw_func (void *closure, cairo_operator_t op, cairo_pattern_t *src, cairo_surface_t *dst, int dst_x, int dst_y, const cairo_rectangle_int16_t *extents){ cairo_composite_traps_info_t *info = closure; cairo_pattern_union_t pattern; cairo_status_t status; if (dst_x != 0 || dst_y != 0) _cairo_traps_translate (info->traps, - dst_x, - dst_y); _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE); if (!src) src = &pattern.base; status = _cairo_surface_composite_trapezoids (op, src, dst, info->antialias, extents->x, extents->y, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height, info->traps->traps, info->traps->num_traps); _cairo_pattern_fini (&pattern.base); return status;}/* Warning: This call modifies the coordinates of traps */static cairo_status_t_clip_and_composite_trapezoids (cairo_pattern_t *src, cairo_operator_t op, cairo_surface_t *dst, cairo_traps_t *traps, cairo_clip_t *clip, cairo_antialias_t antialias){ cairo_status_t status; pixman_region16_t *trap_region; pixman_region16_t *clear_region = NULL; cairo_rectangle_int16_t extents; cairo_composite_traps_info_t traps_info; if (traps->num_traps == 0) return CAIRO_STATUS_SUCCESS; status = _cairo_traps_extract_region (traps, &trap_region); if (status) return status; if (_cairo_operator_bounded_by_mask (op)) { if (trap_region) { status = _cairo_clip_intersect_to_region (clip, trap_region); _cairo_region_extents_rectangle (trap_region, &extents); } else { cairo_box_t trap_extents; _cairo_traps_extents (traps, &trap_extents); _cairo_box_round_to_rectangle (&trap_extents, &extents); status = _cairo_clip_intersect_to_rectangle (clip, &extents); } } else { cairo_surface_t *clip_surface = clip ? clip->surface : NULL; status = _cairo_surface_get_extents (dst, &extents); if (status) return status; if (trap_region && !clip_surface) { /* If we optimize drawing with an unbounded operator to * _cairo_surface_fill_rectangles() or to drawing with a * clip region, then we have an additional region to clear. */ status = _cairo_surface_get_extents (dst, &extents); if (status) return status; clear_region = _cairo_region_create_from_rectangle (&extents); if (clear_region == NULL) return CAIRO_STATUS_NO_MEMORY; status = _cairo_clip_intersect_to_region (clip, clear_region); if (status) return status; _cairo_region_extents_rectangle (clear_region, &extents); if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS) return CAIRO_STATUS_NO_MEMORY; if (!pixman_region_not_empty (clear_region)) { pixman_region_destroy (clear_region); clear_region = NULL; } } else { status = _cairo_clip_intersect_to_rectangle (clip, &extents); if (status) return status; } } if (status) goto out; if (trap_region) { cairo_surface_t *clip_surface = clip ? clip->surface : NULL; if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) && !clip_surface) { const cairo_color_t *color; if (op == CAIRO_OPERATOR_CLEAR) color = CAIRO_COLOR_TRANSPARENT; else color = &((cairo_solid_pattern_t *)src)->color; /* Solid rectangles special case */ status = _cairo_surface_fill_region (dst, op, color, trap_region); if (!status && clear_region) status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, clear_region); goto out; } if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) || !clip_surface) { /* For a simple rectangle, we can just use composite(), for more * rectangles, we have to set a clip region. The cost of rasterizing * trapezoids is pretty high for most backends currently, so it's * worthwhile even if a region is needed. * * If we have a clip surface, we set it as the mask; this only works * for bounded operators other than SOURCE; for unbounded operators, * clip and mask cannot be interchanged. For SOURCE, the operator * as implemented by the backends is different in it's handling * of the mask then what we want. * * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has * more than rectangle and the destination doesn't support clip * regions. In that case, we fall through. */ status = _composite_trap_region (clip, src, op, dst, trap_region, &extents); if (status != CAIRO_INT_STATUS_UNSUPPORTED) { if (!status && clear_region) status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, clear_region); goto out; } } } traps_info.traps = traps; traps_info.antialias = antialias; status = _clip_and_composite (clip, op, src, _composite_traps_draw_func, &traps_info, dst, &extents); out: if (trap_region) pixman_region_destroy (trap_region); if (clear_region) pixman_region_destroy (clear_region); return status;}cairo_status_t_cairo_surface_fallback_paint (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source){ cairo_status_t status; cairo_rectangle_int16_t extents; cairo_box_t box; cairo_traps_t traps; status = _cairo_surface_get_extents (surface, &extents); if (status) return status; if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int16_t source_extents; status = _cairo_pattern_get_extents (source, &source_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &source_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (status) return status; box.p1.x = _cairo_fixed_from_int (extents.x); box.p1.y = _cairo_fixed_from_int (extents.y); box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); status = _cairo_traps_init_box (&traps, &box); if (status) return status; _clip_and_composite_trapezoids (source, op, surface, &traps, surface->clip, CAIRO_ANTIALIAS_NONE); _cairo_traps_fini (&traps); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_surface_mask_draw_func (void *closure, cairo_operator_t op, cairo_pattern_t *src, cairo_surface_t *dst, int dst_x, int dst_y, const cairo_rectangle_int16_t *extents){ cairo_pattern_t *mask = closure; if (src) return _cairo_surface_composite (op, src, mask, dst, extents->x, extents->y, extents->x, extents->y, extents->x - dst_x, extents->y - dst_y, extents->width, extents->height); else return _cairo_surface_composite (op, mask, NULL, dst, extents->x, extents->y, 0, 0, /* unused */ extents->x - dst_x, extents->y - dst_y, extents->width, extents->height);}cairo_status_t_cairo_surface_fallback_mask (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, cairo_pattern_t *mask){ cairo_status_t status; cairo_rectangle_int16_t extents, source_extents, mask_extents; status = _cairo_surface_get_extents (surface, &extents); if (status) return status; if (_cairo_operator_bounded_by_source (op)) { status = _cairo_pattern_get_extents (source, &source_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &source_extents); } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_pattern_get_extents (mask, &mask_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &mask_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (status) return status; status = _clip_and_composite (surface->clip, op, source, _cairo_surface_mask_draw_func, mask, surface, &extents); return status;}cairo_status_t_cairo_surface_fallback_stroke (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *stroke_style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias){ cairo_status_t status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -