diff options
Diffstat (limited to 'common/cairo_canvas.c')
-rw-r--r-- | common/cairo_canvas.c | 455 |
1 files changed, 0 insertions, 455 deletions
diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c index c5ef3b2d..14d8bd7f 100644 --- a/common/cairo_canvas.c +++ b/common/cairo_canvas.c @@ -24,7 +24,6 @@ #include "rop3.h" #include "rect.h" #include "region.h" -#include "lines.h" #include "pixman_utils.h" typedef struct CairoCanvas CairoCanvas; @@ -837,459 +836,6 @@ static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl pixman_region32_fini(&dest_region); } -typedef struct { - lineGC base; - pixman_image_t *dest; - pixman_region32_t dest_region; - SpiceROP fore_rop; - SpiceROP back_rop; - int solid; - uint32_t color; - pixman_image_t *tile; - int tile_offset_x; - int tile_offset_y; -} StrokeGC; - -static void stroke_fill_spans(lineGC * pGC, - int num_spans, - SpicePoint *points, - int *widths, - int sorted, - int foreground) -{ - StrokeGC *strokeGC; - int i; - pixman_image_t *dest; - SpiceROP rop; - - strokeGC = (StrokeGC *)pGC; - dest = strokeGC->dest; - - num_spans = spice_canvas_clip_spans(&strokeGC->dest_region, - points, widths, num_spans, - points, widths, sorted); - - if (foreground) { - rop = strokeGC->fore_rop; - } else { - rop = strokeGC->back_rop; - } - - for (i = 0; i < num_spans; i++) { - if (strokeGC->solid) { - if (rop == SPICE_ROP_COPY) { - spice_pixman_fill_rect(dest, points[i].x, points[i].y, widths[i], 1, - strokeGC->color); - } else { - spice_pixman_fill_rect_rop(dest, points[i].x, points[i].y, widths[i], 1, - strokeGC->color, rop); - } - } else { - if (rop == SPICE_ROP_COPY) { - spice_pixman_tile_rect(dest, - points[i].x, points[i].y, - widths[i], 1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y); - } else { - spice_pixman_tile_rect_rop(dest, - points[i].x, points[i].y, - widths[i], 1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y, - rop); - } - } - } -} - -static void stroke_fill_rects(lineGC * pGC, - int num_rects, - pixman_rectangle32_t *rects, - int foreground) -{ - pixman_region32_t area; - pixman_box32_t *boxes; - StrokeGC *strokeGC; - pixman_image_t *dest; - SpiceROP rop; - int i; - pixman_box32_t *area_rects; - int n_area_rects; - - strokeGC = (StrokeGC *)pGC; - dest = strokeGC->dest; - - if (foreground) { - rop = strokeGC->fore_rop; - } else { - rop = strokeGC->back_rop; - } - - /* TODO: We can optimize this for more common cases where - dest is one rect */ - - boxes = (pixman_box32_t *)malloc(num_rects * sizeof(pixman_box32_t)); - for (i = 0; i < num_rects; i++) { - boxes[i].x1 = rects[i].x; - boxes[i].y1 = rects[i].y; - boxes[i].x2 = rects[i].x + rects[i].width; - boxes[i].y2 = rects[i].y + rects[i].height; - } - pixman_region32_init_rects(&area, boxes, num_rects); - pixman_region32_intersect(&area, &area, &strokeGC->dest_region); - free(boxes); - - area_rects = pixman_region32_rectangles(&area, &n_area_rects); - - for (i = 0; i < n_area_rects; i++) { - if (strokeGC->solid) { - if (rop == SPICE_ROP_COPY) { - spice_pixman_fill_rect(dest, - area_rects[i].x1, - area_rects[i].y1, - area_rects[i].x2 - area_rects[i].x1, - area_rects[i].y2 - area_rects[i].y1, - strokeGC->color); - } else { - spice_pixman_fill_rect_rop(dest, - area_rects[i].x1, - area_rects[i].y1, - area_rects[i].x2 - area_rects[i].x1, - area_rects[i].y2 - area_rects[i].y1, - strokeGC->color, rop); - } - } else { - if (rop == SPICE_ROP_COPY) { - spice_pixman_tile_rect(dest, - area_rects[i].x1, - area_rects[i].y1, - area_rects[i].x2 - area_rects[i].x1, - area_rects[i].y2 - area_rects[i].y1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y); - } else { - spice_pixman_tile_rect_rop(dest, - area_rects[i].x1, - area_rects[i].y1, - area_rects[i].x2 - area_rects[i].x1, - area_rects[i].y2 - area_rects[i].y1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y, - rop); - } - } - } - pixman_region32_fini(&area); -} - -typedef struct { - SpicePoint *points; - int num_points; - int size; -} StrokeLines; - -static void stroke_lines_init(StrokeLines *lines) -{ - lines->points = (SpicePoint *)malloc(10*sizeof(SpicePoint)); - lines->size = 10; - lines->num_points = 0; -} - -static void stroke_lines_free(StrokeLines *lines) -{ - free(lines->points); -} - -static void stroke_lines_append(StrokeLines *lines, - int x, int y) -{ - if (lines->num_points == lines->size) { - lines->size *= 2; - lines->points = (SpicePoint *)realloc(lines->points, - lines->size * sizeof(SpicePoint)); - } - lines->points[lines->num_points].x = x; - lines->points[lines->num_points].y = y; - lines->num_points++; -} - -static void stroke_lines_append_fix(StrokeLines *lines, - SpicePointFix *point) -{ - stroke_lines_append(lines, - fix_to_int(point->x), - fix_to_int(point->y)); -} - -static inline int64_t dot(SPICE_FIXED28_4 x1, - SPICE_FIXED28_4 y1, - SPICE_FIXED28_4 x2, - SPICE_FIXED28_4 y2) -{ - return (((int64_t)x1) *((int64_t)x2) + - ((int64_t)y1) *((int64_t)y2)) >> 4; -} - -static inline int64_t dot2(SPICE_FIXED28_4 x, - SPICE_FIXED28_4 y) -{ - return (((int64_t)x) *((int64_t)x) + - ((int64_t)y) *((int64_t)y)) >> 4; -} - -static void subdivide_bezier(StrokeLines *lines, - SpicePointFix point0, - SpicePointFix point1, - SpicePointFix point2, - SpicePointFix point3) -{ - int64_t A2, B2, C2, AB, CB, h1, h2; - - A2 = dot2(point1.x - point0.x, - point1.y - point0.y); - B2 = dot2(point3.x - point0.x, - point3.y - point0.y); - C2 = dot2(point2.x - point3.x, - point2.y - point3.y); - - AB = dot(point1.x - point0.x, - point1.y - point0.y, - point3.x - point0.x, - point3.y - point0.y); - - CB = dot(point2.x - point3.x, - point2.y - point3.y, - point0.x - point3.x, - point0.y - point3.y); - - h1 = (A2*B2 - AB*AB) >> 3; - h2 = (C2*B2 - CB*CB) >> 3; - - if (h1 < B2 && h2 < B2) { - /* deviation squared less than half a pixel, use straight line */ - stroke_lines_append_fix(lines, &point3); - } else { - SpicePointFix point01, point23, point12, point012, point123, point0123; - - point01.x = (point0.x + point1.x) / 2; - point01.y = (point0.y + point1.y) / 2; - point12.x = (point1.x + point2.x) / 2; - point12.y = (point1.y + point2.y) / 2; - point23.x = (point2.x + point3.x) / 2; - point23.y = (point2.y + point3.y) / 2; - point012.x = (point01.x + point12.x) / 2; - point012.y = (point01.y + point12.y) / 2; - point123.x = (point12.x + point23.x) / 2; - point123.y = (point12.y + point23.y) / 2; - point0123.x = (point012.x + point123.x) / 2; - point0123.y = (point012.y + point123.y) / 2; - - subdivide_bezier(lines, point0, point01, point012, point0123); - subdivide_bezier(lines, point0123, point123, point23, point3); - } -} - -static void stroke_lines_append_bezier(StrokeLines *lines, - SpicePointFix *point1, - SpicePointFix *point2, - SpicePointFix *point3) -{ - SpicePointFix point0; - - point0.x = int_to_fix(lines->points[lines->num_points-1].x); - point0.y = int_to_fix(lines->points[lines->num_points-1].y); - - subdivide_bezier(lines, point0, *point1, *point2, *point3); -} - -static void stroke_lines_draw(StrokeLines *lines, - lineGC *gc, - int dashed) -{ - if (lines->num_points != 0) { - if (dashed) { - spice_canvas_zero_dash_line(gc, CoordModeOrigin, - lines->num_points, lines->points); - } else { - spice_canvas_zero_line(gc, CoordModeOrigin, - lines->num_points, lines->points); - } - lines->num_points = 0; - } -} - - -static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke) -{ - CairoCanvas *canvas = (CairoCanvas *)spice_canvas; - StrokeGC gc = { {0} }; - lineGCOps ops = { - stroke_fill_spans, - stroke_fill_rects - }; - uint32_t *data_size; - uint32_t more; - SpicePathSeg *seg; - StrokeLines lines; - int i; - int dashed; - - pixman_region32_init_rect(&gc.dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(&canvas->base, &gc.dest_region, clip); - - if (pixman_region32_n_rects(&gc.dest_region) == 0) { - touch_brush(&canvas->base, &stroke->brush); - pixman_region32_fini(&gc.dest_region); - return; - } - - gc.fore_rop = ropd_descriptor_to_rop(stroke->fore_mode, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST); - gc.back_rop = ropd_descriptor_to_rop(stroke->back_mode, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST); - - gc.dest = canvas->image; - gc.base.width = pixman_image_get_width(gc.dest); - gc.base.height = pixman_image_get_height(gc.dest); - gc.base.alu = gc.fore_rop; - gc.base.lineWidth = 0; - - /* dash */ - gc.base.dashOffset = 0; - gc.base.dash = NULL; - gc.base.numInDashList = 0; - gc.base.lineStyle = LineSolid; - /* win32 cosmetic lines are endpoint-exclusive, so use CapNotLast */ - gc.base.capStyle = CapNotLast; - gc.base.joinStyle = JoinMiter; - gc.base.ops = &ops; - - dashed = 0; - if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { - SPICE_FIXED28_4 *style = (SPICE_FIXED28_4*)SPICE_GET_ADDRESS(stroke->attr.style); - int nseg; - - dashed = 1; - - nseg = stroke->attr.style_nseg; - - /* To truly handle back_mode we should use LineDoubleDash here - and treat !foreground as back_rop using the same brush. - However, using the same brush for that seems wrong. - The old cairo backend was stroking the non-dashed line with - rop_mode before enabling dashes for the foreground which is - not right either. The gl an gdi backend don't use back_mode - at all */ - gc.base.lineStyle = LineOnOffDash; - gc.base.dash = (unsigned char *)malloc(nseg); - gc.base.numInDashList = nseg; - access_test(&canvas->base, style, nseg * sizeof(*style)); - - if (stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP) { - gc.base.dash[stroke->attr.style_nseg - 1] = fix_to_int(style[0]); - for (i = 0; i < stroke->attr.style_nseg - 1; i++) { - gc.base.dash[i] = fix_to_int(style[i+1]); - } - gc.base.dashOffset = gc.base.dash[0]; - } else { - for (i = 0; i < stroke->attr.style_nseg; i++) { - gc.base.dash[i] = fix_to_int(style[i]); - } - } - } - - switch (stroke->brush.type) { - case SPICE_BRUSH_TYPE_NONE: - gc.solid = TRUE; - gc.color = 0; - break; - case SPICE_BRUSH_TYPE_SOLID: - gc.solid = TRUE; - gc.color = stroke->brush.u.color; - break; - case SPICE_BRUSH_TYPE_PATTERN: - gc.solid = FALSE; - gc.tile = canvas_get_image(&canvas->base, - stroke->brush.u.pattern.pat); - gc.tile_offset_x = stroke->brush.u.pattern.pos.x; - gc.tile_offset_y = stroke->brush.u.pattern.pos.y; - break; - default: - CANVAS_ERROR("invalid brush type"); - } - - data_size = (uint32_t*)SPICE_GET_ADDRESS(stroke->path); - access_test(&canvas->base, data_size, sizeof(uint32_t)); - more = *data_size; - seg = (SpicePathSeg*)(data_size + 1); - - stroke_lines_init(&lines); - - do { - access_test(&canvas->base, seg, sizeof(SpicePathSeg)); - - uint32_t flags = seg->flags; - SpicePointFix* point = (SpicePointFix*)seg->data; - SpicePointFix* end_point = point + seg->count; - access_test(&canvas->base, point, (unsigned long)end_point - (unsigned long)point); - ASSERT(point < end_point); - more -= ((unsigned long)end_point - (unsigned long)seg); - seg = (SpicePathSeg*)end_point; - - if (flags & SPICE_PATH_BEGIN) { - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - stroke_lines_append_fix(&lines, point); - point++; - } - - if (flags & SPICE_PATH_BEZIER) { - ASSERT((point - end_point) % 3 == 0); - for (; point + 2 < end_point; point += 3) { - stroke_lines_append_bezier(&lines, - &point[0], - &point[1], - &point[2]); - } - } else - { - for (; point < end_point; point++) { - stroke_lines_append_fix(&lines, point); - } - } - if (flags & SPICE_PATH_END) { - if (flags & SPICE_PATH_CLOSE) { - stroke_lines_append(&lines, - lines.points[0].x, lines.points[0].y); - } - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - } - } while (more); - - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - - if (gc.base.dash) { - free(gc.base.dash); - } - stroke_lines_free(&lines); - - if (!gc.solid && gc.tile) { - pixman_image_unref(gc.tile); - } - - pixman_region32_fini(&gc.dest_region); -} - static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest, int dest_stride, const SpiceRect *area) { CairoCanvas *canvas = (CairoCanvas *)spice_canvas; @@ -1397,7 +943,6 @@ void cairo_canvas_init() //unsafe global function canvas_base_init_ops(&cairo_canvas_ops); cairo_canvas_ops.draw_text = canvas_draw_text; - cairo_canvas_ops.draw_stroke = canvas_draw_stroke; cairo_canvas_ops.draw_rop3 = canvas_draw_rop3; cairo_canvas_ops.put_image = canvas_put_image; cairo_canvas_ops.clear = canvas_clear; |