[PS/PDF] Fix xstep/ystep values for CAIRO_EXTEND_NONE

This fixes the fallback-resolution test, as well as the two of
surface-pattern-scale-up and surface-pattern-scale-down.
This commit is contained in:
Behdad Esfahbod 2007-02-27 18:47:47 -05:00
parent de0a6522b0
commit e2ce27db30
2 changed files with 43 additions and 36 deletions

View file

@ -878,7 +878,7 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */
cairo_matrix_t cairo_p2d, pdf_p2d;
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
int xstep, ystep;
double xstep, ystep;
cairo_rectangle_int16_t surface_extents;
/* XXX: Should do something clever here for PDF source surfaces ? */
@ -905,36 +905,30 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
switch (extend) {
case CAIRO_EXTEND_NONE:
{
/* In PDF, (as far as I can tell), all patterns are
/* In PS/PDF, (as far as I can tell), all patterns are
* repeating. So we support cairo's EXTEND_NONE semantics
* by setting the repeat step size to a size large enough
* to guarantee that no more than a single occurrence will
* be visible.
*
* First, map the pattern's extents through the inverse
* pattern matrix to compute the device-space bounds of
* the desired single occurrence. Then consider the bounds
* of (the union of this rectangle with the target surface
* extents). If the repeat size is larger than the
* diagonal of the bounds of the union, then it is
* guaranteed to never repeat visibly.
* First, map the surface extents into pattern space (since
* xstep and ystep are in pattern space). Then use an upper
* bound on the length of the diagonal of the pattern image
* and the surface as repeat size. This guarantees to never
* repeat visibly.
*/
double x1 = 0.0, y1 = 0.0;
double x2 = image->width, y2 = image->height;
cairo_matrix_t surface_to_device = pattern->base.matrix;
cairo_matrix_invert (&surface_to_device);
_cairo_matrix_transform_bounding_box (&surface_to_device,
double x2 = surface->width, y2 = surface->height;
_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
&x1, &y1, &x2, &y2,
NULL);
/* Rather than computing precise bounds of the union, just
* add the surface extents unconditionally. We only
* required an answer that's large enough, we don't really
* care if it's not as tight as possible. */
x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width;
y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height;
/* Similarly, don't bother computing the square root to
* determine the length of the final diagonal. */
xstep = ystep = _cairo_lround (ceil (x1 + y1));
* care if it's not as tight as possible.*/
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
image->width + image->height);
}
break;
case CAIRO_EXTEND_REPEAT:
@ -991,8 +985,8 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
stream = _cairo_pdf_surface_open_stream (surface,
FALSE,
" /BBox [0 0 %d %d]\r\n"
" /XStep %d\r\n"
" /YStep %d\r\n"
" /XStep %f\r\n"
" /YStep %f\r\n"
" /PatternType 1\r\n"
" /TilingType 1\r\n"
" /PaintType 1\r\n"

View file

@ -1704,7 +1704,7 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
{
double bbox_width, bbox_height;
int xstep, ystep;
double xstep, ystep;
cairo_matrix_t inverse = pattern->base.matrix;
cairo_matrix_invert (&inverse);
@ -1732,22 +1732,35 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
bbox_width = image->width;
bbox_height = image->height;
/* In PostScript, (as far as I can tell), all patterns are
* repeating. So we support cairo's EXTEND_NONE semantics by
* setting the repeat step size to the larger of the image size
* and the extents of the destination surface. That way we
* guarantee the pattern will not repeat.
*/
switch (pattern->base.extend) {
case CAIRO_EXTEND_NONE:
/* XXX We may need to update this to something like the code
* that is in PDF. The point is, xstep/ystep are in pattern
* space, not device space, so surface->width/height do not
* make much sense. But most of the time patterns scale up,
* not down, so this is less of a problem. */
xstep = MAX (image->width, surface->width);
ystep = MAX (image->height, surface->height);
{
/* In PS/PDF, (as far as I can tell), all patterns are
* repeating. So we support cairo's EXTEND_NONE semantics
* by setting the repeat step size to a size large enough
* to guarantee that no more than a single occurrence will
* be visible.
*
* First, map the surface extents into pattern space (since
* xstep and ystep are in pattern space). Then use an upper
* bound on the length of the diagonal of the pattern image
* and the surface as repeat size. This guarantees to never
* repeat visibly.
*/
double x1 = 0.0, y1 = 0.0;
double x2 = surface->width, y2 = surface->height;
_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
&x1, &y1, &x2, &y2,
NULL);
/* Rather than computing precise bounds of the union, just
* add the surface extents unconditionally. We only
* required an answer that's large enough, we don't really
* care if it's not as tight as possible.*/
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
image->width + image->height);
break;
}
case CAIRO_EXTEND_REPEAT:
case CAIRO_EXTEND_REFLECT:
xstep = image->width;
@ -1773,7 +1786,7 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
" /BBox [0 0 %f %f]\n",
bbox_width, bbox_height);
_cairo_output_stream_printf (surface->stream,
" /XStep %d /YStep %d\n",
" /XStep %f /YStep %f\n",
xstep, ystep);
_cairo_output_stream_printf (surface->stream,
" /PaintProc { MyPattern } bind\n"