Updated core
[LibreOffice.git] / svgio / source / svgreader / svgtextnode.cxx
blob77adedea0eb3f77c2714f18de3d6808922935365
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 <svgio/svgreader/svgtextnode.hxx>
21 #include <svgio/svgreader/svgcharacternode.hxx>
22 #include <svgio/svgreader/svgstyleattributes.hxx>
23 #include <svgio/svgreader/svgtrefnode.hxx>
24 #include <svgio/svgreader/svgtextpathnode.hxx>
25 #include <svgio/svgreader/svgtspannode.hxx>
26 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
27 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
29 //////////////////////////////////////////////////////////////////////////////
31 namespace svgio
33 namespace svgreader
35 SvgTextNode::SvgTextNode(
36 SvgDocument& rDocument,
37 SvgNode* pParent)
38 : SvgNode(SVGTokenText, rDocument, pParent),
39 maSvgStyleAttributes(*this),
40 mpaTransform(0),
41 maSvgTextPositions()
45 SvgTextNode::~SvgTextNode()
47 if(mpaTransform) delete mpaTransform;
50 const SvgStyleAttributes* SvgTextNode::getSvgStyleAttributes() const
52 static rtl::OUString aClassStr(rtl::OUString::createFromAscii("text"));
53 return checkForCssStyle(aClassStr, maSvgStyleAttributes);
56 void SvgTextNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
58 // call parent
59 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
61 // read style attributes
62 maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
64 // read text position attributes
65 maSvgTextPositions.parseTextPositionAttributes(rTokenName, aSVGToken, aContent);
67 // parse own
68 switch(aSVGToken)
70 case SVGTokenStyle:
72 maSvgStyleAttributes.readStyle(aContent);
73 break;
75 case SVGTokenTransform:
77 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
79 if(!aMatrix.isIdentity())
81 setTransform(&aMatrix);
83 break;
85 default:
87 break;
92 void SvgTextNode::addTextPrimitives(
93 const SvgNode& rCandidate,
94 drawinglayer::primitive2d::Primitive2DSequence& rTarget,
95 drawinglayer::primitive2d::Primitive2DSequence& rSource) const
97 if(rSource.hasElements())
99 const SvgStyleAttributes* pAttributes = rCandidate.getSvgStyleAttributes();
101 if(pAttributes)
103 // add text with taking all Fill/Stroke attributes into account
104 pAttributes->add_text(rTarget, rSource);
106 else
108 // should not happen, every subnode from SvgTextNode will at least
109 // return the attributes from SvgTextNode. Nonetheless, add text
110 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, rSource);
115 void SvgTextNode::DecomposeChild(const SvgNode& rCandidate, drawinglayer::primitive2d::Primitive2DSequence& rTarget, SvgTextPosition& rSvgTextPosition) const
117 switch(rCandidate.getType())
119 case SVGTokenCharacter:
121 // direct SvgTextPathNode derivates, decompose them
122 const SvgCharacterNode& rSvgCharacterNode = static_cast< const SvgCharacterNode& >(rCandidate);
123 rSvgCharacterNode.decomposeText(rTarget, rSvgTextPosition);
124 break;
126 case SVGTokenTextPath:
128 // direct TextPath decompose
129 const SvgTextPathNode& rSvgTextPathNode = static_cast< const SvgTextPathNode& >(rCandidate);
130 const SvgNodeVector& rChildren = rSvgTextPathNode.getChildren();
131 const sal_uInt32 nCount(rChildren.size());
133 if(nCount && rSvgTextPathNode.isValid())
135 // remember original TextStart to later detect hor/ver offsets
136 const basegfx::B2DPoint aTextStart(rSvgTextPosition.getPosition());
137 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
139 // decompose to regular TextPrimitives
140 for(sal_uInt32 a(0); a < nCount; a++)
142 DecomposeChild(*rChildren[a], aNewTarget, rSvgTextPosition);
145 if(aNewTarget.hasElements())
147 const drawinglayer::primitive2d::Primitive2DSequence aPathContent(aNewTarget);
148 aNewTarget.realloc(0);
150 // dismantle TextPrimitives and map them on curve/path
151 rSvgTextPathNode.decomposePathNode(aPathContent, aNewTarget, aTextStart);
154 if(aNewTarget.hasElements())
156 addTextPrimitives(rCandidate, rTarget, aNewTarget);
160 break;
162 case SVGTokenTspan:
164 // Tspan may have children, call recursively
165 const SvgTspanNode& rSvgTspanNode = static_cast< const SvgTspanNode& >(rCandidate);
166 const SvgNodeVector& rChildren = rSvgTspanNode.getChildren();
167 const sal_uInt32 nCount(rChildren.size());
169 if(nCount)
171 SvgTextPosition aSvgTextPosition(&rSvgTextPosition, rSvgTspanNode, rSvgTspanNode.getSvgTextPositions());
172 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
174 for(sal_uInt32 a(0); a < nCount; a++)
176 DecomposeChild(*rChildren[a], aNewTarget, aSvgTextPosition);
179 rSvgTextPosition.setPosition(aSvgTextPosition.getPosition());
181 if(aNewTarget.hasElements())
183 addTextPrimitives(rCandidate, rTarget, aNewTarget);
186 break;
188 case SVGTokenTref:
190 const SvgTrefNode& rSvgTrefNode = static_cast< const SvgTrefNode& >(rCandidate);
191 const SvgTextNode* pRefText = rSvgTrefNode.getReferencedSvgTextNode();
193 if(pRefText)
195 const SvgNodeVector& rChildren = pRefText->getChildren();
196 const sal_uInt32 nCount(rChildren.size());
197 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
199 if(nCount)
201 for(sal_uInt32 a(0); a < nCount; a++)
203 const SvgNode& rChildCandidate = *rChildren[a];
204 const_cast< SvgNode& >(rChildCandidate).setAlternativeParent(this);
206 DecomposeChild(rChildCandidate, aNewTarget, rSvgTextPosition);
207 const_cast< SvgNode& >(rChildCandidate).setAlternativeParent(0);
210 if(aNewTarget.hasElements())
212 addTextPrimitives(rCandidate, rTarget, aNewTarget);
217 break;
219 default:
221 OSL_ENSURE(false, "Unexpected node in text token (!)");
222 break;
227 void SvgTextNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool /*bReferenced`*/) const
229 // text has a group of child nodes, allowed are SVGTokenCharacter, SVGTokenTspan,
230 // SVGTokenTref and SVGTokenTextPath. These increase a given current text position
231 const SvgStyleAttributes* pStyle = getSvgStyleAttributes();
233 if(pStyle && !getChildren().empty())
235 const double fOpacity(pStyle->getOpacity().getNumber());
237 if(fOpacity > 0.0)
239 SvgTextPosition aSvgTextPosition(0, *this, getSvgTextPositions());
240 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
241 const SvgNodeVector& rChildren = getChildren();
242 const sal_uInt32 nCount(rChildren.size());
244 for(sal_uInt32 a(0); a < nCount; a++)
246 const SvgNode& rCandidate = *rChildren[a];
248 DecomposeChild(rCandidate, aNewTarget, aSvgTextPosition);
251 if(aNewTarget.hasElements())
253 drawinglayer::primitive2d::Primitive2DSequence aNewTarget2;
255 addTextPrimitives(*this, aNewTarget2, aNewTarget);
256 aNewTarget = aNewTarget2;
259 if(aNewTarget.hasElements())
261 pStyle->add_postProcess(rTarget, aNewTarget, getTransform());
266 } // end of namespace svgreader
267 } // end of namespace svgio
269 //////////////////////////////////////////////////////////////////////////////
270 // eof
272 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */