LibreOffice Module canvas (master)  1
dx_canvas.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 #include <sal/log.hxx>
22 
27 #include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
28 #include <com/sun/star/awt/XWindow.hpp>
29 #include <com/sun/star/lang/NoSupportException.hpp>
30 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
31 #include <com/sun/star/registry/XRegistryKey.hpp>
32 #include <com/sun/star/uno/XComponentContext.hpp>
34 #include <cppuhelper/factory.hxx>
36 #include <osl/mutex.hxx>
37 #include <tools/diagnose_ex.h>
38 #include <vcl/sysdata.hxx>
40 #include <vcl/skia/SkiaHelper.hxx>
41 
42 #include <canvas/canvastools.hxx>
43 
44 #include "dx_canvas.hxx"
45 #include "dx_graphicsprovider.hxx"
46 #include "dx_winstuff.hxx"
47 
48 #define CANVAS_TECH "GDI+"
49 #define CANVAS_SERVICE_NAME "com.sun.star.rendering.Canvas." CANVAS_TECH
50 #define CANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.Canvas." CANVAS_TECH
51 #define BITMAPCANVAS_SERVICE_NAME "com.sun.star.rendering.BitmapCanvas." CANVAS_TECH
52 #define BITMAPCANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.BitmapCanvas." CANVAS_TECH
53 
54 
55 using namespace ::com::sun::star;
56 
58 
59 namespace dxcanvas
60 {
61  namespace {
62 
64  class GraphicsProviderImpl : public GraphicsProvider
65  {
67  public:
68  explicit GraphicsProviderImpl( Gdiplus::Graphics* pGraphics ) : mpGraphics( pGraphics ) {}
69  virtual GraphicsSharedPtr getGraphics() override { return mpGraphics; }
70  };
71 
72  }
73 
74  Canvas::Canvas( const uno::Sequence< uno::Any >& aArguments,
75  const uno::Reference< uno::XComponentContext >& rxContext ) :
76  maArguments(aArguments),
77  mxComponentContext( rxContext )
78  {
79  }
80 
81  void Canvas::initialize()
82  {
83  // #i64742# Only perform initialization when not in probe mode
84  if( maArguments.getLength() == 0 )
85  return;
86 
87  // tdf#93870 - force VCL canvas in OpenGL mode for now.
89  assert( !SkiaHelper::isVCLSkiaEnabled() );
90 
91  SAL_INFO("canvas.directx", "Canvas::initialize called" );
92 
93  // At index 1, we expect a HWND handle here, containing a
94  // pointer to a valid window, on which to output
95  // At index 2, we expect the current window bound rect
96  ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 &&
97  maArguments[4].getValueTypeClass() == uno::TypeClass_SEQUENCE,
98  "Canvas::initialize: wrong number of arguments, or wrong types" );
99 
100  uno::Sequence<sal_Int8> aSeq;
101  maArguments[4] >>= aSeq;
102 
103  const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
104  if( !pSysData || !pSysData->hDC )
105  throw lang::NoSupportException("Passed SystemGraphicsData or HDC invalid!");
106 
107  sal_Int64 nPtr = 0;
108  maArguments[0] >>= nPtr;
109  OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
110  ENSURE_ARG_OR_THROW( pOutDev != nullptr,"Canvas::initialize: invalid OutDev pointer" );
111 
112  // setup helper
113  maDeviceHelper.init( pSysData->hDC, pOutDev, *this );
114  maCanvasHelper.setDevice( *this );
115  maCanvasHelper.setTarget(
117  new GraphicsProviderImpl(
118  Gdiplus::Graphics::FromHDC(pSysData->hDC))));
119 
120  maArguments.realloc(0);
121  }
122 
123  void Canvas::disposeThis()
124  {
125  ::osl::MutexGuard aGuard( m_aMutex );
126 
127  mxComponentContext.clear();
128 
129  // forward to parent
130  CanvasBaseT::disposeThis();
131  }
132 
133  OUString SAL_CALL Canvas::getServiceName( )
134  {
135  return CANVAS_SERVICE_NAME;
136  }
137 
138  BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >& aArguments,
139  const uno::Reference< uno::XComponentContext >& rxContext ) :
140  maArguments(aArguments),
141  mxComponentContext( rxContext ),
142  mpTarget()
143  {
144  }
145 
147  {
148  // #i64742# Only perform initialization when not in probe mode
149  if( maArguments.getLength() == 0 )
150  return;
151 
152  SAL_INFO("canvas.directx", "BitmapCanvas::initialize called" );
153 
154  // At index 1, we expect a HWND handle here, containing a
155  // pointer to a valid window, on which to output
156  // At index 2, we expect the current window bound rect
157  ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 &&
158  maArguments[4].getValueTypeClass() == uno::TypeClass_SEQUENCE,
159  "Canvas::initialize: wrong number of arguments, or wrong types" );
160 
161  uno::Sequence<sal_Int8> aSeq;
162  maArguments[4] >>= aSeq;
163 
164  const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
165  if( !pSysData || !pSysData->hDC )
166  throw lang::NoSupportException( "Passed SystemGraphicsData or HDC invalid!");
167 
168  sal_Int64 nPtr = 0;
169  maArguments[0] >>= nPtr;
170  OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
171  ENSURE_ARG_OR_THROW( pOutDev != nullptr,"Canvas::initialize: invalid OutDev pointer" );
172 
173  // setup helper
174  maDeviceHelper.init( pSysData->hDC, pOutDev, *this );
175  maCanvasHelper.setDevice( *this );
176 
177  // check whether we can actually provide a BitmapCanvas
178  // here. for this, check whether the HDC has a bitmap
179  // selected.
180  HBITMAP hBmp;
181  hBmp=static_cast<HBITMAP>(GetCurrentObject(pSysData->hDC, OBJ_BITMAP));
182  if( !hBmp || GetObjectType(pSysData->hDC) != OBJ_MEMDC )
183  {
184  throw lang::NoSupportException( "Passed HDC is no mem DC/has no bitmap selected!");
185  }
186 
187  mpTarget.reset( new DXBitmap(
189  Gdiplus::Bitmap::FromHBITMAP(
190  hBmp, nullptr) ),
191  false ));
192 
193  maCanvasHelper.setTarget( mpTarget );
194 
195  maArguments.realloc(0);
196  }
197 
199  {
200  ::osl::MutexGuard aGuard( m_aMutex );
201 
202  mpTarget.reset();
203  mxComponentContext.clear();
204 
205  // forward to parent
206  BitmapCanvasBaseT::disposeThis();
207  }
208 
209  OUString SAL_CALL BitmapCanvas::getServiceName( )
210  {
212  }
213 
215  {
216  return mpTarget;
217  }
218 
219  static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
220  {
221  uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
222  pCanvas->initialize();
223  return xRet;
224  }
225 
228  serviceImpl1,
231 
232  static uno::Reference<uno::XInterface> initBitmapCanvas( BitmapCanvas* pCanvas )
233  {
234  uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
235  pCanvas->initialize();
236  return xRet;
237  }
238 
239  namespace sdecl = comphelper::service_decl;
242  serviceImpl2,
245 }
246 
247 // The C shared lib entry points
248 extern "C"
249 SAL_DLLPUBLIC_EXPORT void* gdipluscanvas_component_getFactory( char const* pImplName,
250  void*, void* )
251 {
252  return sdecl::component_getFactoryHelper( pImplName, {&dxcanvas::dxCanvasDecl, &dxcanvas::dxBitmapCanvasDecl} );
253 }
254 
255 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Canvas(const css::uno::Sequence< css::uno::Any > &aArguments, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
const sdecl::ServiceDecl dxCanvasDecl(serviceImpl1, CANVAS_IMPLEMENTATION_NAME, CANVAS_SERVICE_NAME)
#define BITMAPCANVAS_SERVICE_NAME
Definition: dx_canvas.cxx:51
#define CANVAS_SERVICE_NAME
Definition: dx_canvas.cxx:49
osl::Mutex m_aMutex
sdecl::class_< BitmapCanvas, sdecl::with_args< true > > const serviceImpl2 & initBitmapCanvas
Definition: dx_canvas.cxx:240
std::shared_ptr< IBitmap > IBitmapSharedPtr
Definition: dx_ibitmap.hxx:59
const sdecl::ServiceDecl dxBitmapCanvasDecl(serviceImpl2, BITMAPCANVAS_IMPLEMENTATION_NAME, BITMAPCANVAS_SERVICE_NAME)
virtual void disposeThis() override
Dispose all internal references.
Definition: dx_canvas.cxx:198
SAL_DLLPUBLIC_EXPORT void * gdipluscanvas_component_getFactory(char const *pImplName, void *, void *)
Definition: dx_canvas.cxx:249
#define BITMAPCANVAS_IMPLEMENTATION_NAME
Definition: dx_canvas.cxx:52
Product of this component's factory.
Definition: dx_canvas.hxx:131
T * mpTarget
static bool isVCLOpenGLEnabled()
Product of this component's factory.
Definition: dx_canvas.hxx:76
GraphicsSharedPtr mpGraphics
Definition: dx_canvas.cxx:66
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
sdecl::class_< Canvas, sdecl::with_args< true > > const serviceImpl1 & initCanvas
Definition: dx_canvas.cxx:226
IBitmapSharedPtr mpTarget
Definition: dx_canvas.hxx:158
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
Definition: dx_canvas.hxx:157
#define ENSURE_ARG_OR_THROW(c, m)
std::shared_ptr< Gdiplus::Bitmap > BitmapSharedPtr
Definition: dx_winstuff.hxx:63
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
css::uno::Sequence< css::uno::Any > maArguments
Definition: dx_canvas.hxx:156
virtual IBitmapSharedPtr getBitmap() const override
Definition: dx_canvas.cxx:214
#define SAL_INFO(area, stream)
std::shared_ptr< GraphicsProvider > GraphicsProviderSharedPtr
virtual OUString SAL_CALL getServiceName() override
Definition: dx_canvas.cxx:209
Sequence< sal_Int8 > aSeq
#define CANVAS_IMPLEMENTATION_NAME
Definition: dx_canvas.cxx:50
std::shared_ptr< Gdiplus::Graphics > GraphicsSharedPtr
Definition: dx_winstuff.hxx:61