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