Skip to content

Commit

Permalink
Don't cull very thin lines on vector surfaces
Browse files Browse the repository at this point in the history
On vector surfaces, use a minimum line width when calculating extents.

Bug 77298
  • Loading branch information
Adrian Johnson committed Oct 17, 2015
1 parent 6656caf commit b1192be
Show file tree
Hide file tree
Showing 26 changed files with 91 additions and 34 deletions.
8 changes: 5 additions & 3 deletions src/cairo-analysis-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion src/cairo-composite-rectangles.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/cairo-gstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/cairo-image-source.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-image-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion src/cairo-paginated-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
23 changes: 23 additions & 0 deletions src/cairo-path-bounds.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,25 @@ 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) {
cairo_box_t box_extents;
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);
Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-pdf-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-ps-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
8 changes: 5 additions & 3 deletions src/cairo-recording-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/cairo-script-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ",
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion src/cairo-surface-observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/cairo-surface-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-surface-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions src/cairo-surface-subsurface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions src/cairo-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */ \
Expand Down Expand Up @@ -400,14 +401,16 @@ 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 ();

surface->backend = backend;
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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-svg-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-type3-glyph-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/cairo-xcb-surface-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-xcb-surface-render.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion src/cairo-xcb-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,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;
Expand Down
9 changes: 6 additions & 3 deletions src/cairo-xlib-source.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-xlib-surface-shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/cairo-xlib-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,8 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
_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;
Expand Down
Loading

0 comments on commit b1192be

Please sign in to comment.