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