Clip paths which don't clip anything away should be ignored to conserve PDF file size

Bug #523285 reported by Thorsten Meinl
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
Inkscape
Confirmed
Low
Unassigned

Bug Description

Using inkscape 0.46 exporting the attached SVG resulted in a PDF with about 72kB in size that loads very fast in Okular or Acrobat Reader. Exporting the very same SVG with inkscape 0.47 results in a PDF file about 5MB in size that takes minutes to load.
I'm using Gentoo, so I wonder if this is not a inkscape problem but one related to the use poppler library. Unfortunately inkscape 0.46 has been removed from the Portage tree.

Revision history for this message
Thorsten Meinl (thorsten-meinl) wrote :
su_v (suv-lp)
tags: added: exporting pdf
Revision history for this message
su_v (suv-lp) wrote :

reproduced with Inkscape 0.47+devel r9092 on OS X 10.5.8
compared to the PDF export with Inkscape 0.46 the resulting PDF file from 047(+devel) is huge and the default OS X PDF viewer takes more then 2 minutes to completely render the PDF file.

JFTR: the fike was not created with Inkscape:
<!--Generated by KNIME with Batik SVG Generator-->

Changed in inkscape:
status: New → Confirmed
tags: added: regression
Revision history for this message
su_v (suv-lp) wrote :

oops, sorry:

- JFTR: the fike was not created with Inkscape:
+ JFTR: the file was not created with Inkscape:

Revision history for this message
Thorsten Meinl (thorsten-meinl) wrote :

No, it wasn't originally created with Inkscape, but heavily edited with it.

Revision history for this message
su_v (suv-lp) wrote :

Watching the PDF created with Inkscape 0.47 loading in the PDF viewer I can see that it takes a long time until every tiny clipped symbol of the diagram is calculated, clipped and finally rendered - it is almost an animated view of the PDF structure ;-).

