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 | |
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')
-rw-r--r-- | vcl/Library_vcl.mk | 3 | ||||
-rw-r--r-- | vcl/Library_vclplug_gen.mk | 1 | ||||
-rw-r--r-- | vcl/generic/print/genpspgraphics.cxx | 20 | ||||
-rw-r--r-- | vcl/headless/svpgdi.cxx | 20 | ||||
-rw-r--r-- | vcl/inc/cairo_cairo.hxx | 36 | ||||
-rw-r--r-- | vcl/inc/generic/genpspgraphics.h | 4 | ||||
-rw-r--r-- | vcl/inc/headless/svpgdi.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/quartz/salgdi.h | 4 | ||||
-rw-r--r-- | vcl/inc/salgdi.hxx | 7 | ||||
-rw-r--r-- | vcl/inc/unx/salgdi.h | 4 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 4 | ||||
-rw-r--r-- | vcl/quartz/cairo_quartz_cairo.cxx | 260 | ||||
-rw-r--r-- | vcl/quartz/cairo_quartz_cairo.hxx | 70 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 113 | ||||
-rw-r--r-- | vcl/source/outdev/outdev.cxx | 46 | ||||
-rw-r--r-- | vcl/source/window/cairo_cairo.cxx | 51 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/cairo_xlib_cairo.cxx | 311 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/cairo_xlib_cairo.hxx | 105 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi.cxx | 70 | ||||
-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 |
22 files changed, 1509 insertions, 1 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 701766473404..4eaca9a3ad64 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -135,6 +135,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/opengl/texture \ vcl/source/opengl/OpenGLContext \ vcl/source/opengl/OpenGLHelper \ + vcl/source/window/cairo_cairo \ vcl/source/window/openglwin \ vcl/source/window/settings \ vcl/source/window/paint \ @@ -496,6 +497,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/osx/PictToBmpFlt \ vcl/osx/clipboard \ vcl/osx/service_entry \ + vcl/quartz/cairo_quartz_cairo \ $(vcl_quartz_code) \ vcl/quartz/salgdiutils \ vcl/osx/salnativewidgets \ @@ -665,6 +667,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/win/source/app/salinst \ vcl/win/source/app/salshl \ vcl/win/source/app/saltimer \ + vcl/win/source/gdi/cairo_win32_cairo \ vcl/win/source/gdi/gdiimpl \ vcl/win/source/gdi/salbmp \ vcl/win/source/gdi/salgdi \ diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk index 56135af18f78..79bd353cea57 100644 --- a/vcl/Library_vclplug_gen.mk +++ b/vcl/Library_vclplug_gen.mk @@ -89,6 +89,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\ vcl/unx/generic/dtrans/X11_selection \ vcl/unx/generic/dtrans/X11_service \ vcl/unx/generic/dtrans/X11_transferable \ + vcl/unx/generic/gdi/cairo_xlib_cairo \ vcl/unx/generic/gdi/x11cairotextrender \ vcl/unx/generic/gdi/gcach_xpeer \ vcl/unx/generic/gdi/gdiimpl \ diff --git a/vcl/generic/print/genpspgraphics.cxx b/vcl/generic/print/genpspgraphics.cxx index a5457ce399f6..1f7eb2b20999 100644 --- a/vcl/generic/print/genpspgraphics.cxx +++ b/vcl/generic/print/genpspgraphics.cxx @@ -1214,6 +1214,26 @@ bool GenPspGraphics::SupportsCairo() const return false; } +cairo::SurfaceSharedPtr GenPspGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& /*rSurface*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +cairo::SurfaceSharedPtr GenPspGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +cairo::SurfaceSharedPtr GenPspGraphics::CreateBitmapSurface(const OutputDevice& /*rRefDevice*/, const BitmapSystemData& /*rData*/, const Size& /*rSize*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +css::uno::Any GenPspGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /*rSurface*/, const basegfx::B2ISize& /*rSize*/) const +{ + return css::uno::Any(); +} + SystemFontData GenPspGraphics::GetSysFontData( int /* nFallbacklevel */ ) const { return SystemFontData(); diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index f63ae479f31b..49eff809c64a 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -738,4 +738,24 @@ bool SvpSalGraphics::SupportsCairo() const return false; } +cairo::SurfaceSharedPtr SvpSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& /*rSurface*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +cairo::SurfaceSharedPtr SvpSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +cairo::SurfaceSharedPtr SvpSalGraphics::CreateBitmapSurface(const OutputDevice& /*rRefDevice*/, const BitmapSystemData& /*rData*/, const Size& /*rSize*/) const +{ + return cairo::SurfaceSharedPtr(); +} + +css::uno::Any SvpSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /*rSurface*/, const basegfx::B2ISize& /*rSize*/) const +{ + return css::uno::Any(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/cairo_cairo.hxx b/vcl/inc/cairo_cairo.hxx new file mode 100644 index 000000000000..968954b1ce19 --- /dev/null +++ b/vcl/inc/cairo_cairo.hxx @@ -0,0 +1,36 @@ +/* -*- 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_CAIRO_HXX +#define INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_CAIRO_HXX + +#include <sal/config.h> +#include <vcl/cairo.hxx> +#include "vcl/dllapi.h" + +struct SystemEnvData; +namespace vcl { class Window; } + +namespace cairo { + VCL_PLUGIN_PUBLIC const SystemEnvData* GetSysData(const vcl::Window *pOutputWindow); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/generic/genpspgraphics.h b/vcl/inc/generic/genpspgraphics.h index 5e8bcf353e65..8b78faa8d0b1 100644 --- a/vcl/inc/generic/genpspgraphics.h +++ b/vcl/inc/generic/genpspgraphics.h @@ -202,6 +202,10 @@ public: virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; virtual bool SupportsCairo() const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const SAL_OVERRIDE; virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE; diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index 9cc4dbab07b6..3d68e7649314 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -200,6 +200,10 @@ public: virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; virtual bool SupportsCairo() const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const SAL_OVERRIDE; virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE; diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index 54bd2a932831..e9cddd80af3e 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -419,6 +419,10 @@ public: virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; virtual bool SupportsCairo() const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const SAL_OVERRIDE; virtual SystemFontData GetSysFontData( int /* nFallbacklevel */ ) const SAL_OVERRIDE; virtual void BeginPaint() SAL_OVERRIDE { }; diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx index ef1812077ee8..827baa0f2514 100644 --- a/vcl/inc/salgdi.hxx +++ b/vcl/inc/salgdi.hxx @@ -440,6 +440,13 @@ public: /// Check whether cairo will work virtual bool SupportsCairo() const = 0; + /// Create Surface from given cairo surface + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const = 0; + /// Create surface with given dimensions + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const = 0; + /// Create Surface for given bitmap data + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const = 0; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const = 0; virtual SystemFontData GetSysFontData( int nFallbacklevel ) const = 0; diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index b8a2a60972de..0a0d0d329bce 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -263,6 +263,10 @@ public: virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; virtual bool SupportsCairo() const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const SAL_OVERRIDE; virtual SystemFontData GetSysFontData( int nFallbackLevel ) const SAL_OVERRIDE; virtual void BeginPaint() SAL_OVERRIDE; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index e956e0ff4644..fdd931ce5fe6 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -449,6 +449,10 @@ public: virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; virtual bool SupportsCairo() const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const SAL_OVERRIDE; virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE; virtual void BeginPaint() SAL_OVERRIDE; diff --git a/vcl/quartz/cairo_quartz_cairo.cxx b/vcl/quartz/cairo_quartz_cairo.cxx new file mode 100644 index 000000000000..b3a05541c438 --- /dev/null +++ b/vcl/quartz/cairo_quartz_cairo.cxx @@ -0,0 +1,260 @@ +/* -*- 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 +/************************************************************************ + * Mac OS X/Quartz and iOS surface backend for LibreOffice Cairo Canvas * + ************************************************************************/ + +#include <osl/diagnose.h> +#include <vcl/sysdata.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/virdev.hxx> + +#include "cairo_cairo.hxx" + +#include <config_cairo_canvas.h> + +#include "cairo_quartz_cairo.hxx" + +namespace cairo +{ + /** + * QuartzSurface::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 QuartzSurface::getSimilar() + * + * Set the mpSurface to the new surface or NULL + **/ + QuartzSurface::QuartzSurface( const CairoSurfaceSharedPtr& pSurface ) : + mpView(NULL), + mpSurface( pSurface ) + { + // Necessary, context is lost otherwise + CGContextRetain( getCGContext() ); // == NULL for non-native surfaces + } + + /** + * QuartzSurface::Surface: Create Canvas surface from Window reference. + * @param NSView + * @param x horizontal location of the new surface + * @param y vertical location of the new surface + * @param width width of the new surface + * @param height height 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 + **/ + QuartzSurface::QuartzSurface( NSView* pView, int x, int y, int width, int height ) : + mpView(pView), + mpSurface() + { + OSL_TRACE("Canvas::cairo::Surface(NSView*, x:%d, y:%d, w:%d, h:%d): New Surface for window", x, y, width, height); + + // on Mac OS X / Quartz we are not drawing directly to the screen, but via regular CGContextRef. + // The actual drawing to NSView (i.e. screen) is done in QuartzSurface::flush() + + // HACK: currently initial size for windowsurface is 0x0, which is not possible for us. + if (width == 0 || height == 0) { + width = [mpView bounds].size.width; + height = [mpView bounds].size.height; + OSL_TRACE("Canvas::cairo::Surface(): BUG!! size is ZERO! fixing to %d x %d...", width, height); + } + + // create a generic surface, NSView/Window is ARGB32. + mpSurface.reset( + cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, width, height), + &cairo_surface_destroy); + + cairo_surface_set_device_offset( mpSurface.get(), x, y ); + } + + /** + * QuartzSurface::Surface: Create Canvas surface from CGContextRef. + * @param CGContext Native graphics context + * @param x horizontal location of the new surface + * @param y vertical location of the new surface + * @param width width of the new surface + * @param height height of the new surface + * + * Set the mpSurface to the new surface or NULL + **/ + QuartzSurface::QuartzSurface( CGContextRef rContext, int x, int y, int width, int height ) : + mpView(NULL), + mpSurface() + { + OSL_TRACE("Canvas::cairo::Surface(CGContext:%p, x:%d, y:%d, w:%d, h:%d): New Surface.", rContext, x, y, width, height); + // create surface based on CGContext + + // ensure kCGBitmapByteOrder32Host flag, otherwise Cairo breaks (we are practically always using CGBitmapContext) + OSL_ASSERT ((CGBitmapContextGetBitsPerPixel(rContext) != 32) || + (CGBitmapContextGetBitmapInfo(rContext) & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host); + + mpSurface.reset(cairo_quartz_surface_create_for_cg_context(rContext, width, height), + &cairo_surface_destroy); + + cairo_surface_set_device_offset( mpSurface.get(), x, y ); + + // Necessary, context is lost otherwise + CGContextRetain(rContext); + } + + + /** + * QuartzSurface::getCairo: Create Cairo (drawing object) for the Canvas surface + * + * @return new Cairo or NULL + **/ + CairoSharedPtr QuartzSurface::getCairo() const + { + if (mpSurface.get()) + { + return CairoSharedPtr( cairo_create(mpSurface.get()), + &cairo_destroy ); + } + else + { + return CairoSharedPtr(); + } + } + + /** + * QuartzSurface::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 QuartzSurface::getSimilar( Content aContent, int width, int height ) const + { + return SurfaceSharedPtr( + new QuartzSurface( + CairoSurfaceSharedPtr( + cairo_surface_create_similar( mpSurface.get(), aContent, width, height ), + &cairo_surface_destroy ))); + } + + /** + * QuartzSurface::flush: Draw the data to screen + **/ + void QuartzSurface::flush() const + { + // can only flush surfaces with NSView + if( !mpView ) + return; + + OSL_TRACE("Canvas::cairo::QuartzSurface::flush(): flush to NSView"); + + CGContextRef mrContext = getCGContext(); + + if (!mrContext) + return; +#ifndef IOS + [mpView lockFocus]; +#endif + +#ifndef IOS + /** + * This code is using same screen update code as in VCL (esp. AquaSalGraphics::UpdateWindow() ) + */ + CGContextRef rViewContext = reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); +#else + // Just guessing for now... + CGContextRef rViewContext = UIGraphicsGetCurrentContext(); +#endif + CGImageRef xImage = CGBitmapContextCreateImage(mrContext); + CGContextDrawImage(rViewContext, + CGRectMake( 0, 0, + CGImageGetWidth(xImage), + CGImageGetHeight(xImage)), + xImage); + CGImageRelease( xImage ); + CGContextFlush( rViewContext ); +#ifndef IOS + [mpView unlockFocus]; +#endif + } + + /** + * QuartzSurface::getDepth: Get the color depth of the Canvas surface. + * + * @return color depth + **/ + int QuartzSurface::getDepth() const + { + if (mpSurface.get()) + { + 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::QuartzSurface::getDepth(): ERROR - depth unspecified!"); + + return -1; + } + + /** + * QuartzSurface::getCGContext: Get the native CGContextRef of the Canvas's cairo surface + * + * @return graphics context + **/ + CGContextRef QuartzSurface::getCGContext() const + { + if (mpSurface.get()) + return cairo_quartz_surface_get_cg_context(mpSurface.get()); + else + return NULL; + } + + /** + * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface + * + * @return The new virtual device + **/ + boost::shared_ptr<VirtualDevice> QuartzSurface::createVirtualDevice() const + { + SystemGraphicsData aSystemGraphicsData; + aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); + aSystemGraphicsData.rCGContext = getCGContext(); + return boost::shared_ptr<VirtualDevice>( + new VirtualDevice( &aSystemGraphicsData, Size(1, 1), getDepth() )); + } + +} // namespace cairo + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/cairo_quartz_cairo.hxx b/vcl/quartz/cairo_quartz_cairo.hxx new file mode 100644 index 000000000000..a3f94d20abf3 --- /dev/null +++ b/vcl/quartz/cairo_quartz_cairo.hxx @@ -0,0 +1,70 @@ +/* -*- 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_QUARTZ_CAIRO_HXX +#define INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_QUARTZ_CAIRO_HXX + +#include "cairo_cairo.hxx" + +#include "premac.h" +#include <TargetConditionals.h> +#if !defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE +# include <Cocoa/Cocoa.h> +#else +# include <UIKit/UIKit.h> +# define NSView UIView +#endif +#include <cairo-quartz.h> +#include "postmac.h" + +namespace cairo { + + class QuartzSurface : public Surface + { + NSView* mpView; // if NULL - bg surface + CairoSurfaceSharedPtr mpSurface; + + public: + /// takes over ownership of passed cairo_surface + explicit QuartzSurface( const CairoSurfaceSharedPtr& pSurface ); + + /// create surface on subarea of given CGContext + explicit QuartzSurface( CGContextRef rContext, int x, int y, int width, int height ); + + /// create a offscreen surface for given NSView + QuartzSurface( NSView* pView, int x, int y, int width, int height ); + + // Surface interface + virtual CairoSharedPtr getCairo() const; + virtual CairoSurfaceSharedPtr getCairoSurface() const { return mpSurface; } + virtual SurfaceSharedPtr getSimilar( Content aContent, int width, int height ) const; + + virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const; + + virtual void flush() const; + + int getDepth() const; + + CGContextRef getCGContext() const; + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx index b982dd4ff7bb..febf2fdc569a 100644 --- a/vcl/quartz/salgdicommon.cxx +++ b/vcl/quartz/salgdicommon.cxx @@ -39,6 +39,11 @@ #include <vcl/sysdata.hxx> #endif +#include <config_cairo_canvas.h> +#if ENABLE_CAIRO_CANVAS +#include "cairo_quartz_cairo.hxx" +#endif + #if defined(IOS) && defined(DBG_UTIL) // Variables in TiledView.m @@ -1447,7 +1452,115 @@ SystemGraphicsData AquaSalGraphics::GetGraphicsData() const bool AquaSalGraphics::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 AquaSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const +{ +#if ENABLE_CAIRO_CANVAS + return cairo::SurfaceSharedPtr(new cairo::QuartzSurface(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 AquaSalGraphics::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) + surf = cairo::SurfaceSharedPtr(new cairo::QuartzSurface(pSysData->pView, x, y, width, height)); + } + else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) + { + SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData(); + + if (aSysData.rCGContext) + surf = cairo::SurfaceSharedPtr(new cairo::QuartzSurface(aSysData.rCGContext, x, y, width, height)); + } +#else + (void)rRefDevice; + (void)x; + (void)y; + (void)width; + (void)height; +#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 AquaSalGraphics::CreateBitmapSurface( const OutputDevice& /* rRefDevice */, + const BitmapSystemData& rData, + const Size& rSize ) const +{ +#if ENABLE_CAIRO_CANVAS + OSL_TRACE( "requested size: %d x %d available size: %d x %d", + rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); + + if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) + { + CGContextRef rContext = (CGContextRef)rData.rImageContext; + OSL_TRACE("Canvas::cairo::createBitmapSurface(): New native image surface, context = %p.", rData.rImageContext); + + return cairo::SurfaceSharedPtr(new cairo::QuartzSurface(rContext, 0, 0, rData.mnWidth, rData.mnHeight)); + } +#else + (void)rData; + (void)rSize; +#endif + return cairo::SurfaceSharedPtr(); +} + +css::uno::Any AquaSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& /*rSize*/) const +{ + sal_IntPtr handle; +#if ENABLE_CAIRO_CANVAS + cairo::QuartzSurface* pQuartzSurface = dynamic_cast<cairo::QuartzSurface*>(rSurface.get()); + OSL_ASSERT(pQuartzSurface); + handle = sal_IntPtr (pQuartzSurface->getCGContext()); +#else + handle = 0; + (void)rSurface; +#endif + css::uno::Sequence< css::uno::Any > args( 1 ); + args[0] = css::uno::Any( handle ); + return css::uno::Any( args ); } long AquaSalGraphics::GetGraphicsWidth() const diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx index c64fbfffcc84..0fe76778cd1e 100644 --- a/vcl/source/outdev/outdev.cxx +++ b/vcl/source/outdev/outdev.cxx @@ -64,6 +64,8 @@ #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <comphelper/processfactory.hxx> +#include <config_cairo_canvas.h> + #include <numeric> #include <stack> @@ -299,6 +301,7 @@ SystemGraphicsData OutputDevice::GetSystemGfxData() const bool OutputDevice::SupportsCairo() const { +#if ENABLE_CAIRO_CANVAS if (!mpGraphics) { if (!AcquireGraphics()) @@ -306,6 +309,49 @@ bool OutputDevice::SupportsCairo() const } return mpGraphics->SupportsCairo(); +#else + return false; +#endif +} + +cairo::SurfaceSharedPtr OutputDevice::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const +{ + if (!mpGraphics) + { + if (!AcquireGraphics()) + return cairo::SurfaceSharedPtr(); + } + return mpGraphics->CreateSurface(rSurface); +} + +cairo::SurfaceSharedPtr OutputDevice::CreateSurface(int x, int y, int width, int height) const +{ + if (!mpGraphics) + { + if (!AcquireGraphics()) + return cairo::SurfaceSharedPtr(); + } + return mpGraphics->CreateSurface(*this, x, y, width, height); +} + +cairo::SurfaceSharedPtr OutputDevice::CreateBitmapSurface(const BitmapSystemData& rData, const Size& rSize) const +{ + if (!mpGraphics) + { + if (!AcquireGraphics()) + return cairo::SurfaceSharedPtr(); + } + return mpGraphics->CreateBitmapSurface(*this, rData, rSize); +} + +css::uno::Any OutputDevice::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& rSize) const +{ + if (!mpGraphics) + { + if (!AcquireGraphics()) + return css::uno::Any(); + } + return mpGraphics->GetNativeSurfaceHandle(rSurface, rSize); } css::uno::Any OutputDevice::GetSystemGfxDataAny() const diff --git a/vcl/source/window/cairo_cairo.cxx b/vcl/source/window/cairo_cairo.cxx new file mode 100644 index 000000000000..a722c2e8d073 --- /dev/null +++ b/vcl/source/window/cairo_cairo.cxx @@ -0,0 +1,51 @@ +/* -*- 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 <vcl/sysdata.hxx> +#include <vcl/syschild.hxx> +#include "cairo_cairo.hxx" +#ifdef _WIN32 +#include <prewin.h> +#include <postwin.h> +#endif + +namespace cairo +{ + /*************************************************************************************** + * Platform independent part of surface backends for LibreOffice Cairo Canvas * + * For the rest of the functions (and the platform-specific derived * + * Surface classes), see platform specific cairo_<platform>_cairo.cxx * + ****************************************************************************************/ + + const SystemEnvData* GetSysData(const vcl::Window *pOutputWindow) + { + const SystemEnvData* pSysData = NULL; + // check whether we're a SysChild: have to fetch system data + // directly from SystemChildWindow, because the GetSystemData + // method is unfortunately not virtual + const SystemChildWindow* pSysChild = dynamic_cast< const SystemChildWindow* >( pOutputWindow ); + if( pSysChild ) + pSysData = pSysChild->GetSystemData(); + else + pSysData = pOutputWindow->GetSystemData(); + return pSysData; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx b/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx new file mode 100644 index 000000000000..3f063b37e8c7 --- /dev/null +++ b/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx @@ -0,0 +1,311 @@ +/* -*- 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 <utility> + +#include <prex.h> +#include <X11/extensions/Xrender.h> +#include <X11/Xlib.h> +#include <postx.h> + +#include "cairo_cairo.hxx" +#include "cairo_xlib_cairo.hxx" + +#include <vcl/sysdata.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/virdev.hxx> +#include <vcl/window.hxx> +#include <basegfx/vector/b2isize.hxx> + +namespace +{ + Pixmap limitXCreatePixmap(Display *display, Drawable d, unsigned int width, unsigned int height, unsigned int depth) + { + // The X protocol request CreatePixmap puts an upper bound + // of 16 bit to the size. And in practice some drivers + // fall over with values close to the max. + + // see, e.g. moz#424333, fdo#48961, rhbz#1086714 + // we've a duplicate of this in vcl :-( + if (width > SAL_MAX_INT16-10 || height > SAL_MAX_INT16-10) + { + SAL_WARN("canvas", "overlarge pixmap: " << width << " x " << height); + return None; + } + return XCreatePixmap(display, d, width, height, depth); + } +} + +namespace cairo +{ + +#include <cairo-xlib.h> +#include <cairo-xlib-xrender.h> + + X11SysData::X11SysData() : + pDisplay(NULL), + hDrawable(0), + pVisual(NULL), + nScreen(0), + nDepth(-1), + aColormap(-1), + pRenderFormat(NULL) + {} + + X11SysData::X11SysData( const SystemGraphicsData& pSysDat ) : + pDisplay(pSysDat.pDisplay), + hDrawable(pSysDat.hDrawable), + pVisual(pSysDat.pVisual), + nScreen(pSysDat.nScreen), + nDepth(pSysDat.nDepth), + aColormap(pSysDat.aColormap), + pRenderFormat(pSysDat.pXRenderFormat) + {} + + X11SysData::X11SysData( const SystemEnvData& pSysDat ) : + pDisplay(pSysDat.pDisplay), + hDrawable(pSysDat.aWindow), + pVisual(pSysDat.pVisual), + nScreen(pSysDat.nScreen), + nDepth(pSysDat.nDepth), + aColormap(pSysDat.aColormap), + pRenderFormat(NULL) + {} + + X11Pixmap::~X11Pixmap() + { + if( mpDisplay && mhDrawable ) + XFreePixmap( (Display*)mpDisplay, mhDrawable ); + } + + /** + * Surface::Surface: Create Canvas surface with existing data + * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) + * @param pSurface Cairo surface + * + * pSysData contains the platform native Drawable reference + * This constructor only stores data, it does no processing. + * It is used by e.g. Surface::getSimilar() + * + * Set the mpSurface as pSurface + **/ + X11Surface::X11Surface( const X11SysData& rSysData, + const X11PixmapSharedPtr& rPixmap, + const CairoSurfaceSharedPtr& pSurface ) : + maSysData(rSysData), + mpPixmap(rPixmap), + mpSurface(pSurface) + {} + + /** + * 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() + * Unlike other constructors, mpSysData is set to NULL + * + * Set the mpSurface as pSurface + **/ + X11Surface::X11Surface( const CairoSurfaceSharedPtr& pSurface ) : + maSysData(), + mpPixmap(), + 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 + * @param width width of the new surface + * @param height height 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 + **/ + X11Surface::X11Surface( const X11SysData& rSysData, int x, int y, int width, int height ) : + maSysData(rSysData), + mpPixmap(), + mpSurface( + cairo_xlib_surface_create( (Display*)rSysData.pDisplay, + rSysData.hDrawable, + (Visual*)rSysData.pVisual, + width + x, height + y ), + &cairo_surface_destroy) + { + cairo_surface_set_device_offset(mpSurface.get(), x, y ); + } + + /** + * Surface::Surface: Create platform native Canvas surface from BitmapSystemData + * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) + * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) + * @param width width of the new surface + * @param height height of the new surface + * + * The pBmpData provides the imagedata that the created surface should contain. + * + * Set the mpSurface to the new surface or NULL + **/ + X11Surface::X11Surface( const X11SysData& rSysData, + const BitmapSystemData& rData ) : + maSysData( rSysData ), + mpPixmap(), + mpSurface( + cairo_xlib_surface_create( (Display*)rSysData.pDisplay, + reinterpret_cast<Drawable>(rData.aPixmap), + (Visual*) rSysData.pVisual, + rData.mnWidth, rData.mnHeight ), + &cairo_surface_destroy) + { + } + + /** + * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface + * + * @return new Cairo or NULL + **/ + CairoSharedPtr X11Surface::getCairo() const + { + return CairoSharedPtr( cairo_create(mpSurface.get()), + &cairo_destroy ); + } + + /** + * Surface::getSimilar: Create new similar Canvas surface + * @param cairo_content_type 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 cairo_content_type (cairo_content_t) + * + * @return new surface or NULL + **/ + SurfaceSharedPtr X11Surface::getSimilar(int cairo_content_type, int width, int height ) const + { + Pixmap hPixmap; + + if( maSysData.pDisplay && maSysData.hDrawable ) + { + XRenderPictFormat* pFormat; + int nFormat; + + switch (cairo_content_type) + { + case CAIRO_CONTENT_ALPHA: + nFormat = PictStandardA8; + break; + case CAIRO_CONTENT_COLOR: + nFormat = PictStandardRGB24; + break; + case CAIRO_CONTENT_COLOR_ALPHA: + default: + nFormat = PictStandardARGB32; + break; + } + + pFormat = XRenderFindStandardFormat( (Display*)maSysData.pDisplay, nFormat ); + hPixmap = limitXCreatePixmap( (Display*)maSysData.pDisplay, maSysData.hDrawable, + width > 0 ? width : 1, height > 0 ? height : 1, + pFormat->depth ); + + X11SysData aSysData(maSysData); + aSysData.pRenderFormat = pFormat; + return SurfaceSharedPtr( + new X11Surface( aSysData, + X11PixmapSharedPtr( + new X11Pixmap(hPixmap, maSysData.pDisplay)), + CairoSurfaceSharedPtr( + cairo_xlib_surface_create_with_xrender_format( + (Display*)maSysData.pDisplay, + hPixmap, + ScreenOfDisplay((Display *)maSysData.pDisplay, maSysData.nScreen), + pFormat, width, height ), + &cairo_surface_destroy) )); + } + else + return SurfaceSharedPtr( + new X11Surface( maSysData, + X11PixmapSharedPtr(), + CairoSurfaceSharedPtr( + cairo_surface_create_similar( mpSurface.get(), + static_cast<cairo_content_t>(cairo_content_type), width, height ), + &cairo_surface_destroy ))); + } + + boost::shared_ptr<VirtualDevice> X11Surface::createVirtualDevice() const + { + SystemGraphicsData aSystemGraphicsData; + + aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); + aSystemGraphicsData.hDrawable = getDrawable(); + aSystemGraphicsData.pXRenderFormat = getRenderFormat(); + + int width = cairo_xlib_surface_get_width(mpSurface.get()); + int height = cairo_xlib_surface_get_height(mpSurface.get()); + + return boost::shared_ptr<VirtualDevice>( + new VirtualDevice(&aSystemGraphicsData, + Size(width, height), + std::max(getDepth(), 0))); + } + + /** + * Surface::Resize: Resizes the Canvas surface. + * @param width new width of the surface + * @param height new height of the surface + * + * Only used on X11. + * + * @return The new surface or NULL + **/ + bool X11Surface::Resize(int width, int height) + { + cairo_xlib_surface_set_size(mpSurface.get(), width, height); + return true; + } + + void X11Surface::flush() const + { + XSync( (Display*)maSysData.pDisplay, false ); + } + + /** + * Surface::getDepth: Get the color depth of the Canvas surface. + * + * @return color depth + **/ + int X11Surface::getDepth() const + { + if( maSysData.pRenderFormat ) + return ((XRenderPictFormat*) maSysData.pRenderFormat)->depth; + + return -1; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/cairo_xlib_cairo.hxx b/vcl/unx/generic/gdi/cairo_xlib_cairo.hxx new file mode 100644 index 000000000000..076f34f2676c --- /dev/null +++ b/vcl/unx/generic/gdi/cairo_xlib_cairo.hxx @@ -0,0 +1,105 @@ +/* -*- 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_XLIB_CAIRO_HXX +#define INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_XLIB_CAIRO_HXX + +#include <sal/config.h> + +#include <sal/types.h> + +#include <vcl/cairo.hxx> + +class BitmapSystemData; +struct SystemEnvData; +struct SystemGraphicsData; + +namespace cairo { + + /// Holds all X11-output relevant data + struct X11SysData + { + X11SysData(); + explicit X11SysData( const SystemGraphicsData& ); + explicit X11SysData( const SystemEnvData& ); + + void* pDisplay; // the relevant display connection + long hDrawable; // a drawable + void* pVisual; // the visual in use + int nScreen; // the current screen of the drawable + int nDepth; // depth of said visual + long aColormap; // the colormap being used + void* pRenderFormat; // render format for drawable + }; + + /// RAII wrapper for a pixmap + struct X11Pixmap + { + void* mpDisplay; // the relevant display connection + long mhDrawable; // a drawable + + X11Pixmap( long hDrawable, void* pDisplay ) : + mpDisplay(pDisplay), + mhDrawable(hDrawable) + {} + + ~X11Pixmap(); + + void clear() { mpDisplay=NULL; mhDrawable=0; } + }; + + typedef boost::shared_ptr<X11Pixmap> X11PixmapSharedPtr; + + class X11Surface : public Surface + { + const X11SysData maSysData; + X11PixmapSharedPtr mpPixmap; + CairoSurfaceSharedPtr mpSurface; + + X11Surface( const X11SysData& rSysData, const X11PixmapSharedPtr& rPixmap, const CairoSurfaceSharedPtr& pSurface ); + + public: + /// takes over ownership of passed cairo_surface + explicit X11Surface( const CairoSurfaceSharedPtr& pSurface ); + /// create surface on subarea of given drawable + X11Surface( const X11SysData& rSysData, int x, int y, int width, int height ); + /// create surface for given bitmap data + X11Surface( const X11SysData& rSysData, const BitmapSystemData& rBmpData ); + + // Surface interface + virtual CairoSharedPtr getCairo() const SAL_OVERRIDE; + virtual CairoSurfaceSharedPtr getCairoSurface() const SAL_OVERRIDE { return mpSurface; } + virtual SurfaceSharedPtr getSimilar(int cairo_content_type, int width, int height) const SAL_OVERRIDE; + + virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const SAL_OVERRIDE; + + virtual bool Resize( int width, int height ) SAL_OVERRIDE; + + virtual void flush() const SAL_OVERRIDE; + + int getDepth() const; + X11PixmapSharedPtr getPixmap() const { return mpPixmap; } + void* getRenderFormat() const { return maSysData.pRenderFormat; } + long getDrawable() const { return mpPixmap ? mpPixmap->mhDrawable : maSysData.hDrawable; } + }; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index 5b861cac7f1a..ee68a0cac9da 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -40,7 +40,8 @@ #include "basegfx/polygon/b2dpolypolygoncutter.hxx" #include "basegfx/polygon/b2dtrapezoid.hxx" -#include "vcl/jobdata.hxx" +#include <vcl/jobdata.hxx> +#include <vcl/virdev.hxx> #include "unx/salunx.h" #include "unx/saldata.hxx" @@ -61,6 +62,8 @@ #include "generic/printergfx.hxx" #include "xrender_peer.hxx" +#include "cairo_cairo.hxx" +#include "cairo_xlib_cairo.hxx" #include <vcl/opengl/OpenGLHelper.hxx> @@ -456,6 +459,71 @@ bool X11SalGraphics::SupportsCairo() const return XQueryExtension(pDisplay, "RENDER", &nDummy, &nDummy, &nDummy); } +cairo::SurfaceSharedPtr X11SalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const +{ + return cairo::SurfaceSharedPtr(new cairo::X11Surface(rSurface)); +} + +namespace +{ + static cairo::X11SysData getSysData( const vcl::Window& rWindow ) + { + const SystemEnvData* pSysData = cairo::GetSysData(&rWindow); + + if( !pSysData ) + return cairo::X11SysData(); + else + return cairo::X11SysData(*pSysData); + } + + static cairo::X11SysData getSysData( const VirtualDevice& rVirDev ) + { + return cairo::X11SysData( rVirDev.GetSystemGfxData() ); + } +} + +cairo::SurfaceSharedPtr X11SalGraphics::CreateSurface( const OutputDevice& rRefDevice, + int x, int y, int width, int height ) const +{ + if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) + return cairo::SurfaceSharedPtr(new cairo::X11Surface(getSysData(static_cast<const vcl::Window&>(rRefDevice)), + x,y,width,height)); + if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) + return cairo::SurfaceSharedPtr(new cairo::X11Surface(getSysData(static_cast<const VirtualDevice&>(rRefDevice)), + x,y,width,height)); + return cairo::SurfaceSharedPtr(); +} + +cairo::SurfaceSharedPtr X11SalGraphics::CreateBitmapSurface( const OutputDevice& rRefDevice, + const BitmapSystemData& rData, + const Size& rSize ) const +{ + SAL_INFO( + "canvas.cairo", + "requested size: " << rSize.Width() << " x " << rSize.Height() + << " available size: " << rData.mnWidth << " x " + << rData.mnHeight); + if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) + { + if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) + return cairo::SurfaceSharedPtr(new cairo::X11Surface(getSysData(static_cast<const vcl::Window&>(rRefDevice)), rData )); + else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) + return cairo::SurfaceSharedPtr(new cairo::X11Surface(getSysData(static_cast<const VirtualDevice&>(rRefDevice)), rData )); + } + + return cairo::SurfaceSharedPtr(); +} + +css::uno::Any X11SalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const ::basegfx::B2ISize& /*rSize*/) const +{ + cairo::X11Surface& rXlibSurface=dynamic_cast<cairo::X11Surface&>(*rSurface.get()); + css::uno::Sequence< css::uno::Any > args( 3 ); + args[0] = css::uno::Any( false ); // do not call XFreePixmap on it + args[1] = css::uno::Any( rXlibSurface.getPixmap()->mhDrawable ); + args[2] = css::uno::Any( sal_Int32( rXlibSurface.getDepth() ) ); + return css::uno::Any(args); +} + // draw a poly-polygon bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency ) { 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() |