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/svgcharacternode.hxx> 26ddde725dSArmin Le Grand #include <svgio/svgreader/svgstyleattributes.hxx> 27ddde725dSArmin Le Grand #include <drawinglayer/attribute/fontattribute.hxx> 28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/textprimitive2d.hxx> 29ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/textlayoutdevice.hxx> 30ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/textbreakuphelper.hxx> 31ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/groupprimitive2d.hxx> 32ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> 33ddde725dSArmin Le Grand 34ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 35ddde725dSArmin Le Grand 36ddde725dSArmin Le Grand namespace svgio 37ddde725dSArmin Le Grand { 38ddde725dSArmin Le Grand namespace svgreader 39ddde725dSArmin Le Grand { SvgTextPositions()40ddde725dSArmin Le Grand SvgTextPositions::SvgTextPositions() 41ddde725dSArmin Le Grand : maX(), 42ddde725dSArmin Le Grand maY(), 43ddde725dSArmin Le Grand maDx(), 44ddde725dSArmin Le Grand maDy(), 45ddde725dSArmin Le Grand maRotate(), 46ddde725dSArmin Le Grand maTextLength(), 47ddde725dSArmin Le Grand mbLengthAdjust(true) 48ddde725dSArmin Le Grand { 49ddde725dSArmin Le Grand } 50ddde725dSArmin Le Grand parseTextPositionAttributes(const rtl::OUString &,SVGToken aSVGToken,const rtl::OUString & aContent)51e2bf1e9dSArmin Le Grand void SvgTextPositions::parseTextPositionAttributes(const rtl::OUString& /*rTokenName*/, SVGToken aSVGToken, const rtl::OUString& aContent) 52ddde725dSArmin Le Grand { 53ddde725dSArmin Le Grand // parse own 54ddde725dSArmin Le Grand switch(aSVGToken) 55ddde725dSArmin Le Grand { 56ddde725dSArmin Le Grand case SVGTokenX: 57ddde725dSArmin Le Grand { 58ddde725dSArmin Le Grand if(aContent.getLength()) 59ddde725dSArmin Le Grand { 60ddde725dSArmin Le Grand SvgNumberVector aVector; 61ddde725dSArmin Le Grand 62ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 63ddde725dSArmin Le Grand { 64ddde725dSArmin Le Grand setX(aVector); 65ddde725dSArmin Le Grand } 66ddde725dSArmin Le Grand } 67ddde725dSArmin Le Grand break; 68ddde725dSArmin Le Grand } 69ddde725dSArmin Le Grand case SVGTokenY: 70ddde725dSArmin Le Grand { 71ddde725dSArmin Le Grand if(aContent.getLength()) 72ddde725dSArmin Le Grand { 73ddde725dSArmin Le Grand SvgNumberVector aVector; 74ddde725dSArmin Le Grand 75ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 76ddde725dSArmin Le Grand { 77ddde725dSArmin Le Grand setY(aVector); 78ddde725dSArmin Le Grand } 79ddde725dSArmin Le Grand } 80ddde725dSArmin Le Grand break; 81ddde725dSArmin Le Grand } 82ddde725dSArmin Le Grand case SVGTokenDx: 83ddde725dSArmin Le Grand { 84ddde725dSArmin Le Grand if(aContent.getLength()) 85ddde725dSArmin Le Grand { 86ddde725dSArmin Le Grand SvgNumberVector aVector; 87ddde725dSArmin Le Grand 88ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 89ddde725dSArmin Le Grand { 90ddde725dSArmin Le Grand setDx(aVector); 91ddde725dSArmin Le Grand } 92ddde725dSArmin Le Grand } 93ddde725dSArmin Le Grand break; 94ddde725dSArmin Le Grand } 95ddde725dSArmin Le Grand case SVGTokenDy: 96ddde725dSArmin Le Grand { 97ddde725dSArmin Le Grand if(aContent.getLength()) 98ddde725dSArmin Le Grand { 99ddde725dSArmin Le Grand SvgNumberVector aVector; 100ddde725dSArmin Le Grand 101ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 102ddde725dSArmin Le Grand { 103ddde725dSArmin Le Grand setDy(aVector); 104ddde725dSArmin Le Grand } 105ddde725dSArmin Le Grand } 106ddde725dSArmin Le Grand break; 107ddde725dSArmin Le Grand } 108ddde725dSArmin Le Grand case SVGTokenRotate: 109ddde725dSArmin Le Grand { 110ddde725dSArmin Le Grand if(aContent.getLength()) 111ddde725dSArmin Le Grand { 112ddde725dSArmin Le Grand SvgNumberVector aVector; 113ddde725dSArmin Le Grand 114ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 115ddde725dSArmin Le Grand { 116ddde725dSArmin Le Grand setRotate(aVector); 117ddde725dSArmin Le Grand } 118ddde725dSArmin Le Grand } 119ddde725dSArmin Le Grand break; 120ddde725dSArmin Le Grand } 121ddde725dSArmin Le Grand case SVGTokenTextLength: 122ddde725dSArmin Le Grand { 123ddde725dSArmin Le Grand SvgNumber aNum; 124ddde725dSArmin Le Grand 125ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 126ddde725dSArmin Le Grand { 127ddde725dSArmin Le Grand if(aNum.isPositive()) 128ddde725dSArmin Le Grand { 129ddde725dSArmin Le Grand setTextLength(aNum); 130ddde725dSArmin Le Grand } 131ddde725dSArmin Le Grand } 132ddde725dSArmin Le Grand break; 133ddde725dSArmin Le Grand } 134ddde725dSArmin Le Grand case SVGTokenLengthAdjust: 135ddde725dSArmin Le Grand { 136ddde725dSArmin Le Grand if(aContent.getLength()) 137ddde725dSArmin Le Grand { 138ddde725dSArmin Le Grand static rtl::OUString aStrSpacing(rtl::OUString::createFromAscii("spacing")); 139ddde725dSArmin Le Grand static rtl::OUString aStrSpacingAndGlyphs(rtl::OUString::createFromAscii("spacingAndGlyphs")); 140ddde725dSArmin Le Grand 141ddde725dSArmin Le Grand if(aContent.match(aStrSpacing)) 142ddde725dSArmin Le Grand { 143ddde725dSArmin Le Grand setLengthAdjust(true); 144ddde725dSArmin Le Grand } 145ddde725dSArmin Le Grand else if(aContent.match(aStrSpacingAndGlyphs)) 146ddde725dSArmin Le Grand { 147ddde725dSArmin Le Grand setLengthAdjust(false); 148ddde725dSArmin Le Grand } 149ddde725dSArmin Le Grand } 150ddde725dSArmin Le Grand break; 151ddde725dSArmin Le Grand } 152e2bf1e9dSArmin Le Grand default: 153e2bf1e9dSArmin Le Grand { 154e2bf1e9dSArmin Le Grand break; 155e2bf1e9dSArmin Le Grand } 156ddde725dSArmin Le Grand } 157ddde725dSArmin Le Grand } 158ddde725dSArmin Le Grand 159ddde725dSArmin Le Grand } // end of namespace svgreader 160ddde725dSArmin Le Grand } // end of namespace svgio 161ddde725dSArmin Le Grand 162ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 163ddde725dSArmin Le Grand 164ddde725dSArmin Le Grand namespace svgio 165ddde725dSArmin Le Grand { 166ddde725dSArmin Le Grand namespace svgreader 167ddde725dSArmin Le Grand { 168ddde725dSArmin Le Grand class localTextBreakupHelper : public drawinglayer::primitive2d::TextBreakupHelper 169ddde725dSArmin Le Grand { 170ddde725dSArmin Le Grand private: 171ddde725dSArmin Le Grand SvgTextPosition& mrSvgTextPosition; 172ddde725dSArmin Le Grand 173ddde725dSArmin Le Grand protected: 174ddde725dSArmin Le Grand /// allow user callback to allow changes to the new TextTransformation. Default 175ddde725dSArmin Le Grand /// does nothing. 176ddde725dSArmin Le Grand virtual bool allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength); 177ddde725dSArmin Le Grand 178ddde725dSArmin Le Grand public: localTextBreakupHelper(const drawinglayer::primitive2d::TextSimplePortionPrimitive2D & rSource,SvgTextPosition & rSvgTextPosition)179ddde725dSArmin Le Grand localTextBreakupHelper( 180693be7f6SArmin Le Grand const drawinglayer::primitive2d::TextSimplePortionPrimitive2D& rSource, 181ddde725dSArmin Le Grand SvgTextPosition& rSvgTextPosition) 182693be7f6SArmin Le Grand : drawinglayer::primitive2d::TextBreakupHelper(rSource), 183ddde725dSArmin Le Grand mrSvgTextPosition(rSvgTextPosition) 184ddde725dSArmin Le Grand { 185ddde725dSArmin Le Grand } 186ddde725dSArmin Le Grand }; 187ddde725dSArmin Le Grand allowChange(sal_uInt32,basegfx::B2DHomMatrix & rNewTransform,sal_uInt32,sal_uInt32)188e2bf1e9dSArmin Le Grand bool localTextBreakupHelper::allowChange(sal_uInt32 /*nCount*/, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 /*nIndex*/, sal_uInt32 /*nLength*/) 189ddde725dSArmin Le Grand { 190ddde725dSArmin Le Grand const double fRotation(mrSvgTextPosition.consumeRotation()); 191ddde725dSArmin Le Grand 192ddde725dSArmin Le Grand if(0.0 != fRotation) 193ddde725dSArmin Le Grand { 194ddde725dSArmin Le Grand const basegfx::B2DPoint aBasePoint(rNewTransform * basegfx::B2DPoint(0.0, 0.0)); 195ddde725dSArmin Le Grand 196ddde725dSArmin Le Grand rNewTransform.translate(-aBasePoint.getX(), -aBasePoint.getY()); 197ddde725dSArmin Le Grand rNewTransform.rotate(fRotation); 198ddde725dSArmin Le Grand rNewTransform.translate(aBasePoint.getX(), aBasePoint.getY()); 199ddde725dSArmin Le Grand } 200ddde725dSArmin Le Grand 201ddde725dSArmin Le Grand return true; 202ddde725dSArmin Le Grand } 203ddde725dSArmin Le Grand 204ddde725dSArmin Le Grand } // end of namespace svgreader 205ddde725dSArmin Le Grand } // end of namespace svgio 206ddde725dSArmin Le Grand 207ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 208ddde725dSArmin Le Grand 209ddde725dSArmin Le Grand namespace svgio 210ddde725dSArmin Le Grand { 211ddde725dSArmin Le Grand namespace svgreader 212ddde725dSArmin Le Grand { SvgCharacterNode(SvgDocument & rDocument,SvgNode * pParent,const rtl::OUString & rText)213ddde725dSArmin Le Grand SvgCharacterNode::SvgCharacterNode( 214ddde725dSArmin Le Grand SvgDocument& rDocument, 215ddde725dSArmin Le Grand SvgNode* pParent, 216ddde725dSArmin Le Grand const rtl::OUString& rText) 217ddde725dSArmin Le Grand : SvgNode(SVGTokenCharacter, rDocument, pParent), 218ddde725dSArmin Le Grand maText(rText) 219ddde725dSArmin Le Grand { 220ddde725dSArmin Le Grand } 221ddde725dSArmin Le Grand ~SvgCharacterNode()222ddde725dSArmin Le Grand SvgCharacterNode::~SvgCharacterNode() 223ddde725dSArmin Le Grand { 224ddde725dSArmin Le Grand } 225ddde725dSArmin Le Grand getSvgStyleAttributes() const226ddde725dSArmin Le Grand const SvgStyleAttributes* SvgCharacterNode::getSvgStyleAttributes() const 227ddde725dSArmin Le Grand { 228ddde725dSArmin Le Grand // no own style, use parent's 229ddde725dSArmin Le Grand if(getParent()) 230ddde725dSArmin Le Grand { 231ddde725dSArmin Le Grand return getParent()->getSvgStyleAttributes(); 232ddde725dSArmin Le Grand } 233ddde725dSArmin Le Grand else 234ddde725dSArmin Le Grand { 235ddde725dSArmin Le Grand return 0; 236ddde725dSArmin Le Grand } 237ddde725dSArmin Le Grand } 238ddde725dSArmin Le Grand createSimpleTextPrimitive(SvgTextPosition & rSvgTextPosition,const SvgStyleAttributes & rSvgStyleAttributes) const239ddde725dSArmin Le Grand drawinglayer::primitive2d::TextSimplePortionPrimitive2D* SvgCharacterNode::createSimpleTextPrimitive( 240ddde725dSArmin Le Grand SvgTextPosition& rSvgTextPosition, 241ddde725dSArmin Le Grand const SvgStyleAttributes& rSvgStyleAttributes) const 242ddde725dSArmin Le Grand { 243ddde725dSArmin Le Grand // prepare retval, index and length 244ddde725dSArmin Le Grand drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pRetval = 0; 245ddde725dSArmin Le Grand sal_uInt32 nIndex(0); 246ddde725dSArmin Le Grand sal_uInt32 nLength(getText().getLength()); 247ddde725dSArmin Le Grand 248ddde725dSArmin Le Grand if(nLength) 249ddde725dSArmin Le Grand { 250ddde725dSArmin Le Grand // prepare FontAttribute 251861dea5cSArmin Le Grand rtl::OUString aFontFamily = rSvgStyleAttributes.getFontFamily().empty() ? 252ddde725dSArmin Le Grand rtl::OUString(rtl::OUString::createFromAscii("Times New Roman")) : 253ddde725dSArmin Le Grand rSvgStyleAttributes.getFontFamily()[0]; 254861dea5cSArmin Le Grand 255861dea5cSArmin Le Grand // #122324# if the FontFamily name ends on ' embedded' it is probably a re-import 256861dea5cSArmin Le Grand // of a SVG export with fiont embedding. Remove this to make font matching work. This 257861dea5cSArmin Le Grand // is pretty safe since there should be no font family names ending on ' embedded'. 258861dea5cSArmin Le Grand // Remove again when FontEmbedding is implemented in SVG import 259861dea5cSArmin Le Grand if(aFontFamily.endsWithAsciiL(" embedded", 9)) 260861dea5cSArmin Le Grand { 261861dea5cSArmin Le Grand aFontFamily = aFontFamily.copy(0, aFontFamily.getLength() - 9); 262861dea5cSArmin Le Grand } 263861dea5cSArmin Le Grand 264ddde725dSArmin Le Grand const ::FontWeight nFontWeight(getVclFontWeight(rSvgStyleAttributes.getFontWeight())); 265ddde725dSArmin Le Grand bool bSymbol(false); 266ddde725dSArmin Le Grand bool bVertical(false); 267ddde725dSArmin Le Grand bool bItalic(FontStyle_italic == rSvgStyleAttributes.getFontStyle() || FontStyle_oblique == rSvgStyleAttributes.getFontStyle()); 268ddde725dSArmin Le Grand bool bMonospaced(false); 269ddde725dSArmin Le Grand bool bOutline(false); 270ddde725dSArmin Le Grand bool bRTL(false); 271ddde725dSArmin Le Grand bool bBiDiStrong(false); 272ddde725dSArmin Le Grand 273ddde725dSArmin Le Grand const drawinglayer::attribute::FontAttribute aFontAttribute( 274ddde725dSArmin Le Grand aFontFamily, 275ddde725dSArmin Le Grand rtl::OUString(), 276ddde725dSArmin Le Grand nFontWeight, 277ddde725dSArmin Le Grand bSymbol, 278ddde725dSArmin Le Grand bVertical, 279ddde725dSArmin Le Grand bItalic, 280ddde725dSArmin Le Grand bMonospaced, 281ddde725dSArmin Le Grand bOutline, 282ddde725dSArmin Le Grand bRTL, 283ddde725dSArmin Le Grand bBiDiStrong); 284ddde725dSArmin Le Grand 285ddde725dSArmin Le Grand // prepare FontSize 286ddde725dSArmin Le Grand double fFontWidth(rSvgStyleAttributes.getFontSize().solve(*this, length)); 287ddde725dSArmin Le Grand double fFontHeight(fFontWidth); 288ddde725dSArmin Le Grand 289ddde725dSArmin Le Grand // prepare locale 290ddde725dSArmin Le Grand ::com::sun::star::lang::Locale aLocale; 291ddde725dSArmin Le Grand 292ddde725dSArmin Le Grand // prepare TextLayouterDevice 293ddde725dSArmin Le Grand drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; 294ddde725dSArmin Le Grand aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); 295ddde725dSArmin Le Grand 296ddde725dSArmin Le Grand // prepare TextArray 297ddde725dSArmin Le Grand ::std::vector< double > aTextArray(rSvgTextPosition.getX()); 298ddde725dSArmin Le Grand 299ddde725dSArmin Le Grand if(!aTextArray.empty() && aTextArray.size() < nLength) 300ddde725dSArmin Le Grand { 301ddde725dSArmin Le Grand const sal_uInt32 nArray(aTextArray.size()); 302ddde725dSArmin Le Grand 303ddde725dSArmin Le Grand if(nArray < nLength) 304ddde725dSArmin Le Grand { 305ddde725dSArmin Le Grand double fStartX(0.0); 306ddde725dSArmin Le Grand 307ddde725dSArmin Le Grand if(rSvgTextPosition.getParent() && rSvgTextPosition.getParent()->getAbsoluteX()) 308ddde725dSArmin Le Grand { 309ddde725dSArmin Le Grand fStartX = rSvgTextPosition.getParent()->getPosition().getX(); 310ddde725dSArmin Le Grand } 311ddde725dSArmin Le Grand else 312ddde725dSArmin Le Grand { 313ddde725dSArmin Le Grand fStartX = aTextArray[nArray - 1]; 314ddde725dSArmin Le Grand } 315ddde725dSArmin Le Grand 316ddde725dSArmin Le Grand ::std::vector< double > aExtendArray(aTextLayouterDevice.getTextArray(getText(), nArray, nLength - nArray)); 317ddde725dSArmin Le Grand aTextArray.reserve(nLength); 318ddde725dSArmin Le Grand 319ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < aExtendArray.size(); a++) 320ddde725dSArmin Le Grand { 321ddde725dSArmin Le Grand aTextArray.push_back(aExtendArray[a] + fStartX); 322ddde725dSArmin Le Grand } 323ddde725dSArmin Le Grand } 324ddde725dSArmin Le Grand } 325ddde725dSArmin Le Grand 326ddde725dSArmin Le Grand // get current TextPosition and TextWidth in units 327ddde725dSArmin Le Grand basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition()); 328ddde725dSArmin Le Grand double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength)); 329ddde725dSArmin Le Grand 330ddde725dSArmin Le Grand // check for user-given TextLength 331ddde725dSArmin Le Grand if(0.0 != rSvgTextPosition.getTextLength() 332ddde725dSArmin Le Grand && !basegfx::fTools::equal(fTextWidth, rSvgTextPosition.getTextLength())) 333ddde725dSArmin Le Grand { 334ddde725dSArmin Le Grand const double fFactor(rSvgTextPosition.getTextLength() / fTextWidth); 335ddde725dSArmin Le Grand 336ddde725dSArmin Le Grand if(rSvgTextPosition.getLengthAdjust()) 337ddde725dSArmin Le Grand { 338ddde725dSArmin Le Grand // spacing, need to create and expand TextArray 339ddde725dSArmin Le Grand if(aTextArray.empty()) 340ddde725dSArmin Le Grand { 341ddde725dSArmin Le Grand aTextArray = aTextLayouterDevice.getTextArray(getText(), nIndex, nLength); 342ddde725dSArmin Le Grand } 343ddde725dSArmin Le Grand 344ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < aTextArray.size(); a++) 345ddde725dSArmin Le Grand { 346ddde725dSArmin Le Grand aTextArray[a] *= fFactor; 347ddde725dSArmin Le Grand } 348ddde725dSArmin Le Grand } 349ddde725dSArmin Le Grand else 350ddde725dSArmin Le Grand { 351ddde725dSArmin Le Grand // spacing and glyphs, just apply to FontWidth 352ddde725dSArmin Le Grand fFontWidth *= fFactor; 353ddde725dSArmin Le Grand } 354ddde725dSArmin Le Grand 355ddde725dSArmin Le Grand fTextWidth = rSvgTextPosition.getTextLength(); 356ddde725dSArmin Le Grand } 357ddde725dSArmin Le Grand 358ddde725dSArmin Le Grand // get TextAlign 359ddde725dSArmin Le Grand TextAlign aTextAlign(rSvgStyleAttributes.getTextAlign()); 360ddde725dSArmin Le Grand 361ddde725dSArmin Le Grand // map TextAnchor to TextAlign, there seems not to be a difference 362ddde725dSArmin Le Grand if(TextAnchor_notset != rSvgStyleAttributes.getTextAnchor()) 363ddde725dSArmin Le Grand { 364ddde725dSArmin Le Grand switch(rSvgStyleAttributes.getTextAnchor()) 365ddde725dSArmin Le Grand { 366ddde725dSArmin Le Grand case TextAnchor_start: 367ddde725dSArmin Le Grand { 368ddde725dSArmin Le Grand aTextAlign = TextAlign_left; 369ddde725dSArmin Le Grand break; 370ddde725dSArmin Le Grand } 371ddde725dSArmin Le Grand case TextAnchor_middle: 372ddde725dSArmin Le Grand { 373ddde725dSArmin Le Grand aTextAlign = TextAlign_center; 374ddde725dSArmin Le Grand break; 375ddde725dSArmin Le Grand } 376ddde725dSArmin Le Grand case TextAnchor_end: 377ddde725dSArmin Le Grand { 378ddde725dSArmin Le Grand aTextAlign = TextAlign_right; 379ddde725dSArmin Le Grand break; 380ddde725dSArmin Le Grand } 381e2bf1e9dSArmin Le Grand default: 382e2bf1e9dSArmin Le Grand { 383e2bf1e9dSArmin Le Grand break; 384e2bf1e9dSArmin Le Grand } 385ddde725dSArmin Le Grand } 386ddde725dSArmin Le Grand } 387ddde725dSArmin Le Grand 388ddde725dSArmin Le Grand // apply TextAlign 389ddde725dSArmin Le Grand switch(aTextAlign) 390ddde725dSArmin Le Grand { 391ddde725dSArmin Le Grand case TextAlign_right: 392ddde725dSArmin Le Grand { 393ddde725dSArmin Le Grand aPosition.setX(aPosition.getX() - fTextWidth); 394ddde725dSArmin Le Grand break; 395ddde725dSArmin Le Grand } 396ddde725dSArmin Le Grand case TextAlign_center: 397ddde725dSArmin Le Grand { 398ddde725dSArmin Le Grand aPosition.setX(aPosition.getX() - (fTextWidth * 0.5)); 399ddde725dSArmin Le Grand break; 400ddde725dSArmin Le Grand } 401ddde725dSArmin Le Grand case TextAlign_notset: 402ddde725dSArmin Le Grand case TextAlign_left: 403ddde725dSArmin Le Grand case TextAlign_justify: 404ddde725dSArmin Le Grand { 405ddde725dSArmin Le Grand // TextAlign_notset, TextAlign_left: nothing to do 406ddde725dSArmin Le Grand // TextAlign_justify is not clear currently; handle as TextAlign_left 407ddde725dSArmin Le Grand break; 408ddde725dSArmin Le Grand } 409ddde725dSArmin Le Grand } 410ddde725dSArmin Le Grand 411*86d02030SArmin Le Grand // get BaselineShift 412*86d02030SArmin Le Grand const BaselineShift aBaselineShift(rSvgStyleAttributes.getBaselineShift()); 413*86d02030SArmin Le Grand 414*86d02030SArmin Le Grand // apply BaselineShift 415*86d02030SArmin Le Grand switch(aBaselineShift) 416*86d02030SArmin Le Grand { 417*86d02030SArmin Le Grand case BaselineShift_Sub: 418*86d02030SArmin Le Grand { 419*86d02030SArmin Le Grand aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset()); 420*86d02030SArmin Le Grand break; 421*86d02030SArmin Le Grand } 422*86d02030SArmin Le Grand case BaselineShift_Super: 423*86d02030SArmin Le Grand { 424*86d02030SArmin Le Grand aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset()); 425*86d02030SArmin Le Grand break; 426*86d02030SArmin Le Grand } 427*86d02030SArmin Le Grand case BaselineShift_Percentage: 428*86d02030SArmin Le Grand case BaselineShift_Length: 429*86d02030SArmin Le Grand { 430*86d02030SArmin Le Grand const SvgNumber aNumber(rSvgStyleAttributes.getBaselineShiftNumber()); 431*86d02030SArmin Le Grand const double mfBaselineShift(aNumber.solve(*this, length)); 432*86d02030SArmin Le Grand 433*86d02030SArmin Le Grand aPosition.setY(aPosition.getY() + mfBaselineShift); 434*86d02030SArmin Le Grand break; 435*86d02030SArmin Le Grand } 436*86d02030SArmin Le Grand default: // BaselineShift_Baseline 437*86d02030SArmin Le Grand { 438*86d02030SArmin Le Grand // nothing to do 439*86d02030SArmin Le Grand break; 440*86d02030SArmin Le Grand } 441*86d02030SArmin Le Grand } 442*86d02030SArmin Le Grand 443ddde725dSArmin Le Grand // get fill color 444ddde725dSArmin Le Grand const basegfx::BColor aFill(rSvgStyleAttributes.getFill() 445ddde725dSArmin Le Grand ? *rSvgStyleAttributes.getFill() 446ddde725dSArmin Le Grand : basegfx::BColor(0.0, 0.0, 0.0)); 447ddde725dSArmin Le Grand 448ddde725dSArmin Le Grand // prepare TextTransformation 449ddde725dSArmin Le Grand basegfx::B2DHomMatrix aTextTransform; 450ddde725dSArmin Le Grand 451ddde725dSArmin Le Grand aTextTransform.scale(fFontWidth, fFontHeight); 452ddde725dSArmin Le Grand aTextTransform.translate(aPosition.getX(), aPosition.getY()); 453ddde725dSArmin Le Grand 454ddde725dSArmin Le Grand // check TextDecoration and if TextDecoratedPortionPrimitive2D is needed 455ddde725dSArmin Le Grand const TextDecoration aDeco(rSvgStyleAttributes.getTextDecoration()); 456ddde725dSArmin Le Grand 457ddde725dSArmin Le Grand if(TextDecoration_underline == aDeco 458ddde725dSArmin Le Grand || TextDecoration_overline == aDeco 459ddde725dSArmin Le Grand || TextDecoration_line_through == aDeco) 460ddde725dSArmin Le Grand { 461ddde725dSArmin Le Grand // get the fill for decroation as described by SVG. We cannot 462ddde725dSArmin Le Grand // have different stroke colors/definitions for those, though 463ddde725dSArmin Le Grand const SvgStyleAttributes* pDecoDef = rSvgStyleAttributes.getTextDecorationDefiningSvgStyleAttributes(); 464ddde725dSArmin Le Grand const basegfx::BColor aDecoColor(pDecoDef && pDecoDef->getFill() ? *pDecoDef->getFill() : aFill); 465ddde725dSArmin Le Grand 466ddde725dSArmin Le Grand // create decorated text primitive 467ddde725dSArmin Le Grand pRetval = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( 468ddde725dSArmin Le Grand aTextTransform, 469ddde725dSArmin Le Grand getText(), 470ddde725dSArmin Le Grand nIndex, 471ddde725dSArmin Le Grand nLength, 472ddde725dSArmin Le Grand aTextArray, 473ddde725dSArmin Le Grand aFontAttribute, 474ddde725dSArmin Le Grand aLocale, 475ddde725dSArmin Le Grand aFill, 476ddde725dSArmin Le Grand 477ddde725dSArmin Le Grand // extra props for decorated 478ddde725dSArmin Le Grand aDecoColor, 479ddde725dSArmin Le Grand aDecoColor, 480ddde725dSArmin Le Grand TextDecoration_overline == aDeco ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, 481ddde725dSArmin Le Grand TextDecoration_underline == aDeco ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, 482ddde725dSArmin Le Grand false, 483ddde725dSArmin Le Grand TextDecoration_line_through == aDeco ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE, 484ddde725dSArmin Le Grand false, 485ddde725dSArmin Le Grand drawinglayer::primitive2d::TEXT_EMPHASISMARK_NONE, 486ddde725dSArmin Le Grand true, 487ddde725dSArmin Le Grand false, 488ddde725dSArmin Le Grand drawinglayer::primitive2d::TEXT_RELIEF_NONE, 489ddde725dSArmin Le Grand false); 490ddde725dSArmin Le Grand } 491ddde725dSArmin Le Grand else 492ddde725dSArmin Le Grand { 493ddde725dSArmin Le Grand // create text primitive 494ddde725dSArmin Le Grand pRetval = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( 495ddde725dSArmin Le Grand aTextTransform, 496ddde725dSArmin Le Grand getText(), 497ddde725dSArmin Le Grand nIndex, 498ddde725dSArmin Le Grand nLength, 499ddde725dSArmin Le Grand aTextArray, 500ddde725dSArmin Le Grand aFontAttribute, 501ddde725dSArmin Le Grand aLocale, 502ddde725dSArmin Le Grand aFill); 503ddde725dSArmin Le Grand } 504ddde725dSArmin Le Grand 505ddde725dSArmin Le Grand // advance current TextPosition 506ddde725dSArmin Le Grand rSvgTextPosition.setPosition(rSvgTextPosition.getPosition() + basegfx::B2DVector(fTextWidth, 0.0)); 507ddde725dSArmin Le Grand } 508ddde725dSArmin Le Grand 509ddde725dSArmin Le Grand return pRetval; 510ddde725dSArmin Le Grand } 511ddde725dSArmin Le Grand decomposeTextWithStyle(drawinglayer::primitive2d::Primitive2DSequence & rTarget,SvgTextPosition & rSvgTextPosition,const SvgStyleAttributes & rSvgStyleAttributes) const512ddde725dSArmin Le Grand void SvgCharacterNode::decomposeTextWithStyle( 513ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 514ddde725dSArmin Le Grand SvgTextPosition& rSvgTextPosition, 515ddde725dSArmin Le Grand const SvgStyleAttributes& rSvgStyleAttributes) const 516ddde725dSArmin Le Grand { 517ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 518ddde725dSArmin Le Grand createSimpleTextPrimitive( 519ddde725dSArmin Le Grand rSvgTextPosition, 520ddde725dSArmin Le Grand rSvgStyleAttributes)); 521ddde725dSArmin Le Grand 522ddde725dSArmin Le Grand if(xRef.is()) 523ddde725dSArmin Le Grand { 524ddde725dSArmin Le Grand if(!rSvgTextPosition.isRotated()) 525ddde725dSArmin Le Grand { 526ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); 527ddde725dSArmin Le Grand } 528ddde725dSArmin Le Grand else 529ddde725dSArmin Le Grand { 530ddde725dSArmin Le Grand // need to apply rotations to each character as given 531693be7f6SArmin Le Grand const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pCandidate = 532693be7f6SArmin Le Grand dynamic_cast< const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* >(xRef.get()); 533ddde725dSArmin Le Grand 534693be7f6SArmin Le Grand if(pCandidate) 535ddde725dSArmin Le Grand { 536693be7f6SArmin Le Grand const localTextBreakupHelper alocalTextBreakupHelper(*pCandidate, rSvgTextPosition); 537693be7f6SArmin Le Grand const drawinglayer::primitive2d::Primitive2DSequence aResult( 538693be7f6SArmin Le Grand alocalTextBreakupHelper.getResult(drawinglayer::primitive2d::BreakupUnit_character)); 539693be7f6SArmin Le Grand 540693be7f6SArmin Le Grand if(aResult.hasElements()) 541693be7f6SArmin Le Grand { 542693be7f6SArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aResult); 543693be7f6SArmin Le Grand } 544ddde725dSArmin Le Grand 545693be7f6SArmin Le Grand // also consume for the implied single space 546693be7f6SArmin Le Grand rSvgTextPosition.consumeRotation(); 547693be7f6SArmin Le Grand } 548693be7f6SArmin Le Grand else 549693be7f6SArmin Le Grand { 550693be7f6SArmin Le Grand OSL_ENSURE(false, "Used primitive is not a text primitive (!)"); 551693be7f6SArmin Le Grand } 552ddde725dSArmin Le Grand } 553ddde725dSArmin Le Grand } 554ddde725dSArmin Le Grand } 555ddde725dSArmin Le Grand whiteSpaceHandling()556ddde725dSArmin Le Grand void SvgCharacterNode::whiteSpaceHandling() 557ddde725dSArmin Le Grand { 558ddde725dSArmin Le Grand if(XmlSpace_default == getXmlSpace()) 559ddde725dSArmin Le Grand { 560ddde725dSArmin Le Grand maText = whiteSpaceHandlingDefault(maText); 561ddde725dSArmin Le Grand } 562ddde725dSArmin Le Grand else 563ddde725dSArmin Le Grand { 564ddde725dSArmin Le Grand maText = whiteSpaceHandlingPreserve(maText); 565ddde725dSArmin Le Grand } 566ddde725dSArmin Le Grand } 567ddde725dSArmin Le Grand addGap()568ddde725dSArmin Le Grand void SvgCharacterNode::addGap() 569ddde725dSArmin Le Grand { 570ddde725dSArmin Le Grand maText += rtl::OUString(sal_Unicode(' ')); 571ddde725dSArmin Le Grand } 572ddde725dSArmin Le Grand concatenate(const rtl::OUString & rText)573ddde725dSArmin Le Grand void SvgCharacterNode::concatenate(const rtl::OUString& rText) 574ddde725dSArmin Le Grand { 575ddde725dSArmin Le Grand maText += rText; 576ddde725dSArmin Le Grand } 577ddde725dSArmin Le Grand decomposeText(drawinglayer::primitive2d::Primitive2DSequence & rTarget,SvgTextPosition & rSvgTextPosition) const578ddde725dSArmin Le Grand void SvgCharacterNode::decomposeText(drawinglayer::primitive2d::Primitive2DSequence& rTarget, SvgTextPosition& rSvgTextPosition) const 579ddde725dSArmin Le Grand { 580ddde725dSArmin Le Grand if(getText().getLength()) 581ddde725dSArmin Le Grand { 582ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getSvgStyleAttributes(); 583ddde725dSArmin Le Grand 584ddde725dSArmin Le Grand if(pSvgStyleAttributes) 585ddde725dSArmin Le Grand { 586ddde725dSArmin Le Grand decomposeTextWithStyle(rTarget, rSvgTextPosition, *pSvgStyleAttributes); 587ddde725dSArmin Le Grand } 588ddde725dSArmin Le Grand } 589ddde725dSArmin Le Grand } 590ddde725dSArmin Le Grand 591ddde725dSArmin Le Grand } // end of namespace svgreader 592ddde725dSArmin Le Grand } // end of namespace svgio 593ddde725dSArmin Le Grand 594ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 595ddde725dSArmin Le Grand 596ddde725dSArmin Le Grand namespace svgio 597ddde725dSArmin Le Grand { 598ddde725dSArmin Le Grand namespace svgreader 599ddde725dSArmin Le Grand { SvgTextPosition(SvgTextPosition * pParent,const InfoProvider & rInfoProvider,const SvgTextPositions & rSvgTextPositions)600ddde725dSArmin Le Grand SvgTextPosition::SvgTextPosition( 601ddde725dSArmin Le Grand SvgTextPosition* pParent, 602ddde725dSArmin Le Grand const InfoProvider& rInfoProvider, 603ddde725dSArmin Le Grand const SvgTextPositions& rSvgTextPositions) 604ddde725dSArmin Le Grand : mpParent(pParent), 605ddde725dSArmin Le Grand maX(), // computed below 606ddde725dSArmin Le Grand maY(), // computed below 607ddde725dSArmin Le Grand maRotate(solveSvgNumberVector(rSvgTextPositions.getRotate(), rInfoProvider, length)), 608ddde725dSArmin Le Grand mfTextLength(0.0), 609ddde725dSArmin Le Grand maPosition(), // computed below 610ddde725dSArmin Le Grand mnRotationIndex(0), 611ddde725dSArmin Le Grand mbLengthAdjust(rSvgTextPositions.getLengthAdjust()), 612ddde725dSArmin Le Grand mbAbsoluteX(false), 613ddde725dSArmin Le Grand mbAbsoluteY(false) 614ddde725dSArmin Le Grand { 615ddde725dSArmin Le Grand // get TextLength if provided 616ddde725dSArmin Le Grand if(rSvgTextPositions.getTextLength().isSet()) 617ddde725dSArmin Le Grand { 618ddde725dSArmin Le Grand mfTextLength = rSvgTextPositions.getTextLength().solve(rInfoProvider, length); 619ddde725dSArmin Le Grand } 620ddde725dSArmin Le Grand 621ddde725dSArmin Le Grand // SVG does not really define in which units a �rotate� for Text/TSpan is given, 622ddde725dSArmin Le Grand // but it seems to be degrees. Convert here to radians 623ddde725dSArmin Le Grand if(!maRotate.empty()) 624ddde725dSArmin Le Grand { 625ddde725dSArmin Le Grand const double fFactor(F_PI / 180.0); 626ddde725dSArmin Le Grand 627ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < maRotate.size(); a++) 628ddde725dSArmin Le Grand { 629ddde725dSArmin Le Grand maRotate[a] *= fFactor; 630ddde725dSArmin Le Grand } 631ddde725dSArmin Le Grand } 632ddde725dSArmin Le Grand 633ddde725dSArmin Le Grand // get text positions X 634ddde725dSArmin Le Grand const sal_uInt32 nSizeX(rSvgTextPositions.getX().size()); 635ddde725dSArmin Le Grand 636ddde725dSArmin Le Grand if(nSizeX) 637ddde725dSArmin Le Grand { 638ddde725dSArmin Le Grand // we have absolute positions, get first one as current text position X 639ddde725dSArmin Le Grand maPosition.setX(rSvgTextPositions.getX()[0].solve(rInfoProvider, xcoordinate)); 640ddde725dSArmin Le Grand mbAbsoluteX = true; 641ddde725dSArmin Le Grand 642ddde725dSArmin Le Grand if(nSizeX > 1) 643ddde725dSArmin Le Grand { 644ddde725dSArmin Le Grand // fill deltas to maX 645ddde725dSArmin Le Grand maX.reserve(nSizeX); 646ddde725dSArmin Le Grand 647ddde725dSArmin Le Grand for(sal_uInt32 a(1); a < nSizeX; a++) 648ddde725dSArmin Le Grand { 649ddde725dSArmin Le Grand maX.push_back(rSvgTextPositions.getX()[a].solve(rInfoProvider, xcoordinate) - maPosition.getX()); 650ddde725dSArmin Le Grand } 651ddde725dSArmin Le Grand } 652ddde725dSArmin Le Grand } 653ddde725dSArmin Le Grand else 654ddde725dSArmin Le Grand { 655ddde725dSArmin Le Grand // no absolute position, get from parent 656ddde725dSArmin Le Grand if(pParent) 657ddde725dSArmin Le Grand { 658ddde725dSArmin Le Grand maPosition.setX(pParent->getPosition().getX()); 659ddde725dSArmin Le Grand } 660ddde725dSArmin Le Grand 661ddde725dSArmin Le Grand const sal_uInt32 nSizeDx(rSvgTextPositions.getDx().size()); 662ddde725dSArmin Le Grand 663ddde725dSArmin Le Grand if(nSizeDx) 664ddde725dSArmin Le Grand { 665ddde725dSArmin Le Grand // relative positions given, translate position derived from parent 666ddde725dSArmin Le Grand maPosition.setX(maPosition.getX() + rSvgTextPositions.getDx()[0].solve(rInfoProvider, xcoordinate)); 667ddde725dSArmin Le Grand 668ddde725dSArmin Le Grand if(nSizeDx > 1) 669ddde725dSArmin Le Grand { 670ddde725dSArmin Le Grand // fill deltas to maX 671ddde725dSArmin Le Grand maX.reserve(nSizeDx); 672ddde725dSArmin Le Grand 673ddde725dSArmin Le Grand for(sal_uInt32 a(1); a < nSizeDx; a++) 674ddde725dSArmin Le Grand { 675ddde725dSArmin Le Grand maX.push_back(rSvgTextPositions.getDx()[a].solve(rInfoProvider, xcoordinate)); 676ddde725dSArmin Le Grand } 677ddde725dSArmin Le Grand } 678ddde725dSArmin Le Grand } 679ddde725dSArmin Le Grand } 680ddde725dSArmin Le Grand 681ddde725dSArmin Le Grand // get text positions Y 682ddde725dSArmin Le Grand const sal_uInt32 nSizeY(rSvgTextPositions.getY().size()); 683ddde725dSArmin Le Grand 684ddde725dSArmin Le Grand if(nSizeY) 685ddde725dSArmin Le Grand { 686ddde725dSArmin Le Grand // we have absolute positions, get first one as current text position Y 687ddde725dSArmin Le Grand maPosition.setY(rSvgTextPositions.getY()[0].solve(rInfoProvider, ycoordinate)); 688ddde725dSArmin Le Grand mbAbsoluteX = true; 689ddde725dSArmin Le Grand 690ddde725dSArmin Le Grand if(nSizeY > 1) 691ddde725dSArmin Le Grand { 692ddde725dSArmin Le Grand // fill deltas to maY 693ddde725dSArmin Le Grand maY.reserve(nSizeY); 694ddde725dSArmin Le Grand 695ddde725dSArmin Le Grand for(sal_uInt32 a(1); a < nSizeY; a++) 696ddde725dSArmin Le Grand { 697ddde725dSArmin Le Grand maY.push_back(rSvgTextPositions.getY()[a].solve(rInfoProvider, ycoordinate) - maPosition.getY()); 698ddde725dSArmin Le Grand } 699ddde725dSArmin Le Grand } 700ddde725dSArmin Le Grand } 701ddde725dSArmin Le Grand else 702ddde725dSArmin Le Grand { 703ddde725dSArmin Le Grand // no absolute position, get from parent 704ddde725dSArmin Le Grand if(pParent) 705ddde725dSArmin Le Grand { 706ddde725dSArmin Le Grand maPosition.setY(pParent->getPosition().getY()); 707ddde725dSArmin Le Grand } 708ddde725dSArmin Le Grand 709ddde725dSArmin Le Grand const sal_uInt32 nSizeDy(rSvgTextPositions.getDy().size()); 710ddde725dSArmin Le Grand 711ddde725dSArmin Le Grand if(nSizeDy) 712ddde725dSArmin Le Grand { 713ddde725dSArmin Le Grand // relative positions given, translate position derived from parent 714ddde725dSArmin Le Grand maPosition.setY(maPosition.getY() + rSvgTextPositions.getDy()[0].solve(rInfoProvider, ycoordinate)); 715ddde725dSArmin Le Grand 716ddde725dSArmin Le Grand if(nSizeDy > 1) 717ddde725dSArmin Le Grand { 718ddde725dSArmin Le Grand // fill deltas to maY 719ddde725dSArmin Le Grand maY.reserve(nSizeDy); 720ddde725dSArmin Le Grand 721ddde725dSArmin Le Grand for(sal_uInt32 a(1); a < nSizeDy; a++) 722ddde725dSArmin Le Grand { 723ddde725dSArmin Le Grand maY.push_back(rSvgTextPositions.getDy()[a].solve(rInfoProvider, ycoordinate)); 724ddde725dSArmin Le Grand } 725ddde725dSArmin Le Grand } 726ddde725dSArmin Le Grand } 727ddde725dSArmin Le Grand } 728ddde725dSArmin Le Grand } 729ddde725dSArmin Le Grand isRotated() const730ddde725dSArmin Le Grand bool SvgTextPosition::isRotated() const 731ddde725dSArmin Le Grand { 732ddde725dSArmin Le Grand if(maRotate.empty()) 733ddde725dSArmin Le Grand { 734ddde725dSArmin Le Grand if(getParent()) 735ddde725dSArmin Le Grand { 736ddde725dSArmin Le Grand return getParent()->isRotated(); 737ddde725dSArmin Le Grand } 738ddde725dSArmin Le Grand else 739ddde725dSArmin Le Grand { 740ddde725dSArmin Le Grand return false; 741ddde725dSArmin Le Grand } 742ddde725dSArmin Le Grand } 743ddde725dSArmin Le Grand else 744ddde725dSArmin Le Grand { 745ddde725dSArmin Le Grand return true; 746ddde725dSArmin Le Grand } 747ddde725dSArmin Le Grand } 748ddde725dSArmin Le Grand consumeRotation()749ddde725dSArmin Le Grand double SvgTextPosition::consumeRotation() 750ddde725dSArmin Le Grand { 751ddde725dSArmin Le Grand double fRetval(0.0); 752ddde725dSArmin Le Grand 753ddde725dSArmin Le Grand if(maRotate.empty()) 754ddde725dSArmin Le Grand { 755ddde725dSArmin Le Grand if(getParent()) 756ddde725dSArmin Le Grand { 757ddde725dSArmin Le Grand fRetval = mpParent->consumeRotation(); 758ddde725dSArmin Le Grand } 759ddde725dSArmin Le Grand else 760ddde725dSArmin Le Grand { 761ddde725dSArmin Le Grand fRetval = 0.0; 762ddde725dSArmin Le Grand } 763ddde725dSArmin Le Grand } 764ddde725dSArmin Le Grand else 765ddde725dSArmin Le Grand { 766ddde725dSArmin Le Grand const sal_uInt32 nSize(maRotate.size()); 767ddde725dSArmin Le Grand 768ddde725dSArmin Le Grand if(mnRotationIndex < nSize) 769ddde725dSArmin Le Grand { 770ddde725dSArmin Le Grand fRetval = maRotate[mnRotationIndex++]; 771ddde725dSArmin Le Grand } 772ddde725dSArmin Le Grand else 773ddde725dSArmin Le Grand { 774ddde725dSArmin Le Grand fRetval = maRotate[nSize - 1]; 775ddde725dSArmin Le Grand } 776ddde725dSArmin Le Grand } 777ddde725dSArmin Le Grand 778ddde725dSArmin Le Grand return fRetval; 779ddde725dSArmin Le Grand } 780ddde725dSArmin Le Grand 781ddde725dSArmin Le Grand } // end of namespace svgreader 782ddde725dSArmin Le Grand } // end of namespace svgio 783ddde725dSArmin Le Grand 784ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 785ddde725dSArmin Le Grand // eof 786