Updated core
[LibreOffice.git] / svgio / source / svgreader / svgnode.cxx
blobf1e7ea81a2f994c02ac0ea93103c2661c1dd09a5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <basegfx/polygon/b2dpolypolygontools.hxx>
21 #include <svgio/svgreader/svgdocument.hxx>
22 #include <svgio/svgreader/svgnode.hxx>
23 #include <svgio/svgreader/svgstyleattributes.hxx>
24 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
25 #include <tools/urlobj.hxx>
27 //////////////////////////////////////////////////////////////////////////////
29 namespace svgio
31 namespace svgreader
33 const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const
35 return 0;
38 const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const
40 if(maCssStyleVector.empty()) // #120435# Evaluate for CSS styles only once, this cannot change
42 const SvgDocument& rDocument = getDocument();
44 if(rDocument.hasSvgStyleAttributesById())
46 if(getClass())
48 // find all referenced CSS styles, a list of entries is allowed
49 const rtl::OUString* pClassList = getClass();
50 const sal_Int32 nLen(pClassList->getLength());
51 sal_Int32 nPos(0);
52 const SvgStyleAttributes* pNew = 0;
54 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
56 while(nPos < nLen)
58 rtl::OUStringBuffer aTokenValue;
60 copyToLimiter(*pClassList, sal_Unicode(' '), nPos, aTokenValue, nLen);
61 skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
63 rtl::OUString aId(rtl::OUString::createFromAscii("."));
64 const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
66 // look for CSS style common to token
67 aId = aId + aOUTokenValue;
68 pNew = rDocument.findSvgStyleAttributesById(aId);
70 if(!pNew && rClassStr.getLength())
72 // look for CSS style common to class.token
73 aId = rClassStr + aId;
75 pNew = rDocument.findSvgStyleAttributesById(aId);
78 if(pNew)
80 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
85 if(maCssStyleVector.empty() && getId())
87 // if none found, search for CSS style equal to Id
88 const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(*getId());
90 if(pNew)
92 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
96 if(maCssStyleVector.empty() && rClassStr.getLength())
98 // if none found, search for CSS style equal to class type
99 const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(rClassStr);
101 if(pNew)
103 const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
109 if(!maCssStyleVector.empty())
111 // #i123510# if CSS styles were found, create a linked list with rOriginal as parent
112 // and all CSS styles as linked children, so that the style attribute has
113 // priority over the CSS style. If there is no style attribute this means that
114 // no values are set at rOriginal, thus it is still correct to have that order.
115 // Repeated style requests should only be issued from sub-Text nodes and I'm not
116 // sure if in-between text nodes may build other chains (should not happen). But
117 // it's only a re-chaining with pointers (cheap), so allow to do it every time.
118 SvgStyleAttributes* pCurrent = const_cast< SvgStyleAttributes* >(&rOriginal);
119 pCurrent->setCssStyleParent(0);
121 for(sal_uInt32 a(0); a < maCssStyleVector.size(); a++)
123 SvgStyleAttributes* pNext = const_cast< SvgStyleAttributes* >(maCssStyleVector[a]);
125 pCurrent->setCssStyleParent(pNext);
126 pCurrent = pNext;
127 pCurrent->setCssStyleParent(0);
131 return &rOriginal;
134 SvgNode::SvgNode(
135 SVGToken aType,
136 SvgDocument& rDocument,
137 SvgNode* pParent)
138 : maType(aType),
139 mrDocument(rDocument),
140 mpParent(pParent),
141 mpAlternativeParent(0),
142 maChildren(),
143 mpId(0),
144 mpClass(0),
145 maXmlSpace(XmlSpace_notset),
146 maCssStyleVector()
148 OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)");
150 if(pParent)
152 pParent->maChildren.push_back(this);
154 else
156 #ifdef DBG_UTIL
157 if(SVGTokenSvg != getType())
159 OSL_ENSURE(false, "No parent for this node (!)");
161 #endif
165 SvgNode::~SvgNode()
167 while(maChildren.size())
169 delete maChildren[maChildren.size() - 1];
170 maChildren.pop_back();
173 if(mpId) delete mpId;
174 if(mpClass) delete mpClass;
177 void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs)
179 const sal_uInt32 nAttributes(xAttribs->getLength());
181 for(sal_uInt32 a(0); a < nAttributes; a++)
183 const OUString aTokenName(xAttribs->getNameByIndex(a));
185 parseAttribute(aTokenName, StrToSVGToken(aTokenName), xAttribs->getValueByIndex(a));
189 void SvgNode::parseAttribute(const OUString& /*rTokenName*/, SVGToken aSVGToken, const OUString& aContent)
191 switch(aSVGToken)
193 case SVGTokenId:
195 if(aContent.getLength())
197 setId(&aContent);
199 break;
201 case SVGTokenClass:
203 if(aContent.getLength())
205 setClass(&aContent);
207 break;
209 case SVGTokenXmlSpace:
211 if(aContent.getLength())
213 static OUString aStrDefault(OUString::createFromAscii("default"));
214 static OUString aStrPreserve(OUString::createFromAscii("preserve"));
216 if(aContent.match(aStrDefault))
218 setXmlSpace(XmlSpace_default);
220 else if(aContent.match(aStrPreserve))
222 setXmlSpace(XmlSpace_preserve);
225 break;
227 default:
229 break;
234 void SvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const
236 if(!bReferenced)
238 if(SVGTokenDefs == getType() ||
239 SVGTokenSymbol == getType() ||
240 SVGTokenClipPathNode == getType() ||
241 SVGTokenMask == getType() ||
242 SVGTokenMarker == getType() ||
243 SVGTokenPattern == getType())
245 // do not decompose defs or symbol nodes (these hold only style-like
246 // objects which may be used by referencing them) except when doing
247 // so controlled referenced
249 // also do not decompose ClipPaths and Masks. These should be embedded
250 // in a defs node (which gets not decomposed by itself), but you never
251 // know
253 // also not directly used are Markers and Patterns, only indirecty used
254 // by reference
255 return;
259 const SvgNodeVector& rChildren = getChildren();
261 if(!rChildren.empty())
263 const sal_uInt32 nCount(rChildren.size());
265 for(sal_uInt32 a(0); a < nCount; a++)
267 SvgNode* pCandidate = rChildren[a];
269 if(pCandidate)
271 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
273 pCandidate->decomposeSvgNode(aNewTarget, bReferenced);
275 if(aNewTarget.hasElements())
277 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget);
280 else
282 OSL_ENSURE(false, "Null-Pointer in child node list (!)");
286 if(rTarget.hasElements())
288 const SvgStyleAttributes* pStyles = getSvgStyleAttributes();
290 if(pStyles)
292 // check if we have Title or Desc
293 const OUString& rTitle = pStyles->getTitle();
294 const OUString& rDesc = pStyles->getDesc();
296 if(rTitle.getLength() || rDesc.getLength())
298 // default object name is empty
299 OUString aObjectName;
301 // use path as object name when outmost element
302 if(SVGTokenSvg == getType())
304 aObjectName = getDocument().getAbsolutePath();
306 if(aObjectName.getLength())
308 INetURLObject aURL(aObjectName);
310 aObjectName = aURL.getName(
311 INetURLObject::LAST_SEGMENT,
312 true,
313 INetURLObject::DECODE_WITH_CHARSET);
317 // pack in ObjectInfoPrimitive2D group
318 const drawinglayer::primitive2d::Primitive2DReference xRef(
319 new drawinglayer::primitive2d::ObjectInfoPrimitive2D(
320 rTarget,
321 aObjectName,
322 rTitle,
323 rDesc));
325 rTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
332 const basegfx::B2DRange* SvgNode::getCurrentViewPort() const
334 if(getParent())
336 return getParent()->getCurrentViewPort();
338 else
340 return 0;
344 double SvgNode::getCurrentFontSizeInherited() const
346 if(getParent())
348 return getParent()->getCurrentFontSize();
350 else
352 return 0.0;
356 double SvgNode::getCurrentFontSize() const
358 if(getSvgStyleAttributes())
359 return getSvgStyleAttributes()->getFontSize().solve(*this, xcoordinate);
361 return getCurrentFontSizeInherited();
364 double SvgNode::getCurrentXHeightInherited() const
366 if(getParent())
368 return getParent()->getCurrentXHeight();
370 else
372 return 0.0;
376 double SvgNode::getCurrentXHeight() const
378 if(getSvgStyleAttributes())
379 // for XHeight, use FontSize currently
380 return getSvgStyleAttributes()->getFontSize().solve(*this, ycoordinate);
382 return getCurrentXHeightInherited();
385 void SvgNode::setId(const OUString* pfId)
387 if(mpId)
389 mrDocument.removeSvgNodeFromMapper(*mpId);
390 delete mpId;
391 mpId = 0;
394 if(pfId)
396 mpId = new OUString(*pfId);
397 mrDocument.addSvgNodeToMapper(*mpId, *this);
401 void SvgNode::setClass(const OUString* pfClass)
403 if(mpClass)
405 mrDocument.removeSvgNodeFromMapper(*mpClass);
406 delete mpClass;
407 mpClass = 0;
410 if(pfClass)
412 mpClass = new OUString(*pfClass);
413 mrDocument.addSvgNodeToMapper(*mpClass, *this);
417 XmlSpace SvgNode::getXmlSpace() const
419 if(maXmlSpace != XmlSpace_notset)
421 return maXmlSpace;
424 if(getParent())
426 return getParent()->getXmlSpace();
429 // default is XmlSpace_default
430 return XmlSpace_default;
433 } // end of namespace svgreader
434 } // end of namespace svgio
436 //////////////////////////////////////////////////////////////////////////////
437 // eof
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */