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