[cairo-commit] 2 commits - src/cairo-pdf-surface.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Sun Oct 14 02:35:48 PDT 2007
- Previous message: [cairo-commit] cairo-perl Cairo.pm, 1.28, 1.29 ChangeLog, 1.72, 1.73 NEWS, 1.15, 1.16 README, 1.17, 1.18
- Next message: [cairo-commit] cairo-perl ChangeLog,1.73,1.74
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
src/cairo-pdf-surface.c | 271 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 225 insertions(+), 46 deletions(-)
New commits:
commit 4660561cb548ab8d1eca724fda4d3658c95d4c04
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Oct 14 19:05:06 2007 +0930
PDF: Add support for CAIRO_FORMAT_A1 images
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 8a2ef42..31d4c21 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1303,12 +1303,17 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
int i, x, y;
cairo_bool_t opaque;
uint8_t a;
+ int src_bit, dst_bit;
/* This is the only image format we support, which simplfies things. */
assert (image->format == CAIRO_FORMAT_ARGB32 ||
- image->format == CAIRO_FORMAT_A8 );
+ image->format == CAIRO_FORMAT_A8 ||
+ image->format == CAIRO_FORMAT_A1 );
- alpha_size = image->height * image->width;
+ if (image->format == CAIRO_FORMAT_A1)
+ alpha_size = (image->height * image->width + 7)/8;
+ else
+ alpha_size = image->height * image->width;
alpha = malloc (alpha_size);
if (alpha == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1317,6 +1322,8 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
opaque = TRUE;
i = 0;
+ src_bit = 0;
+ dst_bit = 7;
for (y = 0; y < image->height; y++) {
if (image->format == CAIRO_FORMAT_ARGB32) {
pixel32 = (uint32_t *) (image->data + y * image->stride);
@@ -1327,7 +1334,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
if (a != 0xff)
opaque = FALSE;
}
- } else {
+ } else if (image->format == CAIRO_FORMAT_A8){
pixel8 = (uint8_t *) (image->data + y * image->stride);
for (x = 0; x < image->width; x++, pixel8++) {
@@ -1336,6 +1343,25 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
if (a != 0xff)
opaque = FALSE;
}
+ } else { /* image->format == CAIRO_FORMAT_A1 */
+ pixel8 = (uint8_t *) (image->data + y * image->stride);
+
+ for (x = 0; x < image->width; x++, pixel8++) {
+ if (dst_bit == 7)
+ alpha[i] = 0;
+ if ((*pixel8 >> src_bit) & 1) {
+ opaque = FALSE;
+ alpha[i] |= (1 << dst_bit);
+ }
+ if (++src_bit > 7) {
+ src_bit = 0;
+ pixel8++;
+ }
+ if (--dst_bit < 0) {
+ dst_bit = 7;
+ i++;
+ }
+ }
}
}
@@ -1358,9 +1384,10 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
" /Width %d\r\n"
" /Height %d\r\n"
" /ColorSpace /DeviceGray\r\n"
- " /BitsPerComponent 8\r\n"
+ " /BitsPerComponent %d\r\n"
" /Filter /FlateDecode\r\n",
- image->width, image->height);
+ image->width, image->height,
+ image->format == CAIRO_FORMAT_A1 ? 1 : 8);
if (stream_ret->id == 0) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ALPHA_COMPRESSED;
@@ -1405,7 +1432,8 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
*/
assert (image->format == CAIRO_FORMAT_RGB24 ||
image->format == CAIRO_FORMAT_ARGB32 ||
- image->format == CAIRO_FORMAT_A8);
+ image->format == CAIRO_FORMAT_A8 ||
+ image->format == CAIRO_FORMAT_A1);
rgb_size = image->height * image->width * 3;
rgb = malloc (rgb_size);
@@ -1456,7 +1484,8 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
need_smask = FALSE;
if (image->format == CAIRO_FORMAT_ARGB32 ||
- image->format == CAIRO_FORMAT_A8) {
+ image->format == CAIRO_FORMAT_A8 ||
+ image->format == CAIRO_FORMAT_A1) {
status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
if (status)
goto CLEANUP_COMPRESSED;
commit 39044157da03d598b816a459979f3d0e6285e023
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Oct 14 19:04:33 2007 +0930
PDF: Add support for linear gradients with REPEAT and REFLECT
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f2679e1..8a2ef42 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2002,6 +2002,19 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+
+static void
+calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
+ cairo_pdf_color_stop_t *stop1,
+ cairo_pdf_color_stop_t *stop2)
+{
+ int i;
+ double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
+
+ for (i = 0; i < 4; i++)
+ new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
+}
+
#define COLOR_STOP_EPSILON 1e-6
static cairo_status_t
@@ -2036,6 +2049,31 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
}
+ if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
+ pattern->base.extend == CAIRO_EXTEND_REFLECT) {
+ if (stops[0].offset > COLOR_STOP_EPSILON) {
+ if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
+ memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
+ else
+ calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
+ stops = allstops;
+ n_stops++;
+ }
+ stops[0].offset = 0.0;
+
+ if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
+ if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
+ memcpy (&stops[n_stops],
+ &stops[n_stops - 1],
+ sizeof (cairo_pdf_color_stop_t));
+ } else {
+ calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
+ }
+ n_stops++;
+ }
+ stops[n_stops-1].offset = 1.0;
+ }
+
if (n_stops == 2) {
/* no need for stitched function */
status = cairo_pdf_surface_emit_rgb_linear_function (surface,
@@ -2080,6 +2118,67 @@ BAIL:
return status;
}
+static cairo_status_t
+_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
+ cairo_gradient_pattern_t *pattern,
+ cairo_pdf_resource_t *function,
+ int begin,
+ int end)
+{
+ cairo_pdf_resource_t res;
+ int i;
+
+ res = _cairo_pdf_surface_new_object (surface);
+ if (res.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /FunctionType 3\r\n"
+ " /Domain [ %d %d ]\r\n",
+ res.id,
+ begin,
+ end);
+
+ _cairo_output_stream_printf (surface->output,
+ " /Functions [ ");
+ for (i = begin; i < end; i++)
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 R ", function->id);
+ _cairo_output_stream_printf (surface->output,
+ "]\r\n");
+
+ _cairo_output_stream_printf (surface->output,
+ " /Bounds [ ");
+ for (i = begin + 1; i < end; i++)
+ _cairo_output_stream_printf (surface->output,
+ "%d ", i);
+ _cairo_output_stream_printf (surface->output,
+ "]\r\n");
+
+ _cairo_output_stream_printf (surface->output,
+ " /Encode [ ");
+ for (i = begin; i < end; i++) {
+ if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
+ _cairo_output_stream_printf (surface->output,
+ "1 0 ");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "0 1 ");
+ }
+ }
+ _cairo_output_stream_printf (surface->output,
+ "]\r\n");
+
+ _cairo_output_stream_printf (surface->output,
+ ">>\r\n"
+ "endobj\r\n");
+
+ *function = res;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static cairo_pdf_resource_t
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t gradient_mask)
@@ -2168,20 +2267,16 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t pattern_resource, smask;
cairo_pdf_resource_t color_function, alpha_function;
double x1, y1, x2, y2;
+ double _x1, _y1, _x2, _y2;
cairo_matrix_t pat_to_pdf;
cairo_extend_t extend;
cairo_status_t status;
cairo_gradient_pattern_t *gradient = &pattern->base;
double first_stop, last_stop;
+ int repeat_begin = 0, repeat_end = 1;
extend = cairo_pattern_get_extend (&pattern->base.base);
_cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pdf_surface_emit_pattern_stops (surface,
- &pattern->base,
- &color_function,
- &alpha_function);
- if (status)
- return status;
pat_to_pdf = pattern->base.base.matrix;
status = cairo_matrix_invert (&pat_to_pdf);
@@ -2189,41 +2284,93 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
- x1 = _cairo_fixed_to_double (pattern->p1.x);
- y1 = _cairo_fixed_to_double (pattern->p1.y);
- x2 = _cairo_fixed_to_double (pattern->p2.x);
- y2 = _cairo_fixed_to_double (pattern->p2.y);
-
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
- /* PDF requires the first and last stop to be the same as the line
- * coordinates. If this is not a repeating pattern move the line
- * coordinates to the location of first and last stop. */
-
- if (pattern->base.base.extend == CAIRO_EXTEND_NONE ||
- pattern->base.base.extend == CAIRO_EXTEND_PAD) {
- double _x1, _y1, _x2, _y2;
-
- _x1 = x1 + (x2 - x1)*first_stop;
- _y1 = y1 + (y2 - y1)*first_stop;
- _x2 = x1 + (x2 - x1)*last_stop;
- _y2 = y1 + (y2 - y1)*last_stop;
-
- x1 = _x1;
- x2 = _x2;
- y1 = _y1;
- y2 = _y2;
+ if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
+ pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
+ double dx, dy;
+ int x_rep = 0, y_rep = 0;
+
+ x1 = _cairo_fixed_to_double (pattern->p1.x);
+ y1 = _cairo_fixed_to_double (pattern->p1.y);
+ cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1);
+
+ x2 = _cairo_fixed_to_double (pattern->p2.x);
+ y2 = _cairo_fixed_to_double (pattern->p2.y);
+ cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2);
+
+ dx = fabs (x2 - x1);
+ dy = fabs (y2 - y1);
+ if (dx > 1e-6)
+ x_rep = (int) ceil (surface->width/dx);
+ if (dy > 1e-6)
+ y_rep = (int) ceil (surface->height/dy);
+
+ repeat_end = MAX (x_rep, y_rep);
+ repeat_begin = -repeat_end;
+ first_stop = repeat_begin;
+ last_stop = repeat_end;
}
- if (gradient->n_stops == 2) {
- /* If only two stops the Type 2 function is used by itself
- * without a Stitching function. Type 2 functions always have
- * the domain [0 1] */
+ /* PDF requires the first and last stop to be the same as the line
+ * coordinates. For repeating patterns this moves the line
+ * coordinates out to the begin/end of the repeating function. For
+ * non repeating patterns this may move the line coordinates in if
+ * there are not stops at offset 0 and 1. */
+ x1 = _cairo_fixed_to_double (pattern->p1.x);
+ y1 = _cairo_fixed_to_double (pattern->p1.y);
+ x2 = _cairo_fixed_to_double (pattern->p2.x);
+ y2 = _cairo_fixed_to_double (pattern->p2.y);
+
+ _x1 = x1 + (x2 - x1)*first_stop;
+ _y1 = y1 + (y2 - y1)*first_stop;
+ _x2 = x1 + (x2 - x1)*last_stop;
+ _y2 = y1 + (y2 - y1)*last_stop;
+
+ x1 = _x1;
+ x2 = _x2;
+ y1 = _y1;
+ y2 = _y2;
+
+ /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
+ * Type 2 function is used by itself without a stitching
+ * function. Type 2 functions always have the domain [0 1] */
+ if ((pattern->base.base.extend == CAIRO_EXTEND_NONE ||
+ pattern->base.base.extend == CAIRO_EXTEND_PAD) &&
+ gradient->n_stops == 2) {
first_stop = 0.0;
last_stop = 1.0;
}
+ status = _cairo_pdf_surface_emit_pattern_stops (surface,
+ &pattern->base,
+ &color_function,
+ &alpha_function);
+ if (status)
+ return status;
+
+ if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
+ pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
+ status = _cairo_pdf_surface_emit_repeating_function (surface,
+ &pattern->base,
+ &color_function,
+ repeat_begin,
+ repeat_end);
+ if (status)
+ return status;
+
+ if (alpha_function.id != 0) {
+ status = _cairo_pdf_surface_emit_repeating_function (surface,
+ &pattern->base,
+ &alpha_function,
+ repeat_begin,
+ repeat_end);
+ if (status)
+ return status;
+ }
+ }
+
pattern_resource = _cairo_pdf_surface_new_object (surface);
if (pattern_resource.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2279,12 +2426,14 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
" << /ShadingType 2\r\n"
" /ColorSpace /DeviceGray\r\n"
" /Coords [ %f %f %f %f ]\r\n"
+ " /Domain [ %f %f ]\r\n"
" /Function %d 0 R\r\n",
mask_resource.id,
pat_to_pdf.xx, pat_to_pdf.yx,
pat_to_pdf.xy, pat_to_pdf.yy,
pat_to_pdf.x0, pat_to_pdf.y0,
x1, y1, x2, y2,
+ first_stop, last_stop,
alpha_function.id);
if (extend == CAIRO_EXTEND_PAD) {
@@ -3968,18 +4117,19 @@ _gradient_pattern_supported (cairo_pattern_t *pattern)
extend = cairo_pattern_get_extend (pattern);
- if (extend == CAIRO_EXTEND_REPEAT ||
- extend == CAIRO_EXTEND_REFLECT) {
- return FALSE;
- }
- /* Radial gradients are currently only supported when one circle
- * is inside the other. */
+ /* Radial gradients are currently only supported with EXTEND_NONE
+ * and EXTEND_PAD and when one circle is inside the other. */
if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
double x1, y1, x2, y2, r1, r2, d;
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
- x1 = _cairo_fixed_to_double (radial->c1.x);
+ if (extend == CAIRO_EXTEND_REPEAT ||
+ extend == CAIRO_EXTEND_REFLECT) {
+ return FALSE;
+ }
+
+ x1 = _cairo_fixed_to_double (radial->c1.x);
y1 = _cairo_fixed_to_double (radial->c1.y);
r1 = _cairo_fixed_to_double (radial->r1);
x2 = _cairo_fixed_to_double (radial->c2.x);
- Previous message: [cairo-commit] cairo-perl Cairo.pm, 1.28, 1.29 ChangeLog, 1.72, 1.73 NEWS, 1.15, 1.16 README, 1.17, 1.18
- Next message: [cairo-commit] cairo-perl ChangeLog,1.73,1.74
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list