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
10*25ea7f45SAndrew Rist  *
11*25ea7f45SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*25ea7f45SAndrew Rist  *
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.
19*25ea7f45SAndrew Rist  *
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