From a6e6380eb64e5edb194f72c93aa658d9ba1cdee8 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 21 Sep 2015 21:35:05 +0930 Subject: [PATCH 1/2] Don't cull very thin lines on vector surfaces On vector surfaces, use a minimum line width when calculating extents. Bug 77298 --- src/cairo-analysis-surface.c | 8 +++++--- src/cairo-composite-rectangles.c | 2 +- src/cairo-gstate.c | 1 + src/cairo-image-source.c | 5 +++-- src/cairo-image-surface.c | 3 ++- src/cairo-paginated-surface.c | 3 ++- src/cairo-path-bounds.c | 23 +++++++++++++++++++++++ src/cairo-pdf-surface.c | 3 ++- src/cairo-ps-surface.c | 3 ++- src/cairo-recording-surface.c | 8 +++++--- src/cairo-script-surface.c | 6 ++++-- src/cairo-surface-observer.c | 3 ++- src/cairo-surface-private.h | 1 + src/cairo-surface-snapshot.c | 3 ++- src/cairo-surface-subsurface.c | 6 ++++-- src/cairo-surface.c | 7 +++++-- src/cairo-svg-surface.c | 3 ++- src/cairo-type3-glyph-surface.c | 3 ++- src/cairo-xcb-surface-core.c | 6 ++++-- src/cairo-xcb-surface-render.c | 3 ++- src/cairo-xcb-surface.c | 3 ++- src/cairo-xlib-source.c | 9 ++++++--- src/cairo-xlib-surface-shm.c | 3 ++- src/cairo-xlib-surface.c | 3 ++- src/cairoint.h | 4 +++- src/win32/cairo-win32-printing-surface.c | 3 ++- 26 files changed, 91 insertions(+), 34 deletions(-) diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index 8516094..b4069ea 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -122,7 +122,7 @@ attach_proxy (cairo_surface_t *source, if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, target->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, target->content, target->is_vector); proxy->target = target; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -740,7 +740,8 @@ _cairo_analysis_surface_create (cairo_surface_t *target) _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + target->is_vector); cairo_matrix_init_identity (&surface->ctm); surface->has_ctm = FALSE; @@ -928,7 +929,8 @@ _cairo_null_surface_create (cairo_content_t content) _cairo_surface_init (surface, &cairo_null_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ return surface; } diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c index 6c3e97d..495d200 100644 --- a/src/cairo-composite-rectangles.c +++ b/src/cairo-composite-rectangles.c @@ -353,7 +353,7 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten return CAIRO_INT_STATUS_NOTHING_TO_DO; } - _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask); + _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, surface->is_vector, &extents->mask); return _cairo_composite_rectangles_intersect (extents, clip); } diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 4bf945c..4c7eb11 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1228,6 +1228,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate, _cairo_path_fixed_approximate_stroke_extents (path, &gstate->stroke_style, &gstate->ctm, + gstate->target->is_vector, &extents); if (x < extents.x || x > extents.x + extents.width || y < extents.y || y > extents.y + extents.height) diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c index 950053d..4b79db9 100644 --- a/src/cairo-image-source.c +++ b/src/cairo-image-source.c @@ -1081,7 +1081,7 @@ attach_proxy (cairo_surface_t *source, if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content, FALSE); proxy->image = image; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -1592,7 +1592,8 @@ _cairo_image_source_create_for_pattern (cairo_surface_t *dst, _cairo_surface_init (&source->base, &_cairo_image_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ source->is_opaque_solid = pattern == NULL || _cairo_pattern_is_opaque_solid (pattern); diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 1fd563d..13d6272 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -188,7 +188,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, _cairo_surface_init (&surface->base, &_cairo_image_surface_backend, NULL, /* device */ - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ _cairo_image_surface_init (surface, pixman_image, pixman_format); diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c index 68e4e0e..b81215a 100644 --- a/src/cairo-paginated-surface.c +++ b/src/cairo-paginated-surface.c @@ -107,7 +107,8 @@ _cairo_paginated_surface_create (cairo_surface_t *target, _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend, NULL, /* device */ - content); + content, + target->is_vector); /* Override surface->base.type with target's type so we don't leak * evidence of the paginated wrapper out to the user. */ diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c index 9c72224..624b3cb 100644 --- a/src/cairo-path-bounds.c +++ b/src/cairo-path-bounds.c @@ -154,6 +154,7 @@ void _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, + cairo_bool_t is_vector, cairo_rectangle_int_t *extents) { if (path->has_extents) { @@ -161,6 +162,17 @@ _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, double dx, dy; _cairo_stroke_style_max_distance_from_path (style, path, ctm, &dx, &dy); + if (is_vector) + { + /* When calculating extents for vector surfaces, ensure lines thinner + * than the fixed point resolution are not optimized away. */ + double min = _cairo_fixed_to_double (CAIRO_FIXED_EPSILON*2); + if (dx < min) + dx = min; + + if (dy < min) + dy = min; + } box_extents = path->extents; box_extents.p1.x -= _cairo_fixed_from_double (dx); @@ -185,6 +197,17 @@ _cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path, { cairo_polygon_t polygon; cairo_status_t status; + cairo_stroke_style_t style; + + /* When calculating extents for vector surfaces, ensure lines thinner + * than the fixed point resolution are not optimized away. */ + double min_line_width = _cairo_fixed_to_double (CAIRO_FIXED_EPSILON*2); + if (stroke_style->line_width < min_line_width) + { + style = *stroke_style; + style.line_width = min_line_width; + stroke_style = &style; + } _cairo_polygon_init (&polygon, NULL, 0); status = _cairo_path_fixed_stroke_to_polygon (path, diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 4bc2947..42854b2 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -367,7 +367,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->output = output; surface->width = width; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 03eba62..7f61321 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1017,7 +1017,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_surface_init (&surface->base, &cairo_ps_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->final_stream = stream; diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 78e7cfa..c7cd4a1 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -393,7 +393,8 @@ cairo_recording_surface_create (cairo_content_t content, _cairo_surface_init (&surface->base, &cairo_recording_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ surface->unbounded = TRUE; @@ -556,7 +557,7 @@ attach_proxy (cairo_surface_t *source, if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content, FALSE); proxy->image = image; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -1431,7 +1432,8 @@ _cairo_recording_surface_snapshot (void *abstract_other) _cairo_surface_init (&surface->base, &cairo_recording_surface_backend, NULL, /* device */ - other->base.content); + other->base.content, + other->base.is_vector); surface->extents_pixels = other->extents_pixels; surface->extents = other->extents; diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c index a4cefde..ea0117d 100644 --- a/src/cairo-script-surface.c +++ b/src/cairo-script-surface.c @@ -1111,7 +1111,8 @@ attach_snapshot (cairo_script_context_t *ctx, _cairo_surface_init (&surface->base, &script_snapshot_backend, &ctx->base, - source->content); + source->content, + source->is_vector); _cairo_output_stream_printf (ctx->stream, "dup /s%d exch def ", @@ -3648,7 +3649,8 @@ _cairo_script_surface_create_internal (cairo_script_context_t *ctx, _cairo_surface_init (&surface->base, &_cairo_script_surface_backend, &ctx->base, - content); + content, + TRUE); /* is_vector */ _cairo_surface_wrapper_init (&surface->wrapper, passthrough); diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c index 52b0136..9d12fcd 100644 --- a/src/cairo-surface-observer.c +++ b/src/cairo-surface-observer.c @@ -385,7 +385,8 @@ _cairo_surface_create_observer_internal (cairo_device_t *device, _cairo_surface_init (&surface->base, &_cairo_surface_observer_backend, device, - target->content); + target->content, + target->is_vector); status = log_init (&surface->log, ((cairo_device_observer_t *)device)->log.record != NULL); diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h index f20ab07..e4ad5f3 100644 --- a/src/cairo-surface-private.h +++ b/src/cairo-surface-private.h @@ -70,6 +70,7 @@ struct _cairo_surface { unsigned is_clear : 1; unsigned has_font_options : 1; unsigned owns_device : 1; + unsigned is_vector : 1; cairo_user_data_array_t user_data; cairo_user_data_array_t mime_data; diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c index 68bf905..3477ac5 100644 --- a/src/cairo-surface-snapshot.c +++ b/src/cairo-surface-snapshot.c @@ -265,7 +265,8 @@ _cairo_surface_snapshot (cairo_surface_t *surface) _cairo_surface_init (&snapshot->base, &_cairo_surface_snapshot_backend, NULL, /* device */ - surface->content); + surface->content, + surface->is_vector); snapshot->base.type = surface->type; CAIRO_MUTEX_INIT (snapshot->mutex); diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c index b7dfd9d..5b7ce0c 100644 --- a/src/cairo-surface-subsurface.c +++ b/src/cairo-surface-subsurface.c @@ -478,7 +478,8 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target, _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ - target->content); + target->content, + target->is_vector); /* XXX forced integer alignment */ surface->extents.x = ceil (x); @@ -528,7 +529,8 @@ _cairo_surface_create_for_rectangle_int (cairo_surface_t *target, _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ - target->content); + target->content, + target->is_vector); surface->extents = *extents; surface->extents.x *= target->device_transform.xx; diff --git a/src/cairo-surface.c b/src/cairo-surface.c index bfe3fa1..46f6894 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -113,7 +113,8 @@ const cairo_surface_t name = { \ FALSE, /* finished */ \ TRUE, /* is_clear */ \ FALSE, /* has_font_options */ \ - FALSE, /* owns_device */ \ + FALSE, /* owns_device */ \ + FALSE, /* is_vector */ \ { 0, 0, 0, NULL, }, /* user_data */ \ { 0, 0, 0, NULL, }, /* mime_data */ \ { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \ @@ -400,7 +401,8 @@ void _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, - cairo_content_t content) + cairo_content_t content, + cairo_bool_t is_vector) { CAIRO_MUTEX_INITIALIZE (); @@ -408,6 +410,7 @@ _cairo_surface_init (cairo_surface_t *surface, surface->device = cairo_device_reference (device); surface->content = content; surface->type = backend->type; + surface->is_vector = is_vector; CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1); surface->status = CAIRO_STATUS_SUCCESS; diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 372ef45..2e023b3 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -483,7 +483,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, _cairo_surface_init (&surface->base, &cairo_svg_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ surface->width = width; surface->height = height; diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c index c99d461..8c154b3 100644 --- a/src/cairo-type3-glyph-surface.c +++ b/src/cairo-type3-glyph-surface.c @@ -90,7 +90,8 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, _cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->scaled_font = scaled_font; surface->stream = stream; diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c index 9c0c0a0..40d0ca4 100644 --- a/src/cairo-xcb-surface-core.c +++ b/src/cairo-xcb-surface-core.c @@ -93,7 +93,8 @@ _cairo_xcb_pixmap_create (cairo_xcb_surface_t *target, _cairo_surface_init (&surface->base, &_cairo_xcb_pixmap_backend, NULL, - target->base.content); + target->base.content, + FALSE); /* is_vector */ surface->connection = target->connection; surface->screen = target->screen; @@ -126,7 +127,8 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target) _cairo_surface_init (&surface->base, &_cairo_xcb_pixmap_backend, NULL, - target->base.content); + target->base.content, + FALSE); /* is_vector */ surface->connection = target->connection; surface->screen = target->screen; diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index 044339b..64a3d5a 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -122,7 +122,8 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, _cairo_surface_init (&surface->base, &_cairo_xcb_picture_backend, &screen->connection->device, - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ cairo_list_add (&surface->link, &screen->pictures); diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index d7e0d73..9ab1253 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -1082,7 +1082,8 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen, _cairo_surface_init (&surface->base, &_cairo_xcb_surface_backend, &screen->connection->device, - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ surface->connection = _cairo_xcb_connection_reference (screen->connection); surface->screen = screen; diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c index 1591f58..d6ea06a 100644 --- a/src/cairo-xlib-source.c +++ b/src/cairo-xlib-source.c @@ -120,7 +120,8 @@ source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap) _cairo_surface_init (&source->base, &cairo_xlib_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ /* The source exists only within an operation */ source->picture = picture; @@ -626,7 +627,8 @@ static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst, _cairo_surface_init (&source->base, &cairo_xlib_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ pa.subwindow_mode = IncludeInferiors; source->picture = XRenderCreatePicture (dpy, @@ -971,7 +973,8 @@ surface_source (cairo_xlib_surface_t *dst, _cairo_surface_init (&proxy->source.base, &cairo_xlib_proxy_backend, dst->base.device, - src->content); + src->content, + src->is_vector); proxy->source.dpy = dst->display->display; proxy->source.picture = XRenderCreatePicture (proxy->source.dpy, diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c index fb40699..3187223 100644 --- a/src/cairo-xlib-surface-shm.c +++ b/src/cairo-xlib-surface-shm.c @@ -821,7 +821,8 @@ _cairo_xlib_shm_surface_create (cairo_xlib_surface_t *other, _cairo_surface_init (&shm->image.base, &cairo_xlib_shm_surface_backend, other->base.device, - _cairo_content_from_pixman_format (format)); + _cairo_content_from_pixman_format (format), + FALSE); /* is_vector */ if (_cairo_xlib_display_acquire (other->base.device, &display)) goto cleanup_shm; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 029a542..3f407c3 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1796,7 +1796,8 @@ found: _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, screen->device, - _xrender_format_to_content (xrender_format)); + _xrender_format_to_content (xrender_format), + FALSE); /* is_vector */ surface->screen = screen; surface->compositor = display->compositor; diff --git a/src/cairoint.h b/src/cairoint.h index 555aa89..f781748 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1021,6 +1021,7 @@ cairo_private void _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, + cairo_bool_t vector, cairo_rectangle_int_t *extents); cairo_private cairo_status_t @@ -1335,7 +1336,8 @@ cairo_private void _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, - cairo_content_t content); + cairo_content_t content, + cairo_bool_t is_vector); cairo_private void _cairo_surface_set_font_options (cairo_surface_t *surface, diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c index 6005cb5..fa36621 100644 --- a/src/win32/cairo-win32-printing-surface.c +++ b/src/win32/cairo-win32-printing-surface.c @@ -1867,7 +1867,8 @@ cairo_win32_printing_surface_create (HDC hdc) _cairo_surface_init (&surface->win32.base, &cairo_win32_printing_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ paginated = _cairo_paginated_surface_create (&surface->win32.base, CAIRO_CONTENT_COLOR_ALPHA, -- 2.1.4