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