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