Skip to content

Work on the SVG backend

Anton Danilkin requested to merge afdw/cairo:svg-backend-work into master

Replaces #76.

Fixes #361 (closed).

Fixes #431 (closed).

Fixes #78 (closed).

Fixes #4 (closed).

Fixes poppler/poppler#761 (closed).

Fixes poppler/poppler#619 (closed).

Fixes #107 (closed).

Fixes poppler/poppler#268 (closed).

Fixes #73 (closed).

Fixes #478 (closed).

Rough changelog (probably incomplete):

  1. Fix using unitialized memory in the SVG surface.

  2. Fix unintialized memory and working with offsetted images in the recording surface.

  3. Fix problems in the SVG backend related to outputting surfaces and patterns.

    Now the SVG surface should work correctly work with bounded and unbounded image (-like) and recording surfaces with NONE and REPEAT extends as source for all operations.

    Fill or stroke with an unbounded surface as source now means using clip or mask respectively.

  4. Ignore .idea, compile_commands.json and /build /builddir.

  5. Fix using signed types where unsigned ones were needed.

  6. Do not check the status after creating a memory stream As we do not check the status after _cairo_output_stream_printf and _cairo_memory_stream_copy (which are more common operations) anyway.

    This simplifies the code, but keeps it correct, as the status will be propagated anyway, just a bit later.

  7. Fix some compiler warning suppressions.

  8. Remove the use of discard_filter.

  9. Remove the use of extra_attributes.

  10. Implement the operators in a non-SVG 1.2 manner.

  11. Do not use the style attribute.

  12. Change the default SVG unit to user unit.

  13. Fix problems with radial gradients.

  14. Remove support of SVG 1.2.

  15. Simplify SVG document generation.

  16. Implement correct paints in transformed recording patterns (see !76 (comment 710096)).

  17. Move cairo_svg_surface_t to cairo-svg-surface.c.

  18. Fix clip-rule being emitted on the wrong elements.

  19. Do not use parent_matrix in the mask operation.

  20. Mark CAIRO_PATTERN_TYPE_MESH as unsupported and impose a limit on recording surfaces depth.

  21. Emit bitmap glyph data as images instead of as a bunch of squares, as this results in smaller file size and better quality, allowing the use of shades of gray.

  22. Add support for PDF Type 3 fonts.

  23. Implement attempting to recognize a common pattern for a bitmap font and extract the original glyph image from it.

  24. Fix support of CAIRO_CONTENT_COLOR.

  25. Use g instead of symbol for glyphs.

  26. Introduce CAIRO_BOILERPLATE_OPEN_NO_DAEMON and CAIRO_BOILERPLATE_DO_NOT_CRASH_ON_ANY2PPM_ERROR.

Now the test-suite mostly passes, at least visually. I get the following result ("Passed" here means that the result was pixel-perfect or of by a few shades in a few pixels):

