Repository.mk | 3 bin/find-can-be-private-symbols.functions.results | 2 bin/find-mergedlib-can-be-private-symbols.functions.results | 6 canvas/Library_cairocanvas.mk | 75 canvas/Library_directx9canvas.mk | 69 canvas/Library_gdipluscanvas.mk | 60 canvas/Module_canvas.mk | 14 canvas/StaticLibrary_directxcanvas.mk | 41 canvas/inc/pch/precompiled_cairocanvas.hxx | 89 canvas/source/cairo/cairo_cachedbitmap.cxx | 77 canvas/source/cairo/cairo_cachedbitmap.hxx | 58 canvas/source/cairo/cairo_canvas.cxx | 189 + canvas/source/cairo/cairo_canvas.hxx | 142 canvas/source/cairo/cairo_canvasbitmap.cxx | 163 canvas/source/cairo/cairo_canvasbitmap.hxx | 125 canvas/source/cairo/cairo_canvascustomsprite.cxx | 151 canvas/source/cairo/cairo_canvascustomsprite.hxx | 145 canvas/source/cairo/cairo_canvasfont.cxx | 161 canvas/source/cairo/cairo_canvasfont.hxx | 84 canvas/source/cairo/cairo_canvashelper.cxx | 2045 ++++++++++++ canvas/source/cairo/cairo_canvashelper.hxx | 271 + canvas/source/cairo/cairo_canvashelper_text.cxx | 303 + canvas/source/cairo/cairo_devicehelper.cxx | 257 + canvas/source/cairo/cairo_devicehelper.hxx | 122 canvas/source/cairo/cairo_repainttarget.hxx | 48 canvas/source/cairo/cairo_sprite.hxx | 65 canvas/source/cairo/cairo_spritecanvas.cxx | 232 + canvas/source/cairo/cairo_spritecanvas.hxx | 159 canvas/source/cairo/cairo_spritecanvashelper.cxx | 518 +++ canvas/source/cairo/cairo_spritecanvashelper.hxx | 140 canvas/source/cairo/cairo_spritedevicehelper.cxx | 153 canvas/source/cairo/cairo_spritedevicehelper.hxx | 77 canvas/source/cairo/cairo_spritehelper.cxx | 195 + canvas/source/cairo/cairo_spritehelper.hxx | 102 canvas/source/cairo/cairo_surfaceprovider.hxx | 70 canvas/source/cairo/cairo_textlayout.cxx | 363 ++ canvas/source/cairo/cairo_textlayout.hxx | 107 canvas/source/cairo/cairocanvas.component | 30 canvas/source/directx/directx9canvas.component | 26 canvas/source/directx/dx_9rm.cxx | 1201 +++++++ canvas/source/directx/dx_bitmap.cxx | 204 + canvas/source/directx/dx_bitmap.hxx | 82 canvas/source/directx/dx_bitmapcanvashelper.cxx | 221 + canvas/source/directx/dx_bitmapcanvashelper.hxx | 126 canvas/source/directx/dx_bitmapprovider.hxx | 34 canvas/source/directx/dx_canvas.cxx | 256 + canvas/source/directx/dx_canvas.hxx | 173 + canvas/source/directx/dx_canvasbitmap.cxx | 257 + canvas/source/directx/dx_canvasbitmap.hxx | 91 canvas/source/directx/dx_canvascustomsprite.cxx | 106 canvas/source/directx/dx_canvascustomsprite.hxx | 130 canvas/source/directx/dx_canvasfont.cxx | 162 canvas/source/directx/dx_canvasfont.hxx | 92 canvas/source/directx/dx_canvashelper.cxx | 813 ++++ canvas/source/directx/dx_canvashelper.hxx | 252 + canvas/source/directx/dx_canvashelper_texturefill.cxx | 608 +++ canvas/source/directx/dx_config.cxx | 152 canvas/source/directx/dx_config.hxx | 80 canvas/source/directx/dx_devicehelper.cxx | 198 + canvas/source/directx/dx_devicehelper.hxx | 114 canvas/source/directx/dx_gdiplususer.cxx | 74 canvas/source/directx/dx_gdiplususer.hxx | 45 canvas/source/directx/dx_graphicsprovider.hxx | 46 canvas/source/directx/dx_ibitmap.hxx | 62 canvas/source/directx/dx_impltools.cxx | 629 +++ canvas/source/directx/dx_impltools.hxx | 124 canvas/source/directx/dx_linepolypolygon.cxx | 59 canvas/source/directx/dx_linepolypolygon.hxx | 47 canvas/source/directx/dx_rendermodule.hxx | 80 canvas/source/directx/dx_sprite.hxx | 45 canvas/source/directx/dx_spritecanvas.cxx | 192 + canvas/source/directx/dx_spritecanvas.hxx | 155 canvas/source/directx/dx_spritecanvashelper.cxx | 352 ++ canvas/source/directx/dx_spritecanvashelper.hxx | 152 canvas/source/directx/dx_spritedevicehelper.cxx | 221 + canvas/source/directx/dx_spritedevicehelper.hxx | 98 canvas/source/directx/dx_spritehelper.cxx | 199 + canvas/source/directx/dx_spritehelper.hxx | 102 canvas/source/directx/dx_surfacebitmap.cxx | 654 +++ canvas/source/directx/dx_surfacebitmap.hxx | 135 canvas/source/directx/dx_surfacegraphics.cxx | 77 canvas/source/directx/dx_surfacegraphics.hxx | 36 canvas/source/directx/dx_textlayout.cxx | 253 + canvas/source/directx/dx_textlayout.hxx | 107 canvas/source/directx/dx_textlayout_drawhelper.cxx | 312 + canvas/source/directx/dx_textlayout_drawhelper.hxx | 78 canvas/source/directx/dx_vcltools.cxx | 309 + canvas/source/directx/dx_vcltools.hxx | 47 canvas/source/directx/dx_winstuff.hxx | 71 canvas/source/directx/gdipluscanvas.component | 30 compilerplugins/clang/unusedfields.readonly.results | 4 compilerplugins/clang/virtualdead.unusedparams.results | 3 cppcanvas/CppunitTest_cppcanvas_emfplus.mk | 1 cppcanvas/CppunitTest_cppcanvas_test.mk | 1 include/vcl/BitmapTools.hxx | 6 include/vcl/bitmap.hxx | 21 include/vcl/cairo.hxx | 35 include/vcl/outdev.hxx | 10 include/vcl/sysdata.hxx | 10 include/vcl/virdev.hxx | 9 officecfg/registry/data/org/openoffice/Office/Canvas.xcu | 21 solenv/gbuild/extensions/pre_MergedLibsList.mk | 3 vcl/Library_vclplug_gen.mk | 1 vcl/Library_vclplug_gtk3.mk | 1 vcl/Library_vclplug_gtk3_kde5.mk | 1 vcl/Library_vclplug_gtk4.mk | 1 vcl/Library_vclplug_qt5.mk | 1 vcl/Library_vclplug_qt6.mk | 1 vcl/headless/svpbmp.cxx | 5 vcl/headless/svpgdi.cxx | 28 vcl/headless/svpinst.cxx | 23 vcl/inc/headless/svpbmp.hxx | 1 vcl/inc/headless/svpgdi.hxx | 8 vcl/inc/headless/svpinst.hxx | 9 vcl/inc/osx/salinst.h | 5 vcl/inc/qt5/QtBitmap.hxx | 1 vcl/inc/qt5/QtGraphics.hxx | 13 vcl/inc/qt5/QtInstance.hxx | 4 vcl/inc/qt5/QtSvpGraphics.hxx | 10 vcl/inc/qt5/QtSvpSurface.hxx | 44 vcl/inc/qt6/QtSvpSurface.hxx | 12 vcl/inc/quartz/salbmp.h | 2 vcl/inc/quartz/salvd.h | 1 vcl/inc/salbmp.hxx | 2 vcl/inc/salgdi.hxx | 14 vcl/inc/salinst.hxx | 9 vcl/inc/skia/salbmp.hxx | 2 vcl/inc/skia/x11/salvd.hxx | 3 vcl/inc/unx/genpspgraphics.h | 8 vcl/inc/unx/gtk/gtkgdi.hxx | 8 vcl/inc/unx/gtk/gtkinst.hxx | 5 vcl/inc/unx/salgdi.h | 8 vcl/inc/unx/salinst.h | 6 vcl/inc/unx/salvd.h | 2 vcl/inc/win/salbmp.h | 1 vcl/inc/win/salinst.h | 4 vcl/qt5/QtBitmap.cxx | 2 vcl/qt5/QtGraphics.cxx | 31 vcl/qt5/QtInstance.cxx | 23 vcl/qt5/QtSvpGraphics.cxx | 28 vcl/qt5/QtSvpSurface.cxx | 91 vcl/qt6/QtSvpSurface.cxx | 12 vcl/quartz/salbmp.cxx | 60 vcl/quartz/salvd.cxx | 59 vcl/skia/salbmp.cxx | 8 vcl/skia/x11/salvd.cxx | 18 vcl/source/bitmap/BitmapTools.cxx | 336 + vcl/source/bitmap/bitmap.cxx | 6 vcl/source/gdi/virdev.cxx | 22 vcl/source/outdev/outdev.cxx | 45 vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx | 1 vcl/unx/generic/gdi/cairo_xlib_cairo.cxx | 277 + vcl/unx/generic/gdi/cairo_xlib_cairo.hxx | 93 vcl/unx/generic/gdi/salgdi.cxx | 77 vcl/unx/generic/gdi/salvd.cxx | 82 vcl/unx/generic/print/genpspgraphics.cxx | 29 vcl/unx/gtk3/gtkcairo.cxx | 129 vcl/unx/gtk3/gtkcairo.hxx | 46 vcl/unx/gtk3/gtkinst.cxx | 16 vcl/unx/gtk3/salnativewidgets-gtk.cxx | 26 vcl/unx/gtk3_kde5/gtk3_kde5_cairo.cxx | 22 vcl/unx/gtk4/gtkcairo.cxx | 12 vcl/unx/gtk4/gtkcairo.hxx | 12 vcl/win/gdi/salbmp.cxx | 14 vcl/win/gdi/salvd.cxx | 31 vcl/win/window/salframe.cxx | 3 166 files changed, 19047 insertions(+), 12 deletions(-)
New commits: commit 5357da349b4b266b4003d25b61ecb12a515893c4 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Fri Feb 21 08:52:56 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Fri Feb 21 10:40:31 2025 +0100 Revert "remove canvas/cairo and canvas/gdi and canvas/directx backends" So the vclcanvas backend is in worse shape than I thought. It will take too long to get it into shape to be sure of making the next release, so revert this for now, and I will have to find another approach. This reverts the following commits commit fbefe07e4c4a8959278ea08a247d75612994727c Author: Michael Weghorn <m.wegh...@posteo.de> Date: Thu Feb 20 09:42:14 2025 +0100 qt: Remove now unused vcl/inc/qt6/QtSvpSurface.hxx commit 595354ab7e01546765d84103aaf2bc38e5d3c9b3 Author: Julien Nabet <serval2...@yahoo.fr> Date: Wed Feb 19 21:13:49 2025 +0100 Remove also canvas/cairo in gtk4, qt6 and gtk3_kde5 commit d539f6e99e1be89e6133b2ef623c67bf4f0cff4f Author: Noel Grandin <noelgran...@gmail.com> Date: Wed Feb 19 18:15:30 2025 +0200 fix "local variable is unused" warning commit 704f61b1bd2c54831c383e34e74315bd6da356e2 Author: Noel Grandin <noelgran...@collabora.co.uk> Date: Wed Jan 29 15:35:21 2025 +0200 remove canvas/cairo and canvas/gdi and canvas/directx backends Change-Id: I0492dabf7da8c42a15720c868f161919e8dc7ae4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181984 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/Repository.mk b/Repository.mk index fb074d489aae..277a1fb99b8b 100644 --- a/Repository.mk +++ b/Repository.mk @@ -355,9 +355,12 @@ endif ifneq ($(ENABLE_WASM_STRIP_CANVAS),TRUE) $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ canvastools \ + $(if $(ENABLE_CAIRO_CANVAS),cairocanvas) \ canvasfactory \ cppcanvas \ + $(if $(filter WNT,$(OS)),directx9canvas) \ $(if $(ENABLE_OPENGL_CANVAS),oglcanvas) \ + $(if $(filter WNT,$(OS)),gdipluscanvas) \ simplecanvas \ vclcanvas \ )) diff --git a/bin/find-can-be-private-symbols.functions.results b/bin/find-can-be-private-symbols.functions.results index 5dbaf427cb17..ed4b5100cec2 100644 --- a/bin/find-can-be-private-symbols.functions.results +++ b/bin/find-can-be-private-symbols.functions.results @@ -1670,6 +1670,7 @@ QtSvpGraphics::CreateSurface(OutputDevice const&, int, int, int, int) const QtSvpGraphics::CreateSurface(std::shared_ptr<_cairo_surface> const&) const QtSvpGraphics::GetResolution(int&, int&) QtSvpGraphics::QtSvpGraphics(QtFrame*) +QtSvpGraphics::SupportsCairo() const QtSvpGraphics::handleDamage(tools::Rectangle const&) QtSvpGraphics::updateQWidget() const QtSvpGraphics::~QtSvpGraphics() @@ -5770,6 +5771,7 @@ SkiaSalBitmap::GetAsSkBitmap() const SkiaSalBitmap::GetBitCount() const SkiaSalBitmap::GetImageKey(SkiaHelper::DirectImage) const SkiaSalBitmap::GetSkShader(SkSamplingOptions const&, SkiaHelper::DirectImage) const +SkiaSalBitmap::GetSystemData(BitmapSystemData&) SkiaSalBitmap::Invert() SkiaSalBitmap::IsAllBlack() const SkiaSalBitmap::IsFullyOpaqueAsAlpha() const diff --git a/bin/find-mergedlib-can-be-private-symbols.functions.results b/bin/find-mergedlib-can-be-private-symbols.functions.results index cbdb7c75b544..51f40068f0f0 100644 --- a/bin/find-mergedlib-can-be-private-symbols.functions.results +++ b/bin/find-mergedlib-can-be-private-symbols.functions.results @@ -82,6 +82,7 @@ BigInt::operator%=(BigInt const&) BigInt::operator=(BigInt const&) Bitmap::CreateAlphaMask(Color const&) const Bitmap::CreateMask(Color const&) const +Bitmap::GetSystemData(BitmapSystemData&) const Bitmap::RemoveBlendedStartColor(Color const&, AlphaMask const&) BitmapBasicMorphologyFilter::BitmapBasicMorphologyFilter(BasicMorphologyOp, int, unsigned char) BitmapBasicMorphologyFilter::filter(Bitmap const&) const @@ -1786,6 +1787,7 @@ OutlinerView::Indent(short) OutputDevice::AddFontSubstitute(rtl::OUString const&, rtl::OUString const&, AddFontSubstituteFlags) OutputDevice::AddHatchActions(tools::PolyPolygon const&, Hatch const&, GDIMetaFile&) OutputDevice::BeginFontSubstitution() +OutputDevice::CreateBitmapSurface(BitmapSystemData const&, Size const&) const OutputDevice::CreateSurface(int, int, int, int) const OutputDevice::CreateSurface(std::shared_ptr<_cairo_surface> const&) const OutputDevice::CreateUnoGraphicsList() @@ -1799,6 +1801,7 @@ OutputDevice::GetGlyphBoundRects(Point const&, rtl::OUString const&, int, int, s OutputDevice::GetGraphics() const OutputDevice::GetInverseViewTransformation(MapMode const&) const OutputDevice::GetNativeControlRegion(ControlType, ControlPart, tools::Rectangle const&, ControlState, ImplControlValue const&, tools::Rectangle&, tools::Rectangle&) const +OutputDevice::GetNativeSurfaceHandle(std::shared_ptr<cairo::Surface>&, basegfx::B2ISize const&) const OutputDevice::GetRenderBackendName() const OutputDevice::GetSpriteCanvas() const OutputDevice::GetTextBoundRect(basegfx::B2DRange&, rtl::OUString const&, int, int, int, unsigned long, KernArraySpan, std::span<unsigned char const, 18446744073709551615ul>, SalLayoutGlyphs const*) const @@ -1817,6 +1820,7 @@ OutputDevice::PixelToLogic(vcl::Region const&) const OutputDevice::RefreshFontData(bool) OutputDevice::RemoveFontsSubstitute() OutputDevice::RemoveTransparenciesFromMetaFile(GDIMetaFile const&, GDIMetaFile&, long, long, bool, bool, bool, Color const&) +OutputDevice::SupportsCairo() const PDFSignatureHelper::GetNewSecurityId() const PDFSignatureHelper::ReadAndVerifySignature(com::sun::star::uno::Reference<com::sun::star::io::XInputStream> const&) PDFSignatureHelper::SetDescription(rtl::OUString const&) @@ -2008,6 +2012,7 @@ QtSvpGraphics::CreateSurface(OutputDevice const&, int, int, int, int) const QtSvpGraphics::CreateSurface(std::shared_ptr<_cairo_surface> const&) const QtSvpGraphics::GetResolution(int&, int&) QtSvpGraphics::QtSvpGraphics(QtFrame*) +QtSvpGraphics::SupportsCairo() const QtSvpGraphics::handleDamage(tools::Rectangle const&) QtSvpGraphics::updateQWidget() const QtSvpGraphics::~QtSvpGraphics() @@ -6022,6 +6027,7 @@ SkiaSalBitmap::GetAsSkBitmap() const SkiaSalBitmap::GetBitCount() const SkiaSalBitmap::GetImageKey(SkiaHelper::DirectImage) const SkiaSalBitmap::GetSkShader(SkSamplingOptions const&, SkiaHelper::DirectImage) const +SkiaSalBitmap::GetSystemData(BitmapSystemData&) SkiaSalBitmap::Invert() SkiaSalBitmap::IsAllBlack() const SkiaSalBitmap::IsFullyOpaqueAsAlpha() const diff --git a/canvas/Library_cairocanvas.mk b/canvas/Library_cairocanvas.mk new file mode 100644 index 000000000000..b7cd8d86b5f0 --- /dev/null +++ b/canvas/Library_cairocanvas.mk @@ -0,0 +1,75 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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 . +# + +$(eval $(call gb_Library_Library,cairocanvas)) + +$(eval $(call gb_Library_set_include,cairocanvas,\ + $$(INCLUDE) \ + -I$(SRCDIR)/canvas/inc \ +)) + +$(eval $(call gb_Library_set_precompiled_header,cairocanvas,canvas/inc/pch/precompiled_cairocanvas)) + +$(eval $(call gb_Library_set_componentfile,cairocanvas,canvas/source/cairo/cairocanvas,services)) + +$(eval $(call gb_Library_use_sdk_api,cairocanvas)) + +ifeq ($(OS),MACOSX) + +$(eval $(call gb_Library_use_system_darwin_frameworks,cairocanvas,\ + Cocoa \ +)) + +endif + +$(eval $(call gb_Library_use_libraries,cairocanvas,\ + sal \ + cppu \ + basegfx \ + cppuhelper \ + comphelper \ + vcl \ + tk \ + tl \ + i18nlangtag \ + canvastools \ +)) + +$(eval $(call gb_Library_add_exception_objects,cairocanvas,\ + canvas/source/cairo/cairo_cachedbitmap \ + canvas/source/cairo/cairo_canvas \ + canvas/source/cairo/cairo_canvasbitmap \ + canvas/source/cairo/cairo_canvascustomsprite \ + canvas/source/cairo/cairo_canvasfont \ + canvas/source/cairo/cairo_canvashelper \ + canvas/source/cairo/cairo_canvashelper_text \ + canvas/source/cairo/cairo_devicehelper \ + canvas/source/cairo/cairo_spritecanvas \ + canvas/source/cairo/cairo_spritecanvashelper \ + canvas/source/cairo/cairo_spritedevicehelper \ + canvas/source/cairo/cairo_spritehelper \ + canvas/source/cairo/cairo_textlayout \ +)) + +$(eval $(call gb_Library_use_externals,cairocanvas,\ + boost_headers \ + cairo \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/canvas/Library_directx9canvas.mk b/canvas/Library_directx9canvas.mk new file mode 100644 index 000000000000..4369de32d636 --- /dev/null +++ b/canvas/Library_directx9canvas.mk @@ -0,0 +1,69 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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 . +# + +$(eval $(call gb_Library_Library,directx9canvas)) + +$(eval $(call gb_Library_set_include,directx9canvas,\ + $$(INCLUDE) \ + -I$(SRCDIR)/canvas/inc \ +)) + +$(eval $(call gb_Library_set_componentfile,directx9canvas,canvas/source/directx/directx9canvas,services)) + +$(eval $(call gb_Library_use_sdk_api,directx9canvas)) + +$(eval $(call gb_Library_use_external,directx9canvas,boost_headers)) + +$(eval $(call gb_Library_use_libraries,directx9canvas,\ + cppu \ + tk \ + sal \ + comphelper \ + cppuhelper \ + basegfx \ + canvastools \ + vcl \ + tl \ + utl \ + i18nlangtag \ +)) + +$(eval $(call gb_Library_use_system_win32_libs,directx9canvas,\ + d3d9 \ + gdi32 \ + gdiplus \ +)) + +$(eval $(call gb_Library_use_static_libraries,directx9canvas,\ + directxcanvas \ +)) + +$(eval $(call gb_Library_add_exception_objects,directx9canvas,\ + canvas/source/directx/dx_9rm \ + canvas/source/directx/dx_canvascustomsprite \ + canvas/source/directx/dx_config \ + canvas/source/directx/dx_spritecanvas \ + canvas/source/directx/dx_spritecanvashelper \ + canvas/source/directx/dx_spritedevicehelper \ + canvas/source/directx/dx_spritehelper \ + canvas/source/directx/dx_surfacebitmap \ + canvas/source/directx/dx_surfacegraphics \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/canvas/Library_gdipluscanvas.mk b/canvas/Library_gdipluscanvas.mk new file mode 100644 index 000000000000..a67a19df4120 --- /dev/null +++ b/canvas/Library_gdipluscanvas.mk @@ -0,0 +1,60 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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 . +# + +$(eval $(call gb_Library_Library,gdipluscanvas)) + +$(eval $(call gb_Library_set_include,gdipluscanvas,\ + $$(INCLUDE) \ + -I$(SRCDIR)/canvas/inc \ +)) + +$(eval $(call gb_Library_set_componentfile,gdipluscanvas,canvas/source/directx/gdipluscanvas,services)) + +$(eval $(call gb_Library_use_external,gdipluscanvas,boost_headers)) + +$(eval $(call gb_Library_use_sdk_api,gdipluscanvas)) + +$(eval $(call gb_Library_use_libraries,gdipluscanvas,\ + cppu \ + tk \ + sal \ + comphelper \ + cppuhelper \ + basegfx \ + canvastools \ + vcl \ + tl \ + utl \ + i18nlangtag \ +)) + +$(eval $(call gb_Library_use_system_win32_libs,gdipluscanvas,\ + gdi32 \ + gdiplus \ +)) + +$(eval $(call gb_Library_use_static_libraries,gdipluscanvas,\ + directxcanvas \ +)) + +$(eval $(call gb_Library_add_exception_objects,gdipluscanvas,\ + canvas/source/directx/dx_canvas \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/canvas/Module_canvas.mk b/canvas/Module_canvas.mk index 9fc588ad6c76..79165c4976e7 100644 --- a/canvas/Module_canvas.mk +++ b/canvas/Module_canvas.mk @@ -28,6 +28,12 @@ $(eval $(call gb_Module_add_targets,canvas,\ $(if $(or $(DISABLE_GUI),$(DISABLE_DYNLOADING)),,Executable_canvasdemo)) \ )) +ifeq ($(ENABLE_CAIRO_CANVAS),TRUE) +$(eval $(call gb_Module_add_targets,canvas,\ + Library_cairocanvas \ +)) +endif + ifeq ($(ENABLE_OPENGL_CANVAS),TRUE) $(eval $(call gb_Module_add_targets,canvas,\ Library_oglcanvas \ @@ -35,6 +41,14 @@ $(eval $(call gb_Module_add_targets,canvas,\ )) endif +ifeq ($(OS),WNT) +$(eval $(call gb_Module_add_targets,canvas,\ + Library_directx9canvas \ + Library_gdipluscanvas \ + StaticLibrary_directxcanvas \ +)) +endif + $(eval $(call gb_Module_add_check_targets,canvas,\ CppunitTest_canvas_test \ )) diff --git a/canvas/StaticLibrary_directxcanvas.mk b/canvas/StaticLibrary_directxcanvas.mk new file mode 100644 index 000000000000..1e0d34409806 --- /dev/null +++ b/canvas/StaticLibrary_directxcanvas.mk @@ -0,0 +1,41 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# +# 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/. +# + +$(eval $(call gb_StaticLibrary_StaticLibrary,directxcanvas)) + +$(eval $(call gb_StaticLibrary_set_include,directxcanvas,\ + $$(INCLUDE) \ + -I$(SRCDIR)/canvas/inc \ +)) + +$(eval $(call gb_StaticLibrary_use_external,directxcanvas,boost_headers)) + +$(eval $(call gb_StaticLibrary_use_api,directxcanvas,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_StaticLibrary_add_exception_objects,directxcanvas,\ + canvas/source/directx/dx_bitmap \ + canvas/source/directx/dx_bitmapcanvashelper \ + canvas/source/directx/dx_canvasbitmap \ + canvas/source/directx/dx_canvasfont \ + canvas/source/directx/dx_canvashelper \ + canvas/source/directx/dx_canvashelper_texturefill \ + canvas/source/directx/dx_devicehelper \ + canvas/source/directx/dx_gdiplususer \ + canvas/source/directx/dx_impltools \ + canvas/source/directx/dx_linepolypolygon \ + canvas/source/directx/dx_textlayout \ + canvas/source/directx/dx_textlayout_drawhelper \ + canvas/source/directx/dx_vcltools \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/canvas/inc/pch/precompiled_cairocanvas.hxx b/canvas/inc/pch/precompiled_cairocanvas.hxx new file mode 100644 index 000000000000..3657267d7383 --- /dev/null +++ b/canvas/inc/pch/precompiled_cairocanvas.hxx @@ -0,0 +1,89 @@ +/* -*- 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 has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2021-03-08 13:11:37 using: + ./bin/update_pch canvas cairocanvas --cutoff=1 --exclude:system --include:module --include:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./canvas/inc/pch/precompiled_cairocanvas.hxx "make canvas.build" --find-conflicts +*/ + +#include <sal/config.h> +#if PCH_LEVEL >= 1 +#include <algorithm> +#include <cairo.h> +#include <math.h> +#include <memory> +#include <tuple> +#include <boost/cast.hpp> +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include <osl/mutex.hxx> +#include <rtl/instance.hxx> +#include <rtl/math.hxx> +#include <sal/log.hxx> +#include <vcl/BitmapTools.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/cairo.hxx> +#include <vcl/canvastools.hxx> +#include <vcl/dibtools.hxx> +#include <vcl/metric.hxx> +#include <vcl/skia/SkiaHelper.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/virdev.hxx> +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/utils/canvastools.hxx> +#include <basegfx/utils/keystoplerp.hxx> +#include <basegfx/utils/lerp.hxx> +#include <basegfx/utils/unopolypolygon.hxx> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/rendering/ColorComponentTag.hpp> +#include <com/sun/star/rendering/ColorSpaceType.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/IntegerBitmapLayout.hpp> +#include <com/sun/star/rendering/PanoseProportion.hpp> +#include <com/sun/star/rendering/PathCapType.hpp> +#include <com/sun/star/rendering/PathJoinType.hpp> +#include <com/sun/star/rendering/RenderingIntent.hpp> +#include <com/sun/star/rendering/RepaintResult.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp> +#include <com/sun/star/util/Endianness.hpp> +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <tools/stream.hxx> +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include <canvas/canvastools.hxx> +#include <parametricpolypolygon.hxx> +#include <verifyinput.hxx> +#endif // PCH_LEVEL >= 4 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_cachedbitmap.cxx b/canvas/source/cairo/cairo_cachedbitmap.cxx new file mode 100644 index 000000000000..e548778b2fe4 --- /dev/null +++ b/canvas/source/cairo/cairo_cachedbitmap.cxx @@ -0,0 +1,77 @@ +/* -*- 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 <sal/config.h> + +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/RepaintResult.hpp> +#include <utility> +#include <comphelper/diagnose_ex.hxx> + +#include "cairo_cachedbitmap.hxx" +#include "cairo_repainttarget.hxx" + + +using namespace ::cairo; +using namespace ::com::sun::star; + +namespace cairocanvas +{ + CachedBitmap::CachedBitmap( SurfaceSharedPtr pSurface, + const rendering::ViewState& rUsedViewState, + rendering::RenderState aUsedRenderState, + const uno::Reference< rendering::XCanvas >& rTarget ) : + CachedPrimitiveBase( rUsedViewState, rTarget ), + mpSurface(std::move( pSurface )), + maRenderState(std::move( aUsedRenderState )) + {} + + void CachedBitmap::disposing(std::unique_lock<std::mutex>& rGuard) + { + mpSurface.reset(); + CachedPrimitiveBase::disposing(rGuard); + } + + ::sal_Int8 CachedBitmap::doRedraw( const rendering::ViewState& rNewState, + const rendering::ViewState& /*rOldState*/, + const uno::Reference< rendering::XCanvas >& rTargetCanvas, + bool bSameViewTransform ) + { + ENSURE_OR_THROW( bSameViewTransform, + "CachedBitmap::doRedraw(): base called with changed view transform " + "(told otherwise during construction)" ); + + RepaintTarget* pTarget = dynamic_cast< RepaintTarget* >(rTargetCanvas.get()); + + ENSURE_OR_THROW( pTarget, + "CachedBitmap::redraw(): cannot cast target to RepaintTarget" ); + + if( !pTarget->repaint( mpSurface, + rNewState, + maRenderState ) ) + { + // target failed to repaint + return rendering::RepaintResult::FAILED; + } + + return rendering::RepaintResult::REDRAWN; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_cachedbitmap.hxx b/canvas/source/cairo/cairo_cachedbitmap.hxx new file mode 100644 index 000000000000..d7f4c58ef681 --- /dev/null +++ b/canvas/source/cairo/cairo_cachedbitmap.hxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ + +#pragma once + +#include <base/cachedprimitivebase.hxx> +#include <com/sun/star/rendering/RenderState.hpp> + +#include <vcl/cairo.hxx> + +/* Definition of CachedBitmap class */ + +namespace cairocanvas +{ + class CachedBitmap : public ::canvas::CachedPrimitiveBase + { + public: + + /** Create an XCachedPrimitive for given GraphicObject + */ + CachedBitmap( ::cairo::SurfaceSharedPtr pSurface, + const css::rendering::ViewState& rUsedViewState, + css::rendering::RenderState aUsedRenderState, + const css::uno::Reference< css::rendering::XCanvas >& rTarget ); + + /// Dispose all internal references + virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; + + private: + virtual ::sal_Int8 doRedraw( const css::rendering::ViewState& rNewState, + const css::rendering::ViewState& rOldState, + const css::uno::Reference< + css::rendering::XCanvas >& rTargetCanvas, + bool bSameViewTransform ) override; + + + ::cairo::SurfaceSharedPtr mpSurface; + const css::rendering::RenderState maRenderState; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvas.cxx b/canvas/source/cairo/cairo_canvas.cxx new file mode 100644 index 000000000000..4078e95deb63 --- /dev/null +++ b/canvas/source/cairo/cairo_canvas.cxx @@ -0,0 +1,189 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <osl/mutex.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/skia/SkiaHelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include "cairo_canvas.hxx" + +using namespace ::cairo; +using namespace ::com::sun::star; + +namespace cairocanvas +{ + Canvas::Canvas( const uno::Sequence< uno::Any >& aArguments, + const uno::Reference< uno::XComponentContext >& /*rxContext*/ ) : + maArguments(aArguments) + { + } + + void Canvas::initialize() + { + // #i64742# Only perform initialization when not in probe mode + if( !maArguments.hasElements() ) + return; + + assert( !SkiaHelper::isVCLSkiaEnabled() ); + + /* maArguments: + 0: ptr to creating instance (Window or VirtualDevice) + 1: current bounds of creating instance + 2: bool, denoting always on top state for Window (always false for VirtualDevice) + 3: XWindow for creating Window (or empty for VirtualDevice) + 4: SystemGraphicsData as a streamed Any + */ + SAL_INFO("canvas.cairo","Canvas created " << this); + + ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 && + maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER && + maArguments[4].getValueTypeClass() == uno::TypeClass_SEQUENCE, + "Canvas::initialize: wrong number of arguments, or wrong types" ); + + // We expect a single Any here, containing a pointer to a valid + // VCL output device, on which to output (mostly needed for text) + sal_Int64 nPtr = 0; + maArguments[0] >>= nPtr; + OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr); + ENSURE_ARG_OR_THROW( pOutDev != nullptr, + "Canvas::initialize: invalid OutDev pointer" ); + + awt::Rectangle aBounds; + maArguments[1] >>= aBounds; + + uno::Sequence<sal_Int8> aSeq; + maArguments[4] >>= aSeq; + + const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray()); + if( !pSysData || !pSysData->nSize ) + throw lang::NoSupportException( u"Passed SystemGraphicsData invalid!"_ustr ); + + bool bHasCairo = pOutDev->SupportsCairo(); + ENSURE_ARG_OR_THROW(bHasCairo, "SpriteCanvas::SpriteCanvas: No Cairo capability"); + + // setup helper + maDeviceHelper.init( *this, *pOutDev ); + + maCanvasHelper.init( basegfx::B2ISize(aBounds.Width, aBounds.Height), *this, this ); + + // forward surface to render on to canvashelper + maCanvasHelper.setSurface( maDeviceHelper.getSurface(), false ); + + maArguments.realloc(0); + } + + Canvas::~Canvas() + { + SAL_INFO("canvas.cairo", "CairoCanvas destroyed" ); + } + + void Canvas::disposeThis() + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // forward to parent + CanvasBaseT::disposeThis(); + } + + OUString SAL_CALL Canvas::getServiceName( ) + { + return u"com.sun.star.rendering.Canvas.Cairo"_ustr; + } + + // XServiceInfo + sal_Bool Canvas::supportsService(const OUString& sServiceName) + { + return cppu::supportsService(this, sServiceName); + + } + OUString Canvas::getImplementationName() + { + return u"com.sun.star.comp.rendering.Canvas.Cairo"_ustr; + } + css::uno::Sequence< OUString > Canvas::getSupportedServiceNames() + { + return { getServiceName() }; + } + + bool Canvas::repaint( const SurfaceSharedPtr& pSurface, + const rendering::ViewState& viewState, + const rendering::RenderState& renderState ) + { + return maCanvasHelper.repaint( pSurface, viewState, renderState ); + } + + SurfaceSharedPtr Canvas::getSurface() + { + return maDeviceHelper.getSurface(); + } + + SurfaceSharedPtr Canvas::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) + { + return maDeviceHelper.createSurface( rSize, aContent ); + } + + SurfaceSharedPtr Canvas::createSurface( ::Bitmap& rBitmap ) + { + SurfaceSharedPtr pSurface; + + BitmapSystemData aData; + if( rBitmap.GetSystemData( aData ) ) { + const Size aSize = rBitmap.GetSizePixel(); + + pSurface = maDeviceHelper.createSurface( aData, aSize ); + } + + return pSurface; + } + + SurfaceSharedPtr Canvas::changeSurface() + { + // non-modifiable surface here + return SurfaceSharedPtr(); + } + + OutputDevice* Canvas::getOutputDevice() + { + return maDeviceHelper.getOutputDevice(); + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_rendering_Canvas_Cairo_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args) +{ + rtl::Reference<cairocanvas::Canvas> p = new cairocanvas::Canvas(args, context); + try { + p->initialize(); + } catch (css::uno::Exception&) { + p->dispose(); + throw; + } + return cppu::acquire(p.get()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvas.hxx b/canvas/source/cairo/cairo_canvas.hxx new file mode 100644 index 000000000000..0c41a8a5c0d3 --- /dev/null +++ b/canvas/source/cairo/cairo_canvas.hxx @@ -0,0 +1,142 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XUpdatable.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/rendering/XGraphicDevice.hpp> +#include <com/sun/star/rendering/XBitmapCanvas.hpp> + +#include <cppuhelper/compbase.hxx> +#include <comphelper/uno3.hxx> + +#include <base/basemutexhelper.hxx> +#include <base/bitmapcanvasbase.hxx> +#include <base/graphicdevicebase.hxx> +#include <base/integerbitmapbase.hxx> + +#include "cairo_canvashelper.hxx" +#include "cairo_devicehelper.hxx" +#include "cairo_repainttarget.hxx" +#include "cairo_surfaceprovider.hxx" + +namespace cairocanvas +{ + typedef ::cppu::WeakComponentImplHelper< css::rendering::XBitmapCanvas, + css::rendering::XIntegerBitmap, + css::rendering::XGraphicDevice, + css::lang::XMultiServiceFactory, + css::util::XUpdatable, + css::beans::XPropertySet, + css::lang::XServiceName, + css::lang::XServiceInfo > GraphicDeviceBase_Base; + typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase_Base >, + DeviceHelper, + ::osl::MutexGuard, + ::cppu::OWeakObject > CanvasBase_Base; + + /** Mixin SurfaceProvider + + Have to mixin the SurfaceProvider before deriving from + ::canvas::CanvasBase, as this template should already + implement some of those interface methods. + + The reason why this appears kinda convoluted is the fact that + we cannot specify non-IDL types as WeakComponentImplHelper + template args, and furthermore, don't want to derive + ::canvas::CanvasBase directly from + SurfaceProvider (because derivees of + ::canvas::CanvasBase have to explicitly forward the + XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS) + anyway). + */ + class CanvasBaseSurfaceProvider_Base : public CanvasBase_Base, + public SurfaceProvider + { + }; + + typedef ::canvas::IntegerBitmapBase< + canvas::BitmapCanvasBase2< + CanvasBaseSurfaceProvider_Base, + CanvasHelper, + ::osl::MutexGuard, + ::cppu::OWeakObject> > CanvasBaseT; + + /** Product of this component's factory. + + The Canvas object combines the actual Window canvas with + the XGraphicDevice interface. This is because there's a + one-to-one relation between them, anyway, since each window + can have exactly one canvas and one associated + XGraphicDevice. And to avoid messing around with circular + references, this is implemented as one single object. + */ + class Canvas : public CanvasBaseT, + public RepaintTarget + { + public: + Canvas( const css::uno::Sequence< css::uno::Any >& aArguments, + const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + void initialize(); + + /// For resource tracking + virtual ~Canvas() override; + + /// Dispose all internal references + virtual void disposeThis() override; + + // Forwarding the XComponent implementation to the + // cppu::ImplHelper templated base + // Classname Base doing refcounting Base implementing the XComponent interface + // | | | + // V V V + DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( Canvas, GraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase ) + + // XServiceName + virtual OUString SAL_CALL getServiceName( ) override; + + // XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override; + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // RepaintTarget + virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override; + + // SurfaceProvider + virtual ::cairo::SurfaceSharedPtr getSurface() override; + virtual ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, int aContent ) override; + virtual ::cairo::SurfaceSharedPtr createSurface( ::Bitmap& rBitmap ) override; + virtual ::cairo::SurfaceSharedPtr changeSurface() override; + virtual OutputDevice* getOutputDevice() override; + + private: + css::uno::Sequence< css::uno::Any > maArguments; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx new file mode 100644 index 000000000000..c4de75ee2fce --- /dev/null +++ b/canvas/source/cairo/cairo_canvasbitmap.cxx @@ -0,0 +1,163 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <utility> +#include <vcl/bitmapex.hxx> +#include <vcl/BitmapTools.hxx> + +#include <cairo.h> + +#include "cairo_canvasbitmap.hxx" + +using namespace ::cairo; +using namespace ::com::sun::star; + +namespace cairocanvas +{ + CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize, + SurfaceProviderRef rSurfaceProvider, + rendering::XGraphicDevice* pDevice, + bool bHasAlpha ) : + mpSurfaceProvider(std::move( rSurfaceProvider )), + maSize(rSize), + mbHasAlpha(bHasAlpha) + { + ENSURE_OR_THROW( mpSurfaceProvider.is(), + "CanvasBitmap::CanvasBitmap(): Invalid surface or device" ); + + SAL_INFO( + "canvas.cairo", + "bitmap size: " << rSize.getWidth() << "x" << rSize.getHeight()); + + mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR ); + mpBufferCairo = mpBufferSurface->getCairo(); + + maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice ); + maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha ); + + // clear bitmap to 100% transparent + maCanvasHelper.clear(); + } + + void CanvasBitmap::disposeThis() + { + mpSurfaceProvider.clear(); + + mpBufferCairo.reset(); + mpBufferSurface.reset(); + + // forward to parent + CanvasBitmap_Base::disposeThis(); + } + + SurfaceSharedPtr CanvasBitmap::getSurface() + { + return mpBufferSurface; + } + + SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) + { + return mpSurfaceProvider->createSurface(rSize,aContent); + } + + SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap ) + { + return mpSurfaceProvider->createSurface(rBitmap); + } + + SurfaceSharedPtr CanvasBitmap::changeSurface() + { + // non-modifiable surface here + return SurfaceSharedPtr(); + } + + OutputDevice* CanvasBitmap::getOutputDevice() + { + return mpSurfaceProvider->getOutputDevice(); + } + + bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface, + const rendering::ViewState& viewState, + const rendering::RenderState& renderState ) + { + return maCanvasHelper.repaint( pSurface, viewState, renderState ); + } + + uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) + { + uno::Any aRV( sal_Int32(0) ); + // 0 ... get BitmapEx + // 1 ... get Pixbuf with bitmap RGB content + // 2 ... return nothing (empty Any) + switch( nHandle ) + { + case 0: + { + aRV <<= reinterpret_cast<sal_Int64>( nullptr ); + if ( !mbHasAlpha ) + break; + + BitmapEx* pBitmapEx = vcl::bitmap::CreateFromCairoSurface( + ::Size( maSize.getWidth(), maSize.getHeight() ), + getSurface()->getCairoSurface().get()); + if (pBitmapEx) + aRV <<= reinterpret_cast<sal_Int64>( pBitmapEx ); + + break; + } + case 1: + { + aRV = getOutputDevice()->GetNativeSurfaceHandle(mpBufferSurface, maSize); + break; + } + case 2: + { + // Always return nothing - for the RGB surface support. + // Alpha code paths go via the above case 0. + aRV = uno::Any(); + break; + } + } + + return aRV; + } + + OUString SAL_CALL CanvasBitmap::getImplementationName( ) + { + return u"CairoCanvas.CanvasBitmap"_ustr; + } + + sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName ) + { + return cppu::supportsService( this, ServiceName ); + } + + uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) + { + return { u"com.sun.star.rendering.CanvasBitmap"_ustr }; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvasbitmap.hxx b/canvas/source/cairo/cairo_canvasbitmap.hxx new file mode 100644 index 000000000000..f2371821023f --- /dev/null +++ b/canvas/source/cairo/cairo_canvasbitmap.hxx @@ -0,0 +1,125 @@ +/* -*- 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 . + */ + +#pragma once + +#include <cppuhelper/compbase.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/rendering/XBitmapCanvas.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <comphelper/uno3.hxx> + +#include <base/bitmapcanvasbase.hxx> +#include <base/basemutexhelper.hxx> +#include <base/integerbitmapbase.hxx> + +#include "cairo_canvashelper.hxx" +#include "cairo_repainttarget.hxx" + + +/* Definition of CanvasBitmap class */ + +namespace cairocanvas +{ + typedef ::cppu::WeakComponentImplHelper< css::rendering::XBitmapCanvas, + css::rendering::XIntegerBitmap, + css::lang::XServiceInfo, + css::beans::XFastPropertySet > CanvasBitmapBase_Base; + class CanvasBitmapSpriteSurface_Base : + public ::canvas::BaseMutexHelper<CanvasBitmapBase_Base>, + public SurfaceProvider + { + }; + + typedef ::canvas::IntegerBitmapBase< + canvas::BitmapCanvasBase2< + CanvasBitmapSpriteSurface_Base, + CanvasHelper, + ::osl::MutexGuard, + ::cppu::OWeakObject> > CanvasBitmap_Base; + + class CanvasBitmap : public CanvasBitmap_Base, + public RepaintTarget + { + public: + /** Create a canvas bitmap for the given surface + + @param rSize + Size of the bitmap + + @param rDevice + Reference device, with which bitmap should be compatible + */ + CanvasBitmap( const ::basegfx::B2ISize& rSize, + SurfaceProviderRef rDevice, + css::rendering::XGraphicDevice* pDevice, + bool bHasAlpha ); + + /// Dispose all internal references + virtual void disposeThis() override; + + // Forwarding the XComponent implementation to the + // cppu::ImplHelper templated base + // Classname Base doing refcounting Base implementing the XComponent interface + // | | | + // V V V + DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( CanvasBitmap, CanvasBitmapBase_Base, ::cppu::WeakComponentImplHelperBase ) + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // SurfaceProvider + virtual ::cairo::SurfaceSharedPtr getSurface() override; + virtual ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, int aContent ) override; + virtual ::cairo::SurfaceSharedPtr createSurface( ::Bitmap& rBitmap ) override; + virtual ::cairo::SurfaceSharedPtr changeSurface() override; + virtual OutputDevice* getOutputDevice() override; + + // RepaintTarget + virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override; + + // XFastPropertySet + // used to retrieve BitmapEx pointer or X Pixmap handles for this bitmap + // handle values have these meanings: + // 0 ... get pointer to BitmapEx + // 1 ... get X pixmap handle to rgb content + // 2 ... FIXME: leftover? ever called with this? always returns nothing (empty Any) + // returned any contains either BitmapEx pointer or array of two Any value + // 1st a bool value: true - free the pixmap after used by XFreePixmap, false do nothing, the pixmap is used internally in the canvas + // 2nd the pixmap handle (sal_Int64) + virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override; + virtual void SAL_CALL setFastPropertyValue(sal_Int32, const css::uno::Any&) override {} + + private: + SurfaceProviderRef mpSurfaceProvider; + ::cairo::SurfaceSharedPtr mpBufferSurface; + ::cairo::CairoSharedPtr mpBufferCairo; + + const ::basegfx::B2ISize maSize; + const bool mbHasAlpha; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvascustomsprite.cxx b/canvas/source/cairo/cairo_canvascustomsprite.cxx new file mode 100644 index 000000000000..72fb291ebf35 --- /dev/null +++ b/canvas/source/cairo/cairo_canvascustomsprite.cxx @@ -0,0 +1,151 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <basegfx/point/b2dpoint.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <canvas/canvastools.hxx> +#include <cairo.h> + +#include "cairo_canvascustomsprite.hxx" +#include "cairo_spritecanvas.hxx" + + +using namespace ::cairo; +using namespace ::com::sun::star; + +namespace cairocanvas +{ + CanvasCustomSprite::CanvasCustomSprite( const css::geometry::RealSize2D& rSpriteSize, + const SpriteCanvasRef& rRefDevice ) : + mpSpriteCanvas( rRefDevice ), + maSize( ::canvas::tools::roundUp( rSpriteSize.Width ), + ::canvas::tools::roundUp( rSpriteSize.Height ) ) + { + ENSURE_OR_THROW( rRefDevice, + "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" ); + + SAL_INFO( "canvas.cairo", "sprite size: " << ::canvas::tools::roundUp( rSpriteSize.Width ) << ", " << ::canvas::tools::roundUp( rSpriteSize.Height )); + + mpBufferSurface = mpSpriteCanvas->createSurface( maSize, CAIRO_CONTENT_COLOR_ALPHA ); + + maCanvasHelper.init( maSize, + *rRefDevice, + rRefDevice.get() ); + maCanvasHelper.setSurface( mpBufferSurface, true ); + + maSpriteHelper.init( rSpriteSize, + rRefDevice ); + maSpriteHelper.setSurface( mpBufferSurface ); + + // clear sprite to 100% transparent + maCanvasHelper.clear(); + } + + void CanvasCustomSprite::disposeThis() + { + ::osl::MutexGuard aGuard( m_aMutex ); + + mpSpriteCanvas.clear(); + mpBufferSurface.reset(); + + // forward to parent + CanvasCustomSpriteBaseT::disposeThis(); + } + + void CanvasCustomSprite::redraw( const CairoSharedPtr& pCairo, + bool bBufferedUpdate ) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + redraw( pCairo, maSpriteHelper.getPosPixel(), bBufferedUpdate ); + } + + void CanvasCustomSprite::redraw( const CairoSharedPtr& pCairo, + const ::basegfx::B2DPoint& rOrigOutputPos, + bool bBufferedUpdate ) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + maSpriteHelper.redraw( pCairo, + rOrigOutputPos, + mbSurfaceDirty, + bBufferedUpdate ); + + mbSurfaceDirty = false; + } + + bool CanvasCustomSprite::repaint( const SurfaceSharedPtr& pSurface, + const rendering::ViewState& viewState, + const rendering::RenderState& renderState ) + { + return maCanvasHelper.repaint( pSurface, viewState, renderState ); + } + + SurfaceSharedPtr CanvasCustomSprite::getSurface() + { + return mpBufferSurface; + } + + SurfaceSharedPtr CanvasCustomSprite::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) + { + return mpSpriteCanvas->createSurface(rSize,aContent); + } + + SurfaceSharedPtr CanvasCustomSprite::createSurface( ::Bitmap& rBitmap ) + { + return mpSpriteCanvas->createSurface(rBitmap); + } + + SurfaceSharedPtr CanvasCustomSprite::changeSurface() + { + SAL_INFO( "canvas.cairo", "replacing sprite background surface"); + + mpBufferSurface = mpSpriteCanvas->createSurface( maSize, CAIRO_CONTENT_COLOR ); + maSpriteHelper.setSurface( mpBufferSurface ); + + return mpBufferSurface; + } + + OutputDevice* CanvasCustomSprite::getOutputDevice() + { + return mpSpriteCanvas->getOutputDevice(); + } + + OUString SAL_CALL CanvasCustomSprite::getImplementationName() + { + return u"CairoCanvas.CanvasCustomSprite"_ustr; + } + + sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const OUString& ServiceName ) + { + return cppu::supportsService( this, ServiceName ); + } + + uno::Sequence< OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames() + { + return { u"com.sun.star.rendering.CanvasCustomSprite"_ustr }; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvascustomsprite.hxx b/canvas/source/cairo/cairo_canvascustomsprite.hxx new file mode 100644 index 000000000000..ffe766ab0966 --- /dev/null +++ b/canvas/source/cairo/cairo_canvascustomsprite.hxx @@ -0,0 +1,145 @@ +/* -*- 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 . + */ + +#pragma once + +#include <cppuhelper/compbase.hxx> +#include <comphelper/uno3.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/rendering/XBitmapCanvas.hpp> +#include <com/sun/star/rendering/XCustomSprite.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> + +#include <basegfx/point/b2dpoint.hxx> + +#include <base/basemutexhelper.hxx> +#include <base/canvascustomspritebase.hxx> + +#include <vcl/cairo.hxx> + +#include "cairo_sprite.hxx" +#include "cairo_canvashelper.hxx" +#include "cairo_repainttarget.hxx" +#include "cairo_spritehelper.hxx" +#include "cairo_spritecanvas.hxx" + + +namespace cairocanvas +{ + typedef ::cppu::WeakComponentImplHelper< css::rendering::XCustomSprite, + css::rendering::XBitmapCanvas, + css::rendering::XIntegerBitmap, + css::lang::XServiceInfo > CanvasCustomSpriteBase_Base; + /** Mixin Sprite + + Have to mixin the Sprite interface before deriving from + ::canvas::CanvasCustomSpriteBase, as this template should + already implement some of those interface methods. + + The reason why this appears kinda convoluted is the fact that + we cannot specify non-IDL types as WeakComponentImplHelper + template args, and furthermore, don't want to derive + ::canvas::CanvasCustomSpriteBase directly from + ::canvas::Sprite (because derivees of + ::canvas::CanvasCustomSpriteBase have to explicitly forward + the XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS) + anyway). Basically, ::canvas::CanvasCustomSpriteBase should + remain a base class that provides implementation, not to + enforce any specific interface on its derivees. + */ + class CanvasCustomSpriteSpriteBase_Base : public ::canvas::BaseMutexHelper< CanvasCustomSpriteBase_Base >, + public Sprite, + public SurfaceProvider + { + }; + + typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base, + SpriteHelper, + CanvasHelper, + ::osl::MutexGuard, + ::cppu::OWeakObject > CanvasCustomSpriteBaseT; + + /* Definition of CanvasCustomSprite class */ + + class CanvasCustomSprite : public CanvasCustomSpriteBaseT, + public RepaintTarget + { + public: + /** Create a custom sprite + + @param rSpriteSize + Size of the sprite in pixel + + @param rRefDevice + Associated output device + + @param rSpriteCanvas + Target canvas + + @param rDevice + Target DX device + */ + CanvasCustomSprite( const css::geometry::RealSize2D& rSpriteSize, + const SpriteCanvasRef& rRefDevice ); + + virtual void disposeThis() override; + + // Forwarding the XComponent implementation to the + // cppu::ImplHelper templated base + // Classname Base doing refcount Base implementing the XComponent interface + // | | | + // V V V + DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( CanvasCustomSprite, CanvasCustomSpriteBase_Base, ::cppu::WeakComponentImplHelperBase ) + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // Sprite + virtual void redraw( const ::cairo::CairoSharedPtr& pCairo, + bool bBufferedUpdate ) const override; + virtual void redraw( const ::cairo::CairoSharedPtr& pCairo, + const ::basegfx::B2DPoint& rOrigOutputPos, + bool bBufferedUpdate ) const override; + + // RepaintTarget + virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override; + + // SurfaceProvider + virtual ::cairo::SurfaceSharedPtr getSurface() override; + virtual ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, int aContent ) override; + virtual ::cairo::SurfaceSharedPtr createSurface( ::Bitmap& rBitmap ) override; + virtual ::cairo::SurfaceSharedPtr changeSurface() override; + virtual OutputDevice* getOutputDevice() override; + + private: + /** MUST hold here, too, since CanvasHelper only contains a + raw pointer (without refcounting) + */ + SpriteCanvasRef mpSpriteCanvas; + ::cairo::SurfaceSharedPtr mpBufferSurface; + ::basegfx::B2ISize maSize; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvasfont.cxx b/canvas/source/cairo/cairo_canvasfont.cxx new file mode 100644 index 000000000000..a2650811b721 --- /dev/null +++ b/canvas/source/cairo/cairo_canvasfont.cxx @@ -0,0 +1,161 @@ +/* -*- 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 <sal/config.h> + +#include <basegfx/numeric/ftools.hxx> +#include <com/sun/star/rendering/PanoseProportion.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <rtl/math.hxx> +#include <utility> +#include <vcl/metric.hxx> + +#include <canvas/canvastools.hxx> + +#include "cairo_canvasfont.hxx" +#include "cairo_textlayout.hxx" + +using namespace ::com::sun::star; + +namespace cairocanvas +{ + + CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest, + const uno::Sequence< beans::PropertyValue >& rExtraFontProperties, + const geometry::Matrix2D& rFontMatrix, + SurfaceProviderRef rDevice ) : + maFont( vcl::Font( rFontRequest.FontDescription.FamilyName, + rFontRequest.FontDescription.StyleName, + Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ), + maFontRequest( rFontRequest ), + mpRefDevice(std::move( rDevice )), + mnEmphasisMark(0) + { + ::canvas::tools::extractExtraFontProperties(rExtraFontProperties, mnEmphasisMark); + + maFont->SetAlignment( ALIGN_BASELINE ); + maFont->SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==css::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE ); + maFont->SetVertical( rFontRequest.FontDescription.IsVertical==css::util::TriState_YES ); + + // TODO(F2): improve panose->vclenum conversion + maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) ); + maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL ); + maFont->SetPitch( + rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED + ? PITCH_FIXED : PITCH_VARIABLE); + + maFont->SetLanguage( LanguageTag::convertToLanguageType( rFontRequest.Locale, false)); + + // adjust to stretched/shrunk font + if( ::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) ) + return; + + VclPtr<OutputDevice> pOutDev( mpRefDevice->getOutputDevice() ); + + if( !pOutDev ) + return; + + const bool bOldMapState( pOutDev->IsMapModeEnabled() ); + pOutDev->EnableMapMode(false); + + const Size aSize = pOutDev->GetFontMetric( *maFont ).GetFontSize(); + + const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 ); + double fStretch = rFontMatrix.m00 + rFontMatrix.m01; + + if( !::basegfx::fTools::equalZero( fDividend) ) + fStretch /= fDividend; + + const tools::Long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); + + maFont->SetAverageFontWidth( nNewWidth ); + + pOutDev->EnableMapMode(bOldMapState); + } + + void CanvasFont::disposing(std::unique_lock<std::mutex>& rGuard) + { + rGuard.unlock(); + { + SolarMutexGuard aGuard; + mpRefDevice.clear(); + } + rGuard.lock(); + } + + uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) + { + SolarMutexGuard aGuard; + + if( !mpRefDevice.is() ) + return uno::Reference< rendering::XTextLayout >(); // we're disposed + + return new TextLayout( aText, + nDirection, + nRandomSeed, + Reference( this ), + mpRefDevice ); + } + + rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) + { + return maFontRequest; + } + + rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) + { + // TODO(F1) + return rendering::FontMetrics(); + } + + uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) + { + // TODO(F1) + return uno::Sequence< double >(); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) + { + // TODO(F1) + return uno::Sequence< beans::PropertyValue >(); + } + + OUString SAL_CALL CanvasFont::getImplementationName() + { + return u"CairoCanvas::CanvasFont"_ustr; + } + + sal_Bool SAL_CALL CanvasFont::supportsService( const OUString& ServiceName ) + { + return cppu::supportsService( this, ServiceName ); + } + + uno::Sequence< OUString > SAL_CALL CanvasFont::getSupportedServiceNames() + { + return { u"com.sun.star.rendering.CanvasFont"_ustr }; + } + + vcl::Font const & CanvasFont::getVCLFont() const + { + return *maFont; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvasfont.hxx b/canvas/source/cairo/cairo_canvasfont.hxx new file mode 100644 index 000000000000..d5e015006c98 --- /dev/null +++ b/canvas/source/cairo/cairo_canvasfont.hxx @@ -0,0 +1,84 @@ +/* -*- 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 . + */ + +#pragma once + +#include <comphelper/compbase.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/geometry/Matrix2D.hpp> +#include <com/sun/star/rendering/FontRequest.hpp> +#include <com/sun/star/rendering/XCanvasFont.hpp> + +#include <vcl/font.hxx> + +#include <vclwrapper.hxx> + +#include "cairo_surfaceprovider.hxx" + + +/* Definition of CanvasFont class */ + +namespace cairocanvas +{ + typedef ::comphelper::WeakComponentImplHelper< css::rendering::XCanvasFont, + css::lang::XServiceInfo > CanvasFont_Base; + + class CanvasFont : public CanvasFont_Base + { + public: + typedef rtl::Reference<CanvasFont> Reference; + /// make noncopyable + CanvasFont(const CanvasFont&) = delete; + const CanvasFont& operator=(const CanvasFont&) = delete; + + CanvasFont( const css::rendering::FontRequest& fontRequest, + const css::uno::Sequence< css::beans::PropertyValue >& extraFontProperties, + const css::geometry::Matrix2D& rFontMatrix, + SurfaceProviderRef rDevice ); + + /// Dispose all internal references + virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; + + // XCanvasFont + virtual css::uno::Reference< css::rendering::XTextLayout > SAL_CALL createTextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) override; + virtual css::rendering::FontRequest SAL_CALL getFontRequest( ) override; + virtual css::rendering::FontMetrics SAL_CALL getFontMetrics( ) override; + virtual css::uno::Sequence< double > SAL_CALL getAvailableSizes( ) override; + virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + vcl::Font const & getVCLFont() const; + + sal_uInt32 getEmphasisMark() const { return mnEmphasisMark; } + + private: + ::canvas::vcltools::VCLObject<vcl::Font> maFont; + css::rendering::FontRequest maFontRequest; + SurfaceProviderRef mpRefDevice; + sal_uInt32 mnEmphasisMark; + }; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx new file mode 100644 index 000000000000..701ad1e47859 --- /dev/null +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -0,0 +1,2045 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <algorithm> +#include <tuple> + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/utils/canvastools.hxx> +#include <basegfx/utils/keystoplerp.hxx> +#include <basegfx/utils/lerp.hxx> +#include <com/sun/star/rendering/ColorComponentTag.hpp> +#include <com/sun/star/rendering/ColorSpaceType.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/IntegerBitmapLayout.hpp> +#include <com/sun/star/rendering/PathCapType.hpp> +#include <com/sun/star/rendering/PathJoinType.hpp> +#include <com/sun/star/rendering/RenderingIntent.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp> +#include <com/sun/star/util/Endianness.hpp> +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <rtl/math.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/BitmapTools.hxx> +#include <vcl/canvastools.hxx> +#include <vcl/virdev.hxx> + +#include <canvas/canvastools.hxx> +#include <parametricpolypolygon.hxx> +#include <cairo.h> + +#include "cairo_cachedbitmap.hxx" +#include "cairo_canvasbitmap.hxx" +#include "cairo_canvashelper.hxx" + +using namespace ::cairo; +using namespace ::com::sun::star; + +namespace cairocanvas +{ + CanvasHelper::CanvasHelper() : + mpSurfaceProvider(nullptr), + mpDevice(nullptr), + mbHaveAlpha() + { + } + + void CanvasHelper::disposing() + { + mpSurface.reset(); + mpCairo.reset(); + mpVirtualDevice.disposeAndClear(); + mpDevice = nullptr; + mpSurfaceProvider = nullptr; + } + + void CanvasHelper::init( const ::basegfx::B2ISize& rSizePixel, + SurfaceProvider& rSurfaceProvider, + rendering::XGraphicDevice* pDevice ) + { + maSize = rSizePixel; + mpSurfaceProvider = &rSurfaceProvider; + mpDevice = pDevice; + } + + void CanvasHelper::setSize( const ::basegfx::B2ISize& rSize ) + { + maSize = rSize; + } + + void CanvasHelper::setSurface( const SurfaceSharedPtr& pSurface, bool bHasAlpha ) + { + mbHaveAlpha = bHasAlpha; + mpVirtualDevice.disposeAndClear(); + mpSurface = pSurface; + mpCairo = pSurface->getCairo(); + } + + static void setColor( cairo_t* pCairo, + const uno::Sequence<double>& rColor ) + { + if( rColor.getLength() > 3 ) + { + cairo_set_source_rgba( pCairo, + rColor[0], + rColor[1], + rColor[2], + rColor[3] ); + } + else if( rColor.getLength() == 3 ) + cairo_set_source_rgb( pCairo, + rColor[0], + rColor[1], + rColor[2] ); + } + + void CanvasHelper::useStates( const rendering::ViewState& viewState, + const rendering::RenderState& renderState, + bool bSetColor ) + { + cairo_matrix_t aViewMatrix; + cairo_matrix_t aRenderMatrix; + cairo_matrix_t aCombinedMatrix; + + cairo_matrix_init( &aViewMatrix, + viewState.AffineTransform.m00, viewState.AffineTransform.m10, viewState.AffineTransform.m01, + viewState.AffineTransform.m11, viewState.AffineTransform.m02, viewState.AffineTransform.m12); + cairo_matrix_init( &aRenderMatrix, + renderState.AffineTransform.m00, renderState.AffineTransform.m10, renderState.AffineTransform.m01, + renderState.AffineTransform.m11, renderState.AffineTransform.m02, renderState.AffineTransform.m12); + cairo_matrix_multiply( &aCombinedMatrix, &aRenderMatrix, &aViewMatrix); + + if( viewState.Clip.is() ) + { + SAL_INFO( "canvas.cairo", "view clip"); + + aViewMatrix.x0 = basegfx::fround( aViewMatrix.x0 ); + aViewMatrix.y0 = basegfx::fround( aViewMatrix.y0 ); + cairo_set_matrix( mpCairo.get(), &aViewMatrix ); + doPolyPolygonPath( viewState.Clip, Clip ); + } + + aCombinedMatrix.x0 = basegfx::fround( aCombinedMatrix.x0 ); + aCombinedMatrix.y0 = basegfx::fround( aCombinedMatrix.y0 ); + cairo_set_matrix( mpCairo.get(), &aCombinedMatrix ); + + if( renderState.Clip.is() ) + { + SAL_INFO( "canvas.cairo", "render clip BEGIN"); + + doPolyPolygonPath( renderState.Clip, Clip ); + SAL_INFO( "canvas.cairo", "render clip END"); + } + + if( bSetColor ) + setColor(mpCairo.get(),renderState.DeviceColor); + + cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER ); + switch( renderState.CompositeOperation ) + { + case rendering::CompositeOperation::CLEAR: + compositingMode = CAIRO_OPERATOR_CLEAR; + break; + case rendering::CompositeOperation::SOURCE: + compositingMode = CAIRO_OPERATOR_SOURCE; + break; + case rendering::CompositeOperation::DESTINATION: + case rendering::CompositeOperation::UNDER: + compositingMode = CAIRO_OPERATOR_DEST; + break; + case rendering::CompositeOperation::OVER: + compositingMode = CAIRO_OPERATOR_OVER; + break; + case rendering::CompositeOperation::INSIDE: + compositingMode = CAIRO_OPERATOR_IN; + break; + case rendering::CompositeOperation::INSIDE_REVERSE: + compositingMode = CAIRO_OPERATOR_OUT; + break; + case rendering::CompositeOperation::OUTSIDE: + compositingMode = CAIRO_OPERATOR_DEST_OVER; + break; + case rendering::CompositeOperation::OUTSIDE_REVERSE: + compositingMode = CAIRO_OPERATOR_DEST_OUT; + break; + case rendering::CompositeOperation::ATOP: + compositingMode = CAIRO_OPERATOR_ATOP; + break; + case rendering::CompositeOperation::ATOP_REVERSE: + compositingMode = CAIRO_OPERATOR_DEST_ATOP; + break; + case rendering::CompositeOperation::XOR: + compositingMode = CAIRO_OPERATOR_XOR; + break; + case rendering::CompositeOperation::ADD: + compositingMode = CAIRO_OPERATOR_ADD; + break; + case rendering::CompositeOperation::SATURATE: + compositingMode = CAIRO_OPERATOR_SATURATE; + break; + } + cairo_set_operator( mpCairo.get(), compositingMode ); + } + + void CanvasHelper::clear() + { + SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getWidth() << " x " << maSize.getHeight() ); + + if( !mpCairo ) + return; + + cairo_save( mpCairo.get() ); + + cairo_identity_matrix( mpCairo.get() ); + // this does not really differ from all-zero, as cairo + // internally converts to premultiplied alpha. but anyway, + // this keeps it consistent with the other canvas impls + if( mbHaveAlpha ) + cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 ); + else + cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 ); + cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); + + cairo_rectangle( mpCairo.get(), 0, 0, maSize.getWidth(), maSize.getHeight() ); + cairo_fill( mpCairo.get() ); + + cairo_restore( mpCairo.get() ); + } + + void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/, + const geometry::RealPoint2D& aStartPoint, + const geometry::RealPoint2D& aEndPoint, + const rendering::ViewState& viewState, + const rendering::RenderState& renderState ) + { + if( !mpCairo ) + return; + + cairo_save( mpCairo.get() ); + + cairo_set_line_width( mpCairo.get(), 1 ); + + useStates( viewState, renderState, true ); + + cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 ); + cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 ); + cairo_stroke( mpCairo.get() ); + + cairo_restore( mpCairo.get() ); + } + + void CanvasHelper::drawBezier( const rendering::XCanvas* , + const geometry::RealBezierSegment2D& aBezierSegment, + const geometry::RealPoint2D& aEndPoint, + const rendering::ViewState& viewState, + const rendering::RenderState& renderState ) + { + if( !mpCairo ) + return; + + cairo_save( mpCairo.get() ); + + cairo_set_line_width( mpCairo.get(), 1 ); + + useStates( viewState, renderState, true ); + + cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 ); + // tdf#99165 correction of control points not needed here, only hairlines drawn + // (see cairo_set_line_width above) + cairo_curve_to( mpCairo.get(), + aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5, + aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5, + aEndPoint.X + 0.5, aEndPoint.Y + 0.5 ); + cairo_stroke( mpCairo.get() ); + + cairo_restore( mpCairo.get() ); + } + +constexpr OUStringLiteral PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME = u"Canvas::ParametricPolyPolygon"; + + /** surfaceFromXBitmap Create a surface from XBitmap + * @param xBitmap bitmap image that will be used for the surface + * @param bHasAlpha will be set to true if resulting surface has alpha + * + * This is a helper function for the other surfaceFromXBitmap(). + * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas. + * + * @return created surface or NULL + **/ + static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) + { + CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() ); + if( pBitmapImpl ) + return pBitmapImpl->getSurface(); + + SurfaceProvider* pSurfaceProvider = dynamic_cast<SurfaceProvider*>( xBitmap.get() ); + if( pSurfaceProvider ) + return pSurfaceProvider->getSurface(); + + return SurfaceSharedPtr(); + } + + static ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) + { + // TODO(F1): Add support for floating point bitmap formats + uno::Reference<rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap, + uno::UNO_QUERY_THROW); + ::BitmapEx aBmpEx = vcl::unotools::bitmapExFromXBitmap(xIntBmp); + if( !aBmpEx.IsEmpty() ) + return aBmpEx; + + // TODO(F1): extract pixel from XBitmap interface + ENSURE_OR_THROW( false, + "bitmapExFromXBitmap(): could not extract BitmapEx" ); + + return ::BitmapEx(); + } + + /** surfaceFromXBitmap Create a surface from XBitmap + * @param xBitmap bitmap image that will be used for the surface + * @param rDevice reference to the device into which we want to draw + * @param data will be filled with alpha data, if xBitmap is alpha/transparent image + * @param bHasAlpha will be set to true if resulting surface has alpha + * + * This function tries various methods for creating a surface from xBitmap. It also uses + * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha ) + * + * @return created surface or NULL + **/ + static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, const SurfaceProviderRef& rSurfaceProvider, unsigned char*& data, bool& bHasAlpha ) + { + bHasAlpha = xBitmap->hasAlpha(); + SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap ); + if( pSurface ) + data = nullptr; + else + { + ::BitmapEx aBmpEx = bitmapExFromXBitmap(xBitmap); + ::Bitmap aBitmap = aBmpEx.GetBitmap(); + + // there's no pixmap for alpha bitmap. we might still + // use rgb pixmap and only access alpha pixels the + // slow way. now we just speedup rgb bitmaps + if( !aBmpEx.IsAlpha() ) + { + pSurface = rSurfaceProvider->createSurface( aBitmap ); + data = nullptr; + bHasAlpha = false; + } + + if( !pSurface ) + { + tools::Long nWidth; + tools::Long nHeight; + vcl::bitmap::CanvasCairoExtractBitmapData(aBmpEx, aBitmap, data, bHasAlpha, nWidth, nHeight); + + pSurface = rSurfaceProvider->getOutputDevice()->CreateSurface( + CairoSurfaceSharedPtr( + cairo_image_surface_create_for_data( + data, + bHasAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, + nWidth, nHeight, nWidth*4 ), + &cairo_surface_destroy) ); + + SAL_INFO( "canvas.cairo","image: " << nWidth << " x " << nHeight << " alpha: " << bHasAlpha); + } + } + + return pSurface; + } + + static void addColorStops( cairo_pattern_t* pPattern, const uno::Sequence< uno::Sequence< double > >& rColors, const uno::Sequence< double >& rStops, bool bReverseStops ) + { + int i; + + OSL_ASSERT( rColors.getLength() == rStops.getLength() ); + + for( i = 0; i < rColors.getLength(); i++ ) + { + const uno::Sequence< double >& rColor( rColors[i] ); + float stop = bReverseStops ? 1 - rStops[i] : rStops[i]; + if( rColor.getLength() == 3 ) + cairo_pattern_add_color_stop_rgb( pPattern, stop, rColor[0], rColor[1], rColor[2] ); + else if( rColor.getLength() == 4 ) + { + double alpha = rColor[3]; + // cairo expects premultiplied alpha + cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha ); + } + } + } + + static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha) + { + if( rLeft.getLength() == 3 ) + { + return + { + basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha), + basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha), + basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha) + }; + } + else if( rLeft.getLength() == 4 ) + { + return + { + basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha), + basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha), + basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha), + basegfx::utils::lerp(rLeft[3],rRight[3],fAlpha) + }; + } + + return {}; + } + + static cairo_pattern_t* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon const & rPolygon ) + { + cairo_pattern_t* pPattern = nullptr; + const ::canvas::ParametricPolyPolygon::Values& aValues = rPolygon.getValues(); + double x0, x1, y0, y1, cx, cy, r0, r1; + + switch( aValues.meType ) + { + case ::canvas::ParametricPolyPolygon::GradientType::Linear: + x0 = 0; + y0 = 0; + x1 = 1; + y1 = 0; + pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 ); + addColorStops( pPattern, aValues.maColors, aValues.maStops, false ); + break; + + case ::canvas::ParametricPolyPolygon::GradientType::Elliptical: + cx = 0; + cy = 0; + r0 = 0; + r1 = 1; + + pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 ); + addColorStops( pPattern, aValues.maColors, aValues.maStops, true ); + break; + default: + break; + } + + return pPattern; + } + + static void doOperation( Operation aOperation, + cairo_t* pCairo, + const uno::Sequence< rendering::Texture >* pTextures, + const SurfaceProviderRef& pDevice, + const basegfx::B2DRange& rBounds ) + { + switch( aOperation ) + { + case Fill: + /* TODO: multitexturing */ + if( pTextures ) + { + const css::rendering::Texture& aTexture ( (*pTextures)[0] ); + if( aTexture.Bitmap.is() ) + { + unsigned char* data = nullptr; + bool bHasAlpha = false; + SurfaceSharedPtr pSurface = surfaceFromXBitmap( (*pTextures)[0].Bitmap, pDevice, data, bHasAlpha ); + + if( pSurface ) + { + cairo_pattern_t* pPattern; + + cairo_save( pCairo ); + + css::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform ); + cairo_matrix_t aScaleMatrix, aTextureMatrix, aScaledTextureMatrix; + + cairo_matrix_init( &aTextureMatrix, + aTransform.m00, aTransform.m10, aTransform.m01, + aTransform.m11, aTransform.m02, aTransform.m12); + + geometry::IntegerSize2D aSize = aTexture.Bitmap->getSize(); + + cairo_matrix_init_scale( &aScaleMatrix, 1.0/aSize.Width, 1.0/aSize.Height ); + cairo_matrix_multiply( &aScaledTextureMatrix, &aScaleMatrix, &aTextureMatrix ); + cairo_matrix_invert( &aScaledTextureMatrix ); + + // we don't care about repeat mode yet, so the workaround is disabled for now + pPattern = cairo_pattern_create_for_surface( pSurface->getCairoSurface().get() ); + + if( aTexture.RepeatModeX == rendering::TexturingMode::REPEAT && + aTexture.RepeatModeY == rendering::TexturingMode::REPEAT ) + { + cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_REPEAT ); + } + else if ( aTexture.RepeatModeX == rendering::TexturingMode::NONE && + aTexture.RepeatModeY == rendering::TexturingMode::NONE ) + { + cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_NONE ); + } + else if ( aTexture.RepeatModeX == rendering::TexturingMode::CLAMP && + aTexture.RepeatModeY == rendering::TexturingMode::CLAMP ) + { + cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_PAD ); + } + + aScaledTextureMatrix.x0 = basegfx::fround( aScaledTextureMatrix.x0 ); + aScaledTextureMatrix.y0 = basegfx::fround( aScaledTextureMatrix.y0 ); + + double x1, y1, x2, y2; + cairo_path_extents(pCairo, &x1, &y1, &x2, &y2); + aScaledTextureMatrix.x0 -= (x1 * aScaledTextureMatrix.xx); + aScaledTextureMatrix.y0 -= (y1 * aScaledTextureMatrix.yy); + + cairo_pattern_set_matrix( pPattern, &aScaledTextureMatrix ); + + cairo_set_source( pCairo, pPattern ); + if( !bHasAlpha ) + cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE ); + cairo_fill( pCairo ); + + cairo_restore( pCairo ); + + cairo_pattern_destroy( pPattern ); + } + + if( data ) + free( data ); + } + else if( aTexture.Gradient.is() ) + { + uno::Reference< lang::XServiceInfo > xRef( aTexture.Gradient, uno::UNO_QUERY ); + + SAL_INFO( "canvas.cairo", "gradient fill" ); + if( xRef.is() && xRef->getImplementationName() == PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME ) + { + // TODO(Q1): Maybe use dynamic_cast here + + // TODO(E1): Return value + // TODO(F1): FillRule + SAL_INFO( "canvas.cairo", "known implementation" ); + + ::canvas::ParametricPolyPolygon* pPolyImpl = static_cast< ::canvas::ParametricPolyPolygon* >( aTexture.Gradient.get() ); + css::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform ); + cairo_matrix_t aTextureMatrix; + + cairo_matrix_init( &aTextureMatrix, + aTransform.m00, aTransform.m10, aTransform.m01, + aTransform.m11, aTransform.m02, aTransform.m12); + if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GradientType::Rectangular ) + { + // no general path gradient yet in cairo; emulate then + cairo_save( pCairo ); + cairo_clip( pCairo ); + + // fill bound rect with start color + cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(), + rBounds.getWidth(), rBounds.getHeight() ); + setColor(pCairo,pPolyImpl->getValues().maColors[0]); + cairo_fill(pCairo); + + cairo_transform( pCairo, &aTextureMatrix ); + + // longest line in gradient bound rect + const unsigned int nGradientSize( + static_cast<unsigned int>( + ::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) ); + + // typical number for pixel of the same color (strip size) + const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 ); + + // use at least three steps, and at utmost the number of color + // steps + const unsigned int nStepCount( + std::max( + 3U, + std::min( + nGradientSize / nStripSize, + 128U )) + 1 ); + + const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0]; + basegfx::utils::KeyStopLerp aLerper(pPolyImpl->getValues().maStops); + for( unsigned int i=1; i<nStepCount; ++i ) + { + const double fT( i/double(nStepCount) ); + + std::ptrdiff_t nIndex; + double fAlpha; + std::tie(nIndex,fAlpha)=aLerper.lerp(fT); + + setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha)); + cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT ); + cairo_fill(pCairo); + } + + cairo_restore( pCairo ); + } + else + { + cairo_pattern_t* pPattern = patternFromParametricPolyPolygon( *pPolyImpl ); + + if( pPattern ) + { + SAL_INFO( "canvas.cairo", "filling with pattern" ); + + cairo_save( pCairo ); + + cairo_transform( pCairo, &aTextureMatrix ); + cairo_set_source( pCairo, pPattern ); + cairo_fill( pCairo ); + cairo_restore( pCairo ); + + cairo_pattern_destroy( pPattern ); -e ... etc. - the rest is truncated