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

Generated by: LCOV version 1.10