Commit b1192bea authored by Adrian Johnson's avatar Adrian Johnson
Browse files

Don't cull very thin lines on vector surfaces

On vector surfaces, use a minimum line width when calculating extents.

Bug 77298
parent 6656cafe
......@@ -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;
}
......@@ -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);
}
......
......@@ -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)
......
......@@ -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);
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -2146,7 +2146,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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment