xref: /aoo42x/main/svgio/source/svgreader/svgnode.cxx (revision 025b0597)
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/svgnode.hxx>
26ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolypolygontools.hxx>
27ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocument.hxx>
28ddde725dSArmin Le Grand #include <svgio/svgreader/svgnode.hxx>
29ddde725dSArmin Le Grand #include <svgio/svgreader/svgstyleattributes.hxx>
30*025b0597SArmin Le Grand #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
31ddde725dSArmin Le Grand 
32ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
33ddde725dSArmin Le Grand 
34ddde725dSArmin Le Grand namespace svgio
35ddde725dSArmin Le Grand {
36ddde725dSArmin Le Grand     namespace svgreader
37ddde725dSArmin Le Grand     {
38ddde725dSArmin Le Grand         const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const
39ddde725dSArmin Le Grand         {
40ddde725dSArmin Le Grand             return 0;
41ddde725dSArmin Le Grand         }
42ddde725dSArmin Le Grand 
43ddde725dSArmin Le Grand         SvgNode::SvgNode(
44ddde725dSArmin Le Grand             SVGToken aType,
45ddde725dSArmin Le Grand             SvgDocument& rDocument,
46ddde725dSArmin Le Grand             SvgNode* pParent)
47ddde725dSArmin Le Grand         :   maType(aType),
48ddde725dSArmin Le Grand             mrDocument(rDocument),
49ddde725dSArmin Le Grand             mpParent(pParent),
50ddde725dSArmin Le Grand             mpAlternativeParent(0),
51ddde725dSArmin Le Grand             maChildren(),
52ddde725dSArmin Le Grand             mpId(0),
53ddde725dSArmin Le Grand             mpClass(0),
54ddde725dSArmin Le Grand             maXmlSpace(XmlSpace_notset)
55ddde725dSArmin Le Grand         {
56ddde725dSArmin Le Grand             OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)");
57ddde725dSArmin Le Grand 
58ddde725dSArmin Le Grand             if(pParent)
59ddde725dSArmin Le Grand             {
60ddde725dSArmin Le Grand                 pParent->maChildren.push_back(this);
61ddde725dSArmin Le Grand             }
62ddde725dSArmin Le Grand             else
63ddde725dSArmin Le Grand             {
64ddde725dSArmin Le Grand #ifdef DBG_UTIL
65ddde725dSArmin Le Grand                 if(SVGTokenSvg != getType())
66ddde725dSArmin Le Grand                 {
67ddde725dSArmin Le Grand                     OSL_ENSURE(false, "No parent for this node (!)");
68ddde725dSArmin Le Grand                 }
69ddde725dSArmin Le Grand #endif
70ddde725dSArmin Le Grand             }
71ddde725dSArmin Le Grand         }
72ddde725dSArmin Le Grand 
73ddde725dSArmin Le Grand         SvgNode::~SvgNode()
74ddde725dSArmin Le Grand         {
75ddde725dSArmin Le Grand             while(maChildren.size())
76ddde725dSArmin Le Grand             {
77ddde725dSArmin Le Grand                 delete maChildren[maChildren.size() - 1];
78ddde725dSArmin Le Grand                 maChildren.pop_back();
79ddde725dSArmin Le Grand             }
80ddde725dSArmin Le Grand 
81ddde725dSArmin Le Grand             if(mpId) delete mpId;
82ddde725dSArmin Le Grand             if(mpClass) delete mpClass;
83ddde725dSArmin Le Grand         }
84ddde725dSArmin Le Grand 
85ddde725dSArmin Le Grand         void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs)
86ddde725dSArmin Le Grand         {
87ddde725dSArmin Le Grand             const sal_uInt32 nAttributes(xAttribs->getLength());
88ddde725dSArmin Le Grand 
89ddde725dSArmin Le Grand             for(sal_uInt32 a(0); a < nAttributes; a++)
90ddde725dSArmin Le Grand             {
91ddde725dSArmin Le Grand                 const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a));
92ddde725dSArmin Le Grand 
93ddde725dSArmin Le Grand                 parseAttribute(aTokenName, StrToSVGToken(aTokenName), xAttribs->getValueByIndex(a));
94ddde725dSArmin Le Grand             }
95ddde725dSArmin Le Grand         }
96ddde725dSArmin Le Grand 
97e2bf1e9dSArmin Le Grand         void SvgNode::parseAttribute(const rtl::OUString& /*rTokenName*/, SVGToken aSVGToken, const rtl::OUString& aContent)
98ddde725dSArmin Le Grand         {
99ddde725dSArmin Le Grand             switch(aSVGToken)
100ddde725dSArmin Le Grand             {
101ddde725dSArmin Le Grand                 case SVGTokenId:
102ddde725dSArmin Le Grand                 {
103ddde725dSArmin Le Grand                     if(aContent.getLength())
104ddde725dSArmin Le Grand                     {
105ddde725dSArmin Le Grand                         setId(&aContent);
106ddde725dSArmin Le Grand                     }
107ddde725dSArmin Le Grand                     break;
108ddde725dSArmin Le Grand                 }
109ddde725dSArmin Le Grand                 case SVGTokenClass:
110ddde725dSArmin Le Grand                 {
111ddde725dSArmin Le Grand                     if(aContent.getLength())
112ddde725dSArmin Le Grand                     {
113ddde725dSArmin Le Grand                         setClass(&aContent);
114ddde725dSArmin Le Grand                     }
115ddde725dSArmin Le Grand                     break;
116ddde725dSArmin Le Grand                 }
117ddde725dSArmin Le Grand                 case SVGTokenXmlSpace:
118ddde725dSArmin Le Grand                 {
119ddde725dSArmin Le Grand                     if(aContent.getLength())
120ddde725dSArmin Le Grand                     {
121ddde725dSArmin Le Grand                         static rtl::OUString aStrDefault(rtl::OUString::createFromAscii("default"));
122ddde725dSArmin Le Grand                         static rtl::OUString aStrPreserve(rtl::OUString::createFromAscii("preserve"));
123ddde725dSArmin Le Grand 
124ddde725dSArmin Le Grand                         if(aContent.match(aStrDefault))
125ddde725dSArmin Le Grand                         {
126ddde725dSArmin Le Grand                             setXmlSpace(XmlSpace_default);
127ddde725dSArmin Le Grand                         }
128ddde725dSArmin Le Grand                         else if(aContent.match(aStrPreserve))
129ddde725dSArmin Le Grand                         {
130ddde725dSArmin Le Grand                             setXmlSpace(XmlSpace_preserve);
131ddde725dSArmin Le Grand                         }
132ddde725dSArmin Le Grand                     }
133ddde725dSArmin Le Grand                     break;
134ddde725dSArmin Le Grand                 }
135e2bf1e9dSArmin Le Grand                 default:
136e2bf1e9dSArmin Le Grand                 {
137e2bf1e9dSArmin Le Grand                     break;
138e2bf1e9dSArmin Le Grand                 }
139ddde725dSArmin Le Grand             }
140ddde725dSArmin Le Grand         }
141ddde725dSArmin Le Grand 
142ddde725dSArmin Le Grand         void SvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const
143ddde725dSArmin Le Grand         {
144ddde725dSArmin Le Grand             if(!bReferenced)
145ddde725dSArmin Le Grand             {
146ddde725dSArmin Le Grand                 if(SVGTokenDefs == getType() ||
147ddde725dSArmin Le Grand                     SVGTokenSymbol == getType() ||
148ddde725dSArmin Le Grand                     SVGTokenClipPathNode == getType() ||
149ddde725dSArmin Le Grand                     SVGTokenMask == getType() ||
150ddde725dSArmin Le Grand                     SVGTokenMarker == getType() ||
151ddde725dSArmin Le Grand                     SVGTokenPattern == getType())
152ddde725dSArmin Le Grand                 {
153ddde725dSArmin Le Grand                     // do not decompose defs or symbol nodes (these hold only style-like
154ddde725dSArmin Le Grand                     // objects which may be used by referencing them) except when doing
155ddde725dSArmin Le Grand                     // so controlled referenced
156ddde725dSArmin Le Grand 
157ddde725dSArmin Le Grand                     // also do not decompose ClipPaths and Masks. These should be embedded
158ddde725dSArmin Le Grand                     // in a defs node (which gets not decomposed by itself), but you never
159ddde725dSArmin Le Grand                     // know
160ddde725dSArmin Le Grand 
161ddde725dSArmin Le Grand                     // also not directly used are Markers and Patterns, only indirecty used
162ddde725dSArmin Le Grand                     // by reference
163ddde725dSArmin Le Grand                     return;
164ddde725dSArmin Le Grand                 }
165ddde725dSArmin Le Grand             }
166ddde725dSArmin Le Grand 
167ddde725dSArmin Le Grand             const SvgNodeVector& rChildren = getChildren();
168ddde725dSArmin Le Grand 
169ddde725dSArmin Le Grand             if(!rChildren.empty())
170ddde725dSArmin Le Grand             {
171ddde725dSArmin Le Grand                 const sal_uInt32 nCount(rChildren.size());
172ddde725dSArmin Le Grand 
173ddde725dSArmin Le Grand                 for(sal_uInt32 a(0); a < nCount; a++)
174ddde725dSArmin Le Grand                 {
175ddde725dSArmin Le Grand                     SvgNode* pCandidate = rChildren[a];
176ddde725dSArmin Le Grand 
177ddde725dSArmin Le Grand                     if(pCandidate)
178ddde725dSArmin Le Grand                     {
179ddde725dSArmin Le Grand                         drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
180ddde725dSArmin Le Grand 
181ddde725dSArmin Le Grand                         pCandidate->decomposeSvgNode(aNewTarget, bReferenced);
182ddde725dSArmin Le Grand 
183ddde725dSArmin Le Grand                         if(aNewTarget.hasElements())
184ddde725dSArmin Le Grand                         {
185ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget);
186ddde725dSArmin Le Grand                         }
187ddde725dSArmin Le Grand                     }
188ddde725dSArmin Le Grand                     else
189ddde725dSArmin Le Grand                     {
190ddde725dSArmin Le Grand                         OSL_ENSURE(false, "Null-Pointer in child node list (!)");
191ddde725dSArmin Le Grand                     }
192ddde725dSArmin Le Grand                 }
193*025b0597SArmin Le Grand 
194*025b0597SArmin Le Grand                 if(rTarget.hasElements())
195*025b0597SArmin Le Grand                 {
196*025b0597SArmin Le Grand                     const SvgStyleAttributes* pStyles = getSvgStyleAttributes();
197*025b0597SArmin Le Grand 
198*025b0597SArmin Le Grand                     if(pStyles)
199*025b0597SArmin Le Grand                     {
200*025b0597SArmin Le Grand                         // check if we have Title or Desc
201*025b0597SArmin Le Grand                         const rtl::OUString& rTitle = pStyles->getTitle();
202*025b0597SArmin Le Grand                         const rtl::OUString& rDesc = pStyles->getDesc();
203*025b0597SArmin Le Grand 
204*025b0597SArmin Le Grand                         if(rTitle.getLength() || rDesc.getLength())
205*025b0597SArmin Le Grand                         {
206*025b0597SArmin Le Grand                             // default object name is empty
207*025b0597SArmin Le Grand                             rtl::OUString aObjectName;
208*025b0597SArmin Le Grand 
209*025b0597SArmin Le Grand                             // use path as object name when outmost element
210*025b0597SArmin Le Grand                             if(SVGTokenSvg == getType())
211*025b0597SArmin Le Grand                             {
212*025b0597SArmin Le Grand                                 aObjectName = getDocument().getAbsolutePath();
213*025b0597SArmin Le Grand                             }
214*025b0597SArmin Le Grand 
215*025b0597SArmin Le Grand                             // pack in ObjectInfoPrimitive2D group
216*025b0597SArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xRef(
217*025b0597SArmin Le Grand                                 new drawinglayer::primitive2d::ObjectInfoPrimitive2D(
218*025b0597SArmin Le Grand                                     rTarget,
219*025b0597SArmin Le Grand                                     aObjectName,
220*025b0597SArmin Le Grand                                     rTitle,
221*025b0597SArmin Le Grand                                     rDesc));
222*025b0597SArmin Le Grand 
223*025b0597SArmin Le Grand                             rTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
224*025b0597SArmin Le Grand                         }
225*025b0597SArmin Le Grand                     }
226*025b0597SArmin Le Grand                 }
227ddde725dSArmin Le Grand             }
228ddde725dSArmin Le Grand         }
229ddde725dSArmin Le Grand 
230ddde725dSArmin Le Grand         const basegfx::B2DRange* SvgNode::getCurrentViewPort() const
231ddde725dSArmin Le Grand         {
232ddde725dSArmin Le Grand             if(getParent())
233ddde725dSArmin Le Grand             {
234ddde725dSArmin Le Grand                 return getParent()->getCurrentViewPort();
235ddde725dSArmin Le Grand             }
236ddde725dSArmin Le Grand             else
237ddde725dSArmin Le Grand             {
238ddde725dSArmin Le Grand                 return 0;
239ddde725dSArmin Le Grand             }
240ddde725dSArmin Le Grand         }
241ddde725dSArmin Le Grand 
242ddde725dSArmin Le Grand         double SvgNode::getCurrentFontSize() const
243ddde725dSArmin Le Grand         {
244ddde725dSArmin Le Grand             if(getSvgStyleAttributes())
245ddde725dSArmin Le Grand             {
246ddde725dSArmin Le Grand                 return getSvgStyleAttributes()->getFontSize().solve(*this, xcoordinate);
247ddde725dSArmin Le Grand             }
248ddde725dSArmin Le Grand             else if(getParent())
249ddde725dSArmin Le Grand             {
250ddde725dSArmin Le Grand                 return getParent()->getCurrentFontSize();
251ddde725dSArmin Le Grand             }
252ddde725dSArmin Le Grand             else
253ddde725dSArmin Le Grand             {
254ddde725dSArmin Le Grand                 return 0.0;
255ddde725dSArmin Le Grand             }
256ddde725dSArmin Le Grand         }
257ddde725dSArmin Le Grand 
258ddde725dSArmin Le Grand         double SvgNode::getCurrentXHeight() const
259ddde725dSArmin Le Grand         {
260ddde725dSArmin Le Grand             if(getSvgStyleAttributes())
261ddde725dSArmin Le Grand             {
262ddde725dSArmin Le Grand                 // for XHeight, use FontSize currently
263ddde725dSArmin Le Grand                 return getSvgStyleAttributes()->getFontSize().solve(*this, ycoordinate);
264ddde725dSArmin Le Grand             }
265ddde725dSArmin Le Grand             else if(getParent())
266ddde725dSArmin Le Grand             {
267ddde725dSArmin Le Grand                 return getParent()->getCurrentXHeight();
268ddde725dSArmin Le Grand             }
269ddde725dSArmin Le Grand             else
270ddde725dSArmin Le Grand             {
271ddde725dSArmin Le Grand                 return 0.0;
272ddde725dSArmin Le Grand             }
273ddde725dSArmin Le Grand         }
274ddde725dSArmin Le Grand 
275ddde725dSArmin Le Grand         void SvgNode::setId(const rtl::OUString* pfId)
276ddde725dSArmin Le Grand         {
277ddde725dSArmin Le Grand             if(mpId)
278ddde725dSArmin Le Grand             {
279ddde725dSArmin Le Grand                 mrDocument.removeSvgNodeFromMapper(*mpId);
280ddde725dSArmin Le Grand                 delete mpId;
281ddde725dSArmin Le Grand                 mpId = 0;
282ddde725dSArmin Le Grand             }
283ddde725dSArmin Le Grand 
284ddde725dSArmin Le Grand             if(pfId)
285ddde725dSArmin Le Grand             {
286ddde725dSArmin Le Grand                 mpId = new rtl::OUString(*pfId);
287ddde725dSArmin Le Grand                 mrDocument.addSvgNodeToMapper(*mpId, *this);
288ddde725dSArmin Le Grand             }
289ddde725dSArmin Le Grand         }
290ddde725dSArmin Le Grand 
291ddde725dSArmin Le Grand         void SvgNode::setClass(const rtl::OUString* pfClass)
292ddde725dSArmin Le Grand         {
293ddde725dSArmin Le Grand             if(mpClass)
294ddde725dSArmin Le Grand             {
295ddde725dSArmin Le Grand                 mrDocument.removeSvgNodeFromMapper(*mpClass);
296ddde725dSArmin Le Grand                 delete mpClass;
297ddde725dSArmin Le Grand                 mpClass = 0;
298ddde725dSArmin Le Grand             }
299ddde725dSArmin Le Grand 
300ddde725dSArmin Le Grand             if(pfClass)
301ddde725dSArmin Le Grand             {
302ddde725dSArmin Le Grand                 mpClass = new rtl::OUString(*pfClass);
303ddde725dSArmin Le Grand                 mrDocument.addSvgNodeToMapper(*mpClass, *this);
304ddde725dSArmin Le Grand             }
305ddde725dSArmin Le Grand         }
306ddde725dSArmin Le Grand 
307ddde725dSArmin Le Grand         XmlSpace SvgNode::getXmlSpace() const
308ddde725dSArmin Le Grand         {
309ddde725dSArmin Le Grand             if(maXmlSpace != XmlSpace_notset)
310ddde725dSArmin Le Grand             {
311ddde725dSArmin Le Grand                 return maXmlSpace;
312ddde725dSArmin Le Grand             }
313ddde725dSArmin Le Grand 
314ddde725dSArmin Le Grand             if(getParent())
315ddde725dSArmin Le Grand             {
316ddde725dSArmin Le Grand                 return getParent()->getXmlSpace();
317ddde725dSArmin Le Grand             }
318ddde725dSArmin Le Grand 
319ddde725dSArmin Le Grand             // default is XmlSpace_default
320ddde725dSArmin Le Grand             return XmlSpace_default;
321ddde725dSArmin Le Grand         }
322ddde725dSArmin Le Grand 
323ddde725dSArmin Le Grand     } // end of namespace svgreader
324ddde725dSArmin Le Grand } // end of namespace svgio
325ddde725dSArmin Le Grand 
326ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
327ddde725dSArmin Le Grand // eof
328