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