xref: /AOO41X/main/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_cppcanvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <tools/gen.hxx>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <canvas/debug.hxx>
34*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
35*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <rtl/logfile.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <com/sun/star/rendering/XBitmap.hpp>
40*cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvas.hpp>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include <rtl/math.hxx>
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir #include <vcl/metaact.hxx>
45*cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
46*cdf0e10cSrcweir #include <vcl/canvastools.hxx>
47*cdf0e10cSrcweir #include <vcl/svapp.hxx>
48*cdf0e10cSrcweir #include <vcl/outdev.hxx>
49*cdf0e10cSrcweir #include <vcl/virdev.hxx>
50*cdf0e10cSrcweir #include <vcl/virdev.hxx>
51*cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
52*cdf0e10cSrcweir #include <vcl/gradient.hxx>
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
57*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
58*cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx>
59*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
60*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
61*cdf0e10cSrcweir #include <basegfx/tuple/b2dtuple.hxx>
62*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir #include <boost/utility.hpp>
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir #include "transparencygroupaction.hxx"
67*cdf0e10cSrcweir #include "outdevstate.hxx"
68*cdf0e10cSrcweir #include "mtftools.hxx"
69*cdf0e10cSrcweir #include "cppcanvas/vclfactory.hxx"
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir using namespace ::com::sun::star;
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir namespace cppcanvas
75*cdf0e10cSrcweir {
76*cdf0e10cSrcweir     namespace internal
77*cdf0e10cSrcweir     {
78*cdf0e10cSrcweir 		// free support functions
79*cdf0e10cSrcweir 		// ======================
80*cdf0e10cSrcweir         namespace
81*cdf0e10cSrcweir         {
82*cdf0e10cSrcweir             class TransparencyGroupAction : public Action, private ::boost::noncopyable
83*cdf0e10cSrcweir             {
84*cdf0e10cSrcweir             public:
85*cdf0e10cSrcweir                 /** Create new transparency group action.
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir         	    	@param rGroupMtf
88*cdf0e10cSrcweir                     Metafile that groups all actions to be rendered
89*cdf0e10cSrcweir                     transparent
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir                     @param rParms
92*cdf0e10cSrcweir                     Render parameters
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir                     @param rDstPoint
95*cdf0e10cSrcweir                     Left, top edge of destination, in current state
96*cdf0e10cSrcweir                     coordinate system
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir                     @param rDstSize
99*cdf0e10cSrcweir                     Size of the transparency group object, in current
100*cdf0e10cSrcweir                     state coordinate system.
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir                     @param nAlpha
103*cdf0e10cSrcweir                     Alpha value, must be in the range [0,1]
104*cdf0e10cSrcweir                 */
105*cdf0e10cSrcweir                 TransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
106*cdf0e10cSrcweir                                          const Renderer::Parameters& 	rParms,
107*cdf0e10cSrcweir                                          const ::basegfx::B2DPoint& 	rDstPoint,
108*cdf0e10cSrcweir                                          const ::basegfx::B2DVector& 	rDstSize,
109*cdf0e10cSrcweir                                          double 						nAlpha,
110*cdf0e10cSrcweir                                          const CanvasSharedPtr&			rCanvas,
111*cdf0e10cSrcweir                                          const OutDevState& 			rState );
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir                 /** Create new transparency group action.
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir 	            	@param rGroupMtf
116*cdf0e10cSrcweir                     Metafile that groups all actions to be rendered
117*cdf0e10cSrcweir                     transparent.
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir                     @param rAlphaGradient
120*cdf0e10cSrcweir                     VCL gradient, to be rendered into the action's alpha
121*cdf0e10cSrcweir                     channel.
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir                     @param rParms
124*cdf0e10cSrcweir                     Render parameters
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir                     @param rDstPoint
127*cdf0e10cSrcweir                     Left, top edge of destination, in current state
128*cdf0e10cSrcweir                     coordinate system
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir                     @param rDstSize
131*cdf0e10cSrcweir                     Size of the transparency group object, in current
132*cdf0e10cSrcweir                     state coordinate system.
133*cdf0e10cSrcweir                 */
134*cdf0e10cSrcweir                 TransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
135*cdf0e10cSrcweir                                          GradientAutoPtr&				rAlphaGradient,
136*cdf0e10cSrcweir                                          const Renderer::Parameters& 	rParms,
137*cdf0e10cSrcweir                                          const ::basegfx::B2DPoint& 	rDstPoint,
138*cdf0e10cSrcweir                                          const ::basegfx::B2DVector& 	rDstSize,
139*cdf0e10cSrcweir                                          const CanvasSharedPtr&			rCanvas,
140*cdf0e10cSrcweir                                          const OutDevState& 			rState );
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
143*cdf0e10cSrcweir                 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
144*cdf0e10cSrcweir                                      const Subset&					rSubset ) const;
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
147*cdf0e10cSrcweir                 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
148*cdf0e10cSrcweir                                                        const Subset&					rSubset ) const;
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir                 virtual sal_Int32 getActionCount() const;
151*cdf0e10cSrcweir 
152*cdf0e10cSrcweir             private:
153*cdf0e10cSrcweir                 MtfAutoPtr											mpGroupMtf;
154*cdf0e10cSrcweir                 GradientAutoPtr										mpAlphaGradient;
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir                 const Renderer::Parameters 							maParms;
157*cdf0e10cSrcweir 
158*cdf0e10cSrcweir                 const ::basegfx::B2DSize 							maDstSize;
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir                 mutable uno::Reference< rendering::XBitmap > 		mxBufferBitmap; // contains last rendered version
161*cdf0e10cSrcweir                 mutable ::basegfx::B2DHomMatrix						maLastTransformation; // contains last active transformation
162*cdf0e10cSrcweir                 mutable Subset										maLastSubset; // contains last effective subset
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir                 // transformation for
165*cdf0e10cSrcweir                 // mxBufferBitmap content
166*cdf0e10cSrcweir                 CanvasSharedPtr										mpCanvas;
167*cdf0e10cSrcweir                 rendering::RenderState								maState;
168*cdf0e10cSrcweir                 const double										mnAlpha;
169*cdf0e10cSrcweir             };
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir             /** Setup transformation such that the next render call is
173*cdf0e10cSrcweir                 moved rPoint away, and scaled according to the ratio
174*cdf0e10cSrcweir                 given by src and dst size.
175*cdf0e10cSrcweir             */
176*cdf0e10cSrcweir             void implSetupTransform( rendering::RenderState& 	rRenderState,
177*cdf0e10cSrcweir                                      const ::basegfx::B2DPoint&	rDstPoint	)
178*cdf0e10cSrcweir             {
179*cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix	aLocalTransformation;
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir                 aLocalTransformation.translate( rDstPoint.getX(),
182*cdf0e10cSrcweir                                                 rDstPoint.getY() );
183*cdf0e10cSrcweir                 ::canvas::tools::appendToRenderState( rRenderState,
184*cdf0e10cSrcweir                                                       aLocalTransformation );
185*cdf0e10cSrcweir             }
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir             TransparencyGroupAction::TransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
188*cdf0e10cSrcweir                                                               const Renderer::Parameters& 	rParms,
189*cdf0e10cSrcweir                                                               const ::basegfx::B2DPoint& 	rDstPoint,
190*cdf0e10cSrcweir                                                               const ::basegfx::B2DVector& 	rDstSize,
191*cdf0e10cSrcweir                                                               double 						nAlpha,
192*cdf0e10cSrcweir                                                               const CanvasSharedPtr&		rCanvas,
193*cdf0e10cSrcweir                                                               const OutDevState& 			rState ) :
194*cdf0e10cSrcweir                 mpGroupMtf( rGroupMtf ),
195*cdf0e10cSrcweir                 mpAlphaGradient(),
196*cdf0e10cSrcweir                 maParms( rParms ),
197*cdf0e10cSrcweir                 maDstSize( rDstSize ),
198*cdf0e10cSrcweir                 mxBufferBitmap(),
199*cdf0e10cSrcweir                 maLastTransformation(),
200*cdf0e10cSrcweir                 mpCanvas( rCanvas ),
201*cdf0e10cSrcweir                 maState(),
202*cdf0e10cSrcweir                 mnAlpha( nAlpha )
203*cdf0e10cSrcweir             {
204*cdf0e10cSrcweir                 tools::initRenderState(maState,rState);
205*cdf0e10cSrcweir                 implSetupTransform( maState, rDstPoint );
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir                 // correct clip (which is relative to original transform)
208*cdf0e10cSrcweir                 tools::modifyClip( maState,
209*cdf0e10cSrcweir                                    rState,
210*cdf0e10cSrcweir                                    rCanvas,
211*cdf0e10cSrcweir                                    rDstPoint,
212*cdf0e10cSrcweir                                    NULL,
213*cdf0e10cSrcweir                                    NULL );
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir                 maLastSubset.mnSubsetBegin = 0;
216*cdf0e10cSrcweir                 maLastSubset.mnSubsetEnd = -1;
217*cdf0e10cSrcweir             }
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir             TransparencyGroupAction::TransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
220*cdf0e10cSrcweir                                                               GradientAutoPtr&				rAlphaGradient,
221*cdf0e10cSrcweir                                                               const Renderer::Parameters& 	rParms,
222*cdf0e10cSrcweir                                                               const ::basegfx::B2DPoint& 	rDstPoint,
223*cdf0e10cSrcweir                                                               const ::basegfx::B2DVector& 	rDstSize,
224*cdf0e10cSrcweir                                                               const CanvasSharedPtr&		rCanvas,
225*cdf0e10cSrcweir                                                               const OutDevState& 			rState ) :
226*cdf0e10cSrcweir                 mpGroupMtf( rGroupMtf ),
227*cdf0e10cSrcweir                 mpAlphaGradient( rAlphaGradient ),
228*cdf0e10cSrcweir                 maParms( rParms ),
229*cdf0e10cSrcweir                 maDstSize( rDstSize ),
230*cdf0e10cSrcweir                 mxBufferBitmap(),
231*cdf0e10cSrcweir                 maLastTransformation(),
232*cdf0e10cSrcweir                 mpCanvas( rCanvas ),
233*cdf0e10cSrcweir                 maState(),
234*cdf0e10cSrcweir                 mnAlpha( 1.0 )
235*cdf0e10cSrcweir             {
236*cdf0e10cSrcweir                 tools::initRenderState(maState,rState);
237*cdf0e10cSrcweir                 implSetupTransform( maState, rDstPoint );
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir                 // correct clip (which is relative to original transform)
240*cdf0e10cSrcweir                 tools::modifyClip( maState,
241*cdf0e10cSrcweir                                    rState,
242*cdf0e10cSrcweir                                    rCanvas,
243*cdf0e10cSrcweir                                    rDstPoint,
244*cdf0e10cSrcweir                                    NULL,
245*cdf0e10cSrcweir                                    NULL );
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir                 maLastSubset.mnSubsetBegin = 0;
248*cdf0e10cSrcweir                 maLastSubset.mnSubsetEnd = -1;
249*cdf0e10cSrcweir             }
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir             // TODO(P3): The whole float transparency handling is a mess,
252*cdf0e10cSrcweir             // this should be refactored. What's more, the old idea of
253*cdf0e10cSrcweir             // having only internal 'metaactions', and not the original
254*cdf0e10cSrcweir             // GDIMetaFile now looks a lot less attractive. Try to move
255*cdf0e10cSrcweir             // into the direction of having a direct GDIMetaFile2XCanvas
256*cdf0e10cSrcweir             // renderer, and maybe a separate metafile XCanvas
257*cdf0e10cSrcweir             // implementation.
258*cdf0e10cSrcweir             bool TransparencyGroupAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
259*cdf0e10cSrcweir                                                   const Subset&						rSubset ) const
260*cdf0e10cSrcweir             {
261*cdf0e10cSrcweir                 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TransparencyGroupAction::render()" );
262*cdf0e10cSrcweir                 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TransparencyGroupAction: 0x%X", this );
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir                 // determine overall transformation matrix (render, view,
265*cdf0e10cSrcweir                 // and passed transformation)
266*cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix aTransform;
267*cdf0e10cSrcweir                 ::canvas::tools::getRenderStateTransform( aTransform, maState );
268*cdf0e10cSrcweir                 aTransform = rTransformation * aTransform;
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix aTotalTransform;
271*cdf0e10cSrcweir                 ::canvas::tools::getViewStateTransform( aTotalTransform, mpCanvas->getViewState() );
272*cdf0e10cSrcweir                 aTotalTransform = aTotalTransform * aTransform;
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir                 // since pure translational changes to the transformation
275*cdf0e10cSrcweir                 // does not matter, remove them before comparing
276*cdf0e10cSrcweir                 aTotalTransform.set( 0, 2, 0.0 );
277*cdf0e10cSrcweir                 aTotalTransform.set( 1, 2, 0.0 );
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir                 // if there's no buffer bitmap, or as soon as the
280*cdf0e10cSrcweir                 // total transformation changes, we've got to
281*cdf0e10cSrcweir                 // re-render the bitmap
282*cdf0e10cSrcweir                 if( !mxBufferBitmap.is() ||
283*cdf0e10cSrcweir                     aTotalTransform != maLastTransformation ||
284*cdf0e10cSrcweir                     rSubset.mnSubsetBegin != maLastSubset.mnSubsetBegin ||
285*cdf0e10cSrcweir                     rSubset.mnSubsetEnd != maLastSubset.mnSubsetEnd )
286*cdf0e10cSrcweir                 {
287*cdf0e10cSrcweir                     DBG_TESTSOLARMUTEX();
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir                     // determine total scaling factor of the
290*cdf0e10cSrcweir                     // transformation matrix - need to make the bitmap
291*cdf0e10cSrcweir                     // large enough
292*cdf0e10cSrcweir                     ::basegfx::B2DTuple aScale;
293*cdf0e10cSrcweir                     ::basegfx::B2DTuple aTranslate;
294*cdf0e10cSrcweir                     double				nRotate;
295*cdf0e10cSrcweir                     double				nShearX;
296*cdf0e10cSrcweir                     if( !aTotalTransform.decompose( aScale,
297*cdf0e10cSrcweir                                                     aTranslate,
298*cdf0e10cSrcweir                                                     nRotate,
299*cdf0e10cSrcweir                                                     nShearX ) )
300*cdf0e10cSrcweir                     {
301*cdf0e10cSrcweir                         OSL_ENSURE( false,
302*cdf0e10cSrcweir                                     "TransparencyGroupAction::render(): non-decomposable transformation" );
303*cdf0e10cSrcweir                         return false;
304*cdf0e10cSrcweir                     }
305*cdf0e10cSrcweir 
306*cdf0e10cSrcweir                     // output size of metafile
307*cdf0e10cSrcweir                     ::Size aOutputSizePixel( ::basegfx::fround( aScale.getX() * maDstSize.getX() ),
308*cdf0e10cSrcweir                                              ::basegfx::fround( aScale.getY() * maDstSize.getY() ) );
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir                     // pixel size of cache bitmap: round up to nearest int
311*cdf0e10cSrcweir                     ::Size aBitmapSizePixel( static_cast<sal_Int32>( aScale.getX() * maDstSize.getX() )+1,
312*cdf0e10cSrcweir                                              static_cast<sal_Int32>( aScale.getY() * maDstSize.getY() )+1 );
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir                     ::Point aEmptyPoint;
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir                     // render our content into an appropriately sized
317*cdf0e10cSrcweir                     // VirtualDevice with alpha channel
318*cdf0e10cSrcweir                     VirtualDevice aVDev(
319*cdf0e10cSrcweir                         *::Application::GetDefaultDevice(), 0, 0 );
320*cdf0e10cSrcweir                     aVDev.SetOutputSizePixel( aBitmapSizePixel );
321*cdf0e10cSrcweir                     aVDev.SetMapMode();
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir                     if( rSubset.mnSubsetBegin != 0 ||
324*cdf0e10cSrcweir                         rSubset.mnSubsetEnd != -1 )
325*cdf0e10cSrcweir                     {
326*cdf0e10cSrcweir                         // true subset - extract referenced
327*cdf0e10cSrcweir                         // metaactions from mpGroupMtf
328*cdf0e10cSrcweir                         GDIMetaFile aMtf;
329*cdf0e10cSrcweir                         MetaAction* pCurrAct;
330*cdf0e10cSrcweir                         int 		nCurrActionIndex;
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir                         // extract subset actions
333*cdf0e10cSrcweir                         for( nCurrActionIndex=0,
334*cdf0e10cSrcweir                                  pCurrAct=mpGroupMtf->FirstAction();
335*cdf0e10cSrcweir                              pCurrAct;
336*cdf0e10cSrcweir                              ++nCurrActionIndex, pCurrAct = mpGroupMtf->NextAction() )
337*cdf0e10cSrcweir                         {
338*cdf0e10cSrcweir                             switch( pCurrAct->GetType() )
339*cdf0e10cSrcweir                             {
340*cdf0e10cSrcweir                                 case META_PUSH_ACTION:
341*cdf0e10cSrcweir                                 case META_POP_ACTION:
342*cdf0e10cSrcweir                                 case META_CLIPREGION_ACTION:
343*cdf0e10cSrcweir                                 case META_ISECTRECTCLIPREGION_ACTION:
344*cdf0e10cSrcweir                                 case META_ISECTREGIONCLIPREGION_ACTION:
345*cdf0e10cSrcweir                                 case META_MOVECLIPREGION_ACTION:
346*cdf0e10cSrcweir                                 case META_LINECOLOR_ACTION:
347*cdf0e10cSrcweir                                 case META_FILLCOLOR_ACTION:
348*cdf0e10cSrcweir                                 case META_TEXTCOLOR_ACTION:
349*cdf0e10cSrcweir                                 case META_TEXTFILLCOLOR_ACTION:
350*cdf0e10cSrcweir                                 case META_TEXTLINECOLOR_ACTION:
351*cdf0e10cSrcweir                                 case META_TEXTALIGN_ACTION:
352*cdf0e10cSrcweir                                 case META_FONT_ACTION:
353*cdf0e10cSrcweir                                 case META_RASTEROP_ACTION:
354*cdf0e10cSrcweir                                 case META_REFPOINT_ACTION:
355*cdf0e10cSrcweir                                 case META_LAYOUTMODE_ACTION:
356*cdf0e10cSrcweir                                     // state-changing action - copy as-is
357*cdf0e10cSrcweir                                     aMtf.AddAction( pCurrAct->Clone() );
358*cdf0e10cSrcweir                                     break;
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir                                 case META_GRADIENT_ACTION:
361*cdf0e10cSrcweir                                 case META_HATCH_ACTION:
362*cdf0e10cSrcweir                                 case META_EPS_ACTION:
363*cdf0e10cSrcweir                                 case META_COMMENT_ACTION:
364*cdf0e10cSrcweir                                 case META_POINT_ACTION:
365*cdf0e10cSrcweir                                 case META_PIXEL_ACTION:
366*cdf0e10cSrcweir                                 case META_LINE_ACTION:
367*cdf0e10cSrcweir                                 case META_RECT_ACTION:
368*cdf0e10cSrcweir                                 case META_ROUNDRECT_ACTION:
369*cdf0e10cSrcweir                                 case META_ELLIPSE_ACTION:
370*cdf0e10cSrcweir                                 case META_ARC_ACTION:
371*cdf0e10cSrcweir                                 case META_PIE_ACTION:
372*cdf0e10cSrcweir                                 case META_CHORD_ACTION:
373*cdf0e10cSrcweir                                 case META_POLYLINE_ACTION:
374*cdf0e10cSrcweir                                 case META_POLYGON_ACTION:
375*cdf0e10cSrcweir                                 case META_POLYPOLYGON_ACTION:
376*cdf0e10cSrcweir                                 case META_BMP_ACTION:
377*cdf0e10cSrcweir                                 case META_BMPSCALE_ACTION:
378*cdf0e10cSrcweir                                 case META_BMPSCALEPART_ACTION:
379*cdf0e10cSrcweir                                 case META_BMPEX_ACTION:
380*cdf0e10cSrcweir                                 case META_BMPEXSCALE_ACTION:
381*cdf0e10cSrcweir                                 case META_BMPEXSCALEPART_ACTION:
382*cdf0e10cSrcweir                                 case META_MASK_ACTION:
383*cdf0e10cSrcweir                                 case META_MASKSCALE_ACTION:
384*cdf0e10cSrcweir                                 case META_MASKSCALEPART_ACTION:
385*cdf0e10cSrcweir                                 case META_GRADIENTEX_ACTION:
386*cdf0e10cSrcweir                                 case META_WALLPAPER_ACTION:
387*cdf0e10cSrcweir                                 case META_TRANSPARENT_ACTION:
388*cdf0e10cSrcweir                                 case META_FLOATTRANSPARENT_ACTION:
389*cdf0e10cSrcweir                                 case META_TEXT_ACTION:
390*cdf0e10cSrcweir                                 case META_TEXTARRAY_ACTION:
391*cdf0e10cSrcweir                                 case META_TEXTLINE_ACTION:
392*cdf0e10cSrcweir                                 case META_TEXTRECT_ACTION:
393*cdf0e10cSrcweir                                 case META_STRETCHTEXT_ACTION:
394*cdf0e10cSrcweir                                 case META_RENDERGRAPHIC_ACTION:
395*cdf0e10cSrcweir                                     // output-generating action - only
396*cdf0e10cSrcweir                                     // copy, if we're within the
397*cdf0e10cSrcweir                                     // requested subset
398*cdf0e10cSrcweir                                     if( rSubset.mnSubsetBegin <= nCurrActionIndex &&
399*cdf0e10cSrcweir                                         rSubset.mnSubsetEnd > nCurrActionIndex )
400*cdf0e10cSrcweir                                     {
401*cdf0e10cSrcweir                                         aMtf.AddAction( pCurrAct->Clone() );
402*cdf0e10cSrcweir                                     }
403*cdf0e10cSrcweir                                     break;
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir                                 default:
406*cdf0e10cSrcweir                                     OSL_ENSURE( false,
407*cdf0e10cSrcweir                                                 "Unknown meta action type encountered" );
408*cdf0e10cSrcweir                                     break;
409*cdf0e10cSrcweir                             }
410*cdf0e10cSrcweir                         }
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir                         aVDev.DrawTransparent( aMtf,
413*cdf0e10cSrcweir                                                aEmptyPoint,
414*cdf0e10cSrcweir                                                aOutputSizePixel,
415*cdf0e10cSrcweir                                                *mpAlphaGradient );
416*cdf0e10cSrcweir                     }
417*cdf0e10cSrcweir                     else
418*cdf0e10cSrcweir                     {
419*cdf0e10cSrcweir                         // no subsetting - render whole mtf
420*cdf0e10cSrcweir                         aVDev.DrawTransparent( *mpGroupMtf,
421*cdf0e10cSrcweir                                                aEmptyPoint,
422*cdf0e10cSrcweir                                                aOutputSizePixel,
423*cdf0e10cSrcweir                                                *mpAlphaGradient );
424*cdf0e10cSrcweir                     }
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir                     // update buffered bitmap and transformation
428*cdf0e10cSrcweir                     BitmapSharedPtr aBmp( VCLFactory::getInstance().createBitmap(
429*cdf0e10cSrcweir                                               mpCanvas,
430*cdf0e10cSrcweir                                               aVDev.GetBitmapEx(
431*cdf0e10cSrcweir                                                   aEmptyPoint,
432*cdf0e10cSrcweir                                                   aBitmapSizePixel ) ) );
433*cdf0e10cSrcweir                     mxBufferBitmap = aBmp->getUNOBitmap();
434*cdf0e10cSrcweir                     maLastTransformation = aTotalTransform;
435*cdf0e10cSrcweir                     maLastSubset = rSubset;
436*cdf0e10cSrcweir                 }
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir                 // determine target transformation (we can't simply pass
439*cdf0e10cSrcweir                 // aTotalTransform as assembled above, since we must take
440*cdf0e10cSrcweir                 // the canvas' view state as is, it might contain clipping
441*cdf0e10cSrcweir                 // (which, in turn, is relative to the view
442*cdf0e10cSrcweir                 // transformation))
443*cdf0e10cSrcweir 
444*cdf0e10cSrcweir                 // given that aTotalTransform is the identity
445*cdf0e10cSrcweir                 // transformation, we could simply render our bitmap
446*cdf0e10cSrcweir                 // as-is. Now, since the mxBufferBitmap content already
447*cdf0e10cSrcweir                 // accounts for scale changes in the overall
448*cdf0e10cSrcweir                 // transformation, we must factor this out
449*cdf0e10cSrcweir                 // before. Generally, the transformation matrix should be
450*cdf0e10cSrcweir                 // structured like this:
451*cdf0e10cSrcweir                 // Translation*Rotation*Shear*Scale. Thus, to neutralize
452*cdf0e10cSrcweir                 // the contained scaling, we've got to right-multiply with
453*cdf0e10cSrcweir                 // the inverse.
454*cdf0e10cSrcweir                 ::basegfx::B2ISize aBmpSize(
455*cdf0e10cSrcweir                     ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBufferBitmap->getSize() ) );
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix aScaleCorrection;
458*cdf0e10cSrcweir                 aScaleCorrection.scale( (double)maDstSize.getX() / aBmpSize.getX(),
459*cdf0e10cSrcweir                                         (double)maDstSize.getY() / aBmpSize.getY() );
460*cdf0e10cSrcweir                 aTransform = aTransform * aScaleCorrection;
461*cdf0e10cSrcweir 
462*cdf0e10cSrcweir                 rendering::RenderState aLocalState( maState );
463*cdf0e10cSrcweir                 ::canvas::tools::setRenderStateTransform(aLocalState, aTransform);
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir #ifdef SPECIAL_DEBUG
466*cdf0e10cSrcweir                 aLocalState.Clip.clear();
467*cdf0e10cSrcweir                 aLocalState.DeviceColor =
468*cdf0e10cSrcweir                     ::vcl::unotools::colorToDoubleSequence(
469*cdf0e10cSrcweir                         ::Color( 0x80FF0000 ),
470*cdf0e10cSrcweir                         mpCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir                 if( maState.Clip.is() )
473*cdf0e10cSrcweir                     mpCanvas->getUNOCanvas()->fillPolyPolygon( maState.Clip,
474*cdf0e10cSrcweir                                                                mpCanvas->getViewState(),
475*cdf0e10cSrcweir                                                                aLocalState );
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir                 aLocalState.DeviceColor = maState.DeviceColor;
478*cdf0e10cSrcweir #endif
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir                 if( ::rtl::math::approxEqual(mnAlpha, 1.0) )
481*cdf0e10cSrcweir                 {
482*cdf0e10cSrcweir                     // no further alpha changes necessary -> draw directly
483*cdf0e10cSrcweir                     mpCanvas->getUNOCanvas()->drawBitmap( mxBufferBitmap,
484*cdf0e10cSrcweir                                                           mpCanvas->getViewState(),
485*cdf0e10cSrcweir                                                           aLocalState );
486*cdf0e10cSrcweir                 }
487*cdf0e10cSrcweir                 else
488*cdf0e10cSrcweir                 {
489*cdf0e10cSrcweir                     // add alpha modulation value to DeviceColor
490*cdf0e10cSrcweir                     uno::Sequence<rendering::ARGBColor> aCols(1);
491*cdf0e10cSrcweir                     aCols[0] = rendering::ARGBColor( mnAlpha, 1.0, 1.0, 1.0);
492*cdf0e10cSrcweir                     aLocalState.DeviceColor =
493*cdf0e10cSrcweir                         mpCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace()->convertFromARGB(
494*cdf0e10cSrcweir                             aCols);
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir                     mpCanvas->getUNOCanvas()->drawBitmapModulated( mxBufferBitmap,
497*cdf0e10cSrcweir                                                                    mpCanvas->getViewState(),
498*cdf0e10cSrcweir                                                                    aLocalState );
499*cdf0e10cSrcweir                 }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir                 return true;
502*cdf0e10cSrcweir             }
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir             // TODO(P3): The whole float transparency handling is a mess,
505*cdf0e10cSrcweir             // this should be refactored. What's more, the old idea of
506*cdf0e10cSrcweir             // having only internal 'metaactions', and not the original
507*cdf0e10cSrcweir             // GDIMetaFile now looks a lot less attractive. Try to move
508*cdf0e10cSrcweir             // into the direction of having a direct GDIMetaFile2XCanvas
509*cdf0e10cSrcweir             // renderer, and maybe a separate metafile XCanvas
510*cdf0e10cSrcweir             // implementation.
511*cdf0e10cSrcweir             bool TransparencyGroupAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
512*cdf0e10cSrcweir             {
513*cdf0e10cSrcweir                 Subset aSubset;
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir                 aSubset.mnSubsetBegin = 0;
516*cdf0e10cSrcweir                 aSubset.mnSubsetEnd   = -1;
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir                 return render( rTransformation, aSubset );
519*cdf0e10cSrcweir             }
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir             ::basegfx::B2DRange TransparencyGroupAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation ) const
522*cdf0e10cSrcweir             {
523*cdf0e10cSrcweir                 rendering::RenderState aLocalState( maState );
524*cdf0e10cSrcweir                 ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir                 return tools::calcDevicePixelBounds(
527*cdf0e10cSrcweir                     ::basegfx::B2DRange( 0,0,
528*cdf0e10cSrcweir                                          maDstSize.getX(),
529*cdf0e10cSrcweir                                          maDstSize.getY() ),
530*cdf0e10cSrcweir                     mpCanvas->getViewState(),
531*cdf0e10cSrcweir                     aLocalState );
532*cdf0e10cSrcweir             }
533*cdf0e10cSrcweir 
534*cdf0e10cSrcweir             ::basegfx::B2DRange TransparencyGroupAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
535*cdf0e10cSrcweir                                                                     const Subset&					rSubset ) const
536*cdf0e10cSrcweir             {
537*cdf0e10cSrcweir                 // TODO(F3): Currently, the bounds for
538*cdf0e10cSrcweir                 // TransparencyGroupAction subsets equal those of the
539*cdf0e10cSrcweir                 // full set, although this action is able to render
540*cdf0e10cSrcweir                 // true subsets.
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir                 // polygon only contains a single action, empty bounds
543*cdf0e10cSrcweir                 // if subset requests different range
544*cdf0e10cSrcweir                 if( rSubset.mnSubsetBegin != 0 ||
545*cdf0e10cSrcweir                     rSubset.mnSubsetEnd != 1 )
546*cdf0e10cSrcweir                     return ::basegfx::B2DRange();
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir                 return getBounds( rTransformation );
549*cdf0e10cSrcweir             }
550*cdf0e10cSrcweir 
551*cdf0e10cSrcweir             sal_Int32 TransparencyGroupAction::getActionCount() const
552*cdf0e10cSrcweir             {
553*cdf0e10cSrcweir                 return mpGroupMtf.get() ? mpGroupMtf->GetActionCount() : 0;
554*cdf0e10cSrcweir             }
555*cdf0e10cSrcweir 
556*cdf0e10cSrcweir         }
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir         ActionSharedPtr TransparencyGroupActionFactory::createTransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
559*cdf0e10cSrcweir                                                                                        const Renderer::Parameters&	rParms,
560*cdf0e10cSrcweir                                                                                        const ::basegfx::B2DPoint& 	rDstPoint,
561*cdf0e10cSrcweir                                                                                        const ::basegfx::B2DVector& 	rDstSize,
562*cdf0e10cSrcweir                                                                                        double 						nAlpha,
563*cdf0e10cSrcweir                                                                                        const CanvasSharedPtr&		rCanvas,
564*cdf0e10cSrcweir                                                                                        const OutDevState& 			rState )
565*cdf0e10cSrcweir         {
566*cdf0e10cSrcweir             return ActionSharedPtr( new TransparencyGroupAction(rGroupMtf,
567*cdf0e10cSrcweir                                                                 rParms,
568*cdf0e10cSrcweir                                                                 rDstPoint,
569*cdf0e10cSrcweir                                                                 rDstSize,
570*cdf0e10cSrcweir                                                                 nAlpha,
571*cdf0e10cSrcweir                                                                 rCanvas,
572*cdf0e10cSrcweir                                                                 rState ) );
573*cdf0e10cSrcweir         }
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir         ActionSharedPtr TransparencyGroupActionFactory::createTransparencyGroupAction( MtfAutoPtr&					rGroupMtf,
576*cdf0e10cSrcweir                                                                                        GradientAutoPtr&				rAlphaGradient,
577*cdf0e10cSrcweir                                                                                        const Renderer::Parameters&	rParms,
578*cdf0e10cSrcweir                                                                                        const ::basegfx::B2DPoint& 	rDstPoint,
579*cdf0e10cSrcweir                                                                                        const ::basegfx::B2DVector&  rDstSize,
580*cdf0e10cSrcweir                                                                                        const CanvasSharedPtr&		rCanvas,
581*cdf0e10cSrcweir                                                                                        const OutDevState& 			rState )
582*cdf0e10cSrcweir         {
583*cdf0e10cSrcweir             return ActionSharedPtr( new TransparencyGroupAction(rGroupMtf,
584*cdf0e10cSrcweir                                                                 rAlphaGradient,
585*cdf0e10cSrcweir                                                                 rParms,
586*cdf0e10cSrcweir                                                                 rDstPoint,
587*cdf0e10cSrcweir                                                                 rDstSize,
588*cdf0e10cSrcweir                                                                 rCanvas,
589*cdf0e10cSrcweir                                                                 rState ) );
590*cdf0e10cSrcweir         }
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir     }
593*cdf0e10cSrcweir }
594