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>
32*41923119SArmin Le Grand #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
33*41923119SArmin Le Grand #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx>
34ddde725dSArmin Le Grand 
35ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
36ddde725dSArmin Le Grand 
37ddde725dSArmin Le Grand namespace svgio
38ddde725dSArmin Le Grand {
39ddde725dSArmin Le Grand     namespace svgreader
40ddde725dSArmin Le Grand     {
41ddde725dSArmin Le Grand         SvgSvgNode::SvgSvgNode(
42ddde725dSArmin Le Grand             SvgDocument& rDocument,
43ddde725dSArmin Le Grand             SvgNode* pParent)
44ddde725dSArmin Le Grand         :   SvgNode(SVGTokenSvg, rDocument, pParent),
45ddde725dSArmin Le Grand             maSvgStyleAttributes(*this),
46ddde725dSArmin Le Grand             mpViewBox(0),
47ddde725dSArmin Le Grand             maSvgAspectRatio(),
48ddde725dSArmin Le Grand             maX(),
49ddde725dSArmin Le Grand             maY(),
50ddde725dSArmin Le Grand             maWidth(),
51ddde725dSArmin Le Grand             maHeight(),
52ddde725dSArmin Le Grand             maVersion()
53ddde725dSArmin Le Grand         {
54ddde725dSArmin Le Grand             if(!getParent())
55ddde725dSArmin Le Grand             {
56ddde725dSArmin Le Grand                 // initial fill is black
57ddde725dSArmin Le Grand                 maSvgStyleAttributes.setFill(SvgPaint(basegfx::BColor(0.0, 0.0, 0.0), true, true));
58ddde725dSArmin Le Grand             }
59ddde725dSArmin Le Grand         }
60ddde725dSArmin Le Grand 
61ddde725dSArmin Le Grand         SvgSvgNode::~SvgSvgNode()
62ddde725dSArmin Le Grand         {
63ddde725dSArmin Le Grand             if(mpViewBox) delete mpViewBox;
64ddde725dSArmin Le Grand         }
65ddde725dSArmin Le Grand 
66ddde725dSArmin Le Grand         const SvgStyleAttributes* SvgSvgNode::getSvgStyleAttributes() const
67ddde725dSArmin Le Grand         {
68ddde725dSArmin Le Grand             return &maSvgStyleAttributes;
69ddde725dSArmin Le Grand         }
70ddde725dSArmin Le Grand 
71ddde725dSArmin Le Grand         void SvgSvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
72ddde725dSArmin Le Grand         {
73ddde725dSArmin Le Grand             // call parent
74ddde725dSArmin Le Grand             SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
75ddde725dSArmin Le Grand 
76ddde725dSArmin Le Grand             // read style attributes
77ddde725dSArmin Le Grand             maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
78ddde725dSArmin Le Grand 
79ddde725dSArmin Le Grand             // parse own
80ddde725dSArmin Le Grand             switch(aSVGToken)
81ddde725dSArmin Le Grand             {
82ddde725dSArmin Le Grand                 case SVGTokenStyle:
83ddde725dSArmin Le Grand                 {
84ddde725dSArmin Le Grand                     maSvgStyleAttributes.readStyle(aContent);
85ddde725dSArmin Le Grand                     break;
86ddde725dSArmin Le Grand                 }
87ddde725dSArmin Le Grand                 case SVGTokenViewBox:
88ddde725dSArmin Le Grand                 {
89ddde725dSArmin Le Grand                     const basegfx::B2DRange aRange(readViewBox(aContent, *this));
90ddde725dSArmin Le Grand 
91ddde725dSArmin Le Grand                     if(!aRange.isEmpty())
92ddde725dSArmin Le Grand                     {
93ddde725dSArmin Le Grand                         setViewBox(&aRange);
94ddde725dSArmin Le Grand                     }
95ddde725dSArmin Le Grand                     break;
96ddde725dSArmin Le Grand                 }
97ddde725dSArmin Le Grand                 case SVGTokenPreserveAspectRatio:
98ddde725dSArmin Le Grand                 {
99ddde725dSArmin Le Grand                     setSvgAspectRatio(readSvgAspectRatio(aContent));
100ddde725dSArmin Le Grand                     break;
101ddde725dSArmin Le Grand                 }
102ddde725dSArmin Le Grand                 case SVGTokenX:
103ddde725dSArmin Le Grand                 {
104ddde725dSArmin Le Grand                     SvgNumber aNum;
105ddde725dSArmin Le Grand 
106ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
107ddde725dSArmin Le Grand                     {
108ddde725dSArmin Le Grand                         setX(aNum);
109ddde725dSArmin Le Grand                     }
110ddde725dSArmin Le Grand                     break;
111ddde725dSArmin Le Grand                 }
112ddde725dSArmin Le Grand                 case SVGTokenY:
113ddde725dSArmin Le Grand                 {
114ddde725dSArmin Le Grand                     SvgNumber aNum;
115ddde725dSArmin Le Grand 
116ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
117ddde725dSArmin Le Grand                     {
118ddde725dSArmin Le Grand                         setY(aNum);
119ddde725dSArmin Le Grand                     }
120ddde725dSArmin Le Grand                     break;
121ddde725dSArmin Le Grand                 }
122ddde725dSArmin Le Grand                 case SVGTokenWidth:
123ddde725dSArmin Le Grand                 {
124ddde725dSArmin Le Grand                     SvgNumber aNum;
125ddde725dSArmin Le Grand 
126ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
127ddde725dSArmin Le Grand                     {
128ddde725dSArmin Le Grand                         if(aNum.isPositive())
129ddde725dSArmin Le Grand                         {
130ddde725dSArmin Le Grand                             setWidth(aNum);
131ddde725dSArmin Le Grand                         }
132ddde725dSArmin Le Grand                     }
133ddde725dSArmin Le Grand                     break;
134ddde725dSArmin Le Grand                 }
135ddde725dSArmin Le Grand                 case SVGTokenHeight:
136ddde725dSArmin Le Grand                 {
137ddde725dSArmin Le Grand                     SvgNumber aNum;
138ddde725dSArmin Le Grand 
139ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
140ddde725dSArmin Le Grand                     {
141ddde725dSArmin Le Grand                         if(aNum.isPositive())
142ddde725dSArmin Le Grand                         {
143ddde725dSArmin Le Grand                             setHeight(aNum);
144ddde725dSArmin Le Grand                         }
145ddde725dSArmin Le Grand                     }
146ddde725dSArmin Le Grand                     break;
147ddde725dSArmin Le Grand                 }
148ddde725dSArmin Le Grand                 case SVGTokenVersion:
149ddde725dSArmin Le Grand                 {
150ddde725dSArmin Le Grand                     SvgNumber aNum;
151ddde725dSArmin Le Grand 
152ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
153ddde725dSArmin Le Grand                     {
154ddde725dSArmin Le Grand                         setVersion(aNum);
155ddde725dSArmin Le Grand                     }
156ddde725dSArmin Le Grand                     break;
157e2bf1e9dSArmin Le Grand                 }
158e2bf1e9dSArmin Le Grand                 default:
159e2bf1e9dSArmin Le Grand                 {
160e2bf1e9dSArmin Le Grand                     break;
161ddde725dSArmin Le Grand                 }
162ddde725dSArmin Le Grand             }
163ddde725dSArmin Le Grand         }
164ddde725dSArmin Le Grand 
165ddde725dSArmin Le Grand         void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const
166ddde725dSArmin Le Grand         {
167ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence aSequence;
168ddde725dSArmin Le Grand 
169ddde725dSArmin Le Grand             // decompose childs
170ddde725dSArmin Le Grand             SvgNode::decomposeSvgNode(aSequence, bReferenced);
171ddde725dSArmin Le Grand 
172ddde725dSArmin Le Grand             if(aSequence.hasElements())
173ddde725dSArmin Le Grand             {
174ddde725dSArmin Le Grand                 if(getParent())
175ddde725dSArmin Le Grand                 {
176ddde725dSArmin Le Grand                     if(getViewBox())
177ddde725dSArmin Le Grand                     {
178ddde725dSArmin Le Grand                         // Svg defines that with no width or no height the viewBox content is empty,
179ddde725dSArmin Le Grand                         // so both need to exist
180ddde725dSArmin Le Grand                         if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight()))
181ddde725dSArmin Le Grand                         {
182ddde725dSArmin Le Grand                             // create target range homing x,y, width and height as given
183ddde725dSArmin Le Grand                             const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
184ddde725dSArmin Le Grand                             const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
185ddde725dSArmin Le Grand                             const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : getViewBox()->getWidth());
186ddde725dSArmin Le Grand                             const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : getViewBox()->getHeight());
187ddde725dSArmin Le Grand                             const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH);
188ddde725dSArmin Le Grand 
189ddde725dSArmin Le Grand                             if(aTarget.equal(*getViewBox()))
190ddde725dSArmin Le Grand                             {
191ddde725dSArmin Le Grand                                 // no mapping needed, append
192ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence);
193ddde725dSArmin Le Grand                             }
194ddde725dSArmin Le Grand                             else
195ddde725dSArmin Le Grand                             {
196ddde725dSArmin Le Grand                                 // create mapping
197ddde725dSArmin Le Grand                                 const SvgAspectRatio& rRatio = getSvgAspectRatio();
198ddde725dSArmin Le Grand 
199ddde725dSArmin Le Grand                                 if(rRatio.isSet())
200ddde725dSArmin Le Grand                                 {
201ddde725dSArmin Le Grand                                     // let mapping be created from SvgAspectRatio
202ddde725dSArmin Le Grand                                     const basegfx::B2DHomMatrix aEmbeddingTransform(
203ddde725dSArmin Le Grand                                         rRatio.createMapping(aTarget, *getViewBox()));
204ddde725dSArmin Le Grand 
205ddde725dSArmin Le Grand                                     // prepare embedding in transformation
206ddde725dSArmin Le Grand                                     const drawinglayer::primitive2d::Primitive2DReference xRef(
207ddde725dSArmin Le Grand                                         new drawinglayer::primitive2d::TransformPrimitive2D(
208ddde725dSArmin Le Grand                                             aEmbeddingTransform,
209ddde725dSArmin Le Grand                                             aSequence));
210ddde725dSArmin Le Grand 
211ddde725dSArmin Le Grand                                     if(rRatio.isMeetOrSlice())
212ddde725dSArmin Le Grand                                     {
213ddde725dSArmin Le Grand                                         // embed in transformation
214ddde725dSArmin Le Grand                                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef);
215ddde725dSArmin Le Grand                                     }
216ddde725dSArmin Le Grand                                     else
217ddde725dSArmin Le Grand                                     {
218ddde725dSArmin Le Grand                                         // need to embed in MaskPrimitive2D, too
219ddde725dSArmin Le Grand                                         const drawinglayer::primitive2d::Primitive2DReference xMask(
220ddde725dSArmin Le Grand                                             new drawinglayer::primitive2d::MaskPrimitive2D(
221ddde725dSArmin Le Grand                                                 basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)),
222ddde725dSArmin Le Grand                                                 drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1)));
223ddde725dSArmin Le Grand 
224ddde725dSArmin Le Grand                                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask);
225ddde725dSArmin Le Grand                                     }
226ddde725dSArmin Le Grand                                 }
227ddde725dSArmin Le Grand                                 else
228ddde725dSArmin Le Grand                                 {
229ddde725dSArmin Le Grand                                     // choose default mapping
230ddde725dSArmin Le Grand                                     const basegfx::B2DHomMatrix aEmbeddingTransform(
231ddde725dSArmin Le Grand                                         rRatio.createLinearMapping(
232ddde725dSArmin Le Grand                                             aTarget, *getViewBox()));
233ddde725dSArmin Le Grand 
234ddde725dSArmin Le Grand                                     // embed in transformation
235ddde725dSArmin Le Grand                                     const drawinglayer::primitive2d::Primitive2DReference xTransform(
236ddde725dSArmin Le Grand                                         new drawinglayer::primitive2d::TransformPrimitive2D(
237ddde725dSArmin Le Grand                                             aEmbeddingTransform,
238ddde725dSArmin Le Grand                                             aSequence));
239ddde725dSArmin Le Grand 
240ddde725dSArmin Le Grand                                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xTransform);
241ddde725dSArmin Le Grand                                 }
242ddde725dSArmin Le Grand                             }
243ddde725dSArmin Le Grand                         }
244ddde725dSArmin Le Grand                     }
245ddde725dSArmin Le Grand                     else
246ddde725dSArmin Le Grand                     {
247ddde725dSArmin Le Grand                         // check if we have a size
248ddde725dSArmin Le Grand                         const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : 0.0);
249ddde725dSArmin Le Grand                         const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : 0.0);
250ddde725dSArmin Le Grand 
251ddde725dSArmin Le Grand                         // Svg defines that a negative value is an error and that 0.0 disables rendering
252ddde725dSArmin Le Grand                         if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0))
253ddde725dSArmin Le Grand                         {
254ddde725dSArmin Le Grand                             // check if we have a x,y position
255ddde725dSArmin Le Grand                             const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
256ddde725dSArmin Le Grand                             const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
257ddde725dSArmin Le Grand 
258ddde725dSArmin Le Grand                             if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY))
259ddde725dSArmin Le Grand                             {
260ddde725dSArmin Le Grand                                 // embed in transform
261ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xRef(
262ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::TransformPrimitive2D(
263ddde725dSArmin Le Grand                                         basegfx::tools::createTranslateB2DHomMatrix(fX, fY),
264ddde725dSArmin Le Grand                                         aSequence));
265ddde725dSArmin Le Grand 
266ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
267ddde725dSArmin Le Grand                             }
268ddde725dSArmin Le Grand 
269ddde725dSArmin Le Grand                             // embed in MaskPrimitive2D to clip
270ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xMask(
271ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::MaskPrimitive2D(
272ddde725dSArmin Le Grand                                     basegfx::B2DPolyPolygon(
273ddde725dSArmin Le Grand                                         basegfx::tools::createPolygonFromRect(
274ddde725dSArmin Le Grand                                             basegfx::B2DRange(fX, fY, fX + fW, fY + fH))),
275ddde725dSArmin Le Grand                                     aSequence));
276ddde725dSArmin Le Grand 
277ddde725dSArmin Le Grand                             // append
278ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask);
279ddde725dSArmin Le Grand                         }
280ddde725dSArmin Le Grand                     }
281ddde725dSArmin Le Grand                 }
282ddde725dSArmin Le Grand                 else
283ddde725dSArmin Le Grand                 {
284ddde725dSArmin Le Grand                     // Outermost SVG element; create target range homing width and height as given.
285ddde725dSArmin Le Grand                     // SVG defines that x,y has no meanig for the outermost SVG element. Use a fallback
286ddde725dSArmin Le Grand                     // width and height of din A 4 (21 x 29,7 cm)
287ddde725dSArmin Le Grand                     double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : (210.0 * 3.543307));
288ddde725dSArmin Le Grand                     double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : (297.0 * 3.543307));
289ddde725dSArmin Le Grand 
290ddde725dSArmin Le Grand                     // Svg defines that a negative value is an error and that 0.0 disables rendering
291ddde725dSArmin Le Grand                     if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0))
292ddde725dSArmin Le Grand                     {
293ddde725dSArmin Le Grand                         const basegfx::B2DRange aSvgCanvasRange(0.0, 0.0, fW, fH);
294ddde725dSArmin Le Grand 
295ddde725dSArmin Le Grand                         if(getViewBox())
296ddde725dSArmin Le Grand                         {
297ddde725dSArmin Le Grand                             if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight()))
298ddde725dSArmin Le Grand                             {
299ddde725dSArmin Le Grand                                 // create mapping
300ddde725dSArmin Le Grand                                 const SvgAspectRatio& rRatio = getSvgAspectRatio();
301ddde725dSArmin Le Grand                                 basegfx::B2DHomMatrix aViewBoxMapping;
302ddde725dSArmin Le Grand 
303ddde725dSArmin Le Grand                                 if(rRatio.isSet())
304ddde725dSArmin Le Grand                                 {
305ddde725dSArmin Le Grand                                     // let mapping be created from SvgAspectRatio
306ddde725dSArmin Le Grand                                     aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox());
307ddde725dSArmin Le Grand 
308ddde725dSArmin Le Grand                                     // no need to check ratio here for slice, the outermost Svg will
309ddde725dSArmin Le Grand                                     // be clipped anyways (see below)
310ddde725dSArmin Le Grand                                 }
311ddde725dSArmin Le Grand                                 else
312ddde725dSArmin Le Grand                                 {
313ddde725dSArmin Le Grand                                     // choose default mapping
314ddde725dSArmin Le Grand                                     aViewBoxMapping = rRatio.createLinearMapping(aSvgCanvasRange, *getViewBox());
315ddde725dSArmin Le Grand                                 }
316ddde725dSArmin Le Grand 
317ddde725dSArmin Le Grand                                 // scale content to viewBox definitions
318ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xTransform(
319ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::TransformPrimitive2D(
320ddde725dSArmin Le Grand                                         aViewBoxMapping,
321ddde725dSArmin Le Grand                                         aSequence));
322ddde725dSArmin Le Grand 
323ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1);
324ddde725dSArmin Le Grand                             }
325ddde725dSArmin Le Grand                         }
326ddde725dSArmin Le Grand 
327ddde725dSArmin Le Grand                         // to be completely correct in Svg sense it is necessary to clip
328ddde725dSArmin Le Grand                         // the whole content to the given canvas. I choose here to do this
329ddde725dSArmin Le Grand                         // initially despite I found various examples of Svg files out there
330ddde725dSArmin Le Grand                         // which have no correct values for this clipping. It's correct
331ddde725dSArmin Le Grand                         // due to the Svg spec.
332ddde725dSArmin Le Grand                         bool bDoCorrectCanvasClipping(true);
333ddde725dSArmin Le Grand 
334ddde725dSArmin Le Grand                         if(bDoCorrectCanvasClipping)
335ddde725dSArmin Le Grand                         {
336ddde725dSArmin Le Grand                             // different from Svg we have the possibility with primitives to get
337*41923119SArmin Le Grand                             // a correct bounding box for the geometry. Get it for evtl. taking action
338ddde725dSArmin Le Grand                             const basegfx::B2DRange aContentRange(
339ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(
340ddde725dSArmin Le Grand                                     aSequence,
341ddde725dSArmin Le Grand                                     drawinglayer::geometry::ViewInformation2D()));
342ddde725dSArmin Le Grand 
343*41923119SArmin Le Grand                             if(aSvgCanvasRange.isInside(aContentRange))
344ddde725dSArmin Le Grand                             {
345*41923119SArmin Le Grand                                 // no clip needed, but an invisible HiddenGeometryPrimitive2D
346*41923119SArmin Le Grand                                 // to allow getting the full Svg range using the primitive mechanisms.
347*41923119SArmin Le Grand                                 // This is needed since e.g. an SdrObject using this as graphic will
348*41923119SArmin Le Grand                                 // create a mapping transformation to exactly map the content to it's
349*41923119SArmin Le Grand                                 // real life size
350*41923119SArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xLine(
351*41923119SArmin Le Grand                                     new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
352*41923119SArmin Le Grand                                         basegfx::tools::createPolygonFromRect(
353*41923119SArmin Le Grand                                             aSvgCanvasRange),
354*41923119SArmin Le Grand                                         basegfx::BColor(0.0, 0.0, 0.0)));
355*41923119SArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xHidden(
356*41923119SArmin Le Grand                                     new drawinglayer::primitive2d::HiddenGeometryPrimitive2D(
357*41923119SArmin Le Grand                                         drawinglayer::primitive2d::Primitive2DSequence(&xLine, 1)));
358*41923119SArmin Le Grand 
359*41923119SArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aSequence, xHidden);
360*41923119SArmin Le Grand                             }
361*41923119SArmin Le Grand                             else if(aSvgCanvasRange.overlaps(aContentRange))
362*41923119SArmin Le Grand                             {
363*41923119SArmin Le Grand                                 // Clip is necessary. This will make Svg images evtl. smaller
364*41923119SArmin Le Grand                                 // than wanted from Svg (the free space which may be around it is
365*41923119SArmin Le Grand                                 // conform to the Svg spec), but avoids an expensive and unneccessary
366*41923119SArmin Le Grand                                 // clip. Keep the full Svg range here to get the correct mappings
367*41923119SArmin Le Grand                                 // to objects using this. Optimizations can be done in the processors
368ddde725dSArmin Le Grand                                 const drawinglayer::primitive2d::Primitive2DReference xMask(
369ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::MaskPrimitive2D(
370ddde725dSArmin Le Grand                                         basegfx::B2DPolyPolygon(
371ddde725dSArmin Le Grand                                             basegfx::tools::createPolygonFromRect(
372ddde725dSArmin Le Grand                                                 aSvgCanvasRange)),
373ddde725dSArmin Le Grand                                         aSequence));
374ddde725dSArmin Le Grand 
375ddde725dSArmin Le Grand                                 aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1);
376ddde725dSArmin Le Grand                             }
377*41923119SArmin Le Grand                             else
378*41923119SArmin Le Grand                             {
379*41923119SArmin Le Grand                                 // not inside, no overlap. Empty Svg
380*41923119SArmin Le Grand                                 aSequence.realloc(0);
381*41923119SArmin Le Grand                             }
382ddde725dSArmin Le Grand                         }
383ddde725dSArmin Le Grand 
384*41923119SArmin Le Grand                         if(aSequence.hasElements())
385ddde725dSArmin Le Grand                         {
386ddde725dSArmin Le Grand                             // embed in transform primitive to scale to 1/100th mm
387ddde725dSArmin Le Grand                             // where 1 mm == 3.543307 px to get from Svg coordinates to
388ddde725dSArmin Le Grand                             // drawinglayer ones
389ddde725dSArmin Le Grand                             const double fScaleTo100thmm(100.0 / 3.543307);
390ddde725dSArmin Le Grand                             const basegfx::B2DHomMatrix aTransform(
391ddde725dSArmin Le Grand                                 basegfx::tools::createScaleB2DHomMatrix(
392ddde725dSArmin Le Grand                                     fScaleTo100thmm,
393ddde725dSArmin Le Grand                                     fScaleTo100thmm));
394ddde725dSArmin Le Grand 
395ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xTransform(
396ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::TransformPrimitive2D(
397ddde725dSArmin Le Grand                                     aTransform,
398ddde725dSArmin Le Grand                                     aSequence));
399ddde725dSArmin Le Grand 
400ddde725dSArmin Le Grand                             aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1);
401ddde725dSArmin Le Grand 
402*41923119SArmin Le Grand                             // append to result
403*41923119SArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence);
404*41923119SArmin Le Grand                         }
405ddde725dSArmin Le Grand                     }
406ddde725dSArmin Le Grand                 }
407ddde725dSArmin Le Grand             }
408ddde725dSArmin Le Grand         }
409ddde725dSArmin Le Grand 
410ddde725dSArmin Le Grand         const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const
411ddde725dSArmin Le Grand         {
412ddde725dSArmin Le Grand             if(getViewBox())
413ddde725dSArmin Le Grand             {
414ddde725dSArmin Le Grand                 return getViewBox();
415ddde725dSArmin Le Grand             }
416ddde725dSArmin Le Grand             else
417ddde725dSArmin Le Grand             {
418ddde725dSArmin Le Grand                 return SvgNode::getCurrentViewPort();
419ddde725dSArmin Le Grand             }
420ddde725dSArmin Le Grand         }
421ddde725dSArmin Le Grand 
422ddde725dSArmin Le Grand     } // end of namespace svgreader
423ddde725dSArmin Le Grand } // end of namespace svgio
424ddde725dSArmin Le Grand 
425ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
426ddde725dSArmin Le Grand // eof
427