Problem with cairo pdf output
(From mailing list thread with same name: https://lists.cairographics.org/archives/cairo/2022-November/thread.html)
I believe cairo_set_operator(,14,) in paintTransparencyGroup should output a gs change in BOTH cases, but it's only for the first case when using a PDF surface; OTOH, when the context is backed by a Image surface, CAIRO_OPERATOR_MULTIPLY is honored also for the second highlight...
Minimal reproducible example:
#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>
int main()
{
cairo_surface_t *sfc = cairo_pdf_surface_create("out.pdf", 100, 100);
cairo_t *cr = cairo_create(sfc);
// prepare some background
cairo_set_source_rgb(cr, 0.7, 1.0, 1.0);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_move_to(cr, 2.0, 2.0);
cairo_line_to(cr, 98.0, 98.0);
cairo_stroke(cr);
cairo_push_group(cr);
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
cairo_rectangle(cr, 10.0, 10.0, 80.0, 30.0);
cairo_fill(cr);
cairo_pattern_t *p1 = cairo_pop_group(cr);
#if 1
// Problem only manifests, when clipping is enabled
cairo_rectangle(cr, 0.0, 0.0, 100.0, 99.0);
cairo_clip(cr);
#endif
cairo_set_operator(cr, CAIRO_OPERATOR_MULTIPLY);
cairo_set_source(cr, p1);
cairo_paint(cr);
cairo_translate(cr, 0.0, 50.0);
cairo_set_source(cr, p1); // source has cached the ctm -> needs update
cairo_paint(cr);
cairo_pattern_destroy(p1);
cairo_surface_write_to_png(sfc, "out.png");
cairo_destroy(cr);
cairo_surface_destroy(sfc);
return 0;
}
out.png is correct, out.pdf is not.
Comparison of pdf content streams:
-- w/o clipping: --
1 0 0 -1 0 100 cm
q
0.7 1 1 rg /a0 gs
0 0 100 100 re f
0 0 0 RG 2 w
0 J
0 j
[] 0.0 d
10 M 2 2 m 98 98 l S
/b14 gs
q
/a0 gs /x6 Do
Q
q
1 0 0 1 0 50 cm
/a0 gs /x6 Do
Q
Q
-- vs. w/ clipping: --
1 0 0 -1 0 100 cm
q
0.7 1 1 rg /a0 gs
0 0 100 100 re f
0 0 0 RG 2 w
0 J
0 j
[] 0.0 d
10 M 2 2 m 98 98 l S
Q q
0 0 100 99 re W n
/b14 gs
q
/a0 gs /x6 Do
Q
Q q
0 50 100 49 re W n
q
1 0 0 1 0 50 cm
/a0 gs /x6 Do
Q
Q
The change of clipping (translate...) adds another level of q/Q grouping to limit its effect, but the group also contains and limits the /b14 gs command – and the /b14 is not emitted again in the second group, although MULTIPLY should still be used.