xref: /AOO41X/main/canvas/source/directx/dx_spritehelper.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_canvas.hxx"
26 
27 #include <ctype.h> // don't ask. msdev breaks otherwise...
28 #include <canvas/debug.hxx>
29 #include <canvas/verbosetrace.hxx>
30 #include <tools/diagnose_ex.h>
31 
32 #include <rtl/logfile.hxx>
33 #include <rtl/math.hxx>
34 
35 #include <canvas/canvastools.hxx>
36 
37 #include <basegfx/matrix/b2dhommatrix.hxx>
38 #include <basegfx/point/b2dpoint.hxx>
39 #include <basegfx/tools/canvastools.hxx>
40 #include <basegfx/numeric/ftools.hxx>
41 #include <basegfx/polygon/b2dpolypolygontools.hxx>
42 #include <basegfx/polygon/b2dpolygontools.hxx>
43 #include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
44 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
45 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
46 
47 #include "dx_canvascustomsprite.hxx"
48 #include "dx_spritehelper.hxx"
49 #include "dx_impltools.hxx"
50 
51 #include <memory>
52 
53 using namespace ::com::sun::star;
54 
55 namespace dxcanvas
56 {
SpriteHelper()57     SpriteHelper::SpriteHelper() :
58         mpSpriteCanvas(),
59         mpBitmap(),
60         mbTextureDirty( true ),
61         mbShowSpriteBounds( false )
62     {
63     }
64 
init(const geometry::RealSize2D & rSpriteSize,const SpriteCanvasRef & rSpriteCanvas,const IDXRenderModuleSharedPtr & rRenderModule,const DXSurfaceBitmapSharedPtr rBitmap,bool bShowSpriteBounds)65     void SpriteHelper::init( const geometry::RealSize2D&     rSpriteSize,
66                              const SpriteCanvasRef&          rSpriteCanvas,
67                              const IDXRenderModuleSharedPtr& rRenderModule,
68                              const DXSurfaceBitmapSharedPtr  rBitmap,
69                              bool                            bShowSpriteBounds )
70     {
71         ENSURE_OR_THROW( rSpriteCanvas.get() &&
72                           rRenderModule &&
73                           rBitmap,
74                           "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
75 
76         mpSpriteCanvas     = rSpriteCanvas;
77         mpBitmap           = rBitmap;
78         mbTextureDirty     = true;
79         mbShowSpriteBounds = bShowSpriteBounds;
80 
81         // also init base class
82         CanvasCustomSpriteHelper::init( rSpriteSize,
83                                         rSpriteCanvas.get() );
84     }
85 
disposing()86     void SpriteHelper::disposing()
87     {
88         mpBitmap.reset();
89         mpSpriteCanvas.clear();
90 
91         // forward to parent
92         CanvasCustomSpriteHelper::disposing();
93     }
94 
polyPolygonFromXPolyPolygon2D(uno::Reference<rendering::XPolyPolygon2D> & xPoly) const95     ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
96     {
97         return tools::polyPolygonFromXPolyPolygon2D( xPoly );
98     }
99 
needRedraw() const100     bool SpriteHelper::needRedraw() const
101     {
102         if( !mpBitmap ||
103             !mpSpriteCanvas.get() )
104         {
105             return false; // we're disposed, no redraw necessary
106         }
107 
108         if( !isActive() ||
109             ::basegfx::fTools::equalZero( getAlpha() ) )
110         {
111             return false; // sprite is invisible
112         }
113 
114         return true;
115     }
116 
redraw(bool & io_bSurfaceDirty) const117     void SpriteHelper::redraw( bool& io_bSurfaceDirty ) const
118     {
119         if( !mpBitmap ||
120             !mpSpriteCanvas.get() )
121         {
122             return; // we're disposed
123         }
124 
125         const ::basegfx::B2DPoint& rPos( getPosPixel() );
126         const double               fAlpha( getAlpha() );
127 
128         if( isActive() &&
129             !::basegfx::fTools::equalZero( fAlpha ) )
130         {
131 
132             // TODO(Q2): For the time being, Device does not take a target
133             // surface, but always unconditionally renders to the
134             // background buffer.
135 
136             // log output pos in device pixel
137             VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
138                            rPos.getX(),
139                            rPos.getY() );
140 
141             const double                                       fAlpha( getAlpha() );
142             const ::basegfx::B2DVector&                        rSize( getSizePixel() );
143             const ::basegfx::B2DHomMatrix&                     rTransform( getTransformation() );
144             const uno::Reference< rendering::XPolyPolygon2D >& xClip( getClip() );
145 
146             mbTextureDirty   = false;
147             io_bSurfaceDirty = false; // state taken, and processed.
148 
149             ::basegfx::B2DPolyPolygon   aClipPath; // empty for no clip
150             bool                        bIsClipRectangular( false ); // false, if no
151                                                                     // clip, or clip
152                                                                     // is complex
153 
154             // setup and apply clip (if any)
155             // =================================
156 
157             if( xClip.is() )
158             {
159                 aClipPath = tools::polyPolygonFromXPolyPolygon2D( xClip );
160 
161                 const sal_Int32 nNumClipPolygons( aClipPath.count() );
162                 if( nNumClipPolygons )
163                 {
164                     // TODO(P2): hold rectangle attribute directly
165                     // at the XPolyPolygon2D
166 
167                     // check whether the clip is rectangular
168                     if( nNumClipPolygons == 1 )
169                         if( ::basegfx::tools::isRectangle( aClipPath.getB2DPolygon( 0 ) ) )
170                             bIsClipRectangular = true;
171                 }
172             }
173 
174             const ::basegfx::B2DRectangle aSourceRect( 0.0,
175                                                        0.0,
176                                                        rSize.getX(),
177                                                        rSize.getY() );
178 
179             // draw simple rectangular area if no clip is set.
180             if( !aClipPath.count() )
181             {
182                 mpBitmap->draw(fAlpha,rPos,rTransform);
183             }
184             else if( bIsClipRectangular )
185             {
186                 // apply a simple rect clip
187                 // ========================
188 
189                 ::basegfx::B2DRectangle aClipBounds(
190                     ::basegfx::tools::getRange( aClipPath ) );
191                 aClipBounds.intersect( aSourceRect );
192 
193                 mpBitmap->draw(fAlpha,rPos,aClipBounds,rTransform);
194             }
195             else
196             {
197                 // apply clip the hard way
198                 // =======================
199 
200                 mpBitmap->draw(fAlpha,rPos,aClipPath,rTransform);
201             }
202 
203             if( mbShowSpriteBounds )
204             {
205                 if( aClipPath.count() )
206                 {
207                     // TODO(F2): Re-enable debug output
208                 }
209             }
210         }
211     }
212 }
213