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