321 Passed, 241 Failed [0 crashed, 17 expected], 24 Skipped
Preamble: 2 failed - fallback-resolution create-for-stream
image (argb32): 21 failed - clip-text culled-glyphs halo-transform overlapping-glyphs radial-gradient-source record1414x-select-font-face record1414x-text-transform show-glyphs-advance subsurface subsurface-scale text-antialias-subpixel text-antialias-subpixel-rgb text-antialias-subpixel-bgr text-antialias-subpixel-vrgb text-antialias-subpixel-vbgr text-pattern text-rotate text-unhinted-metrics ft-show-glyphs-positioning ft-text-vertical-layout-type1 ft-text-vertical-layout-type3
image (rgb24): 22 failed - clip-text culled-glyphs extended-blend-alpha-mask halo-transform overlapping-glyphs radial-gradient-source record1414x-select-font-face record1414x-text-transform show-glyphs-advance subsurface subsurface-scale text-antialias-subpixel text-antialias-subpixel-rgb text-antialias-subpixel-bgr text-antialias-subpixel-vrgb text-antialias-subpixel-vbgr text-pattern text-rotate text-unhinted-metrics ft-show-glyphs-positioning ft-text-vertical-layout-type1 ft-text-vertical-layout-type3
svg11 (argb32): 215 failed - arc-looping-dash bug-51910 bug-84115 bug-image-compositor caps caps-2 caps-1 caps-05 checkerboard caps-joins-2 caps-joins-1 caps-joins-05 caps-joins-curve caps-tails-curve caps-sub-paths clear-source clip-complex-bug61592 clip-disjoint-quad clip-stroke-unbounded clip-fill-nz-unbounded clip-fill-eo-unbounded clip-image clip-operator clip-push-group clip-text clipped-group close-path close-path-current-point copy-path culled-glyphs dash-caps-joins dash-curve dash-infinite-loop dash-scale dash-state degenerate-arcs degenerate-curve-to degenerate-linear-gradient degenerate-pen degenerate-radial-gradient degenerate-rel-curve-to device-offset-fractional extend-pad-border extended-blend extended-blend-alpha extended-blend-mask extended-blend-alpha-mask extended-blend-solid extended-blend-solid-alpha fallback fill-and-stroke-alpha fill-and-stroke-alpha-add filter-bilinear-extents filter-nearest-offset filter-nearest-transformed finer-grained-fallbacks font-matrix-translation glyph-cache-pressure group-unaligned halo halo-transform huge-radial infinite-join inverse-text joins large-font leaky-dashed-stroke leaky-polygon line-width-scale line-width-tolerance linear-gradient linear-gradient-extend linear-gradient-reflect linear-gradient-subset long-dashed-lines mask-transformed-image mask-transformed-similar mesh-pattern mesh-pattern-conical mesh-pattern-control-points mesh-pattern-fold mesh-pattern-overlap mesh-pattern-transformed operator-source operator-www overlapping-glyphs paint-source-alpha paint-with-alpha paint-with-alpha-solid-clip paint-with-alpha-clip paint-with-alpha-clip-mask partial-clip-text-top partial-clip-text-bottom partial-clip-text-left partial-clip-text-right path-stroke-twice pixman-downscale-fast-24 pixman-downscale-good-24 pixman-downscale-best-24 pixman-downscale-nearest-24 pixman-downscale-bilinear-24 push-group-color radial-gradient radial-gradient-mask radial-gradient-source radial-gradient-mask-source radial-gradient-one-stop radial-gradient-extend record-paint-alpha record-paint-alpha-solid-clip record-paint-alpha-clip record-paint-alpha-clip-mask record-fill-alpha record-select-font-face record-text-transform record1414x-paint record1414x-paint-alpha record1414x-paint-alpha-solid-clip record1414x-paint-alpha-clip record1414x-paint-alpha-clip-mask record1414x-fill-alpha record1414x-select-font-face record1414x-self-intersecting record1414x-text-transform record2x-paint-alpha record2x-paint-alpha-solid-clip record2x-paint-alpha-clip record2x-paint-alpha-clip-mask record2x-fill-alpha record2x-select-font-face record2x-text-transform record90-paint-alpha-solid-clip record90-paint-alpha-clip record90-paint-alpha-clip-mask record90-fill-alpha record90-select-font-face record90-self-intersecting record90-text-transform recordflip-whole-paint-alpha recordflip-whole-paint-alpha-clip recordflip-whole-paint-alpha-clip-mask recordflip-whole-select-font-face recordflip-whole-text-transform recordflip-paint-alpha recordflip-paint-alpha-clip recordflip-paint-alpha-clip-mask recordflip-fill-alpha recordflip-select-font-face recordflip-text-transform record-neg-extents-unbounded record-neg-extents-bounded record-mesh record-replay-extend-repeat record-replay-extend-reflect recording-surface-over recording-surface-source recording-surface-extend-none recording-surface-extend-repeat recording-surface-extend-reflect rectilinear-miter-limit rectilinear-dash-scale rectilinear-dash-scale-unaligned reflected-stroke rotate-image-surface-paint clip-rotate-image-surface-paint rotate-clip-image-surface-paint scale-offset-image scale-offset-similar scale-source-surface-paint stroke-ctm-caps select-font-face self-copy show-glyphs-advance show-text-current-point shape-sierpinski smask smask-fill smask-image-mask smask-mask smask-paint smask-stroke smask-text smp-glyph spline-decomposition stroke-pattern surface-pattern surface-pattern-operator surface-pattern-scale-down surface-pattern-scale-down-extend-repeat surface-pattern-scale-down-extend-none surface-pattern-scale-up text-glyph-range text-pattern text-rotate text-transform text-unhinted-metrics tighten-bounds tiger transforms twin unbounded-operator unclosed-strokes user-font user-font-proxy user-font-rescale world-map world-map-stroke world-map-fill ft-show-glyphs-positioning ft-show-glyphs-table ft-text-vertical-layout-type1 ft-text-vertical-layout-type3 pdf-surface-source ps-surface-source svg-surface-source

Note that the generated SVG files might be very computationally expensive to render (and I do not think much can be done to simplify them, although some improvements are clearly possible), and r-svg sometimes seems to take exponentially long to do so, so you probably want to do the following to run the test suite:

  1. Increase the stack size: ulimit -S -s 131072.
  2. Limit the virtual memory (to ~20 GB): ulimit -S -v 20000000.
  3. Perhaps also limit the CPU time (to 5 minutes): ulimit -S -t 300 (or you can just manually kill the any2ppm process if it takes too long to render the result of a particular test).

Also note that Chrome renders these images much faster (and sometimes more correctly) in many cases, so you can manually test in it.

Most of operators are unsupported in:

  1. Firefox because of SVG filters feImage with xlink:href doesn't work with fragments.
  2. resvg because of Chained filters do not work.
Edited by Anton Danilkin

Merge request reports