Ticket #14462 (closed enhancement: fixed)
Implement wxSVGFileDC::DoSetClippingRegion / DestroyClippingRegion
|Reported by:||steveb||Owned by:|
|Keywords:||wxDC SVG clipping work-needed||Cc:||biol75@…|
wxSVGFileDC (v2.9.3) does not implement SetClippingRegion / DestroyClippingRegion.
I've derived classes from wxSVGFileDC and wxSVGFileDCImpl that implement this functionality in a way that's suitable for use in an example application that I'm working on. I'm not an SVG expert (far from it) so am not submitting a suggested patch for the wxWidgets trunk, but perhaps this could be a starter-for-ten for somebody who understands it better to make an appropriate update to wxSVGFileDC and wxSVGFileDCImpl.
The implementation required one minor change to dcsvg.h to change the 'void write( const wxString &s )' method on wxSVGFileDCImpl to protected (was private) so that the SVG file stream could be written to in the derived class. This is perhaps a useful update to make in general, since it will allow future derived classes to access the SVG file stream.
The implementation is fairly self-explanatory (and short). Only the following is worth mentioning: the implementation of DoSetClippingRegion in my derived class (wxSVGFileDCWithClippingImpl) simply constructs a <clipPath> SVG element and writes it to the SVG stream. After this it begins an SVG group <g style="clip-path..."> element for subsequent drawing instructions to be entered in. I found that my subsequent instructions triggered a call to NewGraphics() (on wxSVGFileDCImpl), which as its first action writes a </g> to the SVG stream and hence immediately closes the clipping group that was started with my DoSetClippingRegion method.
To solve this in my application it is sufficient to write a </g> first in my DoSetClippingRegion to close the previous group, before beginning the new group. I also then have to write an additional superfluous <g> to the stream after the <g style="clip-path..."> element, which is then 'cancelled out' by the </g> that is written by NewGraphics(). The resulting SVG looks like this:
</g> <!-- SJB end previous group -->
<rect id="cliprect1" x="80" y="30" width="358" height="129" style="stroke: gray; fill: none;"/>
<g style="clip-path: url(#clip1);"> <!-- SJB group for clipped objects -->
<g> <!-- SJB to counteract end group that is added below -->
(The final </g> here is the one written by NewGraphics().)