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