diff options
author | Caolán McNamara <caolanm@redhat.com> | 2015-03-19 14:43:08 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-03-23 11:42:28 +0000 |
commit | e510a208b01c87a341b43d74d8d901f992379b84 (patch) | |
tree | 7f437b7d48e60ec14b0051993a9f2eb88f40bd53 /vcl/win | |
parent | 2b838285e206912374f464bd1ab8dc8a561f59f5 (diff) |
move cairo helpers to vcl and make per-plug
Change-Id: I4de4d5c3a191784598e93a8cf70e45a3f59ae857
Reviewed-on: https://gerrit.libreoffice.org/14907
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/win')
-rw-r--r-- | vcl/win/source/gdi/cairo_win32_cairo.cxx | 187 | ||||
-rw-r--r-- | vcl/win/source/gdi/cairo_win32_cairo.hxx | 56 | ||||
-rw-r--r-- | vcl/win/source/gdi/salgdi.cxx | 134 |
3 files changed, 377 insertions, 0 deletions
diff --git a/vcl/win/source/gdi/cairo_win32_cairo.cxx b/vcl/win/source/gdi/cairo_win32_cairo.cxx new file mode 100644 index 000000000000..9cf81c7002de --- /dev/null +++ b/vcl/win/source/gdi/cairo_win32_cairo.cxx @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_cairo_canvas.h> + +#if ENABLE_CAIRO_CANVAS +/************************************************************************ + * Win32 surface backend for LibreOffice Cairo Canvas * + ************************************************************************/ + +#include <osl/diagnose.h> +#include <vcl/bitmap.hxx> +#include <vcl/virdev.hxx> +#include <vcl/sysdata.hxx> + +#include "cairo_win32_cairo.hxx" + +namespace cairo +{ + +#include <cairo-win32.h> + + /** + * Surface::Surface: Create generic Canvas surface using given Cairo Surface + * + * @param pSurface Cairo Surface + * + * This constructor only stores data, it does no processing. + * It is used with e.g. cairo_image_surface_create_for_data() + * and Surface::getSimilar() + * + * Set the mpSurface to the new surface or NULL + **/ + Win32Surface::Win32Surface( const CairoSurfaceSharedPtr& pSurface ) : + mpSurface( pSurface ) + {} + + /** + * Surface::Surface: Create Canvas surface from Window reference. + * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) + * @param x horizontal location of the new surface + * @param y vertical location of the new surface + * + * pSysData contains the platform native Window reference. + * pSysData is used to create a surface on the Window + * + * Set the mpSurface to the new surface or NULL + **/ + Win32Surface::Win32Surface( HDC hDC, int x, int y) : + mpSurface( + cairo_win32_surface_create(hDC), + &cairo_surface_destroy) + { + cairo_surface_set_device_offset( mpSurface.get(), x, y ); + } + + /** + * Surface::Surface: Create platform native Canvas surface from BitmapSystemData + * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) + * + * Create a surface based on image data on pBmpData + * + * Set the mpSurface to the new surface or NULL + **/ + Win32Surface::Win32Surface( const BitmapSystemData& rBmpData ) : + mpSurface() + { + OSL_ASSERT(rBmpData.pDIB == NULL); + + if(rBmpData.pDIB != NULL) + { + // So just leave mpSurface to NULL, little else we can do at + // this stage. Hopefully the Win32 patch to + // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&, + // const Size&) will catch the cases where this + // constructor would be called with a DIB bitmap, and we + // will never get here. At least it worked for Ballmer.ppt. + } + else + { + HDC hDC = CreateCompatibleDC(NULL); + void* hOrigBitmap; + OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC); + hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB ); + if(hOrigBitmap == NULL) + OSL_TRACE ("SelectObject failed: %d", GetLastError ()); + mpSurface.reset( + cairo_win32_surface_create(hDC), + &cairo_surface_destroy); + } + } + + /** + * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface + * + * @return new Cairo or NULL + **/ + CairoSharedPtr Win32Surface::getCairo() const + { + return CairoSharedPtr( cairo_create(mpSurface.get()), + &cairo_destroy ); + } + + /** + * Surface::getSimilar: Create new similar Canvas surface + * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h) + * @param width width of the new surface + * @param height height of the new surface + * + * Creates a new Canvas surface. This normally creates platform native surface, even though + * generic function is used. + * + * Cairo surface from aContent (cairo_content_t) + * + * @return new surface or NULL + **/ + SurfaceSharedPtr Win32Surface::getSimilar( int aContent, int width, int height ) const + { + return SurfaceSharedPtr( + new Win32Surface( + CairoSurfaceSharedPtr( + cairo_surface_create_similar( mpSurface.get(), aContent, width, height ), + &cairo_surface_destroy ))); + } + + void Win32Surface::flush() const + { + GdiFlush(); + } + + /** + * Surface::getDepth: Get the color depth of the Canvas surface. + * + * @return color depth + **/ + int Win32Surface::getDepth() const + { + if (mpSurface) + { + switch (cairo_surface_get_content (mpSurface.get())) + { + case CAIRO_CONTENT_ALPHA: return 8; break; + case CAIRO_CONTENT_COLOR: return 24; break; + case CAIRO_CONTENT_COLOR_ALPHA: return 32; break; + } + } + OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!"); + return -1; + } + + + /** + * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface + * + * @return The new virtual device + **/ + boost::shared_ptr<VirtualDevice> Win32Surface::createVirtualDevice() const + { + SystemGraphicsData aSystemGraphicsData; + aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); + aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() ); + + return boost::shared_ptr<VirtualDevice>( + new VirtualDevice( &aSystemGraphicsData, Size(1, 1), sal::static_int_cast<USHORT>(getDepth()) )); + } + +} // namespace cairo + +#endif // #ENABLE_CAIRO_CANVAS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/source/gdi/cairo_win32_cairo.hxx b/vcl/win/source/gdi/cairo_win32_cairo.hxx new file mode 100644 index 000000000000..dd1be37db7dd --- /dev/null +++ b/vcl/win/source/gdi/cairo_win32_cairo.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_WIN32_CAIRO_HXX +#define INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_WIN32_CAIRO_HXX + +#include "cairo_cairo.hxx" +#include <prewin.h> +#include <postwin.h> + +namespace cairo { + + class Win32Surface : public Surface + { + CairoSurfaceSharedPtr mpSurface; + + public: + /// takes over ownership of passed cairo_surface + explicit Win32Surface( const CairoSurfaceSharedPtr& pSurface ); + /// create surface on subarea of given drawable + Win32Surface( HDC hDC, int x, int y ); + /// create surface for given bitmap data + Win32Surface( const BitmapSystemData& rBmpData ); + + // Surface interface + virtual CairoSharedPtr getCairo() const; + virtual CairoSurfaceSharedPtr getCairoSurface() const { return mpSurface; } + virtual SurfaceSharedPtr getSimilar( int aContent, int width, int height ) const; + + virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const; + + virtual void flush() const; + + int getDepth() const; + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx index ff74b0f5546f..66f95d94a9db 100644 --- a/vcl/win/source/gdi/salgdi.cxx +++ b/vcl/win/source/gdi/salgdi.cxx @@ -36,9 +36,14 @@ #include "salgdiimpl.hxx" #include "gdiimpl.hxx" #include "opengl/win/gdiimpl.hxx" +#include <config_cairo_canvas.h> +#if ENABLE_CAIRO_CANVAS +#include "cairo_win32_cairo.cxx" +#endif #include <vcl/opengl/OpenGLHelper.hxx> + #define DITHER_PAL_DELTA 51 #define DITHER_PAL_STEPS 6 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS) @@ -1075,7 +1080,136 @@ SystemGraphicsData WinSalGraphics::GetGraphicsData() const bool WinSalGraphics::SupportsCairo() const { +#if ENABLE_CAIRO_CANVAS return true; +#else + return false; +#endif +} + +/** + * cairo::createSurface: Create generic Canvas surface using given Cairo Surface + * + * @param rSurface Cairo Surface + * + * @return new Surface + */ +cairo::SurfaceSharedPtr WinSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const +{ +#if ENABLE_CAIRO_CANVAS + return cairo::SurfaceSharedPtr(new cairo::Win32Surface(rSurface)); +#else + (void)rSurface; + return cairo::SurfaceSharedPtr(); +#endif +} + +/** + * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice + * + * @param rSurface Cairo Surface + * + * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) + * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx) + * + * @return new Surface + */ +cairo::SurfaceSharedPtr WinSalGraphics::CreateSurface( const OutputDevice& rRefDevice, + int x, int y, int /* width */, int /* height */) const +{ + cairo::SurfaceSharedPtr surf; + +#if ENABLE_CAIRO_CANVAS + if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) + { + const vcl::Window &rWindow = (const vcl::Window &) rRefDevice; + const SystemEnvData* pSysData = GetSysData(&rWindow); + if (pSysData && pSysData->hWnd) + surf = cairo::SurfaceSharedPtr(new cairo::Win32Surface(GetDC((HWND) pSysData->hWnd), x, y)); + } + else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) + { + SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData(); + if (aSysData.hDC) + surf = cairo::SurfaceSharedPtr(new cairo::Win32Surface((HDC) aSysData.hDC, x, y)); + } +#else + (void)x; + (void)y; +#endif + + return surf; +} + +/** + * cairo::createBitmapSurface: Create platform native Canvas surface from BitmapSystemData + * @param OutputDevice (not used) + * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) + * @param rSize width and height of the new surface + * + * Create a surface based on image data on rData + * + * @return new surface or empty surface + **/ +cairo::SurfaceSharedPtr WinSalGraphics::CreateBitmapSurface( const OutputDevice& /* rRefDevice */, + const BitmapSystemData& rData, + const Size& rSize ) const +{ + OSL_TRACE( "requested size: %d x %d available size: %d x %d", + rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); + +#if ENABLE_CAIRO_CANVAS + if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) + return cairo::SurfaceSharedPtr(new cairo::Win32Surface( rData )); +#else + (void)rData; + (void)rSize; +#endif + return cairo::SurfaceSharedPtr(); +} + +#if ENABLE_CAIRO_CANVAS +namespace +{ + HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize ) + { + // can't seem to retrieve HBITMAP from cairo. copy content then + HDC hScreenDC=GetDC(NULL); + HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, + rSize.getX(), + rSize.getY() ); + + HDC hBmpDC = CreateCompatibleDC( 0 ); + HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap ); + + BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(), + cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()), + 0, 0, SRCCOPY ); + + SelectObject( hBmpDC, hBmpOld ); + DeleteDC( hBmpDC ); + + return hBmpBitmap; + } +} +#endif + +css::uno::Any WinSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const +{ + // TODO(F2): check whether under all circumstances, + // the alpha channel is ignored here. + css::uno::Sequence< css::uno::Any > args( 1 ); + sal_Int64 nHandle; +#if ENABLE_CAIRO_CANVAS + nHandle = sal_Int64(surface2HBitmap(rSurface, rSize)); +#else + (void)rSurface; + (void)rSize; + nHandle = 0; +#endif + args[1] = css::uno::Any(nHandle); + // caller frees the bitmap + return css::uno::Any( args ); } void WinSalGraphics::BeginPaint() |