[cairo] Patch for cairo - high resolution images in PDF surface.
Andrew McRae
amcrae at employees.org
Sat Nov 25 19:24:49 PST 2006
Comrades,
Attached is a patch generated against the git mainline - I wasn't
entirely sure if the right thing to do was to send it here or somewhere
else. At least I'll learn the right way to do it for next time! :-)
This patch allows higher resolution images to be embedded in
PDF surfaces - the idea is that you can set the fallback resolution
on the image, and the PDF surface can use this as a hint for the
DPI of the image. One part of the change is to have a flag to
remember when the fallback resolution is actually set (as opposed
to just having default values).
surface = cairo_pdf_surface_create("test.pdf",
8 * 72.0, 10 * 72.0);
img = cairo_image_surface_create_from_png("large.png");
cr = cairo_create (surface);
// Use 300 DPI for image.
cairo_surface_set_fallback_resolution(img, 300.0, 300.0);
// Use 1/2 inch margin.
cairo_set_source_surface(cr, img, 36.0, 36.0);
cairo_paint(cr);
cairo_show_page(cr);
Feedback welcome...
Cheers,
Andrew McRae
-------------- next part --------------
Subject: [PATCH] Use fallback resolution as a hint for embedded images in PDF surfaces.
---
src/cairo-image-surface.c | 1 +
src/cairo-pdf-surface.c | 35 ++++++++++++++++++++++++++---------
src/cairo-surface-fallback.c | 5 +++++
src/cairo-surface.c | 15 ++++++++++++---
src/cairoint.h | 1 +
5 files changed, 45 insertions(+), 12 deletions(-)
840229bcfddd66e4e0912e374729360278c4fc1f
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 0021ae9..84fe588 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -57,6 +57,7 @@ const cairo_image_surface_t _cairo_image
0.0, 1.0,
0.0, 0.0
}, /* device_transform_inverse */
+ FALSE, /* fallback_set */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 25d367e..0d3208a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -850,6 +850,7 @@ emit_surface_pattern (cairo_pdf_surface_
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
int xstep, ystep;
cairo_rectangle_int16_t surface_extents;
+ double xscale, yscale;
/* XXX: Should do something clever here for PDF source surfaces ? */
@@ -889,6 +890,18 @@ emit_surface_pattern (cairo_pdf_surface_
xstep = 0;
ystep = 0;
}
+ /*
+ * If the fallback resolution has been set on this image,
+ * then use that as the image resolution instead of using
+ * the surface's space.
+ */
+ if (image->base.fallback_set) {
+ xscale = image->width * 72.0 / image->base.x_fallback_resolution;
+ yscale = image->height * 72.0 / image->base.y_fallback_resolution;
+ } else {
+ xscale = image->width;
+ yscale = image->height;
+ }
/* At this point, (that is, within the surface backend interface),
* the pattern's matrix maps from cairo's device space to cairo's
@@ -899,7 +912,7 @@ emit_surface_pattern (cairo_pdf_surface_
* pattern space, (which has a size that we establish in the BBox
* dictionary entry), to the PDF page's *initial* space, (which
* does not benefit from the Y-axis flipping matrix that we emit
- * on each page). So the PDF patterns patrix maps from a
+ * on each page). So the PDF patterns matrix maps from a
* (width,height) pattern space to a device space with the origin
* in the lower-left corner.
*
@@ -909,13 +922,14 @@ emit_surface_pattern (cairo_pdf_surface_
* the PDF origin to cairo's origin). We then multiply in the
* inverse of the cairo pattern matrix, (since it maps from device
* to pattern, while we're setting up pattern to device). Finally,
- * we translate back down by the image height and flip again to
- * end up at the lower-left origin that PDF expects.
+ * we translate back down by the image height (scaled by the DPI
+ * resolution) and flip again to end up at the lower-left origin that
+ * PDF expects.
*
* Additionally, within the stream that paints the pattern itself,
* we are using a PDF image object that has a size of (1,1) so we
- * have to scale it up by the image width and height to fill our
- * pattern cell.
+ * have to scale it up by the image width and height (in the
+ * desired fallback resolution) to fill our pattern cell.
*/
cairo_p2d = pattern->base.matrix;
cairo_matrix_invert (&cairo_p2d);
@@ -924,7 +938,7 @@ emit_surface_pattern (cairo_pdf_surface_
cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
- cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
+ cairo_matrix_translate (&pdf_p2d, 0.0, xscale);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
stream = _cairo_pdf_surface_open_stream (surface,
@@ -944,10 +958,13 @@ emit_surface_pattern (cairo_pdf_surface_
image_resource.id,
image_resource.id);
+ /*
+ * Output a transformation matrix that uses the fallback scaling
+ * so that the bitmapped image is mapped to the desired resolution
+ */
_cairo_output_stream_printf (surface->output,
- "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
- image->width, image->height,
- image_resource.id);
+ "q %f 0 0 %f 0 0 cm /res%d Do Q\r\n",
+ xscale, yscale, image_resource.id);
_cairo_pdf_surface_close_stream (surface);
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 2d23411..1287b75 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -988,6 +988,11 @@ _cairo_surface_fallback_snapshot (cairo_
snapshot->device_transform = surface->device_transform;
snapshot->device_transform_inverse = surface->device_transform_inverse;
+ if (surface->fallback_set) {
+ cairo_surface_set_fallback_resolution (snapshot,
+ surface->x_fallback_resolution,
+ surface->y_fallback_resolution);
+ }
snapshot->is_snapshot = TRUE;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index dfcf39d..f90d535 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -61,6 +61,7 @@ const cairo_surface_t _cairo_surface_nil
0.0, 1.0,
0.0, 0.0
}, /* device_transform_inverse */
+ FALSE, /* fallback_set */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
@@ -95,6 +96,7 @@ const cairo_surface_t _cairo_surface_nil
0.0, 1.0,
0.0, 0.0
}, /* device_transform_inverse */
+ FALSE, /* fallback_set */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
@@ -129,6 +131,7 @@ const cairo_surface_t _cairo_surface_nil
0.0, 1.0,
0.0, 0.0
}, /* device_transform_inverse */
+ FALSE, /* fallback_set */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
@@ -255,6 +258,7 @@ _cairo_surface_init (cairo_surface_t *
cairo_matrix_init_identity (&surface->device_transform);
cairo_matrix_init_identity (&surface->device_transform_inverse);
+ surface->fallback_set = FALSE;
surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
@@ -290,9 +294,10 @@ _cairo_surface_create_similar_scratch (c
cairo_surface_get_font_options (other, &options);
_cairo_surface_set_font_options (surface, &options);
- cairo_surface_set_fallback_resolution (surface,
- other->x_fallback_resolution,
- other->y_fallback_resolution);
+ if (other->fallback_set)
+ cairo_surface_set_fallback_resolution (surface,
+ other->x_fallback_resolution,
+ other->y_fallback_resolution);
return surface;
}
@@ -835,6 +840,9 @@ slim_hidden_def (cairo_surface_get_devic
* resolution used for these image fallbacks, (larger values will
* result in more detailed images, but also larger file sizes).
*
+ * If the backend supports the operation, it can still use the
+ * fallback resolution as a hint for the operation.
+ *
* Some examples of natively vector-oriented backends are the ps, pdf,
* and svg backends.
*
@@ -857,6 +865,7 @@ cairo_surface_set_fallback_resolution (c
{
surface->x_fallback_resolution = x_pixels_per_inch;
surface->y_fallback_resolution = y_pixels_per_inch;
+ surface->fallback_set = TRUE;
}
slim_hidden_def (cairo_surface_set_fallback_resolution);
diff --git a/src/cairoint.h b/src/cairoint.h
index 1f74d62..f0c987f 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -951,6 +951,7 @@ struct _cairo_surface {
cairo_matrix_t device_transform;
cairo_matrix_t device_transform_inverse;
+ cairo_bool_t fallback_set;
double x_fallback_resolution;
double y_fallback_resolution;
--
1.1.3
More information about the cairo
mailing list