cairo_status_t _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, cairo_operator_t op, const cairo_color_t *color, cairo_rectangle_int_t *rects, int num_rects) { fallback_state_t state; cairo_rectangle_int_t *offset_rects = NULL; cairo_status_t status; int x1, y1, x2, y2; int i; assert (! surface->is_snapshot); if (num_rects <= 0) return CAIRO_STATUS_SUCCESS; /* Compute the bounds of the rectangles, so that we know what area of the * destination surface to fetch */ x1 = rects[0].x; y1 = rects[0].y; x2 = rects[0].x + rects[0].width; y2 = rects[0].y + rects[0].height; for (i = 1; i < num_rects; i++) { if (rects[i].x < x1) x1 = rects[i].x; if (rects[i].y < y1) y1 = rects[i].y; if ((int)(rects[i].x + rects[i].width) > x2) x2 = rects[i].x + rects[i].width; if ((int)(rects[i].y + rects[i].height) > y2) y2 = rects[i].y + rects[i].height; } status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1); if (status) { if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) return CAIRO_STATUS_SUCCESS; return status; } /* If the fetched image isn't at 0,0, we need to offset the rectangles */ if (state.image_rect.x != 0 || state.image_rect.y != 0) { offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t)); if (offset_rects == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto DONE; } for (i = 0; i < num_rects; i++) { offset_rects[i].x = rects[i].x - state.image_rect.x; offset_rects[i].y = rects[i].y - state.image_rect.y; offset_rects[i].width = rects[i].width; offset_rects[i].height = rects[i].height; } rects = offset_rects; } status = _cairo_surface_fill_rectangles (&state.image->base, op, color, rects, num_rects); free (offset_rects); DONE: _fallback_fini (&state); return status; }
cairo_int_status_t _cairo_meta_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) { cairo_meta_surface_t *meta; cairo_command_t *command, **elements; int i, num_elements; cairo_int_status_t status; cairo_traps_t traps; cairo_clip_t clip; meta = (cairo_meta_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; _cairo_clip_init (&clip, target); num_elements = meta->commands.num_elements; elements = (cairo_command_t **) meta->commands.elements; for (i = 0; i < num_elements; i++) { command = elements[i]; switch (command->type) { case CAIRO_COMMAND_COMPOSITE: status = _cairo_surface_set_clip (target, &clip); if (status) break; status = _cairo_surface_composite (command->composite.operator, &command->composite.src_pattern.base, command->composite.mask_pattern_pointer, target, command->composite.src_x, command->composite.src_y, command->composite.mask_x, command->composite.mask_y, command->composite.dst_x, command->composite.dst_y, command->composite.width, command->composite.height); break; case CAIRO_COMMAND_FILL_RECTANGLES: status = _cairo_surface_set_clip (target, &clip); if (status) break; status = _cairo_surface_fill_rectangles (target, command->fill_rectangles.operator, &command->fill_rectangles.color, command->fill_rectangles.rects, command->fill_rectangles.num_rects); break; case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS: status = _cairo_surface_set_clip (target, &clip); if (status) break; status = _cairo_surface_composite_trapezoids (command->composite_trapezoids.operator, &command->composite_trapezoids.pattern.base, target, command->composite_trapezoids.antialias, command->composite_trapezoids.x_src, command->composite_trapezoids.y_src, command->composite_trapezoids.x_dst, command->composite_trapezoids.y_dst, command->composite_trapezoids.width, command->composite_trapezoids.height, command->composite_trapezoids.traps, command->composite_trapezoids.num_traps); break; case CAIRO_COMMAND_INTERSECT_CLIP_PATH: /* XXX Meta surface clipping is broken and requires some * cairo-gstate.c rewriting. Work around it for now. */ if (command->intersect_clip_path.path_pointer == NULL) status = _cairo_clip_reset (&clip); else status = _cairo_clip_clip (&clip, command->intersect_clip_path.path_pointer, command->intersect_clip_path.fill_rule, command->intersect_clip_path.tolerance, command->intersect_clip_path.antialias, target); break; case CAIRO_COMMAND_SHOW_GLYPHS: status = _cairo_surface_set_clip (target, &clip); if (status) break; status = _cairo_surface_show_glyphs (command->show_glyphs.scaled_font, command->show_glyphs.operator, &command->show_glyphs.pattern.base, target, command->show_glyphs.source_x, command->show_glyphs.source_y, command->show_glyphs.dest_x, command->show_glyphs.dest_y, command->show_glyphs.width, command->show_glyphs.height, command->show_glyphs.glyphs, command->show_glyphs.num_glyphs); if (status != CAIRO_INT_STATUS_UNSUPPORTED) break; status = (*command->show_glyphs.scaled_font->backend-> show_glyphs) (command->show_glyphs.scaled_font, command->show_glyphs.operator, &command->show_glyphs.pattern.base, target, command->show_glyphs.source_x, command->show_glyphs.source_y, command->show_glyphs.dest_x, command->show_glyphs.dest_y, command->show_glyphs.width, command->show_glyphs.height, command->show_glyphs.glyphs, command->show_glyphs.num_glyphs); break; case CAIRO_COMMAND_FILL_PATH: status = _cairo_surface_set_clip (target, &clip); if (status) break; status = _cairo_surface_fill_path (command->fill_path.operator, &command->fill_path.pattern.base, target, &command->fill_path.path, command->fill_path.fill_rule, command->fill_path.tolerance); if (status != CAIRO_INT_STATUS_UNSUPPORTED) break; _cairo_traps_init (&traps); status = _cairo_path_fixed_fill_to_traps (&command->fill_path.path, command->fill_path.fill_rule, command->fill_path.tolerance, &traps); if (status) { _cairo_traps_fini (&traps); break; } status = _cairo_surface_clip_and_composite_trapezoids (&command->fill_path.pattern.base, command->fill_path.operator, target, &traps, &clip, command->fill_path.antialias); _cairo_traps_fini (&traps); break; default: ASSERT_NOT_REACHED; } if (status) break; } _cairo_clip_fini (&clip); return status; }