xref: /trunk/main/canvas/source/directx/dx_spritehelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
30 
31 #include <ctype.h> // don't ask. msdev breaks otherwise...
32 #include <canvas/debug.hxx>
33 #include <canvas/verbosetrace.hxx>
34 #include <tools/diagnose_ex.h>
35 
36 #include <rtl/logfile.hxx>
37 #include <rtl/math.hxx>
38 
39 #include <canvas/canvastools.hxx>
40 
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <basegfx/point/b2dpoint.hxx>
43 #include <basegfx/tools/canvastools.hxx>
44 #include <basegfx/numeric/ftools.hxx>
45 #include <basegfx/polygon/b2dpolypolygontools.hxx>
46 #include <basegfx/polygon/b2dpolygontools.hxx>
47 #include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
48 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
49 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
50 
51 #include "dx_canvascustomsprite.hxx"
52 #include "dx_spritehelper.hxx"
53 #include "dx_impltools.hxx"
54 
55 #include <memory>
56 
57 using namespace ::com::sun::star;
58 
59 namespace dxcanvas
60 {
61     SpriteHelper::SpriteHelper() :
62         mpSpriteCanvas(),
63         mpBitmap(),
64         mbTextureDirty( true ),
65         mbShowSpriteBounds( false )
66     {
67     }
68 
69     void SpriteHelper::init( const geometry::RealSize2D&     rSpriteSize,
70                              const SpriteCanvasRef&          rSpriteCanvas,
71                              const IDXRenderModuleSharedPtr& rRenderModule,
72                              const DXSurfaceBitmapSharedPtr  rBitmap,
73                              bool                            bShowSpriteBounds )
74     {
75         ENSURE_OR_THROW( rSpriteCanvas.get() &&
76                           rRenderModule &&
77                           rBitmap,
78                           "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
79 
80         mpSpriteCanvas     = rSpriteCanvas;
81         mpBitmap           = rBitmap;
82         mbTextureDirty     = true;
83         mbShowSpriteBounds = bShowSpriteBounds;
84 
85         // also init base class
86         CanvasCustomSpriteHelper::init( rSpriteSize,
87                                         rSpriteCanvas.get() );
88     }
89 
90     void SpriteHelper::disposing()
91     {
92         mpBitmap.reset();
93         mpSpriteCanvas.clear();
94 
95         // forward to parent
96         CanvasCustomSpriteHelper::disposing();
97     }
98 
99     ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
100     {
101         return tools::polyPolygonFromXPolyPolygon2D( xPoly );
102     }
103 
104     bool SpriteHelper::needRedraw() const
105     {
106         if( !mpBitmap ||
107             !mpSpriteCanvas.get() )
108         {
109             return false; // we're disposed, no redraw necessary
110         }
111 
112         if( !isActive() ||
113             ::basegfx::fTools::equalZero( getAlpha() ) )
114         {
115             return false; // sprite is invisible
116         }
117 
118         return true;
119     }
120 
121     void SpriteHelper::redraw( bool& io_bSurfaceDirty ) const
122     {
123         if( !mpBitmap ||
124             !mpSpriteCanvas.get() )
125         {
126             return; // we're disposed
127         }
128 
129         const ::basegfx::B2DPoint& rPos( getPosPixel() );
130         const double               fAlpha( getAlpha() );
131 
132         if( isActive() &&
133             !::basegfx::fTools::equalZero( fAlpha ) )
134         {
135 
136             // TODO(Q2): For the time being, Device does not take a target
137             // surface, but always unconditionally renders to the
138             // background buffer.
139 
140             // log output pos in device pixel
141             VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
142                            rPos.getX(),
143                            rPos.getY() );
144 
145             const double                                       fAlpha( getAlpha() );
146             const ::basegfx::B2DVector&                        rSize( getSizePixel() );
147             const ::basegfx::B2DHomMatrix&                     rTransform( getTransformation() );
148             const uno::Reference< rendering::XPolyPolygon2D >& xClip( getClip() );
149 
150             mbTextureDirty   = false;
151             io_bSurfaceDirty = false; // state taken, and processed.
152 
153             ::basegfx::B2DPolyPolygon   aClipPath; // empty for no clip
154             bool                        bIsClipRectangular( false ); // false, if no
155                                                                     // clip, or clip
156                                                                     // is complex
157 
158             // setup and apply clip (if any)
159             // =================================
160 
161             if( xClip.is() )
162             {
163                 aClipPath = tools::polyPolygonFromXPolyPolygon2D( xClip );
164 
165                 const sal_Int32 nNumClipPolygons( aClipPath.count() );
166                 if( nNumClipPolygons )
167                 {
168                     // TODO(P2): hold rectangle attribute directly
169                     // at the XPolyPolygon2D
170 
171                     // check whether the clip is rectangular
172                     if( nNumClipPolygons == 1 )
173                         if( ::basegfx::tools::isRectangle( aClipPath.getB2DPolygon( 0 ) ) )
174                             bIsClipRectangular = true;
175                 }
176             }
177 
178             const ::basegfx::B2DRectangle aSourceRect( 0.0,
179                                                        0.0,
180                                                        rSize.getX(),
181                                                        rSize.getY() );
182 
183             // draw simple rectangular area if no clip is set.
184             if( !aClipPath.count() )
185             {
186                 mpBitmap->draw(fAlpha,rPos,rTransform);
187             }
188             else if( bIsClipRectangular )
189             {
190                 // apply a simple rect clip
191                 // ========================
192 
193                 ::basegfx::B2DRectangle aClipBounds(
194                     ::basegfx::tools::getRange( aClipPath ) );
195                 aClipBounds.intersect( aSourceRect );
196 
197                 mpBitmap->draw(fAlpha,rPos,aClipBounds,rTransform);
198             }
199             else
200             {
201                 // apply clip the hard way
202                 // =======================
203 
204                 mpBitmap->draw(fAlpha,rPos,aClipPath,rTransform);
205             }
206 
207             if( mbShowSpriteBounds )
208             {
209                 if( aClipPath.count() )
210                 {
211                     // TODO(F2): Re-enable debug output
212                 }
213             }
214         }
215     }
216 }
217