LibreOffice Module canvas (master)  1
simplecanvasimpl.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
24 #include <com/sun/star/lang/IllegalArgumentException.hpp>
25 #include <com/sun/star/lang/XServiceName.hpp>
26 #include <com/sun/star/rendering/CompositeOperation.hpp>
27 #include <com/sun/star/rendering/PanoseLetterForm.hpp>
28 #include <com/sun/star/rendering/PanoseWeight.hpp>
29 #include <com/sun/star/rendering/XSimpleCanvas.hpp>
31 #include <cppuhelper/basemutex.hxx>
32 #include <cppuhelper/compbase.hxx>
33 #include <o3tl/lazy_update.hxx>
34 
35 #include <canvas/canvastools.hxx>
36 
37 
38 #include <functional>
39 
40 #define SERVICE_NAME "com.sun.star.rendering.SimpleCanvas"
41 
42 using namespace ::com::sun::star;
43 using namespace canvas;
44 
45 namespace
46 {
47  uno::Sequence< double > color2Sequence( sal_Int32 nColor )
48  {
49  // TODO(F3): Color management
50  uno::Sequence< double > aRes( 4 );
51 
52  aRes[0] = static_cast<sal_uInt8>( (nColor&0xFF000000U) >> 24U ) / 255.0;
53  aRes[1] = static_cast<sal_uInt8>( (nColor&0x00FF0000U) >> 16U ) / 255.0;
54  aRes[2] = static_cast<sal_uInt8>( (nColor&0x0000FF00U) >> 8U ) / 255.0;
55  aRes[3] = static_cast<sal_uInt8>( (nColor&0x000000FFU) ) / 255.0;
56 
57  return aRes;
58  }
59 
60  uno::Reference< rendering::XPolyPolygon2D > rect2Poly( uno::Reference<rendering::XGraphicDevice> const& xDevice,
61  geometry::RealRectangle2D const& rRect )
62  {
63  uno::Sequence< geometry::RealPoint2D > rectSequence( 4 );
64  geometry::RealPoint2D* pOutput = rectSequence.getArray();
65  pOutput[0] = geometry::RealPoint2D( rRect.X1, rRect.Y1 );
66  pOutput[1] = geometry::RealPoint2D( rRect.X2, rRect.Y1 );
67  pOutput[2] = geometry::RealPoint2D( rRect.X2, rRect.Y2 );
68  pOutput[3] = geometry::RealPoint2D( rRect.X1, rRect.Y2 );
69 
70  uno::Sequence< uno::Sequence< geometry::RealPoint2D > > sequenceSequence( 1 );
71  sequenceSequence[0] = rectSequence;
72 
73  uno::Reference< rendering::XPolyPolygon2D > xRes =
74  xDevice->createCompatibleLinePolyPolygon( sequenceSequence );
75  if( xRes.is() )
76  xRes->setClosed( 0, true );
77  return xRes;
78  }
79 
80  struct SimpleRenderState
81  {
82  o3tl::LazyUpdate<sal_Int32,
83  uno::Sequence<double>,
84  decltype(&color2Sequence)> m_aPenColor;
85  o3tl::LazyUpdate<sal_Int32,
86  uno::Sequence<double>,
87  decltype(&color2Sequence)> m_aFillColor;
88  o3tl::LazyUpdate<geometry::RealRectangle2D,
89  uno::Reference< rendering::XPolyPolygon2D >,
90  std::function<uno::Reference<rendering::XPolyPolygon2D> (geometry::RealRectangle2D)> > m_aRectClip;
91  geometry::AffineMatrix2D m_aTransformation;
92 
93  explicit SimpleRenderState( uno::Reference<rendering::XGraphicDevice> const& xDevice ) :
94  m_aPenColor( &color2Sequence),
95  m_aFillColor( &color2Sequence ),
96  m_aRectClip( [&xDevice](geometry::RealRectangle2D const& rRect) { return rect2Poly(xDevice, rRect); } ),
97  m_aTransformation()
98  {
99  tools::setIdentityAffineMatrix2D( m_aTransformation );
100  }
101  };
102 
103 
104  typedef ::cppu::WeakComponentImplHelper< css::rendering::XSimpleCanvas,
105  css::lang::XServiceName > SimpleCanvasBase;
106 
107  class SimpleCanvasImpl : private cppu::BaseMutex,
108  public SimpleCanvasBase
109  {
110  private:
111  bool isStrokingEnabled() const
112  {
113  return maRenderState.m_aPenColor.getInValue() % 0x100 != 0;
114  }
115 
116  rendering::RenderState createStrokingRenderState() const
117  {
118  return rendering::RenderState(maRenderState.m_aTransformation,
119  *maRenderState.m_aRectClip,
120  *maRenderState.m_aPenColor,
121  rendering::CompositeOperation::OVER);
122  }
123 
124  bool isFillingEnabled() const
125  {
126  return maRenderState.m_aFillColor.getInValue() % 0x100 != 0;
127  }
128 
129  rendering::RenderState createFillingRenderState() const
130  {
131  return rendering::RenderState(maRenderState.m_aTransformation,
132  *maRenderState.m_aRectClip,
133  *maRenderState.m_aFillColor,
134  rendering::CompositeOperation::OVER);
135  }
136 
137  static uno::Reference<rendering::XCanvas> grabCanvas( uno::Sequence<uno::Any> const& rArgs )
138  {
139  uno::Reference<rendering::XCanvas> xRet;
140 
141  // can't do much without an XCanvas, can't we?
142  if( !rArgs.hasElements() )
143  throw lang::IllegalArgumentException();
144 
145  xRet.set( rArgs[0], uno::UNO_QUERY );
146 
147  // can't do much without an XCanvas, can't we?
148  if( !xRet.is() )
149  throw lang::IllegalArgumentException();
150 
151  return xRet;
152  }
153 
154  public:
155  SimpleCanvasImpl( const uno::Sequence< uno::Any >& aArguments,
156  const uno::Reference< uno::XComponentContext >& ) :
157  SimpleCanvasBase( m_aMutex ),
158  mxCanvas( grabCanvas(aArguments) ),
159  maFont([this](rendering::FontRequest const& rFontRequest) {
160  return mxCanvas->createFont(rFontRequest,
161  uno::Sequence< beans::PropertyValue >(),
162  geometry::Matrix2D()); } ),
163  maViewState(),
164  maRenderState( mxCanvas->getDevice() )
165  {
166  tools::initViewState(maViewState);
167  }
168 
169 
170  private:
171  // Ifc XServiceName
172  virtual OUString SAL_CALL getServiceName( ) override
173  {
174  return SERVICE_NAME;
175  }
176 
177  // Ifc XSimpleCanvas
178  virtual void SAL_CALL selectFont( const OUString& sFontName,
179  double size,
180  sal_Bool bold,
181  sal_Bool italic ) override
182  {
183  ::osl::MutexGuard aGuard( m_aMutex );
184 
185  maFont->FontDescription.FamilyName = sFontName;
186  maFont->CellSize = size;
187  maFont->FontDescription.FontDescription.Weight =
188  bold ? rendering::PanoseWeight::BOLD : rendering::PanoseWeight::MEDIUM;
189  maFont->FontDescription.FontDescription.Letterform =
190  italic ? rendering::PanoseLetterForm::OBLIQUE_CONTACT : rendering::PanoseLetterForm::ANYTHING;
191  }
192 
193  virtual void SAL_CALL setPenColor( ::sal_Int32 nsRgbaColor ) override
194  {
195  ::osl::MutexGuard aGuard( m_aMutex );
196  *(maRenderState.m_aPenColor) = nsRgbaColor;
197  }
198 
199  virtual void SAL_CALL setFillColor( ::sal_Int32 nsRgbaColor ) override
200  {
201  ::osl::MutexGuard aGuard( m_aMutex );
202  *(maRenderState.m_aFillColor) = nsRgbaColor;
203  }
204 
205  virtual void SAL_CALL setRectClip( const geometry::RealRectangle2D& aRect ) override
206  {
207  ::osl::MutexGuard aGuard( m_aMutex );
208  *(maRenderState.m_aRectClip) = aRect;
209  }
210 
211  virtual void SAL_CALL setTransformation( const geometry::AffineMatrix2D& aTransform ) override
212  {
213  ::osl::MutexGuard aGuard( m_aMutex );
214  maRenderState.m_aTransformation = aTransform;
215  }
216 
217  virtual void SAL_CALL drawPixel( const geometry::RealPoint2D& aPoint ) override
218  {
219  ::osl::MutexGuard aGuard( m_aMutex );
220  mxCanvas->drawPoint(aPoint,
221  maViewState,
222  createFillingRenderState());
223  }
224 
225  virtual void SAL_CALL drawLine( const geometry::RealPoint2D& aStartPoint,
226  const geometry::RealPoint2D& aEndPoint ) override
227  {
228  ::osl::MutexGuard aGuard( m_aMutex );
229  mxCanvas->drawLine(aStartPoint,
230  aEndPoint,
231  maViewState,
232  createStrokingRenderState());
233  }
234 
235  virtual void SAL_CALL drawRect( const geometry::RealRectangle2D& aRect ) override
236  {
237  ::osl::MutexGuard aGuard( m_aMutex );
238  uno::Reference< rendering::XPolyPolygon2D > xPoly(
239  rect2Poly( mxCanvas->getDevice(),
240  aRect));
241 
242  if( isFillingEnabled() )
243  mxCanvas->drawPolyPolygon(xPoly,
244  maViewState,
245  createFillingRenderState());
246  if( isStrokingEnabled() )
247  mxCanvas->drawPolyPolygon(xPoly,
248  maViewState,
249  createStrokingRenderState());
250  }
251 
252  virtual void SAL_CALL drawPolyPolygon( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon ) override
253  {
254  ::osl::MutexGuard aGuard( m_aMutex );
255 
256  if( isFillingEnabled() )
257  mxCanvas->drawPolyPolygon(xPolyPolygon,
258  maViewState,
259  createFillingRenderState());
260  if( isStrokingEnabled() )
261  mxCanvas->drawPolyPolygon(xPolyPolygon,
262  maViewState,
263  createStrokingRenderState());
264  }
265 
266  virtual void SAL_CALL drawText( const rendering::StringContext& aText,
267  const geometry::RealPoint2D& aOutPos,
268  ::sal_Int8 nTextDirection ) override
269  {
270  ::osl::MutexGuard aGuard( m_aMutex );
271  const basegfx::B2DHomMatrix offsetTransform(basegfx::utils::createTranslateB2DHomMatrix(aOutPos.X,aOutPos.Y));
272  rendering::RenderState aRenderState( createStrokingRenderState() );
273  tools::appendToRenderState(aRenderState, offsetTransform);
274 
275  mxCanvas->drawText(aText,
276  maFont.getOutValue(),
277  maViewState,
278  aRenderState,
279  nTextDirection);
280  }
281 
282  virtual void SAL_CALL drawBitmap( const uno::Reference< rendering::XBitmap >& xBitmap,
283  const geometry::RealPoint2D& aLeftTop ) override
284  {
285  ::osl::MutexGuard aGuard( m_aMutex );
286  const basegfx::B2DHomMatrix offsetTransform(basegfx::utils::createTranslateB2DHomMatrix(aLeftTop.X,aLeftTop.Y));
287  rendering::RenderState aRenderState( createStrokingRenderState() );
288  tools::appendToRenderState(aRenderState, offsetTransform);
289 
290  mxCanvas->drawBitmap(xBitmap,maViewState,aRenderState);
291  }
292 
293  virtual uno::Reference< rendering::XGraphicDevice > SAL_CALL getDevice( ) override
294  {
295  ::osl::MutexGuard aGuard( m_aMutex );
296  return mxCanvas->getDevice();
297  }
298 
299  virtual uno::Reference< rendering::XCanvas > SAL_CALL getCanvas( ) override
300  {
301  ::osl::MutexGuard aGuard( m_aMutex );
302  return mxCanvas;
303  }
304 
305  virtual rendering::FontMetrics SAL_CALL getFontMetrics( ) override
306  {
307  ::osl::MutexGuard aGuard( m_aMutex );
308  return maFont.getOutValue()->getFontMetrics();
309  }
310 
311  virtual uno::Reference< rendering::XCanvasFont > SAL_CALL getCurrentFont( ) override
312  {
313  ::osl::MutexGuard aGuard( m_aMutex );
314  return maFont.getOutValue();
315  }
316 
317  virtual ::sal_Int32 SAL_CALL getCurrentPenColor( ) override
318  {
319  ::osl::MutexGuard aGuard( m_aMutex );
320  return maRenderState.m_aPenColor.getInValue();
321  }
322 
323  virtual ::sal_Int32 SAL_CALL getCurrentFillColor( ) override
324  {
325  ::osl::MutexGuard aGuard( m_aMutex );
326  return maRenderState.m_aFillColor.getInValue();
327  }
328 
329  virtual geometry::RealRectangle2D SAL_CALL getCurrentClipRect( ) override
330  {
331  ::osl::MutexGuard aGuard( m_aMutex );
332  return maRenderState.m_aRectClip.getInValue();
333  }
334 
335  virtual geometry::AffineMatrix2D SAL_CALL getCurrentTransformation( ) override
336  {
337  ::osl::MutexGuard aGuard( m_aMutex );
338  return maRenderState.m_aTransformation;
339  }
340 
341  virtual rendering::ViewState SAL_CALL getCurrentViewState( ) override
342  {
343  ::osl::MutexGuard aGuard( m_aMutex );
344  return maViewState;
345  }
346 
347  virtual rendering::RenderState SAL_CALL getCurrentRenderState( sal_Bool bUseFillColor ) override
348  {
349  ::osl::MutexGuard aGuard( m_aMutex );
350  if( bUseFillColor )
351  return createFillingRenderState();
352  else
353  return createStrokingRenderState();
354  }
355 
356 
357  typedef o3tl::LazyUpdate<
358  rendering::FontRequest,
359  uno::Reference< rendering::XCanvasFont >,
360  std::function<uno::Reference<rendering::XCanvasFont> (rendering::FontRequest)> > SimpleFont;
361 
362  uno::Reference<rendering::XCanvas> mxCanvas;
363  SimpleFont maFont;
364  rendering::ViewState maViewState;
365  SimpleRenderState maRenderState;
366  };
367 
368  namespace sdecl = comphelper::service_decl;
369  const sdecl::ServiceDecl simpleCanvasDecl(
370  sdecl::class_<SimpleCanvasImpl, sdecl::with_args<true> >(),
371  "com.sun.star.comp.rendering.SimpleCanvas",
372  SERVICE_NAME );
373 }
374 
375 // The C shared lib entry points
376 extern "C" SAL_DLLPUBLIC_EXPORT void* simplecanvas_component_getFactory( char const* pImplName,
377  void*, void* )
378 {
379  return sdecl::component_getFactoryHelper( pImplName, {&simpleCanvasDecl} );
380 }
381 
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< rendering::XCanvas > mxCanvas
osl::Mutex m_aMutex
signed char sal_Int8
Sequence< PropertyValue > aArguments
#define SERVICE_NAME
void drawLine(VirtualDevice *dev, Point const &orig, Point const &dest, Size const &pSize)
geometry::AffineMatrix2D & setIdentityAffineMatrix2D(geometry::AffineMatrix2D &matrix)
unsigned char sal_Bool
size
bold
unsigned char sal_uInt8
::basegfx::B2DHomMatrix m_aTransformation
rendering::ViewState & initViewState(rendering::ViewState &viewState)
Definition: canvastools.cxx:86
rendering::RenderState & appendToRenderState(rendering::RenderState &renderState, const ::basegfx::B2DHomMatrix &rTransform)
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
SAL_DLLPUBLIC_EXPORT void * simplecanvas_component_getFactory(char const *pImplName, void *, void *)