Branch libreoffice-5-0-4
[LibreOffice.git] / canvas / source / opengl / ogl_canvascustomsprite.cxx
blobf088180c98cd98ebe79660c910568df051e71c5b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "ogl_canvascustomsprite.hxx"
11 #include "ogl_canvastools.hxx"
12 #include "ogl_tools.hxx"
14 #include <canvas/debug.hxx>
15 #include <canvas/verbosetrace.hxx>
16 #include <canvas/verifyinput.hxx>
17 #include <tools/diagnose_ex.h>
19 #include <canvas/canvastools.hxx>
21 #include <basegfx/matrix/b2dhommatrix.hxx>
22 #include <basegfx/point/b2dpoint.hxx>
23 #include <basegfx/tools/canvastools.hxx>
24 #include <basegfx/polygon/b2dpolygonclipper.hxx>
25 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
26 #include <basegfx/polygon/b2dpolypolygontools.hxx>
28 #include <GL/glew.h>
30 using namespace ::com::sun::star;
32 namespace oglcanvas
34 CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
35 const SpriteCanvasRef& rRefDevice,
36 SpriteDeviceHelper& rDeviceHelper ) :
37 mpSpriteCanvas( rRefDevice ),
38 maSize(rSpriteSize),
39 mxClip(),
40 maTransformation(),
41 maPosition(),
42 mfAlpha(0.0),
43 mfPriority(0.0)
45 ENSURE_OR_THROW( rRefDevice.get(),
46 "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
48 ::canvas::tools::setIdentityAffineMatrix2D(maTransformation);
49 maCanvasHelper.init( *rRefDevice.get(),
50 rDeviceHelper );
53 void CanvasCustomSprite::disposeThis()
55 ::osl::MutexGuard aGuard( m_aMutex );
57 mpSpriteCanvas.clear();
59 // forward to parent
60 CanvasCustomSpriteBaseT::disposeThis();
63 void SAL_CALL CanvasCustomSprite::setAlpha( double alpha ) throw (lang::IllegalArgumentException,
64 uno::RuntimeException, std::exception)
66 canvas::tools::verifyRange( alpha, 0.0, 1.0 );
68 ::osl::MutexGuard aGuard( m_aMutex );
69 mfAlpha = alpha;
72 void SAL_CALL CanvasCustomSprite::move( const geometry::RealPoint2D& aNewPos,
73 const rendering::ViewState& viewState,
74 const rendering::RenderState& renderState ) throw (lang::IllegalArgumentException,
75 uno::RuntimeException, std::exception)
77 canvas::tools::verifyArgs(aNewPos, viewState, renderState,
78 BOOST_CURRENT_FUNCTION,
79 static_cast< ::cppu::OWeakObject* >(this));
81 ::osl::MutexGuard aGuard( m_aMutex );
82 ::basegfx::B2DHomMatrix aTransform;
83 ::canvas::tools::mergeViewAndRenderTransform(aTransform,
84 viewState,
85 renderState);
87 // convert position to device pixel
88 maPosition = ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos);
89 maPosition *= aTransform;
92 void SAL_CALL CanvasCustomSprite::transform( const geometry::AffineMatrix2D& aTransformation ) throw (lang::IllegalArgumentException,
93 uno::RuntimeException, std::exception)
95 ::osl::MutexGuard aGuard( m_aMutex );
96 maTransformation = aTransformation;
99 void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip ) throw (uno::RuntimeException, std::exception)
101 mxClip = xClip;
104 void SAL_CALL CanvasCustomSprite::setPriority( double nPriority ) throw (uno::RuntimeException, std::exception)
106 ::osl::MutexGuard aGuard( m_aMutex );
107 mfPriority = nPriority;
110 void SAL_CALL CanvasCustomSprite::show() throw (uno::RuntimeException, std::exception)
112 ::osl::MutexGuard aGuard( m_aMutex );
113 if( mpSpriteCanvas.is() )
114 mpSpriteCanvas->show(this);
117 void SAL_CALL CanvasCustomSprite::hide() throw (uno::RuntimeException, std::exception)
119 ::osl::MutexGuard aGuard( m_aMutex );
120 if( mpSpriteCanvas.is() )
121 mpSpriteCanvas->hide(this);
124 uno::Reference< rendering::XCanvas > SAL_CALL CanvasCustomSprite::getContentCanvas() throw (uno::RuntimeException, std::exception)
126 return this;
129 bool CanvasCustomSprite::renderSprite() const
131 if( ::basegfx::fTools::equalZero( mfAlpha ) )
132 return true;
134 TransformationPreserver aPreserver1;
135 const ::basegfx::B2IVector aSpriteSizePixel(
136 ::canvas::tools::roundUp( maSize.Width ),
137 ::canvas::tools::roundUp( maSize.Height ));
139 // translate sprite to output position
140 glTranslated(maPosition.getX(), maPosition.getY(), 0);
143 TransformationPreserver aPreserver2;
145 // apply sprite content transformation matrix
146 double aGLTransform[] =
148 maTransformation.m00, maTransformation.m10, 0, 0,
149 maTransformation.m01, maTransformation.m11, 0, 0,
150 0, 0, 1, 0,
151 maTransformation.m02, maTransformation.m12, 0, 1
153 glMultMatrixd(aGLTransform);
155 IBufferContextSharedPtr pBufferContext;
156 if( mfAlpha != 1.0 || mxClip.is() )
158 // drats. need to render to temp surface before, and then
159 // composite that to screen
161 // TODO(P3): buffer texture
162 pBufferContext = maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel);
163 pBufferContext->startBufferRendering();
166 // this ends up in pBufferContext, if that one's "current"
167 if( !maCanvasHelper.renderRecordedActions() )
168 return false;
170 if( pBufferContext )
172 // content ended up in background buffer - compose to
173 // screen now. Calls below switches us back to window
174 // context, and binds to generated, dynamic texture
175 pBufferContext->endBufferRendering();
176 GLuint nTexture = pBufferContext->getTextureId();
177 glBindTexture(GL_TEXTURE_2D, nTexture);
179 glEnable(GL_TEXTURE_2D);
180 glTexParameteri(GL_TEXTURE_2D,
181 GL_TEXTURE_MIN_FILTER,
182 GL_NEAREST);
183 glTexParameteri(GL_TEXTURE_2D,
184 GL_TEXTURE_MAG_FILTER,
185 GL_NEAREST);
186 glEnable(GL_BLEND);
187 glBlendFunc(GL_SRC_ALPHA,
188 GL_ONE_MINUS_SRC_ALPHA);
190 // blend against fixed vertex color; texture alpha is multiplied in
191 glColor4f(1,1,1,mfAlpha);
193 if( mxClip.is() )
195 const double fWidth=maSize.Width;
196 const double fHeight=maSize.Height;
198 // TODO(P3): buffer triangulation
199 const ::basegfx::B2DPolygon& rTriangulatedPolygon(
200 ::basegfx::triangulator::triangulate(
201 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip)));
203 basegfx::B2DPolygon rTriangleList(
204 basegfx::tools::clipTriangleListOnRange(
205 rTriangulatedPolygon,
206 basegfx::B2DRange(
207 0,0,
208 aSpriteSizePixel.getX(),
209 aSpriteSizePixel.getY())));
211 glBegin(GL_TRIANGLES);
212 for( sal_uInt32 i=0; i<rTriangulatedPolygon.count(); i++ )
214 const ::basegfx::B2DPoint& rPt( rTriangulatedPolygon.getB2DPoint(i) );
215 const double s(rPt.getX()/fWidth);
216 const double t(rPt.getY()/fHeight);
217 glTexCoord2f(s,t); glVertex2d(rPt.getX(), rPt.getY());
219 glEnd();
221 else
223 const double fWidth=maSize.Width/aSpriteSizePixel.getX();
224 const double fHeight=maSize.Height/aSpriteSizePixel.getY();
226 glBegin(GL_TRIANGLE_STRIP);
227 glTexCoord2f(0,0); glVertex2d(0,0);
228 glTexCoord2f(0,fHeight); glVertex2d(0, aSpriteSizePixel.getY());
229 glTexCoord2f(fWidth,0); glVertex2d(aSpriteSizePixel.getX(),0);
230 glTexCoord2f(fWidth,fHeight); glVertex2d(aSpriteSizePixel.getX(),aSpriteSizePixel.getY());
231 glEnd();
234 glBindTexture(GL_TEXTURE_2D, 0);
235 glDisable(GL_TEXTURE_2D);
239 glColor4f(1,0,0,1);
240 glBegin(GL_LINE_STRIP);
241 glVertex2d(-2,-2);
242 glVertex2d(-2,maSize.Height+4);
243 glVertex2d(maSize.Width+4,maSize.Height+4);
244 glVertex2d(maSize.Width+4,-2);
245 glVertex2d(-2,-2);
246 glVertex2d(maSize.Width+4,maSize.Height+4);
247 glEnd();
249 std::vector<double> aVec;
250 aVec.push_back(mfAlpha);
251 aVec.push_back(mfPriority);
252 aVec.push_back(maCanvasHelper.getRecordedActionCount());
253 renderOSD( aVec, 10 );
255 return true;
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */