1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <sal/config.h>
14 #include <basegfx/matrix/b2dhommatrix.hxx>
15 #include <basegfx/point/b2dpoint.hxx>
16 #include <basegfx/polygon/b2dpolypolygon.hxx>
17 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
18 #include <basegfx/utils/canvastools.hxx>
19 #include <canvas/canvastools.hxx>
20 #include <o3tl/safeint.hxx>
21 #include <verifyinput.hxx>
22 #include <comphelper/diagnose_ex.hxx>
24 #include "ogl_canvascustomsprite.hxx"
25 #include "ogl_canvastools.hxx"
26 #include "ogl_tools.hxx"
28 using namespace ::com::sun::star
;
32 CanvasCustomSprite::CanvasCustomSprite( const css::geometry::RealSize2D
& rSpriteSize
,
33 const SpriteCanvasRef
& rRefDevice
,
34 SpriteDeviceHelper
& rDeviceHelper
) :
35 mpSpriteCanvas( rRefDevice
),
40 ENSURE_OR_THROW( rRefDevice
,
41 "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
43 ::canvas::tools::setIdentityAffineMatrix2D(maTransformation
);
44 maCanvasHelper
.init( *rRefDevice
,
48 void CanvasCustomSprite::disposeThis()
50 ::osl::MutexGuard
aGuard( m_aMutex
);
52 mpSpriteCanvas
.clear();
55 CanvasCustomSpriteBaseT::disposeThis();
58 void SAL_CALL
CanvasCustomSprite::setAlpha( double alpha
)
60 canvas::tools::verifyRange( alpha
, 0.0, 1.0 );
62 ::osl::MutexGuard
aGuard( m_aMutex
);
66 void SAL_CALL
CanvasCustomSprite::move( const geometry::RealPoint2D
& aNewPos
,
67 const rendering::ViewState
& viewState
,
68 const rendering::RenderState
& renderState
)
70 canvas::tools::verifyArgs(aNewPos
, viewState
, renderState
,
74 ::osl::MutexGuard
aGuard( m_aMutex
);
75 ::basegfx::B2DHomMatrix aTransform
;
76 ::canvas::tools::mergeViewAndRenderTransform(aTransform
,
80 // convert position to device pixel
81 maPosition
= ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos
);
82 maPosition
*= aTransform
;
85 void SAL_CALL
CanvasCustomSprite::transform( const geometry::AffineMatrix2D
& aTransformation
)
87 ::osl::MutexGuard
aGuard( m_aMutex
);
88 maTransformation
= aTransformation
;
91 void SAL_CALL
CanvasCustomSprite::clip( const uno::Reference
< rendering::XPolyPolygon2D
>& xClip
)
96 void SAL_CALL
CanvasCustomSprite::setPriority( double nPriority
)
98 ::osl::MutexGuard
aGuard( m_aMutex
);
99 mfPriority
= nPriority
;
102 void SAL_CALL
CanvasCustomSprite::show()
104 ::osl::MutexGuard
aGuard( m_aMutex
);
105 if( mpSpriteCanvas
.is() )
106 mpSpriteCanvas
->show(this);
109 void SAL_CALL
CanvasCustomSprite::hide()
111 ::osl::MutexGuard
aGuard( m_aMutex
);
112 if( mpSpriteCanvas
.is() )
113 mpSpriteCanvas
->hide(this);
116 uno::Reference
< rendering::XCanvas
> SAL_CALL
CanvasCustomSprite::getContentCanvas()
121 bool CanvasCustomSprite::renderSprite() const
123 if( ::basegfx::fTools::equalZero( mfAlpha
) )
126 TransformationPreserver aPreserver1
;
127 const ::basegfx::B2IVector
aSpriteSizePixel(
128 ::canvas::tools::roundUp( maSize
.Width
),
129 ::canvas::tools::roundUp( maSize
.Height
));
131 // translate sprite to output position
132 glTranslated(maPosition
.getX(), maPosition
.getY(), 0);
135 TransformationPreserver aPreserver2
;
137 // apply sprite content transformation matrix
138 double aGLTransform
[] =
140 maTransformation
.m00
, maTransformation
.m10
, 0, 0,
141 maTransformation
.m01
, maTransformation
.m11
, 0, 0,
143 maTransformation
.m02
, maTransformation
.m12
, 0, 1
145 glMultMatrixd(aGLTransform
);
147 IBufferContextSharedPtr pBufferContext
;
148 if( mfAlpha
!= 1.0 || mxClip
.is() )
150 // drafts. Need to render to temp surface before, and then
151 // composite that to screen
153 // TODO(P3): buffer texture
154 pBufferContext
= maCanvasHelper
.getDeviceHelper()->createBufferContext(aSpriteSizePixel
);
155 pBufferContext
->startBufferRendering();
158 // this ends up in pBufferContext, if that one's "current"
159 if( !maCanvasHelper
.renderRecordedActions() )
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
);
171 glEnable(GL_TEXTURE_2D
);
172 glTexParameteri(GL_TEXTURE_2D
,
173 GL_TEXTURE_MIN_FILTER
,
175 glTexParameteri(GL_TEXTURE_2D
,
176 GL_TEXTURE_MAG_FILTER
,
179 glBlendFunc(GL_SRC_ALPHA
,
180 GL_ONE_MINUS_SRC_ALPHA
);
182 // blend against fixed vertex color; texture alpha is multiplied in
183 glColor4f(1,1,1,mfAlpha
);
187 const double fWidth
=maSize
.Width
;
188 const double fHeight
=maSize
.Height
;
190 // TODO(P3): buffer triangulation
191 const ::basegfx::triangulator::B2DTriangleVector
rTriangulatedPolygon(
192 ::basegfx::triangulator::triangulate(
193 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip
)));
195 glBegin(GL_TRIANGLES
);
196 for(const auto& i
: rTriangulatedPolygon
)
198 const::basegfx::triangulator::B2DTriangle
& rCandidate(i
);
200 rCandidate
.getA().getX()/fWidth
,
201 rCandidate
.getA().getY()/fHeight
);
203 rCandidate
.getA().getX(),
204 rCandidate
.getA().getY());
207 rCandidate
.getB().getX()/fWidth
,
208 rCandidate
.getB().getY()/fHeight
);
210 rCandidate
.getB().getX(),
211 rCandidate
.getB().getY());
214 rCandidate
.getC().getX()/fWidth
,
215 rCandidate
.getC().getY()/fHeight
);
217 rCandidate
.getC().getX(),
218 rCandidate
.getC().getY());
224 const double fWidth
=maSize
.Width
/aSpriteSizePixel
.getX();
225 const double fHeight
=maSize
.Height
/aSpriteSizePixel
.getY();
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());
235 glBindTexture(GL_TEXTURE_2D
, 0);
236 glDisable(GL_TEXTURE_2D
);
241 glBegin(GL_LINE_STRIP
);
243 glVertex2d(-2,maSize
.Height
+4);
244 glVertex2d(maSize
.Width
+4,maSize
.Height
+4);
245 glVertex2d(maSize
.Width
+4,-2);
247 glVertex2d(maSize
.Width
+4,maSize
.Height
+4);
250 std::vector
<double> aVec
{ mfAlpha
, mfPriority
, o3tl::narrowing
<double>(maCanvasHelper
.getRecordedActionCount()) };
251 renderOSD( aVec
, 10 );
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */