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 <canvas/debug.hxx> 28 #include <canvas/verbosetrace.hxx> 29 #include <tools/diagnose_ex.h> 30 31 #include <rtl/logfile.hxx> 32 #include <rtl/math.hxx> 33 34 #include <canvas/canvastools.hxx> 35 36 #include <basegfx/matrix/b2dhommatrix.hxx> 37 #include <basegfx/point/b2dpoint.hxx> 38 #include <basegfx/tools/canvastools.hxx> 39 #include <basegfx/numeric/ftools.hxx> 40 #include <basegfx/polygon/b2dpolypolygontools.hxx> 41 #include <basegfx/polygon/b2dpolygontools.hxx> 42 #include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx> 43 #include <basegfx/polygon/b2dpolygontriangulator.hxx> 44 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx> 45 46 #include "cairo_canvascustomsprite.hxx" 47 #include "cairo_spritehelper.hxx" 48 49 #include <memory> 50 51 52 using namespace ::cairo; 53 using namespace ::com::sun::star; 54 55 namespace cairocanvas 56 { SpriteHelper()57 SpriteHelper::SpriteHelper() : 58 mpSpriteCanvas(), 59 mpBufferSurface(), 60 mbTextureDirty(true) 61 {} 62 init(const geometry::RealSize2D & rSpriteSize,const SpriteCanvasRef & rSpriteCanvas)63 void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize, 64 const SpriteCanvasRef& rSpriteCanvas ) 65 { 66 ENSURE_OR_THROW( rSpriteCanvas.get(), 67 "SpriteHelper::init(): Invalid device, sprite canvas or surface" ); 68 69 mpSpriteCanvas = rSpriteCanvas; 70 mbTextureDirty = true; 71 72 // also init base class 73 CanvasCustomSpriteHelper::init( rSpriteSize, 74 rSpriteCanvas.get() ); 75 } 76 setSurface(const SurfaceSharedPtr & pBufferSurface)77 void SpriteHelper::setSurface( const SurfaceSharedPtr& pBufferSurface ) 78 { 79 mpBufferSurface = pBufferSurface; 80 } 81 disposing()82 void SpriteHelper::disposing() 83 { 84 mpBufferSurface.reset(); 85 mpSpriteCanvas.clear(); 86 87 // forward to parent 88 CanvasCustomSpriteHelper::disposing(); 89 } 90 redraw(const CairoSharedPtr & pCairo,const::basegfx::B2DPoint & rPos,bool &,bool) const91 void SpriteHelper::redraw( const CairoSharedPtr& pCairo, 92 const ::basegfx::B2DPoint& rPos, 93 bool& /*io_bSurfacesDirty*/, 94 bool /*bBufferedUpdate*/ ) const 95 { 96 #ifdef CAIRO_CANVAS_PERF_TRACE 97 struct timespec aTimer; 98 mxDevice->startPerfTrace( &aTimer ); 99 #endif 100 101 const double fAlpha( getAlpha() ); 102 const ::basegfx::B2DHomMatrix aTransform( getTransformation() ); 103 104 if( isActive() && !::basegfx::fTools::equalZero( fAlpha ) ) { 105 OSL_TRACE ("CanvasCustomSprite::redraw called"); 106 if( pCairo ) { 107 basegfx::B2DVector aSize = getSizePixel(); 108 cairo_save( pCairo.get() ); 109 110 double fX, fY; 111 112 fX = rPos.getX(); 113 fY = rPos.getY(); 114 115 if( !aTransform.isIdentity() ) { 116 cairo_matrix_t aMatrix, aInverseMatrix; 117 cairo_matrix_init( &aMatrix, 118 aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ), 119 aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) ); 120 121 aMatrix.x0 = basegfx::fround( aMatrix.x0 ); 122 aMatrix.y0 = basegfx::fround( aMatrix.y0 ); 123 124 cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 ); 125 cairo_matrix_invert( &aInverseMatrix ); 126 cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY ); 127 128 cairo_set_matrix( pCairo.get(), &aMatrix ); 129 } 130 131 fX = basegfx::fround( fX ); 132 fY = basegfx::fround( fY ); 133 134 cairo_matrix_t aOrigMatrix; 135 cairo_get_matrix( pCairo.get(), &aOrigMatrix ); 136 cairo_translate( pCairo.get(), fX, fY ); 137 138 if( getClip().is() ) 139 { 140 const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() ); 141 142 ::basegfx::B2DPolyPolygon aClipPoly( 143 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( 144 rClip )); 145 146 doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(), 147 NULL, SurfaceProviderRef(mpSpriteCanvas.get()), 148 rClip->getFillRule() ); 149 } 150 151 OSL_TRACE ("aSize %f x %f position: %f,%f", aSize.getX(), aSize.getY(), fX, fY ); 152 cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) ); 153 cairo_clip( pCairo.get() ); 154 cairo_set_matrix( pCairo.get(), &aOrigMatrix ); 155 156 if( isContentFullyOpaque() ) 157 cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE ); 158 cairo_set_source_surface( pCairo.get(), 159 mpBufferSurface->getCairoSurface().get(), 160 fX, fY ); 161 if( ::rtl::math::approxEqual( fAlpha, 1.0 ) ) 162 cairo_paint( pCairo.get() ); 163 else 164 cairo_paint_with_alpha( pCairo.get(), fAlpha ); 165 166 cairo_restore( pCairo.get() ); 167 } 168 } 169 170 #ifdef CAIRO_CANVAS_PERF_TRACE 171 mxDevice->stopPerfTrace( &aTimer, "sprite redraw" ); 172 #endif 173 } 174 polyPolygonFromXPolyPolygon2D(uno::Reference<rendering::XPolyPolygon2D> & xPoly) const175 ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const 176 { 177 return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPoly); 178 } 179 } 180