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