LibreOffice Module canvas (master) 1
ogl_canvascustomsprite.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <sal/config.h>
11
12#include <epoxy/gl.h>
13
20#include <o3tl/safeint.hxx>
21#include <verifyinput.hxx>
23
25#include "ogl_canvastools.hxx"
26#include "ogl_tools.hxx"
27
28using namespace ::com::sun::star;
29
30namespace oglcanvas
31{
32 CanvasCustomSprite::CanvasCustomSprite( const css::geometry::RealSize2D& rSpriteSize,
33 const SpriteCanvasRef& rRefDevice,
34 SpriteDeviceHelper& rDeviceHelper ) :
35 mpSpriteCanvas( rRefDevice ),
36 maSize(rSpriteSize),
37 mfAlpha(0.0),
38 mfPriority(0.0)
39 {
40 ENSURE_OR_THROW( rRefDevice,
41 "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
42
44 maCanvasHelper.init( *rRefDevice,
45 rDeviceHelper );
46 }
47
49 {
50 ::osl::MutexGuard aGuard( m_aMutex );
51
52 mpSpriteCanvas.clear();
53
54 // forward to parent
56 }
57
58 void SAL_CALL CanvasCustomSprite::setAlpha( double alpha )
59 {
61
62 ::osl::MutexGuard aGuard( m_aMutex );
63 mfAlpha = alpha;
64 }
65
66 void SAL_CALL CanvasCustomSprite::move( const geometry::RealPoint2D& aNewPos,
67 const rendering::ViewState& viewState,
68 const rendering::RenderState& renderState )
69 {
70 canvas::tools::verifyArgs(aNewPos, viewState, renderState,
71 __func__,
72 getXWeak());
73
74 ::osl::MutexGuard aGuard( m_aMutex );
75 ::basegfx::B2DHomMatrix aTransform;
77 viewState,
78 renderState);
79
80 // convert position to device pixel
81 maPosition = ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos);
82 maPosition *= aTransform;
83 }
84
85 void SAL_CALL CanvasCustomSprite::transform( const geometry::AffineMatrix2D& aTransformation )
86 {
87 ::osl::MutexGuard aGuard( m_aMutex );
88 maTransformation = aTransformation;
89 }
90
91 void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip )
92 {
93 mxClip = xClip;
94 }
95
96 void SAL_CALL CanvasCustomSprite::setPriority( double nPriority )
97 {
98 ::osl::MutexGuard aGuard( m_aMutex );
99 mfPriority = nPriority;
100 }
101
103 {
104 ::osl::MutexGuard aGuard( m_aMutex );
105 if( mpSpriteCanvas.is() )
106 mpSpriteCanvas->show(this);
107 }
108
110 {
111 ::osl::MutexGuard aGuard( m_aMutex );
112 if( mpSpriteCanvas.is() )
113 mpSpriteCanvas->hide(this);
114 }
115
116 uno::Reference< rendering::XCanvas > SAL_CALL CanvasCustomSprite::getContentCanvas()
117 {
118 return this;
119 }
120
122 {
123 if( ::basegfx::fTools::equalZero( mfAlpha ) )
124 return true;
125
126 TransformationPreserver aPreserver1;
127 const ::basegfx::B2IVector aSpriteSizePixel(
128 ::canvas::tools::roundUp( maSize.Width ),
129 ::canvas::tools::roundUp( maSize.Height ));
130
131 // translate sprite to output position
132 glTranslated(maPosition.getX(), maPosition.getY(), 0);
133
134 {
135 TransformationPreserver aPreserver2;
136
137 // apply sprite content transformation matrix
138 double aGLTransform[] =
139 {
140 maTransformation.m00, maTransformation.m10, 0, 0,
141 maTransformation.m01, maTransformation.m11, 0, 0,
142 0, 0, 1, 0,
144 };
145 glMultMatrixd(aGLTransform);
146
147 IBufferContextSharedPtr pBufferContext;
148 if( mfAlpha != 1.0 || mxClip.is() )
149 {
150 // drafts. Need to render to temp surface before, and then
151 // composite that to screen
152
153 // TODO(P3): buffer texture
154 pBufferContext = maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel);
155 pBufferContext->startBufferRendering();
156 }
157
158 // this ends up in pBufferContext, if that one's "current"
159 if( !maCanvasHelper.renderRecordedActions() )
160 return false;
161
162 if( pBufferContext )
163 {
164 // content ended up in background buffer - compose to
165 // screen now. Calls below switches us back to window
166 // context, and binds to generated, dynamic texture
167 pBufferContext->endBufferRendering();
168 GLuint nTexture = pBufferContext->getTextureId();
169 glBindTexture(GL_TEXTURE_2D, nTexture);
170
171 glEnable(GL_TEXTURE_2D);
172 glTexParameteri(GL_TEXTURE_2D,
173 GL_TEXTURE_MIN_FILTER,
174 GL_NEAREST);
175 glTexParameteri(GL_TEXTURE_2D,
176 GL_TEXTURE_MAG_FILTER,
177 GL_NEAREST);
178 glEnable(GL_BLEND);
179 glBlendFunc(GL_SRC_ALPHA,
180 GL_ONE_MINUS_SRC_ALPHA);
181
182 // blend against fixed vertex color; texture alpha is multiplied in
183 glColor4f(1,1,1,mfAlpha);
184
185 if( mxClip.is() )
186 {
187 const double fWidth=maSize.Width;
188 const double fHeight=maSize.Height;
189
190 // TODO(P3): buffer triangulation
191 const ::basegfx::triangulator::B2DTriangleVector rTriangulatedPolygon(
192 ::basegfx::triangulator::triangulate(
193 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip)));
194
195 glBegin(GL_TRIANGLES);
196 for( size_t i=0; i<rTriangulatedPolygon.size(); i++ )
197 {
198 const::basegfx::triangulator::B2DTriangle& rCandidate(rTriangulatedPolygon[i]);
199 glTexCoord2f(
200 rCandidate.getA().getX()/fWidth,
201 rCandidate.getA().getY()/fHeight);
202 glVertex2d(
203 rCandidate.getA().getX(),
204 rCandidate.getA().getY());
205
206 glTexCoord2f(
207 rCandidate.getB().getX()/fWidth,
208 rCandidate.getB().getY()/fHeight);
209 glVertex2d(
210 rCandidate.getB().getX(),
211 rCandidate.getB().getY());
212
213 glTexCoord2f(
214 rCandidate.getC().getX()/fWidth,
215 rCandidate.getC().getY()/fHeight);
216 glVertex2d(
217 rCandidate.getC().getX(),
218 rCandidate.getC().getY());
219 }
220 glEnd();
221 }
222 else
223 {
224 const double fWidth=maSize.Width/aSpriteSizePixel.getX();
225 const double fHeight=maSize.Height/aSpriteSizePixel.getY();
226
227 glBegin(GL_TRIANGLE_STRIP);
228 glTexCoord2f(0,0); glVertex2d(0,0);
229 glTexCoord2f(0,fHeight); glVertex2d(0, aSpriteSizePixel.getY());
230 glTexCoord2f(fWidth,0); glVertex2d(aSpriteSizePixel.getX(),0);
231 glTexCoord2f(fWidth,fHeight); glVertex2d(aSpriteSizePixel.getX(),aSpriteSizePixel.getY());
232 glEnd();
233 }
234
235 glBindTexture(GL_TEXTURE_2D, 0);
236 glDisable(GL_TEXTURE_2D);
237 }
238 }
239
240 glColor4f(1,0,0,1);
241 glBegin(GL_LINE_STRIP);
242 glVertex2d(-2,-2);
243 glVertex2d(-2,maSize.Height+4);
244 glVertex2d(maSize.Width+4,maSize.Height+4);
245 glVertex2d(maSize.Width+4,-2);
246 glVertex2d(-2,-2);
247 glVertex2d(maSize.Width+4,maSize.Height+4);
248 glEnd();
249
250 std::vector<double> aVec { mfAlpha, mfPriority, o3tl::narrowing<double>(maCanvasHelper.getRecordedActionCount()) };
251 renderOSD( aVec, 10 );
252
253 return true;
254 }
255}
256
257/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
TYPE getX() const
TYPE getY() const
virtual void disposeThis() override
Definition: canvasbase.hxx:123
CanvasHelper maCanvasHelper
Definition: canvasbase.hxx:441
virtual void SAL_CALL setPriority(double nPriority) override
SpriteCanvasRef mpSpriteCanvas
MUST hold here, too, since CanvasHelper only contains a raw pointer (without refcounting)
css::geometry::AffineMatrix2D maTransformation
virtual void SAL_CALL transform(const css::geometry::AffineMatrix2D &aTransformation) override
CanvasCustomSprite(const css::geometry::RealSize2D &rSpriteSize, const SpriteCanvasRef &rRefDevice, SpriteDeviceHelper &rDeviceHelper)
Create a custom sprite.
virtual void SAL_CALL show() override
virtual void SAL_CALL move(const css::geometry::RealPoint2D &aNewPos, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState) override
virtual void SAL_CALL clip(const css::uno::Reference< css::rendering::XPolyPolygon2D > &aClip) override
virtual void SAL_CALL hide() override
virtual void SAL_CALL setAlpha(double alpha) override
const css::geometry::RealSize2D maSize
virtual css::uno::Reference< css::rendering::XCanvas > SAL_CALL getContentCanvas() override
css::uno::Reference< css::rendering::XPolyPolygon2D > mxClip
bool renderSprite() const
Render sprite content at sprite position.
#define ENSURE_OR_THROW(c, m)
::basegfx::B2ISize maSize
Definition: dx_9rm.cxx:116
std::mutex m_aMutex
::basegfx::B2DHomMatrix & mergeViewAndRenderTransform(::basegfx::B2DHomMatrix &combinedTransform, const rendering::ViewState &viewState, const rendering::RenderState &renderState)
void verifyRange(NumType arg, NumType lowerBound, NumType upperBound)
Range checker, which throws css::lang::IllegalArgument exception, when range is violated.
geometry::AffineMatrix2D & setIdentityAffineMatrix2D(geometry::AffineMatrix2D &matrix)
void verifyArgs(const Arg0 &rArg0, const char *pStr, const css::uno::Reference< css::uno::XInterface > &xIf)
constexpr double alpha[nDetails]
int i
std::shared_ptr< IBufferContext > IBufferContextSharedPtr
void renderOSD(const std::vector< double > &rNumbers, double scale)
const cppcanvas::SpriteCanvasSharedPtr mpSpriteCanvas