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