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