LCOV - code coverage report
Current view: top level - cppcanvas/source/mtfrenderer - textaction.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 469 0.2 %
Date: 2012-08-25 Functions: 2 77 2.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 1130 0.2 %

           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                 :            : 
      30                 :            : #include <canvas/debug.hxx>
      31                 :            : #include <tools/diagnose_ex.h>
      32                 :            : #include <canvas/verbosetrace.hxx>
      33                 :            : 
      34                 :            : #include <rtl/logfile.hxx>
      35                 :            : 
      36                 :            : #include <com/sun/star/rendering/PathCapType.hpp>
      37                 :            : #include <com/sun/star/rendering/PathJoinType.hpp>
      38                 :            : #include <com/sun/star/rendering/XCanvas.hpp>
      39                 :            : #include <com/sun/star/rendering/XCanvasFont.hpp>
      40                 :            : 
      41                 :            : #include <basegfx/numeric/ftools.hxx>
      42                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      43                 :            : #include <basegfx/range/b2drectangle.hxx>
      44                 :            : #include <basegfx/vector/b2dsize.hxx>
      45                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      46                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      47                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      48                 :            : 
      49                 :            : #include <tools/gen.hxx>
      50                 :            : #include <vcl/canvastools.hxx>
      51                 :            : #include <vcl/virdev.hxx>
      52                 :            : 
      53                 :            : #include <basegfx/tools/canvastools.hxx>
      54                 :            : #include <canvas/canvastools.hxx>
      55                 :            : 
      56                 :            : #include <boost/scoped_array.hpp>
      57                 :            : #include <boost/bind.hpp>
      58                 :            : #include <boost/utility.hpp>
      59                 :            : 
      60                 :            : #include "textaction.hxx"
      61                 :            : #include "outdevstate.hxx"
      62                 :            : #include "mtftools.hxx"
      63                 :            : 
      64                 :            : 
      65                 :            : using namespace ::com::sun::star;
      66                 :            : 
      67                 :            : namespace cppcanvas
      68                 :            : {
      69                 :            :     namespace internal
      70                 :            :     {
      71                 :            :         namespace
      72                 :            :         {
      73                 :          0 :             void init( rendering::RenderState&                  o_rRenderState,
      74                 :            :                        const ::basegfx::B2DPoint&               rStartPoint,
      75                 :            :                        const OutDevState&                       rState,
      76                 :            :                        const CanvasSharedPtr&                   rCanvas      )
      77                 :            :             {
      78         [ #  # ]:          0 :                 tools::initRenderState(o_rRenderState,rState);
      79                 :            : 
      80                 :            :                 // #i36950# Offset clip back to origin (as it's also moved
      81                 :            :                 // by rStartPoint)
      82                 :            :                 // #i53964# Also take VCL font rotation into account,
      83                 :            :                 // since this, opposed to the FontMatrix rotation
      84                 :            :                 // elsewhere, _does_ get incorporated into the render
      85                 :            :                 // state transform.
      86                 :            :                 tools::modifyClip( o_rRenderState,
      87                 :            :                                    rState,
      88                 :            :                                    rCanvas,
      89                 :            :                                    rStartPoint,
      90                 :            :                                    NULL,
      91         [ #  # ]:          0 :                                    &rState.fontRotation );
      92                 :            : 
      93         [ #  # ]:          0 :                 basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState.fontRotation));
      94                 :            :                 aLocalTransformation.translate( rStartPoint.getX(),
      95         [ #  # ]:          0 :                                                 rStartPoint.getY() );
      96                 :            :                 ::canvas::tools::appendToRenderState( o_rRenderState,
      97         [ #  # ]:          0 :                                                       aLocalTransformation );
      98                 :            : 
      99 [ #  # ][ #  # ]:          0 :                 o_rRenderState.DeviceColor = rState.textColor;
     100                 :          0 :             }
     101                 :            : 
     102                 :          0 :             void init( rendering::RenderState&                  o_rRenderState,
     103                 :            :                        const ::basegfx::B2DPoint&               rStartPoint,
     104                 :            :                        const OutDevState&                       rState,
     105                 :            :                        const CanvasSharedPtr&                   rCanvas,
     106                 :            :                        const ::basegfx::B2DHomMatrix&           rTextTransform  )
     107                 :            :             {
     108                 :          0 :                 init( o_rRenderState, rStartPoint, rState, rCanvas );
     109                 :            : 
     110                 :            :                 // TODO(F2): Also inversely-transform clip with
     111                 :            :                 // rTextTransform (which is actually rather hard, as the
     112                 :            :                 // text transform is _prepended_ to the render state)!
     113                 :            : 
     114                 :            :                 // prepend extra font transform to render state
     115                 :            :                 // (prepend it, because it's interpreted in the unit
     116                 :            :                 // rect coordinate space)
     117                 :            :                 ::canvas::tools::prependToRenderState( o_rRenderState,
     118                 :          0 :                                                        rTextTransform );
     119                 :          0 :             }
     120                 :            : 
     121                 :          0 :             void init( rendering::RenderState&                      o_rRenderState,
     122                 :            :                        uno::Reference< rendering::XCanvasFont >&    o_rFont,
     123                 :            :                        const ::basegfx::B2DPoint&                   rStartPoint,
     124                 :            :                        const OutDevState&                           rState,
     125                 :            :                        const CanvasSharedPtr&                       rCanvas      )
     126                 :            :             {
     127                 :            :                 // ensure that o_rFont is valid. It is possible that
     128                 :            :                 // text actions are generated without previously
     129                 :            :                 // setting a font. Then, just take a default font
     130         [ #  # ]:          0 :                 if( !o_rFont.is() )
     131                 :            :                 {
     132                 :            :                     // Use completely default FontRequest
     133                 :          0 :                     const rendering::FontRequest aFontRequest;
     134                 :            : 
     135                 :          0 :                     geometry::Matrix2D aFontMatrix;
     136         [ #  # ]:          0 :                     ::canvas::tools::setIdentityMatrix2D( aFontMatrix );
     137                 :            : 
     138 [ #  # ][ #  # ]:          0 :                     o_rFont = rCanvas->getUNOCanvas()->createFont(
     139                 :            :                         aFontRequest,
     140                 :            :                         uno::Sequence< beans::PropertyValue >(),
     141 [ #  # ][ #  # ]:          0 :                         aFontMatrix );
         [ #  # ][ #  # ]
     142                 :            :                 }
     143                 :            : 
     144                 :            :                 init( o_rRenderState,
     145                 :            :                       rStartPoint,
     146                 :            :                       rState,
     147                 :          0 :                       rCanvas );
     148                 :          0 :             }
     149                 :            : 
     150                 :          0 :             void init( rendering::RenderState&                      o_rRenderState,
     151                 :            :                        uno::Reference< rendering::XCanvasFont >&    o_rFont,
     152                 :            :                        const ::basegfx::B2DPoint&                   rStartPoint,
     153                 :            :                        const OutDevState&                           rState,
     154                 :            :                        const CanvasSharedPtr&                       rCanvas,
     155                 :            :                        const ::basegfx::B2DHomMatrix&               rTextTransform  )
     156                 :            :             {
     157                 :          0 :                 init( o_rRenderState, o_rFont, rStartPoint, rState, rCanvas );
     158                 :            : 
     159                 :            :                 // TODO(F2): Also inversely-transform clip with
     160                 :            :                 // rTextTransform (which is actually rather hard, as the
     161                 :            :                 // text transform is _prepended_ to the render state)!
     162                 :            : 
     163                 :            :                 // prepend extra font transform to render state
     164                 :            :                 // (prepend it, because it's interpreted in the unit
     165                 :            :                 // rect coordinate space)
     166                 :            :                 ::canvas::tools::prependToRenderState( o_rRenderState,
     167                 :          0 :                                                        rTextTransform );
     168                 :          0 :             }
     169                 :            : 
     170                 :          0 :             ::basegfx::B2DPolyPolygon textLinesFromLogicalOffsets( const uno::Sequence< double >&   rOffsets,
     171                 :            :                                                                    const tools::TextLineInfo&       rTextLineInfo )
     172                 :            :             {
     173                 :            :                 return tools::createTextLinesPolyPolygon(
     174                 :            :                     0.0,
     175                 :            :                     // extract character cell furthest to the right
     176                 :            :                     *(::std::max_element(
     177                 :            :                           rOffsets.getConstArray(),
     178                 :          0 :                           rOffsets.getConstArray() + rOffsets.getLength() )),
     179         [ #  # ]:          0 :                     rTextLineInfo );
     180                 :            :             }
     181                 :            : 
     182                 :          0 :             uno::Sequence< double > setupDXArray( const sal_Int32*   pCharWidths,
     183                 :            :                                                   sal_Int32          nLen,
     184                 :            :                                                   const OutDevState& rState )
     185                 :            :             {
     186                 :            :                 // convert character widths from logical units
     187                 :          0 :                 uno::Sequence< double > aCharWidthSeq( nLen );
     188         [ #  # ]:          0 :                 double*                 pOutputWidths( aCharWidthSeq.getArray() );
     189                 :            : 
     190                 :            :                 // #143885# maintain (nearly) full precision of DX
     191                 :            :                 // array, by circumventing integer-based
     192                 :            :                 // OutDev-mapping
     193         [ #  # ]:          0 :                 const double nScale( rState.mapModeTransform.get(0,0) );
     194         [ #  # ]:          0 :                 for( int i = 0; i < nLen; ++i )
     195                 :            :                 {
     196                 :            :                     // TODO(F2): use correct scale direction
     197                 :          0 :                     *pOutputWidths++ = *pCharWidths++ * nScale;
     198                 :            :                 }
     199                 :            : 
     200                 :          0 :                 return aCharWidthSeq;
     201                 :            :             }
     202                 :            : 
     203                 :          0 :             uno::Sequence< double > setupDXArray( const ::String&    rText,
     204                 :            :                                                   sal_Int32          nStartPos,
     205                 :            :                                                   sal_Int32          nLen,
     206                 :            :                                                   VirtualDevice&     rVDev,
     207                 :            :                                                   const OutDevState& rState )
     208                 :            :             {
     209                 :            :                 // no external DX array given, create one from given
     210                 :            :                 // string
     211         [ #  # ]:          0 :                 ::boost::scoped_array< sal_Int32 > pCharWidths( new sal_Int32[nLen] );
     212                 :            : 
     213                 :            :                 rVDev.GetTextArray( rText, pCharWidths.get(),
     214                 :            :                                     static_cast<sal_uInt16>(nStartPos),
     215         [ #  # ]:          0 :                                     static_cast<sal_uInt16>(nLen) );
     216                 :            : 
     217 [ #  # ][ #  # ]:          0 :                 return setupDXArray( pCharWidths.get(), nLen, rState );
     218                 :            :             }
     219                 :            : 
     220                 :          0 :             ::basegfx::B2DPoint adaptStartPoint( const ::basegfx::B2DPoint&     rStartPoint,
     221                 :            :                                                  const OutDevState&             rState,
     222                 :            :                                                  const uno::Sequence< double >& rOffsets )
     223                 :            :             {
     224                 :          0 :                 ::basegfx::B2DPoint aLocalPoint( rStartPoint );
     225                 :            : 
     226         [ #  # ]:          0 :                 if( rState.textAlignment )
     227                 :            :                 {
     228                 :            :                     // text origin is right, not left. Modify start point
     229                 :            :                     // accordingly, because XCanvas::drawTextLayout()
     230                 :            :                     // always aligns left!
     231                 :            : 
     232                 :          0 :                     const double nOffset( rOffsets[ rOffsets.getLength()-1 ] );
     233                 :            : 
     234                 :            :                     // correct start point for rotated text: rotate around
     235                 :            :                     // former start point
     236                 :          0 :                     aLocalPoint.setX( aLocalPoint.getX() + cos( rState.fontRotation )*nOffset );
     237                 :          0 :                     aLocalPoint.setY( aLocalPoint.getY() + sin( rState.fontRotation )*nOffset );
     238                 :            :                 }
     239                 :            : 
     240                 :          0 :                 return aLocalPoint;
     241                 :            :             }
     242                 :            : 
     243                 :            :             /** Perform common setup for array text actions
     244                 :            : 
     245                 :            :                 This method creates the XTextLayout object and
     246                 :            :                 initializes it, e.g. with the logical advancements.
     247                 :            :              */
     248                 :          0 :             void initArrayAction( rendering::RenderState&                   o_rRenderState,
     249                 :            :                                   uno::Reference< rendering::XTextLayout >& o_rTextLayout,
     250                 :            :                                   const ::basegfx::B2DPoint&                rStartPoint,
     251                 :            :                                   const ::rtl::OUString&                    rText,
     252                 :            :                                   sal_Int32                                 nStartPos,
     253                 :            :                                   sal_Int32                                 nLen,
     254                 :            :                                   const uno::Sequence< double >&            rOffsets,
     255                 :            :                                   const CanvasSharedPtr&                    rCanvas,
     256                 :            :                                   const OutDevState&                        rState,
     257                 :            :                                   const ::basegfx::B2DHomMatrix*            pTextTransform )
     258                 :            :             {
     259 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( rOffsets.getLength(),
         [ #  # ][ #  # ]
     260                 :            :                                   "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
     261                 :            : 
     262                 :            :                 const ::basegfx::B2DPoint aLocalStartPoint(
     263         [ #  # ]:          0 :                     adaptStartPoint( rStartPoint, rState, rOffsets ) );
     264                 :            : 
     265                 :          0 :                 uno::Reference< rendering::XCanvasFont > xFont( rState.xFont );
     266                 :            : 
     267         [ #  # ]:          0 :                 if( pTextTransform )
     268         [ #  # ]:          0 :                     init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas, *pTextTransform );
     269                 :            :                 else
     270         [ #  # ]:          0 :                     init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas );
     271                 :            : 
     272         [ #  # ]:          0 :                 o_rTextLayout = xFont->createTextLayout(
     273                 :            :                     rendering::StringContext( rText, nStartPos, nLen ),
     274                 :            :                     rState.textDirection,
     275 [ #  # ][ #  # ]:          0 :                     0 );
     276                 :            : 
     277 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( o_rTextLayout.is(),
         [ #  # ][ #  # ]
     278                 :            :                                   "::cppcanvas::internal::initArrayAction(): Invalid font" );
     279                 :            : 
     280 [ #  # ][ #  # ]:          0 :                 o_rTextLayout->applyLogicalAdvancements( rOffsets );
     281                 :          0 :             }
     282                 :            : 
     283                 :          0 :             double getLineWidth( ::VirtualDevice&                rVDev,
     284                 :            :                                  const OutDevState&              rState,
     285                 :            :                                  const rendering::StringContext& rStringContext )
     286                 :            :             {
     287                 :            :                 // TODO(F2): use correct scale direction
     288                 :            :                 const ::basegfx::B2DSize aSize( rVDev.GetTextWidth( rStringContext.Text,
     289                 :            :                                                                     static_cast<sal_uInt16>(rStringContext.StartPosition),
     290         [ #  # ]:          0 :                                                                     static_cast<sal_uInt16>(rStringContext.Length) ),
           [ #  #  #  # ]
     291                 :          0 :                                     0 );
     292                 :            : 
     293         [ #  # ]:          0 :                 return (rState.mapModeTransform * aSize).getX();
     294                 :            :             }
     295                 :            : 
     296                 :            :             uno::Sequence< double >
     297                 :          0 :                 calcSubsetOffsets( rendering::RenderState&                          io_rRenderState,
     298                 :            :                                    double&                                          o_rMinPos,
     299                 :            :                                    double&                                          o_rMaxPos,
     300                 :            :                                    const uno::Reference< rendering::XTextLayout >&  rOrigTextLayout,
     301                 :            :                                    const ::cppcanvas::internal::Action::Subset&     rSubset )
     302                 :            :             {
     303 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( rSubset.mnSubsetEnd > rSubset.mnSubsetBegin,
         [ #  # ][ #  # ]
     304                 :            :                                   "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
     305                 :            : 
     306 [ #  # ][ #  # ]:          0 :                 uno::Sequence< double > aOrigOffsets( rOrigTextLayout->queryLogicalAdvancements() );
     307                 :          0 :                 const double*           pOffsets( aOrigOffsets.getConstArray() );
     308                 :            : 
     309 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( aOrigOffsets.getLength() >= rSubset.mnSubsetEnd,
         [ #  # ][ #  # ]
     310                 :            :                                   "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
     311                 :            : 
     312                 :            :                 // TODO(F3): It currently seems that for RTL text, the
     313                 :            :                 // DX offsets are nevertheless increasing in logical
     314                 :            :                 // text order (I'd expect they are decreasing,
     315                 :            :                 // mimicking the fact that the text is output
     316                 :            :                 // right-to-left). This breaks text effects for ALL
     317                 :            :                 // RTL languages.
     318                 :            : 
     319                 :            :                 // determine leftmost position in given subset range -
     320                 :            :                 // as the DX array contains the output positions
     321                 :            :                 // starting with the second character (the first is
     322                 :            :                 // assumed to have output position 0), correct begin
     323                 :            :                 // iterator.
     324                 :            :                 const double nMinPos( rSubset.mnSubsetBegin <= 0 ? 0 :
     325                 :            :                                       *(::std::min_element( pOffsets+rSubset.mnSubsetBegin-1,
     326 [ #  # ][ #  # ]:          0 :                                                             pOffsets+rSubset.mnSubsetEnd )) );
     327                 :            : 
     328                 :            :                 // determine rightmost position in given subset range
     329                 :            :                 // - as the DX array contains the output positions
     330                 :            :                 // starting with the second character (the first is
     331                 :            :                 // assumed to have output position 0), correct begin
     332                 :            :                 // iterator.
     333                 :            :                 const double nMaxPos(
     334                 :            :                     *(::std::max_element( pOffsets + (rSubset.mnSubsetBegin <= 0 ?
     335                 :            :                                                       0 : rSubset.mnSubsetBegin-1),
     336 [ #  # ][ #  # ]:          0 :                                           pOffsets + rSubset.mnSubsetEnd )) );
     337                 :            : 
     338                 :            : 
     339                 :            :                 // adapt render state, to move text output to given offset
     340                 :            :                 // -------------------------------------------------------
     341                 :            : 
     342                 :            :                 // TODO(F1): Strictly speaking, we also have to adapt
     343                 :            :                 // the clip here, which normally should _not_ move
     344                 :            :                 // with the output offset. Neglected for now, as it
     345                 :            :                 // does not matter for drawing layer output
     346                 :            : 
     347         [ #  # ]:          0 :                 if( rSubset.mnSubsetBegin > 0 )
     348                 :            :                 {
     349         [ #  # ]:          0 :                     ::basegfx::B2DHomMatrix aTranslation;
     350 [ #  # ][ #  # ]:          0 :                     if( rOrigTextLayout->getFont()->getFontRequest().FontDescription.IsVertical )
         [ #  # ][ #  # ]
                 [ #  # ]
     351                 :            :                     {
     352                 :            :                         // vertical text -> offset in y direction
     353         [ #  # ]:          0 :                         aTranslation.translate( 0.0, nMinPos );
     354                 :            :                     }
     355                 :            :                     else
     356                 :            :                     {
     357                 :            :                         // horizontal text -> offset in x direction
     358         [ #  # ]:          0 :                         aTranslation.translate( nMinPos, 0.0 );
     359                 :            :                     }
     360                 :            : 
     361                 :            :                     ::canvas::tools::appendToRenderState( io_rRenderState,
     362 [ #  # ][ #  # ]:          0 :                                                           aTranslation );
     363                 :            :                 }
     364                 :            : 
     365                 :            : 
     366                 :            :                 // reduce DX array to given substring
     367                 :            :                 // ----------------------------------
     368                 :            : 
     369                 :          0 :                 const sal_Int32         nNewElements( rSubset.mnSubsetEnd - rSubset.mnSubsetBegin );
     370         [ #  # ]:          0 :                 uno::Sequence< double > aAdaptedOffsets( nNewElements );
     371         [ #  # ]:          0 :                 double*                 pAdaptedOffsets( aAdaptedOffsets.getArray() );
     372                 :            : 
     373                 :            :                 // move to new output position (subtract nMinPos,
     374                 :            :                 // which is the new '0' position), copy only the range
     375                 :            :                 // as given by rSubset.
     376                 :            :                 ::std::transform( pOffsets + rSubset.mnSubsetBegin,
     377                 :            :                                   pOffsets + rSubset.mnSubsetEnd,
     378                 :            :                                   pAdaptedOffsets,
     379                 :            :                                   ::boost::bind( ::std::minus<double>(),
     380                 :            :                                                  _1,
     381 [ #  # ][ #  # ]:          0 :                                                  nMinPos ) );
     382                 :            : 
     383                 :          0 :                 o_rMinPos = nMinPos;
     384                 :          0 :                 o_rMaxPos = nMaxPos;
     385                 :            : 
     386         [ #  # ]:          0 :                 return aAdaptedOffsets;
     387                 :            :             }
     388                 :            : 
     389                 :            :             uno::Reference< rendering::XTextLayout >
     390                 :          0 :                 createSubsetLayout( const rendering::StringContext&                 rOrigContext,
     391                 :            :                                     const ::cppcanvas::internal::Action::Subset&    rSubset,
     392                 :            :                                     const uno::Reference< rendering::XTextLayout >& rOrigTextLayout )
     393                 :            :             {
     394                 :            :                 // create temporary new text layout with subset string
     395                 :            :                 // ---------------------------------------------------
     396                 :            : 
     397                 :            :                 const sal_Int32 nNewStartPos( rOrigContext.StartPosition + ::std::min(
     398         [ #  # ]:          0 :                                                   rSubset.mnSubsetBegin, rOrigContext.Length-1 ) );
     399                 :            :                 const sal_Int32 nNewLength( ::std::max(
     400                 :            :                                                 ::std::min(
     401                 :            :                                                     rSubset.mnSubsetEnd - rSubset.mnSubsetBegin,
     402         [ #  # ]:          0 :                                                     rOrigContext.Length ),
     403         [ #  # ]:          0 :                                                 sal_Int32( 0 ) ) );
     404                 :            : 
     405                 :            :                 const rendering::StringContext aContext( rOrigContext.Text,
     406                 :            :                                                          nNewStartPos,
     407                 :          0 :                                                          nNewLength );
     408                 :            : 
     409                 :            :                 uno::Reference< rendering::XTextLayout > xTextLayout(
     410 [ #  # ][ #  # ]:          0 :                     rOrigTextLayout->getFont()->createTextLayout( aContext,
                 [ #  # ]
     411 [ #  # ][ #  # ]:          0 :                                                                   rOrigTextLayout->getMainTextDirection(),
     412                 :          0 :                                                                   0 ),
     413 [ #  # ][ #  # ]:          0 :                     uno::UNO_QUERY_THROW );
     414                 :            : 
     415                 :          0 :                 return xTextLayout;
     416                 :            :             }
     417                 :            : 
     418                 :            :             /** Setup subset text layout
     419                 :            : 
     420                 :            :                 @param io_rTextLayout
     421                 :            :                 Must contain original (full set) text layout on input,
     422                 :            :                 will contain subsetted text layout (or empty
     423                 :            :                 reference, for empty subsets) on output.
     424                 :            : 
     425                 :            :                 @param io_rRenderState
     426                 :            :                 Must contain original render state on input, will
     427                 :            :                 contain shifted render state concatenated with
     428                 :            :                 rTransformation on output.
     429                 :            : 
     430                 :            :                 @param rTransformation
     431                 :            :                 Additional transformation, to be prepended to render
     432                 :            :                 state
     433                 :            : 
     434                 :            :                 @param rSubset
     435                 :            :                 Subset to prepare
     436                 :            :              */
     437                 :          0 :             void createSubsetLayout( uno::Reference< rendering::XTextLayout >&  io_rTextLayout,
     438                 :            :                                      rendering::RenderState&                    io_rRenderState,
     439                 :            :                                      double&                                    o_rMinPos,
     440                 :            :                                      double&                                    o_rMaxPos,
     441                 :            :                                      const ::basegfx::B2DHomMatrix&             rTransformation,
     442                 :            :                                      const Action::Subset&                      rSubset )
     443                 :            :             {
     444         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(io_rRenderState, rTransformation);
     445                 :            : 
     446         [ #  # ]:          0 :                 if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
     447                 :            :                 {
     448                 :            :                      // empty range, empty layout
     449                 :          0 :                     io_rTextLayout.clear();
     450                 :            : 
     451                 :            :                     return;
     452                 :            :                 }
     453                 :            : 
     454 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( io_rTextLayout.is(),
         [ #  # ][ #  # ]
     455                 :            :                                   "createSubsetLayout(): Invalid input layout" );
     456                 :            : 
     457 [ #  # ][ #  # ]:          0 :                 const rendering::StringContext& rOrigContext( io_rTextLayout->getText() );
     458                 :            : 
     459 [ #  # ][ #  # ]:          0 :                 if( rSubset.mnSubsetBegin == 0 &&
     460                 :            :                     rSubset.mnSubsetEnd == rOrigContext.Length )
     461                 :            :                 {
     462                 :            :                     // full range, no need for subsetting
     463                 :            :                     return;
     464                 :            :                 }
     465                 :            : 
     466                 :            :                 uno::Reference< rendering::XTextLayout > xTextLayout(
     467         [ #  # ]:          0 :                     createSubsetLayout( rOrigContext, rSubset, io_rTextLayout ) );
     468                 :            : 
     469         [ #  # ]:          0 :                 if( xTextLayout.is() )
     470                 :            :                 {
     471         [ #  # ]:          0 :                     xTextLayout->applyLogicalAdvancements(
     472                 :            :                         calcSubsetOffsets( io_rRenderState,
     473                 :            :                                            o_rMinPos,
     474                 :            :                                            o_rMaxPos,
     475                 :            :                                            io_rTextLayout,
     476 [ #  # ][ #  # ]:          0 :                                            rSubset ) );
                 [ #  # ]
     477                 :            :                 }
     478                 :            : 
     479 [ #  # ][ #  # ]:          0 :                 io_rTextLayout = xTextLayout;
     480                 :            :             }
     481                 :            : 
     482                 :            : 
     483                 :            :             /** Interface for renderEffectText functor below.
     484                 :            : 
     485                 :            :                 This is interface is used from the renderEffectText()
     486                 :            :                 method below, to call the client implementation.
     487                 :            :              */
     488                 :          0 :             class TextRenderer
     489                 :            :             {
     490                 :            :             public:
     491         [ #  # ]:          0 :                 virtual ~TextRenderer() {}
     492                 :            : 
     493                 :            :                 /// Render text with given RenderState
     494                 :            :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const = 0;
     495                 :            :             };
     496                 :            : 
     497                 :            :             /** Render effect text.
     498                 :            : 
     499                 :            :                 @param rRenderer
     500                 :            :                 Functor object, will be called to render the actual
     501                 :            :                 part of the text effect (the text itself and the means
     502                 :            :                 to render it are unknown to this method)
     503                 :            :              */
     504                 :          0 :             bool renderEffectText( const TextRenderer&                          rRenderer,
     505                 :            :                                    const rendering::RenderState&                rRenderState,
     506                 :            :                                    const rendering::ViewState&                  /*rViewState*/,
     507                 :            :                                    const uno::Reference< rendering::XCanvas >&  xCanvas,
     508                 :            :                                    const ::Color&                               rShadowColor,
     509                 :            :                                    const ::basegfx::B2DSize&                    rShadowOffset,
     510                 :            :                                    const ::Color&                               rReliefColor,
     511                 :            :                                    const ::basegfx::B2DSize&                    rReliefOffset )
     512                 :            :             {
     513                 :          0 :                 ::Color aEmptyColor( COL_AUTO );
     514                 :            :                 uno::Reference<rendering::XColorSpace> xColorSpace(
     515 [ #  # ][ #  # ]:          0 :                     xCanvas->getDevice()->getDeviceColorSpace() );
         [ #  # ][ #  # ]
     516                 :            : 
     517                 :            :                 // draw shadow text, if enabled
     518         [ #  # ]:          0 :                 if( rShadowColor != aEmptyColor )
     519                 :            :                 {
     520         [ #  # ]:          0 :                     rendering::RenderState aShadowState( rRenderState );
     521         [ #  # ]:          0 :                     ::basegfx::B2DHomMatrix aTranslate;
     522                 :            : 
     523                 :            :                     aTranslate.translate( rShadowOffset.getX(),
     524         [ #  # ]:          0 :                                           rShadowOffset.getY() );
     525                 :            : 
     526         [ #  # ]:          0 :                     ::canvas::tools::appendToRenderState(aShadowState, aTranslate);
     527                 :            : 
     528                 :            :                     aShadowState.DeviceColor =
     529                 :            :                         ::vcl::unotools::colorToDoubleSequence( rShadowColor,
     530 [ #  # ][ #  # ]:          0 :                                                                 xColorSpace );
                 [ #  # ]
     531                 :            : 
     532 [ #  # ][ #  # ]:          0 :                     rRenderer( aShadowState );
                 [ #  # ]
     533                 :            :                 }
     534                 :            : 
     535                 :            :                 // draw relief text, if enabled
     536         [ #  # ]:          0 :                 if( rReliefColor != aEmptyColor )
     537                 :            :                 {
     538         [ #  # ]:          0 :                     rendering::RenderState aReliefState( rRenderState );
     539         [ #  # ]:          0 :                     ::basegfx::B2DHomMatrix aTranslate;
     540                 :            : 
     541                 :            :                     aTranslate.translate( rReliefOffset.getX(),
     542         [ #  # ]:          0 :                                           rReliefOffset.getY() );
     543                 :            : 
     544         [ #  # ]:          0 :                     ::canvas::tools::appendToRenderState(aReliefState, aTranslate);
     545                 :            : 
     546                 :            :                     aReliefState.DeviceColor =
     547                 :            :                         ::vcl::unotools::colorToDoubleSequence( rReliefColor,
     548 [ #  # ][ #  # ]:          0 :                                                                 xColorSpace );
                 [ #  # ]
     549                 :            : 
     550 [ #  # ][ #  # ]:          0 :                     rRenderer( aReliefState );
                 [ #  # ]
     551                 :            :                 }
     552                 :            : 
     553                 :            :                 // draw normal text
     554         [ #  # ]:          0 :                 rRenderer( rRenderState );
     555                 :            : 
     556                 :          0 :                 return true;
     557                 :            :             }
     558                 :            : 
     559                 :            : 
     560                 :          0 :             ::basegfx::B2DRange calcEffectTextBounds( const ::basegfx::B2DRange&    rTextBounds,
     561                 :            :                                                       const ::basegfx::B2DRange&    rLineBounds,
     562                 :            :                                                       const ::basegfx::B2DSize&     rReliefOffset,
     563                 :            :                                                       const ::basegfx::B2DSize&     rShadowOffset,
     564                 :            :                                                       const rendering::RenderState& rRenderState,
     565                 :            :                                                       const rendering::ViewState&   rViewState )
     566                 :            :             {
     567                 :          0 :                 ::basegfx::B2DRange aBounds( rTextBounds );
     568                 :            : 
     569                 :            :                 // add extends of text lines
     570         [ #  # ]:          0 :                 aBounds.expand( rLineBounds );
     571                 :            : 
     572                 :            :                 // TODO(Q3): Provide this functionality at the B2DRange
     573                 :          0 :                 ::basegfx::B2DRange aTotalBounds( aBounds );
     574                 :            :                 aTotalBounds.expand(
     575         [ #  # ]:          0 :                     ::basegfx::B2DRange( aBounds.getMinX() + rReliefOffset.getX(),
     576         [ #  # ]:          0 :                                          aBounds.getMinY() + rReliefOffset.getY(),
     577         [ #  # ]:          0 :                                          aBounds.getMaxX() + rReliefOffset.getX(),
     578 [ #  # ][ #  # ]:          0 :                                          aBounds.getMaxY() + rReliefOffset.getY() ) );
                 [ #  # ]
     579                 :            :                 aTotalBounds.expand(
     580         [ #  # ]:          0 :                     ::basegfx::B2DRange( aBounds.getMinX() + rShadowOffset.getX(),
     581         [ #  # ]:          0 :                                          aBounds.getMinY() + rShadowOffset.getY(),
     582         [ #  # ]:          0 :                                          aBounds.getMaxX() + rShadowOffset.getX(),
     583 [ #  # ][ #  # ]:          0 :                                          aBounds.getMaxY() + rShadowOffset.getY() ) );
                 [ #  # ]
     584                 :            : 
     585                 :            :                 return tools::calcDevicePixelBounds( aTotalBounds,
     586                 :            :                                                      rViewState,
     587         [ #  # ]:          0 :                                                      rRenderState );
     588                 :            :             }
     589                 :            : 
     590                 :          0 :             void initEffectLinePolyPolygon( ::basegfx::B2DSize&                             o_rOverallSize,
     591                 :            :                                             uno::Reference< rendering::XPolyPolygon2D >&    o_rTextLines,
     592                 :            :                                             const CanvasSharedPtr&                          rCanvas,
     593                 :            :                                             const uno::Sequence< double >&                  rOffsets,
     594                 :            :                                             const tools::TextLineInfo                       rLineInfo   )
     595                 :            :             {
     596                 :            :                 const ::basegfx::B2DPolyPolygon aPoly(
     597                 :            :                     textLinesFromLogicalOffsets(
     598                 :            :                         rOffsets,
     599         [ #  # ]:          0 :                         rLineInfo ) );
     600                 :            : 
     601 [ #  # ][ #  # ]:          0 :                 o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();
                 [ #  # ]
     602                 :            : 
     603                 :            :                 o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
     604 [ #  # ][ #  # ]:          0 :                     rCanvas->getUNOCanvas()->getDevice(),
     605 [ #  # ][ #  # ]:          0 :                     aPoly );
         [ #  # ][ #  # ]
     606                 :          0 :             }
     607                 :            : 
     608                 :          0 :             void initEffectLinePolyPolygon( ::basegfx::B2DSize&                             o_rOverallSize,
     609                 :            :                                             uno::Reference< rendering::XPolyPolygon2D >&    o_rTextLines,
     610                 :            :                                             const CanvasSharedPtr&                          rCanvas,
     611                 :            :                                             double                                          nLineWidth,
     612                 :            :                                             const tools::TextLineInfo                       rLineInfo   )
     613                 :            :             {
     614                 :            :                 const ::basegfx::B2DPolyPolygon aPoly(
     615                 :            :                     tools::createTextLinesPolyPolygon( 0.0, nLineWidth,
     616         [ #  # ]:          0 :                                                        rLineInfo ) );
     617                 :            : 
     618 [ #  # ][ #  # ]:          0 :                 o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();
                 [ #  # ]
     619                 :            : 
     620                 :            :                 o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
     621 [ #  # ][ #  # ]:          0 :                     rCanvas->getUNOCanvas()->getDevice(),
     622 [ #  # ][ #  # ]:          0 :                     aPoly );
         [ #  # ][ #  # ]
     623                 :          0 :             }
     624                 :            : 
     625                 :            : 
     626                 :            :             // -------------------------------------------------------------------------
     627                 :            : 
     628 [ #  # ][ #  # ]:          0 :             class TextAction : public Action, private ::boost::noncopyable
                 [ #  # ]
     629                 :            :             {
     630                 :            :             public:
     631                 :            :                 TextAction( const ::basegfx::B2DPoint&  rStartPoint,
     632                 :            :                             const ::rtl::OUString&      rString,
     633                 :            :                             sal_Int32                   nStartPos,
     634                 :            :                             sal_Int32                   nLen,
     635                 :            :                             const CanvasSharedPtr&      rCanvas,
     636                 :            :                             const OutDevState&          rState );
     637                 :            : 
     638                 :            :                 TextAction( const ::basegfx::B2DPoint&      rStartPoint,
     639                 :            :                             const ::rtl::OUString&          rString,
     640                 :            :                             sal_Int32                       nStartPos,
     641                 :            :                             sal_Int32                       nLen,
     642                 :            :                             const CanvasSharedPtr&          rCanvas,
     643                 :            :                             const OutDevState&              rState,
     644                 :            :                             const ::basegfx::B2DHomMatrix&  rTextTransform );
     645                 :            : 
     646                 :            :                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
     647                 :            :                 virtual bool renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
     648                 :            :                                            const Subset&                  rSubset ) const;
     649                 :            : 
     650                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
     651                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
     652                 :            :                                                        const Subset&                    rSubset ) const;
     653                 :            : 
     654                 :            :                 virtual sal_Int32 getActionCount() const;
     655                 :            : 
     656                 :            :             private:
     657                 :            :                 // TODO(P2): This is potentially a real mass object
     658                 :            :                 // (every character might be a separate TextAction),
     659                 :            :                 // thus, make it as lightweight as possible. For
     660                 :            :                 // example, share common RenderState among several
     661                 :            :                 // TextActions, maybe using maOffsets for the
     662                 :            :                 // translation.
     663                 :            : 
     664                 :            :                 uno::Reference< rendering::XCanvasFont >    mxFont;
     665                 :            :                 const rendering::StringContext              maStringContext;
     666                 :            :                 const CanvasSharedPtr                       mpCanvas;
     667                 :            :                 rendering::RenderState                      maState;
     668                 :            :                 const sal_Int8                              maTextDirection;
     669                 :            :             };
     670                 :            : 
     671                 :          0 :             TextAction::TextAction( const ::basegfx::B2DPoint&  rStartPoint,
     672                 :            :                                     const ::rtl::OUString&      rString,
     673                 :            :                                     sal_Int32                   nStartPos,
     674                 :            :                                     sal_Int32                   nLen,
     675                 :            :                                     const CanvasSharedPtr&      rCanvas,
     676                 :            :                                     const OutDevState&          rState  ) :
     677                 :            :                 mxFont( rState.xFont ),
     678                 :            :                 maStringContext( rString, nStartPos, nLen ),
     679                 :            :                 mpCanvas( rCanvas ),
     680                 :            :                 maState(),
     681 [ #  # ][ #  # ]:          0 :                 maTextDirection( rState.textDirection )
     682                 :            :             {
     683                 :            :                 init( maState, mxFont,
     684                 :            :                       rStartPoint,
     685         [ #  # ]:          0 :                       rState, rCanvas );
     686                 :            : 
     687 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( mxFont.is(),
         [ #  # ][ #  # ]
     688                 :            :                                   "::cppcanvas::internal::TextAction(): Invalid font" );
     689                 :          0 :             }
     690                 :            : 
     691                 :          0 :             TextAction::TextAction( const ::basegfx::B2DPoint&      rStartPoint,
     692                 :            :                                     const ::rtl::OUString&          rString,
     693                 :            :                                     sal_Int32                       nStartPos,
     694                 :            :                                     sal_Int32                       nLen,
     695                 :            :                                     const CanvasSharedPtr&          rCanvas,
     696                 :            :                                     const OutDevState&              rState,
     697                 :            :                                     const ::basegfx::B2DHomMatrix&  rTextTransform ) :
     698                 :            :                 mxFont( rState.xFont ),
     699                 :            :                 maStringContext( rString, nStartPos, nLen ),
     700                 :            :                 mpCanvas( rCanvas ),
     701                 :            :                 maState(),
     702 [ #  # ][ #  # ]:          0 :                 maTextDirection( rState.textDirection )
     703                 :            :             {
     704                 :            :                 init( maState, mxFont,
     705                 :            :                       rStartPoint,
     706         [ #  # ]:          0 :                       rState, rCanvas, rTextTransform );
     707                 :            : 
     708 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( mxFont.is(),
         [ #  # ][ #  # ]
     709                 :            :                                   "::cppcanvas::internal::TextAction(): Invalid font" );
     710                 :          0 :             }
     711                 :            : 
     712                 :          0 :             bool TextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
     713                 :            :             {
     714                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextAction::render()" );
     715                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextAction: 0x%X", this );
     716                 :            : 
     717         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
     718         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
     719                 :            : 
     720 [ #  # ][ #  # ]:          0 :                 mpCanvas->getUNOCanvas()->drawText( maStringContext, mxFont,
     721 [ #  # ][ #  # ]:          0 :                                                     mpCanvas->getViewState(), aLocalState, maTextDirection );
                 [ #  # ]
     722                 :            : 
     723         [ #  # ]:          0 :                 return true;
     724                 :            :             }
     725                 :            : 
     726                 :          0 :             bool TextAction::renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
     727                 :            :                                            const Subset&                  /*rSubset*/ ) const
     728                 :            :             {
     729                 :            :                 OSL_FAIL( "TextAction::renderSubset(): Subset not supported by this object" );
     730                 :            : 
     731                 :            :                 // TODO(P1): Retrieve necessary font metric info for
     732                 :            :                 // TextAction from XCanvas. Currently, the
     733                 :            :                 // TextActionFactory does not generate this object for
     734                 :            :                 // _subsettable_ text
     735                 :          0 :                 return render( rTransformation );
     736                 :            :             }
     737                 :            : 
     738                 :          0 :             ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
     739                 :            :             {
     740                 :            :                 // create XTextLayout, to have the
     741                 :            :                 // XTextLayout::queryTextBounds() method available
     742                 :            :                 uno::Reference< rendering::XTextLayout > xTextLayout(
     743         [ #  # ]:          0 :                     mxFont->createTextLayout(
     744                 :            :                         maStringContext,
     745                 :            :                         maTextDirection,
     746         [ #  # ]:          0 :                         0 ) );
     747                 :            : 
     748         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
     749         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
     750                 :            : 
     751                 :            :                 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
     752 [ #  # ][ #  # ]:          0 :                                                          xTextLayout->queryTextBounds() ),
     753                 :          0 :                                                      mpCanvas->getViewState(),
     754 [ #  # ][ #  # ]:          0 :                                                      aLocalState );
         [ #  # ][ #  # ]
                 [ #  # ]
     755                 :            :             }
     756                 :            : 
     757                 :          0 :             ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
     758                 :            :                                                        const Subset&                    /*rSubset*/ ) const
     759                 :            :             {
     760                 :            :                 OSL_FAIL( "TextAction::getBounds(): Subset not supported by this object" );
     761                 :            : 
     762                 :            :                 // TODO(P1): Retrieve necessary font metric info for
     763                 :            :                 // TextAction from XCanvas. Currently, the
     764                 :            :                 // TextActionFactory does not generate this object for
     765                 :            :                 // _subsettable_ text
     766                 :          0 :                 return getBounds( rTransformation );
     767                 :            :             }
     768                 :            : 
     769                 :          0 :             sal_Int32 TextAction::getActionCount() const
     770                 :            :             {
     771                 :            :                 // TODO(P1): Retrieve necessary font metric info for
     772                 :            :                 // TextAction from XCanvas. Currently, the
     773                 :            :                 // TextActionFactory does not generate this object for
     774                 :            :                 // _subsettable_ text
     775                 :          0 :                 return 1;
     776                 :            :             }
     777                 :            : 
     778                 :            : 
     779                 :            :             // -------------------------------------------------------------------------
     780                 :            : 
     781 [ #  # ][ #  # ]:          0 :             class EffectTextAction :
                 [ #  # ]
     782                 :            :                 public Action,
     783                 :            :                 public TextRenderer,
     784                 :            :                 private ::boost::noncopyable
     785                 :            :             {
     786                 :            :             public:
     787                 :            :                 EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
     788                 :            :                                   const ::basegfx::B2DSize&  rReliefOffset,
     789                 :            :                                   const ::Color&             rReliefColor,
     790                 :            :                                   const ::basegfx::B2DSize&  rShadowOffset,
     791                 :            :                                   const ::Color&             rShadowColor,
     792                 :            :                                   const ::rtl::OUString&     rText,
     793                 :            :                                   sal_Int32                  nStartPos,
     794                 :            :                                   sal_Int32                  nLen,
     795                 :            :                                   VirtualDevice&             rVDev,
     796                 :            :                                   const CanvasSharedPtr&     rCanvas,
     797                 :            :                                   const OutDevState&         rState );
     798                 :            : 
     799                 :            :                 EffectTextAction( const ::basegfx::B2DPoint&        rStartPoint,
     800                 :            :                                   const ::basegfx::B2DSize&         rReliefOffset,
     801                 :            :                                   const ::Color&                    rReliefColor,
     802                 :            :                                   const ::basegfx::B2DSize&         rShadowOffset,
     803                 :            :                                   const ::Color&                    rShadowColor,
     804                 :            :                                   const ::rtl::OUString&            rText,
     805                 :            :                                   sal_Int32                         nStartPos,
     806                 :            :                                   sal_Int32                         nLen,
     807                 :            :                                   VirtualDevice&                    rVDev,
     808                 :            :                                   const CanvasSharedPtr&            rCanvas,
     809                 :            :                                   const OutDevState&                rState,
     810                 :            :                                   const ::basegfx::B2DHomMatrix&    rTextTransform );
     811                 :            : 
     812                 :            :                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
     813                 :            :                 virtual bool renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
     814                 :            :                                            const Subset&                  rSubset ) const;
     815                 :            : 
     816                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
     817                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
     818                 :            :                                                        const Subset&                    rSubset ) const;
     819                 :            : 
     820                 :            :                 virtual sal_Int32 getActionCount() const;
     821                 :            : 
     822                 :            :             private:
     823                 :            :                 /// Interface TextRenderer
     824                 :            :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const;
     825                 :            : 
     826                 :            :                 // TODO(P2): This is potentially a real mass object
     827                 :            :                 // (every character might be a separate TextAction),
     828                 :            :                 // thus, make it as lightweight as possible. For
     829                 :            :                 // example, share common RenderState among several
     830                 :            :                 // TextActions, maybe using maOffsets for the
     831                 :            :                 // translation.
     832                 :            : 
     833                 :            :                 uno::Reference< rendering::XCanvasFont >    mxFont;
     834                 :            :                 const rendering::StringContext              maStringContext;
     835                 :            :                 const CanvasSharedPtr                       mpCanvas;
     836                 :            :                 rendering::RenderState                      maState;
     837                 :            :                 const tools::TextLineInfo                   maTextLineInfo;
     838                 :            :                 ::basegfx::B2DSize                          maLinesOverallSize;
     839                 :            :                 const double                                mnLineWidth;
     840                 :            :                 uno::Reference< rendering::XPolyPolygon2D > mxTextLines;
     841                 :            :                 const ::basegfx::B2DSize                    maReliefOffset;
     842                 :            :                 const ::Color                               maReliefColor;
     843                 :            :                 const ::basegfx::B2DSize                    maShadowOffset;
     844                 :            :                 const ::Color                               maShadowColor;
     845                 :            :                 const sal_Int8                              maTextDirection;
     846                 :            :             };
     847                 :            : 
     848                 :          0 :             EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
     849                 :            :                                                 const ::basegfx::B2DSize&  rReliefOffset,
     850                 :            :                                                 const ::Color&             rReliefColor,
     851                 :            :                                                 const ::basegfx::B2DSize&  rShadowOffset,
     852                 :            :                                                 const ::Color&             rShadowColor,
     853                 :            :                                                 const ::rtl::OUString&     rText,
     854                 :            :                                                 sal_Int32                  nStartPos,
     855                 :            :                                                 sal_Int32                  nLen,
     856                 :            :                                                 VirtualDevice&             rVDev,
     857                 :            :                                                 const CanvasSharedPtr&     rCanvas,
     858                 :            :                                                 const OutDevState&         rState ) :
     859                 :            :                 mxFont( rState.xFont ),
     860                 :            :                 maStringContext( rText, nStartPos, nLen ),
     861                 :            :                 mpCanvas( rCanvas ),
     862                 :            :                 maState(),
     863                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
     864                 :            :                 maLinesOverallSize(),
     865         [ #  # ]:          0 :                 mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
     866                 :            :                 mxTextLines(),
     867                 :            :                 maReliefOffset( rReliefOffset ),
     868                 :            :                 maReliefColor( rReliefColor ),
     869                 :            :                 maShadowOffset( rShadowOffset ),
     870                 :            :                 maShadowColor( rShadowColor ),
     871 [ #  # ][ #  # ]:          0 :                 maTextDirection( rState.textDirection )
                 [ #  # ]
     872                 :            :             {
     873                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
     874                 :            :                                            mxTextLines,
     875                 :            :                                            rCanvas,
     876                 :            :                                            mnLineWidth,
     877         [ #  # ]:          0 :                                            maTextLineInfo );
     878                 :            : 
     879                 :            :                 init( maState, mxFont,
     880                 :            :                       rStartPoint,
     881         [ #  # ]:          0 :                       rState, rCanvas );
     882                 :            : 
     883 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     884                 :            :                                   "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
     885                 :          0 :             }
     886                 :            : 
     887                 :          0 :             EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint&      rStartPoint,
     888                 :            :                                                 const ::basegfx::B2DSize&       rReliefOffset,
     889                 :            :                                                 const ::Color&                  rReliefColor,
     890                 :            :                                                 const ::basegfx::B2DSize&       rShadowOffset,
     891                 :            :                                                 const ::Color&                  rShadowColor,
     892                 :            :                                                 const ::rtl::OUString&          rText,
     893                 :            :                                                 sal_Int32                       nStartPos,
     894                 :            :                                                 sal_Int32                       nLen,
     895                 :            :                                                 VirtualDevice&                  rVDev,
     896                 :            :                                                 const CanvasSharedPtr&          rCanvas,
     897                 :            :                                                 const OutDevState&              rState,
     898                 :            :                                                 const ::basegfx::B2DHomMatrix&  rTextTransform ) :
     899                 :            :                 mxFont( rState.xFont ),
     900                 :            :                 maStringContext( rText, nStartPos, nLen ),
     901                 :            :                 mpCanvas( rCanvas ),
     902                 :            :                 maState(),
     903                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
     904                 :            :                 maLinesOverallSize(),
     905         [ #  # ]:          0 :                 mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
     906                 :            :                 mxTextLines(),
     907                 :            :                 maReliefOffset( rReliefOffset ),
     908                 :            :                 maReliefColor( rReliefColor ),
     909                 :            :                 maShadowOffset( rShadowOffset ),
     910                 :            :                 maShadowColor( rShadowColor ),
     911 [ #  # ][ #  # ]:          0 :                 maTextDirection( rState.textDirection )
                 [ #  # ]
     912                 :            :             {
     913                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
     914                 :            :                                            mxTextLines,
     915                 :            :                                            rCanvas,
     916                 :            :                                            mnLineWidth,
     917         [ #  # ]:          0 :                                            maTextLineInfo );
     918                 :            : 
     919                 :            :                 init( maState, mxFont,
     920                 :            :                       rStartPoint,
     921         [ #  # ]:          0 :                       rState, rCanvas, rTextTransform );
     922                 :            : 
     923 [ #  # ][ #  # ]:          0 :                 ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     924                 :            :                                   "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
     925                 :          0 :             }
     926                 :            : 
     927                 :          0 :             bool EffectTextAction::operator()( const rendering::RenderState& rRenderState ) const
     928                 :            :             {
     929                 :          0 :                 const rendering::ViewState& rViewState( mpCanvas->getViewState() );
     930         [ #  # ]:          0 :                 const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
     931                 :            : 
     932         [ #  # ]:          0 :                 rCanvas->fillPolyPolygon( mxTextLines,
     933                 :            :                                           rViewState,
     934         [ #  # ]:          0 :                                           rRenderState );
     935                 :            : 
     936         [ #  # ]:          0 :                 rCanvas->drawText( maStringContext, mxFont,
     937                 :            :                                    rViewState,
     938                 :            :                                    rRenderState,
     939         [ #  # ]:          0 :                                    maTextDirection );
     940                 :            : 
     941                 :          0 :                 return true;
     942                 :            :             }
     943                 :            : 
     944                 :          0 :             bool EffectTextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
     945                 :            :             {
     946                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextAction::render()" );
     947                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextAction: 0x%X", this );
     948                 :            : 
     949         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
     950         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
     951                 :            : 
     952                 :            :                 return renderEffectText( *this,
     953                 :            :                                          aLocalState,
     954                 :          0 :                                          mpCanvas->getViewState(),
     955                 :          0 :                                          mpCanvas->getUNOCanvas(),
     956                 :            :                                          maShadowColor,
     957                 :            :                                          maShadowOffset,
     958                 :            :                                          maReliefColor,
     959 [ #  # ][ #  # ]:          0 :                                          maReliefOffset );
                 [ #  # ]
           [ #  #  #  # ]
     960                 :            :             }
     961                 :            : 
     962                 :          0 :             bool EffectTextAction::renderSubset( const ::basegfx::B2DHomMatrix&   rTransformation,
     963                 :            :                                                  const Subset&                    /*rSubset*/ ) const
     964                 :            :             {
     965                 :            :                 OSL_FAIL( "EffectTextAction::renderSubset(): Subset not supported by this object" );
     966                 :            : 
     967                 :            :                 // TODO(P1): Retrieve necessary font metric info for
     968                 :            :                 // TextAction from XCanvas. Currently, the
     969                 :            :                 // TextActionFactory does not generate this object for
     970                 :            :                 // subsettable text
     971                 :          0 :                 return render( rTransformation );
     972                 :            :             }
     973                 :            : 
     974                 :          0 :             ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
     975                 :            :             {
     976                 :            :                 // create XTextLayout, to have the
     977                 :            :                 // XTextLayout::queryTextBounds() method available
     978                 :            :                 uno::Reference< rendering::XTextLayout > xTextLayout(
     979         [ #  # ]:          0 :                     mxFont->createTextLayout(
     980                 :            :                         maStringContext,
     981                 :            :                         maTextDirection,
     982         [ #  # ]:          0 :                         0 ) );
     983                 :            : 
     984         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
     985         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
     986                 :            : 
     987                 :            :                 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
     988 [ #  # ][ #  # ]:          0 :                                                  xTextLayout->queryTextBounds() ),
     989                 :            :                                              ::basegfx::B2DRange( 0,0,
     990                 :            :                                                                   maLinesOverallSize.getX(),
     991                 :            :                                                                   maLinesOverallSize.getY() ),
     992                 :            :                                              maReliefOffset,
     993                 :            :                                              maShadowOffset,
     994                 :            :                                              aLocalState,
     995 [ #  # ][ #  # ]:          0 :                                              mpCanvas->getViewState() );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     996                 :            :             }
     997                 :            : 
     998                 :          0 :             ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
     999                 :            :                                                              const Subset&                  /*rSubset*/ ) const
    1000                 :            :             {
    1001                 :            :                 OSL_FAIL( "EffectTextAction::getBounds(): Subset not supported by this object" );
    1002                 :            : 
    1003                 :            :                 // TODO(P1): Retrieve necessary font metric info for
    1004                 :            :                 // TextAction from XCanvas. Currently, the
    1005                 :            :                 // TextActionFactory does not generate this object for
    1006                 :            :                 // _subsettable_ text
    1007                 :          0 :                 return getBounds( rTransformation );
    1008                 :            :             }
    1009                 :            : 
    1010                 :          0 :             sal_Int32 EffectTextAction::getActionCount() const
    1011                 :            :             {
    1012                 :            :                 // TODO(P1): Retrieve necessary font metric info for
    1013                 :            :                 // TextAction from XCanvas. Currently, the
    1014                 :            :                 // TextActionFactory does not generate this object for
    1015                 :            :                 // subsettable text
    1016                 :          0 :                 return 1;
    1017                 :            :             }
    1018                 :            : 
    1019                 :            : 
    1020                 :            :             // -------------------------------------------------------------------------
    1021                 :            : 
    1022 [ #  # ][ #  # ]:          0 :             class TextArrayAction : public Action, private ::boost::noncopyable
                 [ #  # ]
    1023                 :            :             {
    1024                 :            :             public:
    1025                 :            :                 TextArrayAction( const ::basegfx::B2DPoint&     rStartPoint,
    1026                 :            :                                  const ::rtl::OUString&         rString,
    1027                 :            :                                  sal_Int32                      nStartPos,
    1028                 :            :                                  sal_Int32                      nLen,
    1029                 :            :                                  const uno::Sequence< double >& rOffsets,
    1030                 :            :                                  const CanvasSharedPtr&         rCanvas,
    1031                 :            :                                  const OutDevState&             rState );
    1032                 :            : 
    1033                 :            :                 TextArrayAction( const ::basegfx::B2DPoint&     rStartPoint,
    1034                 :            :                                  const ::rtl::OUString&         rString,
    1035                 :            :                                  sal_Int32                      nStartPos,
    1036                 :            :                                  sal_Int32                      nLen,
    1037                 :            :                                  const uno::Sequence< double >& rOffsets,
    1038                 :            :                                  const CanvasSharedPtr&         rCanvas,
    1039                 :            :                                  const OutDevState&             rState,
    1040                 :            :                                  const ::basegfx::B2DHomMatrix& rTextTransform );
    1041                 :            : 
    1042                 :            :                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1043                 :            :                 virtual bool renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
    1044                 :            :                                            const Subset&                  rSubset ) const;
    1045                 :            : 
    1046                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1047                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
    1048                 :            :                                                        const Subset&                    rSubset ) const;
    1049                 :            : 
    1050                 :            :                 virtual sal_Int32 getActionCount() const;
    1051                 :            : 
    1052                 :            :             private:
    1053                 :            :                 // TODO(P2): This is potentially a real mass object
    1054                 :            :                 // (every character might be a separate TextAction),
    1055                 :            :                 // thus, make it as lightweight as possible. For
    1056                 :            :                 // example, share common RenderState among several
    1057                 :            :                 // TextActions, maybe using maOffsets for the
    1058                 :            :                 // translation.
    1059                 :            : 
    1060                 :            :                 uno::Reference< rendering::XTextLayout >    mxTextLayout;
    1061                 :            :                 const CanvasSharedPtr                       mpCanvas;
    1062                 :            :                 rendering::RenderState                      maState;
    1063                 :            :             };
    1064                 :            : 
    1065                 :          0 :             TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint&        rStartPoint,
    1066                 :            :                                               const ::rtl::OUString&            rString,
    1067                 :            :                                               sal_Int32                         nStartPos,
    1068                 :            :                                               sal_Int32                         nLen,
    1069                 :            :                                               const uno::Sequence< double >&    rOffsets,
    1070                 :            :                                               const CanvasSharedPtr&            rCanvas,
    1071                 :            :                                               const OutDevState&                rState ) :
    1072                 :            :                 mxTextLayout(),
    1073                 :            :                 mpCanvas( rCanvas ),
    1074 [ #  # ][ #  # ]:          0 :                 maState()
    1075                 :            :             {
    1076                 :            :                 initArrayAction( maState,
    1077                 :            :                                  mxTextLayout,
    1078                 :            :                                  rStartPoint,
    1079                 :            :                                  rString,
    1080                 :            :                                  nStartPos,
    1081                 :            :                                  nLen,
    1082                 :            :                                  rOffsets,
    1083                 :            :                                  rCanvas,
    1084         [ #  # ]:          0 :                                  rState, NULL );
    1085                 :          0 :             }
    1086                 :            : 
    1087                 :          0 :             TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint&        rStartPoint,
    1088                 :            :                                               const ::rtl::OUString&            rString,
    1089                 :            :                                               sal_Int32                         nStartPos,
    1090                 :            :                                               sal_Int32                         nLen,
    1091                 :            :                                               const uno::Sequence< double >&    rOffsets,
    1092                 :            :                                               const CanvasSharedPtr&            rCanvas,
    1093                 :            :                                               const OutDevState&                rState,
    1094                 :            :                                               const ::basegfx::B2DHomMatrix&    rTextTransform ) :
    1095                 :            :                 mxTextLayout(),
    1096                 :            :                 mpCanvas( rCanvas ),
    1097 [ #  # ][ #  # ]:          0 :                 maState()
    1098                 :            :             {
    1099                 :            :                 initArrayAction( maState,
    1100                 :            :                                  mxTextLayout,
    1101                 :            :                                  rStartPoint,
    1102                 :            :                                  rString,
    1103                 :            :                                  nStartPos,
    1104                 :            :                                  nLen,
    1105                 :            :                                  rOffsets,
    1106                 :            :                                  rCanvas,
    1107                 :            :                                  rState,
    1108         [ #  # ]:          0 :                                  &rTextTransform );
    1109                 :          0 :             }
    1110                 :            : 
    1111                 :          0 :             bool TextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1112                 :            :             {
    1113                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::render()" );
    1114                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
    1115                 :            : 
    1116         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1117         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1118                 :            : 
    1119 [ #  # ][ #  # ]:          0 :                 mpCanvas->getUNOCanvas()->drawTextLayout( mxTextLayout,
    1120                 :          0 :                                                           mpCanvas->getViewState(),
    1121 [ #  # ][ #  # ]:          0 :                                                           aLocalState );
                 [ #  # ]
    1122                 :            : 
    1123         [ #  # ]:          0 :                 return true;
    1124                 :            :             }
    1125                 :            : 
    1126                 :          0 :             bool TextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix&    rTransformation,
    1127                 :            :                                                 const Subset&                     rSubset ) const
    1128                 :            :             {
    1129                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::renderSubset()" );
    1130                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
    1131                 :            : 
    1132         [ #  # ]:          0 :                 rendering::RenderState                      aLocalState( maState );
    1133                 :          0 :                 uno::Reference< rendering::XTextLayout >    xTextLayout( mxTextLayout );
    1134                 :            : 
    1135                 :            :                 double nDummy0, nDummy1;
    1136                 :            :                 createSubsetLayout( xTextLayout,
    1137                 :            :                                     aLocalState,
    1138                 :            :                                     nDummy0,
    1139                 :            :                                     nDummy1,
    1140                 :            :                                     rTransformation,
    1141         [ #  # ]:          0 :                                     rSubset );
    1142                 :            : 
    1143         [ #  # ]:          0 :                 if( !xTextLayout.is() )
    1144                 :          0 :                     return true; // empty layout, render nothing
    1145                 :            : 
    1146 [ #  # ][ #  # ]:          0 :                 mpCanvas->getUNOCanvas()->drawTextLayout( xTextLayout,
    1147                 :          0 :                                                           mpCanvas->getViewState(),
    1148 [ #  # ][ #  # ]:          0 :                                                           aLocalState );
                 [ #  # ]
    1149                 :            : 
    1150         [ #  # ]:          0 :                 return true;
    1151                 :            :             }
    1152                 :            : 
    1153                 :          0 :             ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1154                 :            :             {
    1155         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1156         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1157                 :            : 
    1158                 :            :                 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
    1159 [ #  # ][ #  # ]:          0 :                                                          mxTextLayout->queryTextBounds() ),
    1160                 :          0 :                                                      mpCanvas->getViewState(),
    1161 [ #  # ][ #  # ]:          0 :                                                      aLocalState );
         [ #  # ][ #  # ]
                 [ #  # ]
    1162                 :            :             }
    1163                 :            : 
    1164                 :          0 :             ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix&  rTransformation,
    1165                 :            :                                                             const Subset&                   rSubset ) const
    1166                 :            :             {
    1167                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
    1168                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
    1169                 :            : 
    1170         [ #  # ]:          0 :                 rendering::RenderState                      aLocalState( maState );
    1171                 :          0 :                 uno::Reference< rendering::XTextLayout >    xTextLayout( mxTextLayout );
    1172                 :            : 
    1173                 :            :                 double nDummy0, nDummy1;
    1174                 :            :                 createSubsetLayout( xTextLayout,
    1175                 :            :                                     aLocalState,
    1176                 :            :                                     nDummy0,
    1177                 :            :                                     nDummy1,
    1178                 :            :                                     rTransformation,
    1179         [ #  # ]:          0 :                                     rSubset );
    1180                 :            : 
    1181         [ #  # ]:          0 :                 if( !xTextLayout.is() )
    1182         [ #  # ]:          0 :                     return ::basegfx::B2DRange(); // empty layout, empty bounds
    1183                 :            : 
    1184                 :            :                 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
    1185 [ #  # ][ #  # ]:          0 :                                                          xTextLayout->queryTextBounds() ),
    1186                 :          0 :                                                      mpCanvas->getViewState(),
    1187 [ #  # ][ #  # ]:          0 :                                                      aLocalState );
         [ #  # ][ #  # ]
                 [ #  # ]
    1188                 :            :             }
    1189                 :            : 
    1190                 :          0 :             sal_Int32 TextArrayAction::getActionCount() const
    1191                 :            :             {
    1192                 :          0 :                 const rendering::StringContext& rOrigContext( mxTextLayout->getText() );
    1193                 :            : 
    1194                 :          0 :                 return rOrigContext.Length;
    1195                 :            :             }
    1196                 :            : 
    1197                 :            : 
    1198                 :            :             // -------------------------------------------------------------------------
    1199                 :            : 
    1200 [ #  # ][ #  # ]:          0 :             class EffectTextArrayAction :
                 [ #  # ]
    1201                 :            :                 public Action,
    1202                 :            :                 public TextRenderer,
    1203                 :            :                 private ::boost::noncopyable
    1204                 :            :             {
    1205                 :            :             public:
    1206                 :            :                 EffectTextArrayAction( const ::basegfx::B2DPoint&       rStartPoint,
    1207                 :            :                                        const ::basegfx::B2DSize&        rReliefOffset,
    1208                 :            :                                        const ::Color&                   rReliefColor,
    1209                 :            :                                        const ::basegfx::B2DSize&        rShadowOffset,
    1210                 :            :                                        const ::Color&                   rShadowColor,
    1211                 :            :                                        const ::rtl::OUString&           rText,
    1212                 :            :                                        sal_Int32                        nStartPos,
    1213                 :            :                                        sal_Int32                        nLen,
    1214                 :            :                                        const uno::Sequence< double >&   rOffsets,
    1215                 :            :                                        VirtualDevice&                   rVDev,
    1216                 :            :                                        const CanvasSharedPtr&           rCanvas,
    1217                 :            :                                        const OutDevState&               rState  );
    1218                 :            :                 EffectTextArrayAction( const ::basegfx::B2DPoint&       rStartPoint,
    1219                 :            :                                        const ::basegfx::B2DSize&        rReliefOffset,
    1220                 :            :                                        const ::Color&                   rReliefColor,
    1221                 :            :                                        const ::basegfx::B2DSize&        rShadowOffset,
    1222                 :            :                                        const ::Color&                   rShadowColor,
    1223                 :            :                                        const ::rtl::OUString&           rText,
    1224                 :            :                                        sal_Int32                        nStartPos,
    1225                 :            :                                        sal_Int32                        nLen,
    1226                 :            :                                        const uno::Sequence< double >&   rOffsets,
    1227                 :            :                                        VirtualDevice&                   rVDev,
    1228                 :            :                                        const CanvasSharedPtr&           rCanvas,
    1229                 :            :                                        const OutDevState&               rState,
    1230                 :            :                                        const ::basegfx::B2DHomMatrix&   rTextTransform );
    1231                 :            : 
    1232                 :            :                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1233                 :            :                 virtual bool renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
    1234                 :            :                                            const Subset&                  rSubset ) const;
    1235                 :            : 
    1236                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1237                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
    1238                 :            :                                                        const Subset&                    rSubset ) const;
    1239                 :            : 
    1240                 :            :                 virtual sal_Int32 getActionCount() const;
    1241                 :            : 
    1242                 :            :             private:
    1243                 :            :                 // TextRenderer interface
    1244                 :            :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const;
    1245                 :            : 
    1246                 :            :                 // TODO(P2): This is potentially a real mass object
    1247                 :            :                 // (every character might be a separate TextAction),
    1248                 :            :                 // thus, make it as lightweight as possible. For
    1249                 :            :                 // example, share common RenderState among several
    1250                 :            :                 // TextActions, maybe using maOffsets for the
    1251                 :            :                 // translation.
    1252                 :            : 
    1253                 :            :                 uno::Reference< rendering::XTextLayout >        mxTextLayout;
    1254                 :            :                 const CanvasSharedPtr                           mpCanvas;
    1255                 :            :                 rendering::RenderState                          maState;
    1256                 :            :                 const tools::TextLineInfo                       maTextLineInfo;
    1257                 :            :                 ::basegfx::B2DSize                              maLinesOverallSize;
    1258                 :            :                 uno::Reference< rendering::XPolyPolygon2D >     mxTextLines;
    1259                 :            :                 const ::basegfx::B2DSize                        maReliefOffset;
    1260                 :            :                 const ::Color                                   maReliefColor;
    1261                 :            :                 const ::basegfx::B2DSize                        maShadowOffset;
    1262                 :            :                 const ::Color                                   maShadowColor;
    1263                 :            :             };
    1264                 :            : 
    1265                 :          0 :             EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint&        rStartPoint,
    1266                 :            :                                                           const ::basegfx::B2DSize&         rReliefOffset,
    1267                 :            :                                                           const ::Color&                    rReliefColor,
    1268                 :            :                                                           const ::basegfx::B2DSize&         rShadowOffset,
    1269                 :            :                                                           const ::Color&                    rShadowColor,
    1270                 :            :                                                           const ::rtl::OUString&            rText,
    1271                 :            :                                                           sal_Int32                         nStartPos,
    1272                 :            :                                                           sal_Int32                         nLen,
    1273                 :            :                                                           const uno::Sequence< double >&    rOffsets,
    1274                 :            :                                                           VirtualDevice&                    rVDev,
    1275                 :            :                                                           const CanvasSharedPtr&            rCanvas,
    1276                 :            :                                                           const OutDevState&                rState  ) :
    1277                 :            :                 mxTextLayout(),
    1278                 :            :                 mpCanvas( rCanvas ),
    1279                 :            :                 maState(),
    1280                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
    1281                 :            :                 maLinesOverallSize(),
    1282                 :            :                 mxTextLines(),
    1283                 :            :                 maReliefOffset( rReliefOffset ),
    1284                 :            :                 maReliefColor( rReliefColor ),
    1285                 :            :                 maShadowOffset( rShadowOffset ),
    1286 [ #  # ][ #  # ]:          0 :                 maShadowColor( rShadowColor )
                 [ #  # ]
    1287                 :            :             {
    1288                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
    1289                 :            :                                            mxTextLines,
    1290                 :            :                                            rCanvas,
    1291                 :            :                                            rOffsets,
    1292         [ #  # ]:          0 :                                            maTextLineInfo );
    1293                 :            : 
    1294                 :            :                 initArrayAction( maState,
    1295                 :            :                                  mxTextLayout,
    1296                 :            :                                  rStartPoint,
    1297                 :            :                                  rText,
    1298                 :            :                                  nStartPos,
    1299                 :            :                                  nLen,
    1300                 :            :                                  rOffsets,
    1301                 :            :                                  rCanvas,
    1302         [ #  # ]:          0 :                                  rState, NULL );
    1303                 :          0 :             }
    1304                 :            : 
    1305                 :          0 :             EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint&        rStartPoint,
    1306                 :            :                                                           const ::basegfx::B2DSize&         rReliefOffset,
    1307                 :            :                                                           const ::Color&                    rReliefColor,
    1308                 :            :                                                           const ::basegfx::B2DSize&         rShadowOffset,
    1309                 :            :                                                           const ::Color&                    rShadowColor,
    1310                 :            :                                                           const ::rtl::OUString&            rText,
    1311                 :            :                                                           sal_Int32                         nStartPos,
    1312                 :            :                                                           sal_Int32                         nLen,
    1313                 :            :                                                           const uno::Sequence< double >&    rOffsets,
    1314                 :            :                                                           VirtualDevice&                    rVDev,
    1315                 :            :                                                           const CanvasSharedPtr&            rCanvas,
    1316                 :            :                                                           const OutDevState&                rState,
    1317                 :            :                                                           const ::basegfx::B2DHomMatrix&    rTextTransform ) :
    1318                 :            :                 mxTextLayout(),
    1319                 :            :                 mpCanvas( rCanvas ),
    1320                 :            :                 maState(),
    1321                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
    1322                 :            :                 maLinesOverallSize(),
    1323                 :            :                 mxTextLines(),
    1324                 :            :                 maReliefOffset( rReliefOffset ),
    1325                 :            :                 maReliefColor( rReliefColor ),
    1326                 :            :                 maShadowOffset( rShadowOffset ),
    1327 [ #  # ][ #  # ]:          0 :                 maShadowColor( rShadowColor )
                 [ #  # ]
    1328                 :            :             {
    1329                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
    1330                 :            :                                            mxTextLines,
    1331                 :            :                                            rCanvas,
    1332                 :            :                                            rOffsets,
    1333         [ #  # ]:          0 :                                            maTextLineInfo );
    1334                 :            : 
    1335                 :            :                 initArrayAction( maState,
    1336                 :            :                                  mxTextLayout,
    1337                 :            :                                  rStartPoint,
    1338                 :            :                                  rText,
    1339                 :            :                                  nStartPos,
    1340                 :            :                                  nLen,
    1341                 :            :                                  rOffsets,
    1342                 :            :                                  rCanvas,
    1343                 :            :                                  rState,
    1344         [ #  # ]:          0 :                                  &rTextTransform );
    1345                 :          0 :             }
    1346                 :            : 
    1347                 :          0 :             bool EffectTextArrayAction::operator()( const rendering::RenderState& rRenderState ) const
    1348                 :            :             {
    1349                 :          0 :                 const rendering::ViewState& rViewState( mpCanvas->getViewState() );
    1350         [ #  # ]:          0 :                 const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
    1351                 :            : 
    1352         [ #  # ]:          0 :                 rCanvas->fillPolyPolygon( mxTextLines,
    1353                 :            :                                           rViewState,
    1354         [ #  # ]:          0 :                                           rRenderState );
    1355                 :            : 
    1356         [ #  # ]:          0 :                 rCanvas->drawTextLayout( mxTextLayout,
    1357                 :            :                                          rViewState,
    1358         [ #  # ]:          0 :                                          rRenderState );
    1359                 :            : 
    1360                 :          0 :                 return true;
    1361                 :            :             }
    1362                 :            : 
    1363                 :          0 :             bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1364                 :            :             {
    1365                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
    1366                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
    1367                 :            : 
    1368         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1369         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1370                 :            : 
    1371                 :            :                 return renderEffectText( *this,
    1372                 :            :                                          aLocalState,
    1373                 :          0 :                                          mpCanvas->getViewState(),
    1374                 :          0 :                                          mpCanvas->getUNOCanvas(),
    1375                 :            :                                          maShadowColor,
    1376                 :            :                                          maShadowOffset,
    1377                 :            :                                          maReliefColor,
    1378 [ #  # ][ #  # ]:          0 :                                          maReliefOffset );
                 [ #  # ]
           [ #  #  #  # ]
    1379                 :            :             }
    1380                 :            : 
    1381         [ #  # ]:          0 :             class EffectTextArrayRenderHelper : public TextRenderer
    1382                 :            :             {
    1383                 :            :             public:
    1384                 :          0 :                 EffectTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >&        rCanvas,
    1385                 :            :                                              const uno::Reference< rendering::XTextLayout >&    rTextLayout,
    1386                 :            :                                              const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
    1387                 :            :                                              const rendering::ViewState&                        rViewState ) :
    1388                 :            :                     mrCanvas( rCanvas ),
    1389                 :            :                     mrTextLayout( rTextLayout ),
    1390                 :            :                     mrLinePolygon( rLinePolygon ),
    1391                 :          0 :                     mrViewState( rViewState )
    1392                 :            :                 {
    1393                 :          0 :                 }
    1394                 :            : 
    1395                 :            :                 // TextRenderer interface
    1396                 :          0 :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const
    1397                 :            :                 {
    1398                 :          0 :                     mrCanvas->fillPolyPolygon( mrLinePolygon,
    1399                 :            :                                                mrViewState,
    1400                 :          0 :                                                rRenderState );
    1401                 :            : 
    1402                 :          0 :                     mrCanvas->drawTextLayout( mrTextLayout,
    1403                 :            :                                               mrViewState,
    1404                 :          0 :                                               rRenderState );
    1405                 :            : 
    1406                 :          0 :                     return true;
    1407                 :            :                 }
    1408                 :            : 
    1409                 :            :             private:
    1410                 :            :                 const uno::Reference< rendering::XCanvas >&         mrCanvas;
    1411                 :            :                 const uno::Reference< rendering::XTextLayout >&     mrTextLayout;
    1412                 :            :                 const uno::Reference< rendering::XPolyPolygon2D >&  mrLinePolygon;
    1413                 :            :                 const rendering::ViewState&                         mrViewState;
    1414                 :            :             };
    1415                 :            : 
    1416                 :          0 :             bool EffectTextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix&  rTransformation,
    1417                 :            :                                                       const Subset&                   rSubset ) const
    1418                 :            :             {
    1419                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::renderSubset()" );
    1420                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
    1421                 :            : 
    1422         [ #  # ]:          0 :                 rendering::RenderState                   aLocalState( maState );
    1423                 :          0 :                 uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
    1424 [ #  # ][ #  # ]:          0 :                 const geometry::RealRectangle2D          aTextBounds( mxTextLayout->queryTextBounds() );
    1425                 :            : 
    1426                 :          0 :                 double nMinPos(0.0);
    1427                 :          0 :                 double nMaxPos(aTextBounds.X2 - aTextBounds.X1);
    1428                 :            : 
    1429                 :            :                 createSubsetLayout( xTextLayout,
    1430                 :            :                                     aLocalState,
    1431                 :            :                                     nMinPos,
    1432                 :            :                                     nMaxPos,
    1433                 :            :                                     rTransformation,
    1434         [ #  # ]:          0 :                                     rSubset );
    1435                 :            : 
    1436         [ #  # ]:          0 :                 if( !xTextLayout.is() )
    1437                 :          0 :                     return true; // empty layout, render nothing
    1438                 :            : 
    1439                 :            : 
    1440                 :            :                 // create and setup local line polygon
    1441                 :            :                 // ===================================
    1442                 :            : 
    1443         [ #  # ]:          0 :                 uno::Reference< rendering::XCanvas > xCanvas( mpCanvas->getUNOCanvas() );
    1444         [ #  # ]:          0 :                 const rendering::ViewState&          rViewState( mpCanvas->getViewState() );
    1445                 :            : 
    1446                 :            :                 uno::Reference< rendering::XPolyPolygon2D > xTextLines(
    1447                 :            :                     ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
    1448         [ #  # ]:          0 :                         xCanvas->getDevice(),
    1449                 :            :                         tools::createTextLinesPolyPolygon(
    1450                 :            :                             0.0, nMaxPos - nMinPos,
    1451 [ #  # ][ #  # ]:          0 :                             maTextLineInfo ) ) );
         [ #  # ][ #  # ]
    1452                 :            : 
    1453                 :            : 
    1454                 :            :                 // render everything
    1455                 :            :                 // =================
    1456                 :            : 
    1457                 :            :                 return renderEffectText(
    1458                 :            :                     EffectTextArrayRenderHelper( xCanvas,
    1459                 :            :                                                  xTextLayout,
    1460                 :            :                                                  xTextLines,
    1461                 :            :                                                  rViewState ),
    1462                 :            :                     aLocalState,
    1463                 :            :                     rViewState,
    1464                 :            :                     xCanvas,
    1465                 :            :                     maShadowColor,
    1466                 :            :                     maShadowOffset,
    1467                 :            :                     maReliefColor,
    1468 [ #  # ][ #  # ]:          0 :                     maReliefOffset );
                 [ #  # ]
    1469                 :            :             }
    1470                 :            : 
    1471                 :          0 :             ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1472                 :            :             {
    1473         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1474         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1475                 :            : 
    1476                 :            :                 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
    1477 [ #  # ][ #  # ]:          0 :                                                  mxTextLayout->queryTextBounds() ),
    1478                 :            :                                              ::basegfx::B2DRange( 0,0,
    1479                 :            :                                                                   maLinesOverallSize.getX(),
    1480                 :            :                                                                   maLinesOverallSize.getY() ),
    1481                 :            :                                              maReliefOffset,
    1482                 :            :                                              maShadowOffset,
    1483                 :            :                                              aLocalState,
    1484 [ #  # ][ #  # ]:          0 :                                              mpCanvas->getViewState() );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1485                 :            :             }
    1486                 :            : 
    1487                 :          0 :             ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix&    rTransformation,
    1488                 :            :                                                                   const Subset&                     rSubset ) const
    1489                 :            :             {
    1490                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
    1491                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
    1492                 :            : 
    1493         [ #  # ]:          0 :                 rendering::RenderState                   aLocalState( maState );
    1494                 :          0 :                 uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
    1495 [ #  # ][ #  # ]:          0 :                 const geometry::RealRectangle2D          aTextBounds( mxTextLayout->queryTextBounds() );
    1496                 :            : 
    1497                 :          0 :                 double nMinPos(0.0);
    1498                 :          0 :                 double nMaxPos(aTextBounds.X2 - aTextBounds.X1);
    1499                 :            : 
    1500                 :            :                 createSubsetLayout( xTextLayout,
    1501                 :            :                                     aLocalState,
    1502                 :            :                                     nMinPos,
    1503                 :            :                                     nMaxPos,
    1504                 :            :                                     rTransformation,
    1505         [ #  # ]:          0 :                                     rSubset );
    1506                 :            : 
    1507         [ #  # ]:          0 :                 if( !xTextLayout.is() )
    1508         [ #  # ]:          0 :                     return ::basegfx::B2DRange(); // empty layout, empty bounds
    1509                 :            : 
    1510                 :            : 
    1511                 :            :                 // create and setup local line polygon
    1512                 :            :                 // ===================================
    1513                 :            : 
    1514                 :            :                 const ::basegfx::B2DPolyPolygon aPoly(
    1515                 :            :                     tools::createTextLinesPolyPolygon(
    1516                 :            :                         0.0, nMaxPos - nMinPos,
    1517         [ #  # ]:          0 :                         maTextLineInfo ) );
    1518                 :            : 
    1519                 :            :                 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
    1520 [ #  # ][ #  # ]:          0 :                                                  xTextLayout->queryTextBounds() ),
    1521                 :            :                                              ::basegfx::tools::getRange( aPoly ),
    1522                 :            :                                              maReliefOffset,
    1523                 :            :                                              maShadowOffset,
    1524                 :            :                                              aLocalState,
    1525 [ #  # ][ #  # ]:          0 :                                              mpCanvas->getViewState() );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1526                 :            :             }
    1527                 :            : 
    1528                 :          0 :             sal_Int32 EffectTextArrayAction::getActionCount() const
    1529                 :            :             {
    1530                 :          0 :                 const rendering::StringContext& rOrigContext( mxTextLayout->getText() );
    1531                 :            : 
    1532                 :          0 :                 return rOrigContext.Length;
    1533                 :            :             }
    1534                 :            : 
    1535                 :            : 
    1536                 :            :             // -------------------------------------------------------------------------
    1537                 :            : 
    1538 [ #  # ][ #  # ]:          0 :             class OutlineAction :
         [ #  # ][ #  # ]
                 [ #  # ]
    1539                 :            :                 public Action,
    1540                 :            :                 public TextRenderer,
    1541                 :            :                 private ::boost::noncopyable
    1542                 :            :             {
    1543                 :            :             public:
    1544                 :            :                 OutlineAction( const ::basegfx::B2DPoint&                           rStartPoint,
    1545                 :            :                                const ::basegfx::B2DSize&                            rReliefOffset,
    1546                 :            :                                const ::Color&                                       rReliefColor,
    1547                 :            :                                const ::basegfx::B2DSize&                            rShadowOffset,
    1548                 :            :                                const ::Color&                                       rShadowColor,
    1549                 :            :                                const ::basegfx::B2DRectangle&                       rOutlineBounds,
    1550                 :            :                                const uno::Reference< rendering::XPolyPolygon2D >&   rTextPoly,
    1551                 :            :                                const ::std::vector< sal_Int32 >&                    rPolygonGlyphMap,
    1552                 :            :                                const uno::Sequence< double >&                       rOffsets,
    1553                 :            :                                VirtualDevice&                                       rVDev,
    1554                 :            :                                const CanvasSharedPtr&                               rCanvas,
    1555                 :            :                                const OutDevState&                                   rState  );
    1556                 :            :                 OutlineAction( const ::basegfx::B2DPoint&                           rStartPoint,
    1557                 :            :                                const ::basegfx::B2DSize&                            rReliefOffset,
    1558                 :            :                                const ::Color&                                       rReliefColor,
    1559                 :            :                                const ::basegfx::B2DSize&                            rShadowOffset,
    1560                 :            :                                const ::Color&                                       rShadowColor,
    1561                 :            :                                const ::basegfx::B2DRectangle&                       rOutlineBounds,
    1562                 :            :                                const uno::Reference< rendering::XPolyPolygon2D >&   rTextPoly,
    1563                 :            :                                const ::std::vector< sal_Int32 >&                    rPolygonGlyphMap,
    1564                 :            :                                const uno::Sequence< double >&                       rOffsets,
    1565                 :            :                                VirtualDevice&                                       rVDev,
    1566                 :            :                                const CanvasSharedPtr&                               rCanvas,
    1567                 :            :                                const OutDevState&                                   rState,
    1568                 :            :                                const ::basegfx::B2DHomMatrix&                       rTextTransform );
    1569                 :            : 
    1570                 :            :                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1571                 :            :                 virtual bool renderSubset( const ::basegfx::B2DHomMatrix& rTransformation,
    1572                 :            :                                            const Subset&                  rSubset ) const;
    1573                 :            : 
    1574                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
    1575                 :            :                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&   rTransformation,
    1576                 :            :                                                        const Subset&                    rSubset ) const;
    1577                 :            : 
    1578                 :            :                 virtual sal_Int32 getActionCount() const;
    1579                 :            : 
    1580                 :            :             private:
    1581                 :            :                 // TextRenderer interface
    1582                 :            :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const;
    1583                 :            : 
    1584                 :            :                 // TODO(P2): This is potentially a real mass object
    1585                 :            :                 // (every character might be a separate TextAction),
    1586                 :            :                 // thus, make it as lightweight as possible. For
    1587                 :            :                 // example, share common RenderState among several
    1588                 :            :                 // TextActions, maybe using maOffsets for the
    1589                 :            :                 // translation.
    1590                 :            : 
    1591                 :            :                 uno::Reference< rendering::XPolyPolygon2D >         mxTextPoly;
    1592                 :            : 
    1593                 :            :                 /** This vector denotes the index of the start polygon
    1594                 :            :                     for the respective glyph sequence.
    1595                 :            : 
    1596                 :            :                     To get a polygon index range for a given character
    1597                 :            :                     index i, take [ maPolygonGlyphMap[i],
    1598                 :            :                     maPolygonGlyphMap[i+1] ). Note that this is wrong
    1599                 :            :                     for BiDi
    1600                 :            :                  */
    1601                 :            :                 const ::std::vector< sal_Int32 >                    maPolygonGlyphMap;
    1602                 :            :                 const uno::Sequence< double >                       maOffsets;
    1603                 :            :                 const CanvasSharedPtr                               mpCanvas;
    1604                 :            :                 rendering::RenderState                              maState;
    1605                 :            :                 double                                              mnOutlineWidth;
    1606                 :            :                 const uno::Sequence< double >                       maFillColor;
    1607                 :            :                 const tools::TextLineInfo                           maTextLineInfo;
    1608                 :            :                 ::basegfx::B2DSize                                  maLinesOverallSize;
    1609                 :            :                 const ::basegfx::B2DRectangle                       maOutlineBounds;
    1610                 :            :                 uno::Reference< rendering::XPolyPolygon2D >         mxTextLines;
    1611                 :            :                 const ::basegfx::B2DSize                            maReliefOffset;
    1612                 :            :                 const ::Color                                       maReliefColor;
    1613                 :            :                 const ::basegfx::B2DSize                            maShadowOffset;
    1614                 :            :                 const ::Color                                       maShadowColor;
    1615                 :            :             };
    1616                 :            : 
    1617                 :          0 :             double calcOutlineWidth( const OutDevState& rState,
    1618                 :            :                                      VirtualDevice&     rVDev )
    1619                 :            :             {
    1620                 :            :                 const ::basegfx::B2DSize aFontSize( 0,
    1621         [ #  # ]:          0 :                                                     rVDev.GetFont().GetHeight() / 64.0 );
    1622                 :            : 
    1623                 :            :                 const double nOutlineWidth(
    1624         [ #  # ]:          0 :                     (rState.mapModeTransform * aFontSize).getY() );
    1625                 :            : 
    1626         [ #  # ]:          0 :                 return nOutlineWidth < 1.0 ? 1.0 : nOutlineWidth;
    1627                 :            :             }
    1628                 :            : 
    1629                 :          0 :             OutlineAction::OutlineAction( const ::basegfx::B2DPoint&                            rStartPoint,
    1630                 :            :                                           const ::basegfx::B2DSize&                             rReliefOffset,
    1631                 :            :                                           const ::Color&                                        rReliefColor,
    1632                 :            :                                           const ::basegfx::B2DSize&                             rShadowOffset,
    1633                 :            :                                           const ::Color&                                        rShadowColor,
    1634                 :            :                                           const ::basegfx::B2DRectangle&                        rOutlineBounds,
    1635                 :            :                                           const uno::Reference< rendering::XPolyPolygon2D >&    rTextPoly,
    1636                 :            :                                           const ::std::vector< sal_Int32 >&                     rPolygonGlyphMap,
    1637                 :            :                                           const uno::Sequence< double >&                        rOffsets,
    1638                 :            :                                           VirtualDevice&                                        rVDev,
    1639                 :            :                                           const CanvasSharedPtr&                                rCanvas,
    1640                 :            :                                           const OutDevState&                                    rState  ) :
    1641                 :            :                 mxTextPoly( rTextPoly ),
    1642                 :            :                 maPolygonGlyphMap( rPolygonGlyphMap ),
    1643                 :            :                 maOffsets( rOffsets ),
    1644                 :            :                 mpCanvas( rCanvas ),
    1645                 :            :                 maState(),
    1646         [ #  # ]:          0 :                 mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
    1647                 :            :                 maFillColor(
    1648                 :            :                     ::vcl::unotools::colorToDoubleSequence(
    1649                 :            :                         ::Color( COL_WHITE ),
    1650 [ #  # ][ #  # ]:          0 :                         rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
         [ #  # ][ #  # ]
    1651                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
    1652                 :            :                 maLinesOverallSize(),
    1653                 :            :                 maOutlineBounds( rOutlineBounds ),
    1654                 :            :                 mxTextLines(),
    1655                 :            :                 maReliefOffset( rReliefOffset ),
    1656                 :            :                 maReliefColor( rReliefColor ),
    1657                 :            :                 maShadowOffset( rShadowOffset ),
    1658 [ #  # ][ #  # ]:          0 :                 maShadowColor( rShadowColor )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1659                 :            :             {
    1660                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
    1661                 :            :                                            mxTextLines,
    1662                 :            :                                            rCanvas,
    1663                 :            :                                            rOffsets,
    1664         [ #  # ]:          0 :                                            maTextLineInfo );
    1665                 :            : 
    1666                 :            :                 init( maState,
    1667                 :            :                       rStartPoint,
    1668                 :            :                       rState,
    1669         [ #  # ]:          0 :                       rCanvas );
    1670                 :          0 :             }
    1671                 :            : 
    1672                 :          0 :             OutlineAction::OutlineAction( const ::basegfx::B2DPoint&                            rStartPoint,
    1673                 :            :                                           const ::basegfx::B2DSize&                             rReliefOffset,
    1674                 :            :                                           const ::Color&                                        rReliefColor,
    1675                 :            :                                           const ::basegfx::B2DSize&                             rShadowOffset,
    1676                 :            :                                           const ::Color&                                        rShadowColor,
    1677                 :            :                                           const ::basegfx::B2DRectangle&                        rOutlineBounds,
    1678                 :            :                                           const uno::Reference< rendering::XPolyPolygon2D >&    rTextPoly,
    1679                 :            :                                           const ::std::vector< sal_Int32 >&                     rPolygonGlyphMap,
    1680                 :            :                                           const uno::Sequence< double >&                        rOffsets,
    1681                 :            :                                           VirtualDevice&                                        rVDev,
    1682                 :            :                                           const CanvasSharedPtr&                                rCanvas,
    1683                 :            :                                           const OutDevState&                                    rState,
    1684                 :            :                                           const ::basegfx::B2DHomMatrix&                        rTextTransform ) :
    1685                 :            :                 mxTextPoly( rTextPoly ),
    1686                 :            :                 maPolygonGlyphMap( rPolygonGlyphMap ),
    1687                 :            :                 maOffsets( rOffsets ),
    1688                 :            :                 mpCanvas( rCanvas ),
    1689                 :            :                 maState(),
    1690         [ #  # ]:          0 :                 mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
    1691                 :            :                 maFillColor(
    1692                 :            :                     ::vcl::unotools::colorToDoubleSequence(
    1693                 :            :                         ::Color( COL_WHITE ),
    1694 [ #  # ][ #  # ]:          0 :                         rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
         [ #  # ][ #  # ]
    1695                 :            :                 maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
    1696                 :            :                 maLinesOverallSize(),
    1697                 :            :                 maOutlineBounds( rOutlineBounds ),
    1698                 :            :                 mxTextLines(),
    1699                 :            :                 maReliefOffset( rReliefOffset ),
    1700                 :            :                 maReliefColor( rReliefColor ),
    1701                 :            :                 maShadowOffset( rShadowOffset ),
    1702 [ #  # ][ #  # ]:          0 :                 maShadowColor( rShadowColor )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1703                 :            :             {
    1704                 :            :                 initEffectLinePolyPolygon( maLinesOverallSize,
    1705                 :            :                                            mxTextLines,
    1706                 :            :                                            rCanvas,
    1707                 :            :                                            rOffsets,
    1708         [ #  # ]:          0 :                                            maTextLineInfo );
    1709                 :            : 
    1710                 :            :                 init( maState,
    1711                 :            :                       rStartPoint,
    1712                 :            :                       rState,
    1713                 :            :                       rCanvas,
    1714         [ #  # ]:          0 :                       rTextTransform );
    1715                 :          0 :             }
    1716                 :            : 
    1717                 :          0 :             bool OutlineAction::operator()( const rendering::RenderState& rRenderState ) const
    1718                 :            :             {
    1719         [ #  # ]:          0 :                 const rendering::ViewState&                 rViewState( mpCanvas->getViewState() );
    1720         [ #  # ]:          0 :                 const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
    1721                 :            : 
    1722         [ #  # ]:          0 :                 rendering::StrokeAttributes aStrokeAttributes;
    1723                 :            : 
    1724                 :          0 :                 aStrokeAttributes.StrokeWidth  = mnOutlineWidth;
    1725                 :          0 :                 aStrokeAttributes.MiterLimit   = 1.0;
    1726                 :          0 :                 aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
    1727                 :          0 :                 aStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
    1728                 :          0 :                 aStrokeAttributes.JoinType     = rendering::PathJoinType::MITER;
    1729                 :            : 
    1730         [ #  # ]:          0 :                 rendering::RenderState aLocalState( rRenderState );
    1731         [ #  # ]:          0 :                 aLocalState.DeviceColor = maFillColor;
    1732                 :            : 
    1733                 :            :                 // TODO(P1): implement caching
    1734                 :            : 
    1735                 :            :                 // background of text
    1736         [ #  # ]:          0 :                 rCanvas->fillPolyPolygon( mxTextPoly,
    1737                 :            :                                           rViewState,
    1738         [ #  # ]:          0 :                                           aLocalState );
    1739                 :            : 
    1740                 :            :                 // border line of text
    1741         [ #  # ]:          0 :                 rCanvas->strokePolyPolygon( mxTextPoly,
    1742                 :            :                                             rViewState,
    1743                 :            :                                             rRenderState,
    1744         [ #  # ]:          0 :                                             aStrokeAttributes );
    1745                 :            : 
    1746                 :            :                 // underlines/strikethrough - background
    1747         [ #  # ]:          0 :                 rCanvas->fillPolyPolygon( mxTextLines,
    1748                 :            :                                           rViewState,
    1749         [ #  # ]:          0 :                                           aLocalState );
    1750                 :            :                 // underlines/strikethrough - border
    1751         [ #  # ]:          0 :                 rCanvas->strokePolyPolygon( mxTextLines,
    1752                 :            :                                             rViewState,
    1753                 :            :                                             rRenderState,
    1754         [ #  # ]:          0 :                                             aStrokeAttributes );
    1755                 :            : 
    1756 [ #  # ][ #  # ]:          0 :                 return true;
                 [ #  # ]
    1757                 :            :             }
    1758                 :            : 
    1759                 :          0 :             bool OutlineAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1760                 :            :             {
    1761                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
    1762                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
    1763                 :            : 
    1764         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1765         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1766                 :            : 
    1767                 :            :                 return renderEffectText( *this,
    1768                 :            :                                          aLocalState,
    1769                 :          0 :                                          mpCanvas->getViewState(),
    1770                 :          0 :                                          mpCanvas->getUNOCanvas(),
    1771                 :            :                                          maShadowColor,
    1772                 :            :                                          maShadowOffset,
    1773                 :            :                                          maReliefColor,
    1774 [ #  # ][ #  # ]:          0 :                                          maReliefOffset );
                 [ #  # ]
           [ #  #  #  # ]
    1775                 :            :             }
    1776                 :            : 
    1777                 :            :             class OutlineTextArrayRenderHelper : public TextRenderer
    1778                 :            :             {
    1779                 :            :             public:
    1780                 :            :                 OutlineTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >&        rCanvas,
    1781                 :            :                                               const uno::Reference< rendering::XPolyPolygon2D >& rTextPolygon,
    1782                 :            :                                               const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
    1783                 :            :                                               const rendering::ViewState&                        rViewState,
    1784                 :            :                                               double                                             nOutlineWidth ) :
    1785                 :            :                     maFillColor(
    1786                 :            :                         ::vcl::unotools::colorToDoubleSequence(
    1787                 :            :                             ::Color( COL_WHITE ),
    1788                 :            :                             rCanvas->getDevice()->getDeviceColorSpace() )),
    1789                 :            :                     mnOutlineWidth( nOutlineWidth ),
    1790                 :            :                     mrCanvas( rCanvas ),
    1791                 :            :                     mrTextPolygon( rTextPolygon ),
    1792                 :            :                     mrLinePolygon( rLinePolygon ),
    1793                 :            :                     mrViewState( rViewState )
    1794                 :            :                 {
    1795                 :            :                 }
    1796                 :            : 
    1797                 :            :                 // TextRenderer interface
    1798                 :            :                 virtual bool operator()( const rendering::RenderState& rRenderState ) const
    1799                 :            :                 {
    1800                 :            :                     rendering::StrokeAttributes aStrokeAttributes;
    1801                 :            : 
    1802                 :            :                     aStrokeAttributes.StrokeWidth  = mnOutlineWidth;
    1803                 :            :                     aStrokeAttributes.MiterLimit   = 1.0;
    1804                 :            :                     aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
    1805                 :            :                     aStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
    1806                 :            :                     aStrokeAttributes.JoinType     = rendering::PathJoinType::MITER;
    1807                 :            : 
    1808                 :            :                     rendering::RenderState aLocalState( rRenderState );
    1809                 :            :                     aLocalState.DeviceColor = maFillColor;
    1810                 :            : 
    1811                 :            :                     // TODO(P1): implement caching
    1812                 :            : 
    1813                 :            :                     // background of text
    1814                 :            :                     mrCanvas->fillPolyPolygon( mrTextPolygon,
    1815                 :            :                                                mrViewState,
    1816                 :            :                                                aLocalState );
    1817                 :            : 
    1818                 :            :                     // border line of text
    1819                 :            :                     mrCanvas->strokePolyPolygon( mrTextPolygon,
    1820                 :            :                                                  mrViewState,
    1821                 :            :                                                  rRenderState,
    1822                 :            :                                                  aStrokeAttributes );
    1823                 :            : 
    1824                 :            :                     // underlines/strikethrough - background
    1825                 :            :                     mrCanvas->fillPolyPolygon( mrLinePolygon,
    1826                 :            :                                                mrViewState,
    1827                 :            :                                                aLocalState );
    1828                 :            :                     // underlines/strikethrough - border
    1829                 :            :                     mrCanvas->strokePolyPolygon( mrLinePolygon,
    1830                 :            :                                                  mrViewState,
    1831                 :            :                                                  rRenderState,
    1832                 :            :                                                  aStrokeAttributes );
    1833                 :            : 
    1834                 :            :                     return true;
    1835                 :            :                 }
    1836                 :            : 
    1837                 :            :             private:
    1838                 :            :                 const uno::Sequence< double >                       maFillColor;
    1839                 :            :                 double                                              mnOutlineWidth;
    1840                 :            :                 const uno::Reference< rendering::XCanvas >&         mrCanvas;
    1841                 :            :                 const uno::Reference< rendering::XPolyPolygon2D >&  mrTextPolygon;
    1842                 :            :                 const uno::Reference< rendering::XPolyPolygon2D >&  mrLinePolygon;
    1843                 :            :                 const rendering::ViewState&                         mrViewState;
    1844                 :            :             };
    1845                 :            : 
    1846                 :          0 :             bool OutlineAction::renderSubset( const ::basegfx::B2DHomMatrix&  rTransformation,
    1847                 :            :                                               const Subset&                   rSubset ) const
    1848                 :            :             {
    1849                 :            :                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::OutlineAction::renderSubset()" );
    1850                 :            :                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::OutlineAction: 0x%X", this );
    1851                 :            : 
    1852         [ #  # ]:          0 :                 if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
    1853                 :          0 :                     return true; // empty range, render nothing
    1854                 :            : 
    1855                 :            : #if 1
    1856                 :            :                 // TODO(F3): Subsetting NYI for outline text!
    1857                 :          0 :                 return render( rTransformation );
    1858                 :            : #else
    1859                 :            :                 const rendering::StringContext rOrigContext( mxTextLayout->getText() );
    1860                 :            : 
    1861                 :            :                 if( rSubset.mnSubsetBegin == 0 &&
    1862                 :            :                     rSubset.mnSubsetEnd == rOrigContext.Length )
    1863                 :            :                 {
    1864                 :            :                     // full range, no need for subsetting
    1865                 :            :                     return render( rTransformation );
    1866                 :            :                 }
    1867                 :            : 
    1868                 :            :                 rendering::RenderState aLocalState( maState );
    1869                 :            :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1870                 :            : 
    1871                 :            : 
    1872                 :            :                 // create and setup local Text polygon
    1873                 :            :                 // ===================================
    1874                 :            : 
    1875                 :            :                 uno::Reference< rendering::XPolyPolygon2D > xTextPolygon();
    1876                 :            : 
    1877                 :            :                 // TODO(P3): Provide an API method for that!
    1878                 :            : 
    1879                 :            :                 if( !xTextLayout.is() )
    1880                 :            :                     return false;
    1881                 :            : 
    1882                 :            :                 // render everything
    1883                 :            :                 // =================
    1884                 :            : 
    1885                 :            :                 return renderEffectText(
    1886                 :            :                     OutlineTextArrayRenderHelper(
    1887                 :            :                         xCanvas,
    1888                 :            :                         mnOutlineWidth,
    1889                 :            :                         xTextLayout,
    1890                 :            :                         xTextLines,
    1891                 :            :                         rViewState ),
    1892                 :            :                     aLocalState,
    1893                 :            :                     rViewState,
    1894                 :            :                     xCanvas,
    1895                 :            :                     maShadowColor,
    1896                 :            :                     maShadowOffset,
    1897                 :            :                     maReliefColor,
    1898                 :            :                     maReliefOffset );
    1899                 :            : #endif
    1900                 :            :             }
    1901                 :            : 
    1902                 :          0 :             ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
    1903                 :            :             {
    1904         [ #  # ]:          0 :                 rendering::RenderState aLocalState( maState );
    1905         [ #  # ]:          0 :                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
    1906                 :            : 
    1907                 :            :                 return calcEffectTextBounds( maOutlineBounds,
    1908                 :            :                                              ::basegfx::B2DRange( 0,0,
    1909                 :            :                                                                   maLinesOverallSize.getX(),
    1910                 :            :                                                                   maLinesOverallSize.getY() ),
    1911                 :            :                                              maReliefOffset,
    1912                 :            :                                              maShadowOffset,
    1913                 :            :                                              aLocalState,
    1914 [ #  # ][ #  # ]:          0 :                                              mpCanvas->getViewState() );
         [ #  # ][ #  # ]
                 [ #  # ]
    1915                 :            :             }
    1916                 :            : 
    1917                 :          0 :             ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix&    rTransformation,
    1918                 :            :                                                           const Subset&                     /*rSubset*/ ) const
    1919                 :            :             {
    1920                 :            :                 OSL_FAIL( "OutlineAction::getBounds(): Subset not yet supported by this object" );
    1921                 :            : 
    1922                 :          0 :                 return getBounds( rTransformation );
    1923                 :            :             }
    1924                 :            : 
    1925                 :          0 :             sal_Int32 OutlineAction::getActionCount() const
    1926                 :            :             {
    1927                 :            :                 // TODO(F3): Subsetting NYI for outline text!
    1928                 :          0 :                 return maOffsets.getLength();
    1929                 :            :             }
    1930                 :            : 
    1931                 :            : 
    1932                 :            :             // ======================================================================
    1933                 :            :             //
    1934                 :            :             // Action factory methods
    1935                 :            :             //
    1936                 :            :             // ======================================================================
    1937                 :            : 
    1938                 :            :             /** Create an outline action
    1939                 :            : 
    1940                 :            :                 This method extracts the polygonal outline from the
    1941                 :            :                 text, and creates a properly setup OutlineAction from
    1942                 :            :                 it.
    1943                 :            :              */
    1944                 :          0 :             ActionSharedPtr createOutline( const ::basegfx::B2DPoint&       rStartPoint,
    1945                 :            :                                            const ::basegfx::B2DSize&        rReliefOffset,
    1946                 :            :                                            const ::Color&                   rReliefColor,
    1947                 :            :                                            const ::basegfx::B2DSize&        rShadowOffset,
    1948                 :            :                                            const ::Color&                   rShadowColor,
    1949                 :            :                                            const String&                    rText,
    1950                 :            :                                            sal_Int32                        nStartPos,
    1951                 :            :                                            sal_Int32                        nLen,
    1952                 :            :                                            const sal_Int32*                 pDXArray,
    1953                 :            :                                            VirtualDevice&                   rVDev,
    1954                 :            :                                            const CanvasSharedPtr&           rCanvas,
    1955                 :            :                                            const OutDevState&               rState,
    1956                 :            :                                            const Renderer::Parameters&      rParms  )
    1957                 :            :             {
    1958                 :            :                 // operate on raw DX array here (in logical coordinate
    1959                 :            :                 // system), to have a higher resolution
    1960                 :            :                 // PolyPolygon. That polygon is then converted to
    1961                 :            :                 // device coordinate system.
    1962                 :            : 
    1963                 :            :                 // #i68512# Temporarily switch off font rotation
    1964                 :            :                 // (which is already contained in the render state
    1965                 :            :                 // transformation matrix - otherwise, glyph polygons
    1966                 :            :                 // will be rotated twice)
    1967         [ #  # ]:          0 :                 const ::Font aOrigFont( rVDev.GetFont() );
    1968         [ #  # ]:          0 :                 ::Font       aUnrotatedFont( aOrigFont );
    1969         [ #  # ]:          0 :                 aUnrotatedFont.SetOrientation(0);
    1970         [ #  # ]:          0 :                 rVDev.SetFont( aUnrotatedFont );
    1971                 :            : 
    1972                 :            :                 // TODO(F3): Don't understand parameter semantics of
    1973                 :            :                 // GetTextOutlines()
    1974         [ #  # ]:          0 :                 ::basegfx::B2DPolyPolygon aResultingPolyPolygon;
    1975         [ #  # ]:          0 :                 PolyPolyVector aVCLPolyPolyVector;
    1976                 :            :                 const bool bHaveOutlines( rVDev.GetTextOutlines( aVCLPolyPolyVector, rText,
    1977                 :            :                                                                  static_cast<sal_uInt16>(nStartPos),
    1978                 :            :                                                                  static_cast<sal_uInt16>(nStartPos),
    1979                 :            :                                                                  static_cast<sal_uInt16>(nLen),
    1980         [ #  # ]:          0 :                                                                  sal_True, 0, pDXArray ) );
    1981         [ #  # ]:          0 :                 rVDev.SetFont(aOrigFont);
    1982                 :            : 
    1983         [ #  # ]:          0 :                 if( !bHaveOutlines )
    1984         [ #  # ]:          0 :                     return ActionSharedPtr();
    1985                 :            : 
    1986         [ #  # ]:          0 :                 ::std::vector< sal_Int32 > aPolygonGlyphMap;
    1987                 :            : 
    1988                 :            :                 // first glyph starts at polygon index 0
    1989         [ #  # ]:          0 :                 aPolygonGlyphMap.push_back( 0 );
    1990                 :            : 
    1991                 :            :                 // remove offsetting from mapmode transformation
    1992                 :            :                 // (outline polygons must stay at origin, only need to
    1993                 :            :                 // be scaled)
    1994                 :            :                 ::basegfx::B2DHomMatrix aMapModeTransform(
    1995         [ #  # ]:          0 :                     rState.mapModeTransform );
    1996         [ #  # ]:          0 :                 aMapModeTransform.set(0,2, 0.0);
    1997         [ #  # ]:          0 :                 aMapModeTransform.set(1,2, 0.0);
    1998                 :            : 
    1999         [ #  # ]:          0 :                 PolyPolyVector::const_iterator       aIter( aVCLPolyPolyVector.begin() );
    2000         [ #  # ]:          0 :                 const PolyPolyVector::const_iterator aEnd( aVCLPolyPolyVector.end() );
    2001 [ #  # ][ #  # ]:          0 :                 for( ; aIter!= aEnd; ++aIter )
                 [ #  # ]
    2002                 :            :                 {
    2003         [ #  # ]:          0 :                     ::basegfx::B2DPolyPolygon aPolyPolygon;
    2004                 :            : 
    2005 [ #  # ][ #  # ]:          0 :                     aPolyPolygon = aIter->getB2DPolyPolygon();
         [ #  # ][ #  # ]
    2006         [ #  # ]:          0 :                     aPolyPolygon.transform( aMapModeTransform );
    2007                 :            : 
    2008                 :            :                     // append result to collecting polypoly
    2009 [ #  # ][ #  # ]:          0 :                     for( sal_uInt32 i=0; i<aPolyPolygon.count(); ++i )
    2010                 :            :                     {
    2011                 :            :                         // #i47795# Ensure closed polygons (since
    2012                 :            :                         // FreeType returns the glyph outlines
    2013                 :            :                         // open)
    2014         [ #  # ]:          0 :                         const ::basegfx::B2DPolygon& rPoly( aPolyPolygon.getB2DPolygon( i ) );
    2015         [ #  # ]:          0 :                         const sal_uInt32 nCount( rPoly.count() );
    2016 [ #  # ][ #  # ]:          0 :                         if( nCount<3 ||
                 [ #  # ]
    2017         [ #  # ]:          0 :                             rPoly.isClosed() )
    2018                 :            :                         {
    2019                 :            :                             // polygon either degenerate, or
    2020                 :            :                             // already closed.
    2021         [ #  # ]:          0 :                             aResultingPolyPolygon.append( rPoly );
    2022                 :            :                         }
    2023                 :            :                         else
    2024                 :            :                         {
    2025         [ #  # ]:          0 :                             ::basegfx::B2DPolygon aPoly(rPoly);
    2026         [ #  # ]:          0 :                             aPoly.setClosed(true);
    2027                 :            : 
    2028 [ #  # ][ #  # ]:          0 :                             aResultingPolyPolygon.append( aPoly );
    2029                 :            :                         }
    2030         [ #  # ]:          0 :                     }
    2031                 :            : 
    2032                 :            :                     // TODO(F3): Depending on the semantics of
    2033                 :            :                     // GetTextOutlines(), this here is wrong!
    2034                 :            : 
    2035                 :            :                     // calc next glyph index
    2036 [ #  # ][ #  # ]:          0 :                     aPolygonGlyphMap.push_back( aResultingPolyPolygon.count() );
    2037         [ #  # ]:          0 :                 }
    2038                 :            : 
    2039                 :            :                 const uno::Sequence< double > aCharWidthSeq(
    2040                 :            :                     pDXArray ?
    2041                 :            :                     setupDXArray( pDXArray, nLen, rState ) :
    2042                 :            :                     setupDXArray( rText,
    2043                 :            :                                   nStartPos,
    2044                 :            :                                   nLen,
    2045                 :            :                                   rVDev,
    2046 [ #  # ][ #  # ]:          0 :                                   rState ));
                 [ #  # ]
    2047                 :            :                 const uno::Reference< rendering::XPolyPolygon2D > xTextPoly(
    2048                 :            :                     ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
    2049 [ #  # ][ #  # ]:          0 :                         rCanvas->getUNOCanvas()->getDevice(),
    2050 [ #  # ][ #  # ]:          0 :                         aResultingPolyPolygon ) );
    2051                 :            : 
    2052         [ #  # ]:          0 :                 if( rParms.maTextTransformation.is_initialized() )
    2053                 :            :                 {
    2054                 :            :                     return ActionSharedPtr(
    2055                 :            :                         new OutlineAction(
    2056                 :            :                             rStartPoint,
    2057                 :            :                             rReliefOffset,
    2058                 :            :                             rReliefColor,
    2059                 :            :                             rShadowOffset,
    2060                 :            :                             rShadowColor,
    2061                 :            :                             ::basegfx::tools::getRange(aResultingPolyPolygon),
    2062                 :            :                             xTextPoly,
    2063                 :            :                             aPolygonGlyphMap,
    2064                 :            :                             aCharWidthSeq,
    2065                 :            :                             rVDev,
    2066                 :            :                             rCanvas,
    2067                 :            :                             rState,
    2068 [ #  # ][ #  # ]:          0 :                             *rParms.maTextTransformation ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2069                 :            :                 }
    2070                 :            :                 else
    2071                 :            :                 {
    2072                 :            :                     return ActionSharedPtr(
    2073                 :            :                         new OutlineAction(
    2074                 :            :                             rStartPoint,
    2075                 :            :                             rReliefOffset,
    2076                 :            :                             rReliefColor,
    2077                 :            :                             rShadowOffset,
    2078                 :            :                             rShadowColor,
    2079                 :            :                             ::basegfx::tools::getRange(aResultingPolyPolygon),
    2080                 :            :                             xTextPoly,
    2081                 :            :                             aPolygonGlyphMap,
    2082                 :            :                             aCharWidthSeq,
    2083                 :            :                             rVDev,
    2084                 :            :                             rCanvas,
    2085 [ #  # ][ #  # ]:          0 :                             rState  ) );
         [ #  # ][ #  # ]
    2086 [ #  # ][ #  # ]:          0 :                 }
         [ #  # ][ #  # ]
                 [ #  # ]
    2087                 :            :             }
    2088                 :            : 
    2089                 :            :         } // namespace
    2090                 :            : 
    2091                 :            : 
    2092                 :            :         // ---------------------------------------------------------------------------------
    2093                 :            : 
    2094                 :          0 :         ActionSharedPtr TextActionFactory::createTextAction( const ::Point&                 rStartPoint,
    2095                 :            :                                                              const ::Size&                  rReliefOffset,
    2096                 :            :                                                              const ::Color&                 rReliefColor,
    2097                 :            :                                                              const ::Size&                  rShadowOffset,
    2098                 :            :                                                              const ::Color&                 rShadowColor,
    2099                 :            :                                                              const String&                  rText,
    2100                 :            :                                                              sal_Int32                      nStartPos,
    2101                 :            :                                                              sal_Int32                      nLen,
    2102                 :            :                                                              const sal_Int32*               pDXArray,
    2103                 :            :                                                              VirtualDevice&                 rVDev,
    2104                 :            :                                                              const CanvasSharedPtr&         rCanvas,
    2105                 :            :                                                              const OutDevState&             rState,
    2106                 :            :                                                              const Renderer::Parameters&    rParms,
    2107                 :            :                                                              bool                           bSubsettable    )
    2108                 :            :         {
    2109                 :            :             const ::Size  aBaselineOffset( tools::getBaselineOffset( rState,
    2110         [ #  # ]:          0 :                                                                      rVDev ) );
    2111                 :            :             // #143885# maintain (nearly) full precision positioning,
    2112                 :            :             // by circumventing integer-based OutDev-mapping
    2113                 :            :             const ::basegfx::B2DPoint aStartPoint(
    2114                 :            :                 rState.mapModeTransform *
    2115                 :          0 :                 ::basegfx::B2DPoint(rStartPoint.X() + aBaselineOffset.Width(),
    2116         [ #  # ]:          0 :                                     rStartPoint.Y() + aBaselineOffset.Height()) );
    2117                 :            : 
    2118                 :            :             const ::basegfx::B2DSize aReliefOffset(
    2119 [ #  # ][ #  # ]:          0 :                 rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rReliefOffset ) );
    2120                 :            :             const ::basegfx::B2DSize aShadowOffset(
    2121 [ #  # ][ #  # ]:          0 :                 rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rShadowOffset ) );
    2122                 :            : 
    2123         [ #  # ]:          0 :             if( rState.isTextOutlineModeSet )
    2124                 :            :             {
    2125                 :            :                 return createOutline(
    2126                 :            :                             aStartPoint,
    2127                 :            :                             aReliefOffset,
    2128                 :            :                             rReliefColor,
    2129                 :            :                             aShadowOffset,
    2130                 :            :                             rShadowColor,
    2131                 :            :                             rText,
    2132                 :            :                             nStartPos,
    2133                 :            :                             nLen,
    2134                 :            :                             pDXArray,
    2135                 :            :                             rVDev,
    2136                 :            :                             rCanvas,
    2137                 :            :                             rState,
    2138         [ #  # ]:          0 :                             rParms );
    2139                 :            :             }
    2140                 :            : 
    2141                 :            :             // convert DX array to device coordinate system (and
    2142                 :            :             // create it in the first place, if pDXArray is NULL)
    2143                 :            :             const uno::Sequence< double > aCharWidths(
    2144                 :            :                 pDXArray ?
    2145                 :            :                 setupDXArray( pDXArray, nLen, rState ) :
    2146                 :            :                 setupDXArray( rText,
    2147                 :            :                               nStartPos,
    2148                 :            :                               nLen,
    2149                 :            :                               rVDev,
    2150 [ #  # ][ #  # ]:          0 :                               rState ));
                 [ #  # ]
    2151                 :            : 
    2152                 :            :             // determine type of text action to create
    2153                 :            :             // =======================================
    2154                 :            : 
    2155                 :          0 :             const ::Color aEmptyColor( COL_AUTO );
    2156                 :            : 
    2157                 :            :             // no DX array, and no need to subset - no need to store
    2158                 :            :             // DX array, then.
    2159 [ #  # ][ #  # ]:          0 :             if( !pDXArray && !bSubsettable )
    2160                 :            :             {
    2161                 :            :                 // effects, or not?
    2162 [ #  # ][ #  # ]:          0 :                 if( !rState.textOverlineStyle &&
           [ #  #  #  #  
           #  # ][ #  # ]
    2163                 :          0 :                     !rState.textUnderlineStyle &&
    2164                 :          0 :                     !rState.textStrikeoutStyle &&
    2165                 :          0 :                     rReliefColor == aEmptyColor &&
    2166                 :          0 :                     rShadowColor == aEmptyColor )
    2167                 :            :                 {
    2168                 :            :                     // nope
    2169         [ #  # ]:          0 :                     if( rParms.maTextTransformation.is_initialized() )
    2170                 :            :                     {
    2171                 :            :                         return ActionSharedPtr( new TextAction(
    2172                 :            :                                                     aStartPoint,
    2173                 :            :                                                     rText,
    2174                 :            :                                                     nStartPos,
    2175                 :            :                                                     nLen,
    2176                 :            :                                                     rCanvas,
    2177                 :            :                                                     rState,
    2178 [ #  # ][ #  # ]:          0 :                                                     *rParms.maTextTransformation ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2179                 :            :                     }
    2180                 :            :                     else
    2181                 :            :                     {
    2182                 :            :                         return ActionSharedPtr( new TextAction(
    2183                 :            :                                                     aStartPoint,
    2184                 :            :                                                     rText,
    2185                 :            :                                                     nStartPos,
    2186                 :            :                                                     nLen,
    2187                 :            :                                                     rCanvas,
    2188 [ #  # ][ #  # ]:          0 :                                                     rState ) );
         [ #  # ][ #  # ]
    2189                 :            :                     }
    2190                 :            :                 }
    2191                 :            :                 else
    2192                 :            :                 {
    2193                 :            :                     // at least one of the effects requested
    2194         [ #  # ]:          0 :                     if( rParms.maTextTransformation.is_initialized() )
    2195                 :            :                         return ActionSharedPtr( new EffectTextAction(
    2196                 :            :                                                     aStartPoint,
    2197                 :            :                                                     aReliefOffset,
    2198                 :            :                                                     rReliefColor,
    2199                 :            :                                                     aShadowOffset,
    2200                 :            :                                                     rShadowColor,
    2201                 :            :                                                     rText,
    2202                 :            :                                                     nStartPos,
    2203                 :            :                                                     nLen,
    2204                 :            :                                                     rVDev,
    2205                 :            :                                                     rCanvas,
    2206                 :            :                                                     rState,
    2207 [ #  # ][ #  # ]:          0 :                                                     *rParms.maTextTransformation ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2208                 :            :                     else
    2209                 :            :                         return ActionSharedPtr( new EffectTextAction(
    2210                 :            :                                                     aStartPoint,
    2211                 :            :                                                     aReliefOffset,
    2212                 :            :                                                     rReliefColor,
    2213                 :            :                                                     aShadowOffset,
    2214                 :            :                                                     rShadowColor,
    2215                 :            :                                                     rText,
    2216                 :            :                                                     nStartPos,
    2217                 :            :                                                     nLen,
    2218                 :            :                                                     rVDev,
    2219                 :            :                                                     rCanvas,
    2220 [ #  # ][ #  # ]:          0 :                                                     rState ) );
         [ #  # ][ #  # ]
    2221                 :            :                 }
    2222                 :            :             }
    2223                 :            :             else
    2224                 :            :             {
    2225                 :            :                 // DX array necessary - any effects?
    2226 [ #  # ][ #  # ]:          0 :                 if( !rState.textOverlineStyle &&
           [ #  #  #  #  
           #  # ][ #  # ]
    2227                 :          0 :                     !rState.textUnderlineStyle &&
    2228                 :          0 :                     !rState.textStrikeoutStyle &&
    2229                 :          0 :                     rReliefColor == aEmptyColor &&
    2230                 :          0 :                     rShadowColor == aEmptyColor )
    2231                 :            :                 {
    2232                 :            :                     // nope
    2233         [ #  # ]:          0 :                     if( rParms.maTextTransformation.is_initialized() )
    2234                 :            :                         return ActionSharedPtr( new TextArrayAction(
    2235                 :            :                                                     aStartPoint,
    2236                 :            :                                                     rText,
    2237                 :            :                                                     nStartPos,
    2238                 :            :                                                     nLen,
    2239                 :            :                                                     aCharWidths,
    2240                 :            :                                                     rCanvas,
    2241                 :            :                                                     rState,
    2242 [ #  # ][ #  # ]:          0 :                                                     *rParms.maTextTransformation ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2243                 :            :                     else
    2244                 :            :                         return ActionSharedPtr( new TextArrayAction(
    2245                 :            :                                                     aStartPoint,
    2246                 :            :                                                     rText,
    2247                 :            :                                                     nStartPos,
    2248                 :            :                                                     nLen,
    2249                 :            :                                                     aCharWidths,
    2250                 :            :                                                     rCanvas,
    2251 [ #  # ][ #  # ]:          0 :                                                     rState ) );
         [ #  # ][ #  # ]
    2252                 :            :                 }
    2253                 :            :                 else
    2254                 :            :                 {
    2255                 :            :                     // at least one of the effects requested
    2256         [ #  # ]:          0 :                     if( rParms.maTextTransformation.is_initialized() )
    2257                 :            :                         return ActionSharedPtr( new EffectTextArrayAction(
    2258                 :            :                                                     aStartPoint,
    2259                 :            :                                                     aReliefOffset,
    2260                 :            :                                                     rReliefColor,
    2261                 :            :                                                     aShadowOffset,
    2262                 :            :                                                     rShadowColor,
    2263                 :            :                                                     rText,
    2264                 :            :                                                     nStartPos,
    2265                 :            :                                                     nLen,
    2266                 :            :                                                     aCharWidths,
    2267                 :            :                                                     rVDev,
    2268                 :            :                                                     rCanvas,
    2269                 :            :                                                     rState,
    2270 [ #  # ][ #  # ]:          0 :                                                     *rParms.maTextTransformation ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2271                 :            :                     else
    2272                 :            :                         return ActionSharedPtr( new EffectTextArrayAction(
    2273                 :            :                                                     aStartPoint,
    2274                 :            :                                                     aReliefOffset,
    2275                 :            :                                                     rReliefColor,
    2276                 :            :                                                     aShadowOffset,
    2277                 :            :                                                     rShadowColor,
    2278                 :            :                                                     rText,
    2279                 :            :                                                     nStartPos,
    2280                 :            :                                                     nLen,
    2281                 :            :                                                     aCharWidths,
    2282                 :            :                                                     rVDev,
    2283                 :            :                                                     rCanvas,
    2284 [ #  # ][ #  # ]:          0 :                                                     rState ) );
         [ #  # ][ #  # ]
    2285                 :            :                 }
    2286                 :            :             }
    2287                 :            : #if defined(__GNUC__)
    2288         [ #  # ]:          0 :             return ActionSharedPtr();
    2289                 :            : #endif
    2290                 :            :         }
    2291                 :            :     }
    2292 [ +  - ][ +  - ]:        735 : }
    2293                 :            : 
    2294                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10