xref: /AOO41X/main/canvas/source/cairo/cairo_spritehelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <canvas/debug.hxx>
32*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
33*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include <rtl/logfile.hxx>
36*cdf0e10cSrcweir #include <rtl/math.hxx>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
41*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
42*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
43*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
44*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
45*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
46*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
47*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontriangulator.hxx>
48*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir #include "cairo_canvascustomsprite.hxx"
51*cdf0e10cSrcweir #include "cairo_spritehelper.hxx"
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir #include <memory>
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir using namespace ::cairo;
57*cdf0e10cSrcweir using namespace ::com::sun::star;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir namespace cairocanvas
60*cdf0e10cSrcweir {
61*cdf0e10cSrcweir     SpriteHelper::SpriteHelper() :
62*cdf0e10cSrcweir         mpSpriteCanvas(),
63*cdf0e10cSrcweir         mpBufferSurface(),
64*cdf0e10cSrcweir         mbTextureDirty(true)
65*cdf0e10cSrcweir     {}
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir     void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
68*cdf0e10cSrcweir                              const SpriteCanvasRef&	     rSpriteCanvas )
69*cdf0e10cSrcweir     {
70*cdf0e10cSrcweir         ENSURE_OR_THROW( rSpriteCanvas.get(),
71*cdf0e10cSrcweir                           "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir         mpSpriteCanvas     = rSpriteCanvas;
74*cdf0e10cSrcweir         mbTextureDirty     = true;
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir         // also init base class
77*cdf0e10cSrcweir         CanvasCustomSpriteHelper::init( rSpriteSize,
78*cdf0e10cSrcweir                                         rSpriteCanvas.get() );
79*cdf0e10cSrcweir     }
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 	void SpriteHelper::setSurface( const SurfaceSharedPtr& pBufferSurface )
82*cdf0e10cSrcweir 	{
83*cdf0e10cSrcweir 		mpBufferSurface = pBufferSurface;
84*cdf0e10cSrcweir 	}
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     void SpriteHelper::disposing()
87*cdf0e10cSrcweir     {
88*cdf0e10cSrcweir         mpBufferSurface.reset();
89*cdf0e10cSrcweir         mpSpriteCanvas.clear();
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir         // forward to parent
92*cdf0e10cSrcweir         CanvasCustomSpriteHelper::disposing();
93*cdf0e10cSrcweir     }
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir     void SpriteHelper::redraw( const CairoSharedPtr&    pCairo,
96*cdf0e10cSrcweir                                const ::basegfx::B2DPoint& rPos,
97*cdf0e10cSrcweir                                bool&                      /*io_bSurfacesDirty*/,
98*cdf0e10cSrcweir                                bool                       /*bBufferedUpdate*/ ) const
99*cdf0e10cSrcweir     {
100*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE
101*cdf0e10cSrcweir         struct timespec aTimer;
102*cdf0e10cSrcweir         mxDevice->startPerfTrace( &aTimer );
103*cdf0e10cSrcweir #endif
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir         const double fAlpha( getAlpha() );
106*cdf0e10cSrcweir         const ::basegfx::B2DHomMatrix aTransform( getTransformation() );
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir         if( isActive() && !::basegfx::fTools::equalZero( fAlpha ) ) {
109*cdf0e10cSrcweir             OSL_TRACE ("CanvasCustomSprite::redraw called");
110*cdf0e10cSrcweir             if( pCairo ) {
111*cdf0e10cSrcweir                 basegfx::B2DVector aSize = getSizePixel();
112*cdf0e10cSrcweir                 cairo_save( pCairo.get() );
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir                 double fX, fY;
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir                 fX = rPos.getX();
117*cdf0e10cSrcweir                 fY = rPos.getY();
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir                 if( !aTransform.isIdentity() ) {
120*cdf0e10cSrcweir                     cairo_matrix_t aMatrix, aInverseMatrix;
121*cdf0e10cSrcweir                     cairo_matrix_init( &aMatrix,
122*cdf0e10cSrcweir                                        aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ),
123*cdf0e10cSrcweir                                        aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) );
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir                     aMatrix.x0 = basegfx::fround( aMatrix.x0 );
126*cdf0e10cSrcweir                     aMatrix.y0 = basegfx::fround( aMatrix.y0 );
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir                     cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 );
129*cdf0e10cSrcweir                     cairo_matrix_invert( &aInverseMatrix );
130*cdf0e10cSrcweir                     cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY );
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir                     cairo_set_matrix( pCairo.get(), &aMatrix );
133*cdf0e10cSrcweir                 }
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir                 fX = basegfx::fround( fX );
136*cdf0e10cSrcweir                 fY = basegfx::fround( fY );
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir                 cairo_matrix_t aOrigMatrix;
139*cdf0e10cSrcweir                 cairo_get_matrix( pCairo.get(), &aOrigMatrix );
140*cdf0e10cSrcweir                 cairo_translate( pCairo.get(), fX, fY );
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir                 if( getClip().is() )
143*cdf0e10cSrcweir                 {
144*cdf0e10cSrcweir                     const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() );
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir                     ::basegfx::B2DPolyPolygon aClipPoly(
147*cdf0e10cSrcweir                         ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
148*cdf0e10cSrcweir                             rClip ));
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir                     doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(),
151*cdf0e10cSrcweir                                                  NULL, SurfaceProviderRef(mpSpriteCanvas.get()),
152*cdf0e10cSrcweir                                                  rClip->getFillRule() );
153*cdf0e10cSrcweir                 }
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir                 OSL_TRACE ("aSize %f x %f position: %f,%f", aSize.getX(), aSize.getY(), fX, fY );
156*cdf0e10cSrcweir                 cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) );
157*cdf0e10cSrcweir                 cairo_clip( pCairo.get() );
158*cdf0e10cSrcweir                 cairo_set_matrix( pCairo.get(), &aOrigMatrix );
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir                 if( isContentFullyOpaque() )
161*cdf0e10cSrcweir                     cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
162*cdf0e10cSrcweir                 cairo_set_source_surface( pCairo.get(),
163*cdf0e10cSrcweir                                           mpBufferSurface->getCairoSurface().get(),
164*cdf0e10cSrcweir                                           fX, fY );
165*cdf0e10cSrcweir                 if( ::rtl::math::approxEqual( fAlpha, 1.0 ) )
166*cdf0e10cSrcweir                     cairo_paint( pCairo.get() );
167*cdf0e10cSrcweir                 else
168*cdf0e10cSrcweir                     cairo_paint_with_alpha( pCairo.get(), fAlpha );
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir                 cairo_restore( pCairo.get() );
171*cdf0e10cSrcweir             }
172*cdf0e10cSrcweir         }
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE
175*cdf0e10cSrcweir         mxDevice->stopPerfTrace( &aTimer, "sprite redraw" );
176*cdf0e10cSrcweir #endif
177*cdf0e10cSrcweir     }
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir     ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
180*cdf0e10cSrcweir     {
181*cdf0e10cSrcweir         return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPoly);
182*cdf0e10cSrcweir     }
183*cdf0e10cSrcweir }
184