mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-26 09:00:40 +02:00
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.
This commit is contained in:
parent
31eff5c6eb
commit
dcbe16eb40
5 changed files with 84 additions and 61 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue