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 commitfbefe07e4cAuthor: Michael Weghorn <m.weghorn@posteo.de> Date: Thu Feb 20 09:42:14 2025 +0100 qt: Remove now unused vcl/inc/qt6/QtSvpSurface.hxx commit595354ab7eAuthor: Julien Nabet <serval2412@yahoo.fr> Date: Wed Feb 19 21:13:49 2025 +0100 Remove also canvas/cairo in gtk4, qt6 and gtk3_kde5 commitd539f6e99eAuthor: Noel Grandin <noelgrandin@gmail.com> Date: Wed Feb 19 18:15:30 2025 +0200 fix "local variable is unused" warning commit704f61b1bdAuthor: Noel Grandin <noelgrandin@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.grandin@collabora.co.uk>
This commit is contained in:
@@ -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 \
|
||||
))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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 \
|
||||
))
|
||||
|
||||
@@ -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:
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,271 @@
|
||||
/* -*- 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/geometry/IntegerPoint2D.hpp>
|
||||
#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
|
||||
#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
|
||||
#include <com/sun/star/rendering/XCanvas.hpp>
|
||||
|
||||
#include <vcl/vclptr.hxx>
|
||||
#include <vcl/virdev.hxx>
|
||||
|
||||
#include <vcl/cairo.hxx>
|
||||
#include "cairo_surfaceprovider.hxx"
|
||||
|
||||
class VirtualDevice;
|
||||
|
||||
namespace basegfx {
|
||||
class B2DPolyPolygon;
|
||||
}
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
class SpriteCanvas;
|
||||
|
||||
enum Operation {
|
||||
Stroke,
|
||||
Fill,
|
||||
Clip
|
||||
};
|
||||
|
||||
class CanvasHelper
|
||||
{
|
||||
public:
|
||||
/// make noncopyable
|
||||
CanvasHelper(const CanvasHelper&) = delete;
|
||||
const CanvasHelper& operator=(const CanvasHelper&) = delete;
|
||||
|
||||
CanvasHelper();
|
||||
|
||||
/// Release all references
|
||||
void disposing();
|
||||
|
||||
/** Initialize canvas helper
|
||||
|
||||
This method late-initializes the canvas helper, providing
|
||||
it with the necessary device and size. Note that the
|
||||
CanvasHelper does <em>not</em> take ownership of the
|
||||
passed rDevice reference, nor does it perform any
|
||||
reference counting. Thus, to prevent the reference counted
|
||||
SpriteCanvas object from deletion, the user of this class
|
||||
is responsible for holding ref-counted references itself!
|
||||
|
||||
@param rSizePixel
|
||||
Size of the output surface in pixel.
|
||||
|
||||
@param rDevice
|
||||
Reference device this canvas is associated with
|
||||
|
||||
*/
|
||||
void init( const ::basegfx::B2ISize& rSizePixel,
|
||||
SurfaceProvider& rSurfaceProvider,
|
||||
css::rendering::XGraphicDevice* pDevice );
|
||||
|
||||
void setSize( const ::basegfx::B2ISize& rSize );
|
||||
void setSurface( const ::cairo::SurfaceSharedPtr& pSurface, bool bHasAlpha );
|
||||
|
||||
// CanvasHelper functionality
|
||||
// ==========================
|
||||
|
||||
// XCanvas (only providing, not implementing the
|
||||
// interface. Also note subtle method parameter differences)
|
||||
void clear();
|
||||
void drawLine( const css::rendering::XCanvas* pCanvas,
|
||||
const css::geometry::RealPoint2D& aStartPoint,
|
||||
const css::geometry::RealPoint2D& aEndPoint,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
void drawBezier( const css::rendering::XCanvas* pCanvas,
|
||||
const css::geometry::RealBezierSegment2D& aBezierSegment,
|
||||
const css::geometry::RealPoint2D& aEndPoint,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokePolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokeTexturedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence< css::rendering::Texture >& textures,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokeTextureMappedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence< css::rendering::Texture >& textures,
|
||||
const css::uno::Reference< css::geometry::XMapping2D >& xMapping,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XPolyPolygon2D >
|
||||
queryStrokeShapes( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillTexturedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence< css::rendering::Texture >& textures );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillTextureMappedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence< css::rendering::Texture >& textures,
|
||||
const css::uno::Reference< css::geometry::XMapping2D >& xMapping );
|
||||
|
||||
css::uno::Reference< css::rendering::XCanvasFont >
|
||||
createFont( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::FontRequest& fontRequest,
|
||||
const css::uno::Sequence< css::beans::PropertyValue >& extraFontProperties,
|
||||
const css::geometry::Matrix2D& fontMatrix );
|
||||
|
||||
css::uno::Sequence< css::rendering::FontInfo >
|
||||
queryAvailableFonts( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::FontInfo& aFilter,
|
||||
const css::uno::Sequence< css::beans::PropertyValue >& aFontProperties );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawText( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::StringContext& text,
|
||||
const css::uno::Reference< css::rendering::XCanvasFont >& xFont,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
sal_Int8 textDirection );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawTextLayout( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XTextLayout >& laidOutText,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawBitmap( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XBitmap >& xBitmap,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawBitmapModulated( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference< css::rendering::XBitmap >& xBitmap,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XGraphicDevice >
|
||||
getDevice() { return css::uno::Reference< css::rendering::XGraphicDevice >(mpDevice); }
|
||||
|
||||
// BitmapCanvasHelper functionality
|
||||
// ================================
|
||||
|
||||
css::geometry::IntegerSize2D getSize() const;
|
||||
|
||||
css::uno::Reference< css::rendering::XBitmap >
|
||||
getScaledBitmap( const css::geometry::RealSize2D& newSize,
|
||||
bool beFast );
|
||||
|
||||
css::uno::Sequence< sal_Int8 >
|
||||
getData( css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect );
|
||||
|
||||
css::uno::Sequence< sal_Int8 >
|
||||
getPixel( css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos );
|
||||
|
||||
css::rendering::IntegerBitmapLayout getMemoryLayout();
|
||||
|
||||
void doPolyPolygonPath( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
Operation aOperation,
|
||||
bool bNoLineJoin = false,
|
||||
const css::uno::Sequence< css::rendering::Texture >* pTextures=nullptr ) const;
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive > implDrawBitmapSurface(
|
||||
const css::rendering::XCanvas* pCanvas,
|
||||
const ::cairo::SurfaceSharedPtr& pSurface,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::geometry::IntegerSize2D& rSize,
|
||||
bool bModulateColors,
|
||||
bool bHasAlpha );
|
||||
|
||||
bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
|
||||
protected:
|
||||
/** Surface provider
|
||||
|
||||
Deliberately not a refcounted reference, because of
|
||||
potential circular references for canvas. Provides us with
|
||||
our output surface and associated functionality.
|
||||
*/
|
||||
SurfaceProvider* mpSurfaceProvider;
|
||||
|
||||
/** Phyical output device
|
||||
|
||||
Deliberately not a refcounted reference, because of
|
||||
potential circular references for spritecanvas.
|
||||
*/
|
||||
css::rendering::XGraphicDevice* mpDevice;
|
||||
|
||||
private:
|
||||
|
||||
VclPtr<VirtualDevice> mpVirtualDevice;
|
||||
|
||||
void useStates( const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
bool setColor );
|
||||
|
||||
css::rendering::IntegerBitmapLayout impl_getMemoryLayout( sal_Int32 nWidth, sal_Int32 nHeight );
|
||||
|
||||
/// When true, content is able to represent alpha
|
||||
bool mbHaveAlpha;
|
||||
|
||||
::cairo::CairoSharedPtr mpCairo;
|
||||
::cairo::SurfaceSharedPtr mpSurface;
|
||||
::basegfx::B2ISize maSize;
|
||||
};
|
||||
|
||||
/// also needed from SpriteHelper
|
||||
void doPolyPolygonImplementation( const ::basegfx::B2DPolyPolygon& aPolyPolygon,
|
||||
Operation aOperation,
|
||||
cairo_t* pCairo,
|
||||
const css::uno::Sequence< css::rendering::Texture >* pTextures,
|
||||
const SurfaceProviderRef& pDevice,
|
||||
css::rendering::FillRule eFillrule );
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,303 @@
|
||||
/* -*- 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/TextDirection.hpp>
|
||||
|
||||
#include <rtl/math.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <vcl/metric.hxx>
|
||||
#include <vcl/virdev.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
#include <verifyinput.hxx>
|
||||
|
||||
#include "cairo_canvasfont.hxx"
|
||||
#include "cairo_canvashelper.hxx"
|
||||
#include "cairo_textlayout.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* ,
|
||||
const rendering::FontRequest& fontRequest,
|
||||
const uno::Sequence< beans::PropertyValue >& extraFontProperties,
|
||||
const geometry::Matrix2D& fontMatrix )
|
||||
{
|
||||
return uno::Reference< rendering::XCanvasFont >( new CanvasFont( fontRequest, extraFontProperties, fontMatrix, mpSurfaceProvider ));
|
||||
}
|
||||
|
||||
uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* ,
|
||||
const rendering::FontInfo& /*aFilter*/,
|
||||
const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< rendering::FontInfo >();
|
||||
}
|
||||
|
||||
static bool
|
||||
setupFontTransform( ::OutputDevice const & rOutDev,
|
||||
::Point& o_rPoint,
|
||||
vcl::Font& io_rVCLFont,
|
||||
const rendering::ViewState& rViewState,
|
||||
const rendering::RenderState& rRenderState )
|
||||
{
|
||||
::basegfx::B2DHomMatrix aMatrix;
|
||||
|
||||
::canvas::tools::mergeViewAndRenderTransform(aMatrix,
|
||||
rViewState,
|
||||
rRenderState);
|
||||
|
||||
::basegfx::B2DTuple aScale;
|
||||
::basegfx::B2DTuple aTranslate;
|
||||
double nRotate, nShearX;
|
||||
|
||||
aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );
|
||||
|
||||
// query font metric _before_ tampering with width and height
|
||||
if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) )
|
||||
{
|
||||
// retrieve true font width
|
||||
const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetAverageFontWidth() );
|
||||
|
||||
const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) );
|
||||
|
||||
if( !nScaledFontWidth )
|
||||
{
|
||||
// scale is smaller than one pixel - disable text
|
||||
// output altogether
|
||||
return false;
|
||||
}
|
||||
|
||||
io_rVCLFont.SetAverageFontWidth( nScaledFontWidth );
|
||||
}
|
||||
|
||||
if( !::rtl::math::approxEqual(aScale.getY(), 1.0) )
|
||||
{
|
||||
const sal_Int32 nFontHeight( io_rVCLFont.GetFontHeight() );
|
||||
io_rVCLFont.SetFontHeight( ::basegfx::fround(nFontHeight * aScale.getY()) );
|
||||
}
|
||||
|
||||
io_rVCLFont.SetOrientation( Degree10( ::basegfx::fround(-basegfx::rad2deg<10>(fmod(nRotate, 2*M_PI))) ) );
|
||||
|
||||
// TODO(F2): Missing functionality in VCL: shearing
|
||||
o_rPoint.setX( ::basegfx::fround(aTranslate.getX()) );
|
||||
o_rPoint.setY( ::basegfx::fround(aTranslate.getY()) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
setupOutDevState( OutputDevice& rOutDev,
|
||||
const rendering::XCanvas* pOwner,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
::canvas::tools::verifyInput( renderState,
|
||||
__func__,
|
||||
const_cast<rendering::XCanvas*>(pOwner), // only for refcount
|
||||
2,
|
||||
3 /* text */ );
|
||||
|
||||
// TODO(P2): Don't change clipping all the time, maintain current clip
|
||||
// state and change only when update is necessary
|
||||
::canvas::tools::clipOutDev(viewState, renderState, rOutDev);
|
||||
|
||||
Color aColor( COL_WHITE );
|
||||
|
||||
if( renderState.DeviceColor.getLength() > 2 )
|
||||
{
|
||||
aColor = vcl::unotools::stdColorSpaceSequenceToColor( renderState.DeviceColor );
|
||||
}
|
||||
|
||||
// extract alpha, and make color opaque
|
||||
// afterwards. Otherwise, OutputDevice won't draw anything
|
||||
aColor.SetAlpha(255);
|
||||
|
||||
rOutDev.SetTextColor( aColor );
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class DeviceSettingsGuard
|
||||
{
|
||||
private:
|
||||
VclPtr<OutputDevice> mpVirtualDevice;
|
||||
bool mbMappingWasEnabled;
|
||||
public:
|
||||
DeviceSettingsGuard(OutputDevice *pVirtualDevice)
|
||||
: mpVirtualDevice(pVirtualDevice)
|
||||
, mbMappingWasEnabled(mpVirtualDevice->IsMapModeEnabled())
|
||||
{
|
||||
mpVirtualDevice->Push();
|
||||
mpVirtualDevice->EnableMapMode(false);
|
||||
}
|
||||
|
||||
~DeviceSettingsGuard()
|
||||
{
|
||||
mpVirtualDevice->EnableMapMode(mbMappingWasEnabled);
|
||||
mpVirtualDevice->Pop();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static bool setupTextOutput( OutputDevice& rOutDev,
|
||||
const rendering::XCanvas* pOwner,
|
||||
::Point& o_rOutPos,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
const uno::Reference< rendering::XCanvasFont >& xFont )
|
||||
{
|
||||
setupOutDevState( rOutDev, pOwner, viewState, renderState );
|
||||
|
||||
CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
|
||||
|
||||
ENSURE_ARG_OR_THROW( pFont,
|
||||
"CanvasHelper::setupTextOutput(): Font not compatible with this canvas" );
|
||||
|
||||
vcl::Font aVCLFont = pFont->getVCLFont();
|
||||
|
||||
Color aColor( COL_BLACK );
|
||||
|
||||
if( renderState.DeviceColor.getLength() > 2 )
|
||||
{
|
||||
aColor = vcl::unotools::stdColorSpaceSequenceToColor(renderState.DeviceColor );
|
||||
}
|
||||
|
||||
// setup font color
|
||||
aVCLFont.SetColor( aColor );
|
||||
aVCLFont.SetFillColor( aColor );
|
||||
|
||||
if (pFont->getEmphasisMark())
|
||||
aVCLFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark()));
|
||||
|
||||
// no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here.
|
||||
if( !setupFontTransform( rOutDev, o_rOutPos, aVCLFont, viewState, renderState ) )
|
||||
return false;
|
||||
|
||||
rOutDev.SetFont( aVCLFont );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* pOwner,
|
||||
const rendering::StringContext& text,
|
||||
const uno::Reference< rendering::XCanvasFont >& xFont,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
sal_Int8 textDirection )
|
||||
{
|
||||
#ifdef CAIRO_CANVAS_PERF_TRACE
|
||||
struct timespec aTimer;
|
||||
mxDevice->startPerfTrace( &aTimer );
|
||||
#endif
|
||||
|
||||
ENSURE_ARG_OR_THROW( xFont.is(),
|
||||
"CanvasHelper::drawText(): font is NULL");
|
||||
|
||||
if( !mpVirtualDevice )
|
||||
mpVirtualDevice = mpSurface->createVirtualDevice();
|
||||
|
||||
if( mpVirtualDevice )
|
||||
{
|
||||
DeviceSettingsGuard aGuard(mpVirtualDevice.get());
|
||||
|
||||
::Point aOutpos;
|
||||
if( !setupTextOutput( *mpVirtualDevice, pOwner, aOutpos, viewState, renderState, xFont ) )
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary
|
||||
|
||||
// change text direction and layout mode
|
||||
vcl::text::ComplexTextLayoutFlags nLayoutMode(vcl::text::ComplexTextLayoutFlags::Default);
|
||||
switch( textDirection )
|
||||
{
|
||||
case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
|
||||
case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
|
||||
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiStrong;
|
||||
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
|
||||
break;
|
||||
|
||||
case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
|
||||
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl;
|
||||
[[fallthrough]];
|
||||
case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
|
||||
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::BiDiStrong;
|
||||
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginRight;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(F2): alpha
|
||||
mpVirtualDevice->SetLayoutMode( nLayoutMode );
|
||||
|
||||
rtl::Reference pTextLayout( new TextLayout(text, textDirection, 0, CanvasFont::Reference(dynamic_cast< CanvasFont* >( xFont.get() )), mpSurfaceProvider) );
|
||||
pTextLayout->draw(*mpVirtualDevice, aOutpos, viewState, renderState);
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* pOwner,
|
||||
const uno::Reference< rendering::XTextLayout >& xLayoutedText,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_ARG_OR_THROW( xLayoutedText.is(),
|
||||
"CanvasHelper::drawTextLayout(): layout is NULL");
|
||||
|
||||
TextLayout* pTextLayout = dynamic_cast< TextLayout* >( xLayoutedText.get() );
|
||||
|
||||
if( pTextLayout )
|
||||
{
|
||||
if( !mpVirtualDevice )
|
||||
mpVirtualDevice = mpSurface->createVirtualDevice();
|
||||
|
||||
if( mpVirtualDevice )
|
||||
{
|
||||
DeviceSettingsGuard aGuard(mpVirtualDevice.get());
|
||||
|
||||
// TODO(T3): Race condition. We're taking the font
|
||||
// from xLayoutedText, and then calling draw() at it,
|
||||
// without exclusive access. Move setupTextOutput(),
|
||||
// e.g. to impltools?
|
||||
|
||||
::Point aOutpos;
|
||||
if( !setupTextOutput( *mpVirtualDevice, pOwner, aOutpos, viewState, renderState, xLayoutedText->getFont() ) )
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary
|
||||
|
||||
// TODO(F2): What about the offset scalings?
|
||||
pTextLayout->draw(*mpVirtualDevice, aOutpos, viewState, renderState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ENSURE_ARG_OR_THROW( false,
|
||||
"CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,257 @@
|
||||
/* -*- 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/utils/canvastools.hxx>
|
||||
#include <basegfx/utils/unopolypolygon.hxx>
|
||||
#include <tools/stream.hxx>
|
||||
#include <vcl/bitmapex.hxx>
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <vcl/dibtools.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "cairo_canvasbitmap.hxx"
|
||||
#include "cairo_devicehelper.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
DeviceHelper::DeviceHelper() :
|
||||
mpSurfaceProvider( nullptr ),
|
||||
mpRefDevice( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
void DeviceHelper::implInit( SurfaceProvider& rSurfaceProvider,
|
||||
OutputDevice& rRefDevice )
|
||||
{
|
||||
mpSurfaceProvider = &rSurfaceProvider;
|
||||
mpRefDevice = &rRefDevice;
|
||||
|
||||
// no own surface, this is handled by derived classes
|
||||
}
|
||||
|
||||
void DeviceHelper::init( SurfaceProvider& rSurfaceProvider,
|
||||
OutputDevice& rRefDevice )
|
||||
{
|
||||
implInit(rSurfaceProvider, rRefDevice);
|
||||
|
||||
OutputDevice* pOutDev = getOutputDevice();
|
||||
mpSurface = pOutDev->CreateSurface(pOutDev->GetOutOffXPixel(),
|
||||
pOutDev->GetOutOffYPixel(),
|
||||
pOutDev->GetOutputWidthPixel(),
|
||||
pOutDev->GetOutputHeightPixel());
|
||||
}
|
||||
|
||||
void DeviceHelper::disposing()
|
||||
{
|
||||
// release all references
|
||||
mpSurface.reset();
|
||||
mpRefDevice = nullptr;
|
||||
mpSurfaceProvider = nullptr;
|
||||
}
|
||||
|
||||
void DeviceHelper::setSize( const ::basegfx::B2ISize& rSize )
|
||||
{
|
||||
SAL_INFO(
|
||||
"canvas.cairo",
|
||||
"device size " << rSize.getWidth() << " x " << rSize.getHeight());
|
||||
|
||||
if( !mpRefDevice )
|
||||
return; // disposed
|
||||
|
||||
OutputDevice* pOutDev = getOutputDevice();
|
||||
|
||||
// X11 only
|
||||
bool bReuseSurface = mpSurface &&
|
||||
mpSurface->Resize(rSize.getWidth() + pOutDev->GetOutOffXPixel(),
|
||||
rSize.getHeight() + pOutDev->GetOutOffYPixel());
|
||||
|
||||
if (!bReuseSurface)
|
||||
{
|
||||
mpSurface = pOutDev->CreateSurface(
|
||||
pOutDev->GetOutOffXPixel(),
|
||||
pOutDev->GetOutOffYPixel(),
|
||||
rSize.getWidth(), rSize.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
geometry::RealSize2D DeviceHelper::getPhysicalResolution()
|
||||
{
|
||||
// Map a one-by-one millimeter box to pixel
|
||||
const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
|
||||
mpRefDevice->SetMapMode( MapMode(MapUnit::MapMM) );
|
||||
const Size aPixelSize( mpRefDevice->LogicToPixel(Size(1,1)) );
|
||||
mpRefDevice->SetMapMode( aOldMapMode );
|
||||
|
||||
return vcl::unotools::size2DFromSize( aPixelSize );
|
||||
}
|
||||
|
||||
geometry::RealSize2D DeviceHelper::getPhysicalSize()
|
||||
{
|
||||
if( !mpRefDevice )
|
||||
return ::canvas::tools::createInfiniteSize2D(); // we're disposed
|
||||
|
||||
// Map the pixel dimensions of the output window to millimeter
|
||||
const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
|
||||
mpRefDevice->SetMapMode( MapMode(MapUnit::MapMM) );
|
||||
const Size aLogSize( mpRefDevice->PixelToLogic(mpRefDevice->GetOutputSizePixel()) );
|
||||
mpRefDevice->SetMapMode( aOldMapMode );
|
||||
|
||||
return vcl::unotools::size2DFromSize( aLogSize );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
|
||||
const uno::Reference< rendering::XGraphicDevice >& ,
|
||||
const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
|
||||
{
|
||||
// disposed?
|
||||
if( !mpSurfaceProvider )
|
||||
return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XLinePolyPolygon2D >(
|
||||
new ::basegfx::unotools::UnoPolyPolygon(
|
||||
::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
|
||||
const uno::Reference< rendering::XGraphicDevice >& ,
|
||||
const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
|
||||
{
|
||||
// disposed?
|
||||
if( !mpSurfaceProvider )
|
||||
return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XBezierPolyPolygon2D >(
|
||||
new ::basegfx::unotools::UnoPolyPolygon(
|
||||
::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
// disposed?
|
||||
if( !mpSurfaceProvider )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XBitmap >(
|
||||
new CanvasBitmap(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
|
||||
SurfaceProviderRef(mpSurfaceProvider),
|
||||
rDevice.get(),
|
||||
false ));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& ,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
// disposed?
|
||||
if( !mpSurfaceProvider )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XBitmap >(
|
||||
new CanvasBitmap(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
|
||||
SurfaceProviderRef(mpSurfaceProvider),
|
||||
rDevice.get(),
|
||||
true ));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& ,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::isAccelerated() const
|
||||
{
|
||||
return css::uno::Any(false);
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::getDeviceHandle() const
|
||||
{
|
||||
return uno::Any( reinterpret_cast< sal_Int64 >(mpRefDevice.get()) );
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::getSurfaceHandle() const
|
||||
{
|
||||
return uno::Any();
|
||||
}
|
||||
|
||||
uno::Reference<rendering::XColorSpace> const & DeviceHelper::getColorSpace() const
|
||||
{
|
||||
static uno::Reference<rendering::XColorSpace> SPACE = vcl::unotools::createStandardColorSpace();
|
||||
// always the same
|
||||
return SPACE;
|
||||
}
|
||||
|
||||
void DeviceHelper::dumpScreenContent() const
|
||||
{
|
||||
static sal_Int32 nFilePostfixCount(0);
|
||||
|
||||
if( !mpRefDevice )
|
||||
return;
|
||||
|
||||
OUString aFilename = "dbg_frontbuffer" + OUString::number(nFilePostfixCount) + ".bmp";
|
||||
|
||||
SvFileStream aStream( aFilename, StreamMode::STD_READWRITE );
|
||||
|
||||
const ::Point aEmptyPoint;
|
||||
bool bOldMap( mpRefDevice->IsMapModeEnabled() );
|
||||
mpRefDevice->EnableMapMode( false );
|
||||
const ::BitmapEx aTempBitmap(mpRefDevice->GetBitmapEx(aEmptyPoint, mpRefDevice->GetOutputSizePixel()));
|
||||
WriteDIB(aTempBitmap, aStream, false);
|
||||
mpRefDevice->EnableMapMode( bOldMap );
|
||||
|
||||
++nFilePostfixCount;
|
||||
}
|
||||
|
||||
SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent )
|
||||
{
|
||||
if( mpSurface )
|
||||
return mpSurface->getSimilar( aContent, rSize.getWidth(), rSize.getHeight() );
|
||||
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr DeviceHelper::createSurface( BitmapSystemData const & rData, const Size& rSize )
|
||||
{
|
||||
if (mpRefDevice)
|
||||
return mpRefDevice->CreateBitmapSurface(rData, rSize);
|
||||
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,122 @@
|
||||
/* -*- 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/rendering/XGraphicDevice.hpp>
|
||||
|
||||
#include <vcl/outdev.hxx>
|
||||
|
||||
#include "cairo_surfaceprovider.hxx"
|
||||
|
||||
/* Definition of DeviceHelper class */
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
class DeviceHelper
|
||||
{
|
||||
public:
|
||||
/// make noncopyable
|
||||
DeviceHelper(const DeviceHelper&) = delete;
|
||||
const DeviceHelper& operator=(const DeviceHelper&) = delete;
|
||||
|
||||
DeviceHelper();
|
||||
|
||||
/** init helper
|
||||
|
||||
@param rCanvas
|
||||
Owning canvas.
|
||||
|
||||
@param rRefDevice
|
||||
Reference output device. Needed for resolution
|
||||
calculations etc.
|
||||
*/
|
||||
void init( SurfaceProvider& rSurfaceProvider,
|
||||
OutputDevice& rRefDevice );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// XWindowGraphicDevice
|
||||
css::geometry::RealSize2D getPhysicalResolution();
|
||||
css::geometry::RealSize2D getPhysicalSize();
|
||||
css::uno::Reference< css::rendering::XLinePolyPolygon2D > createCompatibleLinePolyPolygon(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > >& points );
|
||||
css::uno::Reference< css::rendering::XBezierPolyPolygon2D > createCompatibleBezierPolyPolygon(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > >& points );
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
|
||||
css::uno::Any isAccelerated() const;
|
||||
css::uno::Any getDeviceHandle() const;
|
||||
css::uno::Any getSurfaceHandle() const;
|
||||
css::uno::Reference<
|
||||
css::rendering::XColorSpace > const & getColorSpace() const;
|
||||
|
||||
/** called when DumpScreenContent property is enabled on
|
||||
XGraphicDevice, and writes out bitmaps of current screen.
|
||||
*/
|
||||
void dumpScreenContent() const;
|
||||
|
||||
OutputDevice* getOutputDevice() const { return mpRefDevice; }
|
||||
const ::cairo::SurfaceSharedPtr& getSurface() const { return mpSurface; }
|
||||
::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, int aContent );
|
||||
::cairo::SurfaceSharedPtr createSurface( BitmapSystemData const & rData, const Size& rSize );
|
||||
|
||||
protected:
|
||||
/** init helper
|
||||
|
||||
@param rCanvas
|
||||
Owning canvas.
|
||||
|
||||
@param rRefDevice
|
||||
Reference output device. Needed for resolution
|
||||
calculations etc.
|
||||
*/
|
||||
void implInit( SurfaceProvider& rSurfaceProvider,
|
||||
OutputDevice& rRefDevice );
|
||||
void setSize( const ::basegfx::B2ISize& rSize );
|
||||
|
||||
private:
|
||||
/** Surface provider
|
||||
|
||||
Deliberately not a refcounted reference, because of
|
||||
potential circular references for canvas. Provides us with
|
||||
our output surface and associated functionality.
|
||||
*/
|
||||
SurfaceProvider* mpSurfaceProvider;
|
||||
|
||||
VclPtr<OutputDevice> mpRefDevice;
|
||||
::cairo::SurfaceSharedPtr mpSurface;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,48 @@
|
||||
/* -*- 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/rendering/RenderState.hpp>
|
||||
#include <com/sun/star/rendering/ViewState.hpp>
|
||||
|
||||
#include <vcl/cairo.hxx>
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
/* Definition of RepaintTarget interface */
|
||||
|
||||
/** Target interface for XCachedPrimitive implementations
|
||||
|
||||
This interface must be implemented on all canvas
|
||||
implementations that hand out XCachedPrimitives
|
||||
*/
|
||||
class SAL_LOPLUGIN_ANNOTATE("crosscast") RepaintTarget
|
||||
{
|
||||
public:
|
||||
virtual ~RepaintTarget() {}
|
||||
|
||||
// call this when a bitmap is repainted
|
||||
virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState ) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* -*- 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/sprite.hxx>
|
||||
|
||||
#include <vcl/cairo.hxx>
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
/** Specialization of ::canvas::Sprite interface, to also provide
|
||||
redraw methods.
|
||||
*/
|
||||
class Sprite : public ::canvas::Sprite
|
||||
{
|
||||
public:
|
||||
|
||||
/** Redraw sprite at the stored position.
|
||||
|
||||
@param bBufferedUpdate
|
||||
When true, the redraw does <em>not</em> happen directly on
|
||||
the front buffer, but within a VDev. Used to speed up
|
||||
drawing.
|
||||
*/
|
||||
virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
|
||||
bool bBufferedUpdate ) const = 0;
|
||||
|
||||
/** Redraw sprite at the given position.
|
||||
|
||||
@param rPos
|
||||
Output position of the sprite. Overrides the sprite's own
|
||||
output position.
|
||||
|
||||
@param bBufferedUpdate
|
||||
When true, the redraw does <em>not</em> happen directly on
|
||||
the front buffer, but within a VDev. Used to speed up
|
||||
drawing.
|
||||
*/
|
||||
virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
|
||||
const ::basegfx::B2DPoint& rOrigOutputPos,
|
||||
bool bBufferedUpdate ) const = 0;
|
||||
|
||||
protected:
|
||||
~Sprite() {}
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,232 @@
|
||||
/* -*- 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/range/b2irange.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/awt/XTopWindow.hpp>
|
||||
#include <com/sun/star/awt/Rectangle.hpp>
|
||||
#include <com/sun/star/lang/NoSupportException.hpp>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
|
||||
#include "cairo_spritecanvas.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
|
||||
const uno::Reference< uno::XComponentContext >& /*rxContext*/ ) :
|
||||
maArguments(aArguments)
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteCanvas::initialize()
|
||||
{
|
||||
SAL_INFO("canvas.cairo", "CairoSpriteCanvas created " << this);
|
||||
|
||||
// #i64742# Only call initialize when not in probe mode
|
||||
if( !maArguments.hasElements() )
|
||||
return;
|
||||
|
||||
/* 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
|
||||
*/
|
||||
ENSURE_ARG_OR_THROW( maArguments.getLength() >= 4 &&
|
||||
maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER &&
|
||||
maArguments[3].getValueTypeClass() == uno::TypeClass_INTERFACE,
|
||||
"CairoSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
|
||||
|
||||
awt::Rectangle aRect;
|
||||
maArguments[1] >>= aRect;
|
||||
|
||||
bool bIsFullscreen( false );
|
||||
maArguments[2] >>= bIsFullscreen;
|
||||
|
||||
uno::Reference< awt::XWindow > xParentWindow;
|
||||
maArguments[3] >>= xParentWindow;
|
||||
|
||||
VclPtr<vcl::Window> pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
|
||||
if( !pParentWindow )
|
||||
throw lang::NoSupportException(
|
||||
u"Parent window not VCL window, or canvas out-of-process!"_ustr, nullptr);
|
||||
|
||||
bool bHasCairo = pParentWindow->GetOutDev()->SupportsCairo();
|
||||
ENSURE_ARG_OR_THROW(bHasCairo,
|
||||
"CairoSpriteCanvas::SpriteCanvas: No Cairo capability");
|
||||
|
||||
Size aPixelSize( pParentWindow->GetOutputSizePixel() );
|
||||
const ::basegfx::B2ISize aSize( aPixelSize.Width(),
|
||||
aPixelSize.Height() );
|
||||
|
||||
// setup helper
|
||||
maDeviceHelper.init( *pParentWindow,
|
||||
*this,
|
||||
aSize,
|
||||
bIsFullscreen );
|
||||
|
||||
setWindow(uno::Reference<awt::XWindow2>(xParentWindow, uno::UNO_QUERY_THROW));
|
||||
|
||||
maCanvasHelper.init( maRedrawManager,
|
||||
*this,
|
||||
aSize );
|
||||
|
||||
maArguments.realloc(0);
|
||||
}
|
||||
|
||||
void SpriteCanvas::disposeThis()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
// forward to parent
|
||||
SpriteCanvasBaseT::disposeThis();
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::showBuffer( sal_Bool bUpdateAll )
|
||||
{
|
||||
return updateScreen( bUpdateAll );
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::switchBuffer( sal_Bool bUpdateAll )
|
||||
{
|
||||
return updateScreen( bUpdateAll );
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::updateScreen( sal_Bool bUpdateAll )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
// avoid repaints on hidden window (hidden: not mapped to
|
||||
// screen). Return failure, since the screen really has _not_
|
||||
// been updated (caller should try again later)
|
||||
return mbIsVisible && maCanvasHelper.updateScreen(
|
||||
::basegfx::unotools::b2IRectangleFromAwtRectangle(maBounds),
|
||||
bUpdateAll,
|
||||
mbSurfaceDirty);
|
||||
}
|
||||
|
||||
OUString SAL_CALL SpriteCanvas::getServiceName( )
|
||||
{
|
||||
return u"com.sun.star.rendering.SpriteCanvas.Cairo"_ustr;
|
||||
}
|
||||
|
||||
// XServiceInfo
|
||||
sal_Bool SpriteCanvas::supportsService(const OUString& sServiceName)
|
||||
{
|
||||
return cppu::supportsService(this, sServiceName);
|
||||
|
||||
}
|
||||
OUString SpriteCanvas::getImplementationName()
|
||||
{
|
||||
return u"com.sun.star.comp.rendering.SpriteCanvas.Cairo"_ustr;
|
||||
}
|
||||
css::uno::Sequence< OUString > SpriteCanvas::getSupportedServiceNames()
|
||||
{
|
||||
return { getServiceName() };
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteCanvas::getSurface()
|
||||
{
|
||||
return maDeviceHelper.getBufferSurface();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteCanvas::createSurface( const ::basegfx::B2ISize& rSize, int aContent )
|
||||
{
|
||||
return maDeviceHelper.createSurface( rSize, aContent );
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteCanvas::createSurface( ::Bitmap& rBitmap )
|
||||
{
|
||||
BitmapSystemData aData;
|
||||
if( rBitmap.GetSystemData( aData ) ) {
|
||||
const Size aSize = rBitmap.GetSizePixel();
|
||||
|
||||
return maDeviceHelper.createSurface( aData, aSize );
|
||||
}
|
||||
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteCanvas::changeSurface()
|
||||
{
|
||||
// non-modifiable surface here
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
|
||||
OutputDevice* SpriteCanvas::getOutputDevice()
|
||||
{
|
||||
return maDeviceHelper.getOutputDevice();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr const & SpriteCanvas::getBufferSurface() const
|
||||
{
|
||||
return maDeviceHelper.getBufferSurface();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr const & SpriteCanvas::getWindowSurface() const
|
||||
{
|
||||
return maDeviceHelper.getWindowSurface();
|
||||
}
|
||||
|
||||
const ::basegfx::B2ISize& SpriteCanvas::getSizePixel() const
|
||||
{
|
||||
return maDeviceHelper.getSizePixel();
|
||||
}
|
||||
|
||||
void SpriteCanvas::setSizePixel( const ::basegfx::B2ISize& rSize )
|
||||
{
|
||||
maCanvasHelper.setSize( rSize );
|
||||
// re-set background surface, in case it needed recreation
|
||||
maCanvasHelper.setSurface( maDeviceHelper.getBufferSurface(),
|
||||
false );
|
||||
}
|
||||
|
||||
void SpriteCanvas::flush()
|
||||
{
|
||||
maDeviceHelper.flush();
|
||||
}
|
||||
|
||||
bool SpriteCanvas::repaint( const SurfaceSharedPtr& pSurface,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
return maCanvasHelper.repaint( pSurface, viewState, renderState );
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
||||
com_sun_star_comp_rendering_SpriteCanvas_Cairo_get_implementation(
|
||||
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
|
||||
{
|
||||
rtl::Reference<cairocanvas::SpriteCanvas> p = new cairocanvas::SpriteCanvas(args, context);
|
||||
p->initialize();
|
||||
return cppu::acquire(p.get());
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,159 @@
|
||||
/* -*- 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/awt/XWindowListener.hpp>
|
||||
#include <com/sun/star/util/XUpdatable.hpp>
|
||||
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||
|
||||
#include <cppuhelper/compbase.hxx>
|
||||
#include <comphelper/uno3.hxx>
|
||||
|
||||
#include <base/spritecanvasbase.hxx>
|
||||
#include <base/spritesurface.hxx>
|
||||
#include <base/disambiguationhelper.hxx>
|
||||
#include <base/bufferedgraphicdevicebase.hxx>
|
||||
|
||||
#include "cairo_spritedevicehelper.hxx"
|
||||
#include "cairo_repainttarget.hxx"
|
||||
#include "cairo_surfaceprovider.hxx"
|
||||
#include "cairo_spritecanvashelper.hxx"
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XSpriteCanvas,
|
||||
css::rendering::XIntegerBitmap,
|
||||
css::rendering::XGraphicDevice,
|
||||
css::lang::XMultiServiceFactory,
|
||||
css::rendering::XBufferController,
|
||||
css::awt::XWindowListener,
|
||||
css::util::XUpdatable,
|
||||
css::beans::XPropertySet,
|
||||
css::lang::XServiceName,
|
||||
css::lang::XServiceInfo > WindowGraphicDeviceBase_Base;
|
||||
typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::DisambiguationHelper< WindowGraphicDeviceBase_Base >,
|
||||
SpriteDeviceHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > SpriteCanvasBase_Base;
|
||||
/** Mixin SpriteSurface
|
||||
|
||||
Have to mixin the SpriteSurface before deriving from
|
||||
::canvas::SpriteCanvasBase, 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::SpriteCanvasBase directly from
|
||||
::canvas::SpriteSurface (because derivees of
|
||||
::canvas::SpriteCanvasBase 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 SpriteCanvasBaseSpriteSurface_Base : public SpriteCanvasBase_Base,
|
||||
public ::canvas::SpriteSurface,
|
||||
public SurfaceProvider
|
||||
{
|
||||
};
|
||||
|
||||
typedef ::canvas::SpriteCanvasBase< SpriteCanvasBaseSpriteSurface_Base,
|
||||
SpriteCanvasHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > SpriteCanvasBaseT;
|
||||
|
||||
/** Product of this component's factory.
|
||||
|
||||
The SpriteCanvas 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 SpriteCanvas : public SpriteCanvasBaseT,
|
||||
public RepaintTarget
|
||||
{
|
||||
public:
|
||||
SpriteCanvas( const css::uno::Sequence< css::uno::Any >& aArguments,
|
||||
const css::uno::Reference< css::uno::XComponentContext >& rxContext );
|
||||
|
||||
void initialize();
|
||||
|
||||
/// 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( SpriteCanvas, WindowGraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase )
|
||||
|
||||
// XBufferController (partial)
|
||||
virtual sal_Bool SAL_CALL showBuffer( sal_Bool bUpdateAll ) override;
|
||||
virtual sal_Bool SAL_CALL switchBuffer( sal_Bool bUpdateAll ) override;
|
||||
|
||||
// XSpriteCanvas (partial)
|
||||
virtual sal_Bool SAL_CALL updateScreen( sal_Bool bUpdateAll ) override;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
::cairo::SurfaceSharedPtr const & getWindowSurface() const;
|
||||
::cairo::SurfaceSharedPtr const & getBufferSurface() const;
|
||||
|
||||
const ::basegfx::B2ISize& getSizePixel() const;
|
||||
void setSizePixel( const ::basegfx::B2ISize& rSize );
|
||||
void flush();
|
||||
|
||||
private:
|
||||
css::uno::Sequence< css::uno::Any > maArguments;
|
||||
};
|
||||
|
||||
typedef ::rtl::Reference< SpriteCanvas > SpriteCanvasRef;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,518 @@
|
||||
/* -*- 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 <boost/cast.hpp>
|
||||
|
||||
#include <basegfx/range/b2irange.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#include "cairo_canvascustomsprite.hxx"
|
||||
#include "cairo_spritecanvashelper.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/** Sprite redraw at original position
|
||||
|
||||
Used to repaint the whole canvas (background and all
|
||||
sprites)
|
||||
*/
|
||||
void spriteRedraw( const CairoSharedPtr& pCairo,
|
||||
const ::canvas::Sprite::Reference& rSprite )
|
||||
{
|
||||
// downcast to derived cairocanvas::Sprite interface, which
|
||||
// provides the actual redraw methods.
|
||||
::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw( pCairo, true);
|
||||
}
|
||||
|
||||
void repaintBackground( const CairoSharedPtr& pCairo,
|
||||
const SurfaceSharedPtr& pBackgroundSurface,
|
||||
const ::basegfx::B2DRange& rArea )
|
||||
{
|
||||
cairo_save( pCairo.get() );
|
||||
cairo_rectangle( pCairo.get(), ceil( rArea.getMinX() ), ceil( rArea.getMinY() ),
|
||||
floor( rArea.getWidth() ), floor( rArea.getHeight() ) );
|
||||
cairo_clip( pCairo.get() );
|
||||
cairo_set_source_surface( pCairo.get(), pBackgroundSurface->getCairoSurface().get(), 0, 0 );
|
||||
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pCairo.get() );
|
||||
cairo_restore( pCairo.get() );
|
||||
}
|
||||
|
||||
void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
|
||||
const CairoSharedPtr& pCairo,
|
||||
const ::basegfx::B2IRange& rArea )
|
||||
{
|
||||
// clip output to actual update region (otherwise a)
|
||||
// wouldn't save much render time, and b) will clutter
|
||||
// scrolled sprite content outside this area)
|
||||
cairo_save( pCairo.get() );
|
||||
cairo_rectangle( pCairo.get(), rArea.getMinX(), rArea.getMinY(),
|
||||
sal::static_int_cast<sal_Int32>(rArea.getWidth()),
|
||||
sal::static_int_cast<sal_Int32>(rArea.getHeight()) );
|
||||
cairo_clip( pCairo.get() );
|
||||
|
||||
// repaint affected sprite directly to output device (at
|
||||
// the actual screen output position)
|
||||
// rendering directly to device buffer
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, false );
|
||||
|
||||
cairo_restore( pCairo.get() );
|
||||
}
|
||||
}
|
||||
|
||||
SpriteCanvasHelper::SpriteCanvasHelper() :
|
||||
mpRedrawManager( nullptr ),
|
||||
mpOwningSpriteCanvas( nullptr ),
|
||||
mbCompositingSurfaceDirty(true)
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::init( ::canvas::SpriteRedrawManager& rManager,
|
||||
SpriteCanvas& rDevice,
|
||||
const ::basegfx::B2ISize& rSize )
|
||||
{
|
||||
mpRedrawManager = &rManager;
|
||||
mpOwningSpriteCanvas = &rDevice;
|
||||
|
||||
CanvasHelper::init( rSize, rDevice, &rDevice );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::disposing()
|
||||
{
|
||||
mpCompositingSurface.reset();
|
||||
mpOwningSpriteCanvas = nullptr;
|
||||
mpRedrawManager = nullptr;
|
||||
|
||||
// forward to base
|
||||
CanvasHelper::disposing();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
|
||||
const uno::Reference< rendering::XAnimation >& )
|
||||
{
|
||||
return uno::Reference< rendering::XAnimatedSprite >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
|
||||
const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/,
|
||||
sal_Int8 /*interpolationMode*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XAnimatedSprite >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
|
||||
{
|
||||
if( !mpRedrawManager )
|
||||
return uno::Reference< rendering::XCustomSprite >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XCustomSprite >(
|
||||
new CanvasCustomSprite( spriteSize,
|
||||
mpOwningSpriteCanvas ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite(
|
||||
const uno::Reference< rendering::XSprite >& )
|
||||
{
|
||||
return uno::Reference< rendering::XSprite >();
|
||||
}
|
||||
|
||||
bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRange& /*rCurrArea*/,
|
||||
bool bUpdateAll,
|
||||
bool& io_bSurfaceDirty )
|
||||
{
|
||||
if( !mpRedrawManager ||
|
||||
!mpOwningSpriteCanvas ||
|
||||
!mpOwningSpriteCanvas->getWindowSurface() ||
|
||||
!mpOwningSpriteCanvas->getBufferSurface() )
|
||||
{
|
||||
return false; // disposed, or otherwise dysfunctional
|
||||
}
|
||||
|
||||
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::updateScreen called");
|
||||
|
||||
const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
|
||||
|
||||
// force compositing surface to be available before using it
|
||||
// inside forEachSpriteArea
|
||||
SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
|
||||
SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
|
||||
CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
|
||||
CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
|
||||
|
||||
// TODO(P1): Might be worthwhile to track areas of background
|
||||
// changes, too.
|
||||
if( !bUpdateAll && !io_bSurfaceDirty && !mbCompositingSurfaceDirty )
|
||||
{
|
||||
// background has not changed, so we're free to optimize
|
||||
// repaint to areas where a sprite has changed
|
||||
|
||||
// process each independent area of overlapping sprites
|
||||
// separately.
|
||||
mpRedrawManager->forEachSpriteArea( *this );
|
||||
}
|
||||
else
|
||||
{
|
||||
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::updateScreen update ALL");
|
||||
|
||||
// background has changed, so we currently have no choice
|
||||
// but repaint everything (or caller requested that)
|
||||
|
||||
cairo_rectangle( pCompositingCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() );
|
||||
cairo_clip( pCompositingCairo.get() );
|
||||
cairo_save( pCompositingCairo.get() );
|
||||
cairo_set_source_surface( pCompositingCairo.get(),
|
||||
mpOwningSpriteCanvas->getBufferSurface()->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pCompositingCairo.get() );
|
||||
cairo_restore( pCompositingCairo.get() );
|
||||
|
||||
// repaint all active sprites on top of background into
|
||||
// VDev.
|
||||
mpRedrawManager->forEachSprite(
|
||||
[&pCompositingCairo]( const Sprite::Reference rSprite )
|
||||
{ spriteRedraw( pCompositingCairo, rSprite ); }
|
||||
);
|
||||
|
||||
// flush to screen
|
||||
cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() );
|
||||
cairo_clip( pWindowCairo.get() );
|
||||
cairo_set_source_surface( pWindowCairo.get(),
|
||||
pCompositingSurface->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pWindowCairo.get() );
|
||||
}
|
||||
|
||||
// change record vector must be cleared, for the next turn of
|
||||
// rendering and sprite changing
|
||||
mpRedrawManager->clearChangeRecords();
|
||||
|
||||
mbCompositingSurfaceDirty = false;
|
||||
io_bSurfaceDirty = false;
|
||||
|
||||
// commit to screen
|
||||
mpOwningSpriteCanvas->flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
|
||||
{
|
||||
if( mpOwningSpriteCanvas && mpCompositingSurface )
|
||||
repaintBackground( mpCompositingSurface->getCairo(),
|
||||
mpOwningSpriteCanvas->getBufferSurface(),
|
||||
rUpdateRect );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
|
||||
const ::basegfx::B2DRange& rMoveEnd,
|
||||
const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
|
||||
{
|
||||
ENSURE_OR_THROW( mpOwningSpriteCanvas &&
|
||||
mpOwningSpriteCanvas->getBufferSurface(),
|
||||
"SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
|
||||
|
||||
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::scrollUpdate called");
|
||||
|
||||
const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
|
||||
const ::basegfx::B2IRange aOutputBounds( 0,0,
|
||||
rSize.getWidth(),
|
||||
rSize.getHeight() );
|
||||
|
||||
SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
|
||||
SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
|
||||
CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
|
||||
CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
|
||||
|
||||
// round rectangles to integer pixel. Note: have to be
|
||||
// extremely careful here, to avoid off-by-one errors for
|
||||
// the destination area: otherwise, the next scroll update
|
||||
// would copy pixel that are not supposed to be part of
|
||||
// the sprite.
|
||||
::basegfx::B2IRange aSourceRect(
|
||||
::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) );
|
||||
const ::basegfx::B2IRange aDestRect(
|
||||
::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
|
||||
::basegfx::B2IPoint aDestPos( aDestRect.getMinimum() );
|
||||
|
||||
std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
|
||||
|
||||
// TODO(E3): This is plain buggy (but copies the behaviour of
|
||||
// the old Impress slideshow) - the scrolled area might
|
||||
// actually lie _below_ another window!
|
||||
|
||||
// clip to output bounds (cannot properly scroll stuff
|
||||
// _outside_ our screen area)
|
||||
if( !::canvas::tools::clipScrollArea( aSourceRect,
|
||||
aDestPos,
|
||||
aUnscrollableAreas,
|
||||
aOutputBounds ) )
|
||||
{
|
||||
// fully clipped scroll area: cannot simply scroll
|
||||
// then. Perform normal opaque update (can use that, since
|
||||
// one of the preconditions for scrollable update is
|
||||
// opaque sprite content)
|
||||
|
||||
// repaint all affected sprites directly to output device
|
||||
for( const auto& rComponent : rUpdateArea.maComponentList )
|
||||
{
|
||||
const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
|
||||
if( rSprite.is() )
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw(
|
||||
pCompositingCairo, true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ::basegfx::B2IVector aSourceUpperLeftPos( aSourceRect.getMinimum() );
|
||||
|
||||
// clip dest area (which must be inside rDestBounds)
|
||||
::basegfx::B2IRange aClipDestRect( aDestRect );
|
||||
aClipDestRect.intersect( aOutputBounds );
|
||||
|
||||
::basegfx::B2ISize aScrollSize( aClipDestRect.getWidth(), aClipDestRect.getHeight() );
|
||||
SurfaceSharedPtr pScrollSurface( getTemporarySurface() );
|
||||
CairoSharedPtr pScrollCairo( pScrollSurface->getCairo() );
|
||||
|
||||
cairo_save( pScrollCairo.get() );
|
||||
// scroll the current content of the compositing surface (and,
|
||||
// thus, of the window) in temp. surface
|
||||
cairo_set_source_surface( pScrollCairo.get(),
|
||||
pCompositingSurface->getCairoSurface().get(),
|
||||
aDestPos.getX() - aSourceUpperLeftPos.getX(),
|
||||
aDestPos.getY() - aSourceUpperLeftPos.getY() );
|
||||
cairo_rectangle( pScrollCairo.get(),
|
||||
aDestPos.getX(), aDestPos.getY(),
|
||||
aScrollSize.getWidth(), aScrollSize.getHeight() );
|
||||
cairo_clip( pScrollCairo.get() );
|
||||
cairo_set_operator( pScrollCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pScrollCairo.get() );
|
||||
cairo_restore( pScrollCairo.get() );
|
||||
|
||||
cairo_save( pCompositingCairo.get() );
|
||||
// copy the scrolled area back onto the compositing surface
|
||||
cairo_set_source_surface( pCompositingCairo.get(),
|
||||
pScrollSurface->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_rectangle( pCompositingCairo.get(),
|
||||
aDestPos.getX(), aDestPos.getY(),
|
||||
aScrollSize.getWidth(), aScrollSize.getHeight() );
|
||||
cairo_clip( pCompositingCairo.get() );
|
||||
cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pCompositingCairo.get() );
|
||||
cairo_restore( pCompositingCairo.get() );
|
||||
|
||||
const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
|
||||
aFirst( rUpdateArea.maComponentList.begin() );
|
||||
::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
|
||||
aSecond( aFirst );
|
||||
++aSecond;
|
||||
|
||||
ENSURE_OR_THROW( aFirst->second.getSprite().is(),
|
||||
"VCLCanvas::scrollUpdate(): no sprite" );
|
||||
|
||||
// repaint uncovered areas from sprite. Need to actually
|
||||
// clip here, since we're only repainting _parts_ of the
|
||||
// sprite
|
||||
for( const auto& rArea : aUnscrollableAreas )
|
||||
opaqueUpdateSpriteArea( aFirst->second.getSprite(),
|
||||
pCompositingCairo, rArea );
|
||||
}
|
||||
|
||||
// repaint uncovered areas from backbuffer - take the
|
||||
// _rounded_ rectangles from above, to have the update
|
||||
// consistent with the scroll above.
|
||||
std::vector< ::basegfx::B2DRange > aUncoveredAreas;
|
||||
::basegfx::computeSetDifference( aUncoveredAreas,
|
||||
rUpdateArea.maTotalBounds,
|
||||
::basegfx::B2DRange( aDestRect ) );
|
||||
for( const auto& rArea : aUncoveredAreas )
|
||||
repaintBackground( pCompositingCairo,
|
||||
mpOwningSpriteCanvas->getBufferSurface(), rArea );
|
||||
|
||||
cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() );
|
||||
cairo_clip( pWindowCairo.get() );
|
||||
cairo_set_source_surface( pWindowCairo.get(),
|
||||
pCompositingSurface->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pWindowCairo.get() );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
|
||||
{
|
||||
ENSURE_OR_THROW( mpOwningSpriteCanvas &&
|
||||
mpOwningSpriteCanvas->getBufferSurface(),
|
||||
"SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
|
||||
|
||||
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::opaqueUpdate called");
|
||||
|
||||
const ::basegfx::B2ISize& rDeviceSize = mpOwningSpriteCanvas->getSizePixel();
|
||||
|
||||
SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rDeviceSize);
|
||||
SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
|
||||
CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
|
||||
CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
|
||||
|
||||
cairo_rectangle( pCompositingCairo.get(), 0, 0, rDeviceSize.getWidth(), rDeviceSize.getHeight() );
|
||||
cairo_clip( pCompositingCairo.get() );
|
||||
|
||||
::basegfx::B2DVector aPos( ceil( rTotalArea.getMinX() ), ceil( rTotalArea.getMinY() ) );
|
||||
::basegfx::B2DVector aSize( floor( rTotalArea.getMaxX() - aPos.getX() ), floor( rTotalArea.getMaxY() - aPos.getY() ) );
|
||||
|
||||
cairo_rectangle( pCompositingCairo.get(), aPos.getX(), aPos.getY(), aSize.getX(), aSize.getY() );
|
||||
cairo_clip( pCompositingCairo.get() );
|
||||
|
||||
// repaint all affected sprites directly to output device
|
||||
for( const auto& rSprite : rSortedUpdateSprites )
|
||||
{
|
||||
if( rSprite.is() )
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw(
|
||||
pCompositingCairo, false );
|
||||
}
|
||||
|
||||
// flush to screen
|
||||
cairo_rectangle( pWindowCairo.get(), 0, 0, rDeviceSize.getWidth(), rDeviceSize.getHeight() );
|
||||
cairo_clip( pWindowCairo.get() );
|
||||
cairo_rectangle( pWindowCairo.get(), aPos.getX(), aPos.getY(), aSize.getX(), aSize.getY() );
|
||||
cairo_clip( pWindowCairo.get() );
|
||||
cairo_set_source_surface( pWindowCairo.get(),
|
||||
pCompositingSurface->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pWindowCairo.get() );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rRequestedArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
|
||||
{
|
||||
// TODO
|
||||
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::genericUpdate called");
|
||||
|
||||
ENSURE_OR_THROW( mpOwningSpriteCanvas &&
|
||||
mpOwningSpriteCanvas->getBufferSurface(),
|
||||
"SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
|
||||
|
||||
// limit size of update VDev to target outdev's size
|
||||
const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
|
||||
|
||||
SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
|
||||
SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
|
||||
CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
|
||||
CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
|
||||
|
||||
// round output position towards zero. Don't want to truncate
|
||||
// a fraction of a sprite pixel... Clip position at origin,
|
||||
// otherwise, truncation of size below might leave visible
|
||||
// areas uncovered by VDev.
|
||||
const Point aOutputPosition(
|
||||
std::max( sal_Int32( 0 ),
|
||||
static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
|
||||
std::max( sal_Int32( 0 ),
|
||||
static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
|
||||
// round output size towards +infty. Don't want to truncate a
|
||||
// fraction of a sprite pixel... Limit size of VDev to output
|
||||
// device's area.
|
||||
const Size aOutputSize(
|
||||
std::min( rSize.getWidth(),
|
||||
::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X()) ),
|
||||
std::min( rSize.getHeight(),
|
||||
::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y()) ) );
|
||||
|
||||
cairo_rectangle( pCompositingCairo.get(), aOutputPosition.X(), aOutputPosition.Y(), aOutputSize.Width(), aOutputSize.Height() );
|
||||
cairo_clip( pCompositingCairo.get() );
|
||||
|
||||
// paint background
|
||||
cairo_save( pCompositingCairo.get() );
|
||||
cairo_set_source_surface( pCompositingCairo.get(),
|
||||
mpOwningSpriteCanvas->getBufferSurface()->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pCompositingCairo.get() );
|
||||
cairo_restore( pCompositingCairo.get() );
|
||||
|
||||
// repaint all affected sprites on top of background into
|
||||
// VDev.
|
||||
for( const auto& rSprite : rSortedUpdateSprites )
|
||||
{
|
||||
if( rSprite.is() )
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw(
|
||||
pCompositingCairo, true );
|
||||
}
|
||||
|
||||
// flush to screen
|
||||
cairo_rectangle( pWindowCairo.get(), aOutputPosition.X(), aOutputPosition.Y(), aOutputSize.Width(), aOutputSize.Height() );
|
||||
cairo_clip( pWindowCairo.get() );
|
||||
cairo_set_source_surface( pWindowCairo.get(),
|
||||
pCompositingSurface->getCairoSurface().get(),
|
||||
0, 0 );
|
||||
cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_paint( pWindowCairo.get() );
|
||||
}
|
||||
|
||||
::cairo::SurfaceSharedPtr const & SpriteCanvasHelper::getCompositingSurface( const ::basegfx::B2ISize& rNeededSize )
|
||||
{
|
||||
if( rNeededSize.getWidth() > maCompositingSurfaceSize.getWidth() ||
|
||||
rNeededSize.getHeight() > maCompositingSurfaceSize.getHeight() )
|
||||
{
|
||||
// need to give buffer more size
|
||||
mpCompositingSurface.reset();
|
||||
}
|
||||
|
||||
if( !mpCompositingSurface )
|
||||
{
|
||||
mpCompositingSurface = createSurface( rNeededSize );
|
||||
maCompositingSurfaceSize = rNeededSize;
|
||||
mbCompositingSurfaceDirty = true;
|
||||
mpTemporarySurface.reset();
|
||||
}
|
||||
|
||||
return mpCompositingSurface;
|
||||
}
|
||||
|
||||
::cairo::SurfaceSharedPtr const & SpriteCanvasHelper::getTemporarySurface()
|
||||
{
|
||||
if ( !mpTemporarySurface )
|
||||
mpTemporarySurface = createSurface( maCompositingSurfaceSize );
|
||||
return mpTemporarySurface;
|
||||
}
|
||||
|
||||
::cairo::SurfaceSharedPtr SpriteCanvasHelper::createSurface( const ::basegfx::B2ISize& rNeededSize ) const
|
||||
{
|
||||
return mpOwningSpriteCanvas->getWindowSurface()->getSimilar(
|
||||
CAIRO_CONTENT_COLOR,
|
||||
rNeededSize.getWidth(), rNeededSize.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,140 @@
|
||||
/* -*- 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/rendering/XAnimatedSprite.hpp>
|
||||
#include <com/sun/star/rendering/XAnimation.hpp>
|
||||
#include <com/sun/star/rendering/XCustomSprite.hpp>
|
||||
|
||||
#include <spriteredrawmanager.hxx>
|
||||
|
||||
#include <vcl/cairo.hxx>
|
||||
#include "cairo_canvashelper.hxx"
|
||||
|
||||
namespace basegfx
|
||||
{
|
||||
class B2IRange;
|
||||
}
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
class SpriteCanvas;
|
||||
|
||||
class SpriteCanvasHelper : public CanvasHelper
|
||||
{
|
||||
public:
|
||||
SpriteCanvasHelper();
|
||||
|
||||
void init( ::canvas::SpriteRedrawManager& rManager,
|
||||
SpriteCanvas& rOwningSpriteCanvas,
|
||||
const ::basegfx::B2ISize& rSize );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// XSpriteCanvas
|
||||
css::uno::Reference< css::rendering::XAnimatedSprite > createSpriteFromAnimation(
|
||||
const css::uno::Reference< css::rendering::XAnimation >& animation );
|
||||
|
||||
css::uno::Reference< css::rendering::XAnimatedSprite > createSpriteFromBitmaps(
|
||||
const css::uno::Sequence<
|
||||
css::uno::Reference<
|
||||
css::rendering::XBitmap > >& animationBitmaps,
|
||||
sal_Int8 interpolationMode );
|
||||
|
||||
css::uno::Reference< css::rendering::XCustomSprite > createCustomSprite(
|
||||
const css::geometry::RealSize2D& spriteSize );
|
||||
|
||||
css::uno::Reference< css::rendering::XSprite > createClonedSprite(
|
||||
const css::uno::Reference< css::rendering::XSprite >& original );
|
||||
|
||||
/** Actually perform the screen update
|
||||
|
||||
@param rCurrArea
|
||||
Current window area in absolute screen coordinates
|
||||
|
||||
@param bUpdateAll
|
||||
sal_True, if everything must be updated, not only changed
|
||||
sprites
|
||||
|
||||
@param io_bSurfaceDirty
|
||||
In/out parameter, whether backbuffer surface is dirty (if
|
||||
yes, we're performing a full update, anyway)
|
||||
*/
|
||||
bool updateScreen( const ::basegfx::B2IRange& rCurrArea,
|
||||
bool bUpdateAll,
|
||||
bool& io_bSurfaceDirty );
|
||||
|
||||
|
||||
// SpriteRedrawManager functor calls
|
||||
|
||||
|
||||
/** Gets called for simple background repaints
|
||||
*/
|
||||
void backgroundPaint( const ::basegfx::B2DRange& rUpdateRect );
|
||||
|
||||
/** Gets called when area can be handled by scrolling.
|
||||
|
||||
Called method must copy screen content from rMoveStart to
|
||||
rMoveEnd, and restore the background in the uncovered
|
||||
areas.
|
||||
|
||||
@param rMoveStart
|
||||
Source rect of the scroll
|
||||
|
||||
@param rMoveEnd
|
||||
Dest rect of the scroll
|
||||
|
||||
@param rUpdateArea
|
||||
All info necessary, should rMoveStart be partially or
|
||||
fully outside the outdev
|
||||
*/
|
||||
void scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
|
||||
const ::basegfx::B2DRange& rMoveEnd,
|
||||
const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
|
||||
|
||||
void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
|
||||
|
||||
void genericUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
|
||||
|
||||
private:
|
||||
::cairo::SurfaceSharedPtr const & getCompositingSurface( const ::basegfx::B2ISize& rNeededSize );
|
||||
::cairo::SurfaceSharedPtr const & getTemporarySurface();
|
||||
::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rNeededSize ) const;
|
||||
|
||||
/// Set from the SpriteCanvas: instance coordinating sprite redraw
|
||||
::canvas::SpriteRedrawManager* mpRedrawManager;
|
||||
|
||||
/// Set from the init method. used to generate sprites
|
||||
SpriteCanvas* mpOwningSpriteCanvas;
|
||||
|
||||
/// a surface used to composite the frontbuffer image
|
||||
::cairo::SurfaceSharedPtr mpCompositingSurface;
|
||||
::basegfx::B2ISize maCompositingSurfaceSize;
|
||||
bool mbCompositingSurfaceDirty;
|
||||
/// a temporary surface that is guaranteed to be the same size
|
||||
//as the compositing surface
|
||||
::cairo::SurfaceSharedPtr mpTemporarySurface;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,153 @@
|
||||
/* -*- 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 <vcl/cairo.hxx>
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#include "cairo_devicehelper.hxx"
|
||||
#include "cairo_spritecanvas.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
|
||||
SpriteDeviceHelper::SpriteDeviceHelper() :
|
||||
mpSpriteCanvas( nullptr ),
|
||||
mbFullScreen( false )
|
||||
{}
|
||||
|
||||
void SpriteDeviceHelper::init( vcl::Window& rOutputWindow,
|
||||
SpriteCanvas& rSpriteCanvas,
|
||||
const ::basegfx::B2ISize& rSize,
|
||||
bool bFullscreen )
|
||||
{
|
||||
DeviceHelper::init(rSpriteCanvas,
|
||||
*rOutputWindow.GetOutDev());
|
||||
|
||||
mpSpriteCanvas = &rSpriteCanvas;
|
||||
mbFullScreen = bFullscreen;
|
||||
|
||||
setSize( rSize );
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::disposing()
|
||||
{
|
||||
// release all references
|
||||
mpBufferSurface.reset();
|
||||
mpSpriteCanvas = nullptr;
|
||||
}
|
||||
|
||||
bool SpriteDeviceHelper::showBuffer( bool, bool )
|
||||
{
|
||||
SAL_WARN("canvas.cairo", "showBuffer Not supposed to be called, handled by SpriteCanvas");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpriteDeviceHelper::switchBuffer( bool, bool )
|
||||
{
|
||||
SAL_WARN("canvas.cairo", "showBuffer Not supposed to be called, handled by SpriteCanvas");
|
||||
return false;
|
||||
}
|
||||
|
||||
uno::Any SpriteDeviceHelper::isAccelerated() const
|
||||
{
|
||||
return css::uno::Any(true);
|
||||
}
|
||||
|
||||
uno::Any SpriteDeviceHelper::getDeviceHandle() const
|
||||
{
|
||||
return DeviceHelper::getDeviceHandle();
|
||||
}
|
||||
|
||||
uno::Any SpriteDeviceHelper::getSurfaceHandle() const
|
||||
{
|
||||
return DeviceHelper::getSurfaceHandle();
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::setSize( const ::basegfx::B2ISize& rSize )
|
||||
{
|
||||
SAL_INFO(
|
||||
"canvas.cairo",
|
||||
"device size " << rSize.getWidth() << " x " << rSize.getHeight());
|
||||
|
||||
if( !mpSpriteCanvas )
|
||||
return; // disposed
|
||||
|
||||
DeviceHelper::setSize(rSize);
|
||||
|
||||
if( mpBufferSurface && maSize != rSize )
|
||||
mpBufferSurface.reset();
|
||||
if( !mpBufferSurface )
|
||||
mpBufferSurface = getWindowSurface()->getSimilar(
|
||||
CAIRO_CONTENT_COLOR,
|
||||
rSize.getWidth(), rSize.getHeight() );
|
||||
|
||||
if( maSize != rSize )
|
||||
maSize = rSize;
|
||||
|
||||
mpSpriteCanvas->setSizePixel( maSize );
|
||||
}
|
||||
|
||||
|
||||
void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
|
||||
{
|
||||
setSize( ::basegfx::B2ISize(rBounds.Width, rBounds.Height) );
|
||||
}
|
||||
|
||||
SurfaceSharedPtr const & SpriteDeviceHelper::getWindowSurface() const
|
||||
{
|
||||
return DeviceHelper::getSurface();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteDeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent )
|
||||
{
|
||||
if( mpBufferSurface )
|
||||
return mpBufferSurface->getSimilar( aContent, rSize.getWidth(), rSize.getHeight() );
|
||||
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
|
||||
SurfaceSharedPtr SpriteDeviceHelper::createSurface( BitmapSystemData const & rData, const Size& rSize )
|
||||
{
|
||||
OutputDevice *pDevice = getOutputDevice();
|
||||
if (pDevice)
|
||||
return pDevice->CreateBitmapSurface(rData, rSize);
|
||||
return SurfaceSharedPtr();
|
||||
}
|
||||
|
||||
/** SpriteDeviceHelper::flush Flush the platform native window
|
||||
*
|
||||
* Flushes the window by using the internally stored mpSysData.
|
||||
*
|
||||
**/
|
||||
void SpriteDeviceHelper::flush()
|
||||
{
|
||||
SurfaceSharedPtr pWinSurface=getWindowSurface();
|
||||
if( pWinSurface )
|
||||
pWinSurface->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -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 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <com/sun/star/awt/Rectangle.hpp>
|
||||
|
||||
#include <vcl/window.hxx>
|
||||
#include <vcl/cairo.hxx>
|
||||
|
||||
#include "cairo_devicehelper.hxx"
|
||||
|
||||
/* Definition of DeviceHelper class */
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
class SpriteCanvas;
|
||||
|
||||
class SpriteDeviceHelper : public DeviceHelper
|
||||
{
|
||||
public:
|
||||
SpriteDeviceHelper();
|
||||
|
||||
void init( vcl::Window& rOutputWindow,
|
||||
SpriteCanvas& rSpriteCanvas,
|
||||
const ::basegfx::B2ISize& rSize,
|
||||
bool bFullscreen );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// XWindowGraphicDevice
|
||||
bool showBuffer( bool, bool );
|
||||
bool switchBuffer( bool, bool bUpdateAll );
|
||||
|
||||
css::uno::Any isAccelerated() const;
|
||||
css::uno::Any getDeviceHandle() const;
|
||||
css::uno::Any getSurfaceHandle() const;
|
||||
|
||||
void notifySizeUpdate( const css::awt::Rectangle& rBounds );
|
||||
void setSize( const ::basegfx::B2ISize& rSize );
|
||||
|
||||
const ::cairo::SurfaceSharedPtr& getBufferSurface() const { return mpBufferSurface; }
|
||||
::cairo::SurfaceSharedPtr const & getWindowSurface() const;
|
||||
::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, int aContent );
|
||||
::cairo::SurfaceSharedPtr createSurface( BitmapSystemData const & rData, const Size& rSize );
|
||||
const ::basegfx::B2ISize& getSizePixel() const { return maSize; }
|
||||
void flush();
|
||||
|
||||
private:
|
||||
/// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
|
||||
SpriteCanvas* mpSpriteCanvas;
|
||||
|
||||
::cairo::SurfaceSharedPtr mpBufferSurface;
|
||||
|
||||
::basegfx::B2ISize maSize;
|
||||
bool mbFullScreen;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,195 @@
|
||||
/* -*- 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/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <cairo.h>
|
||||
#include <pixman.h>
|
||||
|
||||
#include "cairo_spritehelper.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
SpriteHelper::SpriteHelper() :
|
||||
mbTextureDirty(true)
|
||||
{}
|
||||
|
||||
void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
|
||||
const SpriteCanvasRef& rSpriteCanvas )
|
||||
{
|
||||
ENSURE_OR_THROW( rSpriteCanvas,
|
||||
"SpriteHelper::init(): Invalid device, sprite canvas or surface" );
|
||||
|
||||
mpSpriteCanvas = rSpriteCanvas;
|
||||
mbTextureDirty = true;
|
||||
|
||||
// also init base class
|
||||
CanvasCustomSpriteHelper::init( rSpriteSize, rSpriteCanvas );
|
||||
}
|
||||
|
||||
void SpriteHelper::setSurface( const SurfaceSharedPtr& pBufferSurface )
|
||||
{
|
||||
mpBufferSurface = pBufferSurface;
|
||||
}
|
||||
|
||||
void SpriteHelper::disposing()
|
||||
{
|
||||
mpBufferSurface.reset();
|
||||
mpSpriteCanvas.clear();
|
||||
|
||||
// forward to parent
|
||||
CanvasCustomSpriteHelper::disposing();
|
||||
}
|
||||
|
||||
void SpriteHelper::redraw( const CairoSharedPtr& pCairo,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
bool& /*io_bSurfacesDirty*/,
|
||||
bool /*bBufferedUpdate*/ ) const
|
||||
{
|
||||
#ifdef CAIRO_CANVAS_PERF_TRACE
|
||||
struct timespec aTimer;
|
||||
mxDevice->startPerfTrace( &aTimer );
|
||||
#endif
|
||||
|
||||
const double fAlpha( getAlpha() );
|
||||
const ::basegfx::B2DHomMatrix aTransform( getTransformation() );
|
||||
|
||||
if( !isActive() || ::basegfx::fTools::equalZero( fAlpha ) )
|
||||
return;
|
||||
|
||||
SAL_INFO( "canvas.cairo", "CanvasCustomSprite::redraw called");
|
||||
if( !pCairo )
|
||||
return;
|
||||
|
||||
basegfx::B2DVector aSize = getSizePixel();
|
||||
cairo_save( pCairo.get() );
|
||||
|
||||
double fX, fY;
|
||||
|
||||
fX = rPos.getX();
|
||||
fY = rPos.getY();
|
||||
|
||||
if( !aTransform.isIdentity() )
|
||||
{
|
||||
cairo_matrix_t aMatrix, aInverseMatrix;
|
||||
cairo_matrix_init( &aMatrix,
|
||||
aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ),
|
||||
aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) );
|
||||
|
||||
aMatrix.x0 = basegfx::fround( aMatrix.x0 );
|
||||
aMatrix.y0 = basegfx::fround( aMatrix.y0 );
|
||||
|
||||
cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 );
|
||||
cairo_matrix_invert( &aInverseMatrix );
|
||||
cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY );
|
||||
|
||||
cairo_set_matrix( pCairo.get(), &aMatrix );
|
||||
}
|
||||
|
||||
fX = basegfx::fround( fX );
|
||||
fY = basegfx::fround( fY );
|
||||
|
||||
cairo_matrix_t aOrigMatrix;
|
||||
cairo_get_matrix( pCairo.get(), &aOrigMatrix );
|
||||
cairo_translate( pCairo.get(), fX, fY );
|
||||
|
||||
if( getClip().is() )
|
||||
{
|
||||
const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() );
|
||||
|
||||
::basegfx::B2DPolyPolygon aClipPoly(
|
||||
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
|
||||
rClip ));
|
||||
|
||||
doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(),
|
||||
nullptr, SurfaceProviderRef(mpSpriteCanvas),
|
||||
rClip->getFillRule() );
|
||||
}
|
||||
|
||||
SAL_INFO( "canvas.cairo","aSize " << aSize.getX() << " x " << aSize.getY() << " position: " << fX << "," << fY );
|
||||
cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) );
|
||||
cairo_clip( pCairo.get() );
|
||||
cairo_set_matrix( pCairo.get(), &aOrigMatrix );
|
||||
|
||||
cairo_matrix_t aInverseMatrix = aOrigMatrix;
|
||||
bool matrixProblem = false;
|
||||
// tdf#125949: Cairo internally uses the pixman library, and _cairo_matrix_to_pixman_matrix()
|
||||
// checks all matrix components to fix PIXMAN_MAX_INT, which is about 32k. Which means that
|
||||
// if our transformation is large, such as an initial step of some zooming animations,
|
||||
// the conversion will fail. To make things worse, once something in cairo fails, it's treated
|
||||
// as a fatal error, the error status of that cairo_t gets set, and there's no way to reset it
|
||||
// besides recreating the whole cairo_t
|
||||
// (https://lists.cairographics.org/archives/cairo/2006-September/007892.html).
|
||||
// So copy&paste PIXMAN_MAX_INT here, and if our matrix could fail, bail out.
|
||||
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
|
||||
if(cairo_matrix_invert(&aInverseMatrix) == CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
if(abs(aOrigMatrix.xx) > PIXMAN_MAX_INT || abs(aOrigMatrix.xx) > PIXMAN_MAX_INT
|
||||
|| abs(aOrigMatrix.xy) > PIXMAN_MAX_INT || abs(aOrigMatrix.yx) > PIXMAN_MAX_INT
|
||||
|| abs(aOrigMatrix.x0) > PIXMAN_MAX_INT || abs(aOrigMatrix.y0) > PIXMAN_MAX_INT
|
||||
|| abs(aInverseMatrix.xx) > PIXMAN_MAX_INT || abs(aInverseMatrix.xx) > PIXMAN_MAX_INT
|
||||
|| abs(aInverseMatrix.xy) > PIXMAN_MAX_INT || abs(aInverseMatrix.yx) > PIXMAN_MAX_INT
|
||||
|| abs(aInverseMatrix.x0) > PIXMAN_MAX_INT || abs(aInverseMatrix.y0) > PIXMAN_MAX_INT)
|
||||
matrixProblem = true;
|
||||
#undef PIXMAN_MAX_INT
|
||||
}
|
||||
else
|
||||
matrixProblem = true;
|
||||
if(matrixProblem)
|
||||
{
|
||||
SAL_WARN( "canvas.cairo", "matrix would overflow PIXMAN_MAX_INT, avoiding drawing" );
|
||||
cairo_restore( pCairo.get() );
|
||||
return;
|
||||
}
|
||||
|
||||
if( isContentFullyOpaque() )
|
||||
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||
cairo_set_source_surface( pCairo.get(),
|
||||
mpBufferSurface->getCairoSurface().get(),
|
||||
fX, fY );
|
||||
if( ::rtl::math::approxEqual( fAlpha, 1.0 ) )
|
||||
cairo_paint( pCairo.get() );
|
||||
else
|
||||
cairo_paint_with_alpha( pCairo.get(), fAlpha );
|
||||
|
||||
cairo_restore( pCairo.get() );
|
||||
|
||||
#ifdef CAIRO_CANVAS_PERF_TRACE
|
||||
mxDevice->stopPerfTrace( &aTimer, "sprite redraw" );
|
||||
#endif
|
||||
}
|
||||
|
||||
::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
|
||||
{
|
||||
return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPoly);
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,102 @@
|
||||
/* -*- 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/canvascustomspritehelper.hxx>
|
||||
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
|
||||
#include "cairo_spritecanvas.hxx"
|
||||
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
/* Definition of SpriteHelper class */
|
||||
|
||||
/** Helper class for canvas sprites.
|
||||
|
||||
This class implements all sprite-related functionality, like
|
||||
that available on the XSprite interface.
|
||||
*/
|
||||
class SpriteHelper : public ::canvas::CanvasCustomSpriteHelper
|
||||
{
|
||||
public:
|
||||
/** Create sprite helper
|
||||
*/
|
||||
SpriteHelper();
|
||||
|
||||
/** Late-init the sprite helper
|
||||
|
||||
@param rSpriteSize
|
||||
Size of the sprite
|
||||
|
||||
@param rSpriteCanvas
|
||||
Sprite canvas this sprite is part of. Object stores
|
||||
ref-counted reference to it, thus, don't forget to pass on
|
||||
disposing()!
|
||||
|
||||
@param rDevice
|
||||
DX device to use
|
||||
|
||||
@param rSpriteSurface
|
||||
The surface of the sprite (not the DX texture, but the
|
||||
persistent target of content rendering)
|
||||
|
||||
@param bShowSpriteBounds
|
||||
When true, little debug bound rects for sprites are shown
|
||||
*/
|
||||
void init( const css::geometry::RealSize2D& rSpriteSize,
|
||||
const SpriteCanvasRef& rSpriteCanvas );
|
||||
|
||||
void disposing();
|
||||
|
||||
void setSurface( const ::cairo::SurfaceSharedPtr& pBufferSurface );
|
||||
|
||||
/** Repaint sprite content to associated sprite canvas
|
||||
|
||||
@param rPos
|
||||
Output position (sprite's own position is disregarded)
|
||||
|
||||
@param io_bSurfacesDirty
|
||||
When true, the referenced sprite surfaces (backBuffer and
|
||||
backBufferMask) have been modified since last call.
|
||||
|
||||
@param bBufferedUpdate
|
||||
When true, the redraw does <em>not</em> happen directly on
|
||||
the front buffer, but within a VDev. Used to speed up
|
||||
drawing.
|
||||
*/
|
||||
void redraw( const ::cairo::CairoSharedPtr& pCairo,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
bool& bSurfacesDirty,
|
||||
bool bBufferedUpdate ) const;
|
||||
|
||||
private:
|
||||
virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
|
||||
css::uno::Reference< css::rendering::XPolyPolygon2D >& xPoly ) const override;
|
||||
|
||||
|
||||
SpriteCanvasRef mpSpriteCanvas;
|
||||
::cairo::SurfaceSharedPtr mpBufferSurface;
|
||||
mutable bool mbTextureDirty; // when true, texture needs update
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -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 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rtl/ref.hxx>
|
||||
#include <com/sun/star/uno/XInterface.hpp>
|
||||
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <vcl/cairo.hxx>
|
||||
|
||||
class OutputDevice;
|
||||
class Bitmap;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
/* Definition of RepaintTarget interface */
|
||||
|
||||
/** Target interface for XCachedPrimitive implementations
|
||||
|
||||
This interface must be implemented on all canvas
|
||||
implementations that hand out XCachedPrimitives
|
||||
*/
|
||||
class SAL_LOPLUGIN_ANNOTATE("crosscast") SurfaceProvider : public css::uno::XInterface
|
||||
{
|
||||
public:
|
||||
virtual ~SurfaceProvider() {}
|
||||
|
||||
/** Query surface from this provider
|
||||
|
||||
This should return the default surface to render on.
|
||||
*/
|
||||
virtual ::cairo::SurfaceSharedPtr getSurface() = 0;
|
||||
|
||||
/// create new surface in given size
|
||||
virtual ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize,
|
||||
int aContent ) = 0;
|
||||
/// create new surface from given bitmap
|
||||
virtual ::cairo::SurfaceSharedPtr createSurface( ::Bitmap& rBitmap ) = 0;
|
||||
|
||||
/** convert surface from alpha to non-alpha, does not copy content
|
||||
channel. returns new surface on success, NULL otherwise
|
||||
*/
|
||||
virtual ::cairo::SurfaceSharedPtr changeSurface() = 0;
|
||||
|
||||
/** Provides the underlying vcl outputdevice this surface renders on
|
||||
*/
|
||||
virtual OutputDevice* getOutputDevice() = 0;
|
||||
};
|
||||
|
||||
typedef ::rtl::Reference< SurfaceProvider > SurfaceProviderRef;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,363 @@
|
||||
/* -*- 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 <math.h>
|
||||
|
||||
#include <com/sun/star/rendering/TextDirection.hpp>
|
||||
#include <canvas/canvastools.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <utility>
|
||||
#include <vcl/kernarray.hxx>
|
||||
#include <vcl/metric.hxx>
|
||||
#include <vcl/virdev.hxx>
|
||||
|
||||
#include "cairo_textlayout.hxx"
|
||||
|
||||
using namespace ::cairo;
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void setupLayoutMode( OutputDevice& rOutDev,
|
||||
sal_Int8 nTextDirection )
|
||||
{
|
||||
// TODO(P3): avoid if already correctly set
|
||||
vcl::text::ComplexTextLayoutFlags nLayoutMode = vcl::text::ComplexTextLayoutFlags::Default;
|
||||
switch( nTextDirection )
|
||||
{
|
||||
case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
|
||||
break;
|
||||
case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
|
||||
nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiStrong;
|
||||
break;
|
||||
case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
|
||||
nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiRtl;
|
||||
break;
|
||||
case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
|
||||
nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::BiDiStrong;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// set calculated layout mode. Origin is always the left edge,
|
||||
// as required at the API spec
|
||||
rOutDev.SetLayoutMode( nLayoutMode | vcl::text::ComplexTextLayoutFlags::TextOriginLeft );
|
||||
}
|
||||
}
|
||||
|
||||
TextLayout::TextLayout( rendering::StringContext aText,
|
||||
sal_Int8 nDirection,
|
||||
sal_Int64 /*nRandomSeed*/,
|
||||
CanvasFont::Reference rFont,
|
||||
SurfaceProviderRef rRefDevice ) :
|
||||
maText(std::move( aText )),
|
||||
mpFont(std::move( rFont )),
|
||||
mpRefDevice(std::move( rRefDevice )),
|
||||
mnTextDirection( nDirection )
|
||||
{
|
||||
}
|
||||
|
||||
TextLayout::~TextLayout()
|
||||
{
|
||||
}
|
||||
|
||||
void TextLayout::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
|
||||
{
|
||||
mpFont.clear();
|
||||
mpRefDevice.clear();
|
||||
}
|
||||
|
||||
// XTextLayout
|
||||
uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
|
||||
}
|
||||
|
||||
uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< geometry::RealRectangle2D >();
|
||||
}
|
||||
|
||||
uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< geometry::RealRectangle2D >();
|
||||
}
|
||||
|
||||
uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
return maLogicalAdvancements;
|
||||
}
|
||||
|
||||
void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
if( aAdvancements.getLength() != maText.Length )
|
||||
{
|
||||
SAL_WARN("canvas.cairo", "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
|
||||
throw lang::IllegalArgumentException(u"mismatching number of advancements"_ustr, getXWeak(), 1);
|
||||
}
|
||||
|
||||
maLogicalAdvancements = aAdvancements;
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Bool > SAL_CALL TextLayout::queryKashidaPositions( )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
return maKashidaPositions;
|
||||
}
|
||||
|
||||
void SAL_CALL TextLayout::applyKashidaPositions( const uno::Sequence< sal_Bool >& aPositions )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
if( aPositions.hasElements() && aPositions.getLength() != maText.Length )
|
||||
{
|
||||
SAL_WARN("canvas.cairo", "TextLayout::applyKashidaPositions(): mismatching number of positions" );
|
||||
throw lang::IllegalArgumentException(u"mismatching number of positions"_ustr, getXWeak(), 1);
|
||||
}
|
||||
|
||||
maKashidaPositions = aPositions;
|
||||
}
|
||||
|
||||
geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
OutputDevice* pOutDev = mpRefDevice->getOutputDevice();
|
||||
if( !pOutDev )
|
||||
return geometry::RealRectangle2D();
|
||||
|
||||
ScopedVclPtrInstance< VirtualDevice > pVDev( *pOutDev );
|
||||
pVDev->SetFont( mpFont->getVCLFont() );
|
||||
|
||||
// need metrics for Y offset, the XCanvas always renders
|
||||
// relative to baseline
|
||||
const ::FontMetric aMetric( pVDev->GetFontMetric() );
|
||||
|
||||
setupLayoutMode( *pVDev, mnTextDirection );
|
||||
|
||||
const sal_Int32 nAboveBaseline( -aMetric.GetAscent() );
|
||||
const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
|
||||
|
||||
if( maLogicalAdvancements.hasElements() )
|
||||
{
|
||||
return geometry::RealRectangle2D( 0, nAboveBaseline,
|
||||
maLogicalAdvancements[ maLogicalAdvancements.getLength()-1 ],
|
||||
nBelowBaseline );
|
||||
}
|
||||
else
|
||||
{
|
||||
return geometry::RealRectangle2D( 0, nAboveBaseline,
|
||||
pVDev->GetTextWidth(
|
||||
maText.Text,
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) ),
|
||||
nBelowBaseline );
|
||||
}
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::justify( double /*nSize*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
|
||||
double /*nSize*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ )
|
||||
{
|
||||
// TODO
|
||||
return rendering::TextHit();
|
||||
}
|
||||
|
||||
rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
|
||||
sal_Bool /*bExcludeLigatures*/ )
|
||||
{
|
||||
// TODO
|
||||
return rendering::Caret();
|
||||
}
|
||||
|
||||
sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nCaretAdvancement*/,
|
||||
sal_Bool /*bExcludeLigatures*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nEndIndex*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XPolyPolygon2D >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nEndIndex*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XPolyPolygon2D >();
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::getBaselineOffset( )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
sal_Int8 SAL_CALL TextLayout::getMainTextDirection( )
|
||||
{
|
||||
return mnTextDirection;
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( )
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
|
||||
return mpFont;
|
||||
}
|
||||
|
||||
rendering::StringContext SAL_CALL TextLayout::getText( )
|
||||
{
|
||||
return maText;
|
||||
}
|
||||
|
||||
/**
|
||||
* TextLayout::draw
|
||||
*
|
||||
* Cairo-based text rendering. Draw text directly on the cairo surface with cairo fonts.
|
||||
* Avoid using VCL VirtualDevices for that, bypassing VCL DrawText functions, when possible
|
||||
*
|
||||
* Note: some text effects are not rendered due to lacking generic canvas or cairo canvas
|
||||
* implementation. See issues 92657, 92658, 92659, 92660, 97529
|
||||
**/
|
||||
void TextLayout::draw( OutputDevice& rOutDev,
|
||||
const Point& rOutpos,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState ) const
|
||||
{
|
||||
std::unique_lock aGuard( m_aMutex );
|
||||
setupLayoutMode( rOutDev, mnTextDirection );
|
||||
|
||||
if (maLogicalAdvancements.hasElements())
|
||||
{
|
||||
KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, viewState, renderState));
|
||||
std::span<const sal_Bool> aKashidaArray(maKashidaPositions.getConstArray(), maKashidaPositions.getLength());
|
||||
|
||||
rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets, aKashidaArray,
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
|
||||
}
|
||||
else
|
||||
{
|
||||
rOutDev.DrawText( rOutpos, maText.Text,
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class OffsetTransformer
|
||||
{
|
||||
public:
|
||||
explicit OffsetTransformer( ::basegfx::B2DHomMatrix aMat ) :
|
||||
maMatrix(std::move( aMat ))
|
||||
{
|
||||
}
|
||||
|
||||
sal_Int32 operator()( const double& rOffset )
|
||||
{
|
||||
// This is an optimization of the normal rMat*[x,0]
|
||||
// transformation of the advancement vector (in x
|
||||
// direction), followed by a length calculation of the
|
||||
// resulting vector: advancement' =
|
||||
// ||rMat*[x,0]||. Since advancements are vectors, we
|
||||
// can ignore translational components, thus if [x,0],
|
||||
// it follows that rMat*[x,0]=[x',0] holds. Thus, we
|
||||
// just have to calc the transformation of the x
|
||||
// component.
|
||||
|
||||
// TODO(F2): Handle non-horizontal advancements!
|
||||
return ::basegfx::fround( hypot(maMatrix.get(0,0)*rOffset,
|
||||
maMatrix.get(1,0)*rOffset) );
|
||||
}
|
||||
|
||||
private:
|
||||
::basegfx::B2DHomMatrix maMatrix;
|
||||
};
|
||||
}
|
||||
|
||||
KernArray TextLayout::setupTextOffsets(
|
||||
const uno::Sequence< double >& inputOffsets,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState ) const
|
||||
{
|
||||
::basegfx::B2DHomMatrix aMatrix;
|
||||
|
||||
::canvas::tools::mergeViewAndRenderTransform(aMatrix,
|
||||
viewState,
|
||||
renderState);
|
||||
|
||||
// fill integer offsets
|
||||
KernArray outputOffsets;
|
||||
OffsetTransformer aTransform(aMatrix);
|
||||
std::for_each(inputOffsets.begin(), inputOffsets.end(),
|
||||
[&outputOffsets, &aTransform](double n) {outputOffsets.push_back(aTransform(n)); } );
|
||||
return outputOffsets;
|
||||
}
|
||||
|
||||
OUString SAL_CALL TextLayout::getImplementationName()
|
||||
{
|
||||
return u"CairoCanvas::TextLayout"_ustr;
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL TextLayout::supportsService( const OUString& ServiceName )
|
||||
{
|
||||
return cppu::supportsService( this, ServiceName );
|
||||
}
|
||||
|
||||
uno::Sequence< OUString > SAL_CALL TextLayout::getSupportedServiceNames()
|
||||
{
|
||||
return { u"com.sun.star.rendering.TextLayout"_ustr };
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,107 @@
|
||||
/* -*- 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/rendering/RenderState.hpp>
|
||||
#include <com/sun/star/rendering/ViewState.hpp>
|
||||
#include <com/sun/star/rendering/XTextLayout.hpp>
|
||||
|
||||
#include <vcl/outdev.hxx>
|
||||
|
||||
#include "cairo_canvasfont.hxx"
|
||||
|
||||
|
||||
/* Definition of TextLayout class */
|
||||
|
||||
namespace cairocanvas
|
||||
{
|
||||
typedef ::comphelper::WeakComponentImplHelper< css::rendering::XTextLayout,
|
||||
css::lang::XServiceInfo > TextLayout_Base;
|
||||
|
||||
class TextLayout : public TextLayout_Base
|
||||
{
|
||||
public:
|
||||
/// make noncopyable
|
||||
TextLayout(const TextLayout&) = delete;
|
||||
const TextLayout& operator=(const TextLayout&) = delete;
|
||||
|
||||
TextLayout( css::rendering::StringContext aText,
|
||||
sal_Int8 nDirection,
|
||||
sal_Int64 nRandomSeed,
|
||||
CanvasFont::Reference rFont,
|
||||
SurfaceProviderRef rRefDevice );
|
||||
|
||||
/// Dispose all internal references
|
||||
virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
|
||||
|
||||
// XTextLayout
|
||||
virtual css::uno::Sequence< css::uno::Reference< css::rendering::XPolyPolygon2D > > SAL_CALL queryTextShapes( ) override;
|
||||
virtual css::uno::Sequence< css::geometry::RealRectangle2D > SAL_CALL queryInkMeasures( ) override;
|
||||
virtual css::uno::Sequence< css::geometry::RealRectangle2D > SAL_CALL queryMeasures( ) override;
|
||||
virtual css::uno::Sequence< double > SAL_CALL queryLogicalAdvancements( ) override;
|
||||
virtual void SAL_CALL applyLogicalAdvancements( const css::uno::Sequence< double >& aAdvancements ) override;
|
||||
virtual css::uno::Sequence< sal_Bool > SAL_CALL queryKashidaPositions( ) override;
|
||||
virtual void SAL_CALL applyKashidaPositions( const css::uno::Sequence< sal_Bool >& aPositions ) override;
|
||||
virtual css::geometry::RealRectangle2D SAL_CALL queryTextBounds( ) override;
|
||||
virtual double SAL_CALL justify( double nSize ) override;
|
||||
virtual double SAL_CALL combinedJustify( const css::uno::Sequence< css::uno::Reference< css::rendering::XTextLayout > >& aNextLayouts, double nSize ) override;
|
||||
virtual css::rendering::TextHit SAL_CALL getTextHit( const css::geometry::RealPoint2D& aHitPoint ) override;
|
||||
virtual css::rendering::Caret SAL_CALL getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) override;
|
||||
virtual sal_Int32 SAL_CALL getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) override;
|
||||
virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
|
||||
virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
|
||||
virtual double SAL_CALL getBaselineOffset( ) override;
|
||||
virtual sal_Int8 SAL_CALL getMainTextDirection( ) override;
|
||||
virtual css::uno::Reference< css::rendering::XCanvasFont > SAL_CALL getFont( ) override;
|
||||
virtual css::rendering::StringContext SAL_CALL getText( ) 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;
|
||||
|
||||
void draw( OutputDevice& rOutDev,
|
||||
const Point& rOutpos,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState ) const;
|
||||
|
||||
KernArray setupTextOffsets(
|
||||
const css::uno::Sequence< double >& inputOffsets,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState ) const;
|
||||
|
||||
protected:
|
||||
virtual ~TextLayout() override; // we're a ref-counted UNO class. _We_ destroy ourselves.
|
||||
|
||||
private:
|
||||
css::rendering::StringContext maText;
|
||||
css::uno::Sequence< double > maLogicalAdvancements;
|
||||
css::uno::Sequence< sal_Bool > maKashidaPositions;
|
||||
CanvasFont::Reference mpFont;
|
||||
SurfaceProviderRef mpRefDevice;
|
||||
sal_Int8 mnTextDirection;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* 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 .
|
||||
-->
|
||||
|
||||
<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
|
||||
xmlns="http://openoffice.org/2010/uno-components">
|
||||
<implementation name="com.sun.star.comp.rendering.Canvas.Cairo"
|
||||
constructor="com_sun_star_comp_rendering_Canvas_Cairo_get_implementation">
|
||||
<service name="com.sun.star.rendering.Canvas.Cairo"/>
|
||||
</implementation>
|
||||
<implementation name="com.sun.star.comp.rendering.SpriteCanvas.Cairo"
|
||||
constructor="com_sun_star_comp_rendering_SpriteCanvas_Cairo_get_implementation">
|
||||
<service name="com.sun.star.rendering.SpriteCanvas.Cairo"/>
|
||||
</implementation>
|
||||
</component>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* 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 .
|
||||
-->
|
||||
|
||||
<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
|
||||
xmlns="http://openoffice.org/2010/uno-components">
|
||||
<implementation name="com.sun.star.comp.rendering.SpriteCanvas.DX9"
|
||||
constructor="canvas_directx9_SpriteCanvas_get_implementation">
|
||||
<service name="com.sun.star.rendering.SpriteCanvas.DX9"/>
|
||||
</implementation>
|
||||
</component>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,204 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/range/b2irange.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include "dx_bitmap.hxx"
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
|
||||
// DXBitmap::DXBitmap
|
||||
|
||||
|
||||
DXBitmap::DXBitmap( const BitmapSharedPtr& rBitmap,
|
||||
bool bWithAlpha ) :
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
maSize(rBitmap->GetWidth(),rBitmap->GetHeight()),
|
||||
mpBitmap(rBitmap),
|
||||
mpGraphics(tools::createGraphicsFromBitmap(mpBitmap)),
|
||||
mbAlpha(bWithAlpha)
|
||||
{
|
||||
}
|
||||
|
||||
DXBitmap::DXBitmap( const ::basegfx::B2ISize& rSize,
|
||||
bool bWithAlpha ) :
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
maSize(rSize),
|
||||
mpBitmap(),
|
||||
mpGraphics(),
|
||||
mbAlpha(bWithAlpha)
|
||||
{
|
||||
// create container for pixel data
|
||||
if(mbAlpha)
|
||||
{
|
||||
mpBitmap = std::make_shared<Gdiplus::Bitmap>(
|
||||
maSize.getWidth(),
|
||||
maSize.getHeight(),
|
||||
PixelFormat32bppARGB);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpBitmap = std::make_shared<Gdiplus::Bitmap>(
|
||||
maSize.getWidth(),
|
||||
maSize.getHeight(),
|
||||
PixelFormat24bppRGB);
|
||||
}
|
||||
|
||||
mpGraphics = tools::createGraphicsFromBitmap(mpBitmap);
|
||||
}
|
||||
|
||||
BitmapSharedPtr DXBitmap::getBitmap() const
|
||||
{
|
||||
return mpBitmap;
|
||||
}
|
||||
|
||||
GraphicsSharedPtr DXBitmap::getGraphics()
|
||||
{
|
||||
return mpGraphics;
|
||||
}
|
||||
|
||||
::basegfx::B2ISize DXBitmap::getSize() const
|
||||
{
|
||||
return maSize;
|
||||
}
|
||||
|
||||
bool DXBitmap::hasAlpha() const
|
||||
{
|
||||
return mbAlpha;
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Int8 > DXBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
|
||||
|
||||
const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = rect.X2-rect.X1;
|
||||
aBmpData.Height = rect.Y2-rect.Y1;
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = aRes.getArray();
|
||||
|
||||
// TODO(F1): Support more pixel formats natively
|
||||
|
||||
// read data from bitmap
|
||||
if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
|
||||
PixelFormat32bppARGB, // TODO(F1): Adapt to
|
||||
// Graphics native
|
||||
// format/change
|
||||
// getMemoryLayout
|
||||
&aBmpData ) )
|
||||
{
|
||||
// failed to lock, bail out
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
}
|
||||
|
||||
mpBitmap->UnlockBits( &aBmpData );
|
||||
|
||||
return aRes;
|
||||
}
|
||||
|
||||
void DXBitmap::setData( const uno::Sequence< sal_Int8 >& data,
|
||||
const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = rect.X2-rect.X1;
|
||||
aBmpData.Height = rect.Y2-rect.Y1;
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = const_cast<sal_Int8 *>(data.getConstArray());
|
||||
// const_cast is safe, "Gdiplus::ImageLockModeWrite
|
||||
// | Gdiplus::ImageLockModeUserInputBuf makes the data go from
|
||||
// BitmapData into Bitmap", says Thorsten
|
||||
|
||||
// TODO(F1): Support more pixel formats natively
|
||||
|
||||
if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
|
||||
PixelFormat32bppARGB, // TODO: Adapt to
|
||||
// Graphics native
|
||||
// format/change
|
||||
// getMemoryLayout
|
||||
&aBmpData ) )
|
||||
{
|
||||
throw uno::RuntimeException("Internal error while writing BitmapData into Bitmap");
|
||||
}
|
||||
|
||||
// commit data to bitmap
|
||||
mpBitmap->UnlockBits( &aBmpData );
|
||||
}
|
||||
|
||||
void DXBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
|
||||
const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
const geometry::IntegerSize2D aSize( maSize.getWidth(),maSize.getHeight() );
|
||||
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
|
||||
"CanvasHelper::setPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
|
||||
"CanvasHelper::setPixel: Y coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( color.getLength() > 3,
|
||||
"CanvasHelper::setPixel: not enough color components" );
|
||||
|
||||
if( Gdiplus::Ok != mpBitmap->SetPixel( pos.X, pos.Y,
|
||||
Gdiplus::Color( tools::sequenceToArgb( color ))))
|
||||
{
|
||||
throw uno::RuntimeException("SetPixel called with invalid x,y points or color");
|
||||
}
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Int8 > DXBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
const geometry::IntegerSize2D aSize( maSize.getWidth(),maSize.getHeight() );
|
||||
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
|
||||
"CanvasHelper::getPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
|
||||
"CanvasHelper::getPixel: Y coordinate out of bounds" );
|
||||
|
||||
Gdiplus::Color aColor;
|
||||
|
||||
if( Gdiplus::Ok != mpBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
|
||||
return tools::argbToIntSequence(aColor.GetValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,82 @@
|
||||
/* -*- 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/rendering/XCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <basegfx/vector/b2ivector.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/range/b2drange.hxx>
|
||||
#include <memory>
|
||||
#include "dx_winstuff.hxx"
|
||||
#include "dx_ibitmap.hxx"
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class DXBitmap : public IBitmap
|
||||
{
|
||||
public:
|
||||
DXBitmap( const BitmapSharedPtr& rBitmap, bool bWithAlpha );
|
||||
DXBitmap( const ::basegfx::B2ISize& rSize, bool bWithAlpha );
|
||||
|
||||
virtual GraphicsSharedPtr getGraphics() override;
|
||||
|
||||
virtual BitmapSharedPtr getBitmap() const override;
|
||||
virtual ::basegfx::B2ISize getSize() const override;
|
||||
virtual bool hasAlpha() const override;
|
||||
|
||||
css::uno::Sequence< sal_Int8 > getData(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) override;
|
||||
|
||||
void setData(
|
||||
const css::uno::Sequence< sal_Int8 >& data,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) override;
|
||||
|
||||
void setPixel(
|
||||
const css::uno::Sequence< sal_Int8 >& color,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) override;
|
||||
|
||||
css::uno::Sequence< sal_Int8 > getPixel(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) override;
|
||||
|
||||
private:
|
||||
// Refcounted global GDI+ state container
|
||||
GDIPlusUserSharedPtr mpGdiPlusUser;
|
||||
|
||||
// size of this image in pixels [integral unit]
|
||||
::basegfx::B2ISize maSize;
|
||||
|
||||
BitmapSharedPtr mpBitmap;
|
||||
GraphicsSharedPtr mpGraphics;
|
||||
|
||||
// true if the bitmap contains an alpha channel
|
||||
bool mbAlpha;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< DXBitmap > DXBitmapSharedPtr;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,221 @@
|
||||
/* -*- 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 <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/rendering/CompositeOperation.hpp>
|
||||
#include <com/sun/star/rendering/PathCapType.hpp>
|
||||
#include <com/sun/star/rendering/PathJoinType.hpp>
|
||||
#include <com/sun/star/rendering/RepaintResult.hpp>
|
||||
#include <com/sun/star/rendering/TexturingMode.hpp>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_bitmapcanvashelper.hxx"
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_textlayout.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
BitmapCanvasHelper::BitmapCanvasHelper() :
|
||||
mpTarget()
|
||||
{}
|
||||
|
||||
void BitmapCanvasHelper::disposing()
|
||||
{
|
||||
mpTarget.reset();
|
||||
CanvasHelper::disposing();
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget )
|
||||
{
|
||||
ENSURE_OR_THROW( rTarget,
|
||||
"BitmapCanvasHelper::setTarget(): Invalid target" );
|
||||
ENSURE_OR_THROW( !mpTarget,
|
||||
"BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
|
||||
|
||||
mpTarget = rTarget;
|
||||
CanvasHelper::setTarget(rTarget);
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget,
|
||||
const ::basegfx::B2ISize& rOutputOffset )
|
||||
{
|
||||
ENSURE_OR_THROW( rTarget,
|
||||
"BitmapCanvasHelper::setTarget(): invalid target" );
|
||||
ENSURE_OR_THROW( !mpTarget,
|
||||
"BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
|
||||
|
||||
mpTarget = rTarget;
|
||||
CanvasHelper::setTarget(rTarget,rOutputOffset);
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::clear()
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpTarget->getGraphics() );
|
||||
|
||||
Gdiplus::Color aClearColor = hasAlpha() ?
|
||||
Gdiplus::Color( 0,255,255,255 ) : Gdiplus::Color(Gdiplus::ARGB(Gdiplus::Color::White));
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->SetCompositingMode(
|
||||
Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
|
||||
"BitmapCanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->Clear( aClearColor ),
|
||||
"BitmapCanvasHelper::clear(): GDI+ Clear call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > BitmapCanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XTextLayout >& xLayoutetText,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xLayoutetText.is(),
|
||||
"BitmapCanvasHelper::drawTextLayout: layout is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
TextLayout* pTextLayout =
|
||||
dynamic_cast< TextLayout* >( xLayoutetText.get() );
|
||||
|
||||
ENSURE_OR_THROW( pTextLayout,
|
||||
"BitmapCanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
|
||||
|
||||
pTextLayout->draw( mpTarget->getGraphics(),
|
||||
viewState,
|
||||
renderState,
|
||||
maOutputOffset,
|
||||
mpDevice,
|
||||
mpTarget->hasAlpha() );
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::copyRect( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XBitmapCanvas >& /*sourceCanvas*/,
|
||||
const geometry::RealRectangle2D& /*sourceRect*/,
|
||||
const rendering::ViewState& /*sourceViewState*/,
|
||||
const rendering::RenderState& /*sourceRenderState*/,
|
||||
const geometry::RealRectangle2D& /*destRect*/,
|
||||
const rendering::ViewState& /*destViewState*/,
|
||||
const rendering::RenderState& /*destRenderState*/ )
|
||||
{
|
||||
// TODO(F2): copyRect NYI
|
||||
}
|
||||
|
||||
geometry::IntegerSize2D BitmapCanvasHelper::getSize()
|
||||
{
|
||||
if( !mpTarget )
|
||||
return geometry::IntegerSize2D(1, 1);
|
||||
return basegfx::unotools::integerSize2DFromB2ISize(mpTarget->getSize());
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > BitmapCanvasHelper::getScaledBitmap( const geometry::RealSize2D& /*newSize*/,
|
||||
bool /*beFast*/ )
|
||||
{
|
||||
// TODO(F1):
|
||||
return uno::Reference< rendering::XBitmap >();
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Int8 > BitmapCanvasHelper::getData( rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
SAL_INFO( "canvas.directx", "::dxcanvas::BitmapCanvasHelper::getData()" );
|
||||
|
||||
ENSURE_OR_THROW( mpTarget,
|
||||
"::dxcanvas::BitmapCanvasHelper::getData(): disposed" );
|
||||
|
||||
bitmapLayout = getMemoryLayout();
|
||||
return mpTarget->getData(bitmapLayout,rect);
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::setData( const uno::Sequence< sal_Int8 >& data,
|
||||
const rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
SAL_INFO( "canvas.directx", "::dxcanvas::BitmapCanvasHelper::setData()" );
|
||||
|
||||
ENSURE_OR_THROW( mpTarget,
|
||||
"::dxcanvas::BitmapCanvasHelper::setData(): disposed" );
|
||||
|
||||
mpTarget->setData(data,bitmapLayout,rect);
|
||||
}
|
||||
|
||||
void BitmapCanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
|
||||
const rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
SAL_INFO( "canvas.directx", "::dxcanvas::BitmapCanvasHelper::setPixel()" );
|
||||
|
||||
ENSURE_OR_THROW( mpTarget,
|
||||
"::dxcanvas::BitmapCanvasHelper::setPixel(): disposed" );
|
||||
|
||||
mpTarget->setPixel(color,bitmapLayout,pos);
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Int8 > BitmapCanvasHelper::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
SAL_INFO( "canvas.directx", "::dxcanvas::BitmapCanvasHelper::getPixel()" );
|
||||
|
||||
ENSURE_OR_THROW( mpTarget,
|
||||
"::dxcanvas::BitmapCanvasHelper::getPixel(): disposed" );
|
||||
|
||||
bitmapLayout = getMemoryLayout();
|
||||
return mpTarget->getPixel(bitmapLayout,pos);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmapPalette > BitmapCanvasHelper::getPalette()
|
||||
{
|
||||
// TODO(F1): Palette bitmaps NYI
|
||||
return uno::Reference< rendering::XBitmapPalette >();
|
||||
}
|
||||
|
||||
rendering::IntegerBitmapLayout BitmapCanvasHelper::getMemoryLayout()
|
||||
{
|
||||
if( !mpTarget )
|
||||
return rendering::IntegerBitmapLayout(); // we're disposed
|
||||
|
||||
return ::canvas::tools::getStdMemoryLayout(getSize());
|
||||
}
|
||||
bool BitmapCanvasHelper::hasAlpha() const
|
||||
{
|
||||
return mpTarget && mpTarget->hasAlpha();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,126 @@
|
||||
/* -*- 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/rendering/XCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XBitmapCanvas.hpp>
|
||||
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <basegfx/vector/b2dsize.hxx>
|
||||
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_ibitmap.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_canvashelper.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Helper class for basic canvas functionality. Also offers
|
||||
optional backbuffer painting, when providing it with a second
|
||||
HDC to render into.
|
||||
*/
|
||||
class BitmapCanvasHelper : public CanvasHelper
|
||||
{
|
||||
public:
|
||||
BitmapCanvasHelper();
|
||||
|
||||
/// Release all references
|
||||
void disposing();
|
||||
|
||||
/** Set the target for rendering operations
|
||||
|
||||
@param rTarget
|
||||
Render target
|
||||
*/
|
||||
void setTarget( const IBitmapSharedPtr& rTarget );
|
||||
|
||||
/** Set the target for rendering operations
|
||||
|
||||
@param rTarget
|
||||
Render target
|
||||
|
||||
@param rOutputOffset
|
||||
Output offset in pixel
|
||||
*/
|
||||
void setTarget( const IBitmapSharedPtr& rTarget,
|
||||
const ::basegfx::B2ISize& rOutputOffset );
|
||||
|
||||
|
||||
// CanvasHelper functionality is implementation-inherited. yuck.
|
||||
// =============================================================
|
||||
void clear();
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawTextLayout( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XTextLayout >& laidOutText,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
|
||||
// BitmapCanvasHelper functionality
|
||||
// ================================
|
||||
|
||||
void copyRect( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XBitmapCanvas >& sourceCanvas,
|
||||
const css::geometry::RealRectangle2D& sourceRect,
|
||||
const css::rendering::ViewState& sourceViewState,
|
||||
const css::rendering::RenderState& sourceRenderState,
|
||||
const css::geometry::RealRectangle2D& destRect,
|
||||
const css::rendering::ViewState& destViewState,
|
||||
const css::rendering::RenderState& destRenderState );
|
||||
|
||||
css::geometry::IntegerSize2D getSize();
|
||||
|
||||
css::uno::Reference< css::rendering::XBitmap >
|
||||
getScaledBitmap( const css::geometry::RealSize2D& newSize,
|
||||
bool beFast );
|
||||
|
||||
css::uno::Sequence< sal_Int8 >
|
||||
getData( css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect );
|
||||
|
||||
void setData( const css::uno::Sequence< sal_Int8 >& data,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect );
|
||||
|
||||
void setPixel( const css::uno::Sequence< sal_Int8 >& color,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos );
|
||||
|
||||
css::uno::Sequence< sal_Int8 >
|
||||
getPixel( css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos );
|
||||
|
||||
css::uno::Reference< css::rendering::XBitmapPalette > getPalette();
|
||||
|
||||
css::rendering::IntegerBitmapLayout getMemoryLayout();
|
||||
|
||||
bool hasAlpha() const;
|
||||
|
||||
protected:
|
||||
/// Render target
|
||||
IBitmapSharedPtr mpTarget;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* -*- 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 "dx_ibitmap.hxx"
|
||||
#include <memory>
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
struct BitmapProvider
|
||||
{
|
||||
virtual ~BitmapProvider() {}
|
||||
virtual IBitmapSharedPtr getBitmap() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,256 @@
|
||||
// /* -*- 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 <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <sal/log.hxx>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
|
||||
#include <com/sun/star/awt/XWindow.hpp>
|
||||
#include <com/sun/star/lang/NoSupportException.hpp>
|
||||
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
|
||||
#include <com/sun/star/registry/XRegistryKey.hpp>
|
||||
#include <com/sun/star/uno/XComponentContext.hpp>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/sysdata.hxx>
|
||||
#include <vcl/skia/SkiaHelper.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvas.hxx"
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace {
|
||||
|
||||
/// Actual canonical implementation of the GraphicsProvider interface
|
||||
class GraphicsProviderImpl : public GraphicsProvider
|
||||
{
|
||||
GraphicsSharedPtr mpGraphics;
|
||||
public:
|
||||
explicit GraphicsProviderImpl( GraphicsSharedPtr && pGraphics ) : mpGraphics( std::move(pGraphics) ) {}
|
||||
virtual GraphicsSharedPtr getGraphics() override { return mpGraphics; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Canvas::Canvas( const uno::Sequence< uno::Any >& aArguments,
|
||||
const uno::Reference< uno::XComponentContext >& rxContext ) :
|
||||
maArguments(aArguments),
|
||||
mxComponentContext( rxContext )
|
||||
{
|
||||
}
|
||||
|
||||
void Canvas::initialize()
|
||||
{
|
||||
// #i64742# Only perform initialization when not in probe mode
|
||||
if( maArguments.getLength() == 0 )
|
||||
return;
|
||||
|
||||
assert( !SkiaHelper::isVCLSkiaEnabled() );
|
||||
|
||||
SAL_INFO("canvas.directx", "Canvas::initialize called" );
|
||||
|
||||
// At index 1, we expect a HWND handle here, containing a
|
||||
// pointer to a valid window, on which to output
|
||||
// At index 2, we expect the current window bound rect
|
||||
ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 &&
|
||||
maArguments[4].getValueTypeClass() == uno::TypeClass_SEQUENCE,
|
||||
"Canvas::initialize: wrong number of arguments, or wrong types" );
|
||||
|
||||
uno::Sequence<sal_Int8> aSeq;
|
||||
maArguments[4] >>= aSeq;
|
||||
|
||||
const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
|
||||
if( !pSysData || !pSysData->hDC )
|
||||
throw lang::NoSupportException("Passed SystemGraphicsData or HDC invalid!");
|
||||
|
||||
sal_Int64 nPtr = 0;
|
||||
maArguments[0] >>= nPtr;
|
||||
OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
|
||||
ENSURE_ARG_OR_THROW( pOutDev != nullptr,"Canvas::initialize: invalid OutDev pointer" );
|
||||
|
||||
// setup helper
|
||||
maDeviceHelper.init( pSysData->hDC, pOutDev, *this );
|
||||
maCanvasHelper.setDevice( *this );
|
||||
maCanvasHelper.setTarget(
|
||||
std::make_shared<GraphicsProviderImpl>(
|
||||
GraphicsSharedPtr(Gdiplus::Graphics::FromHDC(pSysData->hDC))));
|
||||
|
||||
maArguments.realloc(0);
|
||||
}
|
||||
|
||||
void Canvas::disposeThis()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
mxComponentContext.clear();
|
||||
|
||||
// forward to parent
|
||||
CanvasBaseT::disposeThis();
|
||||
}
|
||||
|
||||
OUString SAL_CALL Canvas::getServiceName( )
|
||||
{
|
||||
return u"com.sun.star.rendering.Canvas.GDI+"_ustr;
|
||||
}
|
||||
|
||||
// XServiceInfo
|
||||
css::uno::Sequence<OUString> Canvas::getSupportedServiceNames( )
|
||||
{
|
||||
return { u"com.sun.star.rendering.Canvas.GDI+"_ustr };
|
||||
}
|
||||
OUString Canvas::getImplementationName( )
|
||||
{
|
||||
return u"com.sun.star.comp.rendering.Canvas.GDI+"_ustr;
|
||||
}
|
||||
sal_Bool Canvas::supportsService( const OUString& sServiceName )
|
||||
{
|
||||
return cppu::supportsService(this, sServiceName);
|
||||
}
|
||||
|
||||
BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >& aArguments,
|
||||
const uno::Reference< uno::XComponentContext >& rxContext ) :
|
||||
maArguments(aArguments),
|
||||
mxComponentContext( rxContext ),
|
||||
mpTarget()
|
||||
{
|
||||
}
|
||||
|
||||
void BitmapCanvas::initialize()
|
||||
{
|
||||
// #i64742# Only perform initialization when not in probe mode
|
||||
if( maArguments.getLength() == 0 )
|
||||
return;
|
||||
|
||||
SAL_INFO("canvas.directx", "BitmapCanvas::initialize called" );
|
||||
|
||||
// At index 1, we expect a HWND handle here, containing a
|
||||
// pointer to a valid window, on which to output
|
||||
// At index 2, we expect the current window bound rect
|
||||
ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 &&
|
||||
maArguments[4].getValueTypeClass() == uno::TypeClass_SEQUENCE,
|
||||
"Canvas::initialize: wrong number of arguments, or wrong types" );
|
||||
|
||||
uno::Sequence<sal_Int8> aSeq;
|
||||
maArguments[4] >>= aSeq;
|
||||
|
||||
const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
|
||||
if( !pSysData || !pSysData->hDC )
|
||||
throw lang::NoSupportException( "Passed SystemGraphicsData or HDC invalid!");
|
||||
|
||||
sal_Int64 nPtr = 0;
|
||||
maArguments[0] >>= nPtr;
|
||||
OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
|
||||
ENSURE_ARG_OR_THROW( pOutDev != nullptr,"Canvas::initialize: invalid OutDev pointer" );
|
||||
|
||||
// setup helper
|
||||
maDeviceHelper.init( pSysData->hDC, pOutDev, *this );
|
||||
maCanvasHelper.setDevice( *this );
|
||||
|
||||
// check whether we can actually provide a BitmapCanvas
|
||||
// here. for this, check whether the HDC has a bitmap
|
||||
// selected.
|
||||
HBITMAP hBmp;
|
||||
hBmp=static_cast<HBITMAP>(GetCurrentObject(pSysData->hDC, OBJ_BITMAP));
|
||||
if( !hBmp || GetObjectType(pSysData->hDC) != OBJ_MEMDC )
|
||||
{
|
||||
throw lang::NoSupportException( "Passed HDC is no mem DC/has no bitmap selected!");
|
||||
}
|
||||
|
||||
mpTarget = std::make_shared<DXBitmap>(
|
||||
BitmapSharedPtr(
|
||||
Gdiplus::Bitmap::FromHBITMAP(
|
||||
hBmp, nullptr) ),
|
||||
false );
|
||||
|
||||
maCanvasHelper.setTarget( mpTarget );
|
||||
|
||||
maArguments.realloc(0);
|
||||
}
|
||||
|
||||
void BitmapCanvas::disposeThis()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
mpTarget.reset();
|
||||
mxComponentContext.clear();
|
||||
|
||||
// forward to parent
|
||||
BitmapCanvasBaseT::disposeThis();
|
||||
}
|
||||
|
||||
OUString SAL_CALL BitmapCanvas::getServiceName( )
|
||||
{
|
||||
return u"com.sun.star.rendering.BitmapCanvas.GDI+"_ustr;
|
||||
}
|
||||
|
||||
// XServiceInfo
|
||||
css::uno::Sequence<OUString> BitmapCanvas::getSupportedServiceNames( )
|
||||
{
|
||||
return { u"com.sun.star.rendering.BitmapCanvas.GDI+"_ustr };
|
||||
}
|
||||
OUString BitmapCanvas::getImplementationName( )
|
||||
{
|
||||
return u"com.sun.star.comp.rendering.BitmapCanvas.GDI+"_ustr;
|
||||
}
|
||||
sal_Bool BitmapCanvas::supportsService( const OUString& sServiceName )
|
||||
{
|
||||
return cppu::supportsService(this, sServiceName);
|
||||
}
|
||||
|
||||
IBitmapSharedPtr BitmapCanvas::getBitmap() const
|
||||
{
|
||||
return mpTarget;
|
||||
}
|
||||
|
||||
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
||||
canvas_gdiplus_Canvas_get_implementation(
|
||||
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
|
||||
{
|
||||
rtl::Reference<Canvas> xCanvas(new Canvas(args, context));
|
||||
xCanvas->initialize();
|
||||
return cppu::acquire(xCanvas.get());
|
||||
}
|
||||
|
||||
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
||||
canvas_gdiplus_BitmapCanvas_get_implementation(
|
||||
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
|
||||
{
|
||||
rtl::Reference<BitmapCanvas> xCanvas(new BitmapCanvas(args, context));
|
||||
xCanvas->initialize();
|
||||
return cppu::acquire(xCanvas.get());
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,173 @@
|
||||
/* -*- 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 <rtl/ref.hxx>
|
||||
|
||||
#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/util/XUpdatable.hpp>
|
||||
#include <com/sun/star/rendering/XBitmapCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||
|
||||
#include <cppuhelper/compbase.hxx>
|
||||
#include <comphelper/uno3.hxx>
|
||||
|
||||
#include <base/integerbitmapbase.hxx>
|
||||
#include <base/basemutexhelper.hxx>
|
||||
#include <base/graphicdevicebase.hxx>
|
||||
#include <base/canvasbase.hxx>
|
||||
#include <base/bitmapcanvasbase.hxx>
|
||||
|
||||
#include "dx_bitmapprovider.hxx"
|
||||
#include "dx_canvashelper.hxx"
|
||||
#include "dx_bitmapcanvashelper.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_devicehelper.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XCanvas,
|
||||
css::rendering::XGraphicDevice,
|
||||
css::lang::XMultiServiceFactory,
|
||||
css::util::XUpdatable,
|
||||
css::beans::XPropertySet,
|
||||
css::lang::XServiceName,
|
||||
css::lang::XServiceInfo> GraphicDeviceBase1_Base;
|
||||
typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase1_Base >,
|
||||
DeviceHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > CanvasBase1_Base;
|
||||
typedef ::canvas::CanvasBase< CanvasBase1_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:
|
||||
Canvas( const css::uno::Sequence<
|
||||
css::uno::Any >& aArguments,
|
||||
const css::uno::Reference<
|
||||
css::uno::XComponentContext >& rxContext );
|
||||
|
||||
void initialize();
|
||||
|
||||
/// 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, GraphicDeviceBase1_Base, ::cppu::WeakComponentImplHelperBase )
|
||||
|
||||
// XServiceName
|
||||
virtual OUString SAL_CALL getServiceName( ) override;
|
||||
|
||||
// XServiceInfo
|
||||
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames( ) override;
|
||||
virtual OUString SAL_CALL getImplementationName( ) override;
|
||||
virtual sal_Bool SAL_CALL supportsService( const OUString& ) override;
|
||||
|
||||
private:
|
||||
css::uno::Sequence< css::uno::Any > maArguments;
|
||||
css::uno::Reference< css::uno::XComponentContext > mxComponentContext;
|
||||
};
|
||||
|
||||
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 > GraphicDeviceBase2_Base;
|
||||
typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase2_Base >,
|
||||
DeviceHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > CanvasBase2_Base;
|
||||
typedef ::canvas::IntegerBitmapBase<
|
||||
canvas::BitmapCanvasBase2<
|
||||
CanvasBase2_Base,
|
||||
BitmapCanvasHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject> > BitmapCanvasBaseT;
|
||||
|
||||
/** 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 BitmapCanvas : public BitmapCanvasBaseT, public BitmapProvider
|
||||
{
|
||||
public:
|
||||
BitmapCanvas( const css::uno::Sequence< css::uno::Any >& aArguments,
|
||||
const css::uno::Reference< css::uno::XComponentContext >& rxContext );
|
||||
|
||||
void initialize();
|
||||
|
||||
/// 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( BitmapCanvas, GraphicDeviceBase2_Base, ::cppu::WeakComponentImplHelperBase )
|
||||
|
||||
// XServiceName
|
||||
virtual OUString SAL_CALL getServiceName( ) override;
|
||||
|
||||
// XServiceInfo
|
||||
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames( ) override;
|
||||
virtual OUString SAL_CALL getImplementationName( ) override;
|
||||
virtual sal_Bool SAL_CALL supportsService( const OUString& ) override;
|
||||
|
||||
// BitmapProvider
|
||||
virtual IBitmapSharedPtr getBitmap() const override;
|
||||
|
||||
private:
|
||||
css::uno::Sequence< css::uno::Any > maArguments;
|
||||
css::uno::Reference< css::uno::XComponentContext > mxComponentContext;
|
||||
IBitmapSharedPtr mpTarget;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,257 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/bitmapex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvasbitmap.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
|
||||
const DeviceRef& rDevice ) :
|
||||
mpDevice( rDevice ),
|
||||
mpBitmap( rBitmap )
|
||||
{
|
||||
ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
|
||||
"CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
|
||||
|
||||
maCanvasHelper.setDevice( *mpDevice );
|
||||
maCanvasHelper.setTarget( mpBitmap );
|
||||
}
|
||||
|
||||
void CanvasBitmap::disposeThis()
|
||||
{
|
||||
mpBitmap.reset();
|
||||
mpDevice.clear();
|
||||
|
||||
// forward to parent
|
||||
CanvasBitmap_Base::disposeThis();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct AlphaDIB
|
||||
{
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
RGBQUAD bmiColors[256];
|
||||
AlphaDIB()
|
||||
: bmiHeader({0,0,0,1,8,BI_RGB,0,0,0,0,0})
|
||||
{
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
// this here fills palette with grey level colors, starting
|
||||
// from 0,0,0 up to 255,255,255
|
||||
BYTE const b(i);
|
||||
bmiColors[i] = { b,b,b,b };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle )
|
||||
{
|
||||
uno::Any aRes;
|
||||
// 0 ... get BitmapEx
|
||||
// 1 ... get Pixbuf with bitmap RGB content
|
||||
// 2 ... get Pixbuf with bitmap alpha mask
|
||||
switch( nHandle )
|
||||
{
|
||||
// sorry, no BitmapEx here...
|
||||
case 0:
|
||||
aRes <<= reinterpret_cast<sal_Int64>( nullptr );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
if(!mpBitmap->hasAlpha())
|
||||
{
|
||||
HBITMAP aHBmp;
|
||||
mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
|
||||
|
||||
uno::Sequence< uno::Any > args{ uno::Any(reinterpret_cast<sal_Int64>(aHBmp)) };
|
||||
aRes <<= args;
|
||||
}
|
||||
else
|
||||
{
|
||||
// need to copy&convert the bitmap, since dx
|
||||
// canvas uses inline alpha channel
|
||||
HDC hScreenDC=GetDC(nullptr);
|
||||
const basegfx::B2ISize aSize = mpBitmap->getSize();
|
||||
HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
|
||||
aSize.getWidth(),
|
||||
aSize.getHeight() );
|
||||
if( !hBmpBitmap )
|
||||
return aRes;
|
||||
|
||||
BITMAPINFOHEADER aBIH;
|
||||
|
||||
aBIH.biSize = sizeof( BITMAPINFOHEADER );
|
||||
aBIH.biWidth = aSize.getWidth();
|
||||
aBIH.biHeight = -aSize.getHeight();
|
||||
aBIH.biPlanes = 1;
|
||||
aBIH.biBitCount = 32;
|
||||
aBIH.biCompression = BI_RGB; // expects pixel in
|
||||
// bbggrrxx format
|
||||
// (little endian)
|
||||
aBIH.biSizeImage = 0;
|
||||
aBIH.biXPelsPerMeter = 0;
|
||||
aBIH.biYPelsPerMeter = 0;
|
||||
aBIH.biClrUsed = 0;
|
||||
aBIH.biClrImportant = 0;
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = aSize.getWidth();
|
||||
aBmpData.Height = aSize.getHeight();
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = nullptr;
|
||||
const Gdiplus::Rect aRect( 0,0,aSize.getWidth(),aSize.getHeight() );
|
||||
BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
|
||||
if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeRead,
|
||||
PixelFormat32bppARGB, // outputs ARGB (big endian)
|
||||
&aBmpData ) )
|
||||
{
|
||||
// failed to lock, bail out
|
||||
return aRes;
|
||||
}
|
||||
|
||||
// now aBmpData.Scan0 contains our bits - push
|
||||
// them into HBITMAP, ignoring alpha
|
||||
SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getHeight(), aBmpData.Scan0, reinterpret_cast<PBITMAPINFO>(&aBIH), DIB_RGB_COLORS );
|
||||
|
||||
pGDIPlusBitmap->UnlockBits( &aBmpData );
|
||||
|
||||
uno::Sequence< uno::Any > args{ uno::Any(reinterpret_cast<sal_Int64>(hBmpBitmap)) };
|
||||
aRes <<= args;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
if(!mpBitmap->hasAlpha())
|
||||
{
|
||||
return aRes;
|
||||
}
|
||||
else
|
||||
{
|
||||
static AlphaDIB aDIB;
|
||||
|
||||
// need to copy&convert the bitmap, since dx
|
||||
// canvas uses inline alpha channel
|
||||
HDC hScreenDC=GetDC(nullptr);
|
||||
const basegfx::B2ISize aSize = mpBitmap->getSize();
|
||||
HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getWidth(), aSize.getHeight() );
|
||||
if( !hBmpBitmap )
|
||||
return aRes;
|
||||
|
||||
aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
|
||||
aDIB.bmiHeader.biWidth = aSize.getWidth();
|
||||
aDIB.bmiHeader.biHeight = -aSize.getHeight();
|
||||
aDIB.bmiHeader.biPlanes = 1;
|
||||
aDIB.bmiHeader.biBitCount = 8;
|
||||
aDIB.bmiHeader.biCompression = BI_RGB;
|
||||
aDIB.bmiHeader.biSizeImage = 0;
|
||||
aDIB.bmiHeader.biXPelsPerMeter = 0;
|
||||
aDIB.bmiHeader.biYPelsPerMeter = 0;
|
||||
aDIB.bmiHeader.biClrUsed = 0;
|
||||
aDIB.bmiHeader.biClrImportant = 0;
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = aSize.getWidth();
|
||||
aBmpData.Height = aSize.getHeight();
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = nullptr;
|
||||
const Gdiplus::Rect aRect( 0,0,aSize.getWidth(),aSize.getHeight() );
|
||||
BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
|
||||
if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeRead,
|
||||
PixelFormat32bppARGB, // outputs ARGB (big endian)
|
||||
&aBmpData ) )
|
||||
{
|
||||
// failed to lock, bail out
|
||||
return aRes;
|
||||
}
|
||||
|
||||
// copy only alpha channel to pAlphaBits
|
||||
const sal_Int32 nScanWidth((aSize.getWidth() + 3) & ~3);
|
||||
std::unique_ptr<sal_uInt8[]> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getHeight()] );
|
||||
const sal_uInt8* pInBits=static_cast<sal_uInt8*>(aBmpData.Scan0);
|
||||
assert(pInBits);
|
||||
pInBits+=3;
|
||||
for( sal_Int32 y=0; y<aSize.getHeight(); ++y )
|
||||
{
|
||||
sal_uInt8* pOutBits=pAlphaBits.get()+y*nScanWidth;
|
||||
for( sal_Int32 x=0; x<aSize.getWidth(); ++x )
|
||||
{
|
||||
*pOutBits++ = *pInBits;
|
||||
pInBits += 4;
|
||||
}
|
||||
}
|
||||
|
||||
pGDIPlusBitmap->UnlockBits( &aBmpData );
|
||||
|
||||
// set bits to newly create HBITMAP
|
||||
SetDIBits( hScreenDC, hBmpBitmap, 0,
|
||||
aSize.getHeight(), pAlphaBits.get(),
|
||||
reinterpret_cast<PBITMAPINFO>(&aDIB), DIB_RGB_COLORS );
|
||||
|
||||
uno::Sequence< uno::Any > args{ uno::Any(reinterpret_cast<sal_Int64>(hBmpBitmap)) };
|
||||
aRes <<= args;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return aRes;
|
||||
}
|
||||
|
||||
OUString SAL_CALL CanvasBitmap::getImplementationName( )
|
||||
{
|
||||
return "DXCanvas.CanvasBitmap";
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName )
|
||||
{
|
||||
return cppu::supportsService( this, ServiceName );
|
||||
}
|
||||
|
||||
uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( )
|
||||
{
|
||||
return { "com.sun.star.rendering.CanvasBitmap" };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,91 @@
|
||||
/* -*- 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/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 <basegfx/vector/b2isize.hxx>
|
||||
#include <cppuhelper/compbase.hxx>
|
||||
#include <base/basemutexhelper.hxx>
|
||||
#include <base/bitmapcanvasbase.hxx>
|
||||
#include <base/integerbitmapbase.hxx>
|
||||
|
||||
#include "dx_bitmapprovider.hxx"
|
||||
#include "dx_bitmapcanvashelper.hxx"
|
||||
#include "dx_devicehelper.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_ibitmap.hxx"
|
||||
|
||||
|
||||
/* Definition of CanvasBitmap class */
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XBitmapCanvas,
|
||||
css::rendering::XIntegerBitmap,
|
||||
css::lang::XServiceInfo,
|
||||
css::beans::XFastPropertySet > CanvasBitmapBase_Base;
|
||||
typedef ::canvas::IntegerBitmapBase<
|
||||
canvas::BitmapCanvasBase2<
|
||||
::canvas::BaseMutexHelper< CanvasBitmapBase_Base >,
|
||||
BitmapCanvasHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject> > CanvasBitmap_Base;
|
||||
|
||||
class CanvasBitmap : public CanvasBitmap_Base, public BitmapProvider
|
||||
{
|
||||
public:
|
||||
/** Create a canvas bitmap for the given surface
|
||||
|
||||
@param rSurface
|
||||
Surface to create API object for.
|
||||
|
||||
@param rDevice
|
||||
Reference device, with which bitmap should be compatible
|
||||
*/
|
||||
CanvasBitmap( const IBitmapSharedPtr& rSurface,
|
||||
const DeviceRef& rDevice );
|
||||
|
||||
/// Dispose all internal references
|
||||
virtual void disposeThis() 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;
|
||||
|
||||
// BitmapProvider
|
||||
virtual IBitmapSharedPtr getBitmap() const override { return mpBitmap; }
|
||||
|
||||
virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
|
||||
virtual void SAL_CALL setFastPropertyValue(sal_Int32, const css::uno::Any&) override {}
|
||||
|
||||
private:
|
||||
/** MUST hold here, too, since CanvasHelper only contains a
|
||||
raw pointer (without refcounting)
|
||||
*/
|
||||
DeviceRef mpDevice;
|
||||
IBitmapSharedPtr mpBitmap;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,106 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvascustomsprite.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
CanvasCustomSprite::CanvasCustomSprite( const css::geometry::RealSize2D& rSpriteSize,
|
||||
const SpriteCanvasRef& rRefDevice,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rSurfaceProxy,
|
||||
bool bShowSpriteBounds ) :
|
||||
mpSpriteCanvas( rRefDevice ),
|
||||
mpSurface()
|
||||
{
|
||||
ENSURE_OR_THROW( rRefDevice,
|
||||
"CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
|
||||
|
||||
mpSurface = std::make_shared<DXSurfaceBitmap>(
|
||||
::basegfx::B2ISize(
|
||||
::canvas::tools::roundUp( rSpriteSize.Width ),
|
||||
::canvas::tools::roundUp( rSpriteSize.Height )),
|
||||
rSurfaceProxy,
|
||||
rRenderModule,
|
||||
true);
|
||||
|
||||
maCanvasHelper.setDevice( *rRefDevice );
|
||||
maCanvasHelper.setTarget( mpSurface );
|
||||
|
||||
maSpriteHelper.init( rSpriteSize,
|
||||
rRefDevice,
|
||||
rRenderModule,
|
||||
mpSurface,
|
||||
bShowSpriteBounds );
|
||||
|
||||
// clear sprite to 100% transparent
|
||||
maCanvasHelper.clear();
|
||||
}
|
||||
|
||||
void CanvasCustomSprite::disposeThis()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
mpSurface.reset();
|
||||
mpSpriteCanvas.clear();
|
||||
|
||||
// forward to parent
|
||||
CanvasCustomSpriteBaseT::disposeThis();
|
||||
}
|
||||
|
||||
OUString SAL_CALL CanvasCustomSprite::getImplementationName()
|
||||
{
|
||||
return "DXCanvas.CanvasCustomSprite";
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const OUString& ServiceName )
|
||||
{
|
||||
return cppu::supportsService( this, ServiceName );
|
||||
}
|
||||
|
||||
uno::Sequence< OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames()
|
||||
{
|
||||
return { "com.sun.star.rendering.CanvasCustomSprite" };
|
||||
}
|
||||
|
||||
void CanvasCustomSprite::redraw() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
maSpriteHelper.redraw( mbSurfaceDirty );
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,130 @@
|
||||
/* -*- 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/lang/XComponent.hpp>
|
||||
#include <com/sun/star/rendering/XCustomSprite.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
|
||||
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
|
||||
#include <base/basemutexhelper.hxx>
|
||||
#include <base/canvascustomspritebase.hxx>
|
||||
|
||||
#include "dx_sprite.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
#include "dx_bitmapcanvashelper.hxx"
|
||||
#include "dx_spritehelper.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
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
|
||||
{
|
||||
};
|
||||
|
||||
typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
|
||||
SpriteHelper,
|
||||
BitmapCanvasHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > CanvasCustomSpriteBaseT;
|
||||
|
||||
/* Definition of CanvasCustomSprite class */
|
||||
|
||||
class CanvasCustomSprite : public CanvasCustomSpriteBaseT
|
||||
{
|
||||
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,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rSurfaceProxy,
|
||||
bool bShowSpriteBounds );
|
||||
|
||||
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 override;
|
||||
|
||||
private:
|
||||
/** MUST hold here, too, since BitmapCanvasHelper only contains a
|
||||
raw pointer (without refcounting)
|
||||
*/
|
||||
SpriteCanvasRef mpSpriteCanvas;
|
||||
DXSurfaceBitmapSharedPtr mpSurface;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,162 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <o3tl/char16_t2wchar_t.hxx>
|
||||
|
||||
#include <com/sun/star/rendering/PanoseWeight.hpp>
|
||||
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_textlayout.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
INT calcFontStyle( const rendering::FontRequest& rFontRequest )
|
||||
{
|
||||
INT nFontStyle( Gdiplus::FontStyleRegular );
|
||||
|
||||
if( rFontRequest.FontDescription.FontDescription.Weight > rendering::PanoseWeight::BOOK )
|
||||
nFontStyle = Gdiplus::FontStyleBold;
|
||||
|
||||
return nFontStyle;
|
||||
}
|
||||
}
|
||||
|
||||
CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
|
||||
const uno::Sequence< beans::PropertyValue >& extraFontProperties,
|
||||
const geometry::Matrix2D& fontMatrix ) :
|
||||
CanvasFont_Base( m_aMutex ),
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
mpFontFamily(),
|
||||
mpFont(),
|
||||
maFontRequest( rFontRequest ),
|
||||
mnEmphasisMark(0),
|
||||
maFontMatrix( fontMatrix )
|
||||
{
|
||||
mpFontFamily = std::make_shared<Gdiplus::FontFamily>(o3tl::toW(rFontRequest.FontDescription.FamilyName.getStr()),nullptr);
|
||||
if( !mpFontFamily->IsAvailable() )
|
||||
mpFontFamily = std::make_shared<Gdiplus::FontFamily>(L"Arial",nullptr);
|
||||
|
||||
mpFont = std::make_shared<Gdiplus::Font>( mpFontFamily.get(),
|
||||
static_cast<Gdiplus::REAL>(rFontRequest.CellSize),
|
||||
calcFontStyle( rFontRequest ),
|
||||
Gdiplus::UnitWorld );
|
||||
|
||||
::canvas::tools::extractExtraFontProperties(extraFontProperties, mnEmphasisMark);
|
||||
}
|
||||
|
||||
void SAL_CALL CanvasFont::disposing()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
mpFont.reset();
|
||||
mpFontFamily.reset();
|
||||
mpGdiPlusUser.reset();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText,
|
||||
sal_Int8 nDirection,
|
||||
sal_Int64 nRandomSeed )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) );
|
||||
}
|
||||
|
||||
uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< double >();
|
||||
}
|
||||
|
||||
uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< beans::PropertyValue >();
|
||||
}
|
||||
|
||||
rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maFontRequest;
|
||||
}
|
||||
|
||||
rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( )
|
||||
{
|
||||
// TODO
|
||||
return rendering::FontMetrics();
|
||||
}
|
||||
|
||||
OUString SAL_CALL CanvasFont::getImplementationName()
|
||||
{
|
||||
return "DXCanvas::CanvasFont";
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL CanvasFont::supportsService( const OUString& ServiceName )
|
||||
{
|
||||
return cppu::supportsService( this, ServiceName );
|
||||
}
|
||||
|
||||
uno::Sequence< OUString > SAL_CALL CanvasFont::getSupportedServiceNames()
|
||||
{
|
||||
return { "com.sun.star.rendering.CanvasFont" };
|
||||
}
|
||||
|
||||
double CanvasFont::getCellAscent() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return mpFontFamily->GetCellAscent(0); // TODO(F1): rFontRequest.styleName
|
||||
}
|
||||
|
||||
double CanvasFont::getEmHeight() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return mpFontFamily->GetEmHeight(0); // TODO(F1): rFontRequest.styleName
|
||||
}
|
||||
|
||||
FontSharedPtr CanvasFont::getFont() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return mpFont;
|
||||
}
|
||||
|
||||
const css::geometry::Matrix2D& CanvasFont::getFontMatrix() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maFontMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,92 @@
|
||||
/* -*- 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 <cppuhelper/basemutex.hxx>
|
||||
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
#include <com/sun/star/rendering/XCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XCanvasFont.hpp>
|
||||
|
||||
#include <rtl/ref.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "dx_winstuff.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
|
||||
|
||||
/* Definition of CanvasFont class */
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
typedef std::shared_ptr< Gdiplus::Font > FontSharedPtr;
|
||||
typedef std::shared_ptr< Gdiplus::FontFamily > FontFamilySharedPtr;
|
||||
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XCanvasFont,
|
||||
css::lang::XServiceInfo > CanvasFont_Base;
|
||||
|
||||
class CanvasFont : public ::cppu::BaseMutex,
|
||||
public CanvasFont_Base
|
||||
{
|
||||
public:
|
||||
typedef rtl::Reference<CanvasFont> ImplRef;
|
||||
/// 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& fontMatrix );
|
||||
|
||||
/// Dispose all internal references
|
||||
virtual void SAL_CALL disposing() 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;
|
||||
|
||||
double getCellAscent() const;
|
||||
double getEmHeight() const;
|
||||
FontSharedPtr getFont() const;
|
||||
const css::geometry::Matrix2D& getFontMatrix() const;
|
||||
sal_uInt32 getEmphasisMark() const { return mnEmphasisMark; }
|
||||
|
||||
private:
|
||||
GDIPlusUserSharedPtr mpGdiPlusUser;
|
||||
FontFamilySharedPtr mpFontFamily;
|
||||
FontSharedPtr mpFont;
|
||||
css::rendering::FontRequest maFontRequest;
|
||||
sal_uInt32 mnEmphasisMark;
|
||||
css::geometry::Matrix2D maFontMatrix;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,813 @@
|
||||
/* -*- 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 <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/rendering/CompositeOperation.hpp>
|
||||
#include <com/sun/star/rendering/PathCapType.hpp>
|
||||
#include <com/sun/star/rendering/PathJoinType.hpp>
|
||||
#include <com/sun/star/rendering/RepaintResult.hpp>
|
||||
#include <com/sun/star/rendering/TexturingMode.hpp>
|
||||
#include <comphelper/sequence.hxx>
|
||||
#include <o3tl/char16_t2wchar_t.hxx>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_canvashelper.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_textlayout.hxx"
|
||||
#include "dx_vcltools.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Gdiplus::LineCap gdiLineCapFromCap( sal_Int8 nCapType )
|
||||
{
|
||||
switch( nCapType )
|
||||
{
|
||||
case rendering::PathCapType::BUTT:
|
||||
return Gdiplus::LineCapFlat;
|
||||
|
||||
case rendering::PathCapType::ROUND:
|
||||
return Gdiplus::LineCapRound;
|
||||
|
||||
case rendering::PathCapType::SQUARE:
|
||||
return Gdiplus::LineCapSquare;
|
||||
|
||||
default:
|
||||
ENSURE_OR_THROW( false,
|
||||
"gdiLineCapFromCap(): Unexpected cap type" );
|
||||
}
|
||||
|
||||
return Gdiplus::LineCapFlat;
|
||||
}
|
||||
|
||||
Gdiplus::DashCap gdiDashCapFromCap( sal_Int8 nCapType )
|
||||
{
|
||||
switch( nCapType )
|
||||
{
|
||||
case rendering::PathCapType::BUTT:
|
||||
return Gdiplus::DashCapFlat;
|
||||
|
||||
case rendering::PathCapType::ROUND:
|
||||
return Gdiplus::DashCapRound;
|
||||
|
||||
// Gdiplus does not know square, using flat would make short
|
||||
// dashes disappear, so use triangle as the closest one.
|
||||
case rendering::PathCapType::SQUARE:
|
||||
return Gdiplus::DashCapTriangle;
|
||||
|
||||
default:
|
||||
ENSURE_OR_THROW( false,
|
||||
"gdiDashCapFromCap(): Unexpected cap type" );
|
||||
}
|
||||
|
||||
return Gdiplus::DashCapFlat;
|
||||
}
|
||||
|
||||
Gdiplus::LineJoin gdiJoinFromJoin( sal_Int8 nJoinType )
|
||||
{
|
||||
switch( nJoinType )
|
||||
{
|
||||
case rendering::PathJoinType::NONE:
|
||||
SAL_WARN( "canvas.directx", "gdiJoinFromJoin(): Join NONE not possible, mapping to BEVEL (closest to NONE)" );
|
||||
return Gdiplus::LineJoinBevel;
|
||||
|
||||
case rendering::PathJoinType::MITER:
|
||||
// in GDI+ fallback to Bevel, if miter limit is exceeded, is not done
|
||||
// by Gdiplus::LineJoinMiter but by Gdiplus::LineJoinMiterClipped
|
||||
return Gdiplus::LineJoinMiterClipped;
|
||||
|
||||
case rendering::PathJoinType::ROUND:
|
||||
return Gdiplus::LineJoinRound;
|
||||
|
||||
case rendering::PathJoinType::BEVEL:
|
||||
return Gdiplus::LineJoinBevel;
|
||||
|
||||
default:
|
||||
ENSURE_OR_THROW( false,
|
||||
"gdiJoinFromJoin(): Unexpected join type" );
|
||||
}
|
||||
|
||||
return Gdiplus::LineJoinMiter;
|
||||
}
|
||||
}
|
||||
|
||||
CanvasHelper::CanvasHelper() :
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
mpDevice( nullptr ),
|
||||
mpGraphicsProvider(),
|
||||
maOutputOffset()
|
||||
{
|
||||
}
|
||||
|
||||
void CanvasHelper::disposing()
|
||||
{
|
||||
mpGraphicsProvider.reset();
|
||||
mpDevice = nullptr;
|
||||
mpGdiPlusUser.reset();
|
||||
}
|
||||
|
||||
void CanvasHelper::setDevice( rendering::XGraphicDevice& rDevice )
|
||||
{
|
||||
mpDevice = &rDevice;
|
||||
}
|
||||
|
||||
void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget )
|
||||
{
|
||||
ENSURE_OR_THROW( rTarget,
|
||||
"CanvasHelper::setTarget(): Invalid target" );
|
||||
ENSURE_OR_THROW( !mpGraphicsProvider,
|
||||
"CanvasHelper::setTarget(): target set, old target would be overwritten" );
|
||||
|
||||
mpGraphicsProvider = rTarget;
|
||||
}
|
||||
|
||||
void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget,
|
||||
const ::basegfx::B2ISize& rOutputOffset )
|
||||
{
|
||||
ENSURE_OR_THROW( rTarget,
|
||||
"CanvasHelper::setTarget(): invalid target" );
|
||||
ENSURE_OR_THROW( !mpGraphicsProvider,
|
||||
"CanvasHelper::setTarget(): target set, old target would be overwritten" );
|
||||
|
||||
mpGraphicsProvider = rTarget;
|
||||
maOutputOffset = rOutputOffset;
|
||||
}
|
||||
|
||||
void CanvasHelper::clear()
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
Gdiplus::Color aClearColor{Gdiplus::ARGB(Gdiplus::Color::White)};
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->SetCompositingMode(
|
||||
Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
|
||||
"CanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->Clear( aClearColor ),
|
||||
"CanvasHelper::clear(): GDI+ Clear call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasHelper::drawPoint( const rendering::XCanvas* /*pCanvas*/,
|
||||
const geometry::RealPoint2D& aPoint,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::SolidBrush aBrush(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)) );
|
||||
|
||||
// determine size of one-by-one device pixel ellipse
|
||||
Gdiplus::Matrix aMatrix;
|
||||
pGraphics->GetTransform(&aMatrix);
|
||||
aMatrix.Invert();
|
||||
Gdiplus::PointF vector(1, 1);
|
||||
aMatrix.TransformVectors(&vector);
|
||||
|
||||
// paint a one-by-one circle, with the given point
|
||||
// in the middle (rounded to float)
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->FillEllipse( &aBrush,
|
||||
// disambiguate call
|
||||
Gdiplus::REAL(aPoint.X),
|
||||
Gdiplus::REAL(aPoint.Y),
|
||||
Gdiplus::REAL(vector.X),
|
||||
Gdiplus::REAL(vector.Y) ),
|
||||
"CanvasHelper::drawPoint(): GDI+ call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
|
||||
const geometry::RealPoint2D& aStartPoint,
|
||||
const geometry::RealPoint2D& aEndPoint,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::Pen aPen(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)),
|
||||
Gdiplus::REAL(0.0) );
|
||||
|
||||
// #122683# Switched precedence of pixel offset
|
||||
// mode. Seemingly, polygon stroking needs
|
||||
// PixelOffsetModeNone to achieve visually pleasing
|
||||
// results, whereas all other operations (e.g. polygon
|
||||
// fills, bitmaps) look better with PixelOffsetModeHalf.
|
||||
const Gdiplus::PixelOffsetMode aOldMode(
|
||||
pGraphics->GetPixelOffsetMode() );
|
||||
pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
|
||||
|
||||
Gdiplus::Status hr = pGraphics->DrawLine( &aPen,
|
||||
Gdiplus::REAL(aStartPoint.X), // disambiguate call
|
||||
Gdiplus::REAL(aStartPoint.Y),
|
||||
Gdiplus::REAL(aEndPoint.X),
|
||||
Gdiplus::REAL(aEndPoint.Y) );
|
||||
pGraphics->SetPixelOffsetMode( aOldMode );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == hr,
|
||||
"CanvasHelper::drawLine(): GDI+ call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/,
|
||||
const geometry::RealBezierSegment2D& aBezierSegment,
|
||||
const geometry::RealPoint2D& aEndPoint,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::Pen aPen(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)),
|
||||
Gdiplus::REAL(0.0) );
|
||||
|
||||
// #122683# Switched precedence of pixel offset
|
||||
// mode. Seemingly, polygon stroking needs
|
||||
// PixelOffsetModeNone to achieve visually pleasing
|
||||
// results, whereas all other operations (e.g. polygon
|
||||
// fills, bitmaps) look better with PixelOffsetModeHalf.
|
||||
const Gdiplus::PixelOffsetMode aOldMode(
|
||||
pGraphics->GetPixelOffsetMode() );
|
||||
pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
|
||||
|
||||
Gdiplus::Status hr = pGraphics->DrawBezier( &aPen,
|
||||
Gdiplus::REAL(aBezierSegment.Px), // disambiguate call
|
||||
Gdiplus::REAL(aBezierSegment.Py),
|
||||
Gdiplus::REAL(aBezierSegment.C1x),
|
||||
Gdiplus::REAL(aBezierSegment.C1y),
|
||||
Gdiplus::REAL(aEndPoint.X),
|
||||
Gdiplus::REAL(aEndPoint.Y),
|
||||
Gdiplus::REAL(aBezierSegment.C2x),
|
||||
Gdiplus::REAL(aBezierSegment.C2y) );
|
||||
|
||||
pGraphics->SetPixelOffsetMode( aOldMode );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == hr,
|
||||
"CanvasHelper::drawBezier(): GDI+ call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xPolyPolygon.is(),
|
||||
"CanvasHelper::drawPolyPolygon: polygon is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::Pen aPen(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)),
|
||||
Gdiplus::REAL(0.0) );
|
||||
|
||||
// #122683# Switched precedence of pixel offset
|
||||
// mode. Seemingly, polygon stroking needs
|
||||
// PixelOffsetModeNone to achieve visually pleasing
|
||||
// results, whereas all other operations (e.g. polygon
|
||||
// fills, bitmaps) look better with PixelOffsetModeHalf.
|
||||
const Gdiplus::PixelOffsetMode aOldMode(
|
||||
pGraphics->GetPixelOffsetMode() );
|
||||
pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
|
||||
|
||||
GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
|
||||
|
||||
// TODO(E1): Return value
|
||||
Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
|
||||
|
||||
pGraphics->SetPixelOffsetMode( aOldMode );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == hr,
|
||||
"CanvasHelper::drawPolyPolygon(): GDI+ call failed" );
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
const rendering::StrokeAttributes& strokeAttributes )
|
||||
{
|
||||
ENSURE_OR_THROW( xPolyPolygon.is(),
|
||||
"CanvasHelper::drawPolyPolygon: polygon is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
|
||||
// Setup stroke pen
|
||||
|
||||
|
||||
Gdiplus::Pen aPen(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)),
|
||||
static_cast< Gdiplus::REAL >(strokeAttributes.StrokeWidth) );
|
||||
|
||||
// #122683# Switched precedence of pixel offset
|
||||
// mode. Seemingly, polygon stroking needs
|
||||
// PixelOffsetModeNone to achieve visually pleasing
|
||||
// results, whereas all other operations (e.g. polygon
|
||||
// fills, bitmaps) look better with PixelOffsetModeHalf.
|
||||
const Gdiplus::PixelOffsetMode aOldMode(
|
||||
pGraphics->GetPixelOffsetMode() );
|
||||
pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
|
||||
|
||||
const bool bIsMiter(rendering::PathJoinType::MITER == strokeAttributes.JoinType);
|
||||
const bool bIsNone(rendering::PathJoinType::NONE == strokeAttributes.JoinType);
|
||||
|
||||
if(bIsMiter)
|
||||
aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) );
|
||||
|
||||
const std::vector< Gdiplus::REAL >& rDashArray(
|
||||
::comphelper::sequenceToContainer< std::vector< Gdiplus::REAL >, double >(
|
||||
strokeAttributes.DashArray ) );
|
||||
if( !rDashArray.empty() )
|
||||
{
|
||||
aPen.SetDashPattern( rDashArray.data(),
|
||||
rDashArray.size() );
|
||||
}
|
||||
aPen.SetLineCap( gdiLineCapFromCap(strokeAttributes.StartCapType),
|
||||
gdiLineCapFromCap(strokeAttributes.EndCapType),
|
||||
gdiDashCapFromCap(strokeAttributes.StartCapType));
|
||||
if(!bIsNone)
|
||||
aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
|
||||
|
||||
GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon, bIsNone ) );
|
||||
|
||||
// TODO(E1): Return value
|
||||
Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
|
||||
|
||||
pGraphics->SetPixelOffsetMode( aOldMode );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == hr,
|
||||
"CanvasHelper::strokePolyPolygon(): GDI+ call failed" );
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
|
||||
const rendering::ViewState& /*viewState*/,
|
||||
const rendering::RenderState& /*renderState*/,
|
||||
const uno::Sequence< rendering::Texture >& /*textures*/,
|
||||
const rendering::StrokeAttributes& /*strokeAttributes*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
|
||||
const rendering::ViewState& /*viewState*/,
|
||||
const rendering::RenderState& /*renderState*/,
|
||||
const uno::Sequence< rendering::Texture >& /*textures*/,
|
||||
const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
|
||||
const rendering::StrokeAttributes& /*strokeAttributes*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
|
||||
const rendering::ViewState& /*viewState*/,
|
||||
const rendering::RenderState& /*renderState*/,
|
||||
const rendering::StrokeAttributes& /*strokeAttributes*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XPolyPolygon2D >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xPolyPolygon.is(),
|
||||
"CanvasHelper::fillPolyPolygon: polygon is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::SolidBrush aBrush(
|
||||
tools::sequenceToArgb(renderState.DeviceColor));
|
||||
|
||||
GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
|
||||
|
||||
// TODO(F1): FillRule
|
||||
ENSURE_OR_THROW( Gdiplus::Ok == pGraphics->FillPath( &aBrush, pPath.get() ),
|
||||
"CanvasHelper::fillPolyPolygon(): GDI+ call failed " );
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
|
||||
const rendering::ViewState& /*viewState*/,
|
||||
const rendering::RenderState& /*renderState*/,
|
||||
const uno::Sequence< rendering::Texture >& /*textures*/,
|
||||
const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/,
|
||||
const rendering::FontRequest& fontRequest,
|
||||
const uno::Sequence< beans::PropertyValue >& extraFontProperties,
|
||||
const geometry::Matrix2D& fontMatrix )
|
||||
{
|
||||
if( needOutput() )
|
||||
{
|
||||
return uno::Reference< rendering::XCanvasFont >(
|
||||
new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCanvasFont >();
|
||||
}
|
||||
|
||||
uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/,
|
||||
const rendering::FontInfo& /*aFilter*/,
|
||||
const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< rendering::FontInfo >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/,
|
||||
const rendering::StringContext& text,
|
||||
const uno::Reference< rendering::XCanvasFont >& xFont,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
sal_Int8 /*textDirection*/ )
|
||||
{
|
||||
ENSURE_OR_THROW( xFont.is(),
|
||||
"CanvasHelper::drawText: font is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
Gdiplus::SolidBrush aBrush(
|
||||
Gdiplus::Color(
|
||||
tools::sequenceToArgb(renderState.DeviceColor)));
|
||||
|
||||
CanvasFont::ImplRef pFont(
|
||||
tools::canvasFontFromXFont(xFont) );
|
||||
|
||||
// Move glyphs up, such that output happens at the font
|
||||
// baseline.
|
||||
Gdiplus::PointF aPoint( 0.0,
|
||||
static_cast<Gdiplus::REAL>(-(pFont->getFont()->GetSize()*
|
||||
pFont->getCellAscent() /
|
||||
pFont->getEmHeight())) );
|
||||
|
||||
// TODO(F1): According to
|
||||
// http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q307208,
|
||||
// we might have to revert to GDI and ExTextOut here,
|
||||
// since GDI+ takes the scalability a little bit too
|
||||
// far...
|
||||
|
||||
// TODO(F2): Proper layout (BiDi, CTL)! IMHO must use
|
||||
// DrawDriverString here, and perform layouting myself...
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->DrawString( o3tl::toW(text.Text.copy( text.StartPosition,
|
||||
text.Length ).getStr()),
|
||||
text.Length,
|
||||
pFont->getFont().get(),
|
||||
aPoint,
|
||||
&aBrush ),
|
||||
"CanvasHelper::drawText(): GDI+ call failed" );
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XTextLayout >& xLayoutetText,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xLayoutetText.is(),
|
||||
"CanvasHelper::drawTextLayout: layout is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
TextLayout* pTextLayout =
|
||||
dynamic_cast< TextLayout* >( xLayoutetText.get() );
|
||||
|
||||
ENSURE_OR_THROW( pTextLayout,
|
||||
"CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
|
||||
|
||||
pTextLayout->draw( mpGraphicsProvider->getGraphics(),
|
||||
viewState,
|
||||
renderState,
|
||||
maOutputOffset,
|
||||
mpDevice,
|
||||
false );
|
||||
}
|
||||
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XBitmap >& xBitmap,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xBitmap.is(),
|
||||
"CanvasHelper::drawBitmap: bitmap is NULL");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
// check whether one of our own objects - need to retrieve
|
||||
// bitmap _before_ calling
|
||||
// GraphicsProvider::getGraphics(), to avoid locking our
|
||||
// own surface.
|
||||
BitmapSharedPtr pGdiBitmap;
|
||||
BitmapProvider* pBitmap = dynamic_cast< BitmapProvider* >(xBitmap.get());
|
||||
if( pBitmap )
|
||||
{
|
||||
IBitmapSharedPtr pDXBitmap( pBitmap->getBitmap() );
|
||||
if( pDXBitmap )
|
||||
pGdiBitmap = pDXBitmap->getBitmap();
|
||||
}
|
||||
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
if( pGdiBitmap )
|
||||
tools::drawGdiPlusBitmap(pGraphics,pGdiBitmap);
|
||||
else
|
||||
tools::drawVCLBitmapFromXBitmap(pGraphics,
|
||||
xBitmap);
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
|
||||
const uno::Reference< rendering::XBitmap >& xBitmap,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( xBitmap.is(),
|
||||
"CanvasHelper::drawBitmap: bitmap is NULL");
|
||||
|
||||
// no color set -> this is equivalent to a plain drawBitmap(), then
|
||||
if( renderState.DeviceColor.getLength() < 3 )
|
||||
return drawBitmap( pCanvas, xBitmap, viewState, renderState );
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
BitmapSharedPtr pBitmap( tools::bitmapFromXBitmap( xBitmap ) );
|
||||
Gdiplus::Rect aRect( 0, 0,
|
||||
pBitmap->GetWidth(),
|
||||
pBitmap->GetHeight() );
|
||||
|
||||
// Setup an ImageAttributes with an alpha-modulating
|
||||
// color matrix.
|
||||
rendering::ARGBColor aARGBColor(
|
||||
mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0]);
|
||||
|
||||
Gdiplus::ImageAttributes aImgAttr;
|
||||
tools::setModulateImageAttributes( aImgAttr,
|
||||
aARGBColor.Red,
|
||||
aARGBColor.Green,
|
||||
aARGBColor.Blue,
|
||||
aARGBColor.Alpha );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == pGraphics->DrawImage( pBitmap.get(),
|
||||
aRect,
|
||||
0, 0,
|
||||
pBitmap->GetWidth(),
|
||||
pBitmap->GetHeight(),
|
||||
Gdiplus::UnitPixel,
|
||||
&aImgAttr ),
|
||||
"CanvasHelper::drawBitmapModulated(): GDI+ call failed" );
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
|
||||
{
|
||||
return uno::Reference< rendering::XGraphicDevice >(mpDevice);
|
||||
}
|
||||
|
||||
// private helper
|
||||
|
||||
|
||||
Gdiplus::CompositingMode CanvasHelper::calcCompositingMode( sal_Int8 nMode )
|
||||
{
|
||||
Gdiplus::CompositingMode aRet( Gdiplus::CompositingModeSourceOver );
|
||||
|
||||
switch( nMode )
|
||||
{
|
||||
case rendering::CompositeOperation::OVER:
|
||||
case rendering::CompositeOperation::CLEAR:
|
||||
aRet = Gdiplus::CompositingModeSourceOver;
|
||||
break;
|
||||
|
||||
case rendering::CompositeOperation::SOURCE:
|
||||
aRet = Gdiplus::CompositingModeSourceCopy;
|
||||
break;
|
||||
|
||||
case rendering::CompositeOperation::DESTINATION:
|
||||
case rendering::CompositeOperation::UNDER:
|
||||
case rendering::CompositeOperation::INSIDE:
|
||||
case rendering::CompositeOperation::INSIDE_REVERSE:
|
||||
case rendering::CompositeOperation::OUTSIDE:
|
||||
case rendering::CompositeOperation::OUTSIDE_REVERSE:
|
||||
case rendering::CompositeOperation::ATOP:
|
||||
case rendering::CompositeOperation::ATOP_REVERSE:
|
||||
case rendering::CompositeOperation::XOR:
|
||||
case rendering::CompositeOperation::ADD:
|
||||
case rendering::CompositeOperation::SATURATE:
|
||||
// TODO(F2): Problem, because GDI+ only knows about two compositing modes
|
||||
aRet = Gdiplus::CompositingModeSourceOver;
|
||||
break;
|
||||
|
||||
default:
|
||||
ENSURE_OR_THROW( false, "CanvasHelper::calcCompositingMode: unexpected mode" );
|
||||
break;
|
||||
}
|
||||
|
||||
return aRet;
|
||||
}
|
||||
|
||||
void CanvasHelper::setupGraphicsState( GraphicsSharedPtr const & rGraphics,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState )
|
||||
{
|
||||
ENSURE_OR_THROW( needOutput(),
|
||||
"CanvasHelper::setupGraphicsState: primary graphics invalid" );
|
||||
ENSURE_OR_THROW( mpDevice,
|
||||
"CanvasHelper::setupGraphicsState: reference device invalid" );
|
||||
|
||||
// setup view transform first. Clipping e.g. depends on it
|
||||
::basegfx::B2DHomMatrix aTransform = ::canvas::tools::getViewStateTransform(viewState);
|
||||
|
||||
// add output offset
|
||||
if( !maOutputOffset.equalZero() )
|
||||
{
|
||||
const basegfx::B2DHomMatrix aOutputOffset(basegfx::utils::createTranslateB2DHomMatrix(
|
||||
maOutputOffset.getWidth(), maOutputOffset.getHeight()));
|
||||
aTransform = aOutputOffset * aTransform;
|
||||
}
|
||||
|
||||
Gdiplus::Matrix aMatrix;
|
||||
tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
|
||||
"CanvasHelper::setupGraphicsState(): Failed to set GDI+ transformation" );
|
||||
|
||||
// setup view and render state clipping
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->ResetClip(),
|
||||
"CanvasHelper::setupGraphicsState(): Failed to reset GDI+ clip" );
|
||||
|
||||
if( viewState.Clip.is() )
|
||||
{
|
||||
GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( viewState.Clip ) );
|
||||
|
||||
// TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
|
||||
// Try SetClip( Rect ) or similar for simple clip paths (need some support in
|
||||
// LinePolyPolygon, then)
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
|
||||
Gdiplus::CombineModeIntersect ),
|
||||
"CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
|
||||
}
|
||||
|
||||
// setup overall transform only now. View clip above was relative to
|
||||
// view transform
|
||||
::canvas::tools::mergeViewAndRenderTransform(aTransform,
|
||||
viewState,
|
||||
renderState);
|
||||
|
||||
// add output offset
|
||||
if( !maOutputOffset.equalZero() )
|
||||
{
|
||||
const basegfx::B2DHomMatrix aOutputOffset(basegfx::utils::createTranslateB2DHomMatrix(
|
||||
maOutputOffset.getWidth(), maOutputOffset.getHeight()));
|
||||
aTransform = aOutputOffset * aTransform;
|
||||
}
|
||||
|
||||
tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
|
||||
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
|
||||
"CanvasHelper::setupGraphicsState(): Cannot set GDI+ transformation" );
|
||||
|
||||
if( renderState.Clip.is() )
|
||||
{
|
||||
GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( renderState.Clip ) );
|
||||
|
||||
// TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
|
||||
// Try SetClip( Rect ) or similar for simple clip paths (need some support in
|
||||
// LinePolyPolygon, then)
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
|
||||
Gdiplus::CombineModeIntersect ),
|
||||
"CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
|
||||
}
|
||||
|
||||
// setup compositing
|
||||
const Gdiplus::CompositingMode eCompositing( calcCompositingMode( renderState.CompositeOperation ) );
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ),
|
||||
"CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" );
|
||||
}
|
||||
|
||||
void CanvasHelper::flush() const
|
||||
{
|
||||
if( needOutput() )
|
||||
mpGraphicsProvider->getGraphics()->Flush( Gdiplus::FlushIntentionSync );
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,252 @@
|
||||
/* -*- 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/rendering/XCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XBitmapCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <basegfx/vector/b2dsize.hxx>
|
||||
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Helper class for basic canvas functionality. Also offers
|
||||
optional backbuffer painting, when providing it with a second
|
||||
HDC to render into.
|
||||
*/
|
||||
class CanvasHelper
|
||||
{
|
||||
public:
|
||||
CanvasHelper();
|
||||
|
||||
/// make noncopyable
|
||||
CanvasHelper(const CanvasHelper&) = delete;
|
||||
const CanvasHelper& operator=(const CanvasHelper&) = delete;
|
||||
|
||||
/// Release all references
|
||||
void disposing();
|
||||
|
||||
/** Initialize canvas helper
|
||||
|
||||
This method late-initializes the canvas helper, providing
|
||||
it with the necessary device and output objects. Note that
|
||||
the CanvasHelper does <em>not</em> take ownership of the
|
||||
passed rDevice reference, nor does it perform any
|
||||
reference counting. Thus, to prevent the reference counted
|
||||
SpriteCanvas object from deletion, the user of this class
|
||||
is responsible for holding ref-counted references itself!
|
||||
|
||||
@param rDevice
|
||||
Reference device this canvas is associated with
|
||||
|
||||
*/
|
||||
void setDevice( css::rendering::XGraphicDevice& rDevice );
|
||||
|
||||
/** Set the target for rendering operations
|
||||
|
||||
@param rTarget
|
||||
Render target
|
||||
*/
|
||||
void setTarget( const GraphicsProviderSharedPtr& rTarget );
|
||||
|
||||
/** Set the target for rendering operations
|
||||
|
||||
@param rTarget
|
||||
Render target
|
||||
|
||||
@param rOutputOffset
|
||||
Output offset in pixel
|
||||
*/
|
||||
void setTarget( const GraphicsProviderSharedPtr& rTarget,
|
||||
const ::basegfx::B2ISize& rOutputOffset );
|
||||
|
||||
|
||||
// CanvasHelper functionality
|
||||
// ==========================
|
||||
|
||||
// XCanvas (only providing, not implementing the
|
||||
// interface. Also note subtle method parameter differences)
|
||||
void clear();
|
||||
void drawPoint( const css::rendering::XCanvas* pCanvas,
|
||||
const css::geometry::RealPoint2D& aPoint,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
void drawLine( const css::rendering::XCanvas* pCanvas,
|
||||
const css::geometry::RealPoint2D& aStartPoint,
|
||||
const css::geometry::RealPoint2D& aEndPoint,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
void drawBezier( const css::rendering::XCanvas* pCanvas,
|
||||
const css::geometry::RealBezierSegment2D& aBezierSegment,
|
||||
const css::geometry::RealPoint2D& aEndPoint,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokePolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokeTexturedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence<
|
||||
css::rendering::Texture >& textures,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
strokeTextureMappedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence<
|
||||
css::rendering::Texture >& textures,
|
||||
const css::uno::Reference<
|
||||
css::geometry::XMapping2D >& xMapping,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XPolyPolygon2D >
|
||||
queryStrokeShapes( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::rendering::StrokeAttributes& strokeAttributes );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillTexturedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence<
|
||||
css::rendering::Texture >& textures );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
fillTextureMappedPolyPolygon( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
const css::uno::Sequence<
|
||||
css::rendering::Texture >& textures,
|
||||
const css::uno::Reference<
|
||||
css::geometry::XMapping2D >& xMapping );
|
||||
|
||||
css::uno::Reference< css::rendering::XCanvasFont >
|
||||
createFont( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::FontRequest& fontRequest,
|
||||
const css::uno::Sequence<
|
||||
css::beans::PropertyValue >& extraFontProperties,
|
||||
const css::geometry::Matrix2D& fontMatrix );
|
||||
|
||||
css::uno::Sequence< css::rendering::FontInfo >
|
||||
queryAvailableFonts( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::FontInfo& aFilter,
|
||||
const css::uno::Sequence<
|
||||
css::beans::PropertyValue >& aFontProperties );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawText( const css::rendering::XCanvas* pCanvas,
|
||||
const css::rendering::StringContext& text,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XCanvasFont >& xFont,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState,
|
||||
sal_Int8 textDirection );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawTextLayout( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XTextLayout >& laidOutText,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawBitmap( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XBitmap >& xBitmap,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XCachedPrimitive >
|
||||
drawBitmapModulated( const css::rendering::XCanvas* pCanvas,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XBitmap >& xBitmap,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
css::uno::Reference< css::rendering::XGraphicDevice >
|
||||
getDevice();
|
||||
|
||||
// Flush drawing queue to screen
|
||||
void flush() const;
|
||||
|
||||
/** Called from XCanvas base classes, to notify that content
|
||||
is _about_ to change
|
||||
*/
|
||||
void modifying() {}
|
||||
|
||||
protected:
|
||||
/// Refcounted global GDI+ state container
|
||||
GDIPlusUserSharedPtr mpGdiPlusUser;
|
||||
|
||||
/** Phyical output device
|
||||
|
||||
Deliberately not a refcounted reference, because of
|
||||
potential circular references for spritecanvas.
|
||||
*/
|
||||
css::rendering::XGraphicDevice* mpDevice;
|
||||
|
||||
/// Provides the Gdiplus::Graphics to render into
|
||||
GraphicsProviderSharedPtr mpGraphicsProvider;
|
||||
|
||||
bool needOutput() const { return bool(mpGraphicsProvider); };
|
||||
|
||||
// returns transparency of color
|
||||
void setupGraphicsState( GraphicsSharedPtr const & rGraphics,
|
||||
const css::rendering::ViewState& viewState,
|
||||
const css::rendering::RenderState& renderState );
|
||||
|
||||
Gdiplus::CompositingMode calcCompositingMode( sal_Int8 nMode );
|
||||
|
||||
/// Current (transformation-independent) output buffer offset
|
||||
::basegfx::B2ISize maOutputOffset;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,608 @@
|
||||
/* -*- 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 <cstdlib>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/polygon/b2dpolygontools.hxx>
|
||||
#include <basegfx/range/b2drectangle.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <basegfx/utils/keystoplerp.hxx>
|
||||
#include <basegfx/utils/lerp.hxx>
|
||||
#include <basegfx/utils/tools.hxx>
|
||||
#include <com/sun/star/rendering/TexturingMode.hpp>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <parametricpolypolygon.hxx>
|
||||
|
||||
#include "dx_canvashelper.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
typedef std::shared_ptr< Gdiplus::PathGradientBrush > PathGradientBrushSharedPtr;
|
||||
|
||||
bool fillLinearGradient( GraphicsSharedPtr const & rGraphics,
|
||||
const ::canvas::ParametricPolyPolygon::Values& /*rValues*/,
|
||||
const std::vector< Gdiplus::Color >& rColors,
|
||||
const std::vector< Gdiplus::REAL >& rStops,
|
||||
const GraphicsPathSharedPtr& rFillPath,
|
||||
const rendering::Texture& texture )
|
||||
{
|
||||
// setup a linear gradient with given colors
|
||||
|
||||
|
||||
Gdiplus::LinearGradientBrush aBrush(
|
||||
Gdiplus::PointF(0.0f,
|
||||
0.5f),
|
||||
Gdiplus::PointF(1.0f,
|
||||
0.5f),
|
||||
rColors[0],
|
||||
rColors[1] );
|
||||
|
||||
aBrush.SetInterpolationColors(rColors.data(),
|
||||
rStops.data(),
|
||||
rColors.size());
|
||||
|
||||
// render background color, as LinearGradientBrush does not
|
||||
// properly support the WrapModeClamp repeat mode
|
||||
Gdiplus::SolidBrush aBackgroundBrush( rColors[0] );
|
||||
rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() );
|
||||
|
||||
// TODO(F2): This does not yet support other repeat modes
|
||||
// except clamp, and probably also no multi-texturing
|
||||
|
||||
// calculate parallelogram of gradient in object space, extend
|
||||
// top and bottom of it such that they cover the whole fill
|
||||
// path bound area
|
||||
::basegfx::B2DHomMatrix aTextureTransform;
|
||||
::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
|
||||
texture.AffineTransform );
|
||||
|
||||
::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
|
||||
::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
|
||||
::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
|
||||
::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
|
||||
|
||||
aLeftTop *= aTextureTransform;
|
||||
aLeftBottom *= aTextureTransform;
|
||||
aRightTop *= aTextureTransform;
|
||||
aRightBottom*= aTextureTransform;
|
||||
|
||||
Gdiplus::RectF aBounds;
|
||||
rFillPath->GetBounds( &aBounds );
|
||||
|
||||
// now, we potentially have to enlarge our gradient area
|
||||
// atop and below the transformed [0,1]x[0,1] unit rect,
|
||||
// for the gradient to fill the complete bound rect.
|
||||
::basegfx::utils::infiniteLineFromParallelogram( aLeftTop,
|
||||
aLeftBottom,
|
||||
aRightTop,
|
||||
aRightBottom,
|
||||
tools::b2dRangeFromGdiPlusRectF( aBounds ) );
|
||||
|
||||
// calc length of bound rect diagonal
|
||||
const double nDiagonalLength(
|
||||
hypot( aBounds.Width,
|
||||
aBounds.Height ) );
|
||||
|
||||
// generate a path which covers the 'right' side of the
|
||||
// gradient, extending two times the bound rect diagonal to
|
||||
// the right (and thus covering the whole half plane 'right'
|
||||
// of the gradient). Take the middle of the gradient as the
|
||||
// 'left' side of the polygon, to not fall victim to rounding
|
||||
// errors at the edge.
|
||||
::basegfx::B2DVector aDirection( aLeftTop - aLeftBottom );
|
||||
aDirection = ::basegfx::getNormalizedPerpendicular( aDirection );
|
||||
aDirection *= nDiagonalLength;
|
||||
|
||||
const ::basegfx::B2DPoint aHalfPlaneLeftTop( (aLeftTop + aRightTop) * 0.5 );
|
||||
const ::basegfx::B2DPoint aHalfPlaneLeftBottom( (aLeftBottom + aRightBottom) * 0.5 );
|
||||
const ::basegfx::B2DPoint aHalfPlaneRightTop( aRightTop + aDirection );
|
||||
const ::basegfx::B2DPoint aHalfPlaneRightBottom( aRightBottom + aDirection );
|
||||
|
||||
Gdiplus::GraphicsPath aSolidFillPath;
|
||||
aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getX()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getY()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getX()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getY()) );
|
||||
aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getX()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getY()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getX()),
|
||||
static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getY()) );
|
||||
aSolidFillPath.CloseFigure();
|
||||
|
||||
// limit output to fill path, we've just generated a path that
|
||||
// might be substantially larger
|
||||
if( Gdiplus::Ok != rGraphics->SetClip( rFillPath.get(),
|
||||
Gdiplus::CombineModeIntersect ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Gdiplus::SolidBrush aBackgroundBrush2( rColors.back() );
|
||||
rGraphics->FillPath( &aBackgroundBrush2, &aSolidFillPath );
|
||||
|
||||
// generate clip polygon from the extended parallelogram
|
||||
// (exploit the feature that distinct lines in a figure are
|
||||
// automatically closed by a straight line)
|
||||
Gdiplus::GraphicsPath aClipPath;
|
||||
aClipPath.AddLine( static_cast<Gdiplus::REAL>(aLeftTop.getX()),
|
||||
static_cast<Gdiplus::REAL>(aLeftTop.getY()),
|
||||
static_cast<Gdiplus::REAL>(aRightTop.getX()),
|
||||
static_cast<Gdiplus::REAL>(aRightTop.getY()) );
|
||||
aClipPath.AddLine( static_cast<Gdiplus::REAL>(aRightBottom.getX()),
|
||||
static_cast<Gdiplus::REAL>(aRightBottom.getY()),
|
||||
static_cast<Gdiplus::REAL>(aLeftBottom.getX()),
|
||||
static_cast<Gdiplus::REAL>(aLeftBottom.getY()) );
|
||||
aClipPath.CloseFigure();
|
||||
|
||||
// limit output to a _single_ strip of the gradient (have to
|
||||
// clip here, since GDI+ wrapmode clamp does not work here)
|
||||
if( Gdiplus::Ok != rGraphics->SetClip( &aClipPath,
|
||||
Gdiplus::CombineModeIntersect ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// now, finally, output the gradient
|
||||
Gdiplus::Matrix aMatrix;
|
||||
tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
|
||||
texture.AffineTransform );
|
||||
aBrush.SetTransform( &aMatrix );
|
||||
|
||||
rGraphics->FillRectangle( &aBrush, aBounds );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int numColorSteps( const Gdiplus::Color& rColor1, const Gdiplus::Color& rColor2 )
|
||||
{
|
||||
return std::max(
|
||||
std::abs( rColor1.GetRed() - rColor2.GetRed() ),
|
||||
std::max(
|
||||
std::abs( rColor1.GetGreen() - rColor2.GetGreen() ),
|
||||
std::abs( rColor1.GetBlue() - rColor2.GetBlue() ) ) );
|
||||
}
|
||||
|
||||
bool fillPolygonalGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||
const std::vector< Gdiplus::Color >& rColors,
|
||||
const std::vector< Gdiplus::REAL >& rStops,
|
||||
GraphicsSharedPtr const & rGraphics,
|
||||
const GraphicsPathSharedPtr& rPath,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
const rendering::Texture& texture )
|
||||
{
|
||||
// copy original fill path object, might have to change it
|
||||
// below
|
||||
GraphicsPathSharedPtr pFillPath( rPath );
|
||||
const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
|
||||
|
||||
PathGradientBrushSharedPtr pGradientBrush;
|
||||
|
||||
// fill background uniformly with end color
|
||||
Gdiplus::SolidBrush aBackgroundBrush( rColors[0] );
|
||||
rGraphics->FillPath( &aBackgroundBrush, pFillPath.get() );
|
||||
|
||||
Gdiplus::Matrix aMatrix;
|
||||
// scale focus according to aspect ratio: for wider-than-tall
|
||||
// bounds (nAspectRatio > 1.0), the focus must have non-zero
|
||||
// width. Specifically, a bound rect twice as wide as tall has
|
||||
// a focus of half its width.
|
||||
if( !::rtl::math::approxEqual(rValues.mnAspectRatio,
|
||||
1.0) )
|
||||
{
|
||||
// KLUDGE 1:
|
||||
|
||||
// And here comes the greatest shortcoming of the GDI+
|
||||
// gradients ever: SetFocusScales completely ignores
|
||||
// transformations, both when set at the PathGradientBrush
|
||||
// and for the world coordinate system. Thus, to correctly
|
||||
// display anisotrophic path gradients, we have to render
|
||||
// them by hand. WTF.
|
||||
|
||||
// TODO(F2): This does not yet support other repeat modes
|
||||
// except clamp, and probably also no multi-texturing
|
||||
|
||||
// limit output to to-be-filled polygon
|
||||
if( Gdiplus::Ok != rGraphics->SetClip( pFillPath.get(),
|
||||
Gdiplus::CombineModeIntersect ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// disable anti-aliasing, if any
|
||||
const Gdiplus::SmoothingMode eOldAAMode( rGraphics->GetSmoothingMode() );
|
||||
rGraphics->SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed );
|
||||
|
||||
|
||||
// determine number of steps to use
|
||||
|
||||
|
||||
// TODO(Q2): Unify step calculations with VCL canvas
|
||||
int nColorSteps = 0;
|
||||
for( size_t i=0; i<rColors.size()-1; ++i )
|
||||
nColorSteps += numColorSteps(rColors[i],rColors[i+1]);
|
||||
::basegfx::B2DHomMatrix aTotalTransform;
|
||||
const int nStepCount=
|
||||
::canvas::tools::calcGradientStepCount(aTotalTransform,
|
||||
viewState,
|
||||
renderState,
|
||||
texture,
|
||||
nColorSteps);
|
||||
|
||||
::basegfx::B2DHomMatrix aTextureTransform;
|
||||
::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
|
||||
texture.AffineTransform );
|
||||
// determine overall transformation for inner polygon (might
|
||||
// have to be prefixed by anisotrophic scaling)
|
||||
::basegfx::B2DHomMatrix aInnerPolygonTransformMatrix;
|
||||
|
||||
// For performance reasons, we create a temporary VCL polygon
|
||||
// here, keep it all the way and only change the vertex values
|
||||
// in the loop below (as ::Polygon is a pimpl class, creating
|
||||
// one every loop turn would really stress the mem allocator)
|
||||
::basegfx::B2DPolygon aOuterPoly( rGradientPoly );
|
||||
::basegfx::B2DPolygon aInnerPoly;
|
||||
|
||||
// subdivide polygon _before_ rendering, would otherwise have
|
||||
// to be performed on every loop turn.
|
||||
if( aOuterPoly.areControlPointsUsed() )
|
||||
aOuterPoly = ::basegfx::utils::adaptiveSubdivideByAngle(aOuterPoly);
|
||||
|
||||
aInnerPoly = aOuterPoly;
|
||||
aOuterPoly.transform(aTextureTransform);
|
||||
|
||||
|
||||
// apply scaling (possibly anisotrophic) to inner polygon
|
||||
|
||||
|
||||
// scale inner polygon according to aspect ratio: for
|
||||
// wider-than-tall bounds (nAspectRatio > 1.0), the inner
|
||||
// polygon, representing the gradient focus, must have
|
||||
// non-zero width. Specifically, a bound rect twice as wide as
|
||||
// tall has a focus polygon of half its width.
|
||||
const double nAspectRatio( rValues.mnAspectRatio );
|
||||
if( nAspectRatio > 1.0 )
|
||||
{
|
||||
// width > height case
|
||||
aInnerPolygonTransformMatrix.scale( 1.0 - 1.0/nAspectRatio,
|
||||
0.0 );
|
||||
}
|
||||
else if( nAspectRatio < 1.0 )
|
||||
{
|
||||
// width < height case
|
||||
aInnerPolygonTransformMatrix.scale( 0.0,
|
||||
1.0 - nAspectRatio );
|
||||
}
|
||||
else
|
||||
{
|
||||
// isotrophic case
|
||||
aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
|
||||
}
|
||||
|
||||
// and finally, add texture transform to it.
|
||||
aInnerPolygonTransformMatrix *= aTextureTransform;
|
||||
|
||||
// apply final matrix to polygon
|
||||
aInnerPoly.transform( aInnerPolygonTransformMatrix );
|
||||
|
||||
Gdiplus::GraphicsPath aCurrPath;
|
||||
Gdiplus::SolidBrush aFillBrush( rColors[0] );
|
||||
const sal_uInt32 nNumPoints( aOuterPoly.count() );
|
||||
basegfx::utils::KeyStopLerp aLerper(rValues.maStops);
|
||||
for( int i=1; i<nStepCount; ++i )
|
||||
{
|
||||
std::ptrdiff_t nIndex;
|
||||
double fAlpha;
|
||||
const double fT( i/double(nStepCount) );
|
||||
std::tie(nIndex,fAlpha)=aLerper.lerp(fT);
|
||||
|
||||
const Gdiplus::Color aFillColor(
|
||||
static_cast<BYTE>( basegfx::utils::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha) ),
|
||||
static_cast<BYTE>( basegfx::utils::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha) ),
|
||||
static_cast<BYTE>( basegfx::utils::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha) ) );
|
||||
|
||||
aFillBrush.SetColor( aFillColor );
|
||||
aCurrPath.Reset(); aCurrPath.StartFigure();
|
||||
for( unsigned int p=1; p<nNumPoints; ++p )
|
||||
{
|
||||
const ::basegfx::B2DPoint& rOuterPoint1( aOuterPoly.getB2DPoint(p-1) );
|
||||
const ::basegfx::B2DPoint& rInnerPoint1( aInnerPoly.getB2DPoint(p-1) );
|
||||
const ::basegfx::B2DPoint& rOuterPoint2( aOuterPoly.getB2DPoint(p) );
|
||||
const ::basegfx::B2DPoint& rInnerPoint2( aInnerPoly.getB2DPoint(p) );
|
||||
|
||||
aCurrPath.AddLine(
|
||||
Gdiplus::REAL(fT*rInnerPoint1.getX() + (1-fT)*rOuterPoint1.getX()),
|
||||
Gdiplus::REAL(fT*rInnerPoint1.getY() + (1-fT)*rOuterPoint1.getY()),
|
||||
Gdiplus::REAL(fT*rInnerPoint2.getX() + (1-fT)*rOuterPoint2.getX()),
|
||||
Gdiplus::REAL(fT*rInnerPoint2.getY() + (1-fT)*rOuterPoint2.getY()));
|
||||
}
|
||||
aCurrPath.CloseFigure();
|
||||
|
||||
rGraphics->FillPath( &aFillBrush, &aCurrPath );
|
||||
}
|
||||
|
||||
// reset to old anti-alias mode
|
||||
rGraphics->SetSmoothingMode( eOldAAMode );
|
||||
}
|
||||
else
|
||||
{
|
||||
// KLUDGE 2:
|
||||
|
||||
// We're generating a PathGradientBrush from scratch here,
|
||||
// and put in a transformed GraphicsPath (transformed with
|
||||
// the texture transform). This is because the
|
||||
// straight-forward approach to store a Brush pointer at
|
||||
// this class and set a texture transform via
|
||||
// PathGradientBrush::SetTransform() is spoiled by MS: it
|
||||
// seems that _either_ the texture transform, _or_ the
|
||||
// transform at the Graphics can be set, but not both. If
|
||||
// one sets both, only the translational components of the
|
||||
// texture is respected.
|
||||
|
||||
tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
|
||||
texture.AffineTransform );
|
||||
GraphicsPathSharedPtr pGradientPath(
|
||||
tools::graphicsPathFromB2DPolygon( rValues.maGradientPoly ));
|
||||
pGradientPath->Transform( &aMatrix );
|
||||
|
||||
pGradientBrush
|
||||
= std::make_shared<Gdiplus::PathGradientBrush>( pGradientPath.get() );
|
||||
pGradientBrush->SetInterpolationColors( rColors.data(),
|
||||
rStops.data(),
|
||||
rStops.size() );
|
||||
|
||||
// explicitly setup center point. Since the center of GDI+
|
||||
// gradients are by default the _centroid_ of the path
|
||||
// (i.e. the weighted sum of edge points), it will not
|
||||
// necessarily coincide with our notion of center.
|
||||
Gdiplus::PointF aCenterPoint(0, 0);
|
||||
aMatrix.TransformPoints( &aCenterPoint );
|
||||
pGradientBrush->SetCenterPoint( aCenterPoint );
|
||||
|
||||
const bool bTileX( texture.RepeatModeX != rendering::TexturingMode::CLAMP );
|
||||
const bool bTileY( texture.RepeatModeY != rendering::TexturingMode::CLAMP );
|
||||
|
||||
if( bTileX && bTileY )
|
||||
pGradientBrush->SetWrapMode( Gdiplus::WrapModeTile );
|
||||
else
|
||||
{
|
||||
OSL_ENSURE( bTileY == bTileX,
|
||||
"ParametricPolyPolygon::fillPolygonalGradient(): Cannot have repeat x and repeat y differ!" );
|
||||
|
||||
pGradientBrush->SetWrapMode( Gdiplus::WrapModeClamp );
|
||||
}
|
||||
|
||||
// render actual gradient
|
||||
rGraphics->FillPath( pGradientBrush.get(), pFillPath.get() );
|
||||
}
|
||||
|
||||
#if OSL_DEBUG_LEVEL > 0
|
||||
Gdiplus::Pen aPen( Gdiplus::Color( 255, 255, 0, 0 ),
|
||||
0.0001f );
|
||||
|
||||
rGraphics->DrawRectangle( &aPen,
|
||||
Gdiplus::RectF( 0.0f, 0.0f,
|
||||
1.0f, 1.0f ) );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fillGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||
const std::vector< Gdiplus::Color >& rColors,
|
||||
const std::vector< Gdiplus::REAL >& rStops,
|
||||
GraphicsSharedPtr const & rGraphics,
|
||||
const GraphicsPathSharedPtr& rPath,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
const rendering::Texture& texture )
|
||||
{
|
||||
switch( rValues.meType )
|
||||
{
|
||||
case ::canvas::ParametricPolyPolygon::GradientType::Linear:
|
||||
fillLinearGradient( rGraphics,
|
||||
rValues,
|
||||
rColors,
|
||||
rStops,
|
||||
rPath,
|
||||
texture );
|
||||
break;
|
||||
|
||||
case ::canvas::ParametricPolyPolygon::GradientType::Elliptical:
|
||||
case ::canvas::ParametricPolyPolygon::GradientType::Rectangular:
|
||||
fillPolygonalGradient( rValues,
|
||||
rColors,
|
||||
rStops,
|
||||
rGraphics,
|
||||
rPath,
|
||||
viewState,
|
||||
renderState,
|
||||
texture );
|
||||
break;
|
||||
|
||||
default:
|
||||
ENSURE_OR_THROW( false,
|
||||
"CanvasHelper::fillGradient(): Unexpected case" );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fillBitmap( const uno::Reference< rendering::XBitmap >& xBitmap,
|
||||
GraphicsSharedPtr const & rGraphics,
|
||||
const GraphicsPathSharedPtr& rPath,
|
||||
const rendering::Texture& rTexture )
|
||||
{
|
||||
OSL_ENSURE( rTexture.RepeatModeX ==
|
||||
rTexture.RepeatModeY,
|
||||
"CanvasHelper::fillBitmap(): GDI+ cannot handle differing X/Y repeat mode." );
|
||||
|
||||
const bool bClamp( rTexture.RepeatModeX == rendering::TexturingMode::NONE &&
|
||||
rTexture.RepeatModeY == rendering::TexturingMode::NONE );
|
||||
|
||||
const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
|
||||
ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 &&
|
||||
aBmpSize.Height != 0,
|
||||
"CanvasHelper::fillBitmap(): zero-sized texture bitmap" );
|
||||
|
||||
// TODO(P3): Detect case that path is rectangle and
|
||||
// bitmap is just scaled into that. Then, we can
|
||||
// render directly, without generating a temporary
|
||||
// GDI+ bitmap (this is significant, because drawing
|
||||
// layer presents background object bitmap in that
|
||||
// way!)
|
||||
BitmapSharedPtr pBitmap(
|
||||
tools::bitmapFromXBitmap( xBitmap ) );
|
||||
|
||||
TextureBrushSharedPtr pBrush;
|
||||
if( ::rtl::math::approxEqual( rTexture.Alpha,
|
||||
1.0 ) )
|
||||
{
|
||||
pBrush = std::make_shared<Gdiplus::TextureBrush>(
|
||||
pBitmap.get(),
|
||||
bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile );
|
||||
}
|
||||
else
|
||||
{
|
||||
Gdiplus::ImageAttributes aImgAttr;
|
||||
|
||||
tools::setModulateImageAttributes( aImgAttr,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
rTexture.Alpha );
|
||||
|
||||
Gdiplus::Rect aRect(0,0,
|
||||
aBmpSize.Width,
|
||||
aBmpSize.Height);
|
||||
pBrush = std::make_shared<Gdiplus::TextureBrush>(
|
||||
pBitmap.get(),
|
||||
aRect,
|
||||
&aImgAttr );
|
||||
|
||||
pBrush->SetWrapMode(
|
||||
bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile );
|
||||
}
|
||||
|
||||
Gdiplus::Matrix aTextureTransform;
|
||||
tools::gdiPlusMatrixFromAffineMatrix2D( aTextureTransform,
|
||||
rTexture.AffineTransform );
|
||||
|
||||
// scale down bitmap to [0,1]x[0,1] rect, as required
|
||||
// from the XCanvas interface.
|
||||
pBrush->MultiplyTransform( &aTextureTransform );
|
||||
pBrush->ScaleTransform( static_cast< Gdiplus::REAL >(1.0/aBmpSize.Width),
|
||||
static_cast< Gdiplus::REAL >(1.0/aBmpSize.Height) );
|
||||
|
||||
// TODO(F1): FillRule
|
||||
ENSURE_OR_THROW(
|
||||
Gdiplus::Ok == rGraphics->FillPath( pBrush.get(),
|
||||
rPath.get() ),
|
||||
"CanvasHelper::fillTexturedPolyPolygon(): GDI+ call failed" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
|
||||
const rendering::ViewState& viewState,
|
||||
const rendering::RenderState& renderState,
|
||||
const uno::Sequence< rendering::Texture >& textures )
|
||||
{
|
||||
ENSURE_OR_THROW( xPolyPolygon.is(),
|
||||
"CanvasHelper::fillTexturedPolyPolygon: polygon is NULL");
|
||||
ENSURE_OR_THROW( textures.getLength(),
|
||||
"CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
|
||||
|
||||
if( needOutput() )
|
||||
{
|
||||
GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
|
||||
|
||||
setupGraphicsState( pGraphics, viewState, renderState );
|
||||
|
||||
// TODO(F1): Multi-texturing
|
||||
if( textures[0].Gradient.is() )
|
||||
{
|
||||
// try to cast XParametricPolyPolygon2D reference to
|
||||
// our implementation class.
|
||||
::canvas::ParametricPolyPolygon* pGradient =
|
||||
dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
|
||||
|
||||
if( pGradient )
|
||||
{
|
||||
const ::canvas::ParametricPolyPolygon::Values& rValues(
|
||||
pGradient->getValues() );
|
||||
|
||||
OSL_ASSERT(rValues.maColors.getLength() == rValues.maStops.getLength()
|
||||
&& rValues.maColors.getLength() > 1);
|
||||
|
||||
std::vector< Gdiplus::Color > aColors(rValues.maColors.getLength());
|
||||
std::transform(&rValues.maColors[0],
|
||||
&rValues.maColors[0]+rValues.maColors.getLength(),
|
||||
aColors.begin(),
|
||||
[](const uno::Sequence< double >& aDoubleSequence) { return tools::sequenceToArgb(aDoubleSequence); } );
|
||||
std::vector< Gdiplus::REAL > aStops;
|
||||
comphelper::sequenceToContainer(aStops,rValues.maStops);
|
||||
|
||||
// TODO(E1): Return value
|
||||
// TODO(F1): FillRule
|
||||
fillGradient( rValues,
|
||||
aColors,
|
||||
aStops,
|
||||
pGraphics,
|
||||
tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
|
||||
viewState,
|
||||
renderState,
|
||||
textures[0] );
|
||||
}
|
||||
}
|
||||
else if( textures[0].Bitmap.is() )
|
||||
{
|
||||
// TODO(E1): Return value
|
||||
// TODO(F1): FillRule
|
||||
fillBitmap( textures[0].Bitmap,
|
||||
pGraphics,
|
||||
tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
|
||||
textures[0] );
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(P1): Provide caching here.
|
||||
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,152 @@
|
||||
/* -*- 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/vector/b2ivector.hxx>
|
||||
#include <com/sun/star/uno/Any.hxx>
|
||||
#include <com/sun/star/uno/Sequence.hxx>
|
||||
#include <comphelper/anytostring.hxx>
|
||||
#include <cppuhelper/exc_hlp.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include "dx_config.hxx"
|
||||
|
||||
using namespace com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
DXCanvasItem::DXCanvasItem() :
|
||||
ConfigItem(
|
||||
"Office.Canvas/DXCanvas",
|
||||
ConfigItemMode::NONE ),
|
||||
maValues(),
|
||||
maMaxTextureSize(),
|
||||
mbDenylistCurrentDevice(false),
|
||||
mbValuesDirty(false)
|
||||
{
|
||||
try
|
||||
{
|
||||
uno::Sequence< uno::Any > aProps( GetProperties( { "DeviceDenylist" } ));
|
||||
uno::Sequence< sal_Int32 > aValues;
|
||||
|
||||
if (aProps.hasElements() &&
|
||||
(aProps[0] >>= aValues) )
|
||||
{
|
||||
const sal_Int32* pValues = aValues.getConstArray();
|
||||
const sal_Int32 nNumEntries( aValues.getLength()*sizeof(sal_Int32)/sizeof(DeviceInfo) );
|
||||
for( sal_Int32 i=0; i<nNumEntries; ++i )
|
||||
{
|
||||
DeviceInfo aInfo;
|
||||
aInfo.nVendorId = *pValues++;
|
||||
aInfo.nDeviceId = *pValues++;
|
||||
aInfo.nDeviceSubSysId = *pValues++;
|
||||
aInfo.nDeviceRevision = *pValues++;
|
||||
aInfo.nDriverId = *pValues++;
|
||||
aInfo.nDriverVersion = *pValues++;
|
||||
aInfo.nDriverSubVersion = *pValues++;
|
||||
aInfo.nDriverBuildId = *pValues++;
|
||||
maValues.insert(aInfo);
|
||||
}
|
||||
}
|
||||
|
||||
aProps = GetProperties( { "DenylistCurrentDevice" } );
|
||||
if( aProps.getLength() > 0 )
|
||||
aProps[0] >>= mbDenylistCurrentDevice;
|
||||
|
||||
aProps = GetProperties( { "MaxTextureSize" } );
|
||||
if( aProps.getLength() > 0 )
|
||||
maMaxTextureSize = aProps[0].get<sal_Int32>();
|
||||
else
|
||||
maMaxTextureSize.reset();
|
||||
}
|
||||
catch( const uno::Exception& )
|
||||
{
|
||||
TOOLS_WARN_EXCEPTION( "canvas", "" );
|
||||
}
|
||||
}
|
||||
|
||||
DXCanvasItem::~DXCanvasItem()
|
||||
{
|
||||
if( !mbValuesDirty )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
uno::Sequence< sal_Int32 > aValues( sizeof(DeviceInfo)/sizeof(sal_Int32)*maValues.size() );
|
||||
|
||||
sal_Int32* pValues = aValues.getArray();
|
||||
for( const auto& rValueSet : maValues )
|
||||
{
|
||||
const DeviceInfo& rInfo( rValueSet );
|
||||
*pValues++ = rInfo.nVendorId;
|
||||
*pValues++ = rInfo.nDeviceId;
|
||||
*pValues++ = rInfo.nDeviceSubSysId;
|
||||
*pValues++ = rInfo.nDeviceRevision;
|
||||
*pValues++ = rInfo.nDriverId;
|
||||
*pValues++ = rInfo.nDriverVersion;
|
||||
*pValues++ = rInfo.nDriverSubVersion;
|
||||
*pValues++ = rInfo.nDriverBuildId;
|
||||
}
|
||||
|
||||
PutProperties({"DeviceDenylist"}, {css::uno::Any(aValues)});
|
||||
}
|
||||
catch( const uno::Exception& )
|
||||
{
|
||||
TOOLS_WARN_EXCEPTION( "canvas", "" );
|
||||
}
|
||||
}
|
||||
|
||||
void DXCanvasItem::Notify( const css::uno::Sequence<OUString>& ) {}
|
||||
void DXCanvasItem::ImplCommit() {}
|
||||
|
||||
bool DXCanvasItem::isDeviceUsable( const DeviceInfo& rDeviceInfo ) const
|
||||
{
|
||||
return maValues.find(rDeviceInfo) == maValues.end();
|
||||
}
|
||||
|
||||
bool DXCanvasItem::isDenylistCurrentDevice() const
|
||||
{
|
||||
return mbDenylistCurrentDevice;
|
||||
}
|
||||
|
||||
void DXCanvasItem::denylistDevice( const DeviceInfo& rDeviceInfo )
|
||||
{
|
||||
mbValuesDirty = true;
|
||||
maValues.insert(rDeviceInfo);
|
||||
}
|
||||
|
||||
void DXCanvasItem::adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const
|
||||
{
|
||||
if( maMaxTextureSize )
|
||||
{
|
||||
io_maxTextureSize.setX(
|
||||
std::min( *maMaxTextureSize,
|
||||
io_maxTextureSize.getX() ));
|
||||
io_maxTextureSize.setY(
|
||||
std::min( *maMaxTextureSize,
|
||||
io_maxTextureSize.getY() ));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,80 @@
|
||||
/* -*- 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 <unotools/configitem.hxx>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
|
||||
namespace basegfx { class B2IVector; }
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Provide DX canvas config data
|
||||
*/
|
||||
class DXCanvasItem : public ::utl::ConfigItem
|
||||
{
|
||||
public:
|
||||
DXCanvasItem();
|
||||
|
||||
struct DeviceInfo
|
||||
{
|
||||
sal_Int32 nVendorId;
|
||||
sal_Int32 nDeviceId;
|
||||
sal_Int32 nDeviceSubSysId;
|
||||
sal_Int32 nDeviceRevision;
|
||||
|
||||
sal_Int32 nDriverId;
|
||||
sal_Int32 nDriverVersion;
|
||||
sal_Int32 nDriverSubVersion;
|
||||
sal_Int32 nDriverBuildId;
|
||||
|
||||
bool operator<( const DeviceInfo& rRHS ) const
|
||||
{
|
||||
return nVendorId != rRHS.nVendorId ? nVendorId < rRHS.nVendorId :
|
||||
(nDeviceId != rRHS.nDeviceId ? nDeviceId < rRHS.nDeviceId :
|
||||
(nDeviceSubSysId != rRHS.nDeviceSubSysId ? nDeviceSubSysId < rRHS.nDeviceSubSysId :
|
||||
(nDeviceRevision != rRHS.nDeviceRevision ? nDeviceRevision < rRHS.nDeviceRevision :
|
||||
(nDriverId != rRHS.nDriverId ? nDriverId < rRHS.nDriverId :
|
||||
(nDriverVersion != rRHS.nDriverVersion ? nDriverVersion < rRHS.nDriverVersion :
|
||||
(nDriverSubVersion != rRHS.nDriverSubVersion ? nDriverSubVersion < rRHS.nDriverSubVersion :
|
||||
(nDriverBuildId != rRHS.nDriverBuildId && nDriverBuildId < rRHS.nDriverBuildId)))))));
|
||||
}
|
||||
};
|
||||
|
||||
~DXCanvasItem() override;
|
||||
|
||||
bool isDeviceUsable( const DeviceInfo& rDeviceInfo ) const;
|
||||
bool isDenylistCurrentDevice() const;
|
||||
void denylistDevice( const DeviceInfo& rDeviceInfo );
|
||||
void adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const;
|
||||
virtual void Notify( const css::uno::Sequence<OUString>& aPropertyNames) override;
|
||||
|
||||
private:
|
||||
virtual void ImplCommit() override;
|
||||
typedef std::set< DeviceInfo > ValueSet;
|
||||
ValueSet maValues;
|
||||
std::optional<sal_Int32> maMaxTextureSize;
|
||||
bool mbDenylistCurrentDevice;
|
||||
bool mbValuesDirty;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,198 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/lang/NoSupportException.hpp>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <vcl/outdev.hxx>
|
||||
#include <vcl/sysdata.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvasbitmap.hxx"
|
||||
#include "dx_devicehelper.hxx"
|
||||
#include "dx_linepolypolygon.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
DeviceHelper::DeviceHelper() :
|
||||
mpDevice( nullptr ),
|
||||
mnHDC(nullptr),
|
||||
mpOutDev(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceHelper::~DeviceHelper()
|
||||
{
|
||||
}
|
||||
|
||||
void DeviceHelper::init( HDC hdc, OutputDevice* pOutDev,
|
||||
rendering::XGraphicDevice& rDevice )
|
||||
{
|
||||
mnHDC = hdc;
|
||||
mpDevice = &rDevice;
|
||||
mpOutDev = pOutDev;
|
||||
}
|
||||
|
||||
void DeviceHelper::disposing()
|
||||
{
|
||||
// release all references
|
||||
mnHDC = nullptr;
|
||||
mpDevice = nullptr;
|
||||
mpOutDev = nullptr;
|
||||
}
|
||||
|
||||
geometry::RealSize2D DeviceHelper::getPhysicalResolution()
|
||||
{
|
||||
if( !mpDevice )
|
||||
return ::canvas::tools::createInfiniteSize2D(); // we're disposed
|
||||
|
||||
HDC hDC = getHDC();
|
||||
ENSURE_OR_THROW( hDC,
|
||||
"DeviceHelper::getPhysicalResolution(): cannot retrieve HDC from window" );
|
||||
|
||||
const double nHorzRes(GetDeviceCaps(hDC, LOGPIXELSX));
|
||||
const double nVertRes(GetDeviceCaps(hDC, LOGPIXELSY));
|
||||
|
||||
// Converted units are in the denominator in px/in -> px/mm => conversion is inverted
|
||||
return geometry::RealSize2D(o3tl::convert(nHorzRes, o3tl::Length::mm, o3tl::Length::in),
|
||||
o3tl::convert(nVertRes, o3tl::Length::mm, o3tl::Length::in));
|
||||
}
|
||||
|
||||
geometry::RealSize2D DeviceHelper::getPhysicalSize()
|
||||
{
|
||||
if( !mpDevice )
|
||||
return ::canvas::tools::createInfiniteSize2D(); // we're disposed
|
||||
|
||||
HDC hDC=getHDC();
|
||||
ENSURE_OR_THROW( hDC,
|
||||
"DeviceHelper::getPhysicalSize(): cannot retrieve HDC from window" );
|
||||
|
||||
const int nHorzSize( GetDeviceCaps( hDC,
|
||||
HORZSIZE ) );
|
||||
const int nVertSize( GetDeviceCaps( hDC,
|
||||
VERTSIZE ) );
|
||||
|
||||
return geometry::RealSize2D( nHorzSize,
|
||||
nVertSize );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
|
||||
{
|
||||
if( !mpDevice )
|
||||
return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XLinePolyPolygon2D >(
|
||||
new LinePolyPolygon(
|
||||
::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
|
||||
{
|
||||
if( !mpDevice )
|
||||
return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XBezierPolyPolygon2D >(
|
||||
new LinePolyPolygon(
|
||||
::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
if( !mpDevice )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
DXBitmapSharedPtr pBitmap = std::make_shared<DXBitmap>(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
|
||||
false);
|
||||
|
||||
// create a 24bit RGB system memory surface
|
||||
return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
if( !mpDevice )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
DXBitmapSharedPtr pBitmap = std::make_shared<DXBitmap>(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
|
||||
true);
|
||||
|
||||
// create a 32bit ARGB system memory surface
|
||||
return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::isAccelerated() const
|
||||
{
|
||||
return css::uno::Any(false);
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::getDeviceHandle() const
|
||||
{
|
||||
return uno::Any( reinterpret_cast< sal_Int64 >(mpOutDev.get()) );
|
||||
}
|
||||
|
||||
uno::Any DeviceHelper::getSurfaceHandle() const
|
||||
{
|
||||
// TODO(F1): expose DirectDraw object
|
||||
//return mpBackBuffer->getBitmap().get();
|
||||
return uno::Any();
|
||||
}
|
||||
|
||||
uno::Reference<rendering::XColorSpace> DeviceHelper::getColorSpace() const
|
||||
{
|
||||
// always the same
|
||||
static uno::Reference<rendering::XColorSpace> theSpace = vcl::unotools::createStandardColorSpace();
|
||||
return theSpace;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,114 @@
|
||||
/* -*- 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/awt/Rectangle.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||
|
||||
#include "dx_rendermodule.hxx"
|
||||
#include "dx_bitmap.hxx"
|
||||
|
||||
#include <rendering/isurfaceproxymanager.hxx>
|
||||
#include <vcl/vclptr.hxx>
|
||||
|
||||
class OutputDevice;
|
||||
/* Definition of DeviceHelper class */
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class DeviceHelper
|
||||
{
|
||||
public:
|
||||
DeviceHelper();
|
||||
~DeviceHelper();
|
||||
|
||||
/// make noncopyable
|
||||
DeviceHelper(const DeviceHelper&) = delete;
|
||||
const DeviceHelper& operator=(const DeviceHelper&) = delete;
|
||||
|
||||
/** Init the device helper
|
||||
|
||||
@param hdc
|
||||
private or class dc of the output device. is only stored,
|
||||
not release
|
||||
|
||||
@param rDevice
|
||||
Ref back to owning UNO device
|
||||
*/
|
||||
void init( HDC hdc, OutputDevice* pOutputDev,
|
||||
css::rendering::XGraphicDevice& rDevice );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// XWindowGraphicDevice
|
||||
css::geometry::RealSize2D getPhysicalResolution();
|
||||
css::geometry::RealSize2D getPhysicalSize();
|
||||
css::uno::Reference< css::rendering::XLinePolyPolygon2D > createCompatibleLinePolyPolygon(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > >& points );
|
||||
css::uno::Reference< css::rendering::XBezierPolyPolygon2D > createCompatibleBezierPolyPolygon(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > >& points );
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
|
||||
css::uno::Any isAccelerated() const;
|
||||
css::uno::Any getDeviceHandle() const;
|
||||
css::uno::Any getSurfaceHandle() const;
|
||||
css::uno::Reference<
|
||||
css::rendering::XColorSpace > getColorSpace() const;
|
||||
|
||||
/** called when DumpScreenContent property is enabled on
|
||||
XGraphicDevice, and writes out bitmaps of current screen.
|
||||
*/
|
||||
void dumpScreenContent() const {}
|
||||
|
||||
protected:
|
||||
HDC getHDC() const { return mnHDC; }
|
||||
css::rendering::XGraphicDevice* getDevice() const { return mpDevice; }
|
||||
|
||||
private:
|
||||
/** Phyical output device
|
||||
|
||||
Deliberately not a refcounted reference, because of
|
||||
potential circular references for canvas. Needed to
|
||||
create bitmaps
|
||||
*/
|
||||
css::rendering::XGraphicDevice* mpDevice;
|
||||
HDC mnHDC;
|
||||
VclPtr<OutputDevice> mpOutDev;
|
||||
};
|
||||
|
||||
typedef ::rtl::Reference< css::rendering::XGraphicDevice > DeviceRef;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,74 @@
|
||||
/* -*- 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 <osl/mutex.hxx>
|
||||
|
||||
#include "dx_gdiplususer.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
::osl::Mutex* p_gdiPlusUsageCountMutex( osl::Mutex::getGlobalMutex() );
|
||||
int n_gdiPlusUsageCount( 0 );
|
||||
|
||||
ULONG_PTR a_GdiPlusToken; // GDI+ handle. Owned by this object
|
||||
}
|
||||
|
||||
GDIPlusUser::GDIPlusUserSharedPtr GDIPlusUser::createInstance()
|
||||
{
|
||||
return GDIPlusUserSharedPtr( new GDIPlusUser() );
|
||||
}
|
||||
|
||||
GDIPlusUser::~GDIPlusUser()
|
||||
{
|
||||
::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
|
||||
|
||||
--n_gdiPlusUsageCount;
|
||||
|
||||
if( n_gdiPlusUsageCount == 0 )
|
||||
Gdiplus::GdiplusShutdown( a_GdiPlusToken );
|
||||
}
|
||||
|
||||
GDIPlusUser::GDIPlusUser()
|
||||
{
|
||||
::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
|
||||
|
||||
if( n_gdiPlusUsageCount == 0 )
|
||||
{
|
||||
// Setup GDI+
|
||||
|
||||
// No extras here, simply taking GdiplusStartupInput's
|
||||
// default constructor
|
||||
Gdiplus::GdiplusStartupInput gdiPlusStartupInput;
|
||||
|
||||
Gdiplus::GdiplusStartup( &a_GdiPlusToken,
|
||||
&gdiPlusStartupInput,
|
||||
nullptr );
|
||||
}
|
||||
|
||||
++n_gdiPlusUsageCount;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,45 @@
|
||||
/* -*- 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 <sal/config.h>
|
||||
#include <memory>
|
||||
|
||||
/* Definition of GDIPlusUser class */
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class GDIPlusUser
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr< GDIPlusUser > GDIPlusUserSharedPtr;
|
||||
|
||||
static GDIPlusUserSharedPtr createInstance();
|
||||
~GDIPlusUser();
|
||||
|
||||
private:
|
||||
GDIPlusUser(); // create us via factory method
|
||||
};
|
||||
|
||||
typedef GDIPlusUser::GDIPlusUserSharedPtr GDIPlusUserSharedPtr;
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,46 @@
|
||||
/* -*- 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 "dx_winstuff.hxx"
|
||||
#include <memory>
|
||||
|
||||
namespace Gdiplus{ class Graphics; }
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Provider of a Gdiplus::Graphics. Interface
|
||||
*/
|
||||
class GraphicsProvider
|
||||
{
|
||||
public:
|
||||
GraphicsProvider() = default;
|
||||
virtual ~GraphicsProvider() {}
|
||||
/// make noncopyable
|
||||
GraphicsProvider(const GraphicsProvider&) = delete;
|
||||
GraphicsProvider& operator=(const GraphicsProvider&) = delete;
|
||||
|
||||
virtual GraphicsSharedPtr getGraphics() = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< GraphicsProvider > GraphicsProviderSharedPtr;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,62 @@
|
||||
/* -*- 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/rendering/XCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <basegfx/vector/b2ivector.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/range/b2drange.hxx>
|
||||
#include <memory>
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/// Interface for internal canvas bitmap objects
|
||||
struct IBitmap : public GraphicsProvider
|
||||
{
|
||||
virtual BitmapSharedPtr getBitmap() const = 0;
|
||||
virtual ::basegfx::B2ISize getSize() const = 0;
|
||||
virtual bool hasAlpha() const = 0;
|
||||
|
||||
virtual css::uno::Sequence< sal_Int8 > getData(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) = 0;
|
||||
|
||||
virtual void setData(
|
||||
const css::uno::Sequence< sal_Int8 >& data,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) = 0;
|
||||
|
||||
virtual void setPixel(
|
||||
const css::uno::Sequence< sal_Int8 >& color,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) = 0;
|
||||
|
||||
virtual css::uno::Sequence< sal_Int8 > getPixel(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<IBitmap> IBitmapSharedPtr;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,629 @@
|
||||
/* -*- 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 <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/polygon/b2dpolygon.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
||||
#include <basegfx/range/b2drectangle.hxx>
|
||||
#include <basegfx/range/b2irectangle.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
|
||||
#include <com/sun/star/geometry/RealPoint2D.hpp>
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
#include <com/sun/star/lang/XUnoTunnel.hpp>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
#include <verifyinput.hxx>
|
||||
|
||||
#include "dx_canvas.hxx"
|
||||
#include "dx_canvasbitmap.hxx"
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_linepolypolygon.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_vcltools.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
|
||||
namespace dxcanvas::tools
|
||||
{
|
||||
::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
|
||||
{
|
||||
LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
|
||||
|
||||
if( pPolyImpl )
|
||||
{
|
||||
return pPolyImpl->getPolyPolygon();
|
||||
}
|
||||
else
|
||||
{
|
||||
const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );
|
||||
|
||||
// not a known implementation object - try data source
|
||||
// interfaces
|
||||
uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
|
||||
xPoly,
|
||||
uno::UNO_QUERY );
|
||||
|
||||
if( xBezierPoly.is() )
|
||||
{
|
||||
return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
|
||||
xBezierPoly->getBezierSegments( 0,
|
||||
nPolys,
|
||||
0,
|
||||
-1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
|
||||
xPoly,
|
||||
uno::UNO_QUERY );
|
||||
|
||||
// no implementation class and no data provider
|
||||
// found - contract violation.
|
||||
ENSURE_ARG_OR_THROW( xLinePoly.is(),
|
||||
"VCLCanvas::polyPolygonFromXPolyPolygon2D(): Invalid input "
|
||||
"poly-polygon, cannot retrieve vertex data" );
|
||||
|
||||
return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
|
||||
xLinePoly->getPoints( 0,
|
||||
nPolys,
|
||||
0,
|
||||
-1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupGraphics( Gdiplus::Graphics& rGraphics )
|
||||
{
|
||||
// setup graphics with (somewhat arbitrary) defaults
|
||||
//rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighQuality );
|
||||
rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
|
||||
//rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear ); // with prefiltering for shrinks
|
||||
rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );
|
||||
|
||||
// #122683# Switched precedence of pixel offset
|
||||
// mode. Seemingly, polygon stroking needs
|
||||
// PixelOffsetModeNone to achieve visually pleasing
|
||||
// results, whereas all other operations (e.g. polygon
|
||||
// fills, bitmaps) look better with PixelOffsetModeHalf.
|
||||
rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf ); // Pixel center at (0.5, 0.5) etc.
|
||||
//rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
|
||||
|
||||
//rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed ); // no line/curve antialiasing
|
||||
//rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
|
||||
rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
|
||||
//rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
|
||||
rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintSystemDefault );
|
||||
rGraphics.SetPageUnit(Gdiplus::UnitPixel);
|
||||
}
|
||||
|
||||
Gdiplus::Graphics* createGraphicsFromHDC(HDC aHDC)
|
||||
{
|
||||
Gdiplus::Graphics* pRet = new Gdiplus::Graphics(aHDC);
|
||||
setupGraphics( *pRet );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
GraphicsSharedPtr createGraphicsFromBitmap(const BitmapSharedPtr& rBitmap)
|
||||
{
|
||||
GraphicsSharedPtr pRet(Gdiplus::Graphics::FromImage(rBitmap.get()));
|
||||
if( pRet )
|
||||
setupGraphics( *pRet );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix, const ::basegfx::B2DHomMatrix& rMatrix )
|
||||
{
|
||||
rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.get(0,0)),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.get(1,0)),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.get(0,1)),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.get(1,1)),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.get(0,2)),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.get(1,2)) );
|
||||
}
|
||||
|
||||
void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
|
||||
const geometry::AffineMatrix2D& rMatrix )
|
||||
{
|
||||
rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.m00),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.m10),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.m01),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.m11),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.m02),
|
||||
static_cast<Gdiplus::REAL>(rMatrix.m12) );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// TODO(P2): Check whether this gets inlined. If not, make functor
|
||||
// out of it
|
||||
Gdiplus::PointF implGdiPlusPointFromRealPoint2D( const css::geometry::RealPoint2D& rPoint )
|
||||
{
|
||||
return Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.X),
|
||||
static_cast<Gdiplus::REAL>(rPoint.Y) );
|
||||
}
|
||||
|
||||
void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr const & rOutput,
|
||||
std::vector< Gdiplus::PointF >& rPoints,
|
||||
const ::basegfx::B2DPolygon& rPoly,
|
||||
bool bNoLineJoin)
|
||||
{
|
||||
const sal_uInt32 nPoints( rPoly.count() );
|
||||
|
||||
if( nPoints < 2 )
|
||||
return;
|
||||
|
||||
rOutput->StartFigure();
|
||||
|
||||
const bool bClosedPolygon( rPoly.isClosed() );
|
||||
|
||||
if( rPoly.areControlPointsUsed() )
|
||||
{
|
||||
// control points used -> for now, add all
|
||||
// segments as curves to GraphicsPath
|
||||
|
||||
// If the polygon is closed, we need to add the
|
||||
// first point, thus, one more (can't simply
|
||||
// GraphicsPath::CloseFigure() it, since the last
|
||||
// point cannot have any control points for GDI+)
|
||||
rPoints.resize( 3*nPoints + (bClosedPolygon ? 1 : 0) );
|
||||
|
||||
sal_uInt32 nCurrOutput=0;
|
||||
for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
|
||||
{
|
||||
const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
|
||||
rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
|
||||
static_cast<Gdiplus::REAL>(rPoint.getY()) );
|
||||
|
||||
const ::basegfx::B2DPoint& rControlPointA( rPoly.getNextControlPoint( nCurrPoint ) );
|
||||
rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointA.getX()),
|
||||
static_cast<Gdiplus::REAL>(rControlPointA.getY()) );
|
||||
|
||||
const ::basegfx::B2DPoint& rControlPointB( rPoly.getPrevControlPoint( (nCurrPoint + 1) % nPoints) );
|
||||
rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointB.getX()),
|
||||
static_cast<Gdiplus::REAL>(rControlPointB.getY()) );
|
||||
}
|
||||
|
||||
if( bClosedPolygon )
|
||||
{
|
||||
// add first point again (to be able to pass
|
||||
// control points for the last point, see
|
||||
// above)
|
||||
const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint(0) );
|
||||
rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
|
||||
static_cast<Gdiplus::REAL>(rPoint.getY()) );
|
||||
|
||||
if(bNoLineJoin && nCurrOutput > 7)
|
||||
{
|
||||
for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
|
||||
{
|
||||
rOutput->StartFigure();
|
||||
rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rOutput->AddBeziers( rPoints.data(), nCurrOutput );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// GraphicsPath expects 3(n-1)+1 points (i.e. the
|
||||
// last point must not have any trailing control
|
||||
// points after it).
|
||||
// Therefore, simply don't pass the last two
|
||||
// points here.
|
||||
if( nCurrOutput > 3 )
|
||||
{
|
||||
if(bNoLineJoin && nCurrOutput > 7)
|
||||
{
|
||||
for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
|
||||
{
|
||||
rOutput->StartFigure();
|
||||
rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rOutput->AddBeziers( rPoints.data(), nCurrOutput-2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no control points -> no curves, simply add
|
||||
// straight lines to GraphicsPath
|
||||
rPoints.resize( nPoints );
|
||||
|
||||
for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
|
||||
{
|
||||
const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
|
||||
rPoints[nCurrPoint] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
|
||||
static_cast<Gdiplus::REAL>(rPoint.getY()) );
|
||||
}
|
||||
|
||||
if(bNoLineJoin && nPoints > 2)
|
||||
{
|
||||
for(sal_uInt32 a(1); a < nPoints; a++)
|
||||
{
|
||||
rOutput->StartFigure();
|
||||
rOutput->AddLine(rPoints[a - 1], rPoints[a]);
|
||||
}
|
||||
|
||||
if(bClosedPolygon)
|
||||
{
|
||||
rOutput->StartFigure();
|
||||
rOutput->AddLine(rPoints[nPoints - 1], rPoints[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rOutput->AddLines( rPoints.data(), nPoints );
|
||||
}
|
||||
}
|
||||
|
||||
if( bClosedPolygon && !bNoLineJoin )
|
||||
rOutput->CloseFigure();
|
||||
}
|
||||
}
|
||||
|
||||
Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRect )
|
||||
{
|
||||
return Gdiplus::Rect( rRect.X1,
|
||||
rRect.Y1,
|
||||
rRect.X2 - rRect.X1,
|
||||
rRect.Y2 - rRect.Y1 );
|
||||
}
|
||||
|
||||
Gdiplus::RectF gdiPlusRectFFromRectangle2D( const geometry::RealRectangle2D& rRect )
|
||||
{
|
||||
return Gdiplus::RectF( static_cast<Gdiplus::REAL>(rRect.X1),
|
||||
static_cast<Gdiplus::REAL>(rRect.Y1),
|
||||
static_cast<Gdiplus::REAL>(rRect.X2 - rRect.X1),
|
||||
static_cast<Gdiplus::REAL>(rRect.Y2 - rRect.Y1) );
|
||||
}
|
||||
|
||||
RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& rRect )
|
||||
{
|
||||
RECT aRect = {rRect.getMinX(),
|
||||
rRect.getMinY(),
|
||||
rRect.getMaxX(),
|
||||
rRect.getMaxY()};
|
||||
|
||||
return aRect;
|
||||
}
|
||||
|
||||
geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
|
||||
{
|
||||
return geometry::RealPoint2D( rPoint.X, rPoint.Y );
|
||||
}
|
||||
|
||||
geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& rRect )
|
||||
{
|
||||
return geometry::RealRectangle2D( rRect.X, rRect.Y,
|
||||
rRect.X + rRect.Width,
|
||||
rRect.Y + rRect.Height );
|
||||
}
|
||||
|
||||
::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
|
||||
{
|
||||
return ::basegfx::B2DPoint( rPoint.X, rPoint.Y );
|
||||
}
|
||||
|
||||
::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& rRect )
|
||||
{
|
||||
return ::basegfx::B2DRange( rRect.X, rRect.Y,
|
||||
rRect.X + rRect.Width,
|
||||
rRect.Y + rRect.Height );
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Int8 > argbToIntSequence( Gdiplus::ARGB rColor )
|
||||
{
|
||||
// TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
|
||||
return
|
||||
{
|
||||
static_cast<sal_Int8>((rColor >> 16) & 0xFF), // red
|
||||
static_cast<sal_Int8>((rColor >> 8) & 0xFF), // green
|
||||
static_cast<sal_Int8>(rColor & 0xFF), // blue
|
||||
static_cast<sal_Int8>((rColor >> 24) & 0xFF) // alpha
|
||||
};
|
||||
}
|
||||
|
||||
Gdiplus::ARGB sequenceToArgb( const uno::Sequence< sal_Int8 >& rColor )
|
||||
{
|
||||
ENSURE_OR_THROW( rColor.getLength() > 2,
|
||||
"sequenceToArgb: need at least three channels" );
|
||||
|
||||
// TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
|
||||
Gdiplus::ARGB aColor;
|
||||
|
||||
aColor = (static_cast<sal_uInt8>(rColor[0]) << 16) | (static_cast<sal_uInt8>(rColor[1]) << 8) | static_cast<sal_uInt8>(rColor[2]);
|
||||
|
||||
if( rColor.getLength() > 3 )
|
||||
aColor |= static_cast<sal_uInt8>(rColor[3]) << 24;
|
||||
|
||||
return aColor;
|
||||
}
|
||||
|
||||
Gdiplus::ARGB sequenceToArgb( const uno::Sequence< double >& rColor )
|
||||
{
|
||||
ENSURE_OR_THROW( rColor.getLength() > 2,
|
||||
"sequenceToColor: need at least three channels" );
|
||||
|
||||
// TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
|
||||
Gdiplus::ARGB aColor;
|
||||
|
||||
::canvas::tools::verifyRange(rColor[0],0.0,1.0);
|
||||
::canvas::tools::verifyRange(rColor[1],0.0,1.0);
|
||||
::canvas::tools::verifyRange(rColor[2],0.0,1.0);
|
||||
|
||||
aColor =
|
||||
(static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[0] ) ) << 16) |
|
||||
(static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[1] ) ) << 8) |
|
||||
static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[2] ) );
|
||||
|
||||
if( rColor.getLength() > 3 )
|
||||
{
|
||||
::canvas::tools::verifyRange(rColor[3],0.0,1.0);
|
||||
aColor |= static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[3] ) ) << 24;
|
||||
}
|
||||
|
||||
return aColor;
|
||||
}
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
|
||||
{
|
||||
GraphicsPathSharedPtr pRes = std::make_shared<Gdiplus::GraphicsPath>();
|
||||
std::vector< Gdiplus::PointF > aPoints;
|
||||
|
||||
for( uno::Sequence< geometry::RealPoint2D > const & seqPoints : points )
|
||||
{
|
||||
const sal_Int32 nCurrSize( seqPoints.getLength() );
|
||||
if( nCurrSize )
|
||||
{
|
||||
aPoints.resize( nCurrSize );
|
||||
|
||||
// TODO(F1): Closed/open polygons
|
||||
|
||||
// convert from RealPoint2D array to Gdiplus::PointF array
|
||||
std::transform( seqPoints.getConstArray(),
|
||||
seqPoints.getConstArray()+nCurrSize,
|
||||
aPoints.begin(),
|
||||
implGdiPlusPointFromRealPoint2D );
|
||||
|
||||
pRes->AddLines( aPoints.data(), nCurrSize );
|
||||
}
|
||||
}
|
||||
|
||||
return pRes;
|
||||
}
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly, bool bNoLineJoin )
|
||||
{
|
||||
GraphicsPathSharedPtr pRes = std::make_shared<Gdiplus::GraphicsPath>();
|
||||
std::vector< Gdiplus::PointF > aPoints;
|
||||
|
||||
graphicsPathFromB2DPolygon( pRes, aPoints, rPoly, bNoLineJoin );
|
||||
|
||||
return pRes;
|
||||
}
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, bool bNoLineJoin )
|
||||
{
|
||||
GraphicsPathSharedPtr pRes = std::make_shared<Gdiplus::GraphicsPath>();
|
||||
std::vector< Gdiplus::PointF > aPoints;
|
||||
|
||||
const sal_uInt32 nPolies( rPoly.count() );
|
||||
for( sal_uInt32 nCurrPoly=0; nCurrPoly<nPolies; ++nCurrPoly )
|
||||
{
|
||||
graphicsPathFromB2DPolygon( pRes,
|
||||
aPoints,
|
||||
rPoly.getB2DPolygon( nCurrPoly ),
|
||||
bNoLineJoin);
|
||||
}
|
||||
|
||||
return pRes;
|
||||
}
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly, bool bNoLineJoin )
|
||||
{
|
||||
LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
|
||||
|
||||
if( pPolyImpl )
|
||||
{
|
||||
return pPolyImpl->getGraphicsPath( bNoLineJoin );
|
||||
}
|
||||
else
|
||||
{
|
||||
return tools::graphicsPathFromB2DPolyPolygon(
|
||||
polyPolygonFromXPolyPolygon2D( xPoly ), bNoLineJoin );
|
||||
}
|
||||
}
|
||||
|
||||
bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
|
||||
const BitmapSharedPtr& rBitmap )
|
||||
{
|
||||
Gdiplus::PointF aPoint;
|
||||
return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
|
||||
aPoint ) );
|
||||
}
|
||||
|
||||
bool drawDIBits( const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
|
||||
const BITMAPINFO& rBI,
|
||||
const void* pBits )
|
||||
{
|
||||
BitmapSharedPtr pBitmap(
|
||||
Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
|
||||
const_cast<void*>(pBits) ) );
|
||||
|
||||
return drawGdiPlusBitmap( rGraphics,
|
||||
pBitmap );
|
||||
}
|
||||
|
||||
bool drawRGBABits( const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
|
||||
const RawRGBABitmap& rRawRGBAData )
|
||||
{
|
||||
BitmapSharedPtr pBitmap = std::make_shared<Gdiplus::Bitmap>( rRawRGBAData.mnWidth,
|
||||
rRawRGBAData.mnHeight,
|
||||
PixelFormat32bppARGB );
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = rRawRGBAData.mnWidth;
|
||||
aBmpData.Height = rRawRGBAData.mnHeight;
|
||||
aBmpData.Stride = 4*aBmpData.Width; // bottom-up format
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = const_cast<sal_uInt8*>(rRawRGBAData.maBitmapData.data());
|
||||
|
||||
const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
|
||||
if( Gdiplus::Ok != pBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
|
||||
PixelFormat32bppARGB,
|
||||
&aBmpData ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// commit data to bitmap
|
||||
pBitmap->UnlockBits( &aBmpData );
|
||||
|
||||
return drawGdiPlusBitmap( rGraphics,
|
||||
pBitmap );
|
||||
}
|
||||
|
||||
BitmapSharedPtr bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
|
||||
{
|
||||
BitmapProvider* pBitmapProvider = dynamic_cast< BitmapProvider* >(xBitmap.get());
|
||||
|
||||
if( pBitmapProvider )
|
||||
{
|
||||
IBitmapSharedPtr pBitmap( pBitmapProvider->getBitmap() );
|
||||
return pBitmap->getBitmap();
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a native CanvasBitmap, extract VCL bitmap and
|
||||
// render into GDI+ bitmap of similar size
|
||||
// =================================================
|
||||
|
||||
const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
|
||||
BitmapSharedPtr pBitmap;
|
||||
|
||||
if( xBitmap->hasAlpha() )
|
||||
{
|
||||
// TODO(P2): At least for the alpha bitmap case, it
|
||||
// would be possible to generate the corresponding
|
||||
// bitmap directly
|
||||
pBitmap = std::make_shared<Gdiplus::Bitmap>( aBmpSize.Width,
|
||||
aBmpSize.Height,
|
||||
PixelFormat32bppARGB );
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(F2): Might be wise to create bitmap compatible
|
||||
// to the VCL bitmap. Also, check whether the VCL
|
||||
// bitmap's system handles can be used to create the
|
||||
// GDI+ bitmap (currently, it does not seem so).
|
||||
pBitmap = std::make_shared<Gdiplus::Bitmap>( aBmpSize.Width,
|
||||
aBmpSize.Height,
|
||||
PixelFormat24bppRGB );
|
||||
}
|
||||
|
||||
GraphicsSharedPtr pGraphics(createGraphicsFromBitmap(pBitmap));
|
||||
tools::setupGraphics(*pGraphics);
|
||||
if( !drawVCLBitmapFromXBitmap(
|
||||
pGraphics,
|
||||
xBitmap) )
|
||||
{
|
||||
pBitmap.reset();
|
||||
}
|
||||
|
||||
return pBitmap;
|
||||
}
|
||||
}
|
||||
|
||||
CanvasFont::ImplRef canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >& xFont )
|
||||
{
|
||||
CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get());
|
||||
|
||||
ENSURE_ARG_OR_THROW( pCanvasFont,
|
||||
"canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" );
|
||||
|
||||
return CanvasFont::ImplRef( pCanvasFont );
|
||||
}
|
||||
|
||||
void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
|
||||
double nRedModulation,
|
||||
double nGreenModulation,
|
||||
double nBlueModulation,
|
||||
double nAlphaModulation )
|
||||
{
|
||||
// This gets rather verbose, but we have to setup a color
|
||||
// transformation matrix, in order to incorporate the global
|
||||
// alpha value mfAlpha into the bitmap rendering.
|
||||
Gdiplus::ColorMatrix aColorMatrix;
|
||||
|
||||
aColorMatrix.m[0][0] = static_cast<Gdiplus::REAL>(nRedModulation);
|
||||
aColorMatrix.m[0][1] = 0.0;
|
||||
aColorMatrix.m[0][2] = 0.0;
|
||||
aColorMatrix.m[0][3] = 0.0;
|
||||
aColorMatrix.m[0][4] = 0.0;
|
||||
|
||||
aColorMatrix.m[1][0] = 0.0;
|
||||
aColorMatrix.m[1][1] = static_cast<Gdiplus::REAL>(nGreenModulation);
|
||||
aColorMatrix.m[1][2] = 0.0;
|
||||
aColorMatrix.m[1][3] = 0.0;
|
||||
aColorMatrix.m[1][4] = 0.0;
|
||||
|
||||
aColorMatrix.m[2][0] = 0.0;
|
||||
aColorMatrix.m[2][1] = 0.0;
|
||||
aColorMatrix.m[2][2] = static_cast<Gdiplus::REAL>(nBlueModulation);
|
||||
aColorMatrix.m[2][3] = 0.0;
|
||||
aColorMatrix.m[2][4] = 0.0;
|
||||
|
||||
aColorMatrix.m[3][0] = 0.0;
|
||||
aColorMatrix.m[3][1] = 0.0;
|
||||
aColorMatrix.m[3][2] = 0.0;
|
||||
aColorMatrix.m[3][3] = static_cast<Gdiplus::REAL>(nAlphaModulation);
|
||||
aColorMatrix.m[3][4] = 0.0;
|
||||
|
||||
aColorMatrix.m[4][0] = 0.0;
|
||||
aColorMatrix.m[4][1] = 0.0;
|
||||
aColorMatrix.m[4][2] = 0.0;
|
||||
aColorMatrix.m[4][3] = 0.0;
|
||||
aColorMatrix.m[4][4] = 1.0;
|
||||
|
||||
o_rAttr.SetColorMatrix( &aColorMatrix );
|
||||
}
|
||||
|
||||
} // namespace dxcanvas::tools
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,124 @@
|
||||
/* -*- 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/Reference.hxx>
|
||||
#include <com/sun/star/uno/Sequence.hxx>
|
||||
#include <com/sun/star/util/TriState.hpp>
|
||||
|
||||
#include <basegfx/polygon/b2dpolygon.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
|
||||
#include <memory>
|
||||
#include "dx_canvasfont.hxx"
|
||||
|
||||
namespace basegfx
|
||||
{
|
||||
class B2DPoint;
|
||||
class B2DRange;
|
||||
class B2DHomMatrix;
|
||||
class B2IRange;
|
||||
class B2DPolyPolygon;
|
||||
};
|
||||
|
||||
namespace com::sun::star::geometry
|
||||
{
|
||||
struct IntegerRectangle2D;
|
||||
struct RealPoint2D;
|
||||
}
|
||||
|
||||
namespace com::sun::star::rendering
|
||||
{
|
||||
class XBitmap;
|
||||
class XPolyPolygon2D;
|
||||
class XCanvasFont;
|
||||
}
|
||||
|
||||
|
||||
namespace dxcanvas::tools
|
||||
{
|
||||
struct RawRGBABitmap;
|
||||
|
||||
::basegfx::B2DPolyPolygon
|
||||
polyPolygonFromXPolyPolygon2D( const css::uno::Reference< css::rendering::XPolyPolygon2D >& );
|
||||
|
||||
Gdiplus::Graphics* createGraphicsFromHDC(HDC);
|
||||
GraphicsSharedPtr createGraphicsFromBitmap(const BitmapSharedPtr&);
|
||||
|
||||
void setupGraphics( Gdiplus::Graphics& rGraphics );
|
||||
|
||||
void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix,
|
||||
const ::basegfx::B2DHomMatrix& rMatrix );
|
||||
void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
|
||||
const css::geometry::AffineMatrix2D& rMatrix );
|
||||
|
||||
Gdiplus::PointF gdiPlusPointFFromRealPoint2D( const css::geometry::RealPoint2D& );
|
||||
Gdiplus::RectF gdiPlusRectFFromRectangle2D( const css::geometry::RealRectangle2D& );
|
||||
Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const css::geometry::IntegerRectangle2D& );
|
||||
RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& );
|
||||
|
||||
css::geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& );
|
||||
css::geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& );
|
||||
|
||||
::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& );
|
||||
::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& );
|
||||
|
||||
css::uno::Sequence< sal_Int8 > argbToIntSequence( Gdiplus::ARGB rColor );
|
||||
Gdiplus::ARGB sequenceToArgb( const css::uno::Sequence< sal_Int8 >& rColor );
|
||||
Gdiplus::ARGB sequenceToArgb( const css::uno::Sequence< double >& rColor );
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const css::uno::Sequence<
|
||||
css::uno::Sequence< css::geometry::RealPoint2D > >& );
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromB2DPolygon(
|
||||
const ::basegfx::B2DPolygon& rPoly,
|
||||
bool bNoLineJoin = false);
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon(
|
||||
const ::basegfx::B2DPolyPolygon& rPoly,
|
||||
bool bNoLineJoin = false);
|
||||
|
||||
GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D(
|
||||
const css::uno::Reference< css::rendering::XPolyPolygon2D >&,
|
||||
bool bNoLineJoin = false );
|
||||
|
||||
bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
|
||||
const BitmapSharedPtr& rBitmap );
|
||||
bool drawDIBits( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const BITMAPINFO& rBI,
|
||||
const void* pBits );
|
||||
|
||||
bool drawRGBABits( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const RawRGBABitmap& rRawRGBAData );
|
||||
|
||||
BitmapSharedPtr bitmapFromXBitmap( const css::uno::Reference< css::rendering::XBitmap >& xBitmap );
|
||||
|
||||
CanvasFont::ImplRef canvasFontFromXFont( const css::uno::Reference< css::rendering::XCanvasFont >& xFont );
|
||||
|
||||
void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
|
||||
double nRedModulation,
|
||||
double nGreenModulation,
|
||||
double nBlueModulation,
|
||||
double nAlphaModulation );
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,59 @@
|
||||
/* -*- 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/utils/canvastools.hxx>
|
||||
|
||||
#include "dx_linepolypolygon.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
LinePolyPolygon::LinePolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ) :
|
||||
::basegfx::unotools::UnoPolyPolygon( rPolyPoly ),
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
mpPath()
|
||||
{
|
||||
}
|
||||
|
||||
GraphicsPathSharedPtr LinePolyPolygon::getGraphicsPath( bool bNoLineJoin ) const
|
||||
{
|
||||
// generate GraphicsPath only on demand (gets deleted as soon
|
||||
// as any of the modifying methods above touches the
|
||||
// B2DPolyPolygon).
|
||||
if( !mpPath )
|
||||
{
|
||||
mpPath = tools::graphicsPathFromB2DPolyPolygon( getPolyPolygonUnsafe(), bNoLineJoin );
|
||||
mpPath->SetFillMode( const_cast<LinePolyPolygon*>(this)->getFillRule() == rendering::FillRule_EVEN_ODD ?
|
||||
Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding );
|
||||
}
|
||||
|
||||
return mpPath;
|
||||
}
|
||||
|
||||
void LinePolyPolygon::modifying() const
|
||||
{
|
||||
mpPath.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,47 @@
|
||||
/* -*- 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 <canvas/canvastools.hxx>
|
||||
#include <basegfx/utils/unopolypolygon.hxx>
|
||||
|
||||
#include "dx_gdiplususer.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class LinePolyPolygon : public ::basegfx::unotools::UnoPolyPolygon
|
||||
{
|
||||
public:
|
||||
explicit LinePolyPolygon( const ::basegfx::B2DPolyPolygon& );
|
||||
|
||||
GraphicsPathSharedPtr getGraphicsPath( bool bNoLineJoin = false) const;
|
||||
|
||||
private:
|
||||
// overridden, to clear mpPath
|
||||
virtual void modifying() const override;
|
||||
|
||||
GDIPlusUserSharedPtr mpGdiPlusUser;
|
||||
mutable GraphicsPathSharedPtr mpPath;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,80 @@
|
||||
/* -*- 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 <basegfx/vector/b2ivector.hxx>
|
||||
#include <basegfx/range/b2irectangle.hxx>
|
||||
#include <rendering/irendermodule.hxx>
|
||||
#include <memory>
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
namespace vcl { class Window; }
|
||||
namespace basegfx
|
||||
{
|
||||
class B2IRange;
|
||||
}
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/// Specialization of IRenderModule for DirectX
|
||||
struct IDXRenderModule : public canvas::IRenderModule
|
||||
{
|
||||
/** Flip front- and backbuffer, update only given area
|
||||
|
||||
Note: Both update area and offset are ignored for
|
||||
fullscreen canvas, that uses page flipping (cannot, by
|
||||
definition, do anything else there except displaying the
|
||||
full backbuffer instead of the front buffer)
|
||||
|
||||
@param rUpdateArea
|
||||
Area to copy from backbuffer to front
|
||||
|
||||
@param rCurrWindowArea
|
||||
Current area of VCL window (coordinates relative to VCL
|
||||
HWND)
|
||||
*/
|
||||
virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
|
||||
const ::basegfx::B2IRectangle& rCurrWindowArea ) = 0;
|
||||
|
||||
/** Resize backbuffer area for this render module
|
||||
*/
|
||||
virtual void resize( const ::basegfx::B2IRange& rect ) = 0;
|
||||
|
||||
/// Write a snapshot of the screen to disk
|
||||
virtual void screenShot() = 0;
|
||||
|
||||
virtual sal::systools::COMReference<surface_type>
|
||||
createSystemMemorySurface(
|
||||
const ::basegfx::B2ISize& rSize) = 0;
|
||||
|
||||
virtual void disposing() = 0;
|
||||
virtual HWND getHWND() const = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< IDXRenderModule > IDXRenderModuleSharedPtr;
|
||||
|
||||
|
||||
/** Factory method, to create an IRenderModule instance for the
|
||||
given VCL window instance
|
||||
*/
|
||||
IDXRenderModuleSharedPtr createRenderModule( const vcl::Window& rParent );
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,45 @@
|
||||
/* -*- 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/sprite.hxx>
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Specialization of ::canvas::Sprite interface, to also provide
|
||||
redraw methods.
|
||||
*/
|
||||
class Sprite : public ::canvas::Sprite
|
||||
{
|
||||
public:
|
||||
|
||||
/** Redraw sprite using the hardware
|
||||
|
||||
This method will silently fail, if the previous
|
||||
restoreTextures() call failed.
|
||||
*/
|
||||
virtual void redraw() const = 0;
|
||||
|
||||
protected:
|
||||
~Sprite() {}
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,192 @@
|
||||
/* -*- 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/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/lang/NoSupportException.hpp>
|
||||
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
|
||||
#include <com/sun/star/registry/XRegistryKey.hpp>
|
||||
#include <com/sun/star/uno/XComponentContext.hpp>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
|
||||
const uno::Reference< uno::XComponentContext >& rxContext ) :
|
||||
maArguments(aArguments),
|
||||
mxComponentContext( rxContext )
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteCanvas::initialize()
|
||||
{
|
||||
// #i64742# Only call initialize when not in probe mode
|
||||
if( maArguments.getLength() == 0 )
|
||||
return;
|
||||
|
||||
SAL_INFO("canvas.directx", "SpriteCanvas::initialize called" );
|
||||
|
||||
/* aArguments:
|
||||
0: ptr to creating instance (Window or VirtualDevice)
|
||||
1: SystemEnvData as a streamed Any (or empty for VirtualDevice)
|
||||
2: current bounds of creating instance
|
||||
3: bool, denoting always on top state for Window (always false for VirtualDevice)
|
||||
4: XWindow for creating Window (or empty for VirtualDevice)
|
||||
5: SystemGraphicsData as a streamed Any
|
||||
*/
|
||||
ENSURE_ARG_OR_THROW( maArguments.getLength() >= 4 &&
|
||||
maArguments[3].getValueTypeClass() == uno::TypeClass_INTERFACE,
|
||||
"VCLSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
|
||||
|
||||
uno::Reference< awt::XWindow > xParentWindow;
|
||||
maArguments[3] >>= xParentWindow;
|
||||
auto pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
|
||||
if( !pParentWindow )
|
||||
throw lang::NoSupportException( "Parent window not VCL window, or canvas out-of-process!" );
|
||||
|
||||
awt::Rectangle aRect;
|
||||
maArguments[1] >>= aRect;
|
||||
|
||||
bool bIsFullscreen( false );
|
||||
maArguments[2] >>= bIsFullscreen;
|
||||
|
||||
// setup helper
|
||||
maDeviceHelper.init( *pParentWindow,
|
||||
*this,
|
||||
aRect,
|
||||
bIsFullscreen );
|
||||
maCanvasHelper.init( *this,
|
||||
maRedrawManager,
|
||||
maDeviceHelper.getRenderModule(),
|
||||
maDeviceHelper.getSurfaceProxy(),
|
||||
maDeviceHelper.getBackBuffer(),
|
||||
::basegfx::B2ISize() );
|
||||
maArguments.realloc(0);
|
||||
}
|
||||
|
||||
void SpriteCanvas::disposeThis()
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
mxComponentContext.clear();
|
||||
|
||||
// forward to parent
|
||||
SpriteCanvasBaseT::disposeThis();
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::showBuffer( sal_Bool bUpdateAll )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
// avoid repaints on hidden window (hidden: not mapped to
|
||||
// screen). Return failure, since the screen really has _not_
|
||||
// been updated (caller should try again later)
|
||||
return mbIsVisible && SpriteCanvasBaseT::showBuffer( bUpdateAll );
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::switchBuffer( sal_Bool bUpdateAll )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
// avoid repaints on hidden window (hidden: not mapped to
|
||||
// screen). Return failure, since the screen really has _not_
|
||||
// been updated (caller should try again later)
|
||||
return mbIsVisible && SpriteCanvasBaseT::switchBuffer( bUpdateAll );
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL SpriteCanvas::updateScreen( sal_Bool bUpdateAll )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
// avoid repaints on hidden window (hidden: not mapped to
|
||||
// screen). Return failure, since the screen really has _not_
|
||||
// been updated (caller should try again later)
|
||||
return mbIsVisible && maCanvasHelper.updateScreen(
|
||||
::basegfx::unotools::b2IRectangleFromAwtRectangle(maBounds),
|
||||
bUpdateAll,
|
||||
mbSurfaceDirty );
|
||||
}
|
||||
|
||||
OUString SAL_CALL SpriteCanvas::getServiceName( )
|
||||
{
|
||||
return "com.sun.star.rendering.SpriteCanvas.DX9";
|
||||
}
|
||||
|
||||
// XServiceInfo
|
||||
css::uno::Sequence<OUString> SpriteCanvas::getSupportedServiceNames( )
|
||||
{
|
||||
return { "com.sun.star.rendering.SpriteCanvas.DX9" };
|
||||
}
|
||||
OUString SpriteCanvas::getImplementationName( )
|
||||
{
|
||||
return "com.sun.star.comp.rendering.SpriteCanvas.DX9";
|
||||
}
|
||||
sal_Bool SpriteCanvas::supportsService( const OUString& sServiceName )
|
||||
{
|
||||
return cppu::supportsService(this, sServiceName);
|
||||
}
|
||||
|
||||
const IDXRenderModuleSharedPtr& SpriteCanvas::getRenderModule() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maDeviceHelper.getRenderModule();
|
||||
}
|
||||
|
||||
const DXSurfaceBitmapSharedPtr& SpriteCanvas::getBackBuffer() const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maDeviceHelper.getBackBuffer();
|
||||
}
|
||||
|
||||
IBitmapSharedPtr SpriteCanvas::getBitmap() const
|
||||
{
|
||||
return maDeviceHelper.getBackBuffer();
|
||||
}
|
||||
|
||||
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
||||
canvas_directx9_SpriteCanvas_get_implementation(
|
||||
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
|
||||
{
|
||||
rtl::Reference<SpriteCanvas> xCanvas(new SpriteCanvas(args, context));
|
||||
xCanvas->initialize();
|
||||
return cppu::acquire(xCanvas.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,155 @@
|
||||
/* -*- 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 <rtl/ref.hxx>
|
||||
|
||||
#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/awt/XWindowListener.hpp>
|
||||
#include <com/sun/star/awt/XTopWindow.hpp>
|
||||
#include <com/sun/star/util/XUpdatable.hpp>
|
||||
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||
|
||||
#include <cppuhelper/compbase.hxx>
|
||||
#include <comphelper/uno3.hxx>
|
||||
|
||||
#include <base/spritecanvasbase.hxx>
|
||||
#include <base/spritesurface.hxx>
|
||||
#include <base/disambiguationhelper.hxx>
|
||||
#include <base/bufferedgraphicdevicebase.hxx>
|
||||
|
||||
#include "dx_bitmapprovider.hxx"
|
||||
#include "dx_spritecanvashelper.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritedevicehelper.hxx"
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XSpriteCanvas,
|
||||
css::rendering::XIntegerBitmap,
|
||||
css::rendering::XGraphicDevice,
|
||||
css::lang::XMultiServiceFactory,
|
||||
css::rendering::XBufferController,
|
||||
css::awt::XWindowListener,
|
||||
css::util::XUpdatable,
|
||||
css::beans::XPropertySet,
|
||||
css::lang::XServiceName,
|
||||
css::lang::XServiceInfo> WindowGraphicDeviceBase_Base;
|
||||
typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::DisambiguationHelper< WindowGraphicDeviceBase_Base >,
|
||||
SpriteDeviceHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > SpriteCanvasBase_Base;
|
||||
/** Mixin SpriteSurface
|
||||
|
||||
Have to mixin the SpriteSurface before deriving from
|
||||
::canvas::SpriteCanvasBase, 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::SpriteCanvasBase directly from
|
||||
::canvas::SpriteSurface (because derivees of
|
||||
::canvas::SpriteCanvasBase 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 SpriteCanvasBaseSpriteSurface_Base : public SpriteCanvasBase_Base,
|
||||
public ::canvas::SpriteSurface
|
||||
{
|
||||
};
|
||||
|
||||
typedef ::canvas::SpriteCanvasBase< SpriteCanvasBaseSpriteSurface_Base,
|
||||
SpriteCanvasHelper,
|
||||
::osl::MutexGuard,
|
||||
::cppu::OWeakObject > SpriteCanvasBaseT;
|
||||
|
||||
/** Product of this component's factory.
|
||||
|
||||
The SpriteCanvas 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 SpriteCanvas : public SpriteCanvasBaseT, public BitmapProvider
|
||||
{
|
||||
public:
|
||||
SpriteCanvas( const css::uno::Sequence<
|
||||
css::uno::Any >& aArguments,
|
||||
const css::uno::Reference<
|
||||
css::uno::XComponentContext >& rxContext );
|
||||
|
||||
void initialize();
|
||||
|
||||
/// 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( SpriteCanvas, WindowGraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase )
|
||||
|
||||
// XBufferController (partial)
|
||||
virtual sal_Bool SAL_CALL showBuffer( sal_Bool bUpdateAll ) override;
|
||||
virtual sal_Bool SAL_CALL switchBuffer( sal_Bool bUpdateAll ) override;
|
||||
|
||||
// XSpriteCanvas (partial)
|
||||
virtual sal_Bool SAL_CALL updateScreen( sal_Bool bUpdateAll ) override;
|
||||
|
||||
// XServiceName
|
||||
virtual OUString SAL_CALL getServiceName( ) override;
|
||||
|
||||
// XServiceInfo
|
||||
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames( ) override;
|
||||
virtual OUString SAL_CALL getImplementationName( ) override;
|
||||
virtual sal_Bool SAL_CALL supportsService( const OUString& ) override;
|
||||
|
||||
/// Retrieve rendermodule object for this Canvas
|
||||
const IDXRenderModuleSharedPtr& getRenderModule() const;
|
||||
|
||||
/// Get backbuffer for this canvas
|
||||
const DXSurfaceBitmapSharedPtr& getBackBuffer() const;
|
||||
|
||||
// BitmapProvider
|
||||
virtual IBitmapSharedPtr getBitmap() const override;
|
||||
|
||||
private:
|
||||
css::uno::Sequence< css::uno::Any > maArguments;
|
||||
css::uno::Reference< css::uno::XComponentContext > mxComponentContext;
|
||||
};
|
||||
|
||||
typedef ::rtl::Reference< SpriteCanvas > SpriteCanvasRef;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,352 @@
|
||||
/* -*- 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 <boost/cast.hpp>
|
||||
|
||||
#include <basegfx/range/b2drectangle.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <comphelper/scopeguard.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvascustomsprite.hxx"
|
||||
#include "dx_spritecanvashelper.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void repaintBackground( const ::basegfx::B2DRange& rUpdateArea,
|
||||
const ::basegfx::B2IRange& rOutputArea,
|
||||
const DXSurfaceBitmapSharedPtr& rBackBuffer )
|
||||
{
|
||||
// TODO(E1): Use numeric_cast to catch overflow here
|
||||
::basegfx::B2IRange aActualArea( 0, 0,
|
||||
static_cast<sal_Int32>(rOutputArea.getWidth()),
|
||||
static_cast<sal_Int32>(rOutputArea.getHeight()) );
|
||||
aActualArea.intersect( fround( rUpdateArea ) );
|
||||
|
||||
// repaint the given area of the screen with background content
|
||||
rBackBuffer->draw(aActualArea);
|
||||
}
|
||||
|
||||
void spriteRedraw( const ::canvas::Sprite::Reference& rSprite )
|
||||
{
|
||||
// downcast to derived dxcanvas::Sprite interface, which
|
||||
// provides the actual redraw methods.
|
||||
::boost::polymorphic_downcast< Sprite* >(
|
||||
rSprite.get() )->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
SpriteCanvasHelper::SpriteCanvasHelper() :
|
||||
mpSpriteSurface( nullptr ),
|
||||
mpRedrawManager( nullptr ),
|
||||
mpRenderModule(),
|
||||
mpSurfaceProxy(),
|
||||
mpBackBuffer(),
|
||||
maUpdateRect(),
|
||||
maScrapRect(),
|
||||
mbShowSpriteBounds( false )
|
||||
{
|
||||
#if OSL_DEBUG_LEVEL > 0
|
||||
// inverse default for verbose debug mode
|
||||
mbShowSpriteBounds = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::init( SpriteCanvas& rParent,
|
||||
::canvas::SpriteRedrawManager& rManager,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rSurfaceProxy,
|
||||
const DXSurfaceBitmapSharedPtr& rBackBuffer,
|
||||
const ::basegfx::B2ISize& rOutputOffset )
|
||||
{
|
||||
// init base
|
||||
setDevice( rParent );
|
||||
setTarget( rBackBuffer, rOutputOffset );
|
||||
|
||||
mpSpriteSurface = &rParent;
|
||||
mpRedrawManager = &rManager;
|
||||
mpRenderModule = rRenderModule;
|
||||
mpSurfaceProxy = rSurfaceProxy;
|
||||
mpBackBuffer = rBackBuffer;
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::disposing()
|
||||
{
|
||||
if(mpRenderModule)
|
||||
mpRenderModule->disposing();
|
||||
|
||||
mpBackBuffer.reset();
|
||||
mpRenderModule.reset();
|
||||
mpRedrawManager = nullptr;
|
||||
mpSpriteSurface = nullptr;
|
||||
|
||||
// forward to base
|
||||
CanvasHelper::disposing();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
|
||||
const uno::Reference< rendering::XAnimation >& /*animation*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XAnimatedSprite >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
|
||||
const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/,
|
||||
sal_Int8 /*interpolationMode*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XAnimatedSprite >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
|
||||
{
|
||||
if( !mpRedrawManager )
|
||||
return uno::Reference< rendering::XCustomSprite >(); // we're disposed
|
||||
|
||||
return uno::Reference< rendering::XCustomSprite >(
|
||||
new CanvasCustomSprite( spriteSize,
|
||||
mpSpriteSurface,
|
||||
mpRenderModule,
|
||||
mpSurfaceProxy,
|
||||
mbShowSpriteBounds ) );
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XSprite >();
|
||||
}
|
||||
|
||||
bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
|
||||
bool bUpdateAll,
|
||||
bool& io_bSurfaceDirty )
|
||||
{
|
||||
if( !mpRedrawManager ||
|
||||
!mpRenderModule ||
|
||||
!mpBackBuffer )
|
||||
{
|
||||
return false; // disposed, or otherwise dysfunctional
|
||||
}
|
||||
|
||||
// store current output area (need to tunnel that to the
|
||||
// background, scroll, opaque and general sprite repaint
|
||||
// routines)
|
||||
maScrapRect = rCurrArea;
|
||||
|
||||
// clear area that needs to be blitted to screen beforehand
|
||||
maUpdateRect.reset();
|
||||
|
||||
// TODO(P1): Might be worthwhile to track areas of background
|
||||
// changes, too.
|
||||
|
||||
// TODO(P2): Might be worthwhile to use page-flipping only if
|
||||
// a certain percentage of screen area has changed - and
|
||||
// compose directly to the front buffer otherwise.
|
||||
if( !bUpdateAll && !io_bSurfaceDirty )
|
||||
{
|
||||
// background has not changed, so we're free to optimize
|
||||
// repaint to areas where a sprite has changed
|
||||
|
||||
// process each independent area of overlapping sprites
|
||||
// separately.
|
||||
mpRedrawManager->forEachSpriteArea( *this );
|
||||
|
||||
// flip primary surface to screen
|
||||
// ==============================
|
||||
|
||||
// perform buffer flipping
|
||||
mpRenderModule->flip( maUpdateRect,
|
||||
rCurrArea );
|
||||
}
|
||||
else
|
||||
{
|
||||
// limit update to parent window area (ignored for fullscreen)
|
||||
// TODO(E1): Use numeric_cast to catch overflow here
|
||||
const ::basegfx::B2IRectangle aUpdateArea( 0,0,
|
||||
static_cast<sal_Int32>(rCurrArea.getWidth()),
|
||||
static_cast<sal_Int32>(rCurrArea.getHeight()) );
|
||||
|
||||
// background has changed, or called requested full
|
||||
// update, or we're performing double buffering via page
|
||||
// flipping, so we currently have no choice but repaint
|
||||
// everything
|
||||
|
||||
// repaint the whole screen with background content
|
||||
mpBackBuffer->draw(aUpdateArea);
|
||||
|
||||
// redraw sprites
|
||||
mpRedrawManager->forEachSprite( &spriteRedraw );
|
||||
|
||||
// flip primary surface to screen
|
||||
// ==============================
|
||||
|
||||
// perform buffer flipping
|
||||
mpRenderModule->flip( aUpdateArea,
|
||||
rCurrArea );
|
||||
}
|
||||
|
||||
// change record vector must be cleared, for the next turn of
|
||||
// rendering and sprite changing
|
||||
mpRedrawManager->clearChangeRecords();
|
||||
|
||||
io_bSurfaceDirty = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
|
||||
{
|
||||
ENSURE_OR_THROW( mpRenderModule &&
|
||||
mpBackBuffer,
|
||||
"SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
|
||||
|
||||
repaintBackground( rUpdateRect,
|
||||
maScrapRect,
|
||||
mpBackBuffer );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/,
|
||||
const ::basegfx::B2DRange& rMoveEnd,
|
||||
const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
|
||||
{
|
||||
ENSURE_OR_THROW( mpRenderModule &&
|
||||
mpBackBuffer,
|
||||
"SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
|
||||
|
||||
// round rectangles to integer pixel. Note: have to be
|
||||
// extremely careful here, to avoid off-by-one errors for
|
||||
// the destination area: otherwise, the next scroll update
|
||||
// would copy pixel that are not supposed to be part of
|
||||
// the sprite.
|
||||
const ::basegfx::B2IRange& rDestRect(
|
||||
::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
|
||||
|
||||
// not much sense in really implementing scrollUpdate here,
|
||||
// since outputting a sprite only partially would result in
|
||||
// expensive clipping. Furthermore, we cannot currently render
|
||||
// 3D directly to the front buffer, thus, would have to blit
|
||||
// the full sprite area, anyway. But at least optimized in the
|
||||
// sense that unnecessary background paints behind the sprites
|
||||
// are avoided.
|
||||
for( const auto& rComponent : rUpdateArea.maComponentList )
|
||||
{
|
||||
const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
|
||||
|
||||
if( rSprite.is() )
|
||||
{
|
||||
// downcast to derived dxcanvas::Sprite interface, which
|
||||
// provides the actual redraw methods.
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// repaint uncovered areas from backbuffer - take the
|
||||
// _rounded_ rectangles from above, to have the update
|
||||
// consistent with the scroll above.
|
||||
std::vector< ::basegfx::B2DRange > aUncoveredAreas;
|
||||
::basegfx::computeSetDifference( aUncoveredAreas,
|
||||
rUpdateArea.maTotalBounds,
|
||||
::basegfx::B2DRange( rDestRect ) );
|
||||
for( const auto& rUncoveredArea : aUncoveredAreas )
|
||||
repaintBackground( rUncoveredArea, maScrapRect, mpBackBuffer );
|
||||
|
||||
// TODO(E1): Use numeric_cast to catch overflow here
|
||||
::basegfx::B2IRange aActualArea( 0, 0,
|
||||
static_cast<sal_Int32>(maScrapRect.getWidth()),
|
||||
static_cast<sal_Int32>(maScrapRect.getHeight()) );
|
||||
aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) );
|
||||
|
||||
// add given update area to the 'blit to foreground' rect
|
||||
maUpdateRect.expand( aActualArea );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
|
||||
{
|
||||
ENSURE_OR_THROW( mpRenderModule &&
|
||||
mpBackBuffer,
|
||||
"SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
|
||||
|
||||
// TODO(P2): optimize this by truly rendering to the front
|
||||
// buffer. Currently, we've the 3D device only for the back
|
||||
// buffer.
|
||||
for( const auto& rSprite : rSortedUpdateSprites )
|
||||
{
|
||||
if( rSprite.is() )
|
||||
{
|
||||
// downcast to derived dxcanvas::Sprite interface, which
|
||||
// provides the actual redraw methods.
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(E1): Use numeric_cast to catch overflow here
|
||||
::basegfx::B2IRange aActualArea( 0, 0,
|
||||
static_cast<sal_Int32>(maScrapRect.getWidth()),
|
||||
static_cast<sal_Int32>(maScrapRect.getHeight()) );
|
||||
aActualArea.intersect( fround( rTotalArea ) );
|
||||
|
||||
// add given update area to the 'blit to foreground' rect
|
||||
maUpdateRect.expand( aActualArea );
|
||||
}
|
||||
|
||||
void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
|
||||
{
|
||||
ENSURE_OR_THROW( mpRenderModule &&
|
||||
mpBackBuffer,
|
||||
"SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
|
||||
|
||||
// paint background
|
||||
// ================
|
||||
|
||||
// TODO(E1): Use numeric_cast to catch overflow here
|
||||
::basegfx::B2IRange aActualArea( 0, 0,
|
||||
static_cast<sal_Int32>(maScrapRect.getWidth()),
|
||||
static_cast<sal_Int32>(maScrapRect.getHeight()) );
|
||||
aActualArea.intersect( fround( rTotalArea ) );
|
||||
|
||||
// repaint the given area of the screen with background content
|
||||
mpBackBuffer->draw(aActualArea);
|
||||
|
||||
// paint sprite
|
||||
// ============
|
||||
|
||||
for( const auto& rSprite : rSortedUpdateSprites )
|
||||
{
|
||||
if( rSprite.is() )
|
||||
{
|
||||
// downcast to derived dxcanvas::Sprite interface, which
|
||||
// provides the actual redraw methods.
|
||||
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// add given update area to the 'blit to foreground' rect
|
||||
maUpdateRect.expand( aActualArea );
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,152 @@
|
||||
/* -*- 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/rendering/XSpriteCanvas.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
|
||||
#include <spriteredrawmanager.hxx>
|
||||
#include <rendering/isurfaceproxy.hxx>
|
||||
#include <rendering/isurfaceproxymanager.hxx>
|
||||
|
||||
#include "dx_bitmapcanvashelper.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_rendermodule.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
|
||||
#include <basegfx/range/b2irectangle.hxx>
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class SpriteCanvas;
|
||||
|
||||
class SpriteCanvasHelper : public BitmapCanvasHelper
|
||||
{
|
||||
public:
|
||||
SpriteCanvasHelper();
|
||||
|
||||
void init( SpriteCanvas& rParent,
|
||||
::canvas::SpriteRedrawManager& rManager,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rSurfaceProxy,
|
||||
const DXSurfaceBitmapSharedPtr& rBackBuffer,
|
||||
const ::basegfx::B2ISize& rOutputOffset );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// XSpriteCanvas
|
||||
css::uno::Reference<
|
||||
css::rendering::XAnimatedSprite > createSpriteFromAnimation(
|
||||
const css::uno::Reference< css::rendering::XAnimation >& animation );
|
||||
|
||||
css::uno::Reference<
|
||||
css::rendering::XAnimatedSprite > createSpriteFromBitmaps(
|
||||
const css::uno::Sequence<
|
||||
css::uno::Reference<
|
||||
css::rendering::XBitmap > >& animationBitmaps,
|
||||
sal_Int8 interpolationMode );
|
||||
|
||||
css::uno::Reference<
|
||||
css::rendering::XCustomSprite > createCustomSprite(
|
||||
const css::geometry::RealSize2D& spriteSize );
|
||||
|
||||
css::uno::Reference<
|
||||
css::rendering::XSprite > createClonedSprite(
|
||||
const css::uno::Reference< css::rendering::XSprite >& original );
|
||||
|
||||
/** Actually perform the screen update
|
||||
|
||||
@param rCurrArea
|
||||
Current window area in absolute screen coordinates
|
||||
|
||||
@param bUpdateAll
|
||||
sal_True, if everything must be updated, not only changed
|
||||
sprites
|
||||
|
||||
@param io_bSurfaceDirty
|
||||
In/out parameter, whether backbuffer surface is dirty (if
|
||||
yes, we're performing a full update, anyway)
|
||||
*/
|
||||
bool updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
|
||||
bool bUpdateAll,
|
||||
bool& io_bSurfaceDirty );
|
||||
|
||||
|
||||
// SpriteRedrawManager functor calls
|
||||
|
||||
|
||||
/** Gets called for simple background repaints
|
||||
*/
|
||||
void backgroundPaint( const ::basegfx::B2DRange& rUpdateRect );
|
||||
|
||||
/** Gets called when area can be handled by scrolling.
|
||||
|
||||
Called method must copy screen content from rMoveStart to
|
||||
rMoveEnd, and restore the background in the uncovered
|
||||
areas.
|
||||
|
||||
@param rMoveStart
|
||||
Source rect of the scroll
|
||||
|
||||
@param rMoveEnd
|
||||
Dest rect of the scroll
|
||||
|
||||
@param rUpdateArea
|
||||
All info necessary, should rMoveStart be partially or
|
||||
fully outside the outdev
|
||||
*/
|
||||
void scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
|
||||
const ::basegfx::B2DRange& rMoveEnd,
|
||||
const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
|
||||
|
||||
void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
|
||||
|
||||
void genericUpdate( const ::basegfx::B2DRange& rTotalArea,
|
||||
const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
|
||||
|
||||
private:
|
||||
/// For generating sprites
|
||||
SpriteCanvas* mpSpriteSurface;
|
||||
|
||||
/// Set from the SpriteCanvas: instance coordinating sprite redraw
|
||||
::canvas::SpriteRedrawManager* mpRedrawManager;
|
||||
|
||||
/// DX device, handling all low-level rendering
|
||||
IDXRenderModuleSharedPtr mpRenderModule;
|
||||
|
||||
std::shared_ptr<canvas::ISurfaceProxyManager> mpSurfaceProxy;
|
||||
|
||||
/// Backbuffer, contains the static canvas render output
|
||||
DXSurfaceBitmapSharedPtr mpBackBuffer;
|
||||
|
||||
/// Completely temporary rect storage (used by sprite repaint)
|
||||
mutable ::basegfx::B2IRange maUpdateRect;
|
||||
|
||||
/// Completely temporary rect storage (used by sprite repaint)
|
||||
mutable ::basegfx::B2IRange maScrapRect;
|
||||
|
||||
/// When true, show small bound rects around each sprite
|
||||
bool mbShowSpriteBounds;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,221 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <sal/log.hxx>
|
||||
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <canvas/canvastools.hxx>
|
||||
#include <com/sun/star/lang/NoSupportException.hpp>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/sysdata.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
|
||||
#include "dx_canvasbitmap.hxx"
|
||||
#include "dx_linepolypolygon.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_spritedevicehelper.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
SpriteDeviceHelper::SpriteDeviceHelper() :
|
||||
DeviceHelper(),
|
||||
mpSpriteCanvas( nullptr ),
|
||||
mpBackBuffer(),
|
||||
mpSurfaceProxyManager(),
|
||||
mpRenderModule()
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::init( vcl::Window& rWindow,
|
||||
SpriteCanvas& rSpriteCanvas,
|
||||
const awt::Rectangle& rRect,
|
||||
bool /*bFullscreen*/ )
|
||||
{
|
||||
// #i60490# ensure backbuffer has sensible minimal size
|
||||
const sal_Int32 w( std::max(sal_Int32(1),sal_Int32(rRect.Width)));
|
||||
const sal_Int32 h( std::max(sal_Int32(1),sal_Int32(rRect.Height)));
|
||||
|
||||
rSpriteCanvas.setWindow(
|
||||
uno::Reference<awt::XWindow2>(
|
||||
VCLUnoHelper::GetInterface(&rWindow),
|
||||
uno::UNO_QUERY_THROW) );
|
||||
|
||||
const SystemEnvData *pData = rWindow.GetSystemData();
|
||||
const HWND hWnd = reinterpret_cast<HWND>(pData->hWnd);
|
||||
if( !IsWindow( hWnd ) )
|
||||
throw lang::NoSupportException( "Passed window has invalid system window, or canvas out-of-process!" );
|
||||
|
||||
mpSpriteCanvas = &rSpriteCanvas;
|
||||
|
||||
try
|
||||
{
|
||||
// setup directx rendermodule
|
||||
mpRenderModule = createRenderModule( rWindow );
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
throw lang::NoSupportException( "Could not create DirectX device!",
|
||||
rSpriteCanvas.getXWeak() );
|
||||
}
|
||||
|
||||
// create the surfaceproxy manager
|
||||
mpSurfaceProxyManager = ::canvas::createSurfaceProxyManager( mpRenderModule );
|
||||
|
||||
// #i60490# ensure backbuffer has sensible minimal size
|
||||
mpBackBuffer = std::make_shared<DXSurfaceBitmap>(
|
||||
basegfx::B2ISize(w,h),
|
||||
mpSurfaceProxyManager,
|
||||
mpRenderModule,
|
||||
false);
|
||||
|
||||
// Assumes: SystemChildWindow() has CS_OWNDC
|
||||
DeviceHelper::init(GetDC(mpRenderModule->getHWND()),rWindow.GetOutDev(), rSpriteCanvas);
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::disposing()
|
||||
{
|
||||
// release all references
|
||||
mpBackBuffer.reset();
|
||||
mpSurfaceProxyManager.reset();
|
||||
mpRenderModule.reset();
|
||||
mpSpriteCanvas = nullptr;
|
||||
|
||||
DeviceHelper::disposing();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
if( !getDevice() )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
DXSurfaceBitmapSharedPtr pBitmap = std::make_shared<DXSurfaceBitmap>(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
|
||||
mpSurfaceProxyManager,
|
||||
mpRenderModule,
|
||||
false);
|
||||
|
||||
// create a 24bit RGB system memory surface
|
||||
return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& size )
|
||||
{
|
||||
if( !getDevice() )
|
||||
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
||||
|
||||
DXSurfaceBitmapSharedPtr pBitmap = std::make_shared<DXSurfaceBitmap>(
|
||||
::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
|
||||
mpSurfaceProxyManager,
|
||||
mpRenderModule,
|
||||
true);
|
||||
|
||||
// create a 32bit ARGB system memory surface
|
||||
return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
|
||||
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
||||
const geometry::IntegerSize2D& /*size*/ )
|
||||
{
|
||||
return uno::Reference< rendering::XVolatileBitmap >();
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::destroyBuffers()
|
||||
{
|
||||
// TODO(F3): implement XBufferStrategy interface. For now, we
|
||||
// _always_ will have exactly one backbuffer
|
||||
}
|
||||
|
||||
bool SpriteDeviceHelper::showBuffer( bool, bool )
|
||||
{
|
||||
SAL_WARN("canvas.directx", "Not supposed to be called, handled by SpriteCanvas");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpriteDeviceHelper::switchBuffer( bool, bool )
|
||||
{
|
||||
SAL_WARN("canvas.directx", "Not supposed to be called, handled by SpriteCanvas");
|
||||
return false;
|
||||
}
|
||||
|
||||
uno::Any SpriteDeviceHelper::isAccelerated() const
|
||||
{
|
||||
return css::uno::Any(true);
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
|
||||
{
|
||||
// #i60490# ensure backbuffer has sensible minimal size
|
||||
const sal_Int32 x(rBounds.X);
|
||||
const sal_Int32 y(rBounds.Y);
|
||||
const sal_Int32 w(std::max(sal_Int32(1),sal_Int32(rBounds.Width)));
|
||||
const sal_Int32 h(std::max(sal_Int32(1),sal_Int32(rBounds.Height)));
|
||||
|
||||
if( mpRenderModule )
|
||||
mpRenderModule->resize(::basegfx::B2IRange(x,y,x+w,y+h));
|
||||
|
||||
resizeBackBuffer(::basegfx::B2ISize(w,h));
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::resizeBackBuffer( const ::basegfx::B2ISize& rNewSize )
|
||||
{
|
||||
// disposed?
|
||||
if(!mpBackBuffer)
|
||||
return;
|
||||
|
||||
mpBackBuffer->resize(rNewSize);
|
||||
mpBackBuffer->clear();
|
||||
}
|
||||
|
||||
HWND SpriteDeviceHelper::getHwnd() const
|
||||
{
|
||||
if( mpRenderModule )
|
||||
return mpRenderModule->getHWND();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SpriteDeviceHelper::dumpScreenContent() const
|
||||
{
|
||||
if( mpRenderModule )
|
||||
mpRenderModule->screenShot();
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,98 @@
|
||||
/* -*- 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/awt/Rectangle.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||
|
||||
#include "dx_rendermodule.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
#include "dx_devicehelper.hxx"
|
||||
|
||||
#include <rendering/isurfaceproxymanager.hxx>
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class SpriteCanvas;
|
||||
|
||||
class SpriteDeviceHelper : public DeviceHelper
|
||||
{
|
||||
public:
|
||||
SpriteDeviceHelper();
|
||||
|
||||
void init( vcl::Window& rWindow,
|
||||
SpriteCanvas& rSpriteCanvas,
|
||||
const css::awt::Rectangle& rRect,
|
||||
bool bFullscreen );
|
||||
|
||||
/// Dispose all internal references
|
||||
void disposing();
|
||||
|
||||
// partial override XWindowGraphicDevice
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XBitmap > createCompatibleAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
css::uno::Reference< css::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice,
|
||||
const css::geometry::IntegerSize2D& size );
|
||||
|
||||
void destroyBuffers( );
|
||||
bool showBuffer( bool bIsVisible, bool bUpdateAll );
|
||||
bool switchBuffer( bool bIsVisible, bool bUpdateAll );
|
||||
|
||||
const IDXRenderModuleSharedPtr& getRenderModule() const { return mpRenderModule; }
|
||||
const DXSurfaceBitmapSharedPtr& getBackBuffer() const { return mpBackBuffer; }
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager> &getSurfaceProxy() const { return mpSurfaceProxyManager; }
|
||||
|
||||
css::uno::Any isAccelerated() const;
|
||||
|
||||
void notifySizeUpdate( const css::awt::Rectangle& rBounds );
|
||||
|
||||
/** called when DumpScreenContent property is enabled on
|
||||
XGraphicDevice, and writes out bitmaps of current screen.
|
||||
*/
|
||||
void dumpScreenContent() const;
|
||||
|
||||
private:
|
||||
void resizeBackBuffer( const ::basegfx::B2ISize& rNewSize );
|
||||
HWND getHwnd() const;
|
||||
|
||||
/// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
|
||||
SpriteCanvas* mpSpriteCanvas;
|
||||
|
||||
DXSurfaceBitmapSharedPtr mpBackBuffer;
|
||||
|
||||
/// Instance passing out HW textures
|
||||
std::shared_ptr<canvas::ISurfaceProxyManager> mpSurfaceProxyManager;
|
||||
|
||||
/// Our encapsulation interface to DirectX
|
||||
IDXRenderModuleSharedPtr mpRenderModule;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,199 @@
|
||||
/* -*- 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/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
|
||||
#include <basegfx/polygon/b2dpolygontools.hxx>
|
||||
#include <basegfx/polygon/b2dpolygontriangulator.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <rtl/math.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_canvascustomsprite.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_spritehelper.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
SpriteHelper::SpriteHelper() :
|
||||
mpSpriteCanvas(),
|
||||
mpBitmap(),
|
||||
mbTextureDirty( true ),
|
||||
mbShowSpriteBounds( false )
|
||||
{
|
||||
}
|
||||
|
||||
void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
|
||||
const SpriteCanvasRef& rSpriteCanvas,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const DXSurfaceBitmapSharedPtr& rBitmap,
|
||||
bool bShowSpriteBounds )
|
||||
{
|
||||
ENSURE_OR_THROW( rSpriteCanvas &&
|
||||
rRenderModule &&
|
||||
rBitmap,
|
||||
"SpriteHelper::init(): Invalid device, sprite canvas or surface" );
|
||||
|
||||
mpSpriteCanvas = rSpriteCanvas;
|
||||
mpBitmap = rBitmap;
|
||||
mbTextureDirty = true;
|
||||
mbShowSpriteBounds = bShowSpriteBounds;
|
||||
|
||||
// also init base class
|
||||
CanvasCustomSpriteHelper::init( rSpriteSize,
|
||||
rSpriteCanvas );
|
||||
}
|
||||
|
||||
void SpriteHelper::disposing()
|
||||
{
|
||||
mpBitmap.reset();
|
||||
mpSpriteCanvas.clear();
|
||||
|
||||
// forward to parent
|
||||
CanvasCustomSpriteHelper::disposing();
|
||||
}
|
||||
|
||||
::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
|
||||
{
|
||||
return tools::polyPolygonFromXPolyPolygon2D( xPoly );
|
||||
}
|
||||
|
||||
bool SpriteHelper::needRedraw() const
|
||||
{
|
||||
if( !mpBitmap ||
|
||||
!mpSpriteCanvas )
|
||||
{
|
||||
return false; // we're disposed, no redraw necessary
|
||||
}
|
||||
|
||||
if( !isActive() ||
|
||||
::basegfx::fTools::equalZero( getAlpha() ) )
|
||||
{
|
||||
return false; // sprite is invisible
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteHelper::redraw( bool& io_bSurfaceDirty ) const
|
||||
{
|
||||
if( !mpBitmap ||
|
||||
!mpSpriteCanvas )
|
||||
{
|
||||
return; // we're disposed
|
||||
}
|
||||
|
||||
const ::basegfx::B2DPoint& rPos( getPosPixel() );
|
||||
const double fAlpha( getAlpha() );
|
||||
|
||||
if( isActive() &&
|
||||
!::basegfx::fTools::equalZero( fAlpha ) )
|
||||
{
|
||||
|
||||
// TODO(Q2): For the time being, Device does not take a target
|
||||
// surface, but always unconditionally renders to the
|
||||
// background buffer.
|
||||
|
||||
// log output pos in device pixel
|
||||
SAL_INFO("canvas.directx", "SpriteHelper::redraw(): output pos is (" <<
|
||||
rPos.getX() << "," << rPos.getY() << ")" );
|
||||
|
||||
const ::basegfx::B2DVector& rSize( getSizePixel() );
|
||||
const ::basegfx::B2DHomMatrix& rTransform( getTransformation() );
|
||||
const uno::Reference< rendering::XPolyPolygon2D >& xClip( getClip() );
|
||||
|
||||
mbTextureDirty = false;
|
||||
io_bSurfaceDirty = false; // state taken, and processed.
|
||||
|
||||
::basegfx::B2DPolyPolygon aClipPath; // empty for no clip
|
||||
bool bIsClipRectangular( false ); // false, if no
|
||||
// clip, or clip
|
||||
// is complex
|
||||
|
||||
// setup and apply clip (if any)
|
||||
// =================================
|
||||
|
||||
if( xClip.is() )
|
||||
{
|
||||
aClipPath = tools::polyPolygonFromXPolyPolygon2D( xClip );
|
||||
|
||||
const sal_Int32 nNumClipPolygons( aClipPath.count() );
|
||||
if( nNumClipPolygons )
|
||||
{
|
||||
// TODO(P2): hold rectangle attribute directly
|
||||
// at the XPolyPolygon2D
|
||||
|
||||
// check whether the clip is rectangular
|
||||
if( nNumClipPolygons == 1 )
|
||||
if( ::basegfx::utils::isRectangle( aClipPath.getB2DPolygon( 0 ) ) )
|
||||
bIsClipRectangular = true;
|
||||
}
|
||||
}
|
||||
|
||||
const ::basegfx::B2DRectangle aSourceRect( 0.0,
|
||||
0.0,
|
||||
rSize.getX(),
|
||||
rSize.getY() );
|
||||
|
||||
// draw simple rectangular area if no clip is set.
|
||||
if( !aClipPath.count() )
|
||||
{
|
||||
mpBitmap->draw(fAlpha,rPos,rTransform);
|
||||
}
|
||||
else if( bIsClipRectangular )
|
||||
{
|
||||
// apply a simple rect clip
|
||||
// ========================
|
||||
|
||||
::basegfx::B2DRectangle aClipBounds(
|
||||
::basegfx::utils::getRange( aClipPath ) );
|
||||
aClipBounds.intersect( aSourceRect );
|
||||
|
||||
mpBitmap->draw(fAlpha,rPos,aClipBounds,rTransform);
|
||||
}
|
||||
else
|
||||
{
|
||||
// apply clip the hard way
|
||||
// =======================
|
||||
|
||||
mpBitmap->draw(fAlpha,rPos,aClipPath,rTransform);
|
||||
}
|
||||
|
||||
if( mbShowSpriteBounds )
|
||||
{
|
||||
if( aClipPath.count() )
|
||||
{
|
||||
// TODO(F2): Re-enable debug output
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,102 @@
|
||||
/* -*- 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/rendering/XCustomSprite.hpp>
|
||||
|
||||
#include <base/canvascustomspritehelper.hxx>
|
||||
|
||||
#include <basegfx/point/b2dpoint.hxx>
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/* Definition of SpriteHelper class */
|
||||
|
||||
/** Helper class for canvas sprites.
|
||||
|
||||
This class implements all sprite-related functionality, like
|
||||
that available on the XSprite interface.
|
||||
*/
|
||||
class SpriteHelper : public ::canvas::CanvasCustomSpriteHelper
|
||||
{
|
||||
public:
|
||||
/** Create sprite helper
|
||||
*/
|
||||
SpriteHelper();
|
||||
|
||||
/** Late-init the sprite helper
|
||||
|
||||
@param rSpriteSize
|
||||
Size of the sprite
|
||||
|
||||
@param rSpriteCanvas
|
||||
Sprite canvas this sprite is part of. Object stores
|
||||
ref-counted reference to it, thus, don't forget to pass on
|
||||
disposing()!
|
||||
|
||||
@param rRenderModule
|
||||
rendermodule to use
|
||||
|
||||
@param rSpriteSurface
|
||||
The surface of the sprite (not the DX texture, but the
|
||||
persistent target of content rendering)
|
||||
|
||||
@param bShowSpriteBounds
|
||||
When true, little debug bound rects for sprites are shown
|
||||
*/
|
||||
void init( const css::geometry::RealSize2D& rSpriteSize,
|
||||
const SpriteCanvasRef& rSpriteCanvas,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
const DXSurfaceBitmapSharedPtr& rBitmap,
|
||||
bool bShowSpriteBounds );
|
||||
|
||||
void disposing();
|
||||
|
||||
/** Repaint sprite content via hardware to associated sprite
|
||||
canvas
|
||||
|
||||
@param io_bSurfaceDirty
|
||||
Input/output parameter, whether the sprite content is
|
||||
dirty or not. If texture was updated, set to false
|
||||
|
||||
*/
|
||||
void redraw( bool& io_bSurfaceDirty ) const;
|
||||
|
||||
private:
|
||||
virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
|
||||
css::uno::Reference< css::rendering::XPolyPolygon2D >& xPoly ) const override;
|
||||
|
||||
/// Returns true, if the sprite _really_ needs redraw
|
||||
bool needRedraw() const;
|
||||
|
||||
SpriteCanvasRef mpSpriteCanvas;
|
||||
|
||||
DXSurfaceBitmapSharedPtr mpBitmap;
|
||||
mutable bool mbTextureDirty; // when true, texture needs update
|
||||
bool mbShowSpriteBounds; // when true, debug bound rect for sprites is shown
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,654 @@
|
||||
/* -*- 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 <memory>
|
||||
#include <string.h>
|
||||
|
||||
#include <com/sun/star/rendering/ColorComponentTag.hpp>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/range/b2irange.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <rendering/icolorbuffer.hxx>
|
||||
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_surfacebitmap.hxx"
|
||||
#include "dx_surfacegraphics.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
// DXColorBuffer
|
||||
|
||||
|
||||
struct DXColorBuffer : public canvas::IColorBuffer
|
||||
{
|
||||
public:
|
||||
DXColorBuffer( const sal::systools::COMReference<surface_type>& rSurface,
|
||||
const ::basegfx::B2ISize& rSize )
|
||||
: maSize(rSize)
|
||||
, maLockedRect{}
|
||||
, mpSurface(rSurface)
|
||||
{
|
||||
}
|
||||
|
||||
// implementation of the 'IColorBuffer' interface
|
||||
public:
|
||||
|
||||
virtual sal_uInt8* lock() const override;
|
||||
virtual void unlock() const override;
|
||||
virtual sal_uInt32 getWidth() const override;
|
||||
virtual sal_uInt32 getHeight() const override;
|
||||
virtual sal_uInt32 getStride() const override;
|
||||
virtual Format getFormat() const override;
|
||||
|
||||
private:
|
||||
|
||||
::basegfx::B2ISize maSize;
|
||||
mutable D3DLOCKED_RECT maLockedRect;
|
||||
sal::systools::COMReference<surface_type> mpSurface;
|
||||
};
|
||||
|
||||
sal_uInt8* DXColorBuffer::lock() const
|
||||
{
|
||||
if(SUCCEEDED(mpSurface->LockRect(&maLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
return static_cast<sal_uInt8 *>(maLockedRect.pBits);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DXColorBuffer::unlock() const
|
||||
{
|
||||
mpSurface->UnlockRect();
|
||||
}
|
||||
|
||||
sal_uInt32 DXColorBuffer::getWidth() const
|
||||
{
|
||||
return maSize.getWidth();
|
||||
}
|
||||
|
||||
sal_uInt32 DXColorBuffer::getHeight() const
|
||||
{
|
||||
return maSize.getHeight();
|
||||
}
|
||||
|
||||
sal_uInt32 DXColorBuffer::getStride() const
|
||||
{
|
||||
return maLockedRect.Pitch;
|
||||
}
|
||||
|
||||
canvas::IColorBuffer::Format DXColorBuffer::getFormat() const
|
||||
{
|
||||
return canvas::IColorBuffer::Format::X8R8G8B8;
|
||||
}
|
||||
|
||||
|
||||
// GDIColorBuffer
|
||||
|
||||
|
||||
struct GDIColorBuffer : public canvas::IColorBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
GDIColorBuffer( const BitmapSharedPtr& rSurface,
|
||||
const ::basegfx::B2ISize& rSize )
|
||||
: maSize(rSize)
|
||||
, aBmpData{}
|
||||
, mpGDIPlusBitmap(rSurface)
|
||||
{
|
||||
}
|
||||
|
||||
// implementation of the 'IColorBuffer' interface
|
||||
public:
|
||||
|
||||
virtual sal_uInt8* lock() const override;
|
||||
virtual void unlock() const override;
|
||||
virtual sal_uInt32 getWidth() const override;
|
||||
virtual sal_uInt32 getHeight() const override;
|
||||
virtual sal_uInt32 getStride() const override;
|
||||
virtual Format getFormat() const override;
|
||||
|
||||
private:
|
||||
|
||||
::basegfx::B2ISize maSize;
|
||||
mutable Gdiplus::BitmapData aBmpData;
|
||||
BitmapSharedPtr mpGDIPlusBitmap;
|
||||
};
|
||||
|
||||
sal_uInt8* GDIColorBuffer::lock() const
|
||||
{
|
||||
aBmpData.Width = maSize.getWidth();
|
||||
aBmpData.Height = maSize.getHeight();
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = nullptr;
|
||||
const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
|
||||
if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeRead,
|
||||
PixelFormat32bppARGB,
|
||||
&aBmpData ) )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<sal_uInt8*>(aBmpData.Scan0);
|
||||
}
|
||||
|
||||
void GDIColorBuffer::unlock() const
|
||||
{
|
||||
mpGDIPlusBitmap->UnlockBits( &aBmpData );
|
||||
}
|
||||
|
||||
sal_uInt32 GDIColorBuffer::getWidth() const
|
||||
{
|
||||
return maSize.getWidth();
|
||||
}
|
||||
|
||||
sal_uInt32 GDIColorBuffer::getHeight() const
|
||||
{
|
||||
return maSize.getHeight();
|
||||
}
|
||||
|
||||
sal_uInt32 GDIColorBuffer::getStride() const
|
||||
{
|
||||
return aBmpData.Stride;
|
||||
}
|
||||
|
||||
canvas::IColorBuffer::Format GDIColorBuffer::getFormat() const
|
||||
{
|
||||
return canvas::IColorBuffer::Format::A8R8G8B8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::DXSurfaceBitmap
|
||||
|
||||
|
||||
DXSurfaceBitmap::DXSurfaceBitmap( const ::basegfx::B2ISize& rSize,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rMgr,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
bool bWithAlpha ) :
|
||||
mpGdiPlusUser( GDIPlusUser::createInstance() ),
|
||||
maSize(rSize),
|
||||
mpRenderModule(rRenderModule),
|
||||
mpSurfaceManager(rMgr),
|
||||
mpSurfaceProxy(),
|
||||
mpSurface(),
|
||||
mpGDIPlusBitmap(),
|
||||
mpGraphics(),
|
||||
mpColorBuffer(),
|
||||
mbIsSurfaceDirty(true),
|
||||
mbAlpha(bWithAlpha)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::getSize
|
||||
|
||||
|
||||
::basegfx::B2ISize DXSurfaceBitmap::getSize() const
|
||||
{
|
||||
return maSize;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::init
|
||||
|
||||
|
||||
void DXSurfaceBitmap::init()
|
||||
{
|
||||
// create container for pixel data
|
||||
if(mbAlpha)
|
||||
{
|
||||
mpGDIPlusBitmap = std::make_shared<Gdiplus::Bitmap>(
|
||||
maSize.getWidth(),
|
||||
maSize.getHeight(),
|
||||
PixelFormat32bppARGB
|
||||
);
|
||||
mpGraphics = tools::createGraphicsFromBitmap(mpGDIPlusBitmap);
|
||||
|
||||
// create the colorbuffer object, which is basically a simple
|
||||
// wrapper around the directx surface. the colorbuffer is the
|
||||
// interface which is used by the surfaceproxy to support any
|
||||
// kind of underlying structure for the pixel data container.
|
||||
mpColorBuffer = std::make_shared<GDIColorBuffer>(mpGDIPlusBitmap, maSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpSurface = mpRenderModule->createSystemMemorySurface(maSize);
|
||||
|
||||
// create the colorbuffer object, which is basically a simple
|
||||
// wrapper around the directx surface. the colorbuffer is the
|
||||
// interface which is used by the surfaceproxy to support any
|
||||
// kind of underlying structure for the pixel data container.
|
||||
mpColorBuffer = std::make_shared<DXColorBuffer>(mpSurface, maSize);
|
||||
}
|
||||
|
||||
// create a (possibly hardware accelerated) mirror surface.
|
||||
mpSurfaceProxy = mpSurfaceManager->createSurfaceProxy(mpColorBuffer);
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::resize
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::resize(const ::basegfx::B2ISize& rSize)
|
||||
{
|
||||
if(maSize != rSize)
|
||||
{
|
||||
maSize = rSize;
|
||||
init();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::clear
|
||||
|
||||
|
||||
void DXSurfaceBitmap::clear()
|
||||
{
|
||||
GraphicsSharedPtr pGraphics(getGraphics());
|
||||
Gdiplus::Color transColor(255,0,0,0);
|
||||
pGraphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy );
|
||||
pGraphics->Clear( transColor );
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::hasAlpha
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::hasAlpha() const
|
||||
{
|
||||
return mbAlpha;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::getGraphics
|
||||
|
||||
|
||||
GraphicsSharedPtr DXSurfaceBitmap::getGraphics()
|
||||
{
|
||||
// since clients will most probably draw directly
|
||||
// to the GDI+ bitmap, we need to mark it as dirty
|
||||
// to ensure that the corresponding dxsurface will
|
||||
// be updated.
|
||||
mbIsSurfaceDirty = true;
|
||||
|
||||
if(hasAlpha())
|
||||
return mpGraphics;
|
||||
else
|
||||
return createSurfaceGraphics(mpSurface);
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::getBitmap
|
||||
|
||||
|
||||
BitmapSharedPtr DXSurfaceBitmap::getBitmap() const
|
||||
{
|
||||
if(hasAlpha())
|
||||
return mpGDIPlusBitmap;
|
||||
|
||||
BitmapSharedPtr pResult;
|
||||
|
||||
D3DLOCKED_RECT aLockedRect;
|
||||
if(SUCCEEDED(mpSurface->LockRect(&aLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
{
|
||||
// decide about the format we pass the gdi+, the directx surface is always
|
||||
// 32bit, either with or without alpha component.
|
||||
Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
|
||||
|
||||
// construct a gdi+ bitmap from the raw pixel data.
|
||||
pResult = std::make_shared<Gdiplus::Bitmap>(maSize.getWidth(), maSize.getHeight(),
|
||||
aLockedRect.Pitch,
|
||||
nFormat,
|
||||
static_cast<BYTE *>(aLockedRect.pBits) );
|
||||
|
||||
mpSurface->UnlockRect();
|
||||
}
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::draw
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DPolyPolygon& rClipPoly,
|
||||
const ::basegfx::B2DHomMatrix& rTransform )
|
||||
{
|
||||
if( mbIsSurfaceDirty )
|
||||
{
|
||||
mpSurfaceProxy->setColorBufferDirty();
|
||||
mbIsSurfaceDirty = false;
|
||||
}
|
||||
|
||||
return mpSurfaceProxy->draw( fAlpha, rPos, rClipPoly, rTransform );
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::draw
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DRange& rArea,
|
||||
const ::basegfx::B2DHomMatrix& rTransform )
|
||||
{
|
||||
if( mbIsSurfaceDirty )
|
||||
{
|
||||
mpSurfaceProxy->setColorBufferDirty();
|
||||
mbIsSurfaceDirty = false;
|
||||
}
|
||||
|
||||
return mpSurfaceProxy->draw( fAlpha, rPos, rArea, rTransform );
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::draw
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DHomMatrix& rTransform )
|
||||
{
|
||||
if( mbIsSurfaceDirty )
|
||||
{
|
||||
mpSurfaceProxy->setColorBufferDirty();
|
||||
mbIsSurfaceDirty = false;
|
||||
}
|
||||
|
||||
return mpSurfaceProxy->draw( fAlpha, rPos, rTransform );
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::draw
|
||||
|
||||
|
||||
bool DXSurfaceBitmap::draw( const ::basegfx::B2IRange& rArea )
|
||||
{
|
||||
if( mbIsSurfaceDirty )
|
||||
{
|
||||
mpSurfaceProxy->setColorBufferDirty();
|
||||
mbIsSurfaceDirty = false;
|
||||
}
|
||||
|
||||
const double fAlpha(1.0);
|
||||
const ::basegfx::B2DHomMatrix aTransform;
|
||||
const ::basegfx::B2DRange aIEEEArea( rArea );
|
||||
return mpSurfaceProxy->draw(fAlpha,
|
||||
::basegfx::B2DPoint(),
|
||||
aIEEEArea,
|
||||
aTransform);
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::getData
|
||||
|
||||
|
||||
uno::Sequence< sal_Int8 > DXSurfaceBitmap::getData( rendering::IntegerBitmapLayout& rBitmapLayout,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
if(hasAlpha())
|
||||
{
|
||||
uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
|
||||
|
||||
const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = rect.X2-rect.X1;
|
||||
aBmpData.Height = rect.Y2-rect.Y1;
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = aRes.getArray();
|
||||
|
||||
// TODO(F1): Support more pixel formats natively
|
||||
|
||||
// read data from bitmap
|
||||
if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
|
||||
PixelFormat32bppARGB, // TODO(F1): Adapt to
|
||||
// Graphics native
|
||||
// format/change
|
||||
// getMemoryLayout
|
||||
&aBmpData ) )
|
||||
{
|
||||
// failed to lock, bail out
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
}
|
||||
|
||||
mpGDIPlusBitmap->UnlockBits( &aBmpData );
|
||||
|
||||
return aRes;
|
||||
}
|
||||
else
|
||||
{
|
||||
sal_uInt32 nWidth = rect.X2-rect.X1;
|
||||
sal_uInt32 nHeight = rect.Y2-rect.Y1;
|
||||
|
||||
uno::Sequence< sal_Int8 > aRes(nWidth*nHeight*4);
|
||||
|
||||
D3DLOCKED_RECT aLockedRect;
|
||||
if(FAILED(mpSurface->LockRect(&aLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
D3DSURFACE_DESC aDesc;
|
||||
if(FAILED(mpSurface->GetDesc(&aDesc)))
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
|
||||
assert(aDesc.Format == D3DFMT_A8R8G8B8 || aDesc.Format == D3DFMT_X8R8G8B8);
|
||||
|
||||
sal_uInt8 *pSrc = (static_cast<BYTE *>(aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1;
|
||||
sal_uInt8 *pDst = reinterpret_cast<sal_uInt8 *>(aRes.getArray());
|
||||
sal_uInt32 nSegmentSizeInBytes = nWidth*4;
|
||||
for(sal_uInt32 y=0; y<nHeight; ++y)
|
||||
{
|
||||
memcpy(pDst,pSrc,nSegmentSizeInBytes);
|
||||
pDst += nSegmentSizeInBytes;
|
||||
pSrc += aLockedRect.Pitch;
|
||||
}
|
||||
|
||||
if(rBitmapLayout.ColorSpace->getComponentTags().getArray()[0] == rendering::ColorComponentTag::RGB_RED &&
|
||||
rBitmapLayout.ColorSpace->getComponentTags().getArray()[2] == rendering::ColorComponentTag::RGB_BLUE)
|
||||
{
|
||||
pDst = reinterpret_cast<sal_uInt8 *>(aRes.getArray());
|
||||
for(sal_uInt32 y=0; y<nHeight; ++y)
|
||||
{
|
||||
sal_uInt8* pPixel = pDst;
|
||||
for(sal_uInt32 n = 0; n<nWidth; n++)
|
||||
{
|
||||
sal_uInt8 nB = pPixel[0];
|
||||
pPixel[0] = pPixel[2];
|
||||
pPixel[2] = nB;
|
||||
pPixel += 4;
|
||||
}
|
||||
pDst += nSegmentSizeInBytes;
|
||||
}
|
||||
}
|
||||
|
||||
mpSurface->UnlockRect();
|
||||
return aRes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::setData
|
||||
|
||||
|
||||
void DXSurfaceBitmap::setData( const uno::Sequence< sal_Int8 >& data,
|
||||
const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerRectangle2D& rect )
|
||||
{
|
||||
if(hasAlpha())
|
||||
{
|
||||
const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
|
||||
|
||||
Gdiplus::BitmapData aBmpData;
|
||||
aBmpData.Width = rect.X2-rect.X1;
|
||||
aBmpData.Height = rect.Y2-rect.Y1;
|
||||
aBmpData.Stride = 4*aBmpData.Width;
|
||||
aBmpData.PixelFormat = PixelFormat32bppARGB;
|
||||
aBmpData.Scan0 = const_cast<sal_Int8 *>(data.getConstArray());
|
||||
|
||||
// TODO(F1): Support more pixel formats natively
|
||||
|
||||
if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
|
||||
Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
|
||||
PixelFormat32bppARGB, // TODO: Adapt to
|
||||
// Graphics native
|
||||
// format/change
|
||||
// getMemoryLayout
|
||||
&aBmpData ) )
|
||||
{
|
||||
throw uno::RuntimeException("GDIPlus method call was unsuccessful, problem with locking bitmap aRect object");
|
||||
}
|
||||
|
||||
// commit data to bitmap
|
||||
mpGDIPlusBitmap->UnlockBits( &aBmpData );
|
||||
}
|
||||
else
|
||||
{
|
||||
sal_uInt32 nWidth = rect.X2-rect.X1;
|
||||
sal_uInt32 nHeight = rect.Y2-rect.Y1;
|
||||
|
||||
// lock the directx surface to receive the pointer to the surface memory.
|
||||
D3DLOCKED_RECT aLockedRect;
|
||||
if(FAILED(mpSurface->LockRect(&aLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
throw uno::RuntimeException("failed to lock directx surface to surface memory");
|
||||
|
||||
auto* pSrc = data.getConstArray();
|
||||
sal_uInt8 *pDst = (static_cast<BYTE *>(aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1;
|
||||
sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
|
||||
for(sal_uInt32 y=0; y<nHeight; ++y)
|
||||
{
|
||||
memcpy(pDst,pSrc,nSegmentSizeInBytes);
|
||||
pSrc += nSegmentSizeInBytes;
|
||||
pDst += aLockedRect.Pitch;
|
||||
}
|
||||
|
||||
mpSurface->UnlockRect();
|
||||
}
|
||||
|
||||
mbIsSurfaceDirty = true;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::setPixel
|
||||
|
||||
|
||||
void DXSurfaceBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
|
||||
const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
if(hasAlpha())
|
||||
{
|
||||
const geometry::IntegerSize2D aSize( maSize.getWidth(), maSize.getHeight() );
|
||||
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
|
||||
"CanvasHelper::setPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
|
||||
"CanvasHelper::setPixel: Y coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( color.getLength() > 3,
|
||||
"CanvasHelper::setPixel: not enough color components" );
|
||||
|
||||
if( Gdiplus::Ok != mpGDIPlusBitmap->SetPixel( pos.X, pos.Y,
|
||||
Gdiplus::Color( tools::sequenceToArgb( color ))))
|
||||
{
|
||||
throw uno::RuntimeException("Problem with setting the color of bitmap object");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getWidth(),
|
||||
"CanvasHelper::setPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getHeight(),
|
||||
"CanvasHelper::setPixel: Y coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( color.getLength() > 3,
|
||||
"CanvasHelper::setPixel: not enough color components" );
|
||||
|
||||
Gdiplus::Color aColor(tools::sequenceToArgb(color));
|
||||
|
||||
// lock the directx surface to receive the pointer to the surface memory.
|
||||
D3DLOCKED_RECT aLockedRect;
|
||||
if(FAILED(mpSurface->LockRect(&aLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
throw uno::RuntimeException("cannot lock the directx surface to surface memory");
|
||||
|
||||
sal_uInt32 *pDst = reinterpret_cast<sal_uInt32 *>((static_cast<BYTE *>(aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
|
||||
*pDst = aColor.GetValue();
|
||||
mpSurface->UnlockRect();
|
||||
}
|
||||
|
||||
mbIsSurfaceDirty = true;
|
||||
}
|
||||
|
||||
|
||||
// DXSurfaceBitmap::getPixel
|
||||
|
||||
|
||||
uno::Sequence< sal_Int8 > DXSurfaceBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
|
||||
const geometry::IntegerPoint2D& pos )
|
||||
{
|
||||
if(hasAlpha())
|
||||
{
|
||||
const geometry::IntegerSize2D aSize(maSize.getWidth(), maSize.getHeight());
|
||||
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
|
||||
"CanvasHelper::getPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
|
||||
"CanvasHelper::getPixel: Y coordinate out of bounds" );
|
||||
|
||||
Gdiplus::Color aColor;
|
||||
|
||||
if( Gdiplus::Ok != mpGDIPlusBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
|
||||
return uno::Sequence< sal_Int8 >();
|
||||
|
||||
return tools::argbToIntSequence(aColor.GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getWidth(),
|
||||
"CanvasHelper::getPixel: X coordinate out of bounds" );
|
||||
ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getHeight(),
|
||||
"CanvasHelper::getPixel: Y coordinate out of bounds" );
|
||||
|
||||
// lock the directx surface to receive the pointer to the surface memory.
|
||||
D3DLOCKED_RECT aLockedRect;
|
||||
if(FAILED(mpSurface->LockRect(&aLockedRect,nullptr,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
|
||||
throw uno::RuntimeException("failed to lock directX surface to surface memory");
|
||||
|
||||
sal_uInt32 *pDst = reinterpret_cast<sal_uInt32 *>((static_cast<BYTE *>(aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
|
||||
Gdiplus::Color aColor(*pDst);
|
||||
mpSurface->UnlockRect();
|
||||
|
||||
return tools::argbToIntSequence(aColor.GetValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,135 @@
|
||||
/* -*- 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 <rendering/isurfaceproxy.hxx>
|
||||
#include <rendering/isurfaceproxymanager.hxx>
|
||||
#include "dx_ibitmap.hxx"
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
#include "dx_rendermodule.hxx"
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
class DXSurfaceBitmap : public IBitmap
|
||||
{
|
||||
public:
|
||||
DXSurfaceBitmap( const ::basegfx::B2ISize& rSize,
|
||||
const std::shared_ptr<canvas::ISurfaceProxyManager>& rMgr,
|
||||
const IDXRenderModuleSharedPtr& rRenderModule,
|
||||
bool bWithAlpha );
|
||||
|
||||
bool resize(const ::basegfx::B2ISize& rSize);
|
||||
void clear();
|
||||
|
||||
virtual GraphicsSharedPtr getGraphics() override;
|
||||
|
||||
virtual BitmapSharedPtr getBitmap() const override;
|
||||
virtual ::basegfx::B2ISize getSize() const override;
|
||||
virtual bool hasAlpha() const override;
|
||||
|
||||
sal::systools::COMReference<surface_type> getSurface() const { return mpSurface; }
|
||||
|
||||
bool draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DHomMatrix& rTransform );
|
||||
|
||||
bool draw( const ::basegfx::B2IRange& rArea );
|
||||
|
||||
bool draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DRange& rArea,
|
||||
const ::basegfx::B2DHomMatrix& rTransform );
|
||||
|
||||
bool draw( double fAlpha,
|
||||
const ::basegfx::B2DPoint& rPos,
|
||||
const ::basegfx::B2DPolyPolygon& rClipPoly,
|
||||
const ::basegfx::B2DHomMatrix& rTransform );
|
||||
|
||||
virtual css::uno::Sequence< sal_Int8 > getData(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) override;
|
||||
|
||||
virtual void setData(
|
||||
const css::uno::Sequence< sal_Int8 >& data,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerRectangle2D& rect ) override;
|
||||
|
||||
virtual void setPixel(
|
||||
const css::uno::Sequence< sal_Int8 >& color,
|
||||
const css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) override;
|
||||
|
||||
virtual css::uno::Sequence< sal_Int8 > getPixel(
|
||||
css::rendering::IntegerBitmapLayout& bitmapLayout,
|
||||
const css::geometry::IntegerPoint2D& pos ) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
// Refcounted global GDI+ state container
|
||||
GDIPlusUserSharedPtr mpGdiPlusUser;
|
||||
|
||||
// size of this image in pixels [integral unit]
|
||||
::basegfx::B2ISize maSize;
|
||||
|
||||
// pointer to the rendermodule, needed to create surfaces
|
||||
// which are used as container for the actual pixel data.
|
||||
// generally we could use any kind of storage, but GDI+
|
||||
// is not willing to render antialiased fonts unless we
|
||||
// use this special kind of container, don't ask me why...
|
||||
IDXRenderModuleSharedPtr mpRenderModule;
|
||||
|
||||
// pointer to the surface manager, needed in case clients
|
||||
// want to resize the bitmap.
|
||||
std::shared_ptr<canvas::ISurfaceProxyManager> mpSurfaceManager;
|
||||
|
||||
// access point to the surface proxy which handles
|
||||
// the hardware-dependent rendering stuff.
|
||||
std::shared_ptr< canvas::ISurfaceProxy > mpSurfaceProxy;
|
||||
|
||||
// container for pixel data, we need to use a directx
|
||||
// surface since GDI+ sucks...
|
||||
sal::systools::COMReference<surface_type> mpSurface;
|
||||
|
||||
// since GDI+ does not work correctly in case we
|
||||
// run on a 16bit display [don't ask me why] we need
|
||||
// to occasionally render to a native GDI+ bitmap.
|
||||
BitmapSharedPtr mpGDIPlusBitmap;
|
||||
// Graphics for the mpGDIPlusBitmap
|
||||
GraphicsSharedPtr mpGraphics;
|
||||
|
||||
// internal implementation of the iColorBuffer interface
|
||||
std::shared_ptr<canvas::IColorBuffer> mpColorBuffer;
|
||||
|
||||
// indicates whether the associated surface needs
|
||||
// to refresh its contents or not. in other words,
|
||||
// this flag is set iff both representations are
|
||||
// out of sync.
|
||||
mutable bool mbIsSurfaceDirty;
|
||||
|
||||
// true if the bitmap contains an alpha channel
|
||||
bool mbAlpha;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< DXSurfaceBitmap > DXSurfaceBitmapSharedPtr;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -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 "dx_impltools.hxx"
|
||||
#include "dx_surfacegraphics.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct GraphicsDeleter
|
||||
{
|
||||
sal::systools::COMReference<surface_type> mpSurface;
|
||||
HDC maHDC;
|
||||
|
||||
GraphicsDeleter(const sal::systools::COMReference<surface_type>& rSurface, HDC hdc) :
|
||||
mpSurface(rSurface),
|
||||
maHDC(hdc)
|
||||
{}
|
||||
|
||||
void operator()( Gdiplus::Graphics* pGraphics )
|
||||
{
|
||||
if(!pGraphics)
|
||||
return;
|
||||
|
||||
pGraphics->Flush(Gdiplus::FlushIntentionSync);
|
||||
delete pGraphics;
|
||||
|
||||
if(mpSurface.is())
|
||||
mpSurface->ReleaseDC( maHDC );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GraphicsSharedPtr createSurfaceGraphics(const sal::systools::COMReference<surface_type>& rSurface )
|
||||
{
|
||||
GraphicsSharedPtr pRet;
|
||||
HDC aHDC;
|
||||
if( SUCCEEDED(rSurface->GetDC( &aHDC )) )
|
||||
{
|
||||
Gdiplus::Graphics* pGraphics = Gdiplus::Graphics::FromHDC( aHDC );
|
||||
if(pGraphics)
|
||||
{
|
||||
tools::setupGraphics( *pGraphics );
|
||||
pRet.reset(pGraphics,
|
||||
GraphicsDeleter(rSurface, aHDC));
|
||||
return pRet;
|
||||
}
|
||||
else
|
||||
rSurface->ReleaseDC( aHDC );
|
||||
}
|
||||
|
||||
throw uno::RuntimeException("could not get the DC to rSurface");
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -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 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dx_graphicsprovider.hxx"
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
/** Container providing a Gdiplus::Graphics for a Surface
|
||||
|
||||
This wrapper class transparently handles allocation and
|
||||
release of surface resources the RAII way (the
|
||||
GraphicsSharedPtr returned has a deleter that does all the
|
||||
necessary DX cleanup work).
|
||||
*/
|
||||
GraphicsSharedPtr createSurfaceGraphics(const sal::systools::COMReference<surface_type>& rSurface);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,253 @@
|
||||
/* -*- 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/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
|
||||
#include "dx_bitmap.hxx"
|
||||
#include "dx_spritecanvas.hxx"
|
||||
#include "dx_textlayout.hxx"
|
||||
#include "dx_textlayout_drawhelper.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
TextLayout::TextLayout( const rendering::StringContext& aText,
|
||||
sal_Int8 nDirection,
|
||||
sal_Int64 /*nRandomSeed*/,
|
||||
const CanvasFont::ImplRef& rFont ) :
|
||||
TextLayout_Base( m_aMutex ),
|
||||
maText( aText ),
|
||||
maLogicalAdvancements(),
|
||||
mpFont( rFont ),
|
||||
mnTextDirection( nDirection )
|
||||
{
|
||||
}
|
||||
|
||||
TextLayout::~TextLayout()
|
||||
{
|
||||
}
|
||||
|
||||
void SAL_CALL TextLayout::disposing()
|
||||
{
|
||||
mpFont.clear();
|
||||
}
|
||||
|
||||
// XTextLayout
|
||||
uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
|
||||
}
|
||||
|
||||
uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< geometry::RealRectangle2D >();
|
||||
}
|
||||
|
||||
uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( )
|
||||
{
|
||||
// TODO
|
||||
return uno::Sequence< geometry::RealRectangle2D >();
|
||||
}
|
||||
|
||||
uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maLogicalAdvancements;
|
||||
}
|
||||
|
||||
void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
if( aAdvancements.getLength() != maText.Length )
|
||||
{
|
||||
SAL_WARN("canvas.directx", "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
|
||||
throw lang::IllegalArgumentException();
|
||||
}
|
||||
|
||||
maLogicalAdvancements = aAdvancements;
|
||||
}
|
||||
|
||||
uno::Sequence< sal_Bool > SAL_CALL TextLayout::queryKashidaPositions( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maKashidaPositions;
|
||||
}
|
||||
|
||||
void SAL_CALL TextLayout::applyKashidaPositions( const uno::Sequence< sal_Bool >& aPositions )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
if( aPositions.hasElements() && aPositions.getLength() != maText.Length )
|
||||
{
|
||||
SAL_WARN("canvas.directx", "TextLayout::applyKashidaPositions(): mismatching number of positions" );
|
||||
throw lang::IllegalArgumentException("mismatching number of positions", getXWeak(), 1);
|
||||
}
|
||||
|
||||
maKashidaPositions = aPositions;
|
||||
}
|
||||
|
||||
geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
|
||||
::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
|
||||
|
||||
// render text
|
||||
const geometry::RealRectangle2D aBounds(
|
||||
aDrawHelper.queryTextBounds(
|
||||
maText,
|
||||
maLogicalAdvancements,
|
||||
mpFont,
|
||||
mpFont->getFontMatrix()));
|
||||
|
||||
return aBounds;
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::justify( double /*nSize*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
|
||||
double /*nSize*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ )
|
||||
{
|
||||
// TODO
|
||||
return rendering::TextHit();
|
||||
}
|
||||
|
||||
rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
|
||||
sal_Bool /*bExcludeLigatures*/ )
|
||||
{
|
||||
// TODO
|
||||
return rendering::Caret();
|
||||
}
|
||||
|
||||
sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nCaretAdvancement*/,
|
||||
sal_Bool /*bExcludeLigatures*/ )
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nEndIndex*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XPolyPolygon2D >();
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
|
||||
sal_Int32 /*nEndIndex*/ )
|
||||
{
|
||||
// TODO
|
||||
return uno::Reference< rendering::XPolyPolygon2D >();
|
||||
}
|
||||
|
||||
double SAL_CALL TextLayout::getBaselineOffset( )
|
||||
{
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
sal_Int8 SAL_CALL TextLayout::getMainTextDirection( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return mnTextDirection;
|
||||
}
|
||||
|
||||
uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return mpFont;
|
||||
}
|
||||
|
||||
rendering::StringContext SAL_CALL TextLayout::getText( )
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
return maText;
|
||||
}
|
||||
|
||||
bool TextLayout::draw( const GraphicsSharedPtr& rGraphics,
|
||||
const rendering::ViewState& rViewState,
|
||||
const rendering::RenderState& rRenderState,
|
||||
const ::basegfx::B2ISize& rOutputOffset,
|
||||
const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
|
||||
bool bAlphaSurface ) const
|
||||
{
|
||||
::osl::MutexGuard aGuard( m_aMutex );
|
||||
|
||||
::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
|
||||
|
||||
// render text
|
||||
aDrawHelper.drawText(
|
||||
rGraphics,
|
||||
rViewState,
|
||||
rRenderState,
|
||||
rOutputOffset,
|
||||
maText,
|
||||
maLogicalAdvancements,
|
||||
maKashidaPositions,
|
||||
mpFont,
|
||||
mpFont->getFontMatrix(),
|
||||
bAlphaSurface,
|
||||
mnTextDirection != 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
OUString SAL_CALL TextLayout::getImplementationName()
|
||||
{
|
||||
return "DXCanvas::TextLayout";
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL TextLayout::supportsService( const OUString& ServiceName )
|
||||
{
|
||||
return cppu::supportsService( this, ServiceName );
|
||||
}
|
||||
|
||||
uno::Sequence< OUString > SAL_CALL TextLayout::getSupportedServiceNames()
|
||||
{
|
||||
return { "com.sun.star.rendering.TextLayout" };
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,107 @@
|
||||
/* -*- 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 <cppuhelper/basemutex.hxx>
|
||||
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
|
||||
#include <com/sun/star/rendering/XTextLayout.hpp>
|
||||
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_ibitmap.hxx"
|
||||
#include "dx_winstuff.hxx"
|
||||
#include "dx_gdiplususer.hxx"
|
||||
|
||||
|
||||
/* Definition of TextLayout class */
|
||||
namespace dxcanvas
|
||||
{
|
||||
typedef ::cppu::WeakComponentImplHelper< css::rendering::XTextLayout,
|
||||
css::lang::XServiceInfo > TextLayout_Base;
|
||||
|
||||
class TextLayout : public ::cppu::BaseMutex,
|
||||
public TextLayout_Base
|
||||
{
|
||||
public:
|
||||
TextLayout( const css::rendering::StringContext& aText,
|
||||
sal_Int8 nDirection,
|
||||
sal_Int64 nRandomSeed,
|
||||
const CanvasFont::ImplRef& rFont );
|
||||
/// make noncopyable
|
||||
TextLayout(const TextLayout&) = delete;
|
||||
const TextLayout& operator=(const TextLayout&) = delete;
|
||||
|
||||
/// Dispose all internal references
|
||||
virtual void SAL_CALL disposing() override;
|
||||
|
||||
// XTextLayout
|
||||
virtual css::uno::Sequence< css::uno::Reference< css::rendering::XPolyPolygon2D > > SAL_CALL queryTextShapes( ) override;
|
||||
virtual css::uno::Sequence< css::geometry::RealRectangle2D > SAL_CALL queryInkMeasures( ) override;
|
||||
virtual css::uno::Sequence< css::geometry::RealRectangle2D > SAL_CALL queryMeasures( ) override;
|
||||
virtual css::uno::Sequence< double > SAL_CALL queryLogicalAdvancements( ) override;
|
||||
virtual void SAL_CALL applyLogicalAdvancements( const css::uno::Sequence< double >& aAdvancements ) override;
|
||||
virtual css::uno::Sequence< sal_Bool > SAL_CALL queryKashidaPositions( ) override;
|
||||
virtual void SAL_CALL applyKashidaPositions( const css::uno::Sequence< sal_Bool >& aPositions ) override;
|
||||
virtual css::geometry::RealRectangle2D SAL_CALL queryTextBounds( ) override;
|
||||
virtual double SAL_CALL justify( double nSize ) override;
|
||||
virtual double SAL_CALL combinedJustify( const css::uno::Sequence< css::uno::Reference< css::rendering::XTextLayout > >& aNextLayouts, double nSize ) override;
|
||||
virtual css::rendering::TextHit SAL_CALL getTextHit( const css::geometry::RealPoint2D& aHitPoint ) override;
|
||||
virtual css::rendering::Caret SAL_CALL getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) override;
|
||||
virtual sal_Int32 SAL_CALL getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) override;
|
||||
virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
|
||||
virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
|
||||
virtual double SAL_CALL getBaselineOffset( ) override;
|
||||
virtual sal_Int8 SAL_CALL getMainTextDirection( ) override;
|
||||
virtual css::uno::Reference< css::rendering::XCanvasFont > SAL_CALL getFont( ) override;
|
||||
virtual css::rendering::StringContext SAL_CALL getText( ) 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;
|
||||
|
||||
bool draw( const GraphicsSharedPtr& rGraphics,
|
||||
const css::rendering::ViewState& rViewState,
|
||||
const css::rendering::RenderState& rRenderState,
|
||||
const ::basegfx::B2ISize& rOutputOffset,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XGraphicDevice >& xGraphicDevice,
|
||||
bool bAlphaSurface ) const;
|
||||
|
||||
protected:
|
||||
~TextLayout() override; // we're a ref-counted UNO class. _We_ destroy ourselves.
|
||||
|
||||
private:
|
||||
// NOTE: no need for GDIPlusUserSharedPtr, mpFont implicitly has one already
|
||||
|
||||
css::rendering::StringContext maText;
|
||||
css::uno::Sequence< double > maLogicalAdvancements;
|
||||
css::uno::Sequence< sal_Bool > maKashidaPositions;
|
||||
CanvasFont::ImplRef mpFont;
|
||||
sal_Int8 mnTextDirection;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,312 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
||||
#include <basegfx/utils/canvastools.hxx>
|
||||
#include <com/sun/star/rendering/FontRequest.hpp>
|
||||
#include <com/sun/star/rendering/PanoseProportion.hpp>
|
||||
#include <com/sun/star/rendering/XCanvasFont.hpp>
|
||||
#include <comphelper/scopeguard.hxx>
|
||||
#include <i18nlangtag/languagetag.hxx>
|
||||
#include <rtl/math.hxx>
|
||||
#include <tools/color.hxx>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <tools/poly.hxx>
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <vcl/kernarray.hxx>
|
||||
#include <vcl/metric.hxx>
|
||||
#include <vcl/sysdata.hxx>
|
||||
#include <vcl/virdev.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
#include "dx_bitmap.hxx"
|
||||
#include "dx_canvasfont.hxx"
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_textlayout_drawhelper.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
TextLayoutDrawHelper::TextLayoutDrawHelper(
|
||||
const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice ) :
|
||||
mxGraphicDevice(xGraphicDevice)
|
||||
{
|
||||
}
|
||||
|
||||
TextLayoutDrawHelper::~TextLayoutDrawHelper()
|
||||
{
|
||||
}
|
||||
|
||||
void TextLayoutDrawHelper::drawText(
|
||||
const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
|
||||
const css::rendering::ViewState& rViewState,
|
||||
const css::rendering::RenderState& rRenderState,
|
||||
const ::basegfx::B2ISize& rOutputOffset,
|
||||
const css::rendering::StringContext& rText,
|
||||
const css::uno::Sequence< double >& rLogicalAdvancements,
|
||||
const css::uno::Sequence< sal_Bool >& rKashidaPositions,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XCanvasFont >& rCanvasFont,
|
||||
const css::geometry::Matrix2D& rFontMatrix,
|
||||
bool bAlphaSurface,
|
||||
bool bIsRTL)
|
||||
{
|
||||
HDC hdc = rGraphics->GetHDC();
|
||||
|
||||
// issue a ReleaseHDC() when leaving the scope
|
||||
const ::comphelper::ScopeGuard aGuard(
|
||||
[&rGraphics, &hdc]() mutable { rGraphics->ReleaseHDC(hdc); } );
|
||||
|
||||
SystemGraphicsData aSystemGraphicsData;
|
||||
aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
|
||||
aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(hdc);
|
||||
ScopedVclPtrInstance<VirtualDevice> xVirtualDevice(aSystemGraphicsData, Size(1, 1), DeviceFormat::WITHOUT_ALPHA);
|
||||
|
||||
// disable font antialiasing - GDI does not handle alpha
|
||||
// surfaces properly.
|
||||
if( bAlphaSurface )
|
||||
xVirtualDevice->SetAntialiasing(AntialiasingFlags::DisableText);
|
||||
|
||||
if(rText.Length)
|
||||
{
|
||||
bool test = mxGraphicDevice.is();
|
||||
ENSURE_OR_THROW( test,
|
||||
"TextLayoutDrawHelper::drawText(): Invalid GraphicDevice" );
|
||||
|
||||
// set text color. Make sure to remove transparence part first.
|
||||
Color aColor( COL_WHITE );
|
||||
|
||||
if( rRenderState.DeviceColor.getLength() > 2 )
|
||||
aColor = vcl::unotools::doubleSequenceToColor(
|
||||
rRenderState.DeviceColor,
|
||||
mxGraphicDevice->getDeviceColorSpace());
|
||||
aColor.SetAlpha(255);
|
||||
xVirtualDevice->SetTextColor(aColor);
|
||||
|
||||
// create the font
|
||||
const css::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
|
||||
vcl::Font aFont(
|
||||
rFontRequest.FontDescription.FamilyName,
|
||||
rFontRequest.FontDescription.StyleName,
|
||||
Size( 0, ::basegfx::fround<::tools::Long>(rFontRequest.CellSize)));
|
||||
|
||||
aFont.SetAlignment( ALIGN_BASELINE );
|
||||
aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==css::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
|
||||
aFont.SetVertical( rFontRequest.FontDescription.IsVertical==css::util::TriState_YES );
|
||||
aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
|
||||
aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
|
||||
aFont.SetPitch(
|
||||
rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
|
||||
? PITCH_FIXED : PITCH_VARIABLE);
|
||||
|
||||
aFont.SetLanguage(LanguageTag::convertToLanguageType(rFontRequest.Locale));
|
||||
|
||||
// setup font color
|
||||
aFont.SetColor( aColor );
|
||||
aFont.SetFillColor( aColor );
|
||||
|
||||
CanvasFont::ImplRef pFont(tools::canvasFontFromXFont(rCanvasFont));
|
||||
if (pFont.is() && pFont->getEmphasisMark())
|
||||
aFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark()));
|
||||
|
||||
// adjust to stretched font
|
||||
if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
|
||||
{
|
||||
const Size aSize = xVirtualDevice->GetFontMetric( aFont ).GetFontSize();
|
||||
const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
|
||||
double fStretch = rFontMatrix.m00 + rFontMatrix.m01;
|
||||
|
||||
if( !::basegfx::fTools::equalZero( fDividend) )
|
||||
fStretch /= fDividend;
|
||||
|
||||
const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
|
||||
|
||||
aFont.SetAverageFontWidth( nNewWidth );
|
||||
}
|
||||
|
||||
// set font
|
||||
xVirtualDevice->SetFont(aFont);
|
||||
|
||||
// create world transformation matrix
|
||||
::basegfx::B2DHomMatrix aWorldTransform;
|
||||
::canvas::tools::mergeViewAndRenderTransform(aWorldTransform, rViewState, rRenderState);
|
||||
|
||||
if(!rOutputOffset.equalZero())
|
||||
{
|
||||
aWorldTransform.translate(rOutputOffset.getWidth(), rOutputOffset.getHeight());
|
||||
}
|
||||
|
||||
// set ViewState clipping
|
||||
if(rViewState.Clip.is())
|
||||
{
|
||||
::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rViewState.Clip));
|
||||
::basegfx::B2DHomMatrix aMatrix;
|
||||
::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, rViewState.AffineTransform );
|
||||
|
||||
if(!rOutputOffset.equalZero())
|
||||
{
|
||||
aMatrix.translate(rOutputOffset.getWidth(), rOutputOffset.getHeight());
|
||||
}
|
||||
|
||||
aClipPoly.transform(aMatrix);
|
||||
const vcl::Region& rClipRegion = vcl::Region(::tools::PolyPolygon(aClipPoly));
|
||||
xVirtualDevice->IntersectClipRegion(rClipRegion);
|
||||
}
|
||||
|
||||
if(rRenderState.Clip.is())
|
||||
{
|
||||
::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rRenderState.Clip));
|
||||
aClipPoly.transform(aWorldTransform);
|
||||
const vcl::Region& rClipRegion = vcl::Region(::tools::PolyPolygon(aClipPoly));
|
||||
xVirtualDevice->IntersectClipRegion(rClipRegion);
|
||||
}
|
||||
|
||||
// set world transform
|
||||
XFORM aXForm;
|
||||
aXForm.eM11 = static_cast<FLOAT>(aWorldTransform.get(0, 0));
|
||||
aXForm.eM12 = static_cast<FLOAT>(aWorldTransform.get(1, 0));
|
||||
aXForm.eM21 = static_cast<FLOAT>(aWorldTransform.get(0, 1));
|
||||
aXForm.eM22 = static_cast<FLOAT>(aWorldTransform.get(1, 1));
|
||||
aXForm.eDx = static_cast<FLOAT>(aWorldTransform.get(0, 2));
|
||||
aXForm.eDy = static_cast<FLOAT>(aWorldTransform.get(1, 2));
|
||||
|
||||
// TODO(F3): This is NOT supported on 95/98/ME!
|
||||
SetGraphicsMode(hdc, GM_ADVANCED);
|
||||
SetTextAlign(hdc, TA_BASELINE);
|
||||
SetWorldTransform(hdc, &aXForm);
|
||||
|
||||
// use an empty StartPosition for text rendering
|
||||
const Point aEmptyPoint(0, 0);
|
||||
|
||||
// create the String
|
||||
const OUString aText(rText.Text);
|
||||
|
||||
if( rLogicalAdvancements.getLength() )
|
||||
{
|
||||
// create the DXArray
|
||||
KernArraySpan DXArray( rLogicalAdvancements.getConstArray(), rLogicalAdvancements.getLength() );
|
||||
std::span<const sal_Bool> aKashidaArray(rKashidaPositions.getConstArray(), rKashidaPositions.getLength());
|
||||
|
||||
// draw the String
|
||||
xVirtualDevice->DrawTextArray( aEmptyPoint,
|
||||
aText,
|
||||
DXArray,
|
||||
aKashidaArray,
|
||||
rText.StartPosition,
|
||||
rText.Length,
|
||||
bIsRTL ? SalLayoutFlags::BiDiRtl : SalLayoutFlags::NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw the String
|
||||
xVirtualDevice->DrawText( aEmptyPoint,
|
||||
aText,
|
||||
rText.StartPosition,
|
||||
rText.Length );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
geometry::RealRectangle2D TextLayoutDrawHelper::queryTextBounds( const rendering::StringContext& rText,
|
||||
const uno::Sequence< double >& rLogicalAdvancements,
|
||||
const uno::Reference< rendering::XCanvasFont >& rCanvasFont,
|
||||
const geometry::Matrix2D& rFontMatrix )
|
||||
{
|
||||
if(!(rText.Length))
|
||||
return geometry::RealRectangle2D();
|
||||
|
||||
// TODO(F1): Fetching default screen DC here, will yield wrong
|
||||
// metrics when e.g. formatting for a printer!
|
||||
SystemGraphicsData aSystemGraphicsData;
|
||||
aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
|
||||
aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(GetDC( nullptr ));
|
||||
ScopedVclPtrInstance<VirtualDevice> xVirtualDevice(aSystemGraphicsData, Size(1, 1), DeviceFormat::WITHOUT_ALPHA);
|
||||
|
||||
// create the font
|
||||
const css::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
|
||||
vcl::Font aFont(
|
||||
rFontRequest.FontDescription.FamilyName,
|
||||
rFontRequest.FontDescription.StyleName,
|
||||
Size( 0, ::basegfx::fround<::tools::Long>(rFontRequest.CellSize)));
|
||||
|
||||
aFont.SetAlignment( ALIGN_BASELINE );
|
||||
aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==css::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
|
||||
aFont.SetVertical( rFontRequest.FontDescription.IsVertical==css::util::TriState_YES );
|
||||
aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
|
||||
aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
|
||||
aFont.SetPitch(
|
||||
rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
|
||||
? PITCH_FIXED : PITCH_VARIABLE);
|
||||
|
||||
// adjust to stretched font
|
||||
if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
|
||||
{
|
||||
const Size aSize = xVirtualDevice->GetFontMetric( aFont ).GetFontSize();
|
||||
const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
|
||||
double fStretch = rFontMatrix.m00 + rFontMatrix.m01;
|
||||
|
||||
if( !::basegfx::fTools::equalZero( fDividend) )
|
||||
fStretch /= fDividend;
|
||||
|
||||
const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
|
||||
|
||||
aFont.SetAverageFontWidth( nNewWidth );
|
||||
}
|
||||
|
||||
CanvasFont::ImplRef pFont(tools::canvasFontFromXFont(rCanvasFont));
|
||||
if (pFont.is() && pFont->getEmphasisMark())
|
||||
aFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark()));
|
||||
|
||||
// set font
|
||||
xVirtualDevice->SetFont(aFont);
|
||||
|
||||
// need metrics for Y offset, the XCanvas always renders
|
||||
// relative to baseline
|
||||
const ::FontMetric& aMetric( xVirtualDevice->GetFontMetric() );
|
||||
|
||||
const sal_Int32 nAboveBaseline( -aMetric.GetInternalLeading() - aMetric.GetAscent() );
|
||||
const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
|
||||
|
||||
if( rLogicalAdvancements.getLength() )
|
||||
{
|
||||
return geometry::RealRectangle2D( 0, nAboveBaseline,
|
||||
rLogicalAdvancements[ rLogicalAdvancements.getLength()-1 ],
|
||||
nBelowBaseline );
|
||||
}
|
||||
else
|
||||
{
|
||||
return geometry::RealRectangle2D( 0, nAboveBaseline,
|
||||
xVirtualDevice->GetTextWidth(
|
||||
rText.Text,
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(rText.StartPosition),
|
||||
::canvas::tools::numeric_cast<sal_uInt16>(rText.Length) ),
|
||||
nBelowBaseline );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,78 @@
|
||||
/* -*- 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 <memory>
|
||||
|
||||
#include <com/sun/star/uno/Sequence.hxx>
|
||||
#include <com/sun/star/rendering/StringContext.hpp>
|
||||
#include <com/sun/star/rendering/XCanvasFont.hpp>
|
||||
#include <com/sun/star/geometry/Matrix2D.hpp>
|
||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||
#include <com/sun/star/rendering/ViewState.hpp>
|
||||
#include <com/sun/star/rendering/RenderState.hpp>
|
||||
|
||||
#include <basegfx/vector/b2isize.hxx>
|
||||
|
||||
namespace com::sun::star::rendering { class XCanvasFont; }
|
||||
|
||||
namespace Gdiplus { class Graphics; }
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
struct Bitmap;
|
||||
class TextLayoutDrawHelper
|
||||
{
|
||||
public:
|
||||
explicit TextLayoutDrawHelper(
|
||||
const css::uno::Reference< css::rendering::XGraphicDevice >& xGraphicDevice);
|
||||
~TextLayoutDrawHelper();
|
||||
|
||||
// draw text
|
||||
void drawText( const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
|
||||
const css::rendering::ViewState& rViewState,
|
||||
const css::rendering::RenderState& rRenderState,
|
||||
const ::basegfx::B2ISize& rOutputOffset,
|
||||
const css::rendering::StringContext& rText,
|
||||
const css::uno::Sequence< double >& rLogicalAdvancements,
|
||||
const css::uno::Sequence< sal_Bool >& rKashidaPositions,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XCanvasFont >& rCanvasFont,
|
||||
const css::geometry::Matrix2D& rFontMatrix,
|
||||
bool bAlphaSurface,
|
||||
bool bIsRTL);
|
||||
|
||||
css::geometry::RealRectangle2D queryTextBounds(
|
||||
const css::rendering::StringContext& rText,
|
||||
const css::uno::Sequence< double >& rLogicalAdvancements,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XCanvasFont >& rCanvasFont,
|
||||
const css::geometry::Matrix2D& rFontMatrix );
|
||||
|
||||
#ifdef DBG_UTIL
|
||||
void test();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
css::uno::Reference< css::rendering::XGraphicDevice > mxGraphicDevice;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,309 @@
|
||||
/* -*- 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/lang/XServiceInfo.hpp>
|
||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||
#include <comphelper/diagnose_ex.hxx>
|
||||
#include <vcl/bitmap.hxx>
|
||||
#include <vcl/bitmapex.hxx>
|
||||
#include <vcl/BitmapReadAccess.hxx>
|
||||
#include <vcl/canvastools.hxx>
|
||||
|
||||
#include "dx_impltools.hxx"
|
||||
#include "dx_vcltools.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace dxcanvas::tools
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/// Calc number of colors in given BitmapInfoHeader
|
||||
sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
|
||||
{
|
||||
if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
|
||||
{
|
||||
if( rBIH.biBitCount <= 8 )
|
||||
{
|
||||
if( rBIH.biClrUsed )
|
||||
return rBIH.biClrUsed;
|
||||
else
|
||||
return 1 << rBIH.biBitCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BITMAPCOREHEADER const * pCoreHeader = reinterpret_cast<BITMAPCOREHEADER const *>(&rBIH);
|
||||
|
||||
if( pCoreHeader->bcBitCount <= 8 )
|
||||
return 1 << pCoreHeader->bcBitCount;
|
||||
}
|
||||
|
||||
return 0; // nothing known
|
||||
}
|
||||
|
||||
/// Draw DI bits to given Graphics
|
||||
bool drawDIBits( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const void* hDIB )
|
||||
{
|
||||
bool bRet( false );
|
||||
|
||||
const BITMAPINFO* pBI = static_cast<BITMAPINFO*>(GlobalLock( const_cast<void *>(hDIB) ));
|
||||
|
||||
if( pBI )
|
||||
{
|
||||
const BYTE* pBits = reinterpret_cast<BYTE const *>(pBI) + pBI->bmiHeader.biSize +
|
||||
calcDIBColorCount( pBI->bmiHeader ) * sizeof( RGBQUAD );
|
||||
|
||||
// forward to outsourced GDI+ rendering method
|
||||
// (header clashes)
|
||||
bRet = tools::drawDIBits( rGraphics, *pBI, pBits );
|
||||
|
||||
GlobalUnlock( const_cast<void *>(hDIB) );
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/** Draw VCL bitmap to given Graphics
|
||||
|
||||
@param rBmp
|
||||
Reference to bitmap. Might get modified, in such a way
|
||||
that it will hold a DIB after a successful function call.
|
||||
*/
|
||||
bool drawVCLBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
::Bitmap& rBmp )
|
||||
{
|
||||
BitmapSystemData aBmpSysData;
|
||||
|
||||
if( !rBmp.GetSystemData( aBmpSysData ) ||
|
||||
!aBmpSysData.pDIB )
|
||||
{
|
||||
// first of all, ensure that Bitmap contains a DIB, by
|
||||
// acquiring a read access
|
||||
BitmapScopedReadAccess pReadAcc(rBmp);
|
||||
|
||||
// TODO(P2): Acquiring a read access can actually
|
||||
// force a read from VRAM, thus, avoiding this
|
||||
// step somehow will increase performance
|
||||
// here.
|
||||
if( pReadAcc )
|
||||
{
|
||||
// try again: now, WinSalBitmap must have
|
||||
// generated a DIB
|
||||
if( rBmp.GetSystemData( aBmpSysData ) &&
|
||||
aBmpSysData.pDIB )
|
||||
{
|
||||
return drawDIBits( rGraphics,
|
||||
aBmpSysData.pDIB );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return drawDIBits( rGraphics,
|
||||
aBmpSysData.pDIB );
|
||||
}
|
||||
|
||||
// failed to generate DIBits from vcl bitmap
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BitmapEx
|
||||
*/
|
||||
RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
|
||||
{
|
||||
// TODO(P2): Avoid temporary bitmap generation, maybe
|
||||
// even ensure that created DIBs are copied back to
|
||||
// BmpEx (currently, every AcquireReadAccess() will
|
||||
// make the local bitmap copy unique, effectively
|
||||
// duplicating the memory used)
|
||||
|
||||
ENSURE_OR_THROW( rBmpEx.IsAlpha(),
|
||||
"::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
|
||||
"BmpEx has no alpha" );
|
||||
|
||||
// convert transparent bitmap to 32bit RGBA
|
||||
// ========================================
|
||||
|
||||
const ::Size aBmpSize( rBmpEx.GetSizePixel() );
|
||||
|
||||
RawRGBABitmap aBmpData;
|
||||
aBmpData.mnWidth = aBmpSize.Width();
|
||||
aBmpData.mnHeight = aBmpSize.Height();
|
||||
aBmpData.maBitmapData.resize(4*aBmpData.mnWidth*aBmpData.mnHeight);
|
||||
|
||||
Bitmap aBitmap( rBmpEx.GetBitmap() );
|
||||
|
||||
BitmapScopedReadAccess pReadAccess( aBitmap );
|
||||
|
||||
const sal_Int32 nWidth( aBmpSize.Width() );
|
||||
const sal_Int32 nHeight( aBmpSize.Height() );
|
||||
|
||||
ENSURE_OR_THROW( pReadAccess.get() != nullptr,
|
||||
"::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
|
||||
"Unable to acquire read access to bitmap" );
|
||||
|
||||
Bitmap aAlpha( rBmpEx.GetAlphaMask().GetBitmap() );
|
||||
|
||||
BitmapScopedReadAccess pAlphaReadAccess( aAlpha );
|
||||
|
||||
// By convention, the access buffer always has
|
||||
// one of the following formats:
|
||||
|
||||
// ScanlineFormat::N1BitMsbPal
|
||||
// ScanlineFormat::N8BitPal
|
||||
// ScanlineFormat::N24BitTcBgr
|
||||
|
||||
// and is always ScanlineFormat::BottomUp
|
||||
|
||||
// This is the way
|
||||
// WinSalBitmap::AcquireBuffer() sets up the
|
||||
// buffer
|
||||
|
||||
ENSURE_OR_THROW( pAlphaReadAccess.get() != nullptr,
|
||||
"::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
|
||||
"Unable to acquire read access to alpha" );
|
||||
|
||||
ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal,
|
||||
"::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
|
||||
"Unsupported alpha scanline format" );
|
||||
|
||||
BitmapColor aCol;
|
||||
sal_uInt8* pCurrOutput(aBmpData.maBitmapData.data());
|
||||
int x, y;
|
||||
|
||||
for( y=0; y<nHeight; ++y )
|
||||
{
|
||||
switch( pReadAccess->GetScanlineFormat() )
|
||||
{
|
||||
case ScanlineFormat::N8BitPal:
|
||||
{
|
||||
Scanline pScan = pReadAccess->GetScanline( y );
|
||||
Scanline pAScan = pAlphaReadAccess->GetScanline( y );
|
||||
|
||||
for( x=0; x<nWidth; ++x )
|
||||
{
|
||||
aCol = pReadAccess->GetPaletteColor( *pScan++ );
|
||||
|
||||
*pCurrOutput++ = aCol.GetBlue();
|
||||
*pCurrOutput++ = aCol.GetGreen();
|
||||
*pCurrOutput++ = aCol.GetRed();
|
||||
*pCurrOutput++ = static_cast<BYTE>(*pAScan++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ScanlineFormat::N24BitTcBgr:
|
||||
{
|
||||
Scanline pScan = pReadAccess->GetScanline( y );
|
||||
Scanline pAScan = pAlphaReadAccess->GetScanline( y );
|
||||
|
||||
for( x=0; x<nWidth; ++x )
|
||||
{
|
||||
// store as RGBA
|
||||
*pCurrOutput++ = *pScan++;
|
||||
*pCurrOutput++ = *pScan++;
|
||||
*pCurrOutput++ = *pScan++;
|
||||
*pCurrOutput++ = static_cast<BYTE>(*pAScan++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// TODO(P2): Might be advantageous
|
||||
// to hand-formulate the following
|
||||
// formats, too.
|
||||
case ScanlineFormat::N1BitMsbPal:
|
||||
{
|
||||
Scanline pAScan = pAlphaReadAccess->GetScanline( y );
|
||||
|
||||
// using fallback for those
|
||||
// seldom formats
|
||||
for( x=0; x<nWidth; ++x )
|
||||
{
|
||||
// yes. x and y are swapped on Get/SetPixel
|
||||
aCol = pReadAccess->GetColor(y,x);
|
||||
|
||||
*pCurrOutput++ = aCol.GetBlue();
|
||||
*pCurrOutput++ = aCol.GetGreen();
|
||||
*pCurrOutput++ = aCol.GetRed();
|
||||
*pCurrOutput++ = static_cast<BYTE>(*pAScan++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ScanlineFormat::N24BitTcRgb:
|
||||
case ScanlineFormat::N32BitTcAbgr:
|
||||
case ScanlineFormat::N32BitTcArgb:
|
||||
case ScanlineFormat::N32BitTcBgra:
|
||||
case ScanlineFormat::N32BitTcRgba:
|
||||
case ScanlineFormat::N32BitTcXbgr:
|
||||
case ScanlineFormat::N32BitTcXrgb:
|
||||
case ScanlineFormat::N32BitTcBgrx:
|
||||
case ScanlineFormat::N32BitTcRgbx:
|
||||
default:
|
||||
ENSURE_OR_THROW( false,
|
||||
"::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
|
||||
"Unexpected scanline format - has "
|
||||
"WinSalBitmap::AcquireBuffer() changed?" );
|
||||
}
|
||||
}
|
||||
|
||||
return aBmpData;
|
||||
}
|
||||
|
||||
bool drawVCLBitmapEx( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const ::BitmapEx& rBmpEx )
|
||||
{
|
||||
if( !rBmpEx.IsAlpha() )
|
||||
{
|
||||
Bitmap aBmp( rBmpEx.GetBitmap() );
|
||||
return drawVCLBitmap( rGraphics, aBmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
return drawRGBABits( rGraphics,
|
||||
bitmapFromVCLBitmapEx( rBmpEx ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool drawVCLBitmapFromXBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const uno::Reference< rendering::XBitmap >& xBitmap )
|
||||
{
|
||||
// TODO(F2): add support for floating point bitmap formats
|
||||
uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
|
||||
xBitmap, uno::UNO_QUERY );
|
||||
|
||||
if( !xIntBmp.is() )
|
||||
return false;
|
||||
|
||||
::BitmapEx aBmpEx = vcl::unotools::bitmapExFromXBitmap( xIntBmp );
|
||||
if( aBmpEx.IsEmpty() )
|
||||
return false;
|
||||
|
||||
return drawVCLBitmapEx( rGraphics, aBmpEx );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,47 @@
|
||||
/* -*- 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/Reference.hxx>
|
||||
#include <com/sun/star/rendering/XBitmap.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Gdiplus { class Graphics; }
|
||||
|
||||
namespace dxcanvas::tools
|
||||
{
|
||||
/** Raw RGBA bitmap data,
|
||||
contiguous in memory
|
||||
*/
|
||||
struct RawRGBABitmap
|
||||
{
|
||||
sal_Int32 mnWidth;
|
||||
sal_Int32 mnHeight;
|
||||
std::vector<sal_uInt8> maBitmapData;
|
||||
};
|
||||
|
||||
bool drawVCLBitmapFromXBitmap( const std::shared_ptr< Gdiplus::Graphics >& rGraphics,
|
||||
const css::uno::Reference<
|
||||
css::rendering::XBitmap >& xBitmap );
|
||||
}
|
||||
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,71 @@
|
||||
/* -*- 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 <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
|
||||
#include <prewin.h>
|
||||
|
||||
// Enabling Direct3D Debug Information Further more, with registry key
|
||||
// \\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Direct3D\D3D9Debugging\\EnableCreationStack
|
||||
// set to 1, sets a backtrace each time an object is created to the
|
||||
// following global variable: LPCWSTR CreationCallStack
|
||||
#if OSL_DEBUG_LEVEL > 0
|
||||
# define D3D_DEBUG_INFO
|
||||
#endif
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
typedef IDirect3DSurface9 surface_type;
|
||||
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#include <gdiplus.h>
|
||||
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
|
||||
namespace dxcanvas
|
||||
{
|
||||
// some shared pointer typedefs to Gdiplus objects
|
||||
typedef std::shared_ptr< Gdiplus::Graphics > GraphicsSharedPtr;
|
||||
typedef std::shared_ptr< Gdiplus::GraphicsPath > GraphicsPathSharedPtr;
|
||||
typedef std::shared_ptr< Gdiplus::Bitmap > BitmapSharedPtr;
|
||||
typedef std::shared_ptr< Gdiplus::Font > FontSharedPtr;
|
||||
typedef std::shared_ptr< Gdiplus::TextureBrush > TextureBrushSharedPtr;
|
||||
}
|
||||
|
||||
#include <systools/win32/comtools.hxx> // for COMReference; must be inside prewin...postwin
|
||||
// Attention! All DirectX factory methods return the created interfaces pre-acquired, into a raw
|
||||
// pointer. Do not call AddRef on them when constructing COMReference!
|
||||
|
||||
#include <postwin.h>
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* 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 .
|
||||
-->
|
||||
|
||||
<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
|
||||
xmlns="http://openoffice.org/2010/uno-components">
|
||||
<implementation name="com.sun.star.comp.rendering.BitmapCanvas.GDI+"
|
||||
constructor="canvas_gdiplus_BitmapCanvas_get_implementation">
|
||||
<service name="com.sun.star.rendering.BitmapCanvas.GDI+"/>
|
||||
</implementation>
|
||||
<implementation name="com.sun.star.comp.rendering.Canvas.GDI+"
|
||||
constructor="canvas_gdiplus_Canvas_get_implementation">
|
||||
<service name="com.sun.star.rendering.Canvas.GDI+"/>
|
||||
</implementation>
|
||||
</component>
|
||||
@@ -402,6 +402,10 @@ include/unoidl/unoidl.hxx:455
|
||||
unoidl::ConstantValue::(anonymous union at /home/noel/libo-plugin/include/unoidl/unoidl.hxx:445:5) doubleValue double
|
||||
include/unotest/bootstrapfixturebase.hxx:52
|
||||
test::BootstrapFixtureBase m_directories Directories
|
||||
include/vcl/bitmap.hxx:102
|
||||
BitmapSystemData mnWidth int
|
||||
include/vcl/bitmap.hxx:103
|
||||
BitmapSystemData mnHeight int
|
||||
include/vcl/formatter.hxx:128
|
||||
Formatter m_aStaticFormatter StaticFormatter
|
||||
include/vcl/toolkit/field.hxx:399
|
||||
|
||||
@@ -220,6 +220,9 @@ vcl/inc/font/PhysicalFontFace.hxx:198
|
||||
vcl/inc/salbmp.hxx:71
|
||||
_Bool SalBitmap::Create(const class com::sun::star::uno::Reference<class com::sun::star::rendering::XBitmapCanvas> &,class Size &,_Bool,)
|
||||
000
|
||||
vcl/inc/salbmp.hxx:80
|
||||
_Bool SalBitmap::GetSystemData(struct BitmapSystemData &,)
|
||||
0
|
||||
vcl/inc/salbmp.hxx:86
|
||||
_Bool SalBitmap::Replace(const class Color &,const class Color &,unsigned char,)
|
||||
000
|
||||
|
||||
@@ -37,6 +37,7 @@ $(eval $(call gb_CppunitTest_use_ure,cppcanvas_emfplus))
|
||||
$(eval $(call gb_CppunitTest_use_vcl_non_headless,cppcanvas_emfplus))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_components,cppcanvas_emfplus,\
|
||||
canvas/source/cairo/cairocanvas \
|
||||
canvas/source/factory/canvasfactory \
|
||||
cppcanvas/source/uno/mtfrenderer \
|
||||
configmgr/source/configmgr \
|
||||
|
||||
@@ -39,6 +39,7 @@ $(eval $(call gb_CppunitTest_use_ure,cppcanvas_test))
|
||||
$(eval $(call gb_CppunitTest_use_vcl,cppcanvas_test))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_components,cppcanvas_test,\
|
||||
$(if $(ENABLE_CAIRO_CANVAS),canvas/source/cairo/cairocanvas) \
|
||||
canvas/source/vcl/vclcanvas \
|
||||
canvas/source/factory/canvasfactory \
|
||||
configmgr/source/configmgr \
|
||||
|
||||
@@ -74,6 +74,12 @@ VCL_DLLPUBLIC void DrawAndClipBitmap(const Point& rPos, const Size& rSize, const
|
||||
|
||||
VCL_DLLPUBLIC css::uno::Sequence< sal_Int8 > GetMaskDIB(BitmapEx const & aBmpEx);
|
||||
|
||||
/**
|
||||
* @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
|
||||
**/
|
||||
VCL_DLLPUBLIC void CanvasCairoExtractBitmapData( BitmapEx const & rBmpEx, Bitmap & rBitmap, unsigned char*& data, bool& bHasAlpha, tools::Long& rnWidth, tools::Long& rnHeight );
|
||||
|
||||
VCL_DLLPUBLIC css::uno::Sequence< sal_Int8 > CanvasExtractBitmapData(BitmapEx const & rBitmapEx, const css::geometry::IntegerRectangle2D& rect);
|
||||
|
||||
// helper to construct historical 8x8 bitmaps with two colors
|
||||
|
||||
@@ -90,6 +90,19 @@ class SalBitmap;
|
||||
|
||||
namespace basegfx { class SystemDependentDataHolder; }
|
||||
|
||||
struct BitmapSystemData
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
void* pDIB; // device independent byte buffer
|
||||
#elif defined( MACOSX ) || defined( IOS )
|
||||
// Nothing needed, apparently
|
||||
#else
|
||||
void* aPixmap;
|
||||
#endif
|
||||
int mnWidth;
|
||||
int mnHeight;
|
||||
};
|
||||
|
||||
class SAL_WARN_UNUSED VCL_DLLPUBLIC Bitmap final
|
||||
{
|
||||
public:
|
||||
@@ -120,6 +133,14 @@ public:
|
||||
inline sal_Int64 GetSizeBytes() const;
|
||||
bool HasGreyPalette8Bit() const;
|
||||
bool HasGreyPaletteAny() const;
|
||||
/** get system dependent bitmap data
|
||||
|
||||
@param rData
|
||||
The system dependent BitmapSystemData structure to be filled
|
||||
|
||||
@return true if the bitmap has a valid system object (e.g. not empty)
|
||||
*/
|
||||
bool GetSystemData( BitmapSystemData& rData ) const;
|
||||
|
||||
BitmapChecksum GetChecksum() const;
|
||||
|
||||
|
||||
@@ -61,6 +61,41 @@
|
||||
typedef struct _cairo_surface cairo_surface_t;
|
||||
typedef struct _cairo cairo_t;
|
||||
|
||||
class VirtualDevice;
|
||||
|
||||
namespace cairo {
|
||||
|
||||
typedef std::shared_ptr<cairo_surface_t> CairoSurfaceSharedPtr;
|
||||
typedef std::shared_ptr<cairo_t> CairoSharedPtr;
|
||||
struct Surface;
|
||||
typedef std::shared_ptr<Surface> SurfaceSharedPtr;
|
||||
|
||||
/** Cairo surface interface
|
||||
|
||||
For each cairo-supported platform, there's an implementation of
|
||||
this interface
|
||||
*/
|
||||
struct Surface
|
||||
{
|
||||
public:
|
||||
virtual ~Surface() {}
|
||||
|
||||
// Query methods
|
||||
virtual CairoSharedPtr getCairo() const = 0;
|
||||
virtual CairoSurfaceSharedPtr getCairoSurface() const = 0;
|
||||
virtual SurfaceSharedPtr getSimilar(int cairo_content_type, int width, int height) const = 0;
|
||||
|
||||
/// factory for VirDev on this surface
|
||||
virtual VclPtr<VirtualDevice> createVirtualDevice() const = 0;
|
||||
|
||||
/// Resize the surface (possibly destroying content), only possible for X11 typically
|
||||
/// so on failure caller must create a new surface instead
|
||||
virtual bool Resize( int /*width*/, int /*height*/ ) { return false; }
|
||||
|
||||
/// Flush all pending output to surface
|
||||
virtual void flush() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -288,6 +288,16 @@ public:
|
||||
SystemGraphicsData GetSystemGfxData() const;
|
||||
OUString GetRenderBackendName() const;
|
||||
|
||||
// Used by the canvas module. Despite the name it does not always return true if Cairo is supported.
|
||||
bool SupportsCairo() const;
|
||||
/// Create Surface from given cairo surface
|
||||
cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const;
|
||||
/// Create surface with given dimensions
|
||||
cairo::SurfaceSharedPtr CreateSurface(int x, int y, int width, int height) const;
|
||||
/// Create Surface for given bitmap data
|
||||
cairo::SurfaceSharedPtr CreateBitmapSurface(const BitmapSystemData& rData, const Size& rSize) const;
|
||||
/// Return native handle for underlying surface
|
||||
css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const;
|
||||
SAL_DLLPRIVATE css::uno::Any GetSystemGfxDataAny() const;
|
||||
|
||||
void SetRefPoint();
|
||||
|
||||
@@ -152,7 +152,10 @@ struct SystemGraphicsData
|
||||
#elif defined( IOS )
|
||||
CGContextRef rCGContext; // CoreGraphics graphic context
|
||||
#elif defined( UNX )
|
||||
// Nothing
|
||||
void* pDisplay; // the relevant display connection
|
||||
sal_uIntPtr hDrawable; // a drawable
|
||||
void* pVisual; // the visual in use
|
||||
int nScreen; // the current screen of the drawable
|
||||
#endif
|
||||
#if USE_HEADLESS_CODE
|
||||
void* pSurface; // the cairo surface when using svp-based backends, which includes gtk[3|4]
|
||||
@@ -169,7 +172,10 @@ struct SystemGraphicsData
|
||||
#elif defined( IOS )
|
||||
, rCGContext( NULL )
|
||||
#elif defined( UNX )
|
||||
// Nothing
|
||||
, pDisplay( nullptr )
|
||||
, hDrawable( 0 )
|
||||
, pVisual( nullptr )
|
||||
, nScreen( 0 )
|
||||
#endif
|
||||
#if USE_HEADLESS_CODE
|
||||
, pSurface( nullptr )
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
RefDevMode meRefDevMode;
|
||||
bool mbForceZeroExtleadBug;
|
||||
|
||||
SAL_DLLPRIVATE void ImplInitVirDev( const OutputDevice* pOutDev, tools::Long nDX, tools::Long nDY );
|
||||
SAL_DLLPRIVATE void ImplInitVirDev( const OutputDevice* pOutDev, tools::Long nDX, tools::Long nDY, const SystemGraphicsData *pData = nullptr );
|
||||
SAL_DLLPRIVATE bool InnerImplSetOutputSizePixel( const Size& rNewSize, bool bErase,
|
||||
sal_uInt8* pBuffer );
|
||||
|
||||
@@ -108,6 +108,13 @@ public:
|
||||
DeviceFormat eFormat = DeviceFormat::WITHOUT_ALPHA)
|
||||
: VirtualDevice(&rCompDev, eFormat, OUTDEV_VIRDEV) {}
|
||||
|
||||
/** Create a virtual device using an existing system dependent device or graphics context
|
||||
Any rendering will happen directly on the context and not on any intermediate bitmap.
|
||||
Note: This might not be supported on all platforms !
|
||||
*/
|
||||
explicit VirtualDevice(const SystemGraphicsData& rData, const Size &rSize,
|
||||
DeviceFormat eFormat);
|
||||
|
||||
virtual ~VirtualDevice() override;
|
||||
virtual void dispose() override;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user