svglib icon indicating copy to clipboard operation
svglib copied to clipboard

Support pattern fills.

Open ghost opened this issue 6 years ago • 12 comments

A request for supporting patterns. (I imagine this is not trivial).

ghost avatar May 24 '18 13:05 ghost

I'm not sure ReportLab support patterns. That would be the first question to answer.

claudep avatar May 24 '18 15:05 claudep

I'm pretty sure ReportLab doesn't support anything like that. A long time back I wrote some pseudo (linear) grading shapes for them. I'd love to see them support pure SVG/PDF linear/radial graded shading, because it's so often used for logos etc. Maybe I should ask @replabrobin how much that feature would cost? ;) Quite seriously...

deeplook avatar May 25 '18 06:05 deeplook

I don't determine what get's worked on unfortunately. I think setting up patterns in PDF is quite hard. First off we need to define Pattern objects; these are somewhat similar to forms in that they have resources etc etc. If we have defined patterns then the next step would be to allow them to be used as colours in the rl tk.

We have some contributed code (Peter Johnson [email protected]) that allows shading to be added to a canvas. It supports radial and axial shading, but it demands direct access to the canvas so is not at all integrated into the generic graphics code. There's no tiling / uncoloured support. The pseudo linear stuff is still present, but again it's not treatable as a colour.

replabrobin avatar May 25 '18 07:05 replabrobin

@replabrobin Does this mean the code for true radial/axial shading is already in reportlab, but can be used only for PDF output? If so I think that would still be very valuable for svglib. See also https://github.com/deeplook/svglib/issues/50

deeplook avatar Aug 06 '18 19:08 deeplook

There is code to perform radial / axial shading in reportlab, but it is PDF only and there's no real connection with the graphics code or colours. The example works directly onto a canvas in test_platypus_general.py

` ############# colour gradients title = 'Gradients code contributed by Peter Johnson [email protected]' c.drawString(1inch,10.8inch,title) c.addOutlineEntry(title+" section", title, level=0, closed=True) c.bookmarkHorizontalAbsolute(title, 10.8*inch)

c.saveState()
p = c.beginPath()
p.moveTo(1*inch,2*inch)
p.lineTo(1.5*inch,2.5*inch)
p.curveTo(2*inch,3*inch,3.0*inch,3*inch,4*inch,2.9*inch)
p.lineTo(5.5*inch,2.1*inch)
p.close()
c.clipPath(p)

# Draw a linear gradient from (0, 2*inch) to (5*inch, 3*inch), from orange to white.
# The gradient will extend past the endpoints (so you probably want a clip path in place)
c.linearGradient(1*inch, 2*inch, 6*inch, 3*inch, (red, blue))
c.restoreState()

# Draw a radial gradient with a radius of 3 inches.
# The color starts orange and stays orange until 20% of the radius,
# then fades to white at 80%, and ends up green at 3 inches from the center.
# Since extend is false, the gradient stops drawing at the edge of the circle.
c.radialGradient(4*inch, 6*inch, 3*inch, (red, green, blue), (0.2, 0.8, 1.0), extend=False)
c.showPage()

### now do stuff for the outline
#for x in outlinenametree: print x
#stop
#c.setOutlineNames0(*outlinenametree)
return c

`

replabrobin avatar Aug 07 '18 06:08 replabrobin

@deeplook Is there any chance that gradients will be supported by svglib in future? I would love to create a PDF documentation for our Open Soruce project but since there are svg containing gradient fills I can not build it...

bmxp avatar Jan 03 '21 09:01 bmxp

Unfortunately, I'm afraid that until reportlab adds better support for gradients, it will be very difficult to make any progress in svglib.

claudep avatar Jan 03 '21 09:01 claudep

I would love to see gradient support in reportlab, too. And it might not be that difficult to implement there. @replabrobin, any chance of getting this as a (late) X-mas present, maybe? ;)

deeplook avatar Jan 03 '21 10:01 deeplook

I suppose that to get gradients supported in reportlab would require us to change the colour model to allow gradient type objects as a colour. That implies that everywhere we push a colour onto a canvas we would need to handle the new gradient case.

I imagine we might be able to do this for the PDF canvas by hacking on the _PDFColorSetter class. Before that we have to define the pattern and ensure it gets registered where it is used. The PDF spec requires that patterns are not affected by transforms that occur after definition

For example, if a pattern is used on a page, the pattern appears in the Pattern sub- dictionary of that page’s resource dictionary, and the pattern matrix maps pattern space to the default (initial) coordinate space of the page. Changes to the page’s transformation matrix that occur within the page’s content stream, such as rota- tion and scaling, have no effect on the pattern; it maintains its original relation- ship to the page no matter where on the page it is used.

I'm not sure how restrictive this would be, but given that we are using the reportlab graphics library where we can always look at the overall transform(or calculate it) it may not be a problem.

The hard problem will be to find a way to create patterns that are as complex as SVG allows and also ensure all the graphics backends support this (or at least fail gracefully).

I suspect that Andy Robinson will not want to do any of this unless there's a pressing requirement (eg a big client requested tables with rounded corners before xmas and now we have them).

replabrobin avatar Jan 05 '21 11:01 replabrobin

I was trying out svglib today and found this issue while searching for existing reports of an error I ran into:

$ svg2pdf simple-css-case-fill.svg 
Can't handle color: url(#Crosses_Grey)
simple-css-case-fill.svg
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <style type="text/css">
    .st0, .st1, .st11, .st12, .st13, .st14 {
      fill: none;
    }

    .st1 {
      stroke: #939598;
      stroke-width: 0.3px;
    }

    .st5 {
      fill: url(#Crosses_Grey);
    }
    </style>
    <pattern width="14.4" height="14.4" patternUnits="userSpaceOnUse" id="Crosses_Grey" viewBox="0 0 14.4 14.4" style="overflow:visible;">
      <rect class="st0" width="14.4" height="14.4"/>
      <line class="st1" x1="9.3" y1="3.6" x2="12.3" y2="3.6"/>
    </pattern>
  </defs>
  <g id="Background">
    <g>
      <g>
        <path class="st5" d="M247.6,507.8c-6.6,0-17.4,5.4-24,12L131.4,612h283.9l31.5-31.5c6.6-6.6,17.4-12,24-12H792v-60.7H644.2H247.6z"/>
      </g>
    </g>
  </g>
</svg>

I may be over-interpreting #208, but I guess if this proceeds at some point it'll also need support in cssselect2.

abathur avatar May 17 '21 18:05 abathur

Even if the url() reference was working, we are not supporting <pattern>, as I don't think there is anything in Reportlab we could build on for such a thing.

claudep avatar May 17 '21 19:05 claudep

I'm aware. That's why I said the support is only relevant if this proceeds at some point.

abathur avatar May 17 '21 21:05 abathur