Line data Source code
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 "ogl_canvascustomsprite.hxx"
11 : #include "ogl_canvastools.hxx"
12 : #include "ogl_tools.hxx"
13 :
14 : #include <canvas/debug.hxx>
15 : #include <canvas/verbosetrace.hxx>
16 : #include <canvas/verifyinput.hxx>
17 : #include <tools/diagnose_ex.h>
18 :
19 : #include <canvas/canvastools.hxx>
20 :
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>
27 :
28 : #include <GL/glew.h>
29 :
30 : using namespace ::com::sun::star;
31 :
32 : namespace oglcanvas
33 : {
34 0 : 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 0 : mfPriority(0.0)
44 : {
45 0 : ENSURE_OR_THROW( rRefDevice.get(),
46 : "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
47 :
48 0 : ::canvas::tools::setIdentityAffineMatrix2D(maTransformation);
49 0 : maCanvasHelper.init( *rRefDevice.get(),
50 0 : rDeviceHelper );
51 0 : }
52 :
53 0 : void CanvasCustomSprite::disposeThis()
54 : {
55 0 : ::osl::MutexGuard aGuard( m_aMutex );
56 :
57 0 : mpSpriteCanvas.clear();
58 :
59 : // forward to parent
60 0 : CanvasCustomSpriteBaseT::disposeThis();
61 0 : }
62 :
63 0 : void SAL_CALL CanvasCustomSprite::setAlpha( double alpha ) throw (lang::IllegalArgumentException,
64 : uno::RuntimeException, std::exception)
65 : {
66 0 : canvas::tools::verifyRange( alpha, 0.0, 1.0 );
67 :
68 0 : ::osl::MutexGuard aGuard( m_aMutex );
69 0 : mfAlpha = alpha;
70 0 : }
71 :
72 0 : 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)
76 : {
77 : canvas::tools::verifyArgs(aNewPos, viewState, renderState,
78 : BOOST_CURRENT_FUNCTION,
79 0 : static_cast< ::cppu::OWeakObject* >(this));
80 :
81 0 : ::osl::MutexGuard aGuard( m_aMutex );
82 0 : ::basegfx::B2DHomMatrix aTransform;
83 : ::canvas::tools::mergeViewAndRenderTransform(aTransform,
84 : viewState,
85 0 : renderState);
86 :
87 : // convert position to device pixel
88 0 : maPosition = ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos);
89 0 : maPosition *= aTransform;
90 0 : }
91 :
92 0 : void SAL_CALL CanvasCustomSprite::transform( const geometry::AffineMatrix2D& aTransformation ) throw (lang::IllegalArgumentException,
93 : uno::RuntimeException, std::exception)
94 : {
95 0 : ::osl::MutexGuard aGuard( m_aMutex );
96 0 : maTransformation = aTransformation;
97 0 : }
98 :
99 0 : void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip ) throw (uno::RuntimeException, std::exception)
100 : {
101 0 : mxClip = xClip;
102 0 : }
103 :
104 0 : void SAL_CALL CanvasCustomSprite::setPriority( double nPriority ) throw (uno::RuntimeException, std::exception)
105 : {
106 0 : ::osl::MutexGuard aGuard( m_aMutex );
107 0 : mfPriority = nPriority;
108 0 : }
109 :
110 0 : void SAL_CALL CanvasCustomSprite::show() throw (uno::RuntimeException, std::exception)
111 : {
112 0 : ::osl::MutexGuard aGuard( m_aMutex );
113 0 : if( mpSpriteCanvas.is() )
114 0 : mpSpriteCanvas->show(this);
115 0 : }
116 :
117 0 : void SAL_CALL CanvasCustomSprite::hide() throw (uno::RuntimeException, std::exception)
118 : {
119 0 : ::osl::MutexGuard aGuard( m_aMutex );
120 0 : if( mpSpriteCanvas.is() )
121 0 : mpSpriteCanvas->hide(this);
122 0 : }
123 :
124 0 : uno::Reference< rendering::XCanvas > SAL_CALL CanvasCustomSprite::getContentCanvas() throw (uno::RuntimeException, std::exception)
125 : {
126 0 : return this;
127 : }
128 :
129 0 : bool CanvasCustomSprite::renderSprite() const
130 : {
131 0 : if( ::basegfx::fTools::equalZero( mfAlpha ) )
132 0 : return true;
133 :
134 0 : TransformationPreserver aPreserver1;
135 : const ::basegfx::B2IVector aSpriteSizePixel(
136 : ::canvas::tools::roundUp( maSize.Width ),
137 0 : ::canvas::tools::roundUp( maSize.Height ));
138 :
139 : // translate sprite to output position
140 0 : glTranslated(maPosition.getX(), maPosition.getY(), 0);
141 :
142 : {
143 0 : TransformationPreserver aPreserver2;
144 :
145 : // apply sprite content transformation matrix
146 : double aGLTransform[] =
147 : {
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
152 0 : };
153 0 : glMultMatrixd(aGLTransform);
154 :
155 0 : IBufferContextSharedPtr pBufferContext;
156 0 : if( mfAlpha != 1.0 || mxClip.is() )
157 : {
158 : // drats. need to render to temp surface before, and then
159 : // composite that to screen
160 :
161 : // TODO(P3): buffer texture
162 0 : pBufferContext = maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel);
163 0 : pBufferContext->startBufferRendering();
164 : }
165 :
166 : // this ends up in pBufferContext, if that one's "current"
167 0 : if( !maCanvasHelper.renderRecordedActions() )
168 0 : return false;
169 :
170 0 : if( pBufferContext )
171 : {
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 0 : pBufferContext->endBufferRendering();
176 0 : GLuint nTexture = pBufferContext->getTextureId();
177 0 : glBindTexture(GL_TEXTURE_2D, nTexture);
178 :
179 0 : glEnable(GL_TEXTURE_2D);
180 : glTexParameteri(GL_TEXTURE_2D,
181 : GL_TEXTURE_MIN_FILTER,
182 0 : GL_NEAREST);
183 : glTexParameteri(GL_TEXTURE_2D,
184 : GL_TEXTURE_MAG_FILTER,
185 0 : GL_NEAREST);
186 0 : glEnable(GL_BLEND);
187 : glBlendFunc(GL_SRC_ALPHA,
188 0 : GL_ONE_MINUS_SRC_ALPHA);
189 :
190 : // blend against fixed vertex color; texture alpha is multiplied in
191 0 : glColor4f(1,1,1,mfAlpha);
192 :
193 0 : if( mxClip.is() )
194 : {
195 0 : const double fWidth=maSize.Width;
196 0 : const double fHeight=maSize.Height;
197 :
198 : // TODO(P3): buffer triangulation
199 : const ::basegfx::B2DPolygon& rTriangulatedPolygon(
200 : ::basegfx::triangulator::triangulate(
201 0 : ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip)));
202 :
203 : basegfx::B2DPolygon rTriangleList(
204 : basegfx::tools::clipTriangleListOnRange(
205 : rTriangulatedPolygon,
206 : basegfx::B2DRange(
207 : 0,0,
208 0 : aSpriteSizePixel.getX(),
209 0 : aSpriteSizePixel.getY())));
210 :
211 0 : glBegin(GL_TRIANGLES);
212 0 : for( sal_uInt32 i=0; i<rTriangulatedPolygon.count(); i++ )
213 : {
214 0 : const ::basegfx::B2DPoint& rPt( rTriangulatedPolygon.getB2DPoint(i) );
215 0 : const double s(rPt.getX()/fWidth);
216 0 : const double t(rPt.getY()/fHeight);
217 0 : glTexCoord2f(s,t); glVertex2d(rPt.getX(), rPt.getY());
218 0 : }
219 0 : glEnd();
220 : }
221 : else
222 : {
223 0 : const double fWidth=maSize.Width/aSpriteSizePixel.getX();
224 0 : const double fHeight=maSize.Height/aSpriteSizePixel.getY();
225 :
226 0 : glBegin(GL_TRIANGLE_STRIP);
227 0 : glTexCoord2f(0,0); glVertex2d(0,0);
228 0 : glTexCoord2f(0,fHeight); glVertex2d(0, aSpriteSizePixel.getY());
229 0 : glTexCoord2f(fWidth,0); glVertex2d(aSpriteSizePixel.getX(),0);
230 0 : glTexCoord2f(fWidth,fHeight); glVertex2d(aSpriteSizePixel.getX(),aSpriteSizePixel.getY());
231 0 : glEnd();
232 : }
233 :
234 0 : glBindTexture(GL_TEXTURE_2D, 0);
235 0 : glDisable(GL_TEXTURE_2D);
236 0 : }
237 : }
238 :
239 0 : glColor4f(1,0,0,1);
240 0 : glBegin(GL_LINE_STRIP);
241 0 : glVertex2d(-2,-2);
242 0 : glVertex2d(-2,maSize.Height+4);
243 0 : glVertex2d(maSize.Width+4,maSize.Height+4);
244 0 : glVertex2d(maSize.Width+4,-2);
245 0 : glVertex2d(-2,-2);
246 0 : glVertex2d(maSize.Width+4,maSize.Height+4);
247 0 : glEnd();
248 :
249 0 : std::vector<double> aVec;
250 0 : aVec.push_back(mfAlpha);
251 0 : aVec.push_back(mfPriority);
252 0 : aVec.push_back(maCanvasHelper.getRecordedActionCount());
253 0 : renderOSD( aVec, 10 );
254 :
255 0 : return true;
256 : }
257 0 : }
258 :
259 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|