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