LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - textdecoratedprimitive2d.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 173 204 84.8 %
Date: 2012-08-25 Functions: 7 8 87.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 227 430 52.8 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
      30                 :            : #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
      31                 :            : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
      32                 :            : #include <drawinglayer/attribute/strokeattribute.hxx>
      33                 :            : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      34                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      35                 :            : #include <comphelper/processfactory.hxx>
      36                 :            : #include <com/sun/star/i18n/WordType.hpp>
      37                 :            : #include <drawinglayer/primitive2d/texteffectprimitive2d.hxx>
      38                 :            : #include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
      39                 :            : #include <com/sun/star/i18n/XBreakIterator.hpp>
      40                 :            : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
      41                 :            : #include <drawinglayer/primitive2d/textlineprimitive2d.hxx>
      42                 :            : #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx>
      43                 :            : 
      44                 :            : //////////////////////////////////////////////////////////////////////////////
      45                 :            : 
      46                 :            : namespace drawinglayer
      47                 :            : {
      48                 :            :     namespace primitive2d
      49                 :            :     {
      50                 :       2662 :         void TextDecoratedPortionPrimitive2D::impCreateGeometryContent(
      51                 :            :             std::vector< Primitive2DReference >& rTarget,
      52                 :            :             basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rDecTrans,
      53                 :            :             const String& rText,
      54                 :            :             xub_StrLen aTextPosition,
      55                 :            :             xub_StrLen aTextLength,
      56                 :            :             const ::std::vector< double >& rDXArray,
      57                 :            :             const attribute::FontAttribute& rFontAttribute) const
      58                 :            :         {
      59                 :            :             // create the SimpleTextPrimitive needed in any case
      60                 :            :             rTarget.push_back(Primitive2DReference(
      61                 :            :                 new TextSimplePortionPrimitive2D(
      62                 :            :                     rDecTrans.getB2DHomMatrix(),
      63                 :            :                     rText,
      64                 :            :                     aTextPosition,
      65                 :            :                     aTextLength,
      66                 :            :                     rDXArray,
      67                 :            :                     rFontAttribute,
      68                 :       2662 :                     getLocale(),
      69 [ +  - ][ +  - ]:       2662 :                     getFontColor())));
                 [ +  - ]
      70                 :            : 
      71                 :            :             // see if something else needs to be done
      72                 :       2662 :             const bool bOverlineUsed(TEXT_LINE_NONE != getFontOverline());
      73                 :       2662 :             const bool bUnderlineUsed(TEXT_LINE_NONE != getFontUnderline());
      74                 :       2662 :             const bool bStrikeoutUsed(TEXT_STRIKEOUT_NONE != getTextStrikeout());
      75                 :            : 
      76 [ +  + ][ +  + ]:       2662 :             if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed)
                 [ +  + ]
      77                 :            :             {
      78                 :            :                 // common preparations
      79         [ +  - ]:       2644 :                 TextLayouterDevice aTextLayouter;
      80                 :            : 
      81                 :            :                 // TextLayouterDevice is needed to get metrics for text decorations like
      82                 :            :                 // underline/strikeout/emphasis marks from it. For setup, the font size is needed
      83                 :            :                 aTextLayouter.setFontAttribute(
      84                 :       2644 :                     getFontAttribute(),
      85         [ +  - ]:       2644 :                     rDecTrans.getScale().getX(),
      86         [ +  - ]:       2644 :                     rDecTrans.getScale().getY(),
      87         [ +  - ]:      10576 :                     getLocale());
      88                 :            : 
      89                 :            :                 // get text width
      90                 :       2644 :                 double fTextWidth(0.0);
      91                 :            : 
      92         [ -  + ]:       2644 :                 if(rDXArray.empty())
      93                 :            :                 {
      94         [ #  # ]:          0 :                     fTextWidth = aTextLayouter.getTextWidth(rText, aTextPosition, aTextLength);
      95                 :            :                 }
      96                 :            :                 else
      97                 :            :                 {
      98 [ +  - ][ +  - ]:       2644 :                     fTextWidth = rDXArray.back() * rDecTrans.getScale().getX();
      99         [ +  - ]:       2644 :                     const double fFontScaleX(rDecTrans.getScale().getX());
     100                 :            : 
     101 [ +  - ][ +  - ]:       5288 :                     if(!basegfx::fTools::equal(fFontScaleX, 1.0)
           [ +  -  +  - ]
     102                 :       2644 :                         && !basegfx::fTools::equalZero(fFontScaleX))
     103                 :            :                     {
     104                 :            :                         // need to take FontScaling out of the DXArray
     105                 :       2644 :                         fTextWidth /= fFontScaleX;
     106                 :            :                     }
     107                 :            :                 }
     108                 :            : 
     109         [ +  + ]:       2644 :                 if(bOverlineUsed)
     110                 :            :                 {
     111                 :            :                     // create primitive geometry for overline
     112                 :            :                     rTarget.push_back(Primitive2DReference(
     113                 :            :                         new TextLinePrimitive2D(
     114                 :            :                             rDecTrans.getB2DHomMatrix(),
     115                 :            :                             fTextWidth,
     116                 :            :                             aTextLayouter.getOverlineOffset(),
     117                 :            :                             aTextLayouter.getOverlineHeight(),
     118                 :            :                             getFontOverline(),
     119 [ +  - ][ +  - ]:       1790 :                             getOverlineColor())));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     120                 :            :                 }
     121                 :            : 
     122         [ +  + ]:       2644 :                 if(bUnderlineUsed)
     123                 :            :                 {
     124                 :            :                     // create primitive geometry for underline
     125                 :            :                     rTarget.push_back(Primitive2DReference(
     126                 :            :                         new TextLinePrimitive2D(
     127                 :            :                             rDecTrans.getB2DHomMatrix(),
     128                 :            :                             fTextWidth,
     129                 :            :                             aTextLayouter.getUnderlineOffset(),
     130                 :            :                             aTextLayouter.getUnderlineHeight(),
     131                 :            :                             getFontUnderline(),
     132 [ +  - ][ +  - ]:       2428 :                             getTextlineColor())));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     133                 :            :                 }
     134                 :            : 
     135         [ +  + ]:       2644 :                 if(bStrikeoutUsed)
     136                 :            :                 {
     137                 :            :                     // create primitive geometry for strikeout
     138 [ +  + ][ -  + ]:       1247 :                     if(TEXT_STRIKEOUT_SLASH == getTextStrikeout() || TEXT_STRIKEOUT_X == getTextStrikeout())
                 [ +  + ]
     139                 :            :                     {
     140                 :            :                         // strikeout with character
     141         [ +  - ]:         72 :                         const sal_Unicode aStrikeoutChar(TEXT_STRIKEOUT_SLASH == getTextStrikeout() ? '/' : 'X');
     142                 :            : 
     143                 :            :                         rTarget.push_back(Primitive2DReference(
     144                 :            :                             new TextCharacterStrikeoutPrimitive2D(
     145                 :            :                                 rDecTrans.getB2DHomMatrix(),
     146                 :            :                                 fTextWidth,
     147                 :         72 :                                 getFontColor(),
     148                 :            :                                 aStrikeoutChar,
     149                 :         72 :                                 getFontAttribute(),
     150 [ +  - ][ +  - ]:         72 :                                 getLocale())));
         [ +  - ][ +  - ]
     151                 :            :                     }
     152                 :            :                     else
     153                 :            :                     {
     154                 :            :                         // strikeout with geometry
     155                 :            :                         rTarget.push_back(Primitive2DReference(
     156                 :            :                             new TextGeometryStrikeoutPrimitive2D(
     157                 :            :                                 rDecTrans.getB2DHomMatrix(),
     158                 :            :                                 fTextWidth,
     159                 :       1175 :                                 getFontColor(),
     160                 :            :                                 aTextLayouter.getUnderlineHeight(),
     161                 :            :                                 aTextLayouter.getStrikeoutOffset(),
     162 [ +  - ][ +  - ]:       1175 :                                 getTextStrikeout())));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     163                 :            :                     }
     164         [ +  - ]:       2644 :                 }
     165                 :            :             }
     166                 :            : 
     167                 :            :             // TODO: Handle Font Emphasis Above/Below
     168                 :       2662 :         }
     169                 :            : 
     170                 :       1619 :         void TextDecoratedPortionPrimitive2D::impCorrectTextBoundary(::com::sun::star::i18n::Boundary& rNextWordBoundary) const
     171                 :            :         {
     172                 :            :             // truncate aNextWordBoundary to min/max possible values. This is necessary since the word start may be
     173                 :            :             // before/after getTextPosition() when a long string is the content and getTextPosition()
     174                 :            :             // is right inside a word. Same for end.
     175                 :       1619 :             const sal_Int32 aMinPos(static_cast< sal_Int32 >(getTextPosition()));
     176                 :       1619 :             const sal_Int32 aMaxPos(aMinPos + static_cast< sal_Int32 >(getTextLength()));
     177                 :            : 
     178         [ +  + ]:       1619 :             if(rNextWordBoundary.startPos < aMinPos)
     179                 :            :             {
     180                 :        316 :                 rNextWordBoundary.startPos = aMinPos;
     181                 :            :             }
     182         [ -  + ]:       1303 :             else if(rNextWordBoundary.startPos > aMaxPos)
     183                 :            :             {
     184                 :          0 :                 rNextWordBoundary.startPos = aMaxPos;
     185                 :            :             }
     186                 :            : 
     187         [ -  + ]:       1619 :             if(rNextWordBoundary.endPos < aMinPos)
     188                 :            :             {
     189                 :          0 :                 rNextWordBoundary.endPos = aMinPos;
     190                 :            :             }
     191         [ +  + ]:       1619 :             else if(rNextWordBoundary.endPos > aMaxPos)
     192                 :            :             {
     193                 :        384 :                 rNextWordBoundary.endPos = aMaxPos;
     194                 :            :             }
     195                 :       1619 :         }
     196                 :            : 
     197                 :        907 :         void TextDecoratedPortionPrimitive2D::impSplitSingleWords(
     198                 :            :             std::vector< Primitive2DReference >& rTarget,
     199                 :            :             basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rDecTrans) const
     200                 :            :         {
     201                 :            :             // break iterator support
     202                 :            :             // made static so it only needs to be fetched once, even with many single
     203                 :            :             // constructed VclMetafileProcessor2D. It's still incarnated on demand,
     204                 :            :             // but exists for OOo runtime now by purpose.
     205 [ +  + ][ +  - ]:        907 :             static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xLocalBreakIterator;
     206                 :            : 
     207         [ +  + ]:        907 :             if(!xLocalBreakIterator.is())
     208                 :            :             {
     209         [ +  - ]:          4 :                 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
     210 [ +  - ][ +  - ]:          4 :                 xLocalBreakIterator.set(xMSF->createInstance("com.sun.star.i18n.BreakIterator"), ::com::sun::star::uno::UNO_QUERY);
                 [ +  - ]
     211                 :            :             }
     212                 :            : 
     213 [ +  - ][ +  - ]:        907 :             if(xLocalBreakIterator.is() && getTextLength())
                 [ +  - ]
     214                 :            :             {
     215                 :            :                 // init word iterator, get first word and truncate to possibilities
     216         [ +  - ]:        907 :                 ::com::sun::star::i18n::Boundary aNextWordBoundary(xLocalBreakIterator->getWordBoundary(
     217 [ +  - ][ +  - ]:        907 :                     getText(), getTextPosition(), getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True));
     218                 :            : 
     219         [ -  + ]:        907 :                 if(aNextWordBoundary.endPos == getTextPosition())
     220                 :            :                 {
     221                 :            :                     // backward hit, force next word
     222         [ #  # ]:          0 :                     aNextWordBoundary = xLocalBreakIterator->getWordBoundary(
     223 [ #  # ][ #  # ]:          0 :                         getText(), getTextPosition() + 1, getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True);
     224                 :            :                 }
     225                 :            : 
     226         [ +  - ]:        907 :                 impCorrectTextBoundary(aNextWordBoundary);
     227                 :            : 
     228                 :            :                 // prepare new font attributes WITHOUT outline
     229                 :            :                 const attribute::FontAttribute aNewFontAttribute(
     230         [ +  - ]:        907 :                     getFontAttribute().getFamilyName(),
     231         [ +  - ]:        907 :                     getFontAttribute().getStyleName(),
     232         [ +  - ]:        907 :                     getFontAttribute().getWeight(),
     233         [ +  - ]:        907 :                     getFontAttribute().getSymbol(),
     234         [ +  - ]:        907 :                     getFontAttribute().getVertical(),
     235         [ +  - ]:        907 :                     getFontAttribute().getItalic(),
     236         [ +  - ]:        907 :                     getFontAttribute().getMonospaced(),
     237                 :            :                     false,             // no outline anymore, handled locally
     238         [ +  - ]:        907 :                     getFontAttribute().getRTL(),
     239 [ +  - ][ +  - ]:       1814 :                     getFontAttribute().getBiDiStrong());
     240                 :            : 
     241 [ +  - ][ +  + ]:        907 :                 if(aNextWordBoundary.startPos == getTextPosition() && aNextWordBoundary.endPos == getTextLength())
                 [ +  + ]
     242                 :            :                 {
     243                 :            :                     // it IS only a single word, handle as one word
     244         [ +  - ]:        321 :                     impCreateGeometryContent(rTarget, rDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute);
     245                 :            :                 }
     246                 :            :                 else
     247                 :            :                 {
     248                 :            :                     // prepare TextLayouter
     249                 :        586 :                     const bool bNoDXArray(getDXArray().empty());
     250         [ +  - ]:        586 :                     TextLayouterDevice aTextLayouter;
     251                 :            : 
     252         [ -  + ]:        586 :                     if(bNoDXArray)
     253                 :            :                     {
     254                 :            :                         // ..but only completely when no DXArray
     255                 :            :                         aTextLayouter.setFontAttribute(
     256                 :          0 :                             getFontAttribute(),
     257         [ #  # ]:          0 :                             rDecTrans.getScale().getX(),
     258         [ #  # ]:          0 :                             rDecTrans.getScale().getY(),
     259         [ #  # ]:          0 :                             getLocale());
     260                 :            :                     }
     261                 :            : 
     262                 :            :                     // do iterate over single words
     263         [ +  + ]:       1816 :                     while(aNextWordBoundary.startPos != aNextWordBoundary.endPos)
     264                 :            :                     {
     265                 :            :                         // prepare values for new portion
     266                 :       1230 :                         const xub_StrLen nNewTextStart(static_cast< xub_StrLen >(aNextWordBoundary.startPos));
     267                 :       1230 :                         const xub_StrLen nNewTextEnd(static_cast< xub_StrLen >(aNextWordBoundary.endPos));
     268                 :            : 
     269                 :            :                         // prepare transform for the single word
     270         [ +  - ]:       1230 :                         basegfx::B2DHomMatrix aNewTransform;
     271         [ +  - ]:       1230 :                         ::std::vector< double > aNewDXArray;
     272                 :       1230 :                         const bool bNewStartIsNotOldStart(nNewTextStart > getTextPosition());
     273                 :            : 
     274         [ +  - ]:       1230 :                         if(!bNoDXArray)
     275                 :            :                         {
     276                 :            :                             // prepare new DXArray for the single word
     277                 :            :                             aNewDXArray = ::std::vector< double >(
     278                 :       1230 :                                 getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextStart - getTextPosition()),
     279   [ +  -  +  - ]:       2460 :                                 getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextEnd - getTextPosition()));
                 [ +  - ]
     280                 :            :                         }
     281                 :            : 
     282         [ +  + ]:       1230 :                         if(bNewStartIsNotOldStart)
     283                 :            :                         {
     284                 :            :                             // needs to be moved to a new start position
     285                 :        644 :                             double fOffset(0.0);
     286                 :            : 
     287         [ -  + ]:        644 :                             if(bNoDXArray)
     288                 :            :                             {
     289                 :            :                                 // evaluate using TextLayouter
     290         [ #  # ]:          0 :                                 fOffset = aTextLayouter.getTextWidth(getText(), getTextPosition(), nNewTextStart);
     291                 :            :                             }
     292                 :            :                             else
     293                 :            :                             {
     294                 :            :                                 // get from DXArray
     295                 :        644 :                                 const sal_uInt32 nIndex(static_cast< sal_uInt32 >(nNewTextStart - getTextPosition()));
     296         [ +  - ]:        644 :                                 fOffset = getDXArray()[nIndex - 1];
     297                 :            :                             }
     298                 :            : 
     299                 :            :                             // need offset without FontScale for building the new transformation. The
     300                 :            :                             // new transformation will be multiplied with the current text transformation
     301                 :            :                             // so FontScale would be double
     302                 :        644 :                             double fOffsetNoScale(fOffset);
     303         [ +  - ]:        644 :                             const double fFontScaleX(rDecTrans.getScale().getX());
     304                 :            : 
     305 [ +  - ][ +  - ]:       1288 :                             if(!basegfx::fTools::equal(fFontScaleX, 1.0)
           [ +  -  +  - ]
     306                 :        644 :                                 && !basegfx::fTools::equalZero(fFontScaleX))
     307                 :            :                             {
     308                 :        644 :                                 fOffsetNoScale /= fFontScaleX;
     309                 :            :                             }
     310                 :            : 
     311                 :            :                             // apply needed offset to transformation
     312         [ +  - ]:        644 :                             aNewTransform.translate(fOffsetNoScale, 0.0);
     313                 :            : 
     314         [ +  - ]:        644 :                             if(!bNoDXArray)
     315                 :            :                             {
     316                 :            :                                 // DXArray values need to be corrected with the offset, too. Here,
     317                 :            :                                 // take the scaled offset since the DXArray is scaled
     318                 :        644 :                                 const sal_uInt32 nArraySize(aNewDXArray.size());
     319                 :            : 
     320         [ +  + ]:       1737 :                                 for(sal_uInt32 a(0); a < nArraySize; a++)
     321                 :            :                                 {
     322         [ +  - ]:       1093 :                                     aNewDXArray[a] -= fOffset;
     323                 :            :                                 }
     324                 :            :                             }
     325                 :            :                         }
     326                 :            : 
     327                 :            :                         // add text transformation to new transformation
     328         [ +  - ]:       1230 :                         aNewTransform *= rDecTrans.getB2DHomMatrix();
     329                 :            : 
     330                 :            :                         // create geometry content for the single word. Do not forget
     331                 :            :                         // to use the new transformation
     332         [ +  - ]:       1230 :                         basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(aNewTransform);
     333                 :            : 
     334                 :       1230 :                         impCreateGeometryContent(rTarget, aDecTrans, getText(), nNewTextStart,
     335         [ +  - ]:       1230 :                             nNewTextEnd - nNewTextStart, aNewDXArray, aNewFontAttribute);
     336                 :            : 
     337         [ +  + ]:       1230 :                         if(aNextWordBoundary.endPos >= getTextPosition() + getTextLength())
     338                 :            :                         {
     339                 :            :                             // end reached
     340                 :        518 :                             aNextWordBoundary.startPos = aNextWordBoundary.endPos;
     341                 :            :                         }
     342                 :            :                         else
     343                 :            :                         {
     344                 :            :                             // get new word portion
     345                 :        712 :                             const sal_Int32 nLastEndPos(aNextWordBoundary.endPos);
     346                 :            : 
     347         [ +  - ]:        712 :                             aNextWordBoundary = xLocalBreakIterator->getWordBoundary(
     348                 :        712 :                                 getText(), aNextWordBoundary.endPos, getLocale(),
     349 [ +  - ][ +  - ]:        712 :                                 ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True);
     350                 :            : 
     351         [ +  + ]:        712 :                             if(nLastEndPos == aNextWordBoundary.endPos)
     352                 :            :                             {
     353                 :            :                                 // backward hit, force next word
     354         [ +  - ]:        506 :                                 aNextWordBoundary = xLocalBreakIterator->getWordBoundary(
     355                 :        506 :                                     getText(), nLastEndPos + 1, getLocale(),
     356 [ +  - ][ +  - ]:        506 :                                     ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True);
     357                 :            :                             }
     358                 :            : 
     359         [ +  - ]:        712 :                             impCorrectTextBoundary(aNextWordBoundary);
     360                 :            :                         }
     361 [ +  - ][ +  - ]:       1816 :                     }
                 [ +  - ]
     362         [ +  - ]:        907 :                 }
     363                 :            :             }
     364                 :        907 :         }
     365                 :            : 
     366                 :       2018 :         Primitive2DSequence TextDecoratedPortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     367                 :            :         {
     368         [ +  - ]:       2018 :             std::vector< Primitive2DReference > aNewPrimitives;
     369         [ +  - ]:       2018 :             basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(getTextTransform());
     370         [ +  - ]:       2018 :             Primitive2DSequence aRetval;
     371                 :            : 
     372                 :            :             // create basic geometry such as SimpleTextPrimitive, Overline, Underline,
     373                 :            :             // Strikeout, etc...
     374         [ +  + ]:       2018 :             if(getWordLineMode())
     375                 :            :             {
     376                 :            :                 // support for single word mode
     377         [ +  - ]:        907 :                 impSplitSingleWords(aNewPrimitives, aDecTrans);
     378                 :            :             }
     379                 :            :             else
     380                 :            :             {
     381                 :            :                 // prepare new font attributes WITHOUT outline
     382                 :            :                 const attribute::FontAttribute aNewFontAttribute(
     383         [ +  - ]:       1111 :                     getFontAttribute().getFamilyName(),
     384         [ +  - ]:       1111 :                     getFontAttribute().getStyleName(),
     385         [ +  - ]:       1111 :                     getFontAttribute().getWeight(),
     386         [ +  - ]:       1111 :                     getFontAttribute().getSymbol(),
     387         [ +  - ]:       1111 :                     getFontAttribute().getVertical(),
     388         [ +  - ]:       1111 :                     getFontAttribute().getItalic(),
     389                 :            :                     false,             // no outline anymore, handled locally
     390         [ +  - ]:       1111 :                     getFontAttribute().getRTL(),
     391 [ +  - ][ +  - ]:       2222 :                     getFontAttribute().getBiDiStrong());
     392                 :            : 
     393                 :            :                 // handle as one word
     394 [ +  - ][ +  - ]:       1111 :                 impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute);
     395                 :            :             }
     396                 :            : 
     397                 :            :             // convert to Primitive2DSequence
     398                 :       2018 :             const sal_uInt32 nMemberCount(aNewPrimitives.size());
     399                 :            : 
     400         [ +  - ]:       2018 :             if(nMemberCount)
     401                 :            :             {
     402         [ +  - ]:       2018 :                 aRetval.realloc(nMemberCount);
     403                 :            : 
     404         [ +  + ]:      10145 :                 for(sal_uInt32 a(0); a < nMemberCount; a++)
     405                 :            :                 {
     406 [ +  - ][ +  - ]:       8127 :                     aRetval[a] = aNewPrimitives[a];
     407                 :            :                 }
     408                 :            :             }
     409                 :            : 
     410                 :            :             // Handle Shadow, Outline and TextRelief
     411         [ +  - ]:       2018 :             if(aRetval.hasElements())
     412                 :            :             {
     413                 :            :                 // outline AND shadow depend on NO TextRelief (see dialog)
     414                 :       2018 :                 const bool bHasTextRelief(TEXT_RELIEF_NONE != getTextRelief());
     415 [ +  + ][ +  + ]:       2018 :                 const bool bHasShadow(!bHasTextRelief && getShadow());
     416 [ +  + ][ +  - ]:       2018 :                 const bool bHasOutline(!bHasTextRelief && getFontAttribute().getOutline());
                 [ +  + ]
     417                 :            : 
     418 [ +  + ][ +  + ]:       2018 :                 if(bHasShadow || bHasTextRelief || bHasOutline)
                 [ +  + ]
     419                 :            :                 {
     420                 :       1798 :                     Primitive2DReference aShadow;
     421                 :            : 
     422         [ +  + ]:       1798 :                     if(bHasShadow)
     423                 :            :                     {
     424                 :            :                         // create shadow with current content (in aRetval). Text shadow
     425                 :            :                         // is constant, relative to font size, rotated with the text and has a
     426                 :            :                         // constant color.
     427                 :            :                         // shadow parameter values
     428                 :            :                         static double fFactor(1.0 / 24.0);
     429         [ +  - ]:        338 :                         const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor);
     430 [ +  - ][ +  + ]:        338 :                         static basegfx::BColor aShadowColor(0.3, 0.3, 0.3);
     431                 :            : 
     432                 :            :                         // preapare shadow transform matrix
     433                 :            :                         const basegfx::B2DHomMatrix aShadowTransform(basegfx::tools::createTranslateB2DHomMatrix(
     434         [ +  - ]:        338 :                             fTextShadowOffset, fTextShadowOffset));
     435                 :            : 
     436                 :            :                         // create shadow primitive
     437                 :            :                         aShadow = Primitive2DReference(new ShadowPrimitive2D(
     438                 :            :                             aShadowTransform,
     439                 :            :                             aShadowColor,
     440 [ +  - ][ +  - ]:        338 :                             aRetval));
         [ +  - ][ +  - ]
                 [ +  - ]
     441                 :            :                     }
     442                 :            : 
     443         [ +  + ]:       1798 :                     if(bHasTextRelief)
     444                 :            :                     {
     445                 :            :                         // create emboss using an own helper primitive since this will
     446                 :            :                         // be view-dependent
     447                 :       1372 :                         const basegfx::BColor aBBlack(0.0, 0.0, 0.0);
     448                 :       1372 :                         const bool bDefaultTextColor(aBBlack == getFontColor());
     449                 :       1372 :                         TextEffectStyle2D aTextEffectStyle2D(TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED);
     450                 :            : 
     451         [ -  + ]:       1372 :                         if(bDefaultTextColor)
     452                 :            :                         {
     453         [ #  # ]:          0 :                             if(TEXT_RELIEF_ENGRAVED == getTextRelief())
     454                 :            :                             {
     455                 :          0 :                                 aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT;
     456                 :            :                             }
     457                 :            :                             else
     458                 :            :                             {
     459                 :          0 :                                 aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT;
     460                 :            :                             }
     461                 :            :                         }
     462                 :            :                         else
     463                 :            :                         {
     464         [ -  + ]:       1372 :                             if(TEXT_RELIEF_ENGRAVED == getTextRelief())
     465                 :            :                             {
     466                 :          0 :                                 aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED;
     467                 :            :                             }
     468                 :            :                             else
     469                 :            :                             {
     470                 :       1372 :                                 aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED;
     471                 :            :                             }
     472                 :            :                         }
     473                 :            : 
     474                 :            :                         Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
     475                 :            :                             aRetval,
     476         [ +  - ]:       1372 :                             aDecTrans.getTranslate(),
     477                 :            :                             aDecTrans.getRotate(),
     478 [ +  - ][ +  - ]:       1372 :                             aTextEffectStyle2D));
         [ +  - ][ +  - ]
     479 [ +  - ][ +  - ]:       1372 :                         aRetval = Primitive2DSequence(&aNewTextEffect, 1);
                 [ +  - ]
     480                 :            :                     }
     481         [ +  + ]:        426 :                     else if(bHasOutline)
     482                 :            :                     {
     483                 :            :                         // create outline using an own helper primitive since this will
     484                 :            :                         // be view-dependent
     485                 :            :                         Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
     486                 :            :                             aRetval,
     487         [ +  - ]:        355 :                             aDecTrans.getTranslate(),
     488                 :            :                             aDecTrans.getRotate(),
     489 [ +  - ][ +  - ]:        355 :                             TEXTEFFECTSTYLE2D_OUTLINE));
         [ +  - ][ +  - ]
     490 [ +  - ][ +  - ]:        355 :                         aRetval = Primitive2DSequence(&aNewTextEffect, 1);
                 [ +  - ]
     491                 :            :                     }
     492                 :            : 
     493         [ +  + ]:       1798 :                     if(aShadow.is())
     494                 :            :                     {
     495                 :            :                         // put shadow in front if there is one to paint timely before
     496                 :            :                         // but placed behind content
     497         [ +  - ]:        338 :                         const Primitive2DSequence aContent(aRetval);
     498 [ +  - ][ +  - ]:        338 :                         aRetval = Primitive2DSequence(&aShadow, 1);
                 [ +  - ]
     499 [ +  - ][ +  - ]:        338 :                         appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aContent);
     500                 :       1798 :                     }
     501                 :            :                 }
     502                 :            :             }
     503                 :            : 
     504         [ +  - ]:       2018 :             return aRetval;
     505                 :            :         }
     506                 :            : 
     507                 :       2018 :         TextDecoratedPortionPrimitive2D::TextDecoratedPortionPrimitive2D(
     508                 :            : 
     509                 :            :             // TextSimplePortionPrimitive2D parameters
     510                 :            :             const basegfx::B2DHomMatrix& rNewTransform,
     511                 :            :             const String& rText,
     512                 :            :             xub_StrLen aTextPosition,
     513                 :            :             xub_StrLen aTextLength,
     514                 :            :             const ::std::vector< double >& rDXArray,
     515                 :            :             const attribute::FontAttribute& rFontAttribute,
     516                 :            :             const ::com::sun::star::lang::Locale& rLocale,
     517                 :            :             const basegfx::BColor& rFontColor,
     518                 :            : 
     519                 :            :             // local parameters
     520                 :            :             const basegfx::BColor& rOverlineColor,
     521                 :            :             const basegfx::BColor& rTextlineColor,
     522                 :            :             TextLine eFontOverline,
     523                 :            :             TextLine eFontUnderline,
     524                 :            :             bool bUnderlineAbove,
     525                 :            :             TextStrikeout eTextStrikeout,
     526                 :            :             bool bWordLineMode,
     527                 :            :             TextEmphasisMark eTextEmphasisMark,
     528                 :            :             bool bEmphasisMarkAbove,
     529                 :            :             bool bEmphasisMarkBelow,
     530                 :            :             TextRelief eTextRelief,
     531                 :            :             bool bShadow)
     532                 :            :         :   TextSimplePortionPrimitive2D(rNewTransform, rText, aTextPosition, aTextLength, rDXArray, rFontAttribute, rLocale, rFontColor),
     533                 :            :             maOverlineColor(rOverlineColor),
     534                 :            :             maTextlineColor(rTextlineColor),
     535                 :            :             meFontOverline(eFontOverline),
     536                 :            :             meFontUnderline(eFontUnderline),
     537                 :            :             meTextStrikeout(eTextStrikeout),
     538                 :            :             meTextEmphasisMark(eTextEmphasisMark),
     539                 :            :             meTextRelief(eTextRelief),
     540                 :            :             mbUnderlineAbove(bUnderlineAbove),
     541                 :            :             mbWordLineMode(bWordLineMode),
     542                 :            :             mbEmphasisMarkAbove(bEmphasisMarkAbove),
     543                 :            :             mbEmphasisMarkBelow(bEmphasisMarkBelow),
     544                 :       2018 :             mbShadow(bShadow)
     545                 :            :         {
     546                 :       2018 :         }
     547                 :            : 
     548                 :          0 :         bool TextDecoratedPortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     549                 :            :         {
     550         [ #  # ]:          0 :             if(TextSimplePortionPrimitive2D::operator==(rPrimitive))
     551                 :            :             {
     552                 :          0 :                 const TextDecoratedPortionPrimitive2D& rCompare = (TextDecoratedPortionPrimitive2D&)rPrimitive;
     553                 :            : 
     554                 :          0 :                 return (getOverlineColor() == rCompare.getOverlineColor()
     555                 :          0 :                     && getTextlineColor() == rCompare.getTextlineColor()
     556                 :          0 :                     && getFontOverline() == rCompare.getFontOverline()
     557                 :          0 :                     && getFontUnderline() == rCompare.getFontUnderline()
     558                 :          0 :                     && getTextStrikeout() == rCompare.getTextStrikeout()
     559                 :          0 :                     && getTextEmphasisMark() == rCompare.getTextEmphasisMark()
     560                 :          0 :                     && getTextRelief() == rCompare.getTextRelief()
     561                 :          0 :                     && getUnderlineAbove() == rCompare.getUnderlineAbove()
     562                 :          0 :                     && getWordLineMode() == rCompare.getWordLineMode()
     563                 :          0 :                     && getEmphasisMarkAbove() == rCompare.getEmphasisMarkAbove()
     564                 :          0 :                     && getEmphasisMarkBelow() == rCompare.getEmphasisMarkBelow()
     565 [ #  # ][ #  #  :          0 :                     && getShadow() == rCompare.getShadow());
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     566                 :            :             }
     567                 :            : 
     568                 :          0 :             return false;
     569                 :            :         }
     570                 :            : 
     571                 :            :         // #i96475#
     572                 :            :         // Added missing implementation. Decorations may (will) stick out of the text's
     573                 :            :         // inking area, so add them if needed
     574                 :      14348 :         basegfx::B2DRange TextDecoratedPortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
     575                 :            :         {
     576                 :            :             const bool bDecoratedIsNeeded(
     577                 :      14348 :                 TEXT_LINE_NONE != getFontOverline()
     578                 :       3659 :              || TEXT_LINE_NONE != getFontUnderline()
     579                 :        465 :              || TEXT_STRIKEOUT_NONE != getTextStrikeout()
     580                 :         62 :              || TEXT_EMPHASISMARK_NONE != getTextEmphasisMark()
     581                 :          0 :              || TEXT_RELIEF_NONE != getTextRelief()
     582 [ #  # ][ +  +  :      18534 :              || getShadow());
          +  +  +  +  -  
                +  #  # ]
     583                 :            : 
     584         [ +  - ]:      14348 :             if(bDecoratedIsNeeded)
     585                 :            :             {
     586                 :            :                 // decoration is used, fallback to BufferedDecompositionPrimitive2D::getB2DRange which uses
     587                 :            :                 // the own local decomposition for computation and thus creates all necessary
     588                 :            :                 // geometric objects
     589                 :      14348 :                 return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
     590                 :            :             }
     591                 :            :             else
     592                 :            :             {
     593                 :            :                 // no relevant decoration used, fallback to TextSimplePortionPrimitive2D::getB2DRange
     594                 :      14348 :                 return TextSimplePortionPrimitive2D::getB2DRange(rViewInformation);
     595                 :            :             }
     596                 :            :         }
     597                 :            : 
     598                 :            :         // provide unique ID
     599                 :       2357 :         ImplPrimitrive2DIDBlock(TextDecoratedPortionPrimitive2D, PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
     600                 :            : 
     601                 :            :     } // end of namespace primitive2d
     602                 :            : } // end of namespace drawinglayer
     603                 :            : 
     604                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10