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