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

Generated by: LCOV version 1.10