1ddde725dSArmin Le Grand /**************************************************************
2ddde725dSArmin Le Grand  *
3ddde725dSArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4ddde725dSArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5ddde725dSArmin Le Grand  * distributed with this work for additional information
6ddde725dSArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7ddde725dSArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8ddde725dSArmin Le Grand  * "License"); you may not use this file except in compliance
9ddde725dSArmin Le Grand  * with the License.  You may obtain a copy of the License at
10ddde725dSArmin Le Grand  *
11ddde725dSArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12ddde725dSArmin Le Grand  *
13ddde725dSArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14ddde725dSArmin Le Grand  * software distributed under the License is distributed on an
15ddde725dSArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ddde725dSArmin Le Grand  * KIND, either express or implied.  See the License for the
17ddde725dSArmin Le Grand  * specific language governing permissions and limitations
18ddde725dSArmin Le Grand  * under the License.
19ddde725dSArmin Le Grand  *
20ddde725dSArmin Le Grand  *************************************************************/
21ddde725dSArmin Le Grand 
22ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
23ddde725dSArmin Le Grand #include "precompiled_svgio.hxx"
24ddde725dSArmin Le Grand 
25ddde725dSArmin Le Grand #include <svgio/svgreader/svgsvgnode.hxx>
26ddde725dSArmin Le Grand #include <drawinglayer/geometry/viewinformation2d.hxx>
27ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
29ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx>
30ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygon.hxx>
31ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
32ddde725dSArmin Le Grand 
33ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
34ddde725dSArmin Le Grand 
35ddde725dSArmin Le Grand namespace svgio
36ddde725dSArmin Le Grand {
37ddde725dSArmin Le Grand     namespace svgreader
38ddde725dSArmin Le Grand     {
39ddde725dSArmin Le Grand         SvgSvgNode::SvgSvgNode(
40ddde725dSArmin Le Grand             SvgDocument& rDocument,
41ddde725dSArmin Le Grand             SvgNode* pParent)
42ddde725dSArmin Le Grand         :   SvgNode(SVGTokenSvg, rDocument, pParent),
43ddde725dSArmin Le Grand             maSvgStyleAttributes(*this),
44ddde725dSArmin Le Grand             mpViewBox(0),
45ddde725dSArmin Le Grand             maSvgAspectRatio(),
46ddde725dSArmin Le Grand             maX(),
47ddde725dSArmin Le Grand             maY(),
48ddde725dSArmin Le Grand             maWidth(),
49ddde725dSArmin Le Grand             maHeight(),
50ddde725dSArmin Le Grand             maVersion()
51ddde725dSArmin Le Grand         {
52ddde725dSArmin Le Grand             if(!getParent())
53ddde725dSArmin Le Grand             {
54ddde725dSArmin Le Grand                 // initial fill is black
55ddde725dSArmin Le Grand                 maSvgStyleAttributes.setFill(SvgPaint(basegfx::BColor(0.0, 0.0, 0.0), true, true));
56ddde725dSArmin Le Grand             }
57ddde725dSArmin Le Grand         }
58ddde725dSArmin Le Grand 
59ddde725dSArmin Le Grand         SvgSvgNode::~SvgSvgNode()
60ddde725dSArmin Le Grand         {
61ddde725dSArmin Le Grand             if(mpViewBox) delete mpViewBox;
62ddde725dSArmin Le Grand         }
63ddde725dSArmin Le Grand 
64ddde725dSArmin Le Grand         const SvgStyleAttributes* SvgSvgNode::getSvgStyleAttributes() const
65ddde725dSArmin Le Grand         {
66ddde725dSArmin Le Grand             return &maSvgStyleAttributes;
67ddde725dSArmin Le Grand         }
68ddde725dSArmin Le Grand 
69ddde725dSArmin Le Grand         void SvgSvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
70ddde725dSArmin Le Grand         {
71ddde725dSArmin Le Grand             // call parent
72ddde725dSArmin Le Grand             SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
73ddde725dSArmin Le Grand 
74ddde725dSArmin Le Grand             // read style attributes
75ddde725dSArmin Le Grand             maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
76ddde725dSArmin Le Grand 
77ddde725dSArmin Le Grand             // parse own
78ddde725dSArmin Le Grand             switch(aSVGToken)
79ddde725dSArmin Le Grand             {
80ddde725dSArmin Le Grand                 case SVGTokenStyle:
81ddde725dSArmin Le Grand                 {
82ddde725dSArmin Le Grand                     maSvgStyleAttributes.readStyle(aContent);
83ddde725dSArmin Le Grand                     break;
84ddde725dSArmin Le Grand                 }
85ddde725dSArmin Le Grand                 case SVGTokenViewBox:
86ddde725dSArmin Le Grand                 {
87ddde725dSArmin Le Grand                     const basegfx::B2DRange aRange(readViewBox(aContent, *this));
88ddde725dSArmin Le Grand 
89ddde725dSArmin Le Grand                     if(!aRange.isEmpty())
90ddde725dSArmin Le Grand                     {
91ddde725dSArmin Le Grand                         setViewBox(&aRange);
92ddde725dSArmin Le Grand                     }
93ddde725dSArmin Le Grand                     break;
94ddde725dSArmin Le Grand                 }
95ddde725dSArmin Le Grand                 case SVGTokenPreserveAspectRatio:
96ddde725dSArmin Le Grand                 {
97ddde725dSArmin Le Grand                     setSvgAspectRatio(readSvgAspectRatio(aContent));
98ddde725dSArmin Le Grand                     break;
99ddde725dSArmin Le Grand                 }
100ddde725dSArmin Le Grand                 case SVGTokenX:
101ddde725dSArmin Le Grand                 {
102ddde725dSArmin Le Grand                     SvgNumber aNum;
103ddde725dSArmin Le Grand 
104ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
105ddde725dSArmin Le Grand                     {
106ddde725dSArmin Le Grand                         setX(aNum);
107ddde725dSArmin Le Grand                     }
108ddde725dSArmin Le Grand                     break;
109ddde725dSArmin Le Grand                 }
110ddde725dSArmin Le Grand                 case SVGTokenY:
111ddde725dSArmin Le Grand                 {
112ddde725dSArmin Le Grand                     SvgNumber aNum;
113ddde725dSArmin Le Grand 
114ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
115ddde725dSArmin Le Grand                     {
116ddde725dSArmin Le Grand                         setY(aNum);
117ddde725dSArmin Le Grand                     }
118ddde725dSArmin Le Grand                     break;
119ddde725dSArmin Le Grand                 }
120ddde725dSArmin Le Grand                 case SVGTokenWidth:
121ddde725dSArmin Le Grand                 {
122ddde725dSArmin Le Grand                     SvgNumber aNum;
123ddde725dSArmin Le Grand 
124ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
125ddde725dSArmin Le Grand                     {
126ddde725dSArmin Le Grand                         if(aNum.isPositive())
127ddde725dSArmin Le Grand                         {
128ddde725dSArmin Le Grand                             setWidth(aNum);
129ddde725dSArmin Le Grand                         }
130ddde725dSArmin Le Grand                     }
131ddde725dSArmin Le Grand                     break;
132ddde725dSArmin Le Grand                 }
133ddde725dSArmin Le Grand                 case SVGTokenHeight:
134ddde725dSArmin Le Grand                 {
135ddde725dSArmin Le Grand                     SvgNumber aNum;
136ddde725dSArmin Le Grand 
137ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
138ddde725dSArmin Le Grand                     {
139ddde725dSArmin Le Grand                         if(aNum.isPositive())
140ddde725dSArmin Le Grand                         {
141ddde725dSArmin Le Grand                             setHeight(aNum);
142ddde725dSArmin Le Grand                         }
143ddde725dSArmin Le Grand                     }
144ddde725dSArmin Le Grand                     break;
145ddde725dSArmin Le Grand                 }
146ddde725dSArmin Le Grand                 case SVGTokenVersion:
147ddde725dSArmin Le Grand                 {
148ddde725dSArmin Le Grand                     SvgNumber aNum;
149ddde725dSArmin Le Grand 
150ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
151ddde725dSArmin Le Grand                     {
152ddde725dSArmin Le Grand                         setVersion(aNum);
153ddde725dSArmin Le Grand                     }
154ddde725dSArmin Le Grand                     break;
155*e2bf1e9dSArmin Le Grand                 }
156*e2bf1e9dSArmin Le Grand                 default:
157*e2bf1e9dSArmin Le Grand                 {
158*e2bf1e9dSArmin Le Grand                     break;
159ddde725dSArmin Le Grand                 }
160ddde725dSArmin Le Grand             }
161ddde725dSArmin Le Grand         }
162ddde725dSArmin Le Grand 
163ddde725dSArmin Le Grand         void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const
164ddde725dSArmin Le Grand         {
165ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence aSequence;
166ddde725dSArmin Le Grand 
167ddde725dSArmin Le Grand             // decompose childs
168ddde725dSArmin Le Grand             SvgNode::decomposeSvgNode(aSequence, bReferenced);
169ddde725dSArmin Le Grand 
170ddde725dSArmin Le Grand             if(aSequence.hasElements())
171ddde725dSArmin Le Grand             {
172ddde725dSArmin Le Grand                 if(getParent())
173ddde725dSArmin Le Grand                 {
174ddde725dSArmin Le Grand                     if(getViewBox())
175ddde725dSArmin Le Grand                     {
176ddde725dSArmin Le Grand                         // Svg defines that with no width or no height the viewBox content is empty,
177ddde725dSArmin Le Grand                         // so both need to exist
178ddde725dSArmin Le Grand                         if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight()))
179ddde725dSArmin Le Grand                         {
180ddde725dSArmin Le Grand                             // create target range homing x,y, width and height as given
181ddde725dSArmin Le Grand                             const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
182ddde725dSArmin Le Grand                             const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
183ddde725dSArmin Le Grand                             const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : getViewBox()->getWidth());
184ddde725dSArmin Le Grand                             const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : getViewBox()->getHeight());
185ddde725dSArmin Le Grand                             const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH);
186ddde725dSArmin Le Grand 
187ddde725dSArmin Le Grand                             if(aTarget.equal(*getViewBox()))
188ddde725dSArmin Le Grand                             {
189ddde725dSArmin Le Grand                                 // no mapping needed, append
190ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence);
191ddde725dSArmin Le Grand                             }
192ddde725dSArmin Le Grand                             else
193ddde725dSArmin Le Grand                             {
194ddde725dSArmin Le Grand                                 // create mapping
195ddde725dSArmin Le Grand                                 const SvgAspectRatio& rRatio = getSvgAspectRatio();
196ddde725dSArmin Le Grand 
197ddde725dSArmin Le Grand                                 if(rRatio.isSet())
198ddde725dSArmin Le Grand                                 {
199ddde725dSArmin Le Grand                                     // let mapping be created from SvgAspectRatio
200ddde725dSArmin Le Grand                                     const basegfx::B2DHomMatrix aEmbeddingTransform(
201ddde725dSArmin Le Grand                                         rRatio.createMapping(aTarget, *getViewBox()));
202ddde725dSArmin Le Grand 
203ddde725dSArmin Le Grand                                     // prepare embedding in transformation
204ddde725dSArmin Le Grand                                     const drawinglayer::primitive2d::Primitive2DReference xRef(
205ddde725dSArmin Le Grand                                         new drawinglayer::primitive2d::TransformPrimitive2D(
206ddde725dSArmin Le Grand                                             aEmbeddingTransform,
207ddde725dSArmin Le Grand                                             aSequence));
208ddde725dSArmin Le Grand 
209ddde725dSArmin Le Grand                                     if(rRatio.isMeetOrSlice())
210ddde725dSArmin Le Grand                                     {
211ddde725dSArmin Le Grand                                         // embed in transformation
212ddde725dSArmin Le Grand                                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef);
213ddde725dSArmin Le Grand                                     }
214ddde725dSArmin Le Grand                                     else
215ddde725dSArmin Le Grand                                     {
216ddde725dSArmin Le Grand                                         // need to embed in MaskPrimitive2D, too
217ddde725dSArmin Le Grand                                         const drawinglayer::primitive2d::Primitive2DReference xMask(
218ddde725dSArmin Le Grand                                             new drawinglayer::primitive2d::MaskPrimitive2D(
219ddde725dSArmin Le Grand                                                 basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)),
220ddde725dSArmin Le Grand                                                 drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1)));
221ddde725dSArmin Le Grand 
222ddde725dSArmin Le Grand                                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask);
223ddde725dSArmin Le Grand                                     }
224ddde725dSArmin Le Grand                                 }
225ddde725dSArmin Le Grand                                 else
226ddde725dSArmin Le Grand                                 {
227ddde725dSArmin Le Grand                                     // choose default mapping
228ddde725dSArmin Le Grand                                     const basegfx::B2DHomMatrix aEmbeddingTransform(
229ddde725dSArmin Le Grand                                         rRatio.createLinearMapping(
230ddde725dSArmin Le Grand                                             aTarget, *getViewBox()));
231ddde725dSArmin Le Grand 
232ddde725dSArmin Le Grand                                     // embed in transformation
233ddde725dSArmin Le Grand                                     const drawinglayer::primitive2d::Primitive2DReference xTransform(
234ddde725dSArmin Le Grand                                         new drawinglayer::primitive2d::TransformPrimitive2D(
235ddde725dSArmin Le Grand                                             aEmbeddingTransform,
236ddde725dSArmin Le Grand                                             aSequence));
237ddde725dSArmin Le Grand 
238ddde725dSArmin Le Grand                                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xTransform);
239ddde725dSArmin Le Grand                                 }
240ddde725dSArmin Le Grand                             }
241ddde725dSArmin Le Grand                         }
242ddde725dSArmin Le Grand                     }
243ddde725dSArmin Le Grand                     else
244ddde725dSArmin Le Grand                     {
245ddde725dSArmin Le Grand                         // check if we have a size
246ddde725dSArmin Le Grand                         const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : 0.0);
247ddde725dSArmin Le Grand                         const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : 0.0);
248ddde725dSArmin Le Grand 
249ddde725dSArmin Le Grand                         // Svg defines that a negative value is an error and that 0.0 disables rendering
250ddde725dSArmin Le Grand                         if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0))
251ddde725dSArmin Le Grand                         {
252ddde725dSArmin Le Grand                             // check if we have a x,y position
253ddde725dSArmin Le Grand                             const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
254ddde725dSArmin Le Grand                             const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
255ddde725dSArmin Le Grand 
256ddde725dSArmin Le Grand                             if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY))
257ddde725dSArmin Le Grand                             {
258ddde725dSArmin Le Grand                                 // embed in transform
259ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xRef(
260ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::TransformPrimitive2D(
261ddde725dSArmin Le Grand                                         basegfx::tools::createTranslateB2DHomMatrix(fX, fY),
262ddde725dSArmin Le Grand                                         aSequence));
263ddde725dSArmin Le Grand 
264ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
265ddde725dSArmin Le Grand                             }
266ddde725dSArmin Le Grand 
267ddde725dSArmin Le Grand                             // embed in MaskPrimitive2D to clip
268ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xMask(
269ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::MaskPrimitive2D(
270ddde725dSArmin Le Grand                                     basegfx::B2DPolyPolygon(
271ddde725dSArmin Le Grand                                         basegfx::tools::createPolygonFromRect(
272ddde725dSArmin Le Grand                                             basegfx::B2DRange(fX, fY, fX + fW, fY + fH))),
273ddde725dSArmin Le Grand                                     aSequence));
274ddde725dSArmin Le Grand 
275ddde725dSArmin Le Grand                             // append
276ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask);
277ddde725dSArmin Le Grand                         }
278ddde725dSArmin Le Grand                     }
279ddde725dSArmin Le Grand                 }
280ddde725dSArmin Le Grand                 else
281ddde725dSArmin Le Grand                 {
282ddde725dSArmin Le Grand                     // Outermost SVG element; create target range homing width and height as given.
283ddde725dSArmin Le Grand                     // SVG defines that x,y has no meanig for the outermost SVG element. Use a fallback
284ddde725dSArmin Le Grand                     // width and height of din A 4 (21 x 29,7 cm)
285ddde725dSArmin Le Grand                     double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : (210.0 * 3.543307));
286ddde725dSArmin Le Grand                     double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : (297.0 * 3.543307));
287ddde725dSArmin Le Grand 
288ddde725dSArmin Le Grand                     // Svg defines that a negative value is an error and that 0.0 disables rendering
289ddde725dSArmin Le Grand                     if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0))
290ddde725dSArmin Le Grand                     {
291ddde725dSArmin Le Grand                         const basegfx::B2DRange aSvgCanvasRange(0.0, 0.0, fW, fH);
292ddde725dSArmin Le Grand 
293ddde725dSArmin Le Grand                         if(getViewBox())
294ddde725dSArmin Le Grand                         {
295ddde725dSArmin Le Grand                             if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight()))
296ddde725dSArmin Le Grand                             {
297ddde725dSArmin Le Grand                                 // create mapping
298ddde725dSArmin Le Grand                                 const SvgAspectRatio& rRatio = getSvgAspectRatio();
299ddde725dSArmin Le Grand                                 basegfx::B2DHomMatrix aViewBoxMapping;
300ddde725dSArmin Le Grand 
301ddde725dSArmin Le Grand                                 if(rRatio.isSet())
302ddde725dSArmin Le Grand                                 {
303ddde725dSArmin Le Grand                                     // let mapping be created from SvgAspectRatio
304ddde725dSArmin Le Grand                                     aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox());
305ddde725dSArmin Le Grand 
306ddde725dSArmin Le Grand                                     // no need to check ratio here for slice, the outermost Svg will
307ddde725dSArmin Le Grand                                     // be clipped anyways (see below)
308ddde725dSArmin Le Grand                                 }
309ddde725dSArmin Le Grand                                 else
310ddde725dSArmin Le Grand                                 {
311ddde725dSArmin Le Grand                                     // choose default mapping
312ddde725dSArmin Le Grand                                     aViewBoxMapping = rRatio.createLinearMapping(aSvgCanvasRange, *getViewBox());
313ddde725dSArmin Le Grand                                 }
314ddde725dSArmin Le Grand 
315ddde725dSArmin Le Grand                                 // scale content to viewBox definitions
316ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xTransform(
317ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::TransformPrimitive2D(
318ddde725dSArmin Le Grand                                         aViewBoxMapping,
319ddde725dSArmin Le Grand                                         aSequence));
320ddde725dSArmin Le Grand 
321ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1);
322ddde725dSArmin Le Grand                             }
323ddde725dSArmin Le Grand                         }
324ddde725dSArmin Le Grand 
325ddde725dSArmin Le Grand                         // to be completely correct in Svg sense it is necessary to clip
326ddde725dSArmin Le Grand                         // the whole content to the given canvas. I choose here to do this
327ddde725dSArmin Le Grand                         // initially despite I found various examples of Svg files out there
328ddde725dSArmin Le Grand                         // which have no correct values for this clipping. It's correct
329ddde725dSArmin Le Grand                         // due to the Svg spec.
330ddde725dSArmin Le Grand                         bool bDoCorrectCanvasClipping(true);
331ddde725dSArmin Le Grand 
332ddde725dSArmin Le Grand                         if(bDoCorrectCanvasClipping)
333ddde725dSArmin Le Grand                         {
334ddde725dSArmin Le Grand                             // different from Svg we have the possibility with primitives to get
335ddde725dSArmin Le Grand                             // a correct bounding box for the geometry, thhus I will allow to
336ddde725dSArmin Le Grand                             // only clip if necessary. This will make Svg images evtl. smaller
337ddde725dSArmin Le Grand                             // than wanted from Svg (the free space which may be around it is
338ddde725dSArmin Le Grand                             // conform to the Svg spec), but avoids an expensive and unneccessary
339ddde725dSArmin Le Grand                             // clip.
340ddde725dSArmin Le Grand                             const basegfx::B2DRange aContentRange(
341ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(
342ddde725dSArmin Le Grand                                     aSequence,
343ddde725dSArmin Le Grand                                     drawinglayer::geometry::ViewInformation2D()));
344ddde725dSArmin Le Grand 
345ddde725dSArmin Le Grand                             if(!aSvgCanvasRange.isInside(aContentRange))
346ddde725dSArmin Le Grand                             {
347ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xMask(
348ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::MaskPrimitive2D(
349ddde725dSArmin Le Grand                                         basegfx::B2DPolyPolygon(
350ddde725dSArmin Le Grand                                             basegfx::tools::createPolygonFromRect(
351ddde725dSArmin Le Grand                                                 aSvgCanvasRange)),
352ddde725dSArmin Le Grand                                         aSequence));
353ddde725dSArmin Le Grand 
354ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1);
355ddde725dSArmin Le Grand                             }
356ddde725dSArmin Le Grand                         }
357ddde725dSArmin Le Grand 
358ddde725dSArmin Le Grand                         {
359ddde725dSArmin Le Grand                             // embed in transform primitive to scale to 1/100th mm
360ddde725dSArmin Le Grand                             // where 1 mm == 3.543307 px to get from Svg coordinates to
361ddde725dSArmin Le Grand                             // drawinglayer ones
362ddde725dSArmin Le Grand                             const double fScaleTo100thmm(100.0 / 3.543307);
363ddde725dSArmin Le Grand                             const basegfx::B2DHomMatrix aTransform(
364ddde725dSArmin Le Grand                                 basegfx::tools::createScaleB2DHomMatrix(
365ddde725dSArmin Le Grand                                     fScaleTo100thmm,
366ddde725dSArmin Le Grand                                     fScaleTo100thmm));
367ddde725dSArmin Le Grand 
368ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xTransform(
369ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::TransformPrimitive2D(
370ddde725dSArmin Le Grand                                     aTransform,
371ddde725dSArmin Le Grand                                     aSequence));
372ddde725dSArmin Le Grand 
373ddde725dSArmin Le Grand                             aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1);
374ddde725dSArmin Le Grand                         }
375ddde725dSArmin Le Grand 
376ddde725dSArmin Le Grand                         // append
377ddde725dSArmin Le Grand                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence);
378ddde725dSArmin Le Grand                     }
379ddde725dSArmin Le Grand                 }
380ddde725dSArmin Le Grand             }
381ddde725dSArmin Le Grand         }
382ddde725dSArmin Le Grand 
383ddde725dSArmin Le Grand         const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const
384ddde725dSArmin Le Grand         {
385ddde725dSArmin Le Grand             if(getViewBox())
386ddde725dSArmin Le Grand             {
387ddde725dSArmin Le Grand                 return getViewBox();
388ddde725dSArmin Le Grand             }
389ddde725dSArmin Le Grand             else
390ddde725dSArmin Le Grand             {
391ddde725dSArmin Le Grand                 return SvgNode::getCurrentViewPort();
392ddde725dSArmin Le Grand             }
393ddde725dSArmin Le Grand         }
394ddde725dSArmin Le Grand 
395ddde725dSArmin Le Grand     } // end of namespace svgreader
396ddde725dSArmin Le Grand } // end of namespace svgio
397ddde725dSArmin Le Grand 
398ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
399ddde725dSArmin Le Grand // eof
400