Bug 104042

Summary: text failing to display on SVG and X11 surface even though it works correctly on PDF and PS surfaces
Product: cairo Reporter: Antony Lee <anntzer.lee>
Component: generalAssignee: Chris Wilson <chris>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium    
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: cairo-script that reproduces the reported issue
minimal example reproducing the issue.

Description Antony Lee 2017-12-03 02:24:45 UTC
Created attachment 135887 [details]
cairo-script that reproduces the reported issue

This bug was first reported on the cairo mailing list.


I have an issue of text failing to be displayed onto a SVG surface.  I have attached a cairo-script to this bug report; the script is quite large because of the font (DejaVu) definition embedded.  Stripping the font definition yields

    %!CairoScript
    << /content //COLOR_ALPHA /width 460 /height 345 /fallback-resolution
[100 100] >> surface context
    1 g set-source
    paint
    //ALPHA [] record
    dup /s6 exch def dup context
    [12 0 0 12 0 0] set-font-matrix
    << /type 42 /index 0 /flags 32 /source < ... > >> font dup /f0 exch def
set-font-face /scaled-font get /sf0 exch def
    [0 7 <~6i~>] show-glyphs
    pop pattern
    [1 0 0 1 -227.4 -9.312] set-matrix
    set-source
    paint
    pop

where the ellipsis stands for the binary font definition.

Replaying the script with csi-replay (cairo 1.14.10), patched to output the results to a file

    {
    -    return cairo_pdf_surface_create_for_stream (NULL, NULL, width,
height);
    +    return cairo_pdf_surface_create("/tmp/out.pdf", width, height);
    }


(and similarly for ps and svg) shows that the pdf and ps surfaces (correctly) create a file that displays a single letter "a" on the surface, but the svg surface creates a file that displays nothing.  Although I can't showcase the issue as easily on other surfaces, my tests indicate that the text is also correctly displayed by the image surface, and also missing when using the X11 surface.

As some side notes: 1) It may be worth documenting somewhere (e.g. util/cairo-script/README) that the way to build csi-replay is `make csi-replay`; this took me a while to realize.  2) It may be worth supporting output to a file from csi-replay, in the manner of the patch I used (but either with proper integration to the command line, or perhaps just outputting to $pid.pdf).

Any help would be welcome.  Thanks!
Comment 1 Uli Schlachter 2017-12-27 12:15:09 UTC
I don't really know my way around cairo-script, so bear with me.

First, to test your script with the xlib backend:

diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index 4c66b7752..e25e6fc63 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -40,6 +40,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 static const cairo_user_data_key_t _key;
 
@@ -119,6 +120,7 @@ static void
 _destroy_window (void *closure)
 {
     XFlush (_get_display ());
+    sleep(3);
     XDestroyWindow (_get_display(), (Window) closure);
 }
 

Then, let's take a look at your script (could you provide a self-contained C program instead if the following is not what you want to hear?):

    %!CairoScript
    << /content //COLOR_ALPHA /width 460 /height 345 /fallback-resolution
[100 100] >> surface context
    1 g set-source
    paint

The above creates a surface of size 460x345, creates a context for it, sets the source to all white (1 g is apparently r=g=b) and paints it, i.e. this fills the surface with white.

    //ALPHA [] record
    dup /s6 exch def dup context

Uhm... I'm not quite sure. I guess this creates another cairo context for the same surface?

    [12 0 0 12 0 0] set-font-matrix
    << /type 42 /index 0 /flags 32 /source < ... > >> font dup /f0 exch def
set-font-face /scaled-font get /sf0 exch def
    [0 7 <~6i~>] show-glyphs

Font setup and draw some glyph somewhere.

    pop pattern

Turn the surface that is on the stack into a surface pattern.

    [1 0 0 1 -227.4 -9.312] set-matrix
    set-source

Set this pattern as the source with the above matrix (just some offset).

    paint
    pop

Draw the cairo surface. Is this a self-copy (drawing a surface to itself)? If so, that's not allowed in cairo.
Comment 2 Antony Lee 2017-12-28 01:25:56 UTC
I'll try to provide a minimal C example but that's not easy -- this is in the context of a cairo backend (https://github.com/anntzer/mplcairo) for Matplotlib (a Python plotting library) so it's layers and layers of Python driving a C library.  In the meantime...

    //ALPHA [] record
    dup /s6 exch def dup context

Looking at cairo-script-surface.c, one sees that this is written by _emit_recording_pattern_surface and attach_snapshot, with the contents of the recording surface in the next lines.

Both from my own code and from my interpretation of the script I believe that I am not drawing a surface to itself.
Comment 3 Antony Lee 2017-12-28 02:50:31 UTC
Created attachment 136417 [details]
minimal example reproducing the issue.

I managed to find a self-contained way to reproduce the issue, as documented in the attached source.

Compile and run with
  $ gcc main.c -g $(pkg-config --cflags cairo-ft) $(pkg-config --libs cairo-ft) -o main
  $ ./main
Inspect the contents of /tmp/test.png, /tmp/test1.png, /tmp/test.svg,
/tmp/test1.svg.  Only the last one is missing text (this is the
bug). cairo-script output is also generated (for reference) to
/tmp/test{,1}.script.

The program writes "hello world" to an image, an SVG and a script surface,
either directly, or via a recording surface used as pattern.

My investigations indicate that for the issue to appear, it is necessary
that
1. the recording surface is unbounded, and
2. the recording surface has content type CAIRO_CONTENT_ALPHA.
Comment 4 Uli Schlachter 2017-12-28 13:02:02 UTC
Oh, sorry for misinterpreting your script.

I don't have much clue about SVGs either, but on cairo git/master, the test1.svg actually does contain some drawing, but it is just not visible. (With debian's libcairo2 1.15.8-3 the SVG looks quite empty in a text editor.) To make that drawing visible, it is enough to get rid of the "just use the alpha component"-filter. Specifically replacing

   <g id="surface5" clip-path="url(#clip1)" filter="url(#alpha)">

in test1.svg with

   <g id="surface5" clip-path="url(#clip1)">

makes the text visible. (The "clip1" reference seems to point into nowhere, by the way, there is no such path in the file, I think.)

I'll leave the details of what this means to someone with some knowledge about SVGs. Perhaps chromium just does not support this filter correctly?

In the meantime, I'll modify your example for cairo-xcb / cairo-xlib and investigate what is going on there.
Comment 5 Uli Schlachter 2017-12-28 13:33:06 UTC
Actually... what are the semantics of drawing an alpha-only surface to a color-only target with operator OVER? I'm not quite sure and this seems to be the root of the problem. https://www.cairographics.org/operators/ doesn't answer this either.

I noticed that with cairo-xcb the example program works, while with cairo-xlib still nothing is displayed. After staring at protocol traces for far too long, I noticed that the significant difference seems to be in the drawing to the intermediate surface:

cairo-xlib:
- creates an uninitialized(???) intermediate pixmap
- draws the glyphs to it via operator OVER
- with a black solid source

cairo-xcb:
- creates an intermediate pixmap and clears it
- draws the glyphs to it via operator ADD
- with a white solid source

Both backends then OVER this intermediate to the target picture which uses a RGB24 format. I'm not actually sure why this produces no result with cairo-xlib, but the missing clearing of the intermediate pixmap strikes me as quite odd.
Comment 6 GitLab Migration User 2018-08-25 13:36:35 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/94.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.