What I fail to understand looking at the way the diagram in the SVG file is structured: there are 8198 tiny symbols (line, rect, circle and polygon entities) and each of it is clipped with a huge rectangular path of the size of the diagram itself (clipPath23). Depending how cairo export handles clip-paths (the structure could possibly trigger a bug in the export function) that means there are ~8200 big rectangles on top of each other, not visible in the end because the object they clip is much, much smaller. (I can't think of a reason why one would create this kind of inverted logical structure with Inkscape itself: (big) object A is clipped with (transformed or smaller) object B so that the clip-path B limits the rendered contents of object A to a certain region. I could be wrong though ;-)

The same structure is used for all labels (clipped lines and clipped text objects) of the x and y axis, but not for the legend (probably the part created with Inkscape).

su_v (suv-lp)
Changed in inkscape:
importance: Undecided → Medium
Revision history for this message
Thorsten Meinl (thorsten-meinl) wrote :

You are right, the legend was hand-made with Inkscape while the remaining parts are taken from the Batik export of a Java Swing/AWT window. Anyhow, Inkscape 0.46 seems to be smarter when exporting this strange structure than 0.47.

Revision history for this message
plastique (vasek-p) wrote :

~suv:: <cite> What I fail to understand looking at the way the diagram in the SVG file is structured: there are 8198 tiny symbols (line, rect, circle and polygon entities) and each of it is clipped with a huge rectangular path of the size of the diagram itself (clipPath23).</cite>

I'm using Batik SVG Generator occasionally for exporting charts created by JFreeChart. And this type of clipping structures are often created this way. Maybe Batik should be blame for it.

su_v (suv-lp)
tags: added: clipping
Revision history for this message
mhtrinh (mhtrinh) wrote :

Hi,

I have the same problem. I don't know if it's a clipping problem or not (I don't know the specifities of SVG file). The svg file is generated by the software yEd Graph Editor. Export well with Inkscape 0.46 but very bad with 0.47 and 0.48
I attached my file hopping that will give some supplement information.

Revision history for this message
su_v (suv-lp) wrote :

The file 'heapsort.svg' - generated by ySVG - uses a page-sized clip-path for each and every object. In the (cairo-)based export to PDF of Inkscape 0.47/0.48 this apparently creates a much more complex structure in the PDF.

Revision history for this message
Adrian Johnson (ajohnson-redneon) wrote :

Running cairo-trace on the test case in comment 1 there are a large number of operations similar to the following:

  save
  //COLOR_ALPHA push-group
  1 0 0 1 0 0 matrix transform
  save
  0 0 0 1 set-source-rgba
  [] 0 set-dash
  1 set-line-width
  //LINE_JOIN_MITER set-line-join
  //LINE_CAP_SQUARE set-line-cap
  10 set-miter-limit
  n 0 2 m 932 2 l stroke
  restore
  pop-group set-source
  save
  1 0 0 1 0 0 matrix transform
  //WINDING set-fill-rule
  0 0 m 0 50 l 932 50 l 932 0 l h
  restore
  clip
  paint
  restore

Inkscape is creating a separate group for each stroke or fill operation. This is unnecessary and extremely inefficient when converted to PDF. I had a look at the Inkscape source to see why it is using a separate group for each operation. It seems to be because of the separate clip for each operation. I don't think this is necessary. Cairo does not require clips to be in a separate group. A save/restore pair can be used to isolate a clip to a single operation.

I tried the following patch to prevent clips from using a separate group. It seems to work for this test case. The PDF output is attached. I don't know if this is the correct fix or if it causes any other regressions.

=== modified file 'src/extension/internal/cairo-renderer.cpp'
--- src/extension/internal/cairo-renderer.cpp 2011-08-27 16:05:32 +0000
+++ src/extension/internal/cairo-renderer.cpp 2011-09-05 11:51:43 +0000
@@ -587,7 +587,7 @@
     setStateForItem(ctx, item);

     CairoRenderState *state = ctx->getCurrentState();
- state->need_layer = ( state->mask || state->clip_path || state->opacity != 1.0 );
+ state->need_layer = ( state->mask || state->opacity != 1.0 );

     // Draw item on a temporary surface so a mask, clip path, or opacity can be applied to it.
     if (state->need_layer) {

Revision history for this message
jazzynico (jazzynico) wrote :

Reproduced on Windows XP, Inkscape trunk revision 11649.
The exported PDF file is 72kb with 0.46, about 4Mb now.

Changed in inkscape:
status: Confirmed → Triaged
Revision history for this message
jazzynico (jazzynico) wrote :

With the patch from comment #10, the file size is only about 50kb.
The file seems to render as expected, but it surely needs more tests.

Attaching the patch as a patch file for convenience.

Revision history for this message
jazzynico (jazzynico) wrote :

@Adrian - As you posted the original patch I'm assigning the report to you.

Changed in inkscape:
assignee: nobody → Adrian Johnson (ajohnson-redneon)
status: Triaged → In Progress
Kris (kris-degussem)
Changed in inkscape:
milestone: none → 0.49
Revision history for this message
Krzysztof Kosinski (tweenk) wrote :

I think Adrian's fix is correct. Committed as r12544.

Changed in inkscape:
status: In Progress → Fix Committed
assignee: nobody → Adrian Johnson (ajohnson-redneon)
Revision history for this message
su_v (suv-lp) wrote :

Regression with r12544 and later revisions (tested with cairo 1.12.16 on OS X 10.7.5):
Save attached SVG as EPS file: the clip-path of group with 'id="g10705"' is not applied in the exported EPS file.

Revision history for this message
su_v (suv-lp) wrote :

Follow-up report filed:
- Bug #1256449 “trunk: clipped groups lose clipping in cairo-based exports (rev >= 12544)”
  <https://bugs.launchpad.net/inkscape/+bug/1256449>

Revision history for this message
Tavmjong Bah (tavmjong-free) wrote :

The "fix" applied in r12544 is incorrect. It disables clipping as clipping is currently applied in ctx->popLayer() which is bypassed if state->need_layer is false.

Revision history for this message
Tavmjong Bah (tavmjong-free) wrote :

The SVG files in question use clip paths (unnecessarily) on each object. It is should not be expected that Inkscape be able to remove/combine these clip paths (it could be done by adding such a feature, perhaps via an extension). The real problem is with the programs that created the original SVG files.

Prior to 0.47 I am guessing clipping wasn't handled at all by Inkscape on export leading to small file sizes. Since the clipping is doing nothing in the example files, no rendering errors would be visible.

I have reverted the commit of r12544 and mark this as "Not a bug"

Changed in inkscape:
status: Fix Committed → Invalid
Revision history for this message
Krzysztof Kosinski (tweenk) wrote :

With some 2Geom improvements, we could detect clipping paths which "do nothing" and ignore them, so I think it might be worthwile to keep this. report as a low priority item.

Changed in inkscape:
status: Invalid → Confirmed
importance: Medium → Low
assignee: Adrian Johnson (ajohnson-redneon) → nobody
milestone: 0.91 → none
summary: - exported PDF 50 times as large as before
+ Clip paths which don't clip anything away should be ignored to conserve
+ PDF file size
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.