/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include "ogl_canvascustomsprite.hxx" #include "ogl_canvastools.hxx" #include "ogl_tools.hxx" using namespace ::com::sun::star; namespace oglcanvas { CanvasCustomSprite::CanvasCustomSprite( const css::geometry::RealSize2D& rSpriteSize, const SpriteCanvasRef& rRefDevice, SpriteDeviceHelper& rDeviceHelper ) : mpSpriteCanvas( rRefDevice ), maSize(rSpriteSize), mfAlpha(0.0), mfPriority(0.0) { ENSURE_OR_THROW( rRefDevice, "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" ); ::canvas::tools::setIdentityAffineMatrix2D(maTransformation); maCanvasHelper.init( *rRefDevice, rDeviceHelper ); } void CanvasCustomSprite::disposeThis() { ::osl::MutexGuard aGuard( m_aMutex ); mpSpriteCanvas.clear(); // forward to parent CanvasCustomSpriteBaseT::disposeThis(); } void SAL_CALL CanvasCustomSprite::setAlpha( double alpha ) { canvas::tools::verifyRange( alpha, 0.0, 1.0 ); ::osl::MutexGuard aGuard( m_aMutex ); mfAlpha = alpha; } void SAL_CALL CanvasCustomSprite::move( const geometry::RealPoint2D& aNewPos, const rendering::ViewState& viewState, const rendering::RenderState& renderState ) { canvas::tools::verifyArgs(aNewPos, viewState, renderState, __func__, static_cast< ::cppu::OWeakObject* >(this)); ::osl::MutexGuard aGuard( m_aMutex ); ::basegfx::B2DHomMatrix aTransform; ::canvas::tools::mergeViewAndRenderTransform(aTransform, viewState, renderState); // convert position to device pixel maPosition = ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos); maPosition *= aTransform; } void SAL_CALL CanvasCustomSprite::transform( const geometry::AffineMatrix2D& aTransformation ) { ::osl::MutexGuard aGuard( m_aMutex ); maTransformation = aTransformation; } void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip ) { mxClip = xClip; } void SAL_CALL CanvasCustomSprite::setPriority( double nPriority ) { ::osl::MutexGuard aGuard( m_aMutex ); mfPriority = nPriority; } void SAL_CALL CanvasCustomSprite::show() { ::osl::MutexGuard aGuard( m_aMutex ); if( mpSpriteCanvas.is() ) mpSpriteCanvas->show(this); } void SAL_CALL CanvasCustomSprite::hide() { ::osl::MutexGuard aGuard( m_aMutex ); if( mpSpriteCanvas.is() ) mpSpriteCanvas->hide(this); } uno::Reference< rendering::XCanvas > SAL_CALL CanvasCustomSprite::getContentCanvas() { return this; } bool CanvasCustomSprite::renderSprite() const { if( ::basegfx::fTools::equalZero( mfAlpha ) ) return true; TransformationPreserver aPreserver1; const ::basegfx::B2IVector aSpriteSizePixel( ::canvas::tools::roundUp( maSize.Width ), ::canvas::tools::roundUp( maSize.Height )); // translate sprite to output position glTranslated(maPosition.getX(), maPosition.getY(), 0); { TransformationPreserver aPreserver2; // apply sprite content transformation matrix double aGLTransform[] = { maTransformation.m00, maTransformation.m10, 0, 0, maTransformation.m01, maTransformation.m11, 0, 0, 0, 0, 1, 0, maTransformation.m02, maTransformation.m12, 0, 1 }; glMultMatrixd(aGLTransform); IBufferContextSharedPtr pBufferContext; if( mfAlpha != 1.0 || mxClip.is() ) { // drafts. Need to render to temp surface before, and then // composite that to screen // TODO(P3): buffer texture pBufferContext = maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel); pBufferContext->startBufferRendering(); } // this ends up in pBufferContext, if that one's "current" if( !maCanvasHelper.renderRecordedActions() ) return false; if( pBufferContext ) { // content ended up in background buffer - compose to // screen now. Calls below switches us back to window // context, and binds to generated, dynamic texture pBufferContext->endBufferRendering(); GLuint nTexture = pBufferContext->getTextureId(); glBindTexture(GL_TEXTURE_2D, nTexture); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blend against fixed vertex color; texture alpha is multiplied in glColor4f(1,1,1,mfAlpha); if( mxClip.is() ) { const double fWidth=maSize.Width; const double fHeight=maSize.Height; // TODO(P3): buffer triangulation const ::basegfx::triangulator::B2DTriangleVector rTriangulatedPolygon( ::basegfx::triangulator::triangulate( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip))); glBegin(GL_TRIANGLES); for( size_t i=0; i aVec { mfAlpha, mfPriority, o3tl::narrowing(maCanvasHelper.getRecordedActionCount()) }; renderOSD( aVec, 10 ); return true; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */