LCOV - code coverage report
Current view: top level - libreoffice/svgio/source/svgreader - svgcharacternode.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 241 0.0 %
Date: 2012-12-27 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10