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