[cairo-commit] src/cairo-output-stream.c src/cairo-output-stream-private.h src/cairo-pdf-operators.c src/cairo-pdf-surface.c src/cairo-ps-surface.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Fri Dec 6 21:27:29 PST 2013
src/cairo-output-stream-private.h | 5 ++++
src/cairo-output-stream.c | 39 +++++++++++++++++++++++++++++++++
src/cairo-pdf-operators.c | 17 ++++----------
src/cairo-pdf-surface.c | 44 ++++++++++++++++----------------------
src/cairo-ps-surface.c | 40 +++++++++++++---------------------
5 files changed, 84 insertions(+), 61 deletions(-)
New commits:
commit dcbe16eb40b488f89f2398181f4c3f8a65f84b52
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sat Dec 7 15:48:26 2013 +1030
pdf/ps: avoid outputting excess decimal places in matrices
Sometimes as a result of rounding errors in matrix transformations the
matrices in ps/pdf output look like:
0.000000000000000061 1 1 -0.000000000000000061 0 842 cm
This patch rounds to zero matrix elements that are very small compared to
other elements in the same matrix.
diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h
index edaabbe..38a137f 100644
--- a/src/cairo-output-stream-private.h
+++ b/src/cairo-output-stream-private.h
@@ -135,6 +135,11 @@ _cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt,
...) CAIRO_PRINTF_FORMAT (2, 3);
+/* Print matrix element values with rounding of insignificant digits. */
+void
+_cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
+ const cairo_matrix_t *matrix);
+
cairo_private long
_cairo_output_stream_get_position (cairo_output_stream_t *stream);
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index cc7e300..6d6c180 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -530,6 +530,45 @@ _cairo_output_stream_printf (cairo_output_stream_t *stream,
va_end (ap);
}
+/* Matrix elements that are smaller than the value of the largest element * MATRIX_ROUNDING_TOLERANCE
+ * are rounded down to zero. */
+#define MATRIX_ROUNDING_TOLERANCE 1e-12
+
+void
+_cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
+ const cairo_matrix_t *matrix)
+{
+ cairo_matrix_t m;
+ double s, e;
+
+ m = *matrix;
+ s = fabs (m.xx);
+ if (fabs (m.xy) > s)
+ s = fabs (m.xy);
+ if (fabs (m.yx) > s)
+ s = fabs (m.yx);
+ if (fabs (m.yy) > s)
+ s = fabs (m.yy);
+
+ e = s * MATRIX_ROUNDING_TOLERANCE;
+ if (fabs(m.xx) < e)
+ m.xx = 0;
+ if (fabs(m.xy) < e)
+ m.xy = 0;
+ if (fabs(m.yx) < e)
+ m.yx = 0;
+ if (fabs(m.yy) < e)
+ m.yy = 0;
+ if (fabs(m.x0) < e)
+ m.x0 = 0;
+ if (fabs(m.y0) < e)
+ m.y0 = 0;
+
+ _cairo_output_stream_printf (stream,
+ "%f %f %f %f %f %f",
+ m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
+}
+
long
_cairo_output_stream_get_position (cairo_output_stream_t *stream)
{
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index fceaf1c..84d2441 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -828,10 +828,9 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
return status;
if (has_ctm) {
- _cairo_output_stream_printf (pdf_operators->stream,
- "q %f %f %f %f %f %f cm\n",
- m.xx, m.yx, m.xy, m.yy,
- m.x0, m.y0);
+ _cairo_output_stream_printf (pdf_operators->stream, "q ");
+ _cairo_output_stream_print_matrix (pdf_operators->stream, &m);
+ _cairo_output_stream_printf (pdf_operators->stream, " cm\n");
} else {
path_transform = pdf_operators->cairo_to_pdf;
}
@@ -1120,14 +1119,8 @@ _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t *pdf_operators,
pdf_operators->cur_x = 0;
pdf_operators->cur_y = 0;
pdf_operators->glyph_buf_x_pos = 0;
- _cairo_output_stream_printf (pdf_operators->stream,
- "%f %f %f %f %f %f Tm\n",
- pdf_operators->text_matrix.xx,
- pdf_operators->text_matrix.yx,
- pdf_operators->text_matrix.xy,
- pdf_operators->text_matrix.yy,
- pdf_operators->text_matrix.x0,
- pdf_operators->text_matrix.y0);
+ _cairo_output_stream_print_matrix (pdf_operators->stream, &pdf_operators->text_matrix);
+ _cairo_output_stream_printf (pdf_operators->stream, " Tm\n");
pdf_operators->cairo_to_pdftext = *matrix;
status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a8a1217..c200c28 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3843,11 +3843,11 @@ _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output,
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
- " /Shading\n",
- pat_to_pdf->xx, pat_to_pdf->yx,
- pat_to_pdf->xy, pat_to_pdf->yy,
- pat_to_pdf->x0, pat_to_pdf->y0);
+ " /Matrix [ ");
+ _cairo_output_stream_print_matrix (surface->output, pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
+ " /Shading\n");
}
if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
@@ -4105,14 +4105,14 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
"%d 0 obj\n"
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
+ " /Matrix [ ",
+ pdf_pattern->pattern_res.id);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
" /Shading %d 0 R\n"
">>\n"
"endobj\n",
- pdf_pattern->pattern_res.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,
res.id);
if (pdf_pattern->gstate_res.id != 0) {
@@ -4166,14 +4166,14 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
"%d 0 obj\n"
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
+ " /Matrix [ ",
+ mask_resource.id);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
" /Shading %d 0 R\n"
">>\n"
"endobj\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,
res.id);
status = cairo_pdf_surface_emit_transparency_group (surface,
@@ -4302,11 +4302,8 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
return status;
if (! _cairo_matrix_is_identity (&pdf_p2d)) {
- _cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f cm\n",
- pdf_p2d.xx, pdf_p2d.yx,
- pdf_p2d.xy, pdf_p2d.yy,
- pdf_p2d.x0, pdf_p2d.y0);
+ _cairo_output_stream_print_matrix (surface->output, &pdf_p2d);
+ _cairo_output_stream_printf (surface->output, " cm\n");
}
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
@@ -4357,11 +4354,8 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
return status;
if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
- _cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f cm\n",
- pat_to_pdf.xx, pat_to_pdf.yx,
- pat_to_pdf.xy, pat_to_pdf.yy,
- pat_to_pdf.x0, pat_to_pdf.y0);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output, " cm\n");
}
status = _cairo_pdf_surface_add_shading (surface, shading_res);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index dfab4f7..f4ae3a8 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3251,11 +3251,9 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
if (! _cairo_matrix_is_identity (&ps_p2d)) {
- _cairo_output_stream_printf (surface->stream,
- "[ %f %f %f %f %f %f ] concat\n",
- ps_p2d.xx, ps_p2d.yx,
- ps_p2d.xy, ps_p2d.yy,
- ps_p2d.x0, ps_p2d.y0);
+ _cairo_output_stream_printf (surface->stream, "[ ");
+ _cairo_output_stream_print_matrix (surface->stream, &ps_p2d);
+ _cairo_output_stream_printf (surface->stream, " ] concat\n");
}
status = _cairo_ps_surface_emit_surface (surface,
@@ -3444,12 +3442,10 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
+ _cairo_output_stream_printf (surface->stream, "[ ");
+ _cairo_output_stream_print_matrix (surface->stream, &ps_p2d);
_cairo_output_stream_printf (surface->stream,
- "[ %f %f %f %f %f %f ]\n",
- ps_p2d.xx, ps_p2d.yx,
- ps_p2d.xy, ps_p2d.yy,
- ps_p2d.x0, ps_p2d.y0);
- _cairo_output_stream_printf (surface->stream,
+ " ]\n"
"makepattern setpattern\n");
release_source:
@@ -3823,11 +3819,10 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t *surface,
if (is_ps_pattern) {
_cairo_output_stream_printf (surface->stream,
">>\n"
- "[ %f %f %f %f %f %f ]\n"
- "makepattern setpattern\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ "[ ");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
+ _cairo_output_stream_printf (surface->stream, " ]\n"
+ "makepattern setpattern\n");
} else {
_cairo_output_stream_printf (surface->stream,
"shfill\n");
@@ -3905,11 +3900,10 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t *surface,
if (is_ps_pattern) {
_cairo_output_stream_printf (surface->stream,
">>\n"
- "[ %f %f %f %f %f %f ]\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ "[ \n");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
_cairo_output_stream_printf (surface->stream,
+ " ]\n"
"makepattern\n"
"setpattern\n");
} else {
@@ -4008,11 +4002,9 @@ _cairo_ps_surface_paint_gradient (cairo_ps_surface_t *surface,
cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
if (! _cairo_matrix_is_identity (&pat_to_ps)) {
- _cairo_output_stream_printf (surface->stream,
- "[%f %f %f %f %f %f] concat\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ _cairo_output_stream_printf (surface->stream, "[");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
+ _cairo_output_stream_printf (surface->stream, "] concat\n");
}
if (source->type == CAIRO_PATTERN_TYPE_MESH) {
More information about the cairo-commit
mailing list