xref: /AOO41X/main/cppcanvas/source/mtfrenderer/implrenderer.cxx (revision 25b1114295101a2e8c55dab9e4c2ddcafdffc2eb)
1*25b11142SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*25b11142SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*25b11142SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*25b11142SAndrew Rist  * distributed with this work for additional information
6*25b11142SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*25b11142SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*25b11142SAndrew Rist  * "License"); you may not use this file except in compliance
9*25b11142SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*25b11142SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*25b11142SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*25b11142SAndrew Rist  * software distributed under the License is distributed on an
15*25b11142SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*25b11142SAndrew Rist  * KIND, either express or implied.  See the License for the
17*25b11142SAndrew Rist  * specific language governing permissions and limitations
18*25b11142SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*25b11142SAndrew Rist  *************************************************************/
21*25b11142SAndrew Rist 
22*25b11142SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_cppcanvas.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
30cdf0e10cSrcweir #include <osl/mutex.hxx>
31cdf0e10cSrcweir #include <vos/mutex.hxx>
32cdf0e10cSrcweir #include <vcl/svapp.hxx>
33cdf0e10cSrcweir #include <rtl/logfile.hxx>
34cdf0e10cSrcweir #include <comphelper/sequence.hxx>
35cdf0e10cSrcweir #include <comphelper/anytostring.hxx>
36cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
37cdf0e10cSrcweir #include <cppcanvas/canvas.hxx>
38cdf0e10cSrcweir #include <com/sun/star/rendering/XGraphicDevice.hpp>
39cdf0e10cSrcweir #include <com/sun/star/rendering/TexturingMode.hpp>
40cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx>
41cdf0e10cSrcweir #include <com/sun/star/geometry/RealPoint2D.hpp>
42cdf0e10cSrcweir #include <com/sun/star/rendering/PanoseProportion.hpp>
43cdf0e10cSrcweir #include <com/sun/star/rendering/ViewState.hpp>
44cdf0e10cSrcweir #include <com/sun/star/rendering/RenderState.hpp>
45cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvasFont.hpp>
46cdf0e10cSrcweir #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
47cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvas.hpp>
48cdf0e10cSrcweir #include <com/sun/star/rendering/PathCapType.hpp>
49cdf0e10cSrcweir #include <com/sun/star/rendering/PathJoinType.hpp>
50cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
51cdf0e10cSrcweir #include <basegfx/tools/gradienttools.hxx>
52cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
53cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
54cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
55cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
56cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
57cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
58cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx>
59cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
60cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
61cdf0e10cSrcweir #include <basegfx/tuple/b2dtuple.hxx>
62cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx>
63cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
64cdf0e10cSrcweir #include <canvas/canvastools.hxx>
65cdf0e10cSrcweir #include <vcl/canvastools.hxx>
66cdf0e10cSrcweir #include <vcl/salbtype.hxx>
67cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
68cdf0e10cSrcweir #include <vcl/metaact.hxx>
69cdf0e10cSrcweir #include <vcl/virdev.hxx>
70cdf0e10cSrcweir #include <vcl/metric.hxx>
71cdf0e10cSrcweir #include <vcl/graphictools.hxx>
72cdf0e10cSrcweir #include <tools/poly.hxx>
73cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
74cdf0e10cSrcweir #include <implrenderer.hxx>
75cdf0e10cSrcweir #include <tools.hxx>
76cdf0e10cSrcweir #include <outdevstate.hxx>
77cdf0e10cSrcweir #include <action.hxx>
78cdf0e10cSrcweir #include <bitmapaction.hxx>
79cdf0e10cSrcweir #include <lineaction.hxx>
80cdf0e10cSrcweir #include <pointaction.hxx>
81cdf0e10cSrcweir #include <polypolyaction.hxx>
82cdf0e10cSrcweir #include <rendergraphicaction.hxx>
83cdf0e10cSrcweir #include <textaction.hxx>
84cdf0e10cSrcweir #include <transparencygroupaction.hxx>
85cdf0e10cSrcweir #include <vector>
86cdf0e10cSrcweir #include <algorithm>
87cdf0e10cSrcweir #include <iterator>
88cdf0e10cSrcweir #include <boost/scoped_array.hpp>
89cdf0e10cSrcweir #include "mtftools.hxx"
90cdf0e10cSrcweir #include "outdevstate.hxx"
91cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
92cdf0e10cSrcweir 
93cdf0e10cSrcweir 
94cdf0e10cSrcweir using namespace ::com::sun::star;
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 
97cdf0e10cSrcweir // free support functions
98cdf0e10cSrcweir // ======================
99cdf0e10cSrcweir namespace
100cdf0e10cSrcweir {
101cdf0e10cSrcweir     template < class MetaActionType > void setStateColor( MetaActionType* 					pAct,
102cdf0e10cSrcweir                                                           bool&								rIsColorSet,
103cdf0e10cSrcweir                                                           uno::Sequence< double >& 			rColorSequence,
104cdf0e10cSrcweir                                                           const cppcanvas::CanvasSharedPtr&	rCanvas )
105cdf0e10cSrcweir     {
106cdf0e10cSrcweir         // set rIsColorSet and check for true at the same time
107cdf0e10cSrcweir         if( (rIsColorSet=pAct->IsSetting()) != false )
108cdf0e10cSrcweir         {
109cdf0e10cSrcweir             ::Color aColor( pAct->GetColor() );
110cdf0e10cSrcweir 
111cdf0e10cSrcweir             // force alpha part of color to
112cdf0e10cSrcweir             // opaque. transparent painting is done
113cdf0e10cSrcweir             // explicitely via META_TRANSPARENT_ACTION
114cdf0e10cSrcweir             aColor.SetTransparency(0);
115cdf0e10cSrcweir             //aColor.SetTransparency(128);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             rColorSequence = ::vcl::unotools::colorToDoubleSequence(
118cdf0e10cSrcweir                 aColor,
119cdf0e10cSrcweir                 rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
120cdf0e10cSrcweir         }
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir 
124cdf0e10cSrcweir     // state stack manipulators
125cdf0e10cSrcweir     // ------------------------
126cdf0e10cSrcweir     void clearStateStack( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
127cdf0e10cSrcweir     {
128cdf0e10cSrcweir         rStates.clear();
129cdf0e10cSrcweir         const ::cppcanvas::internal::OutDevState aDefaultState;
130cdf0e10cSrcweir         rStates.push_back( aDefaultState );
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     ::cppcanvas::internal::OutDevState& getState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         return rStates.back();
136cdf0e10cSrcweir     }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir     const ::cppcanvas::internal::OutDevState& getState( const ::cppcanvas::internal::VectorOfOutDevStates& rStates )
139cdf0e10cSrcweir     {
140cdf0e10cSrcweir         return rStates.back();
141cdf0e10cSrcweir     }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir     void pushState( ::cppcanvas::internal::VectorOfOutDevStates& rStates,
144cdf0e10cSrcweir                     sal_uInt16 nFlags											)
145cdf0e10cSrcweir     {
146cdf0e10cSrcweir         rStates.push_back( getState( rStates ) );
147cdf0e10cSrcweir         getState( rStates ).pushFlags = nFlags;
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     void popState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
151cdf0e10cSrcweir     {
152cdf0e10cSrcweir         if( getState( rStates ).pushFlags != PUSH_ALL )
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             // a state is pushed which is incomplete, i.e. does not
155cdf0e10cSrcweir             // restore everything to the previous stack level when
156cdf0e10cSrcweir             // popped.
157cdf0e10cSrcweir             // That means, we take the old state, and restore every
158cdf0e10cSrcweir             // OutDevState member whose flag is set, from the new to the
159cdf0e10cSrcweir             // old state. Then the new state gets overwritten by the
160cdf0e10cSrcweir             // calculated state
161cdf0e10cSrcweir 
162cdf0e10cSrcweir             // preset to-be-calculated new state with old state
163cdf0e10cSrcweir             ::cppcanvas::internal::OutDevState aCalculatedNewState( getState( rStates ) );
164cdf0e10cSrcweir 
165cdf0e10cSrcweir             // selectively copy to-be-restored content over saved old
166cdf0e10cSrcweir             // state
167cdf0e10cSrcweir             rStates.pop_back();
168cdf0e10cSrcweir 
169cdf0e10cSrcweir             const ::cppcanvas::internal::OutDevState& rNewState( getState( rStates ) );
170cdf0e10cSrcweir 
171cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_LINECOLOR) )
172cdf0e10cSrcweir             {
173cdf0e10cSrcweir                 aCalculatedNewState.lineColor 	   = rNewState.lineColor;
174cdf0e10cSrcweir                 aCalculatedNewState.isLineColorSet = rNewState.isLineColorSet;
175cdf0e10cSrcweir             }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_FILLCOLOR) )
178cdf0e10cSrcweir             {
179cdf0e10cSrcweir                 aCalculatedNewState.fillColor 	   = rNewState.fillColor;
180cdf0e10cSrcweir                 aCalculatedNewState.isFillColorSet = rNewState.isFillColorSet;
181cdf0e10cSrcweir             }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_FONT) )
184cdf0e10cSrcweir             {
185cdf0e10cSrcweir                 aCalculatedNewState.xFont 					= rNewState.xFont;
186cdf0e10cSrcweir                 aCalculatedNewState.fontRotation 			= rNewState.fontRotation;
187cdf0e10cSrcweir                 aCalculatedNewState.textReliefStyle 		= rNewState.textReliefStyle;
188cdf0e10cSrcweir                 aCalculatedNewState.textOverlineStyle 		= rNewState.textOverlineStyle;
189cdf0e10cSrcweir                 aCalculatedNewState.textUnderlineStyle 		= rNewState.textUnderlineStyle;
190cdf0e10cSrcweir                 aCalculatedNewState.textStrikeoutStyle 		= rNewState.textStrikeoutStyle;
191cdf0e10cSrcweir                 aCalculatedNewState.textEmphasisMarkStyle 	= rNewState.textEmphasisMarkStyle;
192cdf0e10cSrcweir                 aCalculatedNewState.isTextEffectShadowSet 	= rNewState.isTextEffectShadowSet;
193cdf0e10cSrcweir                 aCalculatedNewState.isTextWordUnderlineSet 	= rNewState.isTextWordUnderlineSet;
194cdf0e10cSrcweir                 aCalculatedNewState.isTextOutlineModeSet 	= rNewState.isTextOutlineModeSet;
195cdf0e10cSrcweir             }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_TEXTCOLOR) )
198cdf0e10cSrcweir             {
199cdf0e10cSrcweir                 aCalculatedNewState.textColor = rNewState.textColor;
200cdf0e10cSrcweir             }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_MAPMODE) )
203cdf0e10cSrcweir             {
204cdf0e10cSrcweir                 aCalculatedNewState.mapModeTransform = rNewState.mapModeTransform;
205cdf0e10cSrcweir             }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_CLIPREGION) )
208cdf0e10cSrcweir             {
209cdf0e10cSrcweir                 aCalculatedNewState.clip 		= rNewState.clip;
210cdf0e10cSrcweir                 aCalculatedNewState.clipRect	= rNewState.clipRect;
211cdf0e10cSrcweir                 aCalculatedNewState.xClipPoly	= rNewState.xClipPoly;
212cdf0e10cSrcweir             }
213cdf0e10cSrcweir 
214cdf0e10cSrcweir             // TODO(F2): Raster ops NYI
215cdf0e10cSrcweir             // if( (aCalculatedNewState.pushFlags & PUSH_RASTEROP) )
216cdf0e10cSrcweir             // {
217cdf0e10cSrcweir             // }
218cdf0e10cSrcweir 
219cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_TEXTFILLCOLOR) )
220cdf0e10cSrcweir             {
221cdf0e10cSrcweir                 aCalculatedNewState.textFillColor 	   = rNewState.textFillColor;
222cdf0e10cSrcweir                 aCalculatedNewState.isTextFillColorSet = rNewState.isTextFillColorSet;
223cdf0e10cSrcweir             }
224cdf0e10cSrcweir 
225cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_TEXTALIGN) )
226cdf0e10cSrcweir             {
227cdf0e10cSrcweir                 aCalculatedNewState.textReferencePoint = rNewState.textReferencePoint;
228cdf0e10cSrcweir             }
229cdf0e10cSrcweir 
230cdf0e10cSrcweir             // TODO(F1): Refpoint handling NYI
231cdf0e10cSrcweir             // if( (aCalculatedNewState.pushFlags & PUSH_REFPOINT) )
232cdf0e10cSrcweir             // {
233cdf0e10cSrcweir             // }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_TEXTLINECOLOR) )
236cdf0e10cSrcweir             {
237cdf0e10cSrcweir                 aCalculatedNewState.textLineColor 	   = rNewState.textLineColor;
238cdf0e10cSrcweir                 aCalculatedNewState.isTextLineColorSet = rNewState.isTextLineColorSet;
239cdf0e10cSrcweir             }
240cdf0e10cSrcweir 
241cdf0e10cSrcweir             if( (aCalculatedNewState.pushFlags & PUSH_TEXTLAYOUTMODE) )
242cdf0e10cSrcweir             {
243cdf0e10cSrcweir                 aCalculatedNewState.textAlignment = rNewState.textAlignment;
244cdf0e10cSrcweir                 aCalculatedNewState.textDirection = rNewState.textDirection;
245cdf0e10cSrcweir             }
246cdf0e10cSrcweir 
247cdf0e10cSrcweir             // TODO(F2): Text language handling NYI
248cdf0e10cSrcweir             // if( (aCalculatedNewState.pushFlags & PUSH_TEXTLANGUAGE) )
249cdf0e10cSrcweir             // {
250cdf0e10cSrcweir             // }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir             // always copy push mode
253cdf0e10cSrcweir             aCalculatedNewState.pushFlags = rNewState.pushFlags;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir             // flush to stack
256cdf0e10cSrcweir             getState( rStates ) = aCalculatedNewState;
257cdf0e10cSrcweir         }
258cdf0e10cSrcweir         else
259cdf0e10cSrcweir         {
260cdf0e10cSrcweir             rStates.pop_back();
261cdf0e10cSrcweir         }
262cdf0e10cSrcweir     }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     void setupStrokeAttributes( rendering::StrokeAttributes&                          o_rStrokeAttributes,
265cdf0e10cSrcweir                                 const ::cppcanvas::internal::ActionFactoryParameters& rParms,
266cdf0e10cSrcweir                                 const LineInfo&                                       rLineInfo 				)
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         const ::basegfx::B2DSize aWidth( rLineInfo.GetWidth(), 0 );
269cdf0e10cSrcweir         o_rStrokeAttributes.StrokeWidth =
270cdf0e10cSrcweir             (getState( rParms.mrStates ).mapModeTransform * aWidth).getX();
271cdf0e10cSrcweir 
272cdf0e10cSrcweir         // setup reasonable defaults
273cdf0e10cSrcweir         o_rStrokeAttributes.MiterLimit 	 = 15.0; // 1.0 was no good default; GDI+'s limit is 10.0, our's is 15.0
274cdf0e10cSrcweir         o_rStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
275cdf0e10cSrcweir         o_rStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         switch(rLineInfo.GetLineJoin())
278cdf0e10cSrcweir         {
279cdf0e10cSrcweir             default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
280cdf0e10cSrcweir                 o_rStrokeAttributes.JoinType = rendering::PathJoinType::NONE;
281cdf0e10cSrcweir                 break;
282cdf0e10cSrcweir             case basegfx::B2DLINEJOIN_BEVEL:
283cdf0e10cSrcweir                 o_rStrokeAttributes.JoinType = rendering::PathJoinType::BEVEL;
284cdf0e10cSrcweir                 break;
285cdf0e10cSrcweir             case basegfx::B2DLINEJOIN_MITER:
286cdf0e10cSrcweir                 o_rStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
287cdf0e10cSrcweir                 break;
288cdf0e10cSrcweir             case basegfx::B2DLINEJOIN_ROUND:
289cdf0e10cSrcweir                 o_rStrokeAttributes.JoinType = rendering::PathJoinType::ROUND;
290cdf0e10cSrcweir                 break;
291cdf0e10cSrcweir         }
292cdf0e10cSrcweir 
293cdf0e10cSrcweir         if( LINE_DASH == rLineInfo.GetStyle() )
294cdf0e10cSrcweir         {
295cdf0e10cSrcweir             const ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
296cdf0e10cSrcweir 
297cdf0e10cSrcweir             // TODO(F1): Interpret OutDev::GetRefPoint() for the start of the dashing.
298cdf0e10cSrcweir 
299cdf0e10cSrcweir             // interpret dash info only if explicitely enabled as
300cdf0e10cSrcweir             // style
301cdf0e10cSrcweir             const ::basegfx::B2DSize aDistance( rLineInfo.GetDistance(), 0 );
302cdf0e10cSrcweir             const double nDistance( (rState.mapModeTransform * aDistance).getX() );
303cdf0e10cSrcweir 
304cdf0e10cSrcweir             const ::basegfx::B2DSize aDashLen( rLineInfo.GetDashLen(), 0 );
305cdf0e10cSrcweir             const double nDashLen( (rState.mapModeTransform * aDashLen).getX() );
306cdf0e10cSrcweir 
307cdf0e10cSrcweir             const ::basegfx::B2DSize aDotLen( rLineInfo.GetDotLen(), 0 );
308cdf0e10cSrcweir             const double nDotLen( (rState.mapModeTransform * aDotLen).getX() );
309cdf0e10cSrcweir 
310cdf0e10cSrcweir             const sal_Int32 nNumArryEntries( 2*rLineInfo.GetDashCount() +
311cdf0e10cSrcweir                                              2*rLineInfo.GetDotCount() );
312cdf0e10cSrcweir 
313cdf0e10cSrcweir             o_rStrokeAttributes.DashArray.realloc( nNumArryEntries );
314cdf0e10cSrcweir             double* pDashArray = o_rStrokeAttributes.DashArray.getArray();
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 
317cdf0e10cSrcweir             // iteratively fill dash array, first with dashs, then
318cdf0e10cSrcweir             // with dots.
319cdf0e10cSrcweir             // ===================================================
320cdf0e10cSrcweir 
321cdf0e10cSrcweir             sal_Int32 nCurrEntry=0;
322cdf0e10cSrcweir 
323cdf0e10cSrcweir             for( sal_Int32 i=0; i<rLineInfo.GetDashCount(); ++i )
324cdf0e10cSrcweir             {
325cdf0e10cSrcweir                 pDashArray[nCurrEntry++] = nDashLen;
326cdf0e10cSrcweir                 pDashArray[nCurrEntry++] = nDistance;
327cdf0e10cSrcweir             }
328cdf0e10cSrcweir             for( sal_Int32 i=0; i<rLineInfo.GetDotCount(); ++i )
329cdf0e10cSrcweir             {
330cdf0e10cSrcweir                 pDashArray[nCurrEntry++] = nDotLen;
331cdf0e10cSrcweir                 pDashArray[nCurrEntry++] = nDistance;
332cdf0e10cSrcweir             }
333cdf0e10cSrcweir         }
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 
337cdf0e10cSrcweir     /** Create masked BitmapEx, where the white areas of rBitmap are
338cdf0e10cSrcweir         transparent, and the other appear in rMaskColor.
339cdf0e10cSrcweir      */
340cdf0e10cSrcweir     BitmapEx createMaskBmpEx( const Bitmap&  rBitmap,
341cdf0e10cSrcweir                               const ::Color& rMaskColor )
342cdf0e10cSrcweir     {
343cdf0e10cSrcweir         const ::Color aWhite( COL_WHITE );
344cdf0e10cSrcweir         BitmapPalette aBiLevelPalette(2);
345cdf0e10cSrcweir         aBiLevelPalette[0] = aWhite;
346cdf0e10cSrcweir         aBiLevelPalette[1] = rMaskColor;
347cdf0e10cSrcweir 
348cdf0e10cSrcweir         Bitmap aMask( rBitmap.CreateMask( aWhite ));
349cdf0e10cSrcweir         Bitmap aSolid( rBitmap.GetSizePixel(),
350cdf0e10cSrcweir                        1,
351cdf0e10cSrcweir                        &aBiLevelPalette );
352cdf0e10cSrcweir         aSolid.Erase( rMaskColor );
353cdf0e10cSrcweir 
354cdf0e10cSrcweir         return BitmapEx( aSolid, aMask );
355cdf0e10cSrcweir     }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir     /** Shameless rip from vcl/source/gdi/outdev3.cxx
358cdf0e10cSrcweir 
359cdf0e10cSrcweir         Should consolidate, into something like basetxt...
360cdf0e10cSrcweir      */
361cdf0e10cSrcweir     sal_Unicode getLocalizedChar( sal_Unicode nChar, LanguageType eLang )
362cdf0e10cSrcweir     {
363cdf0e10cSrcweir         // currently only conversion from ASCII digits is interesting
364cdf0e10cSrcweir         if( (nChar < '0') || ('9' < nChar) )
365cdf0e10cSrcweir             return nChar;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir         sal_Unicode nOffset(0);
368cdf0e10cSrcweir         // eLang & LANGUAGE_MASK_PRIMARY catches language independent of region.
369cdf0e10cSrcweir         // CAVEAT! To some like Mongolian MS assigned the same primary language
370cdf0e10cSrcweir         // although the script type is different!
371cdf0e10cSrcweir         switch( eLang & LANGUAGE_MASK_PRIMARY )
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             default:
374cdf0e10cSrcweir                 break;
375cdf0e10cSrcweir 
376cdf0e10cSrcweir             case LANGUAGE_ARABIC_SAUDI_ARABIA  & LANGUAGE_MASK_PRIMARY:
377cdf0e10cSrcweir             case LANGUAGE_URDU          & LANGUAGE_MASK_PRIMARY:
378cdf0e10cSrcweir             case LANGUAGE_PUNJABI       & LANGUAGE_MASK_PRIMARY: //???
379cdf0e10cSrcweir                 nOffset = 0x0660 - '0';  // arabic/persian/urdu
380cdf0e10cSrcweir                 break;
381cdf0e10cSrcweir             case LANGUAGE_BENGALI       & LANGUAGE_MASK_PRIMARY:
382cdf0e10cSrcweir                 nOffset = 0x09E6 - '0';  // bengali
383cdf0e10cSrcweir                 break;
384cdf0e10cSrcweir             case LANGUAGE_BURMESE       & LANGUAGE_MASK_PRIMARY:
385cdf0e10cSrcweir                 nOffset = 0x1040 - '0';  // burmese
386cdf0e10cSrcweir                 break;
387cdf0e10cSrcweir             case LANGUAGE_HINDI         & LANGUAGE_MASK_PRIMARY:
388cdf0e10cSrcweir                 nOffset = 0x0966 - '0';  // devanagari
389cdf0e10cSrcweir                 break;
390cdf0e10cSrcweir             case LANGUAGE_GUJARATI      & LANGUAGE_MASK_PRIMARY:
391cdf0e10cSrcweir                 nOffset = 0x0AE6 - '0';  // gujarati
392cdf0e10cSrcweir                 break;
393cdf0e10cSrcweir             case LANGUAGE_KANNADA       & LANGUAGE_MASK_PRIMARY:
394cdf0e10cSrcweir                 nOffset = 0x0CE6 - '0';  // kannada
395cdf0e10cSrcweir                 break;
396cdf0e10cSrcweir             case LANGUAGE_KHMER         & LANGUAGE_MASK_PRIMARY:
397cdf0e10cSrcweir                 nOffset = 0x17E0 - '0';  // khmer
398cdf0e10cSrcweir                 break;
399cdf0e10cSrcweir             case LANGUAGE_LAO           & LANGUAGE_MASK_PRIMARY:
400cdf0e10cSrcweir                 nOffset = 0x0ED0 - '0';  // lao
401cdf0e10cSrcweir                 break;
402cdf0e10cSrcweir             case LANGUAGE_MALAYALAM     & LANGUAGE_MASK_PRIMARY:
403cdf0e10cSrcweir                 nOffset = 0x0D66 - '0';   // malayalam
404cdf0e10cSrcweir                 break;
405cdf0e10cSrcweir             case LANGUAGE_MONGOLIAN     & LANGUAGE_MASK_PRIMARY:
406cdf0e10cSrcweir                 if (eLang == LANGUAGE_MONGOLIAN_MONGOLIAN)
407cdf0e10cSrcweir                     nOffset = 0x1810 - '0';   // mongolian
408cdf0e10cSrcweir                 else
409cdf0e10cSrcweir                     nOffset = 0;              // mongolian cyrillic
410cdf0e10cSrcweir                 break;
411cdf0e10cSrcweir             case LANGUAGE_ORIYA         & LANGUAGE_MASK_PRIMARY:
412cdf0e10cSrcweir                 nOffset = 0x0B66 - '0';   // oriya
413cdf0e10cSrcweir                 break;
414cdf0e10cSrcweir             case LANGUAGE_TAMIL         & LANGUAGE_MASK_PRIMARY:
415cdf0e10cSrcweir                 nOffset = 0x0BE7 - '0';   // tamil
416cdf0e10cSrcweir                 break;
417cdf0e10cSrcweir             case LANGUAGE_TELUGU        & LANGUAGE_MASK_PRIMARY:
418cdf0e10cSrcweir                 nOffset = 0x0C66 - '0';   // telugu
419cdf0e10cSrcweir                 break;
420cdf0e10cSrcweir             case LANGUAGE_THAI          & LANGUAGE_MASK_PRIMARY:
421cdf0e10cSrcweir                 nOffset = 0x0E50 - '0';   // thai
422cdf0e10cSrcweir                 break;
423cdf0e10cSrcweir             case LANGUAGE_TIBETAN       & LANGUAGE_MASK_PRIMARY:
424cdf0e10cSrcweir                 nOffset = 0x0F20 - '0';   // tibetan
425cdf0e10cSrcweir                 break;
426cdf0e10cSrcweir         }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir         nChar = sal::static_int_cast<sal_Unicode>(nChar + nOffset);
429cdf0e10cSrcweir         return nChar;
430cdf0e10cSrcweir     }
431cdf0e10cSrcweir 
432cdf0e10cSrcweir     void convertToLocalizedNumerals( XubString&   rStr,
433cdf0e10cSrcweir                                      LanguageType eTextLanguage )
434cdf0e10cSrcweir     {
435cdf0e10cSrcweir         const sal_Unicode* pBase = rStr.GetBuffer();
436cdf0e10cSrcweir         const sal_Unicode* pBegin = pBase + 0;
437cdf0e10cSrcweir         const xub_StrLen nEndIndex = rStr.Len();
438cdf0e10cSrcweir         const sal_Unicode* pEnd = pBase + nEndIndex;
439cdf0e10cSrcweir 
440cdf0e10cSrcweir         for( ; pBegin < pEnd; ++pBegin )
441cdf0e10cSrcweir         {
442cdf0e10cSrcweir             // TODO: are there non-digit localizations?
443cdf0e10cSrcweir             if( (*pBegin >= '0') && (*pBegin <= '9') )
444cdf0e10cSrcweir             {
445cdf0e10cSrcweir                 // translate characters to local preference
446cdf0e10cSrcweir                 sal_Unicode cChar = getLocalizedChar( *pBegin, eTextLanguage );
447cdf0e10cSrcweir                 if( cChar != *pBegin )
448cdf0e10cSrcweir                     rStr.SetChar( sal::static_int_cast<sal_uInt16>(pBegin - pBase), cChar );
449cdf0e10cSrcweir             }
450cdf0e10cSrcweir         }
451cdf0e10cSrcweir     }
452cdf0e10cSrcweir }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir 
455cdf0e10cSrcweir namespace cppcanvas
456cdf0e10cSrcweir {
457cdf0e10cSrcweir     namespace internal
458cdf0e10cSrcweir     {
459cdf0e10cSrcweir         bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolyPolygon& rPolyPoly,
460cdf0e10cSrcweir                                                 const ActionFactoryParameters&   rParms )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir             const OutDevState& rState( getState( rParms.mrStates ) );
463cdf0e10cSrcweir             if( (!rState.isLineColorSet &&
464cdf0e10cSrcweir                  !rState.isFillColorSet) ||
465cdf0e10cSrcweir                 (rState.lineColor.getLength() == 0 &&
466cdf0e10cSrcweir                  rState.fillColor.getLength() == 0) )
467cdf0e10cSrcweir             {
468cdf0e10cSrcweir                 return false;
469cdf0e10cSrcweir             }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir             ActionSharedPtr pPolyAction(
472cdf0e10cSrcweir                 internal::PolyPolyActionFactory::createPolyPolyAction(
473cdf0e10cSrcweir                     rPolyPoly, rParms.mrCanvas, rState ) );
474cdf0e10cSrcweir 
475cdf0e10cSrcweir             if( pPolyAction )
476cdf0e10cSrcweir             {
477cdf0e10cSrcweir                 maActions.push_back(
478cdf0e10cSrcweir                     MtfAction(
479cdf0e10cSrcweir                         pPolyAction,
480cdf0e10cSrcweir                         rParms.mrCurrActionIndex ) );
481cdf0e10cSrcweir 
482cdf0e10cSrcweir                 rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
483cdf0e10cSrcweir             }
484cdf0e10cSrcweir 
485cdf0e10cSrcweir             return true;
486cdf0e10cSrcweir         }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir         bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolygon&   rPoly,
489cdf0e10cSrcweir                                                 const ActionFactoryParameters& rParms )
490cdf0e10cSrcweir         {
491cdf0e10cSrcweir             return createFillAndStroke( ::basegfx::B2DPolyPolygon( rPoly ),
492cdf0e10cSrcweir                                         rParms );
493cdf0e10cSrcweir         }
494cdf0e10cSrcweir 
495cdf0e10cSrcweir         void ImplRenderer::skipContent( GDIMetaFile& rMtf,
496cdf0e10cSrcweir                                         const char*  pCommentString,
497cdf0e10cSrcweir                                         sal_Int32& 	 io_rCurrActionIndex ) const
498cdf0e10cSrcweir         {
499cdf0e10cSrcweir             ENSURE_OR_THROW( pCommentString,
500cdf0e10cSrcweir                               "ImplRenderer::skipContent(): NULL string given" );
501cdf0e10cSrcweir 
502cdf0e10cSrcweir             MetaAction* pCurrAct;
503cdf0e10cSrcweir             while( (pCurrAct=rMtf.NextAction()) != NULL )
504cdf0e10cSrcweir             {
505cdf0e10cSrcweir                 // increment action index, we've skipped an action.
506cdf0e10cSrcweir                 ++io_rCurrActionIndex;
507cdf0e10cSrcweir 
508cdf0e10cSrcweir                 if( pCurrAct->GetType() == META_COMMENT_ACTION &&
509cdf0e10cSrcweir                     static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
510cdf0e10cSrcweir                         pCommentString ) == COMPARE_EQUAL )
511cdf0e10cSrcweir                 {
512cdf0e10cSrcweir                     // requested comment found, done
513cdf0e10cSrcweir                     return;
514cdf0e10cSrcweir                 }
515cdf0e10cSrcweir             }
516cdf0e10cSrcweir 
517cdf0e10cSrcweir             // EOF
518cdf0e10cSrcweir             return;
519cdf0e10cSrcweir         }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir         bool ImplRenderer::isActionContained( GDIMetaFile& rMtf,
522cdf0e10cSrcweir                                               const char*  pCommentString,
523cdf0e10cSrcweir                                               sal_uInt16	   nType ) const
524cdf0e10cSrcweir         {
525cdf0e10cSrcweir             ENSURE_OR_THROW( pCommentString,
526cdf0e10cSrcweir                               "ImplRenderer::isActionContained(): NULL string given" );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir             bool bRet( false );
529cdf0e10cSrcweir 
530cdf0e10cSrcweir             // at least _one_ call to GDIMetaFile::NextAction() is
531cdf0e10cSrcweir             // executed
532cdf0e10cSrcweir             sal_uIntPtr nPos( 1 );
533cdf0e10cSrcweir 
534cdf0e10cSrcweir             MetaAction* pCurrAct;
535cdf0e10cSrcweir             while( (pCurrAct=rMtf.NextAction()) != NULL )
536cdf0e10cSrcweir             {
537cdf0e10cSrcweir                 if( pCurrAct->GetType() == nType )
538cdf0e10cSrcweir                 {
539cdf0e10cSrcweir                     bRet = true; // action type found
540cdf0e10cSrcweir                     break;
541cdf0e10cSrcweir                 }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir                 if( pCurrAct->GetType() == META_COMMENT_ACTION &&
544cdf0e10cSrcweir                     static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
545cdf0e10cSrcweir                         pCommentString ) == COMPARE_EQUAL )
546cdf0e10cSrcweir                 {
547cdf0e10cSrcweir                     // delimiting end comment found, done
548cdf0e10cSrcweir                     bRet = false; // not yet found
549cdf0e10cSrcweir                     break;
550cdf0e10cSrcweir                 }
551cdf0e10cSrcweir 
552cdf0e10cSrcweir                 ++nPos;
553cdf0e10cSrcweir             }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir             // rewind metafile to previous position (this method must
556cdf0e10cSrcweir             // not change the current metaaction)
557cdf0e10cSrcweir             while( nPos-- )
558cdf0e10cSrcweir                 rMtf.WindPrev();
559cdf0e10cSrcweir 
560cdf0e10cSrcweir             if( !pCurrAct )
561cdf0e10cSrcweir             {
562cdf0e10cSrcweir                 // EOF, and not yet found
563cdf0e10cSrcweir                 bRet = false;
564cdf0e10cSrcweir             }
565cdf0e10cSrcweir 
566cdf0e10cSrcweir             return bRet;
567cdf0e10cSrcweir         }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir         void ImplRenderer::createGradientAction( const ::PolyPolygon& 			rPoly,
570cdf0e10cSrcweir                                                  const ::Gradient&				rGradient,
571cdf0e10cSrcweir                                                  const ActionFactoryParameters& rParms,
572cdf0e10cSrcweir                                                  bool							bIsPolygonRectangle,
573cdf0e10cSrcweir                                                  bool 							bSubsettableActions )
574cdf0e10cSrcweir         {
575cdf0e10cSrcweir             DBG_TESTSOLARMUTEX();
576cdf0e10cSrcweir 
577cdf0e10cSrcweir             ::basegfx::B2DPolyPolygon aDevicePoly( rPoly.getB2DPolyPolygon() );
578cdf0e10cSrcweir             aDevicePoly.transform( getState( rParms.mrStates ).mapModeTransform );
579cdf0e10cSrcweir 
580cdf0e10cSrcweir             // decide, whether this gradient can be rendered natively
581cdf0e10cSrcweir             // by the canvas, or must be emulated via VCL gradient
582cdf0e10cSrcweir             // action extraction.
583cdf0e10cSrcweir             const sal_uInt16 nSteps( rGradient.GetSteps() );
584cdf0e10cSrcweir 
585cdf0e10cSrcweir             if( // step count is infinite, can use native canvas
586cdf0e10cSrcweir                 // gradients here
587cdf0e10cSrcweir                 nSteps == 0 ||
588cdf0e10cSrcweir                 // step count is sufficiently high, such that no
589cdf0e10cSrcweir                 // discernible difference should be visible.
590cdf0e10cSrcweir                 nSteps > 64 )
591cdf0e10cSrcweir             {
592cdf0e10cSrcweir                 uno::Reference< lang::XMultiServiceFactory> xFactory(
593cdf0e10cSrcweir                     rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
594cdf0e10cSrcweir 
595cdf0e10cSrcweir                 if( xFactory.is() )
596cdf0e10cSrcweir                 {
597cdf0e10cSrcweir                     rendering::Texture aTexture;
598cdf0e10cSrcweir 
599cdf0e10cSrcweir                     aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
600cdf0e10cSrcweir                     aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
601cdf0e10cSrcweir                     aTexture.Alpha = 1.0;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 
604cdf0e10cSrcweir                     // setup start/end color values
605cdf0e10cSrcweir                     // ----------------------------
606cdf0e10cSrcweir 
607cdf0e10cSrcweir                     // scale color coefficients with gradient intensities
608cdf0e10cSrcweir                     const sal_uInt16 nStartIntensity( rGradient.GetStartIntensity() );
609cdf0e10cSrcweir                     ::Color aVCLStartColor( rGradient.GetStartColor() );
610cdf0e10cSrcweir                     aVCLStartColor.SetRed( (sal_uInt8)(aVCLStartColor.GetRed() * nStartIntensity / 100) );
611cdf0e10cSrcweir                     aVCLStartColor.SetGreen( (sal_uInt8)(aVCLStartColor.GetGreen() * nStartIntensity / 100) );
612cdf0e10cSrcweir                     aVCLStartColor.SetBlue( (sal_uInt8)(aVCLStartColor.GetBlue() * nStartIntensity / 100) );
613cdf0e10cSrcweir 
614cdf0e10cSrcweir                     const sal_uInt16 nEndIntensity( rGradient.GetEndIntensity() );
615cdf0e10cSrcweir                     ::Color aVCLEndColor( rGradient.GetEndColor() );
616cdf0e10cSrcweir                     aVCLEndColor.SetRed( (sal_uInt8)(aVCLEndColor.GetRed() * nEndIntensity / 100) );
617cdf0e10cSrcweir                     aVCLEndColor.SetGreen( (sal_uInt8)(aVCLEndColor.GetGreen() * nEndIntensity / 100) );
618cdf0e10cSrcweir                     aVCLEndColor.SetBlue( (sal_uInt8)(aVCLEndColor.GetBlue() * nEndIntensity / 100) );
619cdf0e10cSrcweir 
620cdf0e10cSrcweir                     uno::Reference<rendering::XColorSpace> xColorSpace(
621cdf0e10cSrcweir                         rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
622cdf0e10cSrcweir                     const uno::Sequence< double > aStartColor(
623cdf0e10cSrcweir                         ::vcl::unotools::colorToDoubleSequence( aVCLStartColor,
624cdf0e10cSrcweir                                                                 xColorSpace ));
625cdf0e10cSrcweir                     const uno::Sequence< double > aEndColor(
626cdf0e10cSrcweir                         ::vcl::unotools::colorToDoubleSequence( aVCLEndColor,
627cdf0e10cSrcweir                                                                 xColorSpace ));
628cdf0e10cSrcweir 
629cdf0e10cSrcweir                     uno::Sequence< uno::Sequence < double > > aColors(2);
630cdf0e10cSrcweir                     uno::Sequence< double > aStops(2);
631cdf0e10cSrcweir 
632cdf0e10cSrcweir                     if( rGradient.GetStyle() == GRADIENT_AXIAL )
633cdf0e10cSrcweir                     {
634cdf0e10cSrcweir                         aStops.realloc(3);
635cdf0e10cSrcweir                         aColors.realloc(3);
636cdf0e10cSrcweir 
637cdf0e10cSrcweir                         aStops[0] = 0.0;
638cdf0e10cSrcweir                         aStops[1] = 0.5;
639cdf0e10cSrcweir                         aStops[2] = 1.0;
640cdf0e10cSrcweir 
641cdf0e10cSrcweir                         aColors[0] = aEndColor;
642cdf0e10cSrcweir                         aColors[1] = aStartColor;
643cdf0e10cSrcweir                         aColors[2] = aEndColor;
644cdf0e10cSrcweir                     }
645cdf0e10cSrcweir                     else
646cdf0e10cSrcweir                     {
647cdf0e10cSrcweir                         aStops[0] = 0.0;
648cdf0e10cSrcweir                         aStops[1] = 1.0;
649cdf0e10cSrcweir 
650cdf0e10cSrcweir                         aColors[0] = aStartColor;
651cdf0e10cSrcweir                         aColors[1] = aEndColor;
652cdf0e10cSrcweir                     }
653cdf0e10cSrcweir 
654cdf0e10cSrcweir                     const ::basegfx::B2DRectangle aBounds(
655cdf0e10cSrcweir                         ::basegfx::tools::getRange(aDevicePoly) );
656cdf0e10cSrcweir                     const ::basegfx::B2DVector aOffset(
657cdf0e10cSrcweir                         rGradient.GetOfsX() / 100.0,
658cdf0e10cSrcweir                         rGradient.GetOfsY() / 100.0);
659cdf0e10cSrcweir                     double fRotation( rGradient.GetAngle() * M_PI / 1800.0 );
660cdf0e10cSrcweir                     const double fBorder( rGradient.GetBorder() / 100.0 );
661cdf0e10cSrcweir 
662cdf0e10cSrcweir                     basegfx::B2DHomMatrix aRot90;
663cdf0e10cSrcweir                     aRot90.rotate(M_PI_2);
664cdf0e10cSrcweir 
665cdf0e10cSrcweir                     basegfx::ODFGradientInfo aGradInfo;
666cdf0e10cSrcweir                     rtl::OUString aGradientService;
667cdf0e10cSrcweir                     switch( rGradient.GetStyle() )
668cdf0e10cSrcweir                     {
669cdf0e10cSrcweir                         case GRADIENT_LINEAR:
670cdf0e10cSrcweir                             basegfx::tools::createLinearODFGradientInfo(aGradInfo,
671cdf0e10cSrcweir                                                                         aBounds,
672cdf0e10cSrcweir                                                                         nSteps,
673cdf0e10cSrcweir                                                                         fBorder,
674cdf0e10cSrcweir                                                                         fRotation);
675cdf0e10cSrcweir                             // map odf to svg gradient orientation - x
676cdf0e10cSrcweir                             // instead of y direction
677cdf0e10cSrcweir                             aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
678cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("LinearGradient");
679cdf0e10cSrcweir                             break;
680cdf0e10cSrcweir 
681cdf0e10cSrcweir                         case GRADIENT_AXIAL:
682cdf0e10cSrcweir                         {
683cdf0e10cSrcweir                             // Adapt the border so that it is suitable
684cdf0e10cSrcweir                             // for the axial gradient.  An axial
685cdf0e10cSrcweir                             // gradient consists of two linear
686cdf0e10cSrcweir                             // gradients.  Each of those covers half
687cdf0e10cSrcweir                             // of the total size.  In order to
688cdf0e10cSrcweir                             // compensate for the condensed display of
689cdf0e10cSrcweir                             // the linear gradients, we have to
690cdf0e10cSrcweir                             // enlarge the area taken up by the actual
691cdf0e10cSrcweir                             // gradient (1-fBorder).  After that we
692cdf0e10cSrcweir                             // have to turn the result back into a
693cdf0e10cSrcweir                             // border value, hence the second (left
694cdf0e10cSrcweir                             // most 1-...
695cdf0e10cSrcweir                             const double fAxialBorder (1-2*(1-fBorder));
696cdf0e10cSrcweir                             basegfx::tools::createAxialODFGradientInfo(aGradInfo,
697cdf0e10cSrcweir                                                                         aBounds,
698cdf0e10cSrcweir                                                                         nSteps,
699cdf0e10cSrcweir                                                                         fAxialBorder,
700cdf0e10cSrcweir                                                                         fRotation);
701cdf0e10cSrcweir                             // map odf to svg gradient orientation - x
702cdf0e10cSrcweir                             // instead of y direction
703cdf0e10cSrcweir                             aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
704cdf0e10cSrcweir 
705cdf0e10cSrcweir                             // map odf axial gradient to 3-stop linear
706cdf0e10cSrcweir                             // gradient - shift left by 0.5
707cdf0e10cSrcweir                             basegfx::B2DHomMatrix aShift;
708cdf0e10cSrcweir                             aShift.translate(-0.5,0);
709cdf0e10cSrcweir                             aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aShift;
710cdf0e10cSrcweir 
711cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("LinearGradient");
712cdf0e10cSrcweir                             break;
713cdf0e10cSrcweir                         }
714cdf0e10cSrcweir 
715cdf0e10cSrcweir                         case GRADIENT_RADIAL:
716cdf0e10cSrcweir                             basegfx::tools::createRadialODFGradientInfo(aGradInfo,
717cdf0e10cSrcweir                                                                         aBounds,
718cdf0e10cSrcweir                                                                         aOffset,
719cdf0e10cSrcweir                                                                         nSteps,
720cdf0e10cSrcweir                                                                         fBorder);
721cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("EllipticalGradient");
722cdf0e10cSrcweir                             break;
723cdf0e10cSrcweir 
724cdf0e10cSrcweir                         case GRADIENT_ELLIPTICAL:
725cdf0e10cSrcweir                             basegfx::tools::createEllipticalODFGradientInfo(aGradInfo,
726cdf0e10cSrcweir                                                                             aBounds,
727cdf0e10cSrcweir                                                                             aOffset,
728cdf0e10cSrcweir                                                                             nSteps,
729cdf0e10cSrcweir                                                                             fBorder,
730cdf0e10cSrcweir                                                                             fRotation);
731cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("EllipticalGradient");
732cdf0e10cSrcweir                             break;
733cdf0e10cSrcweir 
734cdf0e10cSrcweir                         case GRADIENT_SQUARE:
735cdf0e10cSrcweir                             basegfx::tools::createSquareODFGradientInfo(aGradInfo,
736cdf0e10cSrcweir                                                                         aBounds,
737cdf0e10cSrcweir                                                                         aOffset,
738cdf0e10cSrcweir                                                                         nSteps,
739cdf0e10cSrcweir                                                                         fBorder,
740cdf0e10cSrcweir                                                                         fRotation);
741cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("RectangularGradient");
742cdf0e10cSrcweir                             break;
743cdf0e10cSrcweir 
744cdf0e10cSrcweir                         case GRADIENT_RECT:
745cdf0e10cSrcweir                             basegfx::tools::createRectangularODFGradientInfo(aGradInfo,
746cdf0e10cSrcweir                                                                              aBounds,
747cdf0e10cSrcweir                                                                              aOffset,
748cdf0e10cSrcweir                                                                              nSteps,
749cdf0e10cSrcweir                                                                              fBorder,
750cdf0e10cSrcweir                                                                              fRotation);
751cdf0e10cSrcweir                             aGradientService = rtl::OUString::createFromAscii("RectangularGradient");
752cdf0e10cSrcweir                             break;
753cdf0e10cSrcweir 
754cdf0e10cSrcweir                         default:
755cdf0e10cSrcweir                             ENSURE_OR_THROW( false,
756cdf0e10cSrcweir                                              "ImplRenderer::createGradientAction(): Unexpected gradient type" );
757cdf0e10cSrcweir                             break;
758cdf0e10cSrcweir                     }
759cdf0e10cSrcweir 
760cdf0e10cSrcweir                     // As the texture coordinate space is relative to
761cdf0e10cSrcweir                     // the polygon coordinate space (NOT to the
762cdf0e10cSrcweir                     // polygon itself), move gradient to the start of
763cdf0e10cSrcweir                     // the actual polygon. If we skip this, the
764cdf0e10cSrcweir                     // gradient will always display at the origin, and
765cdf0e10cSrcweir                     // not within the polygon bound (which might be
766cdf0e10cSrcweir                     // miles away from the origin).
767cdf0e10cSrcweir                     aGradInfo.maTextureTransform.translate( aBounds.getMinX(),
768cdf0e10cSrcweir                                                             aBounds.getMinY() );
769cdf0e10cSrcweir                     ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
770cdf0e10cSrcweir                                                                     aGradInfo.maTextureTransform );
771cdf0e10cSrcweir 
772cdf0e10cSrcweir                     uno::Sequence<uno::Any> args(3);
773cdf0e10cSrcweir                     beans::PropertyValue aProp;
774cdf0e10cSrcweir                     aProp.Name = rtl::OUString::createFromAscii("Colors");
775cdf0e10cSrcweir                     aProp.Value <<= aColors;
776cdf0e10cSrcweir                     args[0] <<= aProp;
777cdf0e10cSrcweir                     aProp.Name = rtl::OUString::createFromAscii("Stops");
778cdf0e10cSrcweir                     aProp.Value <<= aStops;
779cdf0e10cSrcweir                     args[1] <<= aProp;
780cdf0e10cSrcweir                     aProp.Name = rtl::OUString::createFromAscii("AspectRatio");
781cdf0e10cSrcweir                     aProp.Value <<= aGradInfo.mfAspectRatio;
782cdf0e10cSrcweir                     args[2] <<= aProp;
783cdf0e10cSrcweir 
784cdf0e10cSrcweir                     aTexture.Gradient.set(
785cdf0e10cSrcweir                         xFactory->createInstanceWithArguments(aGradientService,
786cdf0e10cSrcweir                                                               args),
787cdf0e10cSrcweir                         uno::UNO_QUERY);
788cdf0e10cSrcweir                     if( aTexture.Gradient.is() )
789cdf0e10cSrcweir                     {
790cdf0e10cSrcweir                         ActionSharedPtr pPolyAction(
791cdf0e10cSrcweir                             internal::PolyPolyActionFactory::createPolyPolyAction(
792cdf0e10cSrcweir                                 aDevicePoly,
793cdf0e10cSrcweir                                 rParms.mrCanvas,
794cdf0e10cSrcweir                                 getState( rParms.mrStates ),
795cdf0e10cSrcweir                                 aTexture ) );
796cdf0e10cSrcweir 
797cdf0e10cSrcweir                         if( pPolyAction )
798cdf0e10cSrcweir                         {
799cdf0e10cSrcweir                             maActions.push_back(
800cdf0e10cSrcweir                                 MtfAction(
801cdf0e10cSrcweir                                     pPolyAction,
802cdf0e10cSrcweir                                     rParms.mrCurrActionIndex ) );
803cdf0e10cSrcweir 
804cdf0e10cSrcweir                             rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
805cdf0e10cSrcweir                         }
806cdf0e10cSrcweir 
807cdf0e10cSrcweir                         // done, using native gradients
808cdf0e10cSrcweir                         return;
809cdf0e10cSrcweir                     }
810cdf0e10cSrcweir                 }
811cdf0e10cSrcweir             }
812cdf0e10cSrcweir 
813cdf0e10cSrcweir             // cannot currently use native canvas gradients, as a
814cdf0e10cSrcweir             // finite step size is given (this funny feature is not
815cdf0e10cSrcweir             // supported by the XCanvas API)
816cdf0e10cSrcweir             pushState( rParms.mrStates, PUSH_ALL );
817cdf0e10cSrcweir 
818cdf0e10cSrcweir             if( !bIsPolygonRectangle )
819cdf0e10cSrcweir             {
820cdf0e10cSrcweir                 // only clip, if given polygon is not a rectangle in
821cdf0e10cSrcweir                 // the first place (the gradient is always limited to
822cdf0e10cSrcweir                 // the given bound rect)
823cdf0e10cSrcweir                 updateClipping(
824cdf0e10cSrcweir                     aDevicePoly,
825cdf0e10cSrcweir                     rParms,
826cdf0e10cSrcweir                     true );
827cdf0e10cSrcweir             }
828cdf0e10cSrcweir 
829cdf0e10cSrcweir             GDIMetaFile aTmpMtf;
830cdf0e10cSrcweir             rParms.mrVDev.AddGradientActions( rPoly.GetBoundRect(),
831cdf0e10cSrcweir                                               rGradient,
832cdf0e10cSrcweir                                                aTmpMtf );
833cdf0e10cSrcweir 
834cdf0e10cSrcweir             createActions( aTmpMtf, rParms, bSubsettableActions );
835cdf0e10cSrcweir 
836cdf0e10cSrcweir             popState( rParms.mrStates );
837cdf0e10cSrcweir         }
838cdf0e10cSrcweir 
839cdf0e10cSrcweir         uno::Reference< rendering::XCanvasFont > ImplRenderer::createFont( double&                        o_rFontRotation,
840cdf0e10cSrcweir                                                                            const ::Font&                  rFont,
841cdf0e10cSrcweir                                                                            const ActionFactoryParameters& rParms ) const
842cdf0e10cSrcweir         {
843cdf0e10cSrcweir             rendering::FontRequest aFontRequest;
844cdf0e10cSrcweir 
845cdf0e10cSrcweir             if( rParms.mrParms.maFontName.is_initialized() )
846cdf0e10cSrcweir                 aFontRequest.FontDescription.FamilyName = *rParms.mrParms.maFontName;
847cdf0e10cSrcweir             else
848cdf0e10cSrcweir                 aFontRequest.FontDescription.FamilyName = rFont.GetName();
849cdf0e10cSrcweir 
850cdf0e10cSrcweir             aFontRequest.FontDescription.StyleName = rFont.GetStyleName();
851cdf0e10cSrcweir 
852cdf0e10cSrcweir             aFontRequest.FontDescription.IsSymbolFont = (rFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL) ? util::TriState_YES : util::TriState_NO;
853cdf0e10cSrcweir             aFontRequest.FontDescription.IsVertical = rFont.IsVertical() ? util::TriState_YES : util::TriState_NO;
854cdf0e10cSrcweir 
855cdf0e10cSrcweir             // TODO(F2): improve vclenum->panose conversion
856cdf0e10cSrcweir             aFontRequest.FontDescription.FontDescription.Weight =
857cdf0e10cSrcweir                 rParms.mrParms.maFontWeight.is_initialized() ?
858cdf0e10cSrcweir                 *rParms.mrParms.maFontWeight :
859cdf0e10cSrcweir                 ::canvas::tools::numeric_cast<sal_Int8>( ::basegfx::fround( rFont.GetWeight() ) );
860cdf0e10cSrcweir             aFontRequest.FontDescription.FontDescription.Letterform =
861cdf0e10cSrcweir                 rParms.mrParms.maFontLetterForm.is_initialized() ?
862cdf0e10cSrcweir                 *rParms.mrParms.maFontLetterForm :
863cdf0e10cSrcweir                 (rFont.GetItalic() == ITALIC_NONE) ? 0 : 9;
864cdf0e10cSrcweir             aFontRequest.FontDescription.FontDescription.Proportion =
865cdf0e10cSrcweir                 rParms.mrParms.maFontProportion.is_initialized() ?
866cdf0e10cSrcweir                 *rParms.mrParms.maFontProportion :
867cdf0e10cSrcweir                 (rFont.GetPitch() == PITCH_FIXED)
868cdf0e10cSrcweir                     ? rendering::PanoseProportion::MONO_SPACED
869cdf0e10cSrcweir                     : rendering::PanoseProportion::ANYTHING;
870cdf0e10cSrcweir 
871cdf0e10cSrcweir             LanguageType aLang = rFont.GetLanguage();
872cdf0e10cSrcweir             aFontRequest.Locale = MsLangId::convertLanguageToLocale(aLang, false);
873cdf0e10cSrcweir 
874cdf0e10cSrcweir             // setup state-local text transformation,
875cdf0e10cSrcweir             // if the font be rotated
876cdf0e10cSrcweir             const short nFontAngle( rFont.GetOrientation() );
877cdf0e10cSrcweir             if( nFontAngle != 0 )
878cdf0e10cSrcweir             {
879cdf0e10cSrcweir                 // set to unity transform rotated by font angle
880cdf0e10cSrcweir                 const double nAngle( nFontAngle * (F_PI / 1800.0) );
881cdf0e10cSrcweir                 o_rFontRotation = -nAngle;
882cdf0e10cSrcweir             }
883cdf0e10cSrcweir             else
884cdf0e10cSrcweir             {
885cdf0e10cSrcweir                 o_rFontRotation = 0.0;
886cdf0e10cSrcweir             }
887cdf0e10cSrcweir 
888cdf0e10cSrcweir             geometry::Matrix2D aFontMatrix;
889cdf0e10cSrcweir             ::canvas::tools::setIdentityMatrix2D( aFontMatrix );
890cdf0e10cSrcweir 
891cdf0e10cSrcweir             // TODO(F2): use correct scale direction, font
892cdf0e10cSrcweir             // height might be width or anything else
893cdf0e10cSrcweir 
894cdf0e10cSrcweir             // TODO(Q3): This code smells of programming by
895cdf0e10cSrcweir             // coincidence (the next two if statements)
896cdf0e10cSrcweir             const ::Size rFontSizeLog( rFont.GetSize() );
897cdf0e10cSrcweir             const sal_Int32 nFontWidthLog = rFontSizeLog.Width();
898cdf0e10cSrcweir             if( nFontWidthLog != 0 )
899cdf0e10cSrcweir             {
900cdf0e10cSrcweir                 ::Font aTestFont = rFont;
901cdf0e10cSrcweir                 aTestFont.SetWidth( 0 );
902cdf0e10cSrcweir                 sal_Int32 nNormalWidth = rParms.mrVDev.GetFontMetric( aTestFont ).GetWidth();
903cdf0e10cSrcweir                 if( nNormalWidth != nFontWidthLog )
904cdf0e10cSrcweir                     if( nNormalWidth )
905cdf0e10cSrcweir                         aFontMatrix.m00 = (double)nFontWidthLog / nNormalWidth;
906cdf0e10cSrcweir             }
907cdf0e10cSrcweir 
908cdf0e10cSrcweir             // #i52608# apply map mode scale also to font matrix - an
909cdf0e10cSrcweir             // anisotrophic mapmode must be reflected in an
910cdf0e10cSrcweir             // anisotrophic font matrix scale.
911cdf0e10cSrcweir             const OutDevState& rState( getState( rParms.mrStates ) );
912cdf0e10cSrcweir             if( !::basegfx::fTools::equal(
913cdf0e10cSrcweir                     rState.mapModeTransform.get(0,0),
914cdf0e10cSrcweir                     rState.mapModeTransform.get(1,1)) )
915cdf0e10cSrcweir             {
916cdf0e10cSrcweir                 const double nScaleX( rState.mapModeTransform.get(0,0) );
917cdf0e10cSrcweir                 const double nScaleY( rState.mapModeTransform.get(1,1) );
918cdf0e10cSrcweir 
919cdf0e10cSrcweir                 // note: no reason to check for division by zero, we
920cdf0e10cSrcweir                 // always have the value closer (or equal) to zero as
921cdf0e10cSrcweir                 // the nominator.
922cdf0e10cSrcweir                 if( fabs(nScaleX) < fabs(nScaleY) )
923cdf0e10cSrcweir                     aFontMatrix.m00 *= nScaleX / nScaleY;
924cdf0e10cSrcweir                 else
925cdf0e10cSrcweir                     aFontMatrix.m11 *= nScaleY / nScaleX;
926cdf0e10cSrcweir             }
927cdf0e10cSrcweir             aFontRequest.CellSize = (rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize(rFontSizeLog)).getY();
928cdf0e10cSrcweir 
929cdf0e10cSrcweir             return rParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
930cdf0e10cSrcweir                                                                 uno::Sequence< beans::PropertyValue >(),
931cdf0e10cSrcweir                                                                 aFontMatrix );
932cdf0e10cSrcweir         }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir         // create text effects such as shadow/relief/embossed
935cdf0e10cSrcweir         void ImplRenderer::createTextAction( const ::Point& 		        rStartPoint,
936cdf0e10cSrcweir                                              const String                   rString,
937cdf0e10cSrcweir                                              int                            nIndex,
938cdf0e10cSrcweir                                              int                            nLength,
939cdf0e10cSrcweir                                              const sal_Int32*               pCharWidths,
940cdf0e10cSrcweir                                              const ActionFactoryParameters& rParms,
941cdf0e10cSrcweir                                              bool                           bSubsettableActions )
942cdf0e10cSrcweir         {
943cdf0e10cSrcweir             ENSURE_OR_THROW( nIndex >= 0 && nLength <= rString.Len() + nIndex,
944cdf0e10cSrcweir                               "ImplRenderer::createTextWithEffectsAction(): Invalid text index" );
945cdf0e10cSrcweir 
946cdf0e10cSrcweir             if( !nLength )
947cdf0e10cSrcweir                 return; // zero-length text, no visible output
948cdf0e10cSrcweir 
949cdf0e10cSrcweir             const OutDevState& rState( getState( rParms.mrStates ) );
950cdf0e10cSrcweir 
951cdf0e10cSrcweir             // TODO(F2): implement all text effects
952cdf0e10cSrcweir             // if( rState.textAlignment );             // TODO(F2): NYI
953cdf0e10cSrcweir 
954cdf0e10cSrcweir             ::Color aShadowColor( COL_AUTO );
955cdf0e10cSrcweir             ::Color aReliefColor( COL_AUTO );
956cdf0e10cSrcweir             ::Size  aShadowOffset;
957cdf0e10cSrcweir             ::Size  aReliefOffset;
958cdf0e10cSrcweir 
959cdf0e10cSrcweir             uno::Reference<rendering::XColorSpace> xColorSpace(
960cdf0e10cSrcweir                 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
961cdf0e10cSrcweir 
962cdf0e10cSrcweir             if( rState.isTextEffectShadowSet )
963cdf0e10cSrcweir             {
964cdf0e10cSrcweir                 // calculate shadow offset (similar to outdev3.cxx)
965cdf0e10cSrcweir                 // TODO(F3): better match with outdev3.cxx
966cdf0e10cSrcweir                 sal_Int32 nShadowOffset = static_cast<sal_Int32>(1.5 + ((rParms.mrVDev.GetFont().GetHeight()-24.0)/24.0));
967cdf0e10cSrcweir                 if( nShadowOffset < 1 )
968cdf0e10cSrcweir                     nShadowOffset = 1;
969cdf0e10cSrcweir 
970cdf0e10cSrcweir                 aShadowOffset.setWidth( nShadowOffset );
971cdf0e10cSrcweir                 aShadowOffset.setHeight( nShadowOffset );
972cdf0e10cSrcweir 
973cdf0e10cSrcweir                 // determine shadow color (from outdev3.cxx)
974cdf0e10cSrcweir                 ::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
975cdf0e10cSrcweir                     rState.textColor, xColorSpace );
976cdf0e10cSrcweir                 bool bIsDark = (aTextColor.GetColor() == COL_BLACK)
977cdf0e10cSrcweir                     || (aTextColor.GetLuminance() < 8);
978cdf0e10cSrcweir 
979cdf0e10cSrcweir                 aShadowColor = bIsDark ? COL_LIGHTGRAY : COL_BLACK;
980cdf0e10cSrcweir                 aShadowColor.SetTransparency( aTextColor.GetTransparency() );
981cdf0e10cSrcweir             }
982cdf0e10cSrcweir 
983cdf0e10cSrcweir             if( rState.textReliefStyle )
984cdf0e10cSrcweir             {
985cdf0e10cSrcweir                 // calculate relief offset (similar to outdev3.cxx)
986cdf0e10cSrcweir                 sal_Int32 nReliefOffset = rParms.mrVDev.PixelToLogic( Size( 1, 1 ) ).Height();
987cdf0e10cSrcweir                 nReliefOffset += nReliefOffset/2;
988cdf0e10cSrcweir                 if( nReliefOffset < 1 )
989cdf0e10cSrcweir                     nReliefOffset = 1;
990cdf0e10cSrcweir 
991cdf0e10cSrcweir                 if( rState.textReliefStyle == RELIEF_ENGRAVED )
992cdf0e10cSrcweir                     nReliefOffset = -nReliefOffset;
993cdf0e10cSrcweir 
994cdf0e10cSrcweir                 aReliefOffset.setWidth( nReliefOffset );
995cdf0e10cSrcweir                 aReliefOffset.setHeight( nReliefOffset );
996cdf0e10cSrcweir 
997cdf0e10cSrcweir                 // determine relief color (from outdev3.cxx)
998cdf0e10cSrcweir                 ::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
999cdf0e10cSrcweir                     rState.textColor, xColorSpace );
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir                 aReliefColor = ::Color( COL_LIGHTGRAY );
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir                 // we don't have a automatic color, so black is always
1004cdf0e10cSrcweir                 // drawn on white (literally copied from
1005cdf0e10cSrcweir                 // vcl/source/gdi/outdev3.cxx)
1006cdf0e10cSrcweir                 if( aTextColor.GetColor() == COL_BLACK )
1007cdf0e10cSrcweir                 {
1008cdf0e10cSrcweir                     aTextColor = ::Color( COL_WHITE );
1009cdf0e10cSrcweir                     getState( rParms.mrStates ).textColor =
1010cdf0e10cSrcweir                         ::vcl::unotools::colorToDoubleSequence(
1011cdf0e10cSrcweir                             aTextColor, xColorSpace );
1012cdf0e10cSrcweir                 }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir                 if( aTextColor.GetColor() == COL_WHITE )
1015cdf0e10cSrcweir                     aReliefColor = ::Color( COL_BLACK );
1016cdf0e10cSrcweir                 aReliefColor.SetTransparency( aTextColor.GetTransparency() );
1017cdf0e10cSrcweir             }
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir             // create the actual text action
1020cdf0e10cSrcweir             ActionSharedPtr pTextAction(
1021cdf0e10cSrcweir                 TextActionFactory::createTextAction(
1022cdf0e10cSrcweir                     rStartPoint,
1023cdf0e10cSrcweir                     aReliefOffset,
1024cdf0e10cSrcweir                     aReliefColor,
1025cdf0e10cSrcweir                     aShadowOffset,
1026cdf0e10cSrcweir                     aShadowColor,
1027cdf0e10cSrcweir                     rString,
1028cdf0e10cSrcweir                     nIndex,
1029cdf0e10cSrcweir                     nLength,
1030cdf0e10cSrcweir                     pCharWidths,
1031cdf0e10cSrcweir                     rParms.mrVDev,
1032cdf0e10cSrcweir                     rParms.mrCanvas,
1033cdf0e10cSrcweir                     rState,
1034cdf0e10cSrcweir                     rParms.mrParms,
1035cdf0e10cSrcweir                     bSubsettableActions ) );
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir             ActionSharedPtr pStrikeoutTextAction;
1038cdf0e10cSrcweir 
1039cdf0e10cSrcweir             if ( rState.textStrikeoutStyle == STRIKEOUT_X || rState.textStrikeoutStyle == STRIKEOUT_SLASH )
1040cdf0e10cSrcweir             {
1041cdf0e10cSrcweir                 long nWidth = rParms.mrVDev.GetTextWidth( rString,nIndex,nLength );
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir                 xub_Unicode pChars[5];
1044cdf0e10cSrcweir                 if ( rState.textStrikeoutStyle == STRIKEOUT_X )
1045cdf0e10cSrcweir                     pChars[0] = 'X';
1046cdf0e10cSrcweir                 else
1047cdf0e10cSrcweir                     pChars[0] = '/';
1048cdf0e10cSrcweir                 pChars[3]=pChars[2]=pChars[1]=pChars[0];
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir                 long nStrikeoutWidth = nWidth;
1051cdf0e10cSrcweir                 String aStrikeoutTest( pChars, 4 );
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir                 if( aStrikeoutTest.Len() )
1054cdf0e10cSrcweir                 {
1055cdf0e10cSrcweir                     nStrikeoutWidth = ( rParms.mrVDev.GetTextWidth( aStrikeoutTest ) + 2 ) / 4;
1056cdf0e10cSrcweir                     aStrikeoutTest.Erase();
1057cdf0e10cSrcweir 
1058cdf0e10cSrcweir                     if( nStrikeoutWidth <= 0 )
1059cdf0e10cSrcweir                         nStrikeoutWidth = 1;
1060cdf0e10cSrcweir                 }
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir                 long nMaxWidth = nStrikeoutWidth/2;
1063cdf0e10cSrcweir                 if ( nMaxWidth < 2 )
1064cdf0e10cSrcweir                     nMaxWidth = 2;
1065cdf0e10cSrcweir                 nMaxWidth += nWidth + 1;
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir                 long nFullStrikeoutWidth = 0;
1068cdf0e10cSrcweir                 String aStrikeoutText( pChars, 0 );
1069cdf0e10cSrcweir                 while( (nFullStrikeoutWidth+=nStrikeoutWidth ) < nMaxWidth+1 )
1070cdf0e10cSrcweir                     aStrikeoutText += pChars[0];
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir                 sal_Int32 nStartPos = 0;
1074cdf0e10cSrcweir                 xub_StrLen nLen = aStrikeoutText.Len();
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir                 if( nLen )
1077cdf0e10cSrcweir                 {
1078cdf0e10cSrcweir                     long nInterval = ( nWidth - nStrikeoutWidth * nLen ) / nLen;
1079cdf0e10cSrcweir                     nStrikeoutWidth += nInterval;
1080cdf0e10cSrcweir                     sal_Int32* pStrikeoutCharWidths = new sal_Int32[nLen];
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir                     for ( int i = 0;i<nLen; i++)
1083cdf0e10cSrcweir                     {
1084cdf0e10cSrcweir                         pStrikeoutCharWidths[i] = nStrikeoutWidth;
1085cdf0e10cSrcweir                     }
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir                     for ( int i = 1;i< nLen; i++ )
1088cdf0e10cSrcweir                     {
1089cdf0e10cSrcweir                         pStrikeoutCharWidths[ i ] += pStrikeoutCharWidths[ i-1 ];
1090cdf0e10cSrcweir                     }
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir                     pStrikeoutTextAction =
1093cdf0e10cSrcweir                         TextActionFactory::createTextAction(
1094cdf0e10cSrcweir                             rStartPoint,
1095cdf0e10cSrcweir                             aReliefOffset,
1096cdf0e10cSrcweir                             aReliefColor,
1097cdf0e10cSrcweir                             aShadowOffset,
1098cdf0e10cSrcweir                             aShadowColor,
1099cdf0e10cSrcweir                             aStrikeoutText,
1100cdf0e10cSrcweir                             nStartPos,
1101cdf0e10cSrcweir                             aStrikeoutText.Len(),
1102cdf0e10cSrcweir                             pStrikeoutCharWidths,
1103cdf0e10cSrcweir                             rParms.mrVDev,
1104cdf0e10cSrcweir                             rParms.mrCanvas,
1105cdf0e10cSrcweir                             rState,
1106cdf0e10cSrcweir                             rParms.mrParms,
1107cdf0e10cSrcweir                             bSubsettableActions ) ;
1108cdf0e10cSrcweir                 }
1109cdf0e10cSrcweir             }
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir             if( pTextAction )
1112cdf0e10cSrcweir             {
1113cdf0e10cSrcweir                 maActions.push_back(
1114cdf0e10cSrcweir                     MtfAction(
1115cdf0e10cSrcweir                         pTextAction,
1116cdf0e10cSrcweir                         rParms.mrCurrActionIndex ) );
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir                 if ( pStrikeoutTextAction )
1119cdf0e10cSrcweir                 {
1120cdf0e10cSrcweir                     maActions.push_back(
1121cdf0e10cSrcweir                         MtfAction(
1122cdf0e10cSrcweir                         pStrikeoutTextAction,
1123cdf0e10cSrcweir                         rParms.mrCurrActionIndex ) );
1124cdf0e10cSrcweir                 }
1125cdf0e10cSrcweir 
1126cdf0e10cSrcweir                 rParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
1127cdf0e10cSrcweir             }
1128cdf0e10cSrcweir 		}
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir         void ImplRenderer::updateClipping( const ::basegfx::B2DPolyPolygon&	rClipPoly,
1131cdf0e10cSrcweir                                            const ActionFactoryParameters&   rParms,
1132cdf0e10cSrcweir                                            bool								bIntersect )
1133cdf0e10cSrcweir         {
1134cdf0e10cSrcweir             ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
1135cdf0e10cSrcweir             ::basegfx::B2DPolyPolygon aClipPoly( rClipPoly );
1136cdf0e10cSrcweir 
1137cdf0e10cSrcweir             const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
1138cdf0e10cSrcweir             const bool bEmptyClipPoly( rState.clip.count() == 0 );
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir             ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
1141cdf0e10cSrcweir                               "ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir             if( !bIntersect ||
1144cdf0e10cSrcweir                 (bEmptyClipRect && bEmptyClipPoly) )
1145cdf0e10cSrcweir             {
1146cdf0e10cSrcweir                 rState.clip = rClipPoly;
1147cdf0e10cSrcweir             }
1148cdf0e10cSrcweir             else
1149cdf0e10cSrcweir             {
1150cdf0e10cSrcweir                 if( !bEmptyClipRect )
1151cdf0e10cSrcweir                 {
1152cdf0e10cSrcweir                     // TODO(P3): Use Liang-Barsky polygon clip here,
1153cdf0e10cSrcweir                     // after all, one object is just a rectangle!
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir                     // convert rect to polygon beforehand, must revert
1156cdf0e10cSrcweir                     // to general polygon clipping here.
1157cdf0e10cSrcweir                     rState.clip = ::basegfx::B2DPolyPolygon(
1158cdf0e10cSrcweir                         ::basegfx::tools::createPolygonFromRect(
1159cdf0e10cSrcweir                             // #121100# VCL rectangular clips always
1160cdf0e10cSrcweir                             // include one more pixel to the right
1161cdf0e10cSrcweir                             // and the bottom
1162cdf0e10cSrcweir                             ::basegfx::B2DRectangle( rState.clipRect.Left(),
1163cdf0e10cSrcweir                                                      rState.clipRect.Top(),
1164cdf0e10cSrcweir                                                      rState.clipRect.Right()+1,
1165cdf0e10cSrcweir                                                      rState.clipRect.Bottom()+1 ) ) );
1166cdf0e10cSrcweir                 }
1167cdf0e10cSrcweir 
1168cdf0e10cSrcweir                 // AW: Simplified
1169cdf0e10cSrcweir 				rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
1170cdf0e10cSrcweir 					aClipPoly, rState.clip, true, false);
1171cdf0e10cSrcweir             }
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir             // by now, our clip resides in the OutDevState::clip
1174cdf0e10cSrcweir             // poly-polygon.
1175cdf0e10cSrcweir             rState.clipRect.SetEmpty();
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir             if( rState.clip.count() == 0 )
1178cdf0e10cSrcweir             {
1179cdf0e10cSrcweir                 if( rState.clipRect.IsEmpty() )
1180cdf0e10cSrcweir                 {
1181cdf0e10cSrcweir                     rState.xClipPoly.clear();
1182cdf0e10cSrcweir                 }
1183cdf0e10cSrcweir                 else
1184cdf0e10cSrcweir                 {
1185cdf0e10cSrcweir                     rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1186cdf0e10cSrcweir                         rParms.mrCanvas->getUNOCanvas()->getDevice(),
1187cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon(
1188cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromRect(
1189cdf0e10cSrcweir                                 // #121100# VCL rectangular clips
1190cdf0e10cSrcweir                                 // always include one more pixel to
1191cdf0e10cSrcweir                                 // the right and the bottom
1192cdf0e10cSrcweir                                 ::basegfx::B2DRectangle( rState.clipRect.Left(),
1193cdf0e10cSrcweir                                                          rState.clipRect.Top(),
1194cdf0e10cSrcweir                                                          rState.clipRect.Right()+1,
1195cdf0e10cSrcweir                                                          rState.clipRect.Bottom()+1 ) ) ) );
1196cdf0e10cSrcweir                 }
1197cdf0e10cSrcweir             }
1198cdf0e10cSrcweir             else
1199cdf0e10cSrcweir             {
1200cdf0e10cSrcweir                 rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1201cdf0e10cSrcweir                     rParms.mrCanvas->getUNOCanvas()->getDevice(),
1202cdf0e10cSrcweir                     rState.clip );
1203cdf0e10cSrcweir             }
1204cdf0e10cSrcweir         }
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir         void ImplRenderer::updateClipping( const ::Rectangle&		      rClipRect,
1207cdf0e10cSrcweir                                            const ActionFactoryParameters& rParms,
1208cdf0e10cSrcweir                                            bool                           bIntersect )
1209cdf0e10cSrcweir         {
1210cdf0e10cSrcweir             ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir             const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
1213cdf0e10cSrcweir             const bool bEmptyClipPoly( rState.clip.count() == 0 );
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir             ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
1216cdf0e10cSrcweir                               "ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir             if( !bIntersect ||
1219cdf0e10cSrcweir                 (bEmptyClipRect && bEmptyClipPoly) )
1220cdf0e10cSrcweir             {
1221cdf0e10cSrcweir                 rState.clipRect = rClipRect;
1222cdf0e10cSrcweir                 rState.clip.clear();
1223cdf0e10cSrcweir             }
1224cdf0e10cSrcweir             else if( bEmptyClipPoly )
1225cdf0e10cSrcweir             {
1226cdf0e10cSrcweir                 rState.clipRect.Intersection( rClipRect );
1227cdf0e10cSrcweir                 rState.clip.clear();
1228cdf0e10cSrcweir             }
1229cdf0e10cSrcweir             else
1230cdf0e10cSrcweir             {
1231cdf0e10cSrcweir                 // TODO(P3): Handle a fourth case here, when all clip
1232cdf0e10cSrcweir                 // polygons are rectangular, once B2DMultiRange's
1233cdf0e10cSrcweir                 // sweep line implementation is done.
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir                 // general case: convert to polygon and clip
1236cdf0e10cSrcweir                 // -----------------------------------------
1237cdf0e10cSrcweir 
1238cdf0e10cSrcweir                 // convert rect to polygon beforehand, must revert
1239cdf0e10cSrcweir                 // to general polygon clipping here.
1240cdf0e10cSrcweir                 ::basegfx::B2DPolyPolygon aClipPoly(
1241cdf0e10cSrcweir                     ::basegfx::tools::createPolygonFromRect(
1242cdf0e10cSrcweir                         ::basegfx::B2DRectangle( rClipRect.Left(),
1243cdf0e10cSrcweir                                                  rClipRect.Top(),
1244cdf0e10cSrcweir                                                  rClipRect.Right(),
1245cdf0e10cSrcweir                                                  rClipRect.Bottom() ) ) );
1246cdf0e10cSrcweir 
1247cdf0e10cSrcweir                 rState.clipRect.SetEmpty();
1248cdf0e10cSrcweir 
1249cdf0e10cSrcweir                 // AW: Simplified
1250cdf0e10cSrcweir 				rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
1251cdf0e10cSrcweir 					aClipPoly, rState.clip, true, false);
1252cdf0e10cSrcweir             }
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir             if( rState.clip.count() == 0 )
1255cdf0e10cSrcweir             {
1256cdf0e10cSrcweir                 if( rState.clipRect.IsEmpty() )
1257cdf0e10cSrcweir                 {
1258cdf0e10cSrcweir                     rState.xClipPoly.clear();
1259cdf0e10cSrcweir                 }
1260cdf0e10cSrcweir                 else
1261cdf0e10cSrcweir                 {
1262cdf0e10cSrcweir                     rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1263cdf0e10cSrcweir                         rParms.mrCanvas->getUNOCanvas()->getDevice(),
1264cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon(
1265cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromRect(
1266cdf0e10cSrcweir                                 // #121100# VCL rectangular clips
1267cdf0e10cSrcweir                                 // always include one more pixel to
1268cdf0e10cSrcweir                                 // the right and the bottom
1269cdf0e10cSrcweir                                 ::basegfx::B2DRectangle( rState.clipRect.Left(),
1270cdf0e10cSrcweir                                                          rState.clipRect.Top(),
1271cdf0e10cSrcweir                                                          rState.clipRect.Right()+1,
1272cdf0e10cSrcweir                                                          rState.clipRect.Bottom()+1 ) ) ) );
1273cdf0e10cSrcweir                 }
1274cdf0e10cSrcweir             }
1275cdf0e10cSrcweir             else
1276cdf0e10cSrcweir             {
1277cdf0e10cSrcweir                 rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1278cdf0e10cSrcweir                     rParms.mrCanvas->getUNOCanvas()->getDevice(),
1279cdf0e10cSrcweir                     rState.clip );
1280cdf0e10cSrcweir             }
1281cdf0e10cSrcweir         }
1282cdf0e10cSrcweir 
1283cdf0e10cSrcweir         bool ImplRenderer::createActions( GDIMetaFile&				     rMtf,
1284cdf0e10cSrcweir                                           const ActionFactoryParameters& rFactoryParms,
1285cdf0e10cSrcweir                                           bool                           bSubsettableActions )
1286cdf0e10cSrcweir         {
1287cdf0e10cSrcweir             /* TODO(P2): interpret mtf-comments
1288cdf0e10cSrcweir                ================================
1289cdf0e10cSrcweir 
1290cdf0e10cSrcweir                - gradient fillings (do that via comments)
1291cdf0e10cSrcweir 
1292cdf0e10cSrcweir                - think about mapping. _If_ we do everything in logical
1293cdf0e10cSrcweir                	 coordinates (which would solve the probs for stroke
1294cdf0e10cSrcweir                  widths and text offsets), then we would have to
1295cdf0e10cSrcweir                  recalc scaling for every drawing operation. This is
1296cdf0e10cSrcweir                  because the outdev map mode might change at any time.
1297cdf0e10cSrcweir                  Also keep in mind, that, although we've double precision
1298cdf0e10cSrcweir                  float arithmetic now, different offsets might still
1299cdf0e10cSrcweir                  generate different roundings (aka
1300cdf0e10cSrcweir                  'OutputDevice::SetPixelOffset())
1301cdf0e10cSrcweir 
1302cdf0e10cSrcweir              */
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir             // alias common parameters
1305cdf0e10cSrcweir             VectorOfOutDevStates&  rStates(rFactoryParms.mrStates);
1306cdf0e10cSrcweir             const CanvasSharedPtr& rCanvas(rFactoryParms.mrCanvas);
1307cdf0e10cSrcweir             ::VirtualDevice&       rVDev(rFactoryParms.mrVDev);
1308cdf0e10cSrcweir             const Parameters&      rParms(rFactoryParms.mrParms);
1309cdf0e10cSrcweir             sal_Int32&             io_rCurrActionIndex(rFactoryParms.mrCurrActionIndex);
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir 
1312cdf0e10cSrcweir             // Loop over every metaaction
1313cdf0e10cSrcweir             // ==========================
1314cdf0e10cSrcweir             MetaAction* pCurrAct;
1315cdf0e10cSrcweir 
1316cdf0e10cSrcweir             // TODO(P1): think about caching
1317cdf0e10cSrcweir             for( pCurrAct=rMtf.FirstAction();
1318cdf0e10cSrcweir                  pCurrAct;
1319cdf0e10cSrcweir                  pCurrAct = rMtf.NextAction() )
1320cdf0e10cSrcweir             {
1321cdf0e10cSrcweir                 // execute every action, to keep VDev state up-to-date
1322cdf0e10cSrcweir                 // currently used only for
1323cdf0e10cSrcweir                 // - the map mode
1324cdf0e10cSrcweir                 // - the line/fill color when processing a META_TRANSPARENT_ACTION
1325cdf0e10cSrcweir                 // - SetFont to process font metric specific actions
1326cdf0e10cSrcweir                 pCurrAct->Execute( &rVDev );
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir                 switch( pCurrAct->GetType() )
1329cdf0e10cSrcweir                 {
1330cdf0e10cSrcweir                     // ------------------------------------------------------------
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir                     // In the first part of this monster-switch, we
1333cdf0e10cSrcweir                     // handle all state-changing meta actions. These
1334cdf0e10cSrcweir                     // are all handled locally.
1335cdf0e10cSrcweir 
1336cdf0e10cSrcweir                     // ------------------------------------------------------------
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir                     case META_PUSH_ACTION:
1339cdf0e10cSrcweir                     {
1340cdf0e10cSrcweir                         MetaPushAction* pPushAction = static_cast<MetaPushAction*>(pCurrAct);
1341cdf0e10cSrcweir                         pushState( rStates,
1342cdf0e10cSrcweir                                    pPushAction->GetFlags() );
1343cdf0e10cSrcweir                     }
1344cdf0e10cSrcweir                     break;
1345cdf0e10cSrcweir 
1346cdf0e10cSrcweir                     case META_POP_ACTION:
1347cdf0e10cSrcweir                         popState( rStates );
1348cdf0e10cSrcweir                         break;
1349cdf0e10cSrcweir 
1350cdf0e10cSrcweir                     case META_TEXTLANGUAGE_ACTION:
1351cdf0e10cSrcweir                         // FALLTHROUGH intended
1352cdf0e10cSrcweir                     case META_REFPOINT_ACTION:
1353cdf0e10cSrcweir                         // handled via pCurrAct->Execute( &rVDev )
1354cdf0e10cSrcweir                         break;
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir                     case META_MAPMODE_ACTION:
1357cdf0e10cSrcweir                         // modify current mapModeTransformation
1358cdf0e10cSrcweir                         // transformation, such that subsequent
1359cdf0e10cSrcweir                         // coordinates map correctly
1360cdf0e10cSrcweir                         tools::calcLogic2PixelAffineTransform( getState( rStates ).mapModeTransform,
1361cdf0e10cSrcweir                                                                rVDev );
1362cdf0e10cSrcweir                         break;
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir                     // monitor clip regions, to assemble clip polygon on our own
1365cdf0e10cSrcweir                     case META_CLIPREGION_ACTION:
1366cdf0e10cSrcweir                     {
1367cdf0e10cSrcweir                         MetaClipRegionAction* pClipAction = static_cast<MetaClipRegionAction*>(pCurrAct);
1368cdf0e10cSrcweir 
1369cdf0e10cSrcweir                         if( !pClipAction->IsClipping() )
1370cdf0e10cSrcweir                         {
1371cdf0e10cSrcweir                             // clear clipping
1372cdf0e10cSrcweir                             getState( rStates ).clip.clear();
1373cdf0e10cSrcweir                         }
1374cdf0e10cSrcweir                         else
1375cdf0e10cSrcweir                         {
1376cdf0e10cSrcweir                             if( !pClipAction->GetRegion().HasPolyPolygon() )
1377cdf0e10cSrcweir                             {
1378cdf0e10cSrcweir                                 VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
1379cdf0e10cSrcweir                                                "region encountered, falling back to bounding box!" );
1380cdf0e10cSrcweir 
1381cdf0e10cSrcweir                                 // #121806# explicitely kept integer
1382cdf0e10cSrcweir                                 Rectangle aClipRect(
1383cdf0e10cSrcweir                                     rVDev.LogicToPixel(
1384cdf0e10cSrcweir                                         pClipAction->GetRegion().GetBoundRect() ) );
1385cdf0e10cSrcweir 
1386cdf0e10cSrcweir                                 // intersect current clip with given rect
1387cdf0e10cSrcweir                                 updateClipping(
1388cdf0e10cSrcweir                                     aClipRect,
1389cdf0e10cSrcweir                                     rFactoryParms,
1390cdf0e10cSrcweir                                     false );
1391cdf0e10cSrcweir                             }
1392cdf0e10cSrcweir                             else
1393cdf0e10cSrcweir                             {
1394cdf0e10cSrcweir                                 // set new clip polygon (don't intersect
1395cdf0e10cSrcweir                                 // with old one, just set it)
1396cdf0e10cSrcweir 
1397cdf0e10cSrcweir                                 // #121806# explicitely kept integer
1398cdf0e10cSrcweir                                 updateClipping(
1399cdf0e10cSrcweir                                     rVDev.LogicToPixel(
1400cdf0e10cSrcweir                                         pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
1401cdf0e10cSrcweir                                     rFactoryParms,
1402cdf0e10cSrcweir                                     false );
1403cdf0e10cSrcweir                             }
1404cdf0e10cSrcweir                         }
1405cdf0e10cSrcweir 
1406cdf0e10cSrcweir                         break;
1407cdf0e10cSrcweir                     }
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir                     case META_ISECTRECTCLIPREGION_ACTION:
1410cdf0e10cSrcweir                     {
1411cdf0e10cSrcweir                         MetaISectRectClipRegionAction* pClipAction = static_cast<MetaISectRectClipRegionAction*>(pCurrAct);
1412cdf0e10cSrcweir 
1413cdf0e10cSrcweir                         // #121806# explicitely kept integer
1414cdf0e10cSrcweir                         Rectangle aClipRect(
1415cdf0e10cSrcweir                             rVDev.LogicToPixel( pClipAction->GetRect() ) );
1416cdf0e10cSrcweir 
1417cdf0e10cSrcweir                         // intersect current clip with given rect
1418cdf0e10cSrcweir                         updateClipping(
1419cdf0e10cSrcweir                             aClipRect,
1420cdf0e10cSrcweir                             rFactoryParms,
1421cdf0e10cSrcweir                             true );
1422cdf0e10cSrcweir 
1423cdf0e10cSrcweir                         break;
1424cdf0e10cSrcweir                     }
1425cdf0e10cSrcweir 
1426cdf0e10cSrcweir                     case META_ISECTREGIONCLIPREGION_ACTION:
1427cdf0e10cSrcweir                     {
1428cdf0e10cSrcweir                         MetaISectRegionClipRegionAction* pClipAction = static_cast<MetaISectRegionClipRegionAction*>(pCurrAct);
1429cdf0e10cSrcweir 
1430cdf0e10cSrcweir                         if( !pClipAction->GetRegion().HasPolyPolygon() )
1431cdf0e10cSrcweir                         {
1432cdf0e10cSrcweir                             VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
1433cdf0e10cSrcweir                                            "region encountered, falling back to bounding box!" );
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir                             // #121806# explicitely kept integer
1436cdf0e10cSrcweir                             Rectangle aClipRect(
1437cdf0e10cSrcweir                                 rVDev.LogicToPixel( pClipAction->GetRegion().GetBoundRect() ) );
1438cdf0e10cSrcweir 
1439cdf0e10cSrcweir                             // intersect current clip with given rect
1440cdf0e10cSrcweir                             updateClipping(
1441cdf0e10cSrcweir                                 aClipRect,
1442cdf0e10cSrcweir                                 rFactoryParms,
1443cdf0e10cSrcweir                                 true );
1444cdf0e10cSrcweir                         }
1445cdf0e10cSrcweir                         else
1446cdf0e10cSrcweir                         {
1447cdf0e10cSrcweir                             // intersect current clip with given clip polygon
1448cdf0e10cSrcweir 
1449cdf0e10cSrcweir                             // #121806# explicitely kept integer
1450cdf0e10cSrcweir                             updateClipping(
1451cdf0e10cSrcweir                                 rVDev.LogicToPixel(
1452cdf0e10cSrcweir                                     pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
1453cdf0e10cSrcweir                                 rFactoryParms,
1454cdf0e10cSrcweir                                 true );
1455cdf0e10cSrcweir                         }
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir                         break;
1458cdf0e10cSrcweir                     }
1459cdf0e10cSrcweir 
1460cdf0e10cSrcweir                     case META_MOVECLIPREGION_ACTION:
1461cdf0e10cSrcweir                         // TODO(F2): NYI
1462cdf0e10cSrcweir                         break;
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir                     case META_LINECOLOR_ACTION:
1465cdf0e10cSrcweir                         if( !rParms.maLineColor.is_initialized() )
1466cdf0e10cSrcweir                         {
1467cdf0e10cSrcweir                             setStateColor( static_cast<MetaLineColorAction*>(pCurrAct),
1468cdf0e10cSrcweir                                            getState( rStates ).isLineColorSet,
1469cdf0e10cSrcweir                                            getState( rStates ).lineColor,
1470cdf0e10cSrcweir                                            rCanvas );
1471cdf0e10cSrcweir                         }
1472cdf0e10cSrcweir                         break;
1473cdf0e10cSrcweir 
1474cdf0e10cSrcweir                     case META_FILLCOLOR_ACTION:
1475cdf0e10cSrcweir                         if( !rParms.maFillColor.is_initialized() )
1476cdf0e10cSrcweir                         {
1477cdf0e10cSrcweir                             setStateColor( static_cast<MetaFillColorAction*>(pCurrAct),
1478cdf0e10cSrcweir                                            getState( rStates ).isFillColorSet,
1479cdf0e10cSrcweir                                            getState( rStates ).fillColor,
1480cdf0e10cSrcweir                                            rCanvas );
1481cdf0e10cSrcweir                         }
1482cdf0e10cSrcweir                         break;
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir                     case META_TEXTCOLOR_ACTION:
1485cdf0e10cSrcweir                     {
1486cdf0e10cSrcweir                         if( !rParms.maTextColor.is_initialized() )
1487cdf0e10cSrcweir                         {
1488cdf0e10cSrcweir                             // Text color is set unconditionally, thus, no
1489cdf0e10cSrcweir                             // use of setStateColor here
1490cdf0e10cSrcweir                             ::Color aColor( static_cast<MetaTextColorAction*>(pCurrAct)->GetColor() );
1491cdf0e10cSrcweir 
1492cdf0e10cSrcweir                             // force alpha part of color to
1493cdf0e10cSrcweir                             // opaque. transparent painting is done
1494cdf0e10cSrcweir                             // explicitely via META_TRANSPARENT_ACTION
1495cdf0e10cSrcweir                             aColor.SetTransparency(0);
1496cdf0e10cSrcweir 
1497cdf0e10cSrcweir                             getState( rStates ).textColor =
1498cdf0e10cSrcweir                                 ::vcl::unotools::colorToDoubleSequence(
1499cdf0e10cSrcweir                                     aColor,
1500cdf0e10cSrcweir                                     rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
1501cdf0e10cSrcweir                         }
1502cdf0e10cSrcweir                     }
1503cdf0e10cSrcweir                     break;
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir                     case META_TEXTFILLCOLOR_ACTION:
1506cdf0e10cSrcweir                         if( !rParms.maTextColor.is_initialized() )
1507cdf0e10cSrcweir                         {
1508cdf0e10cSrcweir                             setStateColor( static_cast<MetaTextFillColorAction*>(pCurrAct),
1509cdf0e10cSrcweir                                            getState( rStates ).isTextFillColorSet,
1510cdf0e10cSrcweir                                            getState( rStates ).textFillColor,
1511cdf0e10cSrcweir                                            rCanvas );
1512cdf0e10cSrcweir                         }
1513cdf0e10cSrcweir                         break;
1514cdf0e10cSrcweir 
1515cdf0e10cSrcweir                     case META_TEXTLINECOLOR_ACTION:
1516cdf0e10cSrcweir                         if( !rParms.maTextColor.is_initialized() )
1517cdf0e10cSrcweir                         {
1518cdf0e10cSrcweir                             setStateColor( static_cast<MetaTextLineColorAction*>(pCurrAct),
1519cdf0e10cSrcweir                                            getState( rStates ).isTextLineColorSet,
1520cdf0e10cSrcweir                                            getState( rStates ).textLineColor,
1521cdf0e10cSrcweir                                            rCanvas );
1522cdf0e10cSrcweir                         }
1523cdf0e10cSrcweir                         break;
1524cdf0e10cSrcweir 
1525cdf0e10cSrcweir                     case META_TEXTALIGN_ACTION:
1526cdf0e10cSrcweir                     {
1527cdf0e10cSrcweir                         ::cppcanvas::internal::OutDevState& rState = getState( rStates );
1528cdf0e10cSrcweir                         const TextAlign eTextAlign( static_cast<MetaTextAlignAction*>(pCurrAct)->GetTextAlign() );
1529cdf0e10cSrcweir 
1530cdf0e10cSrcweir                         rState.textReferencePoint = eTextAlign;
1531cdf0e10cSrcweir                     }
1532cdf0e10cSrcweir                     break;
1533cdf0e10cSrcweir 
1534cdf0e10cSrcweir                     case META_FONT_ACTION:
1535cdf0e10cSrcweir                     {
1536cdf0e10cSrcweir                         ::cppcanvas::internal::OutDevState& rState = getState( rStates );
1537cdf0e10cSrcweir                         const ::Font& rFont( static_cast<MetaFontAction*>(pCurrAct)->GetFont() );
1538cdf0e10cSrcweir 
1539cdf0e10cSrcweir                         rState.xFont = createFont( rState.fontRotation,
1540cdf0e10cSrcweir                                                    rFont,
1541cdf0e10cSrcweir                                                    rFactoryParms );
1542cdf0e10cSrcweir 
1543cdf0e10cSrcweir                         // TODO(Q2): define and use appropriate enumeration types
1544cdf0e10cSrcweir                         rState.textReliefStyle          = (sal_Int8)rFont.GetRelief();
1545cdf0e10cSrcweir                         rState.textOverlineStyle        = (sal_Int8)rFont.GetOverline();
1546cdf0e10cSrcweir                         rState.textUnderlineStyle       = rParms.maFontUnderline.is_initialized() ?
1547cdf0e10cSrcweir                             (*rParms.maFontUnderline ? (sal_Int8)UNDERLINE_SINGLE : (sal_Int8)UNDERLINE_NONE) :
1548cdf0e10cSrcweir                             (sal_Int8)rFont.GetUnderline();
1549cdf0e10cSrcweir                         rState.textStrikeoutStyle       = (sal_Int8)rFont.GetStrikeout();
1550cdf0e10cSrcweir                         rState.textEmphasisMarkStyle    = (sal_Int8)rFont.GetEmphasisMark();
1551cdf0e10cSrcweir                         rState.isTextEffectShadowSet    = (rFont.IsShadow() != sal_False);
1552cdf0e10cSrcweir                         rState.isTextWordUnderlineSet   = (rFont.IsWordLineMode() != sal_False);
1553cdf0e10cSrcweir                         rState.isTextOutlineModeSet     = (rFont.IsOutline() != sal_False);
1554cdf0e10cSrcweir                     }
1555cdf0e10cSrcweir                     break;
1556cdf0e10cSrcweir 
1557cdf0e10cSrcweir                     case META_RASTEROP_ACTION:
1558cdf0e10cSrcweir                         // TODO(F2): NYI
1559cdf0e10cSrcweir                         break;
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir                     case META_LAYOUTMODE_ACTION:
1562cdf0e10cSrcweir                     {
1563cdf0e10cSrcweir                         // TODO(F2): A lot is missing here
1564cdf0e10cSrcweir                         int nLayoutMode = static_cast<MetaLayoutModeAction*>(pCurrAct)->GetLayoutMode();
1565cdf0e10cSrcweir                         ::cppcanvas::internal::OutDevState& rState = getState( rStates );
1566cdf0e10cSrcweir                         switch( nLayoutMode & (TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_BIDI_STRONG) )
1567cdf0e10cSrcweir                         {
1568cdf0e10cSrcweir                             case TEXT_LAYOUT_BIDI_LTR:
1569cdf0e10cSrcweir                                 rState.textDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
1570cdf0e10cSrcweir                                 break;
1571cdf0e10cSrcweir 
1572cdf0e10cSrcweir                             case (TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG):
1573cdf0e10cSrcweir                                 rState.textDirection = rendering::TextDirection::STRONG_LEFT_TO_RIGHT;
1574cdf0e10cSrcweir                                 break;
1575cdf0e10cSrcweir 
1576cdf0e10cSrcweir                             case TEXT_LAYOUT_BIDI_RTL:
1577cdf0e10cSrcweir                                 rState.textDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
1578cdf0e10cSrcweir                                 break;
1579cdf0e10cSrcweir 
1580cdf0e10cSrcweir                             case (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG):
1581cdf0e10cSrcweir                                 rState.textDirection = rendering::TextDirection::STRONG_RIGHT_TO_LEFT;
1582cdf0e10cSrcweir                                 break;
1583cdf0e10cSrcweir                         }
1584cdf0e10cSrcweir 
1585cdf0e10cSrcweir                         rState.textAlignment = 0; // TODO(F2): rendering::TextAlignment::LEFT_ALIGNED;
1586cdf0e10cSrcweir                         if( (nLayoutMode & (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_RIGHT) )
1587cdf0e10cSrcweir                             && !(nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT ) )
1588cdf0e10cSrcweir                         {
1589cdf0e10cSrcweir                             rState.textAlignment = 1; // TODO(F2): rendering::TextAlignment::RIGHT_ALIGNED;
1590cdf0e10cSrcweir                         }
1591cdf0e10cSrcweir                     }
1592cdf0e10cSrcweir                     break;
1593cdf0e10cSrcweir 
1594cdf0e10cSrcweir                     // ------------------------------------------------------------
1595cdf0e10cSrcweir 
1596cdf0e10cSrcweir                     // In the second part of this monster-switch, we
1597cdf0e10cSrcweir                     // handle all recursing meta actions. These are the
1598cdf0e10cSrcweir                     // ones generating a metafile by themselves, which is
1599cdf0e10cSrcweir                     // then processed by recursively calling this method.
1600cdf0e10cSrcweir 
1601cdf0e10cSrcweir                     // ------------------------------------------------------------
1602cdf0e10cSrcweir 
1603cdf0e10cSrcweir                     case META_GRADIENT_ACTION:
1604cdf0e10cSrcweir                     {
1605cdf0e10cSrcweir                         MetaGradientAction* pGradAct = static_cast<MetaGradientAction*>(pCurrAct);
1606cdf0e10cSrcweir                         createGradientAction( ::Polygon( pGradAct->GetRect() ),
1607cdf0e10cSrcweir                                               pGradAct->GetGradient(),
1608cdf0e10cSrcweir                                               rFactoryParms,
1609cdf0e10cSrcweir                                               true,
1610cdf0e10cSrcweir                                               bSubsettableActions );
1611cdf0e10cSrcweir                     }
1612cdf0e10cSrcweir                     break;
1613cdf0e10cSrcweir 
1614cdf0e10cSrcweir                     case META_HATCH_ACTION:
1615cdf0e10cSrcweir                     {
1616cdf0e10cSrcweir                         // TODO(F2): use native Canvas hatches here
1617cdf0e10cSrcweir                         GDIMetaFile aTmpMtf;
1618cdf0e10cSrcweir 
1619cdf0e10cSrcweir                         rVDev.AddHatchActions( static_cast<MetaHatchAction*>(pCurrAct)->GetPolyPolygon(),
1620cdf0e10cSrcweir                                                static_cast<MetaHatchAction*>(pCurrAct)->GetHatch(),
1621cdf0e10cSrcweir                                                aTmpMtf );
1622cdf0e10cSrcweir                         createActions( aTmpMtf, rFactoryParms,
1623cdf0e10cSrcweir                                        bSubsettableActions );
1624cdf0e10cSrcweir                     }
1625cdf0e10cSrcweir                     break;
1626cdf0e10cSrcweir 
1627cdf0e10cSrcweir                     case META_EPS_ACTION:
1628cdf0e10cSrcweir                     {
1629cdf0e10cSrcweir                         MetaEPSAction* 		pAct = static_cast<MetaEPSAction*>(pCurrAct);
1630cdf0e10cSrcweir                         const GDIMetaFile&  rSubstitute = pAct->GetSubstitute();
1631cdf0e10cSrcweir 
1632cdf0e10cSrcweir                         // #121806# explicitely kept integer
1633cdf0e10cSrcweir                         const Size aMtfSize( rSubstitute.GetPrefSize() );
1634cdf0e10cSrcweir                         const Size aMtfSizePixPre( rVDev.LogicToPixel( aMtfSize,
1635cdf0e10cSrcweir                                                                        rSubstitute.GetPrefMapMode() ) );
1636cdf0e10cSrcweir 
1637cdf0e10cSrcweir                         // #i44110# correct null-sized output - there
1638cdf0e10cSrcweir                         // are metafiles which have zero size in at
1639cdf0e10cSrcweir                         // least one dimension
1640cdf0e10cSrcweir                         const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
1641cdf0e10cSrcweir                                                 ::std::max( aMtfSizePixPre.Height(), 1L ) );
1642cdf0e10cSrcweir 
1643cdf0e10cSrcweir                         // Setup local transform, such that the
1644cdf0e10cSrcweir                         // metafile renders itself into the given
1645cdf0e10cSrcweir                         // output rectangle
1646cdf0e10cSrcweir                         pushState( rStates, PUSH_ALL );
1647cdf0e10cSrcweir 
1648cdf0e10cSrcweir                         rVDev.Push();
1649cdf0e10cSrcweir                         rVDev.SetMapMode( rSubstitute.GetPrefMapMode() );
1650cdf0e10cSrcweir 
1651cdf0e10cSrcweir                         const ::Point& rPos( rVDev.LogicToPixel( pAct->GetPoint() ) );
1652cdf0e10cSrcweir                         const ::Size&  rSize( rVDev.LogicToPixel( pAct->GetSize() ) );
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir                         getState( rStates ).transform.translate( rPos.X(),
1655cdf0e10cSrcweir                                                                  rPos.Y() );
1656cdf0e10cSrcweir                         getState( rStates ).transform.scale( (double)rSize.Width() / aMtfSizePix.Width(),
1657cdf0e10cSrcweir                                                              (double)rSize.Height() / aMtfSizePix.Height() );
1658cdf0e10cSrcweir 
1659cdf0e10cSrcweir                         createActions( const_cast<GDIMetaFile&>(pAct->GetSubstitute()),
1660cdf0e10cSrcweir                                        rFactoryParms,
1661cdf0e10cSrcweir                                        bSubsettableActions );
1662cdf0e10cSrcweir 
1663cdf0e10cSrcweir                         rVDev.Pop();
1664cdf0e10cSrcweir                         popState( rStates );
1665cdf0e10cSrcweir                     }
1666cdf0e10cSrcweir                     break;
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir                     // handle metafile comments, to retrieve
1669cdf0e10cSrcweir                     // meta-information for gradients, fills and
1670cdf0e10cSrcweir                     // strokes. May skip actions, and may recurse.
1671cdf0e10cSrcweir                     case META_COMMENT_ACTION:
1672cdf0e10cSrcweir                     {
1673cdf0e10cSrcweir                         MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pCurrAct);
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir                         // Handle gradients
1676cdf0e10cSrcweir                         if ( pAct->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1677cdf0e10cSrcweir                         {
1678cdf0e10cSrcweir                             MetaGradientExAction* pGradAction = NULL;
1679cdf0e10cSrcweir                             bool bDone( false );
1680cdf0e10cSrcweir                             while( !bDone &&
1681cdf0e10cSrcweir                                    (pCurrAct=rMtf.NextAction()) != NULL )
1682cdf0e10cSrcweir                             {
1683cdf0e10cSrcweir                                 switch( pCurrAct->GetType() )
1684cdf0e10cSrcweir                                 {
1685cdf0e10cSrcweir                                     // extract gradient info
1686cdf0e10cSrcweir                                     case META_GRADIENTEX_ACTION:
1687cdf0e10cSrcweir                                         pGradAction = static_cast<MetaGradientExAction*>(pCurrAct);
1688cdf0e10cSrcweir                                         break;
1689cdf0e10cSrcweir 
1690cdf0e10cSrcweir                                     // skip broken-down rendering, output gradient when sequence is ended
1691cdf0e10cSrcweir                                     case META_COMMENT_ACTION:
1692cdf0e10cSrcweir                                         if( static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL )
1693cdf0e10cSrcweir                                         {
1694cdf0e10cSrcweir                                             bDone = true;
1695cdf0e10cSrcweir 
1696cdf0e10cSrcweir                                             if( pGradAction )
1697cdf0e10cSrcweir                                             {
1698cdf0e10cSrcweir                                                 createGradientAction( pGradAction->GetPolyPolygon(),
1699cdf0e10cSrcweir                                                                       pGradAction->GetGradient(),
1700cdf0e10cSrcweir                                                                       rFactoryParms,
1701cdf0e10cSrcweir                                                                       false,
1702cdf0e10cSrcweir                                                                       bSubsettableActions );
1703cdf0e10cSrcweir                                             }
1704cdf0e10cSrcweir                                         }
1705cdf0e10cSrcweir                                         break;
1706cdf0e10cSrcweir                                 }
1707cdf0e10cSrcweir                             }
1708cdf0e10cSrcweir                         }
1709cdf0e10cSrcweir                         // TODO(P2): Handle drawing layer strokes, via
1710cdf0e10cSrcweir                         // XPATHSTROKE_SEQ_BEGIN comment
1711cdf0e10cSrcweir 
1712cdf0e10cSrcweir                         // Handle drawing layer fills
1713cdf0e10cSrcweir                         else if( pAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1714cdf0e10cSrcweir                         {
1715cdf0e10cSrcweir                             const sal_uInt8* pData = pAct->GetData();
1716cdf0e10cSrcweir                             if ( pData )
1717cdf0e10cSrcweir                             {
1718cdf0e10cSrcweir                                 SvMemoryStream	aMemStm( (void*)pData, pAct->GetDataSize(), STREAM_READ );
1719cdf0e10cSrcweir 
1720cdf0e10cSrcweir                                 SvtGraphicFill aFill;
1721cdf0e10cSrcweir                                 aMemStm >> aFill;
1722cdf0e10cSrcweir 
1723cdf0e10cSrcweir                                 // TODO(P2): Also handle gradients and
1724cdf0e10cSrcweir                                 // hatches like this
1725cdf0e10cSrcweir 
1726cdf0e10cSrcweir                                 // only evaluate comment for pure
1727cdf0e10cSrcweir                                 // bitmap fills. If a transparency
1728cdf0e10cSrcweir                                 // gradient is involved (denoted by
1729cdf0e10cSrcweir                                 // the FloatTransparent action), take
1730cdf0e10cSrcweir                                 // the normal meta actions.
1731cdf0e10cSrcweir                                 if( aFill.getFillType() == SvtGraphicFill::fillTexture &&
1732cdf0e10cSrcweir                                     !isActionContained( rMtf,
1733cdf0e10cSrcweir                                                        "XPATHFILL_SEQ_END",
1734cdf0e10cSrcweir                                                         META_FLOATTRANSPARENT_ACTION ) )
1735cdf0e10cSrcweir                                 {
1736cdf0e10cSrcweir                                     rendering::Texture aTexture;
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir                                     // TODO(F1): the SvtGraphicFill
1739cdf0e10cSrcweir                                     // can also transport metafiles
1740cdf0e10cSrcweir                                     // here, handle that case, too
1741cdf0e10cSrcweir                                     Graphic	aGraphic;
1742cdf0e10cSrcweir                                     aFill.getGraphic( aGraphic );
1743cdf0e10cSrcweir 
1744cdf0e10cSrcweir                                     BitmapEx 	 aBmpEx( aGraphic.GetBitmapEx() );
1745cdf0e10cSrcweir                                     const ::Size aBmpSize( aBmpEx.GetSizePixel() );
1746cdf0e10cSrcweir 
1747cdf0e10cSrcweir                                     ::SvtGraphicFill::Transform aTransform;
1748cdf0e10cSrcweir                                     aFill.getTransform( aTransform );
1749cdf0e10cSrcweir 
1750cdf0e10cSrcweir                                     ::basegfx::B2DHomMatrix aMatrix;
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir                                     // convert to basegfx matrix
1753cdf0e10cSrcweir                                     aMatrix.set(0,0, aTransform.matrix[ 0 ] );
1754cdf0e10cSrcweir                                     aMatrix.set(0,1, aTransform.matrix[ 1 ] );
1755cdf0e10cSrcweir                                     aMatrix.set(0,2, aTransform.matrix[ 2 ] );
1756cdf0e10cSrcweir                                     aMatrix.set(1,0, aTransform.matrix[ 3 ] );
1757cdf0e10cSrcweir                                     aMatrix.set(1,1, aTransform.matrix[ 4 ] );
1758cdf0e10cSrcweir                                     aMatrix.set(1,2, aTransform.matrix[ 5 ] );
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir                                     ::basegfx::B2DHomMatrix aScale;
1761cdf0e10cSrcweir                                     aScale.scale( aBmpSize.Width(),
1762cdf0e10cSrcweir                                                   aBmpSize.Height() );
1763cdf0e10cSrcweir 
1764cdf0e10cSrcweir                                     // post-multiply with the bitmap
1765cdf0e10cSrcweir                                     // size (XCanvas' texture assumes
1766cdf0e10cSrcweir                                     // the given bitmap to be
1767cdf0e10cSrcweir                                     // normalized to [0,1]x[0,1]
1768cdf0e10cSrcweir                                     // rectangle)
1769cdf0e10cSrcweir                                     aMatrix = aMatrix * aScale;
1770cdf0e10cSrcweir 
1771cdf0e10cSrcweir                                     // pre-multiply with the
1772cdf0e10cSrcweir                                     // logic-to-pixel scale factor
1773cdf0e10cSrcweir                                     // (the metafile comment works in
1774cdf0e10cSrcweir                                     // logical coordinates).
1775cdf0e10cSrcweir                                     ::basegfx::B2DHomMatrix aLogic2PixelTransform;
1776cdf0e10cSrcweir                                     aMatrix *= tools::calcLogic2PixelLinearTransform( aLogic2PixelTransform,
1777cdf0e10cSrcweir                                                                                       rVDev );
1778cdf0e10cSrcweir 
1779cdf0e10cSrcweir                                     ::basegfx::unotools::affineMatrixFromHomMatrix(
1780cdf0e10cSrcweir                                         aTexture.AffineTransform,
1781cdf0e10cSrcweir                                         aMatrix );
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir                                     aTexture.Alpha = 1.0 - aFill.getTransparency();
1784cdf0e10cSrcweir                                     aTexture.Bitmap =
1785cdf0e10cSrcweir                                         ::vcl::unotools::xBitmapFromBitmapEx(
1786cdf0e10cSrcweir                                             rCanvas->getUNOCanvas()->getDevice(),
1787cdf0e10cSrcweir                                             aBmpEx );
1788cdf0e10cSrcweir                                     if( aFill.isTiling() )
1789cdf0e10cSrcweir                                     {
1790cdf0e10cSrcweir                                         aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
1791cdf0e10cSrcweir                                         aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
1792cdf0e10cSrcweir                                     }
1793cdf0e10cSrcweir                                     else
1794cdf0e10cSrcweir                                     {
1795cdf0e10cSrcweir                                         aTexture.RepeatModeX = rendering::TexturingMode::NONE;
1796cdf0e10cSrcweir                                         aTexture.RepeatModeY = rendering::TexturingMode::NONE;
1797cdf0e10cSrcweir                                     }
1798cdf0e10cSrcweir 
1799cdf0e10cSrcweir                                     ::PolyPolygon aPath;
1800cdf0e10cSrcweir                                     aFill.getPath( aPath );
1801cdf0e10cSrcweir 
1802cdf0e10cSrcweir                                     ::basegfx::B2DPolyPolygon aPoly( aPath.getB2DPolyPolygon() );
1803cdf0e10cSrcweir                                     aPoly.transform( getState( rStates ).mapModeTransform );
1804cdf0e10cSrcweir                                     ActionSharedPtr pPolyAction(
1805cdf0e10cSrcweir                                         internal::PolyPolyActionFactory::createPolyPolyAction(
1806cdf0e10cSrcweir                                             aPoly,
1807cdf0e10cSrcweir                                             rCanvas,
1808cdf0e10cSrcweir                                             getState( rStates ),
1809cdf0e10cSrcweir                                             aTexture ) );
1810cdf0e10cSrcweir 
1811cdf0e10cSrcweir                                     if( pPolyAction )
1812cdf0e10cSrcweir                                     {
1813cdf0e10cSrcweir                                         maActions.push_back(
1814cdf0e10cSrcweir                                             MtfAction(
1815cdf0e10cSrcweir                                                 pPolyAction,
1816cdf0e10cSrcweir                                                 io_rCurrActionIndex ) );
1817cdf0e10cSrcweir 
1818cdf0e10cSrcweir                                         io_rCurrActionIndex += pPolyAction->getActionCount()-1;
1819cdf0e10cSrcweir                                     }
1820cdf0e10cSrcweir 
1821cdf0e10cSrcweir                                     // skip broken-down render output
1822cdf0e10cSrcweir                                     skipContent( rMtf,
1823cdf0e10cSrcweir                                                  "XPATHFILL_SEQ_END",
1824cdf0e10cSrcweir                                                  io_rCurrActionIndex );
1825cdf0e10cSrcweir                                 }
1826cdf0e10cSrcweir                             }
1827cdf0e10cSrcweir                         }
1828cdf0e10cSrcweir                     }
1829cdf0e10cSrcweir                     break;
1830cdf0e10cSrcweir 
1831cdf0e10cSrcweir                     // ------------------------------------------------------------
1832cdf0e10cSrcweir 
1833cdf0e10cSrcweir                     // In the third part of this monster-switch, we
1834cdf0e10cSrcweir                     // handle all 'acting' meta actions. These are all
1835cdf0e10cSrcweir                     // processed by constructing function objects for
1836cdf0e10cSrcweir                     // them, which will later ease caching.
1837cdf0e10cSrcweir 
1838cdf0e10cSrcweir                     // ------------------------------------------------------------
1839cdf0e10cSrcweir 
1840cdf0e10cSrcweir                     case META_POINT_ACTION:
1841cdf0e10cSrcweir                     {
1842cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
1843cdf0e10cSrcweir                         if( rState.lineColor.getLength() )
1844cdf0e10cSrcweir                         {
1845cdf0e10cSrcweir                             ActionSharedPtr pPointAction(
1846cdf0e10cSrcweir                                 internal::PointActionFactory::createPointAction(
1847cdf0e10cSrcweir                                     rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
1848cdf0e10cSrcweir                                         static_cast<MetaPointAction*>(pCurrAct)->GetPoint() ),
1849cdf0e10cSrcweir                                     rCanvas,
1850cdf0e10cSrcweir                                     rState ) );
1851cdf0e10cSrcweir 
1852cdf0e10cSrcweir                             if( pPointAction )
1853cdf0e10cSrcweir                             {
1854cdf0e10cSrcweir                                 maActions.push_back(
1855cdf0e10cSrcweir                                     MtfAction(
1856cdf0e10cSrcweir                                         pPointAction,
1857cdf0e10cSrcweir                                         io_rCurrActionIndex ) );
1858cdf0e10cSrcweir 
1859cdf0e10cSrcweir                                 io_rCurrActionIndex += pPointAction->getActionCount()-1;
1860cdf0e10cSrcweir                             }
1861cdf0e10cSrcweir                         }
1862cdf0e10cSrcweir                     }
1863cdf0e10cSrcweir                     break;
1864cdf0e10cSrcweir 
1865cdf0e10cSrcweir                     case META_PIXEL_ACTION:
1866cdf0e10cSrcweir                     {
1867cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
1868cdf0e10cSrcweir                         if( rState.lineColor.getLength() )
1869cdf0e10cSrcweir                         {
1870cdf0e10cSrcweir                             ActionSharedPtr pPointAction(
1871cdf0e10cSrcweir                                 internal::PointActionFactory::createPointAction(
1872cdf0e10cSrcweir                                     rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
1873cdf0e10cSrcweir                                         static_cast<MetaPixelAction*>(pCurrAct)->GetPoint() ),
1874cdf0e10cSrcweir                                     rCanvas,
1875cdf0e10cSrcweir                                     rState,
1876cdf0e10cSrcweir                                     static_cast<MetaPixelAction*>(pCurrAct)->GetColor() ) );
1877cdf0e10cSrcweir 
1878cdf0e10cSrcweir                             if( pPointAction )
1879cdf0e10cSrcweir                             {
1880cdf0e10cSrcweir                                 maActions.push_back(
1881cdf0e10cSrcweir                                     MtfAction(
1882cdf0e10cSrcweir                                         pPointAction,
1883cdf0e10cSrcweir                                         io_rCurrActionIndex ) );
1884cdf0e10cSrcweir 
1885cdf0e10cSrcweir                                 io_rCurrActionIndex += pPointAction->getActionCount()-1;
1886cdf0e10cSrcweir                             }
1887cdf0e10cSrcweir                         }
1888cdf0e10cSrcweir                     }
1889cdf0e10cSrcweir                     break;
1890cdf0e10cSrcweir 
1891cdf0e10cSrcweir                     case META_LINE_ACTION:
1892cdf0e10cSrcweir                     {
1893cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
1894cdf0e10cSrcweir                         if( rState.lineColor.getLength() )
1895cdf0e10cSrcweir                         {
1896cdf0e10cSrcweir                             MetaLineAction* pLineAct = static_cast<MetaLineAction*>(pCurrAct);
1897cdf0e10cSrcweir 
1898cdf0e10cSrcweir                             const LineInfo& rLineInfo( pLineAct->GetLineInfo() );
1899cdf0e10cSrcweir 
1900cdf0e10cSrcweir                             const ::basegfx::B2DPoint aStartPoint(
1901cdf0e10cSrcweir                                 rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetStartPoint() ));
1902cdf0e10cSrcweir                             const ::basegfx::B2DPoint aEndPoint(
1903cdf0e10cSrcweir                                 rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetEndPoint() ));
1904cdf0e10cSrcweir 
1905cdf0e10cSrcweir                             ActionSharedPtr pLineAction;
1906cdf0e10cSrcweir 
1907cdf0e10cSrcweir                             if( rLineInfo.IsDefault() )
1908cdf0e10cSrcweir                             {
1909cdf0e10cSrcweir                                 // plain hair line
1910cdf0e10cSrcweir                                 pLineAction =
1911cdf0e10cSrcweir                                     internal::LineActionFactory::createLineAction(
1912cdf0e10cSrcweir                                         aStartPoint,
1913cdf0e10cSrcweir                                         aEndPoint,
1914cdf0e10cSrcweir                                         rCanvas,
1915cdf0e10cSrcweir                                         rState );
1916cdf0e10cSrcweir 
1917cdf0e10cSrcweir                                 if( pLineAction )
1918cdf0e10cSrcweir                                 {
1919cdf0e10cSrcweir                                     maActions.push_back(
1920cdf0e10cSrcweir                                         MtfAction(
1921cdf0e10cSrcweir                                             pLineAction,
1922cdf0e10cSrcweir                                             io_rCurrActionIndex ) );
1923cdf0e10cSrcweir 
1924cdf0e10cSrcweir                                     io_rCurrActionIndex += pLineAction->getActionCount()-1;
1925cdf0e10cSrcweir                                 }
1926cdf0e10cSrcweir                             }
1927cdf0e10cSrcweir                             else if( LINE_NONE != rLineInfo.GetStyle() )
1928cdf0e10cSrcweir                             {
1929cdf0e10cSrcweir                                 // 'thick' line
1930cdf0e10cSrcweir                                 rendering::StrokeAttributes aStrokeAttributes;
1931cdf0e10cSrcweir 
1932cdf0e10cSrcweir                                 setupStrokeAttributes( aStrokeAttributes,
1933cdf0e10cSrcweir                                                        rFactoryParms,
1934cdf0e10cSrcweir                                                        rLineInfo );
1935cdf0e10cSrcweir 
1936cdf0e10cSrcweir                                 // XCanvas can only stroke polygons,
1937cdf0e10cSrcweir                                 // not simple lines - thus, handle
1938cdf0e10cSrcweir                                 // this case via the polypolygon
1939cdf0e10cSrcweir                                 // action
1940cdf0e10cSrcweir                                 ::basegfx::B2DPolygon aPoly;
1941cdf0e10cSrcweir                                 aPoly.append( aStartPoint );
1942cdf0e10cSrcweir                                 aPoly.append( aEndPoint );
1943cdf0e10cSrcweir                                 pLineAction =
1944cdf0e10cSrcweir                                     internal::PolyPolyActionFactory::createPolyPolyAction(
1945cdf0e10cSrcweir                                         ::basegfx::B2DPolyPolygon( aPoly ),
1946cdf0e10cSrcweir                                         rCanvas, rState, aStrokeAttributes );
1947cdf0e10cSrcweir 
1948cdf0e10cSrcweir                                 if( pLineAction )
1949cdf0e10cSrcweir                                 {
1950cdf0e10cSrcweir                                     maActions.push_back(
1951cdf0e10cSrcweir                                         MtfAction(
1952cdf0e10cSrcweir                                             pLineAction,
1953cdf0e10cSrcweir                                             io_rCurrActionIndex ) );
1954cdf0e10cSrcweir 
1955cdf0e10cSrcweir                                     io_rCurrActionIndex += pLineAction->getActionCount()-1;
1956cdf0e10cSrcweir                                 }
1957cdf0e10cSrcweir                             }
1958cdf0e10cSrcweir                             // else: line style is default
1959cdf0e10cSrcweir                             // (i.e. invisible), don't generate action
1960cdf0e10cSrcweir                         }
1961cdf0e10cSrcweir                     }
1962cdf0e10cSrcweir                     break;
1963cdf0e10cSrcweir 
1964cdf0e10cSrcweir                     case META_RECT_ACTION:
1965cdf0e10cSrcweir                     {
1966cdf0e10cSrcweir                         const Rectangle& rRect(
1967cdf0e10cSrcweir                             static_cast<MetaRectAction*>(pCurrAct)->GetRect() );
1968cdf0e10cSrcweir 
1969cdf0e10cSrcweir                         if( rRect.IsEmpty() )
1970cdf0e10cSrcweir                             break;
1971cdf0e10cSrcweir 
1972cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
1973cdf0e10cSrcweir                         const ::basegfx::B2DPoint aTopLeftPixel(
1974cdf0e10cSrcweir                             rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ) );
1975cdf0e10cSrcweir                         const ::basegfx::B2DPoint aBottomRightPixel(
1976cdf0e10cSrcweir                             rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
1977cdf0e10cSrcweir                             // #121100# OutputDevice::DrawRect() fills
1978cdf0e10cSrcweir                             // rectangles Apple-like, i.e. with one
1979cdf0e10cSrcweir                             // additional pixel to the right and bottom.
1980cdf0e10cSrcweir                             ::basegfx::B2DPoint(1,1) );
1981cdf0e10cSrcweir 
1982cdf0e10cSrcweir                         createFillAndStroke( ::basegfx::tools::createPolygonFromRect(
1983cdf0e10cSrcweir                                                  ::basegfx::B2DRange( aTopLeftPixel,
1984cdf0e10cSrcweir                                                                       aBottomRightPixel )),
1985cdf0e10cSrcweir                                              rFactoryParms );
1986cdf0e10cSrcweir                         break;
1987cdf0e10cSrcweir                     }
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir                     case META_ROUNDRECT_ACTION:
1990cdf0e10cSrcweir                     {
1991cdf0e10cSrcweir                         const Rectangle& rRect(
1992cdf0e10cSrcweir                             static_cast<MetaRoundRectAction*>(pCurrAct)->GetRect());
1993cdf0e10cSrcweir 
1994cdf0e10cSrcweir                         if( rRect.IsEmpty() )
1995cdf0e10cSrcweir                             break;
1996cdf0e10cSrcweir 
1997cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly(
1998cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromRect(
1999cdf0e10cSrcweir                                 ::basegfx::B2DRange(
2000cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
2001cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
2002cdf0e10cSrcweir                                     ::basegfx::B2DPoint(1,1) ),
2003cdf0e10cSrcweir                                 static_cast<MetaRoundRectAction*>(pCurrAct)->GetHorzRound(),
2004cdf0e10cSrcweir                                 static_cast<MetaRoundRectAction*>(pCurrAct)->GetVertRound() ));
2005cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2006cdf0e10cSrcweir 
2007cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2008cdf0e10cSrcweir                                              rFactoryParms );
2009cdf0e10cSrcweir                     }
2010cdf0e10cSrcweir                     break;
2011cdf0e10cSrcweir 
2012cdf0e10cSrcweir                     case META_ELLIPSE_ACTION:
2013cdf0e10cSrcweir                     {
2014cdf0e10cSrcweir                         const Rectangle& rRect(
2015cdf0e10cSrcweir                             static_cast<MetaEllipseAction*>(pCurrAct)->GetRect() );
2016cdf0e10cSrcweir 
2017cdf0e10cSrcweir                         if( rRect.IsEmpty() )
2018cdf0e10cSrcweir                             break;
2019cdf0e10cSrcweir 
2020cdf0e10cSrcweir                         const ::basegfx::B2DRange aRange(
2021cdf0e10cSrcweir                             ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
2022cdf0e10cSrcweir                             ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
2023cdf0e10cSrcweir                             ::basegfx::B2DPoint(1,1) );
2024cdf0e10cSrcweir 
2025cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly(
2026cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromEllipse(
2027cdf0e10cSrcweir                                 aRange.getCenter(),
2028cdf0e10cSrcweir                                 aRange.getWidth(),
2029cdf0e10cSrcweir                                 aRange.getHeight() ));
2030cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2031cdf0e10cSrcweir 
2032cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2033cdf0e10cSrcweir                                              rFactoryParms );
2034cdf0e10cSrcweir                     }
2035cdf0e10cSrcweir                     break;
2036cdf0e10cSrcweir 
2037cdf0e10cSrcweir                     case META_ARC_ACTION:
2038cdf0e10cSrcweir                     {
2039cdf0e10cSrcweir                         // TODO(F1): Missing basegfx functionality. Mind empty rects!
2040cdf0e10cSrcweir                         const Polygon aToolsPoly( static_cast<MetaArcAction*>(pCurrAct)->GetRect(),
2041cdf0e10cSrcweir                                                   static_cast<MetaArcAction*>(pCurrAct)->GetStartPoint(),
2042cdf0e10cSrcweir                                                   static_cast<MetaArcAction*>(pCurrAct)->GetEndPoint(), POLY_ARC );
2043cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
2044cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2045cdf0e10cSrcweir 
2046cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2047cdf0e10cSrcweir                                              rFactoryParms );
2048cdf0e10cSrcweir                     }
2049cdf0e10cSrcweir                     break;
2050cdf0e10cSrcweir 
2051cdf0e10cSrcweir                     case META_PIE_ACTION:
2052cdf0e10cSrcweir                     {
2053cdf0e10cSrcweir                         // TODO(F1): Missing basegfx functionality. Mind empty rects!
2054cdf0e10cSrcweir                         const Polygon aToolsPoly( static_cast<MetaPieAction*>(pCurrAct)->GetRect(),
2055cdf0e10cSrcweir                                                   static_cast<MetaPieAction*>(pCurrAct)->GetStartPoint(),
2056cdf0e10cSrcweir                                                   static_cast<MetaPieAction*>(pCurrAct)->GetEndPoint(), POLY_PIE );
2057cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
2058cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2061cdf0e10cSrcweir                                              rFactoryParms );
2062cdf0e10cSrcweir                     }
2063cdf0e10cSrcweir                     break;
2064cdf0e10cSrcweir 
2065cdf0e10cSrcweir                     case META_CHORD_ACTION:
2066cdf0e10cSrcweir                     {
2067cdf0e10cSrcweir                         // TODO(F1): Missing basegfx functionality. Mind empty rects!
2068cdf0e10cSrcweir                         const Polygon aToolsPoly( static_cast<MetaChordAction*>(pCurrAct)->GetRect(),
2069cdf0e10cSrcweir                                                   static_cast<MetaChordAction*>(pCurrAct)->GetStartPoint(),
2070cdf0e10cSrcweir                                                   static_cast<MetaChordAction*>(pCurrAct)->GetEndPoint(), POLY_CHORD );
2071cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
2072cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2073cdf0e10cSrcweir 
2074cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2075cdf0e10cSrcweir                                              rFactoryParms );
2076cdf0e10cSrcweir                     }
2077cdf0e10cSrcweir                     break;
2078cdf0e10cSrcweir 
2079cdf0e10cSrcweir                     case META_POLYLINE_ACTION:
2080cdf0e10cSrcweir                     {
2081cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
2082cdf0e10cSrcweir                         if( rState.lineColor.getLength() ||
2083cdf0e10cSrcweir                             rState.fillColor.getLength() )
2084cdf0e10cSrcweir                         {
2085cdf0e10cSrcweir                             MetaPolyLineAction* pPolyLineAct = static_cast<MetaPolyLineAction*>(pCurrAct);
2086cdf0e10cSrcweir 
2087cdf0e10cSrcweir                             const LineInfo& rLineInfo( pPolyLineAct->GetLineInfo() );
2088cdf0e10cSrcweir                             ::basegfx::B2DPolygon aPoly( pPolyLineAct->GetPolygon().getB2DPolygon() );
2089cdf0e10cSrcweir                             aPoly.transform( rState.mapModeTransform );
2090cdf0e10cSrcweir 
2091cdf0e10cSrcweir                             ActionSharedPtr pLineAction;
2092cdf0e10cSrcweir 
2093cdf0e10cSrcweir                             if( rLineInfo.IsDefault() )
2094cdf0e10cSrcweir                             {
2095cdf0e10cSrcweir                                 // plain hair line polygon
2096cdf0e10cSrcweir                                 pLineAction =
2097cdf0e10cSrcweir                                     internal::PolyPolyActionFactory::createLinePolyPolyAction(
2098cdf0e10cSrcweir                                         ::basegfx::B2DPolyPolygon(aPoly),
2099cdf0e10cSrcweir                                         rCanvas,
2100cdf0e10cSrcweir                                         rState );
2101cdf0e10cSrcweir 
2102cdf0e10cSrcweir                                 if( pLineAction )
2103cdf0e10cSrcweir                                 {
2104cdf0e10cSrcweir                                     maActions.push_back(
2105cdf0e10cSrcweir                                         MtfAction(
2106cdf0e10cSrcweir                                             pLineAction,
2107cdf0e10cSrcweir                                             io_rCurrActionIndex ) );
2108cdf0e10cSrcweir 
2109cdf0e10cSrcweir                                     io_rCurrActionIndex += pLineAction->getActionCount()-1;
2110cdf0e10cSrcweir                                 }
2111cdf0e10cSrcweir                             }
2112cdf0e10cSrcweir                             else if( LINE_NONE != rLineInfo.GetStyle() )
2113cdf0e10cSrcweir                             {
2114cdf0e10cSrcweir                                 // 'thick' line polygon
2115cdf0e10cSrcweir                                 rendering::StrokeAttributes aStrokeAttributes;
2116cdf0e10cSrcweir 
2117cdf0e10cSrcweir                                 setupStrokeAttributes( aStrokeAttributes,
2118cdf0e10cSrcweir                                                        rFactoryParms,
2119cdf0e10cSrcweir                                                        rLineInfo );
2120cdf0e10cSrcweir 
2121cdf0e10cSrcweir                                 pLineAction =
2122cdf0e10cSrcweir                                     internal::PolyPolyActionFactory::createPolyPolyAction(
2123cdf0e10cSrcweir                                         ::basegfx::B2DPolyPolygon(aPoly),
2124cdf0e10cSrcweir                                         rCanvas,
2125cdf0e10cSrcweir                                         rState,
2126cdf0e10cSrcweir                                         aStrokeAttributes ) ;
2127cdf0e10cSrcweir 
2128cdf0e10cSrcweir                                 if( pLineAction )
2129cdf0e10cSrcweir                                 {
2130cdf0e10cSrcweir                                     maActions.push_back(
2131cdf0e10cSrcweir                                         MtfAction(
2132cdf0e10cSrcweir                                             pLineAction,
2133cdf0e10cSrcweir                                             io_rCurrActionIndex ) );
2134cdf0e10cSrcweir 
2135cdf0e10cSrcweir                                     io_rCurrActionIndex += pLineAction->getActionCount()-1;
2136cdf0e10cSrcweir                                 }
2137cdf0e10cSrcweir                             }
2138cdf0e10cSrcweir                             // else: line style is default
2139cdf0e10cSrcweir                             // (i.e. invisible), don't generate action
2140cdf0e10cSrcweir                         }
2141cdf0e10cSrcweir                     }
2142cdf0e10cSrcweir                     break;
2143cdf0e10cSrcweir 
2144cdf0e10cSrcweir                     case META_POLYGON_ACTION:
2145cdf0e10cSrcweir                     {
2146cdf0e10cSrcweir                         ::basegfx::B2DPolygon aPoly( static_cast<MetaPolygonAction*>(pCurrAct)->GetPolygon().getB2DPolygon() );
2147cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2148cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2149cdf0e10cSrcweir                                              rFactoryParms );
2150cdf0e10cSrcweir                     }
2151cdf0e10cSrcweir                     break;
2152cdf0e10cSrcweir 
2153cdf0e10cSrcweir                     case META_POLYPOLYGON_ACTION:
2154cdf0e10cSrcweir                     {
2155cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon aPoly( static_cast<MetaPolyPolygonAction*>(pCurrAct)->GetPolyPolygon().getB2DPolyPolygon() );
2156cdf0e10cSrcweir                         aPoly.transform( getState( rStates ).mapModeTransform );
2157cdf0e10cSrcweir                         createFillAndStroke( aPoly,
2158cdf0e10cSrcweir                                              rFactoryParms );
2159cdf0e10cSrcweir                     }
2160cdf0e10cSrcweir                     break;
2161cdf0e10cSrcweir 
2162cdf0e10cSrcweir                     case META_BMP_ACTION:
2163cdf0e10cSrcweir                     {
2164cdf0e10cSrcweir                         MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pCurrAct);
2165cdf0e10cSrcweir 
2166cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2167cdf0e10cSrcweir                                 internal::BitmapActionFactory::createBitmapAction(
2168cdf0e10cSrcweir                                     pAct->GetBitmap(),
2169cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2170cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2171cdf0e10cSrcweir                                     rCanvas,
2172cdf0e10cSrcweir                                     getState( rStates ) ) );
2173cdf0e10cSrcweir 
2174cdf0e10cSrcweir                         if( pBmpAction )
2175cdf0e10cSrcweir                         {
2176cdf0e10cSrcweir                             maActions.push_back(
2177cdf0e10cSrcweir                                 MtfAction(
2178cdf0e10cSrcweir                                     pBmpAction,
2179cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2180cdf0e10cSrcweir 
2181cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2182cdf0e10cSrcweir                         }
2183cdf0e10cSrcweir                     }
2184cdf0e10cSrcweir                     break;
2185cdf0e10cSrcweir 
2186cdf0e10cSrcweir                     case META_BMPSCALE_ACTION:
2187cdf0e10cSrcweir                     {
2188cdf0e10cSrcweir                         MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pCurrAct);
2189cdf0e10cSrcweir 
2190cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2191cdf0e10cSrcweir                                 internal::BitmapActionFactory::createBitmapAction(
2192cdf0e10cSrcweir                                     pAct->GetBitmap(),
2193cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2194cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2195cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2196cdf0e10cSrcweir                                     ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
2197cdf0e10cSrcweir                                     rCanvas,
2198cdf0e10cSrcweir                                     getState( rStates ) ) );
2199cdf0e10cSrcweir 
2200cdf0e10cSrcweir                         if( pBmpAction )
2201cdf0e10cSrcweir                         {
2202cdf0e10cSrcweir                             maActions.push_back(
2203cdf0e10cSrcweir                                 MtfAction(
2204cdf0e10cSrcweir                                     pBmpAction,
2205cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2206cdf0e10cSrcweir 
2207cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2208cdf0e10cSrcweir                         }
2209cdf0e10cSrcweir                     }
2210cdf0e10cSrcweir                     break;
2211cdf0e10cSrcweir 
2212cdf0e10cSrcweir                     case META_BMPSCALEPART_ACTION:
2213cdf0e10cSrcweir                     {
2214cdf0e10cSrcweir                         MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pCurrAct);
2215cdf0e10cSrcweir 
2216cdf0e10cSrcweir                         // crop bitmap to given source rectangle (no
2217cdf0e10cSrcweir                         // need to copy and convert the whole bitmap)
2218cdf0e10cSrcweir                         Bitmap aBmp( pAct->GetBitmap() );
2219cdf0e10cSrcweir                         const Rectangle aCropRect( pAct->GetSrcPoint(),
2220cdf0e10cSrcweir                                                     pAct->GetSrcSize() );
2221cdf0e10cSrcweir                         aBmp.Crop( aCropRect );
2222cdf0e10cSrcweir 
2223cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2224cdf0e10cSrcweir                                 internal::BitmapActionFactory::createBitmapAction(
2225cdf0e10cSrcweir                                     aBmp,
2226cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2227cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
2228cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2229cdf0e10cSrcweir                                     ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
2230cdf0e10cSrcweir                                     rCanvas,
2231cdf0e10cSrcweir                                     getState( rStates ) ) );
2232cdf0e10cSrcweir 
2233cdf0e10cSrcweir                         if( pBmpAction )
2234cdf0e10cSrcweir                         {
2235cdf0e10cSrcweir                             maActions.push_back(
2236cdf0e10cSrcweir                                 MtfAction(
2237cdf0e10cSrcweir                                     pBmpAction,
2238cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2239cdf0e10cSrcweir 
2240cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2241cdf0e10cSrcweir                         }
2242cdf0e10cSrcweir                     }
2243cdf0e10cSrcweir                     break;
2244cdf0e10cSrcweir 
2245cdf0e10cSrcweir                     case META_BMPEX_ACTION:
2246cdf0e10cSrcweir                     {
2247cdf0e10cSrcweir                         MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pCurrAct);
2248cdf0e10cSrcweir 
2249cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2250cdf0e10cSrcweir                                 internal::BitmapActionFactory::createBitmapAction(
2251cdf0e10cSrcweir                                     pAct->GetBitmapEx(),
2252cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2253cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2254cdf0e10cSrcweir                                     rCanvas,
2255cdf0e10cSrcweir                                     getState( rStates ) ) );
2256cdf0e10cSrcweir 
2257cdf0e10cSrcweir                         if( pBmpAction )
2258cdf0e10cSrcweir                         {
2259cdf0e10cSrcweir                             maActions.push_back(
2260cdf0e10cSrcweir                                 MtfAction(
2261cdf0e10cSrcweir                                     pBmpAction,
2262cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2263cdf0e10cSrcweir 
2264cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2265cdf0e10cSrcweir                         }
2266cdf0e10cSrcweir                     }
2267cdf0e10cSrcweir                     break;
2268cdf0e10cSrcweir 
2269cdf0e10cSrcweir                     case META_BMPEXSCALE_ACTION:
2270cdf0e10cSrcweir                     {
2271cdf0e10cSrcweir                         MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pCurrAct);
2272cdf0e10cSrcweir 
2273cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2274cdf0e10cSrcweir                                 internal::BitmapActionFactory::createBitmapAction(
2275cdf0e10cSrcweir                                     pAct->GetBitmapEx(),
2276cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2277cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2278cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2279cdf0e10cSrcweir                                     ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
2280cdf0e10cSrcweir                                     rCanvas,
2281cdf0e10cSrcweir                                     getState( rStates ) ) );
2282cdf0e10cSrcweir 
2283cdf0e10cSrcweir                         if( pBmpAction )
2284cdf0e10cSrcweir                         {
2285cdf0e10cSrcweir                             maActions.push_back(
2286cdf0e10cSrcweir                                 MtfAction(
2287cdf0e10cSrcweir                                     pBmpAction,
2288cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2289cdf0e10cSrcweir 
2290cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2291cdf0e10cSrcweir                         }
2292cdf0e10cSrcweir                     }
2293cdf0e10cSrcweir                     break;
2294cdf0e10cSrcweir 
2295cdf0e10cSrcweir                     case META_BMPEXSCALEPART_ACTION:
2296cdf0e10cSrcweir                     {
2297cdf0e10cSrcweir                         MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pCurrAct);
2298cdf0e10cSrcweir 
2299cdf0e10cSrcweir                         // crop bitmap to given source rectangle (no
2300cdf0e10cSrcweir                         // need to copy and convert the whole bitmap)
2301cdf0e10cSrcweir                         BitmapEx aBmp( pAct->GetBitmapEx() );
2302cdf0e10cSrcweir                         const Rectangle aCropRect( pAct->GetSrcPoint(),
2303cdf0e10cSrcweir                                                    pAct->GetSrcSize() );
2304cdf0e10cSrcweir                         aBmp.Crop( aCropRect );
2305cdf0e10cSrcweir 
2306cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2307cdf0e10cSrcweir                             internal::BitmapActionFactory::createBitmapAction(
2308cdf0e10cSrcweir                                 aBmp,
2309cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2310cdf0e10cSrcweir                                 ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
2311cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2312cdf0e10cSrcweir                                 ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
2313cdf0e10cSrcweir                                 rCanvas,
2314cdf0e10cSrcweir                                 getState( rStates ) ) );
2315cdf0e10cSrcweir 
2316cdf0e10cSrcweir                         if( pBmpAction )
2317cdf0e10cSrcweir                         {
2318cdf0e10cSrcweir                             maActions.push_back(
2319cdf0e10cSrcweir                                 MtfAction(
2320cdf0e10cSrcweir                                     pBmpAction,
2321cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2322cdf0e10cSrcweir 
2323cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2324cdf0e10cSrcweir                         }
2325cdf0e10cSrcweir                     }
2326cdf0e10cSrcweir                     break;
2327cdf0e10cSrcweir 
2328cdf0e10cSrcweir                     case META_MASK_ACTION:
2329cdf0e10cSrcweir                     {
2330cdf0e10cSrcweir                         MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pCurrAct);
2331cdf0e10cSrcweir 
2332cdf0e10cSrcweir                         // create masked BitmapEx right here, as the
2333cdf0e10cSrcweir                         // canvas does not provide equivalent
2334cdf0e10cSrcweir                         // functionality
2335cdf0e10cSrcweir                         BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
2336cdf0e10cSrcweir                                                         pAct->GetColor() ));
2337cdf0e10cSrcweir 
2338cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2339cdf0e10cSrcweir                             internal::BitmapActionFactory::createBitmapAction(
2340cdf0e10cSrcweir                                 aBmp,
2341cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2342cdf0e10cSrcweir                                 ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2343cdf0e10cSrcweir                                 rCanvas,
2344cdf0e10cSrcweir                                 getState( rStates ) ) );
2345cdf0e10cSrcweir 
2346cdf0e10cSrcweir                         if( pBmpAction )
2347cdf0e10cSrcweir                         {
2348cdf0e10cSrcweir                             maActions.push_back(
2349cdf0e10cSrcweir                                 MtfAction(
2350cdf0e10cSrcweir                                     pBmpAction,
2351cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2352cdf0e10cSrcweir 
2353cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2354cdf0e10cSrcweir                         }
2355cdf0e10cSrcweir                     }
2356cdf0e10cSrcweir                     break;
2357cdf0e10cSrcweir 
2358cdf0e10cSrcweir                     case META_MASKSCALE_ACTION:
2359cdf0e10cSrcweir                     {
2360cdf0e10cSrcweir                         MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pCurrAct);
2361cdf0e10cSrcweir 
2362cdf0e10cSrcweir                         // create masked BitmapEx right here, as the
2363cdf0e10cSrcweir                         // canvas does not provide equivalent
2364cdf0e10cSrcweir                         // functionality
2365cdf0e10cSrcweir                         BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
2366cdf0e10cSrcweir                                                         pAct->GetColor() ));
2367cdf0e10cSrcweir 
2368cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2369cdf0e10cSrcweir                             internal::BitmapActionFactory::createBitmapAction(
2370cdf0e10cSrcweir                                 aBmp,
2371cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2372cdf0e10cSrcweir                                 ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2373cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2374cdf0e10cSrcweir                                 ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
2375cdf0e10cSrcweir                                 rCanvas,
2376cdf0e10cSrcweir                                 getState( rStates ) ) );
2377cdf0e10cSrcweir 
2378cdf0e10cSrcweir                         if( pBmpAction )
2379cdf0e10cSrcweir                         {
2380cdf0e10cSrcweir                             maActions.push_back(
2381cdf0e10cSrcweir                                 MtfAction(
2382cdf0e10cSrcweir                                     pBmpAction,
2383cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2384cdf0e10cSrcweir 
2385cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2386cdf0e10cSrcweir                         }
2387cdf0e10cSrcweir                     }
2388cdf0e10cSrcweir                     break;
2389cdf0e10cSrcweir 
2390cdf0e10cSrcweir                     case META_MASKSCALEPART_ACTION:
2391cdf0e10cSrcweir                     {
2392cdf0e10cSrcweir                         MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pCurrAct);
2393cdf0e10cSrcweir 
2394cdf0e10cSrcweir                         // create masked BitmapEx right here, as the
2395cdf0e10cSrcweir                         // canvas does not provide equivalent
2396cdf0e10cSrcweir                         // functionality
2397cdf0e10cSrcweir                         BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
2398cdf0e10cSrcweir                                                         pAct->GetColor() ));
2399cdf0e10cSrcweir 
2400cdf0e10cSrcweir                         // crop bitmap to given source rectangle (no
2401cdf0e10cSrcweir                         // need to copy and convert the whole bitmap)
2402cdf0e10cSrcweir                         const Rectangle aCropRect( pAct->GetSrcPoint(),
2403cdf0e10cSrcweir                                                    pAct->GetSrcSize() );
2404cdf0e10cSrcweir                         aBmp.Crop( aCropRect );
2405cdf0e10cSrcweir 
2406cdf0e10cSrcweir                         ActionSharedPtr pBmpAction(
2407cdf0e10cSrcweir                             internal::BitmapActionFactory::createBitmapAction(
2408cdf0e10cSrcweir                                 aBmp,
2409cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2410cdf0e10cSrcweir                                 ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
2411cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2412cdf0e10cSrcweir                                 ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
2413cdf0e10cSrcweir                                 rCanvas,
2414cdf0e10cSrcweir                                 getState( rStates ) ) );
2415cdf0e10cSrcweir 
2416cdf0e10cSrcweir                         if( pBmpAction )
2417cdf0e10cSrcweir                         {
2418cdf0e10cSrcweir                             maActions.push_back(
2419cdf0e10cSrcweir                                 MtfAction(
2420cdf0e10cSrcweir                                     pBmpAction,
2421cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2422cdf0e10cSrcweir 
2423cdf0e10cSrcweir                             io_rCurrActionIndex += pBmpAction->getActionCount()-1;
2424cdf0e10cSrcweir                         }
2425cdf0e10cSrcweir                     }
2426cdf0e10cSrcweir                     break;
2427cdf0e10cSrcweir 
2428cdf0e10cSrcweir                     case META_GRADIENTEX_ACTION:
2429cdf0e10cSrcweir                         // TODO(F1): use native Canvas gradients here
2430cdf0e10cSrcweir                         // action is ignored here, because redundant to META_GRADIENT_ACTION
2431cdf0e10cSrcweir                         break;
2432cdf0e10cSrcweir 
2433cdf0e10cSrcweir                     case META_WALLPAPER_ACTION:
2434cdf0e10cSrcweir                         // TODO(F2): NYI
2435cdf0e10cSrcweir                         break;
2436cdf0e10cSrcweir 
2437cdf0e10cSrcweir                     case META_TRANSPARENT_ACTION:
2438cdf0e10cSrcweir                     {
2439cdf0e10cSrcweir                         const OutDevState& rState( getState( rStates ) );
2440cdf0e10cSrcweir                         if( rState.lineColor.getLength() ||
2441cdf0e10cSrcweir                             rState.fillColor.getLength() )
2442cdf0e10cSrcweir                         {
2443cdf0e10cSrcweir                             MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pCurrAct);
2444cdf0e10cSrcweir                             ::basegfx::B2DPolyPolygon aPoly( pAct->GetPolyPolygon().getB2DPolyPolygon() );
2445cdf0e10cSrcweir                             aPoly.transform( rState.mapModeTransform );
2446cdf0e10cSrcweir 
2447cdf0e10cSrcweir                             ActionSharedPtr pPolyAction(
2448cdf0e10cSrcweir                                 internal::PolyPolyActionFactory::createPolyPolyAction(
2449cdf0e10cSrcweir                                     aPoly,
2450cdf0e10cSrcweir                                     rCanvas,
2451cdf0e10cSrcweir                                     rState,
2452cdf0e10cSrcweir                                     pAct->GetTransparence() ) );
2453cdf0e10cSrcweir 
2454cdf0e10cSrcweir                             if( pPolyAction )
2455cdf0e10cSrcweir                             {
2456cdf0e10cSrcweir                                 maActions.push_back(
2457cdf0e10cSrcweir                                     MtfAction(
2458cdf0e10cSrcweir                                         pPolyAction,
2459cdf0e10cSrcweir                                         io_rCurrActionIndex ) );
2460cdf0e10cSrcweir 
2461cdf0e10cSrcweir                                 io_rCurrActionIndex += pPolyAction->getActionCount()-1;
2462cdf0e10cSrcweir                             }
2463cdf0e10cSrcweir                         }
2464cdf0e10cSrcweir                     }
2465cdf0e10cSrcweir                     break;
2466cdf0e10cSrcweir 
2467cdf0e10cSrcweir                     case META_FLOATTRANSPARENT_ACTION:
2468cdf0e10cSrcweir                     {
2469cdf0e10cSrcweir                         MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pCurrAct);
2470cdf0e10cSrcweir 
2471cdf0e10cSrcweir                         internal::MtfAutoPtr pMtf(
2472cdf0e10cSrcweir                             new ::GDIMetaFile( pAct->GetGDIMetaFile() ) );
2473cdf0e10cSrcweir 
2474cdf0e10cSrcweir                         // TODO(P2): Use native canvas gradients here (saves a lot of UNO calls)
2475cdf0e10cSrcweir                         internal::GradientAutoPtr pGradient(
2476cdf0e10cSrcweir                             new Gradient( pAct->GetGradient() ) );
2477cdf0e10cSrcweir 
2478cdf0e10cSrcweir                         DBG_TESTSOLARMUTEX();
2479cdf0e10cSrcweir 
2480cdf0e10cSrcweir                         ActionSharedPtr pFloatTransAction(
2481cdf0e10cSrcweir                             internal::TransparencyGroupActionFactory::createTransparencyGroupAction(
2482cdf0e10cSrcweir                                 pMtf,
2483cdf0e10cSrcweir                                 pGradient,
2484cdf0e10cSrcweir                                 rParms,
2485cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2486cdf0e10cSrcweir                                 ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2487cdf0e10cSrcweir                                 getState( rStates ).mapModeTransform *
2488cdf0e10cSrcweir                                 ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
2489cdf0e10cSrcweir                                 rCanvas,
2490cdf0e10cSrcweir                                 getState( rStates ) ) );
2491cdf0e10cSrcweir 
2492cdf0e10cSrcweir                         if( pFloatTransAction )
2493cdf0e10cSrcweir                         {
2494cdf0e10cSrcweir                             maActions.push_back(
2495cdf0e10cSrcweir                                 MtfAction(
2496cdf0e10cSrcweir                                     pFloatTransAction,
2497cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2498cdf0e10cSrcweir 
2499cdf0e10cSrcweir                             io_rCurrActionIndex += pFloatTransAction->getActionCount()-1;
2500cdf0e10cSrcweir                         }
2501cdf0e10cSrcweir                     }
2502cdf0e10cSrcweir                     break;
2503cdf0e10cSrcweir 
2504cdf0e10cSrcweir                     case META_TEXT_ACTION:
2505cdf0e10cSrcweir                     {
2506cdf0e10cSrcweir                         MetaTextAction* pAct = static_cast<MetaTextAction*>(pCurrAct);
2507cdf0e10cSrcweir                         XubString sText = XubString( pAct->GetText() );
2508cdf0e10cSrcweir 
2509cdf0e10cSrcweir                         if( rVDev.GetDigitLanguage())
2510cdf0e10cSrcweir                             convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
2511cdf0e10cSrcweir 
2512cdf0e10cSrcweir                         createTextAction(
2513cdf0e10cSrcweir                             pAct->GetPoint(),
2514cdf0e10cSrcweir                             sText,
2515cdf0e10cSrcweir                             pAct->GetIndex(),
2516cdf0e10cSrcweir                             pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
2517cdf0e10cSrcweir                             NULL,
2518cdf0e10cSrcweir                             rFactoryParms,
2519cdf0e10cSrcweir                             bSubsettableActions );
2520cdf0e10cSrcweir                     }
2521cdf0e10cSrcweir                     break;
2522cdf0e10cSrcweir 
2523cdf0e10cSrcweir                     case META_TEXTARRAY_ACTION:
2524cdf0e10cSrcweir                     {
2525cdf0e10cSrcweir                         MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pCurrAct);
2526cdf0e10cSrcweir                         XubString sText = XubString( pAct->GetText() );
2527cdf0e10cSrcweir 
2528cdf0e10cSrcweir                         if( rVDev.GetDigitLanguage())
2529cdf0e10cSrcweir                             convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
2530cdf0e10cSrcweir 
2531cdf0e10cSrcweir                         createTextAction(
2532cdf0e10cSrcweir                             pAct->GetPoint(),
2533cdf0e10cSrcweir                             sText,
2534cdf0e10cSrcweir                             pAct->GetIndex(),
2535cdf0e10cSrcweir                             pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
2536cdf0e10cSrcweir                             pAct->GetDXArray(),
2537cdf0e10cSrcweir                             rFactoryParms,
2538cdf0e10cSrcweir                             bSubsettableActions );
2539cdf0e10cSrcweir                     }
2540cdf0e10cSrcweir                     break;
2541cdf0e10cSrcweir 
2542cdf0e10cSrcweir                     case META_TEXTLINE_ACTION:
2543cdf0e10cSrcweir                     {
2544cdf0e10cSrcweir                         MetaTextLineAction*      pAct = static_cast<MetaTextLineAction*>(pCurrAct);
2545cdf0e10cSrcweir 
2546cdf0e10cSrcweir                         const OutDevState&       rState( getState( rStates ) );
2547cdf0e10cSrcweir                         const ::Size             aBaselineOffset( tools::getBaselineOffset( rState,
2548cdf0e10cSrcweir                                                                                             rVDev ) );
2549cdf0e10cSrcweir                         const ::Point 		     aStartPoint( pAct->GetStartPoint() );
2550cdf0e10cSrcweir                         const ::basegfx::B2DSize aSize( rState.mapModeTransform *
2551cdf0e10cSrcweir                                                         ::basegfx::B2DSize(pAct->GetWidth(),
2552cdf0e10cSrcweir                                                                            0 ));
2553cdf0e10cSrcweir 
2554cdf0e10cSrcweir                         ActionSharedPtr pPolyAction(
2555cdf0e10cSrcweir                             PolyPolyActionFactory::createPolyPolyAction(
2556cdf0e10cSrcweir                                 tools::createTextLinesPolyPolygon(
2557cdf0e10cSrcweir                                     rState.mapModeTransform *
2558cdf0e10cSrcweir                                     ::basegfx::B2DPoint(
2559cdf0e10cSrcweir                                         ::vcl::unotools::b2DPointFromPoint(pAct->GetStartPoint()) +
2560cdf0e10cSrcweir                                         ::vcl::unotools::b2DSizeFromSize(aBaselineOffset)),
2561cdf0e10cSrcweir                                     aSize.getX(),
2562cdf0e10cSrcweir                                     tools::createTextLineInfo( rVDev,
2563cdf0e10cSrcweir                                                                rState )),
2564cdf0e10cSrcweir                                 rCanvas,
2565cdf0e10cSrcweir                                 rState ) );
2566cdf0e10cSrcweir 
2567cdf0e10cSrcweir                         if( pPolyAction.get() )
2568cdf0e10cSrcweir                         {
2569cdf0e10cSrcweir                             maActions.push_back(
2570cdf0e10cSrcweir                                 MtfAction(
2571cdf0e10cSrcweir                                     pPolyAction,
2572cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2573cdf0e10cSrcweir 
2574cdf0e10cSrcweir                             io_rCurrActionIndex += pPolyAction->getActionCount()-1;
2575cdf0e10cSrcweir                         }
2576cdf0e10cSrcweir                     }
2577cdf0e10cSrcweir                     break;
2578cdf0e10cSrcweir 
2579cdf0e10cSrcweir                     case META_TEXTRECT_ACTION:
2580cdf0e10cSrcweir                     {
2581cdf0e10cSrcweir                         MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pCurrAct);
2582cdf0e10cSrcweir 
2583cdf0e10cSrcweir                         pushState( rStates, PUSH_ALL );
2584cdf0e10cSrcweir 
2585cdf0e10cSrcweir                         // use the VDev to break up the text rect
2586cdf0e10cSrcweir                         // action into readily formatted lines
2587cdf0e10cSrcweir                         GDIMetaFile aTmpMtf;
2588cdf0e10cSrcweir                         rVDev.AddTextRectActions( pAct->GetRect(),
2589cdf0e10cSrcweir                                                   pAct->GetText(),
2590cdf0e10cSrcweir                                                   pAct->GetStyle(),
2591cdf0e10cSrcweir                                                   aTmpMtf );
2592cdf0e10cSrcweir 
2593cdf0e10cSrcweir                         createActions( aTmpMtf,
2594cdf0e10cSrcweir                                        rFactoryParms,
2595cdf0e10cSrcweir                                        bSubsettableActions );
2596cdf0e10cSrcweir 
2597cdf0e10cSrcweir                         popState( rStates );
2598cdf0e10cSrcweir 
2599cdf0e10cSrcweir                         break;
2600cdf0e10cSrcweir                     }
2601cdf0e10cSrcweir 
2602cdf0e10cSrcweir                     case META_STRETCHTEXT_ACTION:
2603cdf0e10cSrcweir                     {
2604cdf0e10cSrcweir                         MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pCurrAct);
2605cdf0e10cSrcweir                         XubString sText = XubString( pAct->GetText() );
2606cdf0e10cSrcweir 
2607cdf0e10cSrcweir                         if( rVDev.GetDigitLanguage())
2608cdf0e10cSrcweir                             convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
2609cdf0e10cSrcweir 
2610cdf0e10cSrcweir                         const sal_uInt16 nLen( pAct->GetLen() == (sal_uInt16)STRING_LEN ?
2611cdf0e10cSrcweir                                            pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen() );
2612cdf0e10cSrcweir 
2613cdf0e10cSrcweir                         // #i70897# Nothing to do, actually...
2614cdf0e10cSrcweir                         if( nLen == 0 )
2615cdf0e10cSrcweir                             break;
2616cdf0e10cSrcweir 
2617cdf0e10cSrcweir                         // have to fit the text into the given
2618cdf0e10cSrcweir                         // width. This is achieved by internally
2619cdf0e10cSrcweir                         // generating a DX array, and uniformly
2620cdf0e10cSrcweir                         // distributing the excess/insufficient width
2621cdf0e10cSrcweir                         // to every logical character.
2622cdf0e10cSrcweir                         ::boost::scoped_array< sal_Int32 > pDXArray( new sal_Int32[nLen] );
2623cdf0e10cSrcweir 
2624cdf0e10cSrcweir                         rVDev.GetTextArray( pAct->GetText(), pDXArray.get(),
2625cdf0e10cSrcweir                                             pAct->GetIndex(), pAct->GetLen() );
2626cdf0e10cSrcweir 
2627cdf0e10cSrcweir                         const sal_Int32 nWidthDifference( pAct->GetWidth() - pDXArray[ nLen-1 ] );
2628cdf0e10cSrcweir 
2629cdf0e10cSrcweir                         // Last entry of pDXArray contains total width of the text
2630cdf0e10cSrcweir                         sal_Int32* p=pDXArray.get();
2631cdf0e10cSrcweir                         for( sal_uInt16 i=1; i<=nLen; ++i )
2632cdf0e10cSrcweir                         {
2633cdf0e10cSrcweir                             // calc ratio for every array entry, to
2634cdf0e10cSrcweir                             // distribute rounding errors 'evenly'
2635cdf0e10cSrcweir                             // across the characters. Note that each
2636cdf0e10cSrcweir                             // entry represents the 'end' position of
2637cdf0e10cSrcweir                             // the corresponding character, thus, we
2638cdf0e10cSrcweir                             // let i run from 1 to nLen.
2639cdf0e10cSrcweir                             *p++ += (sal_Int32)i*nWidthDifference/nLen;
2640cdf0e10cSrcweir                         }
2641cdf0e10cSrcweir 
2642cdf0e10cSrcweir                         createTextAction(
2643cdf0e10cSrcweir                             pAct->GetPoint(),
2644cdf0e10cSrcweir                             sText,
2645cdf0e10cSrcweir                             pAct->GetIndex(),
2646cdf0e10cSrcweir                             pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
2647cdf0e10cSrcweir                             pDXArray.get(),
2648cdf0e10cSrcweir                             rFactoryParms,
2649cdf0e10cSrcweir                             bSubsettableActions );
2650cdf0e10cSrcweir                     }
2651cdf0e10cSrcweir                     break;
2652cdf0e10cSrcweir 
2653cdf0e10cSrcweir                     case META_RENDERGRAPHIC_ACTION:
2654cdf0e10cSrcweir                     {
2655cdf0e10cSrcweir                         MetaRenderGraphicAction* pAct = static_cast<MetaRenderGraphicAction*>(pCurrAct);
2656cdf0e10cSrcweir 
2657cdf0e10cSrcweir                         ActionSharedPtr pRenderGraphicAction(
2658cdf0e10cSrcweir                                 internal::RenderGraphicActionFactory::createRenderGraphicAction(
2659cdf0e10cSrcweir                                     pAct->GetRenderGraphic(),
2660cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2661cdf0e10cSrcweir                                     ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
2662cdf0e10cSrcweir                                     getState( rStates ).mapModeTransform *
2663cdf0e10cSrcweir                                     ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
2664cdf0e10cSrcweir                                     rCanvas,
2665cdf0e10cSrcweir                                     getState( rStates ) ) );
2666cdf0e10cSrcweir 
2667cdf0e10cSrcweir                         if( pRenderGraphicAction )
2668cdf0e10cSrcweir                         {
2669cdf0e10cSrcweir                             maActions.push_back(
2670cdf0e10cSrcweir                                 MtfAction(
2671cdf0e10cSrcweir                                     pRenderGraphicAction,
2672cdf0e10cSrcweir                                     io_rCurrActionIndex ) );
2673cdf0e10cSrcweir 
2674cdf0e10cSrcweir                             io_rCurrActionIndex += pRenderGraphicAction->getActionCount()-1;
2675cdf0e10cSrcweir                         }
2676cdf0e10cSrcweir                     }
2677cdf0e10cSrcweir                     break;
2678cdf0e10cSrcweir 
2679cdf0e10cSrcweir                     default:
2680cdf0e10cSrcweir                         OSL_ENSURE( false,
2681cdf0e10cSrcweir                                     "Unknown meta action type encountered" );
2682cdf0e10cSrcweir                         break;
2683cdf0e10cSrcweir                 }
2684cdf0e10cSrcweir 
2685cdf0e10cSrcweir                 // increment action index (each mtf action counts _at
2686cdf0e10cSrcweir                 // least_ one. Some count for more, therefore,
2687cdf0e10cSrcweir                 // io_rCurrActionIndex is sometimes incremented by
2688cdf0e10cSrcweir                 // pAct->getActionCount()-1 above, the -1 being the
2689cdf0e10cSrcweir                 // correction for the unconditional increment here).
2690cdf0e10cSrcweir                 ++io_rCurrActionIndex;
2691cdf0e10cSrcweir             }
2692cdf0e10cSrcweir 
2693cdf0e10cSrcweir             return true;
2694cdf0e10cSrcweir         }
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir 
2697cdf0e10cSrcweir         namespace
2698cdf0e10cSrcweir         {
2699cdf0e10cSrcweir             class ActionRenderer
2700cdf0e10cSrcweir             {
2701cdf0e10cSrcweir             public:
2702cdf0e10cSrcweir                 ActionRenderer( const ::basegfx::B2DHomMatrix& rTransformation ) :
2703cdf0e10cSrcweir                     maTransformation( rTransformation ),
2704cdf0e10cSrcweir                     mbRet( true )
2705cdf0e10cSrcweir                 {
2706cdf0e10cSrcweir                 }
2707cdf0e10cSrcweir 
2708cdf0e10cSrcweir                 bool result()
2709cdf0e10cSrcweir                 {
2710cdf0e10cSrcweir                     return mbRet;
2711cdf0e10cSrcweir                 }
2712cdf0e10cSrcweir 
2713cdf0e10cSrcweir                 void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
2714cdf0e10cSrcweir                 {
2715cdf0e10cSrcweir                     // ANDing the result. We want to fail if at least
2716cdf0e10cSrcweir                     // one action failed.
2717cdf0e10cSrcweir                     mbRet &= rAction.mpAction->render( maTransformation );
2718cdf0e10cSrcweir                 }
2719cdf0e10cSrcweir 
2720cdf0e10cSrcweir                 void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction&	rAction,
2721cdf0e10cSrcweir                                  const Action::Subset&									rSubset )
2722cdf0e10cSrcweir                 {
2723cdf0e10cSrcweir                     // ANDing the result. We want to fail if at least
2724cdf0e10cSrcweir                     // one action failed.
2725cdf0e10cSrcweir                     mbRet &= rAction.mpAction->render( maTransformation,
2726cdf0e10cSrcweir                                                        rSubset );
2727cdf0e10cSrcweir                 }
2728cdf0e10cSrcweir 
2729cdf0e10cSrcweir             private:
2730cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix	maTransformation;
2731cdf0e10cSrcweir                 bool					mbRet;
2732cdf0e10cSrcweir             };
2733cdf0e10cSrcweir 
2734cdf0e10cSrcweir             class AreaQuery
2735cdf0e10cSrcweir             {
2736cdf0e10cSrcweir             public:
2737cdf0e10cSrcweir                 AreaQuery( const ::basegfx::B2DHomMatrix& rTransformation ) :
2738cdf0e10cSrcweir                     maTransformation( rTransformation ),
2739cdf0e10cSrcweir                     maBounds()
2740cdf0e10cSrcweir                 {
2741cdf0e10cSrcweir                 }
2742cdf0e10cSrcweir 
2743cdf0e10cSrcweir                 bool result()
2744cdf0e10cSrcweir                 {
2745cdf0e10cSrcweir                     return true; // nothing can fail here
2746cdf0e10cSrcweir                 }
2747cdf0e10cSrcweir 
2748cdf0e10cSrcweir                 void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
2749cdf0e10cSrcweir                 {
2750cdf0e10cSrcweir                     maBounds.expand( rAction.mpAction->getBounds( maTransformation ) );
2751cdf0e10cSrcweir                 }
2752cdf0e10cSrcweir 
2753cdf0e10cSrcweir                 void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction&	rAction,
2754cdf0e10cSrcweir                                  const Action::Subset&									rSubset )
2755cdf0e10cSrcweir                 {
2756cdf0e10cSrcweir                     maBounds.expand( rAction.mpAction->getBounds( maTransformation,
2757cdf0e10cSrcweir                                                                   rSubset ) );
2758cdf0e10cSrcweir                 }
2759cdf0e10cSrcweir 
2760cdf0e10cSrcweir                 ::basegfx::B2DRange getBounds() const
2761cdf0e10cSrcweir                 {
2762cdf0e10cSrcweir                     return maBounds;
2763cdf0e10cSrcweir                 }
2764cdf0e10cSrcweir 
2765cdf0e10cSrcweir             private:
2766cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix	maTransformation;
2767cdf0e10cSrcweir                 ::basegfx::B2DRange		maBounds;
2768cdf0e10cSrcweir             };
2769cdf0e10cSrcweir 
2770cdf0e10cSrcweir             // Doing that via inline class. Compilers tend to not inline free
2771cdf0e10cSrcweir             // functions.
2772cdf0e10cSrcweir             struct UpperBoundActionIndexComparator
2773cdf0e10cSrcweir             {
2774cdf0e10cSrcweir                 bool operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rLHS,
2775cdf0e10cSrcweir                                  const ::cppcanvas::internal::ImplRenderer::MtfAction& rRHS )
2776cdf0e10cSrcweir                 {
2777cdf0e10cSrcweir                     const sal_Int32 nLHSCount( rLHS.mpAction ?
2778cdf0e10cSrcweir                                                rLHS.mpAction->getActionCount() : 0 );
2779cdf0e10cSrcweir                     const sal_Int32 nRHSCount( rRHS.mpAction ?
2780cdf0e10cSrcweir                                                rRHS.mpAction->getActionCount() : 0 );
2781cdf0e10cSrcweir 
2782cdf0e10cSrcweir                     // compare end of action range, to have an action selected
2783cdf0e10cSrcweir                     // by lower_bound even if the requested index points in
2784cdf0e10cSrcweir                     // the middle of the action's range
2785cdf0e10cSrcweir                     return rLHS.mnOrigIndex + nLHSCount < rRHS.mnOrigIndex + nRHSCount;
2786cdf0e10cSrcweir                 }
2787cdf0e10cSrcweir             };
2788cdf0e10cSrcweir 
2789cdf0e10cSrcweir             /** Algorithm to apply given functor to a subset range
2790cdf0e10cSrcweir 
2791cdf0e10cSrcweir             	@tpl Functor
2792cdf0e10cSrcweir 
2793cdf0e10cSrcweir                 Functor to call for each element of the subset
2794cdf0e10cSrcweir                 range. Must provide the following method signatures:
2795cdf0e10cSrcweir                 bool result() (returning false if operation failed)
2796cdf0e10cSrcweir 
2797cdf0e10cSrcweir              */
2798cdf0e10cSrcweir             template< typename Functor > bool
2799cdf0e10cSrcweir             	forSubsetRange( Functor& 											rFunctor,
2800cdf0e10cSrcweir                                 ImplRenderer::ActionVector::const_iterator			aRangeBegin,
2801cdf0e10cSrcweir                                 ImplRenderer::ActionVector::const_iterator			aRangeEnd,
2802cdf0e10cSrcweir                                 sal_Int32											nStartIndex,
2803cdf0e10cSrcweir                                 sal_Int32											nEndIndex,
2804cdf0e10cSrcweir                                 const ImplRenderer::ActionVector::const_iterator&	rEnd )
2805cdf0e10cSrcweir             {
2806cdf0e10cSrcweir                 if( aRangeBegin == aRangeEnd )
2807cdf0e10cSrcweir                 {
2808cdf0e10cSrcweir                     // only a single action. Setup subset, and call functor
2809cdf0e10cSrcweir                     Action::Subset aSubset;
2810cdf0e10cSrcweir                     aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
2811cdf0e10cSrcweir                                                         nStartIndex - aRangeBegin->mnOrigIndex );
2812cdf0e10cSrcweir                     aSubset.mnSubsetEnd   = ::std::min( aRangeBegin->mpAction->getActionCount(),
2813cdf0e10cSrcweir                                                         nEndIndex - aRangeBegin->mnOrigIndex );
2814cdf0e10cSrcweir 
2815cdf0e10cSrcweir                     ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
2816cdf0e10cSrcweir                                       "ImplRenderer::forSubsetRange(): Invalid indices" );
2817cdf0e10cSrcweir 
2818cdf0e10cSrcweir                     rFunctor( *aRangeBegin, aSubset );
2819cdf0e10cSrcweir                 }
2820cdf0e10cSrcweir                 else
2821cdf0e10cSrcweir                 {
2822cdf0e10cSrcweir                     // more than one action.
2823cdf0e10cSrcweir 
2824cdf0e10cSrcweir                     // render partial first, full intermediate, and
2825cdf0e10cSrcweir                     // partial last action
2826cdf0e10cSrcweir                     Action::Subset aSubset;
2827cdf0e10cSrcweir                     aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
2828cdf0e10cSrcweir                                                         nStartIndex - aRangeBegin->mnOrigIndex );
2829cdf0e10cSrcweir                     aSubset.mnSubsetEnd   = aRangeBegin->mpAction->getActionCount();
2830cdf0e10cSrcweir 
2831cdf0e10cSrcweir                     ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
2832cdf0e10cSrcweir                                       "ImplRenderer::forSubsetRange(): Invalid indices" );
2833cdf0e10cSrcweir 
2834cdf0e10cSrcweir                     rFunctor( *aRangeBegin, aSubset );
2835cdf0e10cSrcweir 
2836cdf0e10cSrcweir                     // first action rendered, skip to next
2837cdf0e10cSrcweir                     ++aRangeBegin;
2838cdf0e10cSrcweir 
2839cdf0e10cSrcweir                     // render full middle actions
2840cdf0e10cSrcweir                     while( aRangeBegin != aRangeEnd )
2841cdf0e10cSrcweir                         rFunctor( *aRangeBegin++ );
2842cdf0e10cSrcweir 
2843cdf0e10cSrcweir                     if( aRangeEnd == rEnd ||
2844cdf0e10cSrcweir                         aRangeEnd->mnOrigIndex > nEndIndex )
2845cdf0e10cSrcweir                     {
2846cdf0e10cSrcweir                         // aRangeEnd denotes end of action vector,
2847cdf0e10cSrcweir                         //
2848cdf0e10cSrcweir                         // or
2849cdf0e10cSrcweir                         //
2850cdf0e10cSrcweir                         // nEndIndex references something _after_
2851cdf0e10cSrcweir                         // aRangeBegin, but _before_ aRangeEnd
2852cdf0e10cSrcweir                         //
2853cdf0e10cSrcweir                         // either way: no partial action left
2854cdf0e10cSrcweir                         return rFunctor.result();
2855cdf0e10cSrcweir                     }
2856cdf0e10cSrcweir 
2857cdf0e10cSrcweir                     aSubset.mnSubsetBegin = 0;
2858cdf0e10cSrcweir                     aSubset.mnSubsetEnd   = nEndIndex - aRangeEnd->mnOrigIndex;
2859cdf0e10cSrcweir 
2860cdf0e10cSrcweir                     ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
2861cdf0e10cSrcweir                                       "ImplRenderer::forSubsetRange(): Invalid indices" );
2862cdf0e10cSrcweir 
2863cdf0e10cSrcweir                     rFunctor( *aRangeEnd, aSubset );
2864cdf0e10cSrcweir                 }
2865cdf0e10cSrcweir 
2866cdf0e10cSrcweir                 return rFunctor.result();
2867cdf0e10cSrcweir             }
2868cdf0e10cSrcweir         }
2869cdf0e10cSrcweir 
2870cdf0e10cSrcweir         bool ImplRenderer::getSubsetIndices( sal_Int32&						io_rStartIndex,
2871cdf0e10cSrcweir                                              sal_Int32&						io_rEndIndex,
2872cdf0e10cSrcweir                                              ActionVector::const_iterator& 	o_rRangeBegin,
2873cdf0e10cSrcweir                                              ActionVector::const_iterator& 	o_rRangeEnd ) const
2874cdf0e10cSrcweir         {
2875cdf0e10cSrcweir             ENSURE_OR_RETURN_FALSE( io_rStartIndex<=io_rEndIndex,
2876cdf0e10cSrcweir                               "ImplRenderer::getSubsetIndices(): invalid action range" );
2877cdf0e10cSrcweir 
2878cdf0e10cSrcweir             ENSURE_OR_RETURN_FALSE( !maActions.empty(),
2879cdf0e10cSrcweir                               "ImplRenderer::getSubsetIndices(): no actions to render" );
2880cdf0e10cSrcweir 
2881cdf0e10cSrcweir             const sal_Int32 nMinActionIndex( maActions.front().mnOrigIndex );
2882cdf0e10cSrcweir             const sal_Int32 nMaxActionIndex( maActions.back().mnOrigIndex +
2883cdf0e10cSrcweir                                              maActions.back().mpAction->getActionCount() );
2884cdf0e10cSrcweir 
2885cdf0e10cSrcweir             // clip given range to permissible values (there might be
2886cdf0e10cSrcweir             // ranges before and behind the valid indices)
2887cdf0e10cSrcweir             io_rStartIndex = ::std::max( nMinActionIndex,
2888cdf0e10cSrcweir                                          io_rStartIndex );
2889cdf0e10cSrcweir             io_rEndIndex = ::std::min( nMaxActionIndex,
2890cdf0e10cSrcweir                                        io_rEndIndex );
2891cdf0e10cSrcweir 
2892cdf0e10cSrcweir             if( io_rStartIndex == io_rEndIndex ||
2893cdf0e10cSrcweir                 io_rStartIndex > io_rEndIndex )
2894cdf0e10cSrcweir             {
2895cdf0e10cSrcweir 				// empty range, don't render anything. The second
2896cdf0e10cSrcweir 				// condition e.g. happens if the requested range lies
2897cdf0e10cSrcweir 				// fully before or behind the valid action indices.
2898cdf0e10cSrcweir                 return false;
2899cdf0e10cSrcweir             }
2900cdf0e10cSrcweir 
2901cdf0e10cSrcweir 
2902cdf0e10cSrcweir             const ActionVector::const_iterator aBegin( maActions.begin() );
2903cdf0e10cSrcweir             const ActionVector::const_iterator aEnd( maActions.end() );
2904cdf0e10cSrcweir 
2905cdf0e10cSrcweir 
2906cdf0e10cSrcweir             // find start and end action
2907cdf0e10cSrcweir             // =========================
2908cdf0e10cSrcweir             o_rRangeBegin = ::std::lower_bound( aBegin, aEnd,
2909cdf0e10cSrcweir                                                 MtfAction( ActionSharedPtr(), io_rStartIndex ),
2910cdf0e10cSrcweir                                                 UpperBoundActionIndexComparator() );
2911cdf0e10cSrcweir             o_rRangeEnd   = ::std::lower_bound( aBegin, aEnd,
2912cdf0e10cSrcweir                                                 MtfAction( ActionSharedPtr(), io_rEndIndex ),
2913cdf0e10cSrcweir                                                 UpperBoundActionIndexComparator() );
2914cdf0e10cSrcweir             return true;
2915cdf0e10cSrcweir         }
2916cdf0e10cSrcweir 
2917cdf0e10cSrcweir 
2918cdf0e10cSrcweir         // Public methods
2919cdf0e10cSrcweir         // ====================================================================
2920cdf0e10cSrcweir 
2921cdf0e10cSrcweir         ImplRenderer::ImplRenderer( const CanvasSharedPtr&	rCanvas,
2922cdf0e10cSrcweir                                     const GDIMetaFile&		rMtf,
2923cdf0e10cSrcweir                                     const Parameters&		rParams ) :
2924cdf0e10cSrcweir             CanvasGraphicHelper( rCanvas ),
2925cdf0e10cSrcweir             maActions()
2926cdf0e10cSrcweir         {
2927cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(mtf)" );
2928cdf0e10cSrcweir 
2929cdf0e10cSrcweir             OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
2930cdf0e10cSrcweir                         "ImplRenderer::ImplRenderer(): Invalid canvas" );
2931cdf0e10cSrcweir             OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
2932cdf0e10cSrcweir                         "ImplRenderer::ImplRenderer(): Invalid graphic device" );
2933cdf0e10cSrcweir 
2934cdf0e10cSrcweir             // make sure canvas and graphic device are valid; action
2935cdf0e10cSrcweir             // creation don't check that every time
2936cdf0e10cSrcweir             if( rCanvas.get() == NULL ||
2937cdf0e10cSrcweir                 !rCanvas->getUNOCanvas().is() ||
2938cdf0e10cSrcweir                 !rCanvas->getUNOCanvas()->getDevice().is() )
2939cdf0e10cSrcweir             {
2940cdf0e10cSrcweir                 // leave actions empty
2941cdf0e10cSrcweir                 return;
2942cdf0e10cSrcweir             }
2943cdf0e10cSrcweir 
2944cdf0e10cSrcweir             VectorOfOutDevStates	aStateStack;
2945cdf0e10cSrcweir 
2946cdf0e10cSrcweir             VirtualDevice aVDev;
2947cdf0e10cSrcweir             aVDev.EnableOutput( sal_False );
2948cdf0e10cSrcweir 
2949cdf0e10cSrcweir             // Setup VDev for state tracking and mapping
2950cdf0e10cSrcweir             // =========================================
2951cdf0e10cSrcweir 
2952cdf0e10cSrcweir             aVDev.SetMapMode( rMtf.GetPrefMapMode() );
2953cdf0e10cSrcweir 
2954cdf0e10cSrcweir             const Size aMtfSize( rMtf.GetPrefSize() );
2955cdf0e10cSrcweir             const Size aMtfSizePixPre( aVDev.LogicToPixel( aMtfSize,
2956cdf0e10cSrcweir                                                            rMtf.GetPrefMapMode() ) );
2957cdf0e10cSrcweir             const Point aEmptyPt;
2958cdf0e10cSrcweir             const Point aMtfOriginPix( aVDev.LogicToPixel( aEmptyPt ) );
2959cdf0e10cSrcweir 
2960cdf0e10cSrcweir             // #i44110# correct null-sized output - there are shapes
2961cdf0e10cSrcweir             // which have zero size in at least one dimension
2962cdf0e10cSrcweir             const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
2963cdf0e10cSrcweir                                     ::std::max( aMtfSizePixPre.Height(), 1L ) );
2964cdf0e10cSrcweir 
2965cdf0e10cSrcweir             sal_Int32 nCurrActions(0);
2966cdf0e10cSrcweir             ActionFactoryParameters aParms(aStateStack,
2967cdf0e10cSrcweir                                            rCanvas,
2968cdf0e10cSrcweir                                            aVDev,
2969cdf0e10cSrcweir                                            rParams,
2970cdf0e10cSrcweir                                            nCurrActions );
2971cdf0e10cSrcweir 
2972cdf0e10cSrcweir             // init state stack
2973cdf0e10cSrcweir             clearStateStack( aStateStack );
2974cdf0e10cSrcweir 
2975cdf0e10cSrcweir             // Setup local state, such that the metafile renders
2976cdf0e10cSrcweir             // itself into a one-by-one square at the origin for
2977cdf0e10cSrcweir             // identity view and render transformations
2978cdf0e10cSrcweir             getState( aStateStack ).transform.scale( 1.0 / aMtfSizePix.Width(),
2979cdf0e10cSrcweir                                                      1.0 / aMtfSizePix.Height() );
2980cdf0e10cSrcweir 
2981cdf0e10cSrcweir             tools::calcLogic2PixelAffineTransform( getState( aStateStack ).mapModeTransform,
2982cdf0e10cSrcweir                                                    aVDev );
2983cdf0e10cSrcweir 
2984cdf0e10cSrcweir             ColorSharedPtr pColor( getCanvas()->createColor() );
2985cdf0e10cSrcweir 
2986cdf0e10cSrcweir             // setup default text color to black
2987cdf0e10cSrcweir             getState( aStateStack ).textColor =
2988cdf0e10cSrcweir                 getState( aStateStack ).textFillColor =
2989cdf0e10cSrcweir                 getState( aStateStack ).textLineColor = pColor->getDeviceColor( 0x000000FF );
2990cdf0e10cSrcweir 
2991cdf0e10cSrcweir             // apply overrides from the Parameters struct
2992cdf0e10cSrcweir             if( rParams.maFillColor.is_initialized() )
2993cdf0e10cSrcweir             {
2994cdf0e10cSrcweir                 getState( aStateStack ).isFillColorSet = true;
2995cdf0e10cSrcweir                 getState( aStateStack ).fillColor = pColor->getDeviceColor( *rParams.maFillColor );
2996cdf0e10cSrcweir             }
2997cdf0e10cSrcweir             if( rParams.maLineColor.is_initialized() )
2998cdf0e10cSrcweir             {
2999cdf0e10cSrcweir                 getState( aStateStack ).isLineColorSet = true;
3000cdf0e10cSrcweir                 getState( aStateStack ).lineColor = pColor->getDeviceColor( *rParams.maLineColor );
3001cdf0e10cSrcweir             }
3002cdf0e10cSrcweir             if( rParams.maTextColor.is_initialized() )
3003cdf0e10cSrcweir             {
3004cdf0e10cSrcweir                 getState( aStateStack ).isTextFillColorSet = true;
3005cdf0e10cSrcweir                 getState( aStateStack ).isTextLineColorSet = true;
3006cdf0e10cSrcweir                 getState( aStateStack ).textColor =
3007cdf0e10cSrcweir                     getState( aStateStack ).textFillColor =
3008cdf0e10cSrcweir                     getState( aStateStack ).textLineColor = pColor->getDeviceColor( *rParams.maTextColor );
3009cdf0e10cSrcweir             }
3010cdf0e10cSrcweir             if( rParams.maFontName.is_initialized() ||
3011cdf0e10cSrcweir                 rParams.maFontWeight.is_initialized() ||
3012cdf0e10cSrcweir                 rParams.maFontLetterForm.is_initialized() ||
3013cdf0e10cSrcweir                 rParams.maFontUnderline.is_initialized()  ||
3014cdf0e10cSrcweir                 rParams.maFontProportion.is_initialized() )
3015cdf0e10cSrcweir             {
3016cdf0e10cSrcweir                 ::cppcanvas::internal::OutDevState& rState = getState( aStateStack );
3017cdf0e10cSrcweir 
3018cdf0e10cSrcweir                 rState.xFont = createFont( rState.fontRotation,
3019cdf0e10cSrcweir                                            ::Font(), // default font
3020cdf0e10cSrcweir                                            aParms );
3021cdf0e10cSrcweir             }
3022cdf0e10cSrcweir 
3023cdf0e10cSrcweir             createActions( const_cast<GDIMetaFile&>(rMtf), // HACK(Q2):
3024cdf0e10cSrcweir 								                           // we're
3025cdf0e10cSrcweir                         		                           // changing
3026cdf0e10cSrcweir                            		                           // the
3027cdf0e10cSrcweir                            		                           // current
3028cdf0e10cSrcweir                            		                           // action
3029cdf0e10cSrcweir                            		                           // in
3030cdf0e10cSrcweir                            		                           // createActions!
3031cdf0e10cSrcweir                            aParms,
3032cdf0e10cSrcweir                            true // TODO(P1): make subsettability configurable
3033cdf0e10cSrcweir                             );
3034cdf0e10cSrcweir         }
3035cdf0e10cSrcweir 
3036cdf0e10cSrcweir         ImplRenderer::ImplRenderer( const CanvasSharedPtr&	rCanvas,
3037cdf0e10cSrcweir                                     const BitmapEx&			rBmpEx,
3038cdf0e10cSrcweir                                     const Parameters&		rParams ) :
3039cdf0e10cSrcweir             CanvasGraphicHelper( rCanvas ),
3040cdf0e10cSrcweir             maActions()
3041cdf0e10cSrcweir         {
3042cdf0e10cSrcweir             // TODO(F3): property modification parameters are
3043cdf0e10cSrcweir             // currently ignored for Bitmaps
3044cdf0e10cSrcweir             (void)rParams;
3045cdf0e10cSrcweir 
3046cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(bitmap)" );
3047cdf0e10cSrcweir 
3048cdf0e10cSrcweir             OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
3049cdf0e10cSrcweir                         "ImplRenderer::ImplRenderer(): Invalid canvas" );
3050cdf0e10cSrcweir             OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
3051cdf0e10cSrcweir                         "ImplRenderer::ImplRenderer(): Invalid graphic device" );
3052cdf0e10cSrcweir 
3053cdf0e10cSrcweir             // make sure canvas and graphic device are valid; action
3054cdf0e10cSrcweir             // creation don't check that every time
3055cdf0e10cSrcweir             if( rCanvas.get() == NULL ||
3056cdf0e10cSrcweir                 !rCanvas->getUNOCanvas().is() ||
3057cdf0e10cSrcweir                 !rCanvas->getUNOCanvas()->getDevice().is() )
3058cdf0e10cSrcweir             {
3059cdf0e10cSrcweir                 // leave actions empty
3060cdf0e10cSrcweir                 return;
3061cdf0e10cSrcweir             }
3062cdf0e10cSrcweir 
3063cdf0e10cSrcweir             OutDevState aState;
3064cdf0e10cSrcweir 
3065cdf0e10cSrcweir             const Size aBmpSize( rBmpEx.GetSizePixel() );
3066cdf0e10cSrcweir 
3067cdf0e10cSrcweir             // Setup local state, such that the bitmap renders itself
3068cdf0e10cSrcweir             // into a one-by-one square for identity view and render
3069cdf0e10cSrcweir             // transformations
3070cdf0e10cSrcweir             aState.transform.scale( 1.0 / aBmpSize.Width(),
3071cdf0e10cSrcweir                                     1.0 / aBmpSize.Height() );
3072cdf0e10cSrcweir 
3073cdf0e10cSrcweir             // create a single action for the provided BitmapEx
3074cdf0e10cSrcweir             maActions.push_back(
3075cdf0e10cSrcweir                 MtfAction(
3076cdf0e10cSrcweir                     BitmapActionFactory::createBitmapAction(
3077cdf0e10cSrcweir                         rBmpEx,
3078cdf0e10cSrcweir                         ::basegfx::B2DPoint(),
3079cdf0e10cSrcweir                         rCanvas,
3080cdf0e10cSrcweir                         aState),
3081cdf0e10cSrcweir                     0 ) );
3082cdf0e10cSrcweir         }
3083cdf0e10cSrcweir 
3084cdf0e10cSrcweir         ImplRenderer::~ImplRenderer()
3085cdf0e10cSrcweir         {
3086cdf0e10cSrcweir         }
3087cdf0e10cSrcweir 
3088cdf0e10cSrcweir         bool ImplRenderer::drawSubset( sal_Int32	nStartIndex,
3089cdf0e10cSrcweir                                        sal_Int32	nEndIndex ) const
3090cdf0e10cSrcweir         {
3091cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::drawSubset()" );
3092cdf0e10cSrcweir 
3093cdf0e10cSrcweir             ActionVector::const_iterator aRangeBegin;
3094cdf0e10cSrcweir             ActionVector::const_iterator aRangeEnd;
3095cdf0e10cSrcweir 
3096cdf0e10cSrcweir             try
3097cdf0e10cSrcweir             {
3098cdf0e10cSrcweir                 if( !getSubsetIndices( nStartIndex, nEndIndex,
3099cdf0e10cSrcweir                                        aRangeBegin, aRangeEnd ) )
3100cdf0e10cSrcweir                     return true; // nothing to render (but _that_ was successful)
3101cdf0e10cSrcweir 
3102cdf0e10cSrcweir                 // now, aRangeBegin references the action in which the
3103cdf0e10cSrcweir                 // subset rendering must start, and aRangeEnd references
3104cdf0e10cSrcweir                 // the action in which the subset rendering must end (it
3105cdf0e10cSrcweir                 // might also end right at the start of the referenced
3106cdf0e10cSrcweir                 // action, such that zero of that action needs to be
3107cdf0e10cSrcweir                 // rendered).
3108cdf0e10cSrcweir 
3109cdf0e10cSrcweir 
3110cdf0e10cSrcweir                 // render subset of actions
3111cdf0e10cSrcweir                 // ========================
3112cdf0e10cSrcweir 
3113cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix aMatrix;
3114cdf0e10cSrcweir                 ::canvas::tools::getRenderStateTransform( aMatrix,
3115cdf0e10cSrcweir                                                           getRenderState() );
3116cdf0e10cSrcweir 
3117cdf0e10cSrcweir                 ActionRenderer aRenderer( aMatrix );
3118cdf0e10cSrcweir 
3119cdf0e10cSrcweir                 return forSubsetRange( aRenderer,
3120cdf0e10cSrcweir                                        aRangeBegin,
3121cdf0e10cSrcweir                                        aRangeEnd,
3122cdf0e10cSrcweir                                        nStartIndex,
3123cdf0e10cSrcweir                                        nEndIndex,
3124cdf0e10cSrcweir                                        maActions.end() );
3125cdf0e10cSrcweir             }
3126cdf0e10cSrcweir             catch( uno::Exception& )
3127cdf0e10cSrcweir             {
3128cdf0e10cSrcweir                 OSL_ENSURE( false,
3129cdf0e10cSrcweir                             rtl::OUStringToOString(
3130cdf0e10cSrcweir                                 comphelper::anyToString( cppu::getCaughtException() ),
3131cdf0e10cSrcweir                                 RTL_TEXTENCODING_UTF8 ).getStr() );
3132cdf0e10cSrcweir 
3133cdf0e10cSrcweir                 // convert error to return value
3134cdf0e10cSrcweir                 return false;
3135cdf0e10cSrcweir             }
3136cdf0e10cSrcweir         }
3137cdf0e10cSrcweir 
3138cdf0e10cSrcweir         ::basegfx::B2DRange ImplRenderer::getSubsetArea( sal_Int32	nStartIndex,
3139cdf0e10cSrcweir                                                          sal_Int32	nEndIndex ) const
3140cdf0e10cSrcweir         {
3141cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::getSubsetArea()" );
3142cdf0e10cSrcweir 
3143cdf0e10cSrcweir             ActionVector::const_iterator aRangeBegin;
3144cdf0e10cSrcweir             ActionVector::const_iterator aRangeEnd;
3145cdf0e10cSrcweir 
3146cdf0e10cSrcweir             if( !getSubsetIndices( nStartIndex, nEndIndex,
3147cdf0e10cSrcweir                                    aRangeBegin, aRangeEnd ) )
3148cdf0e10cSrcweir                 return ::basegfx::B2DRange(); // nothing to render -> empty range
3149cdf0e10cSrcweir 
3150cdf0e10cSrcweir             // now, aRangeBegin references the action in which the
3151cdf0e10cSrcweir             // subset querying must start, and aRangeEnd references
3152cdf0e10cSrcweir             // the action in which the subset querying must end (it
3153cdf0e10cSrcweir             // might also end right at the start of the referenced
3154cdf0e10cSrcweir             // action, such that zero of that action needs to be
3155cdf0e10cSrcweir             // queried).
3156cdf0e10cSrcweir 
3157cdf0e10cSrcweir 
3158cdf0e10cSrcweir             // query bounds for subset of actions
3159cdf0e10cSrcweir             // ==================================
3160cdf0e10cSrcweir 
3161cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aMatrix;
3162cdf0e10cSrcweir             ::canvas::tools::getRenderStateTransform( aMatrix,
3163cdf0e10cSrcweir                                                       getRenderState() );
3164cdf0e10cSrcweir 
3165cdf0e10cSrcweir             AreaQuery aQuery( aMatrix );
3166cdf0e10cSrcweir             forSubsetRange( aQuery,
3167cdf0e10cSrcweir                             aRangeBegin,
3168cdf0e10cSrcweir                             aRangeEnd,
3169cdf0e10cSrcweir                             nStartIndex,
3170cdf0e10cSrcweir                             nEndIndex,
3171cdf0e10cSrcweir                             maActions.end() );
3172cdf0e10cSrcweir 
3173cdf0e10cSrcweir             return aQuery.getBounds();
3174cdf0e10cSrcweir         }
3175cdf0e10cSrcweir 
3176cdf0e10cSrcweir         bool ImplRenderer::draw() const
3177cdf0e10cSrcweir         {
3178cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::draw()" );
3179cdf0e10cSrcweir 
3180cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aMatrix;
3181cdf0e10cSrcweir             ::canvas::tools::getRenderStateTransform( aMatrix,
3182cdf0e10cSrcweir                                                       getRenderState() );
3183cdf0e10cSrcweir 
3184cdf0e10cSrcweir             try
3185cdf0e10cSrcweir             {
3186cdf0e10cSrcweir                 return ::std::for_each( maActions.begin(), maActions.end(), ActionRenderer( aMatrix ) ).result();
3187cdf0e10cSrcweir             }
3188cdf0e10cSrcweir             catch( uno::Exception& )
3189cdf0e10cSrcweir             {
3190cdf0e10cSrcweir                 OSL_ENSURE( false,
3191cdf0e10cSrcweir                             rtl::OUStringToOString(
3192cdf0e10cSrcweir                                 comphelper::anyToString( cppu::getCaughtException() ),
3193cdf0e10cSrcweir                                 RTL_TEXTENCODING_UTF8 ).getStr() );
3194cdf0e10cSrcweir 
3195cdf0e10cSrcweir                 return false;
3196cdf0e10cSrcweir             }
3197cdf0e10cSrcweir         }
3198cdf0e10cSrcweir     }
3199cdf0e10cSrcweir }
3200