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