summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/CppunitTest_drawinglayer_border.mk2
-rw-r--r--drawinglayer/CppunitTest_drawinglayer_processors.mk57
-rw-r--r--drawinglayer/IwyuFilter_drawinglayer.yaml9
-rw-r--r--drawinglayer/Library_drawinglayer.mk58
-rw-r--r--drawinglayer/Library_drawinglayercore.mk57
-rw-r--r--drawinglayer/Module_drawinglayer.mk5
-rw-r--r--drawinglayer/README.md (renamed from drawinglayer/README)62
-rw-r--r--drawinglayer/inc/converters.hxx36
-rw-r--r--drawinglayer/inc/pch/precompiled_drawinglayer.hxx35
-rw-r--r--drawinglayer/inc/pch/precompiled_drawinglayercore.cxx12
-rw-r--r--drawinglayer/inc/pch/precompiled_drawinglayercore.hxx52
-rw-r--r--drawinglayer/inc/primitive2d/cropprimitive2d.hxx13
-rw-r--r--drawinglayer/inc/primitive2d/graphicprimitivehelper2d.hxx59
-rw-r--r--drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx143
-rw-r--r--drawinglayer/inc/primitive2d/textlineprimitive2d.hxx16
-rw-r--r--drawinglayer/inc/primitive2d/textstrikeoutprimitive2d.hxx38
-rw-r--r--drawinglayer/inc/primitive2d/wallpaperprimitive2d.hxx20
-rw-r--r--drawinglayer/inc/primitive3d/hatchtextureprimitive3d.hxx12
-rw-r--r--drawinglayer/inc/primitive3d/hiddengeometryprimitive3d.hxx10
-rw-r--r--drawinglayer/inc/primitive3d/polygontubeprimitive3d.hxx10
-rw-r--r--drawinglayer/inc/primitive3d/sdrdecompositiontools3d.hxx9
-rw-r--r--drawinglayer/inc/primitive3d/shadowprimitive3d.hxx12
-rw-r--r--drawinglayer/inc/primitive3d/textureprimitive3d.hxx44
-rw-r--r--drawinglayer/inc/processor3d/defaultprocessor3d.hxx15
-rw-r--r--drawinglayer/inc/processor3d/geometry2dextractor.hxx14
-rw-r--r--drawinglayer/inc/processor3d/shadow3dextractor.hxx14
-rw-r--r--drawinglayer/inc/processor3d/zbufferprocessor3d.hxx14
-rw-r--r--drawinglayer/inc/texture/texture.hxx73
-rw-r--r--drawinglayer/inc/texture/texture3d.hxx52
-rw-r--r--drawinglayer/inc/wmfemfhelper.hxx48
-rw-r--r--drawinglayer/qa/unit/border.cxx79
-rw-r--r--drawinglayer/qa/unit/vclmetafileprocessor2d.cxx156
-rw-r--r--drawinglayer/qa/unit/vclpixelprocessor2d.cxx138
-rw-r--r--drawinglayer/source/animation/animationtiming.cxx23
-rw-r--r--drawinglayer/source/attribute/fillgradientattribute.cxx151
-rw-r--r--drawinglayer/source/attribute/fillgraphicattribute.cxx25
-rw-r--r--drawinglayer/source/attribute/fillhatchattribute.cxx13
-rw-r--r--drawinglayer/source/attribute/fontattribute.cxx297
-rw-r--r--drawinglayer/source/attribute/lineattribute.cxx15
-rw-r--r--drawinglayer/source/attribute/linestartendattribute.cxx18
-rw-r--r--drawinglayer/source/attribute/materialattribute3d.cxx16
-rw-r--r--drawinglayer/source/attribute/sdrallattribute3d.cxx21
-rw-r--r--drawinglayer/source/attribute/sdrfillattribute.cxx45
-rw-r--r--drawinglayer/source/attribute/sdrfillgraphicattribute.cxx25
-rw-r--r--drawinglayer/source/attribute/sdrglowattribute.cxx17
-rw-r--r--drawinglayer/source/attribute/sdrglowtextattribute.cxx37
-rw-r--r--drawinglayer/source/attribute/sdrlightattribute3d.cxx7
-rw-r--r--drawinglayer/source/attribute/sdrlightingattribute3d.cxx31
-rw-r--r--drawinglayer/source/attribute/sdrlineattribute.cxx44
-rw-r--r--drawinglayer/source/attribute/sdrlinestartendattribute.cxx25
-rw-r--r--drawinglayer/source/attribute/sdrobjectattribute3d.cxx7
-rw-r--r--drawinglayer/source/attribute/sdrsceneattribute3d.cxx12
-rw-r--r--drawinglayer/source/attribute/sdrshadowattribute.cxx32
-rw-r--r--drawinglayer/source/attribute/strokeattribute.cxx23
-rw-r--r--drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx57
-rw-r--r--drawinglayer/source/dumper/EnhancedShapeDumper.cxx535
-rw-r--r--drawinglayer/source/dumper/EnhancedShapeDumper.hxx10
-rw-r--r--drawinglayer/source/dumper/XShapeDumper.cxx806
-rw-r--r--drawinglayer/source/geometry/viewinformation2d.cxx505
-rw-r--r--drawinglayer/source/geometry/viewinformation3d.cxx257
-rw-r--r--drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx105
-rw-r--r--drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx178
-rw-r--r--drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx114
-rw-r--r--drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx113
-rw-r--r--drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx96
-rw-r--r--drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.hxx (renamed from drawinglayer/source/processor2d/helperwrongspellrenderer.hxx)31
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx106
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D.cxx57
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D.cxx67
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx62
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonHairlinePrimitive2D.cxx26
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D.cxx33
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D.cxx31
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx99
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D.cxx18
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D.cxx34
-rw-r--r--drawinglayer/source/primitive2d/Primitive2DContainer.cxx64
-rw-r--r--drawinglayer/source/primitive2d/Tools.cxx211
-rw-r--r--drawinglayer/source/primitive2d/animatedprimitive2d.cxx40
-rw-r--r--drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx47
-rw-r--r--drawinglayer/source/primitive2d/baseprimitive2d.cxx57
-rw-r--r--drawinglayer/source/primitive2d/bitmapprimitive2d.cxx27
-rw-r--r--drawinglayer/source/primitive2d/borderlineprimitive2d.cxx75
-rw-r--r--drawinglayer/source/primitive2d/controlprimitive2d.cxx195
-rw-r--r--drawinglayer/source/primitive2d/cropprimitive2d.cxx22
-rw-r--r--drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx28
-rw-r--r--drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx140
-rw-r--r--drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx31
-rw-r--r--drawinglayer/source/primitive2d/epsprimitive2d.cxx22
-rw-r--r--drawinglayer/source/primitive2d/exclusiveeditviewprimitive2d.cxx55
-rw-r--r--drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx405
-rw-r--r--drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx52
-rw-r--r--drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx43
-rw-r--r--drawinglayer/source/primitive2d/glowprimitive2d.cxx309
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitive2d.cxx122
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx301
-rw-r--r--drawinglayer/source/primitive2d/gridprimitive2d.cxx42
-rw-r--r--drawinglayer/source/primitive2d/groupprimitive2d.cxx21
-rw-r--r--drawinglayer/source/primitive2d/helplineprimitive2d.cxx43
-rw-r--r--drawinglayer/source/primitive2d/hiddengeometryprimitive2d.cxx9
-rw-r--r--drawinglayer/source/primitive2d/invertprimitive2d.cxx9
-rw-r--r--drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx30
-rw-r--r--drawinglayer/source/primitive2d/maskprimitive2d.cxx14
-rw-r--r--drawinglayer/source/primitive2d/mediaprimitive2d.cxx33
-rw-r--r--drawinglayer/source/primitive2d/metafileprimitive2d.cxx91
-rw-r--r--drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx14
-rw-r--r--drawinglayer/source/primitive2d/objectinfoprimitive2d.cxx22
-rw-r--r--drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx9
-rw-r--r--drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx35
-rw-r--r--drawinglayer/source/primitive2d/patternfillprimitive2d.cxx136
-rw-r--r--drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx13
-rw-r--r--drawinglayer/source/primitive2d/polygonprimitive2d.cxx1175
-rw-r--r--drawinglayer/source/primitive2d/primitivetools2d.cxx36
-rw-r--r--drawinglayer/source/primitive2d/sceneprimitive2d.cxx227
-rw-r--r--drawinglayer/source/primitive2d/sdrdecompositiontools2d.cxx7
-rw-r--r--drawinglayer/source/primitive2d/shadowprimitive2d.cxx396
-rw-r--r--drawinglayer/source/primitive2d/softedgeprimitive2d.cxx321
-rw-r--r--drawinglayer/source/primitive2d/structuretagprimitive2d.cxx29
-rw-r--r--drawinglayer/source/primitive2d/svggradientprimitive2d.cxx443
-rw-r--r--drawinglayer/source/primitive2d/textbreakuphelper.cxx34
-rw-r--r--drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx485
-rw-r--r--drawinglayer/source/primitive2d/texteffectprimitive2d.cxx391
-rw-r--r--drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx82
-rw-r--r--drawinglayer/source/primitive2d/textlayoutdevice.cxx795
-rw-r--r--drawinglayer/source/primitive2d/textlineprimitive2d.cxx41
-rw-r--r--drawinglayer/source/primitive2d/textprimitive2d.cxx561
-rw-r--r--drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx55
-rw-r--r--drawinglayer/source/primitive2d/transformprimitive2d.cxx28
-rw-r--r--drawinglayer/source/primitive2d/transparenceprimitive2d.cxx13
-rw-r--r--drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d.cxx22
-rw-r--r--drawinglayer/source/primitive2d/wallpaperprimitive2d.cxx350
-rw-r--r--drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx113
-rw-r--r--drawinglayer/source/primitive3d/Tools.cxx67
-rw-r--r--drawinglayer/source/primitive3d/baseprimitive3d.cxx30
-rw-r--r--drawinglayer/source/primitive3d/groupprimitive3d.cxx11
-rw-r--r--drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx346
-rw-r--r--drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx3
-rw-r--r--drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx8
-rw-r--r--drawinglayer/source/primitive3d/polygonprimitive3d.cxx15
-rw-r--r--drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx125
-rw-r--r--drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx9
-rw-r--r--drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx19
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx53
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx19
-rw-r--r--drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx19
-rw-r--r--drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx8
-rw-r--r--drawinglayer/source/primitive3d/sdrprimitive3d.cxx13
-rw-r--r--drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx2
-rw-r--r--drawinglayer/source/primitive3d/shadowprimitive3d.cxx8
-rw-r--r--drawinglayer/source/primitive3d/textureprimitive3d.cxx14
-rw-r--r--drawinglayer/source/primitive3d/transformprimitive3d.cxx8
-rw-r--r--drawinglayer/source/processor2d/SDPRProcessor2dTools.cxx302
-rw-r--r--drawinglayer/source/processor2d/baseprocessor2d.cxx69
-rw-r--r--drawinglayer/source/processor2d/cairopixelprocessor2d.cxx4584
-rw-r--r--drawinglayer/source/processor2d/contourextractor2d.cxx19
-rw-r--r--drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx2177
-rw-r--r--drawinglayer/source/processor2d/getdigitlanguage.cxx2
-rw-r--r--drawinglayer/source/processor2d/getdigitlanguage.hxx10
-rw-r--r--drawinglayer/source/processor2d/helperwrongspellrenderer.cxx76
-rw-r--r--drawinglayer/source/processor2d/hittestprocessor2d.cxx190
-rw-r--r--drawinglayer/source/processor2d/linegeometryextractor2d.cxx20
-rw-r--r--drawinglayer/source/processor2d/objectinfoextractor2d.cxx2
-rw-r--r--drawinglayer/source/processor2d/processor2dtools.cxx166
-rw-r--r--drawinglayer/source/processor2d/processorfromoutputdevice.cxx50
-rw-r--r--drawinglayer/source/processor2d/textaspolygonextractor2d.cxx122
-rw-r--r--drawinglayer/source/processor2d/textextractor2d.cxx88
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.cxx386
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.hxx79
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx1353
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx24
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx703
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.hxx25
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx855
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.hxx32
-rw-r--r--drawinglayer/source/processor3d/baseprocessor3d.cxx34
-rw-r--r--drawinglayer/source/processor3d/cutfindprocessor3d.cxx6
-rw-r--r--drawinglayer/source/processor3d/defaultprocessor3d.cxx106
-rw-r--r--drawinglayer/source/processor3d/geometry2dextractor.cxx19
-rw-r--r--drawinglayer/source/processor3d/shadow3dextractor.cxx35
-rw-r--r--drawinglayer/source/processor3d/zbufferprocessor3d.cxx68
-rw-r--r--drawinglayer/source/texture/texture.cxx672
-rw-r--r--drawinglayer/source/texture/texture3d.cxx102
-rw-r--r--drawinglayer/source/tools/converters.cxx474
-rw-r--r--drawinglayer/source/tools/emfpbrush.cxx191
-rw-r--r--drawinglayer/source/tools/emfpbrush.hxx13
-rw-r--r--drawinglayer/source/tools/emfpcustomlinecap.cxx53
-rw-r--r--drawinglayer/source/tools/emfpcustomlinecap.hxx9
-rw-r--r--drawinglayer/source/tools/emfpfont.cxx29
-rw-r--r--drawinglayer/source/tools/emfpfont.hxx5
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx1543
-rw-r--r--drawinglayer/source/tools/emfphelperdata.hxx34
-rw-r--r--drawinglayer/source/tools/emfpimage.cxx12
-rw-r--r--drawinglayer/source/tools/emfpimage.hxx5
-rw-r--r--drawinglayer/source/tools/emfpimageattributes.cxx18
-rw-r--r--drawinglayer/source/tools/emfpimageattributes.hxx6
-rw-r--r--drawinglayer/source/tools/emfppath.cxx157
-rw-r--r--drawinglayer/source/tools/emfppath.hxx17
-rw-r--r--drawinglayer/source/tools/emfppen.cxx299
-rw-r--r--drawinglayer/source/tools/emfppen.hxx18
-rw-r--r--drawinglayer/source/tools/emfpregion.cxx21
-rw-r--r--drawinglayer/source/tools/emfpregion.hxx5
-rw-r--r--drawinglayer/source/tools/emfpstringformat.cxx163
-rw-r--r--drawinglayer/source/tools/emfpstringformat.hxx5
-rw-r--r--drawinglayer/source/tools/primitive2dxmldump.cxx1031
-rw-r--r--drawinglayer/source/tools/wmfemfhelper.cxx567
205 files changed, 22000 insertions, 9797 deletions
diff --git a/drawinglayer/CppunitTest_drawinglayer_border.mk b/drawinglayer/CppunitTest_drawinglayer_border.mk
index fa2f715590cd..f87321a608c5 100644
--- a/drawinglayer/CppunitTest_drawinglayer_border.mk
+++ b/drawinglayer/CppunitTest_drawinglayer_border.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_border, \
sal \
salhelper \
drawinglayer \
+ drawinglayercore \
vcl \
test \
tl \
@@ -30,7 +31,6 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_border, \
$(eval $(call gb_CppunitTest_use_externals,drawinglayer_border,\
boost_headers \
- libxml2 \
))
$(eval $(call gb_CppunitTest_add_exception_objects,drawinglayer_border, \
diff --git a/drawinglayer/CppunitTest_drawinglayer_processors.mk b/drawinglayer/CppunitTest_drawinglayer_processors.mk
new file mode 100644
index 000000000000..627809b814a8
--- /dev/null
+++ b/drawinglayer/CppunitTest_drawinglayer_processors.mk
@@ -0,0 +1,57 @@
+# -*- 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_CppunitTest_CppunitTest,drawinglayer_processors))
+
+$(eval $(call gb_CppunitTest_use_api,drawinglayer_processors,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,drawinglayer_processors, \
+ basegfx \
+ $(if $(ENABLE_WASM_STRIP_CANVAS),,cppcanvas) \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ drawinglayer \
+ drawinglayercore \
+ vcl \
+ test \
+ tl \
+ unotest \
+ svt \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,drawinglayer_processors,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,drawinglayer_processors, \
+ drawinglayer/qa/unit/vclmetafileprocessor2d \
+ drawinglayer/qa/unit/vclpixelprocessor2d \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,drawinglayer_processors))
+
+$(eval $(call gb_CppunitTest_use_vcl,drawinglayer_processors))
+
+$(eval $(call gb_CppunitTest_use_components,drawinglayer_processors,\
+ canvas/source/vcl/vclcanvas \
+ canvas/source/factory/canvasfactory \
+ configmgr/source/configmgr \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,drawinglayer_processors))
+
+# vim: set noet sw=4 ts=4:
diff --git a/drawinglayer/IwyuFilter_drawinglayer.yaml b/drawinglayer/IwyuFilter_drawinglayer.yaml
index 5d430b2fd490..c3f3a169cb7b 100644
--- a/drawinglayer/IwyuFilter_drawinglayer.yaml
+++ b/drawinglayer/IwyuFilter_drawinglayer.yaml
@@ -1,9 +1,6 @@
---
assumeFilename: drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
excludelist:
- drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx:
- # Actually used
- - com/sun/star/lang/XMultiServiceFactory.hpp
drawinglayer/source/dumper/EnhancedShapeDumper.cxx:
# Actually used
- com/sun/star/beans/XPropertySet.hpp
@@ -13,6 +10,12 @@ excludelist:
drawinglayer/source/primitive2d/sceneprimitive2d.cxx:
# Needed for direct member access
- drawinglayer/attribute/sdrlightattribute3d.hxx
+ drawinglayer/source/primitive2d/textlayoutdevice.cxx:
+ # Needed for template
+ - com/sun/star/uno/XComponentContext.hpp
drawinglayer/source/processor2d/vclhelperbufferdevice.cxx:
# Needed for direct member access
- basegfx/matrix/b2dhommatrix.hxx
+ drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:
+ # Needed for rtl::math::sin
+ - rtl/math.hxx
diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk
index 43a42b83b42c..6997bd22457e 100644
--- a/drawinglayer/Library_drawinglayer.mk
+++ b/drawinglayer/Library_drawinglayer.mk
@@ -20,32 +20,67 @@ $(eval $(call gb_Library_add_defs,drawinglayer,\
$(eval $(call gb_Library_set_precompiled_header,drawinglayer,drawinglayer/inc/pch/precompiled_drawinglayer))
-$(eval $(call gb_Library_set_componentfile,drawinglayer,drawinglayer/drawinglayer))
+$(eval $(call gb_Library_set_componentfile,drawinglayer,drawinglayer/drawinglayer,services))
$(eval $(call gb_Library_use_sdk_api,drawinglayer))
$(eval $(call gb_Library_use_externals,drawinglayer,\
boost_headers \
libxml2 \
+ $(if $(USE_HEADLESS_CODE), cairo) \
))
+ifneq ($(ENABLE_WASM_STRIP_CANVAS),TRUE)
$(eval $(call gb_Library_use_libraries,drawinglayer,\
- basegfx \
canvastools \
- comphelper \
cppcanvas \
+))
+endif
+
+$(eval $(call gb_Library_use_system_win32_libs,drawinglayer,\
+ d2d1 \
+ dxguid \
+))
+
+$(eval $(call gb_Library_use_libraries,drawinglayer,\
+ basegfx \
+ comphelper \
cppu \
cppuhelper \
+ drawinglayercore \
i18nlangtag \
sal \
salhelper \
svl \
svt \
- tk \
tl \
vcl \
))
+$(eval $(call gb_Library_use_custom_headers,drawinglayer,\
+ officecfg/registry \
+))
+
+ifeq ($(OS),WNT)
+$(eval $(call gb_Library_use_system_win32_libs,drawinglayer,\
+ gdi32 \
+))
+endif
+
+ifeq ($(OS),WNT)
+$(eval $(call gb_Library_add_exception_objects,drawinglayer,\
+ drawinglayer/source/processor2d/d2dpixelprocessor2d \
+ drawinglayer/source/processor2d/SDPRProcessor2dTools \
+))
+endif
+
+ifeq ($(USE_HEADLESS_CODE),TRUE)
+$(eval $(call gb_Library_add_exception_objects,drawinglayer,\
+ drawinglayer/source/processor2d/cairopixelprocessor2d \
+ drawinglayer/source/processor2d/SDPRProcessor2dTools \
+))
+endif
+
$(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/animation/animationtiming \
drawinglayer/source/attribute/fillgraphicattribute \
@@ -59,6 +94,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/attribute/sdrfillattribute \
drawinglayer/source/attribute/sdrfillgraphicattribute \
drawinglayer/source/attribute/sdrglowattribute \
+ drawinglayer/source/attribute/sdrglowtextattribute \
drawinglayer/source/attribute/sdrlightattribute3d \
drawinglayer/source/attribute/sdrlightingattribute3d \
drawinglayer/source/attribute/sdrlineattribute \
@@ -67,27 +103,27 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/attribute/sdrsceneattribute3d \
drawinglayer/source/attribute/sdrshadowattribute \
drawinglayer/source/attribute/strokeattribute \
- drawinglayer/source/geometry/viewinformation2d \
drawinglayer/source/geometry/viewinformation3d \
drawinglayer/source/primitive2d/animatedprimitive2d \
drawinglayer/source/primitive2d/backgroundcolorprimitive2d \
- drawinglayer/source/primitive2d/baseprimitive2d \
drawinglayer/source/primitive2d/bitmapprimitive2d \
+ drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D \
drawinglayer/source/primitive2d/borderlineprimitive2d \
drawinglayer/source/primitive2d/controlprimitive2d \
drawinglayer/source/primitive2d/cropprimitive2d \
drawinglayer/source/primitive2d/discretebitmapprimitive2d \
drawinglayer/source/primitive2d/discreteshadowprimitive2d \
drawinglayer/source/primitive2d/embedded3dprimitive2d \
+ drawinglayer/source/primitive2d/exclusiveeditviewprimitive2d \
drawinglayer/source/primitive2d/epsprimitive2d \
drawinglayer/source/primitive2d/fillgraphicprimitive2d \
drawinglayer/source/primitive2d/fillgradientprimitive2d \
drawinglayer/source/primitive2d/fillhatchprimitive2d \
drawinglayer/source/primitive2d/glowprimitive2d \
+ drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools \
drawinglayer/source/primitive2d/graphicprimitivehelper2d \
drawinglayer/source/primitive2d/graphicprimitive2d \
drawinglayer/source/primitive2d/gridprimitive2d \
- drawinglayer/source/primitive2d/groupprimitive2d \
drawinglayer/source/primitive2d/helplineprimitive2d \
drawinglayer/source/primitive2d/hiddengeometryprimitive2d \
drawinglayer/source/primitive2d/invertprimitive2d \
@@ -106,12 +142,13 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D \
+ drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D \
+ drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D \
drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D \
drawinglayer/source/primitive2d/primitivetools2d \
- drawinglayer/source/primitive2d/Primitive2DContainer \
drawinglayer/source/primitive2d/sceneprimitive2d \
drawinglayer/source/primitive2d/sdrdecompositiontools2d \
drawinglayer/source/primitive2d/shadowprimitive2d \
@@ -127,7 +164,6 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/primitive2d/textlineprimitive2d \
drawinglayer/source/primitive2d/textprimitive2d \
drawinglayer/source/primitive2d/textstrikeoutprimitive2d \
- drawinglayer/source/primitive2d/Tools \
drawinglayer/source/primitive2d/transformprimitive2d \
drawinglayer/source/primitive2d/transparenceprimitive2d \
drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d \
@@ -152,15 +188,15 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/primitive3d/shadowprimitive3d \
drawinglayer/source/primitive3d/textureprimitive3d \
drawinglayer/source/primitive3d/transformprimitive3d \
+ drawinglayer/source/primitive3d/Tools \
drawinglayer/source/processor2d/baseprocessor2d \
drawinglayer/source/processor2d/processor2dtools \
drawinglayer/source/processor2d/contourextractor2d \
drawinglayer/source/processor2d/getdigitlanguage \
- drawinglayer/source/processor2d/helperwrongspellrenderer \
drawinglayer/source/processor2d/hittestprocessor2d \
drawinglayer/source/processor2d/linegeometryextractor2d \
drawinglayer/source/processor2d/objectinfoextractor2d \
- drawinglayer/source/processor2d/processorfromoutputdevice \
+ drawinglayer/source/processor2d/textextractor2d \
drawinglayer/source/processor2d/textaspolygonextractor2d \
drawinglayer/source/processor2d/vclhelperbufferdevice \
drawinglayer/source/processor2d/vclmetafileprocessor2d \
diff --git a/drawinglayer/Library_drawinglayercore.mk b/drawinglayer/Library_drawinglayercore.mk
new file mode 100644
index 000000000000..83d2c0faab6d
--- /dev/null
+++ b/drawinglayer/Library_drawinglayercore.mk
@@ -0,0 +1,57 @@
+# -*- 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_Library_Library,drawinglayercore))
+
+$(eval $(call gb_Library_set_include,drawinglayercore,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/drawinglayer/inc \
+))
+
+$(eval $(call gb_Library_add_defs,drawinglayercore,\
+ -DDRAWINGLAYERCORE_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,drawinglayercore,drawinglayer/inc/pch/precompiled_drawinglayercore))
+
+$(eval $(call gb_Library_use_sdk_api,drawinglayercore))
+
+$(eval $(call gb_Library_use_externals,drawinglayercore,\
+ boost_headers \
+))
+
+$(eval $(call gb_Library_use_libraries,drawinglayercore,\
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ i18nlangtag \
+ sal \
+ salhelper \
+ svl \
+ tl \
+ utl \
+))
+
+$(eval $(call gb_Library_use_custom_headers,drawinglayercore,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_add_exception_objects,drawinglayercore,\
+ drawinglayer/source/primitive2d/baseprimitive2d \
+ drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D \
+ drawinglayer/source/primitive2d/BufferedDecompositionFlusher \
+ drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D \
+ drawinglayer/source/primitive2d/Primitive2DContainer \
+ drawinglayer/source/primitive2d/groupprimitive2d \
+ drawinglayer/source/primitive2d/Tools \
+ drawinglayer/source/geometry/viewinformation2d \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/drawinglayer/Module_drawinglayer.mk b/drawinglayer/Module_drawinglayer.mk
index 6d329e95c60a..5a3799991c6d 100644
--- a/drawinglayer/Module_drawinglayer.mk
+++ b/drawinglayer/Module_drawinglayer.mk
@@ -10,9 +10,14 @@
$(eval $(call gb_Module_Module,drawinglayer))
$(eval $(call gb_Module_add_targets,drawinglayer,\
+ Library_drawinglayercore \
Library_drawinglayer \
))
+$(eval $(call gb_Module_add_check_targets,drawinglayer,\
+ CppunitTest_drawinglayer_processors \
+))
+
$(eval $(call gb_Module_add_slowcheck_targets,drawinglayer,\
CppunitTest_drawinglayer_border \
))
diff --git a/drawinglayer/README b/drawinglayer/README.md
index b530ba6fedac..9eb7057d2a37 100644
--- a/drawinglayer/README
+++ b/drawinglayer/README.md
@@ -1,6 +1,8 @@
+# Drawing API
+
Drawing API that can specify what to draw via a kind of display list.
-Example of the DrawingLayer use is eg. in svx/source/xoutdev/xtabhtch.cxx:121.
+Example of the DrawingLayer use is eg. in `svx/source/xoutdev/xtabhtch.cxx:121`.
A stripped down version with extended comments:
// Create a hatch primitive (here a rectangle that will be filled with
@@ -22,24 +24,21 @@ A stripped down version with extended comments:
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(...));
- if (pProcessor2D)
- {
- // Fill-in the display list.
- drawinglayer::primitive2d::Primitive2DSequence aSequence(2);
+ // Fill-in the display list.
+ drawinglayer::primitive2d::Primitive2DSequence aSequence(2);
- aSequence[0] = aHatchPrimitive;
- aSequence[1] = aBlackRectanglePrimitive;
+ aSequence[0] = aHatchPrimitive;
+ aSequence[1] = aBlackRectanglePrimitive;
- // Render it to the virtual device.
- pProcessor2D->process(aSequence);
- pProcessor2D.reset();
- }
+ // Render it to the virtual device.
+ pProcessor2D->process(aSequence);
+ pProcessor2D.reset();
// Obtain the bitmap that was rendered from the virtual device, to re-use
// it in the widget.
aRetval = aVirtualDevice.GetBitmap(Point(0, 0), aVirtualDevice.GetOutputSizePixel());
-== DrawingLayer glossary ==
+## DrawingLayer Glossary
Primitives - classes that represent what should be drawn. It holds the data
what to draw, but does not contain any kind of the rendering. Some of the
@@ -49,31 +48,31 @@ primitives.
Decomposition - a way how to break down the more complicated primitives into
the basic primitives, and represent them via them; this logically makes the
-plain Primitive2DSequence display list a hierarchy.
-Eg. PolygonMarkerPrimitive2D can be decomposed to 2 hairlines
-PolyPolygonHairlinePrimitive2D's, each with different color.
+plain `Primitive2DSequence` display list a hierarchy.
+Eg. `PolygonMarkerPrimitive2D` can be decomposed to 2 hairlines
+`PolyPolygonHairlinePrimitive2D`'s, each with different color.
Processor - a class that goes through the hierarchy of the Primitives, and
-renders it some way. Various processors, like VclPixelProcessor2D (renders to
-the screen), VclMetafileProcessor2D (renders to the VCL metafile, eg. for
+renders it some way. Various processors, like `VclPixelProcessor2D` (renders to
+the screen), `VclMetafileProcessor2D` (renders to the VCL metafile, eg. for
printing), etc.
-== How to Implement a new Primitive ("something new to draw") ==
+## How to Implement a New Primitive ("Something New to Draw")
-* Create an ancestor of BasePrimitive2D
+* Create an ancestor of `BasePrimitive2D`
(or of its ancestor if it fits the purpose better)
- * Assign it an ID [in drawinglayer_primitivetypes2d.hxx]
+ * Assign it an ID [in `drawinglayer_primitivetypes2d.hxx`]
* Implement its decomposition
- [virtual Primitive2DSequence create2DDecomposition(...)]
+ [`virtual Primitive2DSequence create2DDecomposition(...)`]
* Extend the (various) processor(s)
If you need more than relying on just the decomposition
-== Where is DrawingLayer used ==
+## Where is DrawingLayer Used
-* SdrObject(s) (rectangles, Circles, predefined shapes etc.)
+* `SdrObject`(s) (rectangles, Circles, predefined shapes etc.)
* Selections
@@ -83,3 +82,20 @@ printing), etc.
above)
* Custom widgets (like the Header / Footer indicator button)
+
+## Dumping DrawingLayer Primitives as XML
+
+For debugging purposes, it is possible to dump the drawinglayer primitives as
+an xml file. The drawinglayer xml dump can show possible problems with the
+rendering.
+
+For example, in `emfio/qa/cppunit/emf/EmfImportTest.cxx`, one can write:
+
+ Primitive2DSequence aSequence = parseEmf(u"emfio/qa/cppunit/wmf/data/stockobject.emf");
+ drawinglayer::Primitive2dXmlDump dumper;
+ Primitive2DContainer aContainer(aSequence);
+ dumper.dump(aContainer, "/tmp/drawyinglayer.xml");
+
+Then, after invoking `make CppunitTest_emfio_emf`, `/tmp/drawyinglayer.xml` will
+be the dump of the drawinglayer primitives used to draw the emf file in
+LibreOffice. The top level tag will be <primitive2D>.
diff --git a/drawinglayer/inc/converters.hxx b/drawinglayer/inc/converters.hxx
deleted file mode 100644
index 4f585d5d08db..000000000000
--- a/drawinglayer/inc/converters.hxx
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- 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 <vcl/bitmapex.hxx>
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
-
-namespace drawinglayer
-{
- BitmapEx convertToBitmapEx(
- const drawinglayer::primitive2d::Primitive2DContainer& rSeq,
- const geometry::ViewInformation2D& rViewInformation2D,
- sal_uInt32 nDiscreteWidth,
- sal_uInt32 nDiscreteHeight,
- sal_uInt32 nMaxQuadratPixels);
-
-} // end of namespace drawinglayer
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/pch/precompiled_drawinglayer.hxx b/drawinglayer/inc/pch/precompiled_drawinglayer.hxx
index b8c4aadb7dab..5acb7c70c2ca 100644
--- a/drawinglayer/inc/pch/precompiled_drawinglayer.hxx
+++ b/drawinglayer/inc/pch/precompiled_drawinglayer.hxx
@@ -13,26 +13,30 @@
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 2020-07-09 17:06:23 using:
+ Generated on 2021-12-23 08:55:28 using:
./bin/update_pch drawinglayer drawinglayer --cutoff=4 --exclude:system --exclude:module --exclude:local
If after updating build fails, use the following command to locate conflicting headers:
./bin/update_pch_bisect ./drawinglayer/inc/pch/precompiled_drawinglayer.hxx "make drawinglayer.build" --find-conflicts
*/
+#include <sal/config.h>
#if PCH_LEVEL >= 1
#include <algorithm>
#include <cassert>
+#include <cmath>
#include <cstddef>
-#include <cstring>
+#include <cstdlib>
#include <deque>
#include <limits.h>
#include <limits>
#include <memory>
#include <new>
+#include <optional>
#include <ostream>
#include <string.h>
#include <string_view>
+#include <type_traits>
#include <utility>
#include <vector>
#endif // PCH_LEVEL >= 1
@@ -43,20 +47,18 @@
#include <rtl/instance.hxx>
#include <rtl/math.hxx>
#include <rtl/ref.hxx>
-#include <rtl/strbuf.h>
#include <rtl/string.h>
#include <rtl/string.hxx>
#include <rtl/stringconcat.hxx>
#include <rtl/stringutils.hxx>
#include <rtl/textenc.h>
+#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.h>
#include <rtl/ustring.hxx>
-#include <sal/config.h>
#include <sal/detail/log.h>
#include <sal/log.hxx>
#include <sal/types.h>
#include <vcl/bitmap.hxx>
-#include <vcl/bitmapex.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/dllapi.h>
#include <vcl/graph.hxx>
@@ -68,7 +70,6 @@
#if PCH_LEVEL >= 3
#include <basegfx/basegfxdllapi.h>
#include <basegfx/color/bcolor.hxx>
-#include <basegfx/color/bcolormodifier.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>
@@ -90,7 +91,6 @@
#include <basegfx/range/basicrange.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/tuple/b3dtuple.hxx>
-#include <basegfx/utils/canvastools.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/vector/b2enums.hxx>
#include <basegfx/vector/b2ivector.hxx>
@@ -102,7 +102,7 @@
#include <com/sun/star/drawing/TextureMode.hpp>
#include <com/sun/star/drawing/TextureProjectionMode.hpp>
#include <com/sun/star/graphic/XPrimitive3D.hpp>
-#include <com/sun/star/util/XAccounting.hpp>
+#include <com/sun/star/uno/Sequence.h>
#include <comphelper/comphelperdllapi.h>
#include <comphelper/processfactory.hxx>
#include <comphelper/sequence.hxx>
@@ -113,22 +113,28 @@
#include <o3tl/cow_wrapper.hxx>
#include <o3tl/strong_int.hxx>
#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/unit_conversion.hxx>
#include <salhelper/simplereferenceobject.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <tools/color.hxx>
+#include <tools/degree.hxx>
#include <tools/fontenum.hxx>
#include <tools/gen.hxx>
-#include <tools/link.hxx>
+#include <tools/long.hxx>
#include <tools/stream.hxx>
#include <tools/toolsdllapi.h>
#endif // PCH_LEVEL >= 3
#if PCH_LEVEL >= 4
#include <drawinglayer/attribute/fillgradientattribute.hxx>
+#include <drawinglayer/attribute/fillgraphicattribute.hxx>
#include <drawinglayer/attribute/fontattribute.hxx>
#include <drawinglayer/attribute/lineattribute.hxx>
#include <drawinglayer/attribute/materialattribute3d.hxx>
#include <drawinglayer/attribute/sdrallattribute3d.hxx>
#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
+#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
#include <drawinglayer/attribute/sdrobjectattribute3d.hxx>
@@ -136,17 +142,18 @@
#include <drawinglayer/drawinglayerdllapi.h>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/geometry/viewinformation3d.hxx>
-#include <drawinglayer/primitive2d/CommonTypes.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokeArrowPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
#include <drawinglayer/primitive2d/Primitive2DVisitor.hxx>
-#include <drawinglayer/primitive2d/Tools.hxx>
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
@@ -163,8 +170,8 @@
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
+#include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
diff --git a/drawinglayer/inc/pch/precompiled_drawinglayercore.cxx b/drawinglayer/inc/pch/precompiled_drawinglayercore.cxx
new file mode 100644
index 000000000000..4a8c23ea8e65
--- /dev/null
+++ b/drawinglayer/inc/pch/precompiled_drawinglayercore.cxx
@@ -0,0 +1,12 @@
+/* -*- 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/.
+ */
+
+#include "precompiled_drawinglayercore.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/pch/precompiled_drawinglayercore.hxx b/drawinglayer/inc/pch/precompiled_drawinglayercore.hxx
new file mode 100644
index 000000000000..9912df042380
--- /dev/null
+++ b/drawinglayer/inc/pch/precompiled_drawinglayercore.hxx
@@ -0,0 +1,52 @@
+/* -*- 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-12-23 08:57:20 using:
+ ./bin/update_pch drawinglayer drawinglayercore --cutoff=3 --exclude:system --exclude:module --exclude:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./drawinglayer/inc/pch/precompiled_drawinglayercore.hxx "make drawinglayer.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <deque>
+#include <ostream>
+#include <vector>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <sal/types.h>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/basicrange.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/utils/canvastools.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <drawinglayer/drawinglayerdllapi.h>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/CommonTypes.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <drawinglayer/primitive2d/Primitive2DVisitor.hxx>
+#include <drawinglayer/primitive2d/Tools.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/cropprimitive2d.hxx b/drawinglayer/inc/primitive2d/cropprimitive2d.hxx
index ba427eb6fba6..e1c66cffab27 100644
--- a/drawinglayer/inc/primitive2d/cropprimitive2d.hxx
+++ b/drawinglayer/inc/primitive2d/cropprimitive2d.hxx
@@ -19,14 +19,11 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
-namespace drawinglayer
-{
- namespace primitive2d
+namespace drawinglayer::primitive2d
{
/** CropPrimitive2D class
@@ -67,8 +64,8 @@ namespace drawinglayer
public:
/// constructor
CropPrimitive2D(
- const Primitive2DContainer& rChildren,
- const basegfx::B2DHomMatrix& rTransformation,
+ Primitive2DContainer&& aChildren,
+ basegfx::B2DHomMatrix aTransformation,
double fCropLeft,
double fCropTop,
double fCropRight,
@@ -90,7 +87,7 @@ namespace drawinglayer
/// provide unique ID
virtual sal_uInt32 getPrimitive2DID() const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/graphicprimitivehelper2d.hxx b/drawinglayer/inc/primitive2d/graphicprimitivehelper2d.hxx
deleted file mode 100644
index fb1431152b16..000000000000
--- a/drawinglayer/inc/primitive2d/graphicprimitivehelper2d.hxx
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- 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 <drawinglayer/primitive2d/baseprimitive2d.hxx>
-#include <vcl/GraphicObject.hxx>
-
-class Graphic;
-
-namespace drawinglayer::primitive2d
-{
- /** Helper method with supports decomposing a Graphic with all
- possible contents to lower level primitives.
-
- #i121194# Unified to use this helper for FillGraphicPrimitive2D
- and GraphicPrimitive2D at the same time. It is able to handle
- Bitmaps (with the sub-categories animated bitmap, and SVG),
- and Metafiles.
- */
- void create2DDecompositionOfGraphic(
- Primitive2DContainer& rContainer,
- const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform);
-
- /** Helper to embed given sequence of primitives to evtl. a stack
- of ModifiedColorPrimitive2D's to get all the needed modifications
- applied.
- */
- Primitive2DContainer create2DColorModifierEmbeddingsAsNeeded(
- const Primitive2DContainer& rChildren,
- GraphicDrawMode aGraphicDrawMode,
- double fLuminance = 0.0, // [-1.0 .. 1.0]
- double fContrast = 0.0, // [-1.0 .. 1.0]
- double fRed = 0.0, // [-1.0 .. 1.0]
- double fGreen = 0.0, // [-1.0 .. 1.0]
- double fBlue = 0.0, // [-1.0 .. 1.0]
- double fGamma = 1.0, // ]0.0 .. 10.0]
- bool bInvert = false);
-
-} // end of namespace drawinglayer::primitive2d
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx b/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx
index a39256453f17..8512f64114af 100644
--- a/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx
+++ b/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx
@@ -19,82 +19,77 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
-
-namespace drawinglayer
+namespace drawinglayer::primitive2d
{
- namespace primitive2d
- {
- /** TextEffectStyle2D definition */
- enum class TextEffectStyle2D
- {
- ReliefEmbossedDefault,
- ReliefEngravedDefault,
- ReliefEmbossed,
- ReliefEngraved,
- Outline
- };
-
- /** TextEffectPrimitive2D class
-
- This primitive embeds text primitives (normally, as can be seen can
- also be used for any other primitives) which have some TextEffect applied
- and create the needed geometry and embedding on decomposition.
- */
- class TextEffectPrimitive2D final : public BufferedDecompositionPrimitive2D
- {
- private:
- /// the text (or other) content
- Primitive2DContainer maTextContent;
-
- /// the style to apply, the direction and the rotation center
- const basegfx::B2DPoint maRotationCenter;
- double mfDirection;
- TextEffectStyle2D meTextEffectStyle2D;
-
- /** the last used object to view transformtion used from getDecomposition
- for decide buffering
- */
- basegfx::B2DHomMatrix maLastObjectToViewTransformation;
-
- /// create local decomposition
- virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
-
- public:
- /// constructor
- TextEffectPrimitive2D(
- const Primitive2DContainer& rTextContent,
- const basegfx::B2DPoint& rRotationCenter,
- double fDirection,
- TextEffectStyle2D eTextEffectStyle2D);
-
- /// data read access
- const Primitive2DContainer& getTextContent() const { return maTextContent; }
- const basegfx::B2DPoint& getRotationCenter() const { return maRotationCenter; }
- double getDirection() const { return mfDirection; }
- TextEffectStyle2D getTextEffectStyle2D() const { return meTextEffectStyle2D; }
-
- /// compare operator
- virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
-
- /** own get range implementation to solve more effective. Content is by definition displaced
- by a fixed discrete unit, thus the contained geometry needs only once be asked for its
- own basegfx::B2DRange
- */
- virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
-
- /// provide unique ID
- virtual sal_uInt32 getPrimitive2DID() const override;
-
- /// Override standard getDecomposition to be view-dependent here
- virtual void get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const override;
- };
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
-
+/** TextEffectStyle2D definition */
+enum class TextEffectStyle2D
+{
+ ReliefEmbossedDefault,
+ ReliefEngravedDefault,
+ ReliefEmbossed,
+ Outline
+};
+
+/** TextEffectPrimitive2D class
+
+ This primitive embeds text primitives (normally, as can be seen can
+ also be used for any other primitives) which have some TextEffect applied
+ and create the needed geometry and embedding on decomposition.
+*/
+class TextEffectPrimitive2D final : public BufferedDecompositionPrimitive2D
+{
+private:
+ /// the text (or other) content
+ Primitive2DContainer maTextContent;
+
+ /// the style to apply, the direction and the rotation center
+ const basegfx::B2DPoint maRotationCenter;
+ double mfDirection;
+ TextEffectStyle2D meTextEffectStyle2D;
+
+ /** the last used object to view transformtion used from getDecomposition
+ for decide buffering
+ */
+ basegfx::B2DHomMatrix maLastObjectToViewTransformation;
+
+ /// create local decomposition
+ virtual Primitive2DReference
+ create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
+
+public:
+ /// constructor
+ TextEffectPrimitive2D(Primitive2DContainer&& rTextContent,
+ const basegfx::B2DPoint& rRotationCenter, double fDirection,
+ TextEffectStyle2D eTextEffectStyle2D);
+
+ /// data read access
+ const Primitive2DContainer& getTextContent() const { return maTextContent; }
+ const basegfx::B2DPoint& getRotationCenter() const { return maRotationCenter; }
+ double getDirection() const { return mfDirection; }
+ TextEffectStyle2D getTextEffectStyle2D() const { return meTextEffectStyle2D; }
+
+ /// compare operator
+ virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+
+ /** own get range implementation to solve more effective. Content is by definition displaced
+ by a fixed discrete unit, thus the contained geometry needs only once be asked for its
+ own basegfx::B2DRange
+ */
+ virtual basegfx::B2DRange
+ getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
+
+ /// provide unique ID
+ virtual sal_uInt32 getPrimitive2DID() const override;
+
+ /// Override standard getDecomposition to be view-dependent here
+ virtual void
+ get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const override;
+};
+
+} // end of namespace primitive2d::drawinglayer
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/textlineprimitive2d.hxx b/drawinglayer/inc/primitive2d/textlineprimitive2d.hxx
index 059c69bd7ca3..904ee38e31c6 100644
--- a/drawinglayer/inc/primitive2d/textlineprimitive2d.hxx
+++ b/drawinglayer/inc/primitive2d/textlineprimitive2d.hxx
@@ -19,17 +19,13 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
#include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/color/bcolor.hxx>
-namespace drawinglayer
-{
- namespace primitive2d
+namespace drawinglayer::primitive2d
{
class TextLinePrimitive2D final : public BufferedDecompositionPrimitive2D
{
@@ -45,12 +41,12 @@ namespace drawinglayer
basegfx::BColor maLineColor;
/// local decomposition.
- virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
+ virtual Primitive2DReference create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
public:
/// constructor
TextLinePrimitive2D(
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
double fWidth,
double fOffset,
double fHeight,
@@ -71,8 +67,8 @@ namespace drawinglayer
/// provide unique ID
virtual sal_uInt32 getPrimitive2DID() const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/textstrikeoutprimitive2d.hxx b/drawinglayer/inc/primitive2d/textstrikeoutprimitive2d.hxx
index 1e1e75f7ced1..ffb8c144e77f 100644
--- a/drawinglayer/inc/primitive2d/textstrikeoutprimitive2d.hxx
+++ b/drawinglayer/inc/primitive2d/textstrikeoutprimitive2d.hxx
@@ -19,9 +19,7 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
#include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/color/bcolor.hxx>
@@ -29,9 +27,7 @@
#include <com/sun/star/lang/Locale.hpp>
-namespace drawinglayer
-{
- namespace primitive2d
+namespace drawinglayer::primitive2d
{
class BaseTextStrikeoutPrimitive2D : public BufferedDecompositionPrimitive2D
{
@@ -46,7 +42,7 @@ namespace drawinglayer
public:
/// constructor
BaseTextStrikeoutPrimitive2D(
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
double fWidth,
const basegfx::BColor& rFontColor);
@@ -58,13 +54,11 @@ namespace drawinglayer
/// compare operator
virtual bool operator==( const BasePrimitive2D& rPrimitive ) const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive2d
-namespace drawinglayer
-{
- namespace primitive2d
+namespace drawinglayer::primitive2d
{
class TextCharacterStrikeoutPrimitive2D final : public BaseTextStrikeoutPrimitive2D
{
@@ -74,7 +68,7 @@ namespace drawinglayer
css::lang::Locale maLocale;
/// local decomposition.
- virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
+ virtual Primitive2DReference create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
public:
/// constructor
@@ -83,8 +77,8 @@ namespace drawinglayer
double fWidth,
const basegfx::BColor& rFontColor,
sal_Unicode aStrikeoutChar,
- const attribute::FontAttribute& rFontAttribute,
- const css::lang::Locale& rLocale);
+ attribute::FontAttribute aFontAttribute,
+ css::lang::Locale aLocale);
/// data read access
sal_Unicode getStrikeoutChar() const { return maStrikeoutChar; }
@@ -97,13 +91,11 @@ namespace drawinglayer
/// provide unique ID
virtual sal_uInt32 getPrimitive2DID() const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::primitive2d
-namespace drawinglayer
-{
- namespace primitive2d
+
+namespace drawinglayer::primitive2d
{
class TextGeometryStrikeoutPrimitive2D final : public BaseTextStrikeoutPrimitive2D
{
@@ -113,7 +105,7 @@ namespace drawinglayer
TextStrikeout meTextStrikeout;
/// local decomposition.
- virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
+ virtual Primitive2DReference create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
public:
/// constructor
@@ -136,8 +128,8 @@ namespace drawinglayer
/// provide unique ID
virtual sal_uInt32 getPrimitive2DID() const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive2d/wallpaperprimitive2d.hxx b/drawinglayer/inc/primitive2d/wallpaperprimitive2d.hxx
index a8e4b158f30e..f92f2378a2aa 100644
--- a/drawinglayer/inc/primitive2d/wallpaperprimitive2d.hxx
+++ b/drawinglayer/inc/primitive2d/wallpaperprimitive2d.hxx
@@ -19,16 +19,12 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
-#include <vcl/bitmapex.hxx>
+#include <vcl/bitmap.hxx>
#include <vcl/wall.hxx>
-namespace drawinglayer
-{
- namespace primitive2d
+namespace drawinglayer::primitive2d
{
/** WallpaperBitmapPrimitive2D class
@@ -47,22 +43,22 @@ namespace drawinglayer
{
private:
basegfx::B2DRange maObjectRange;
- BitmapEx maBitmapEx;
+ Bitmap maBitmap;
WallpaperStyle meWallpaperStyle;
/// create local decomposition
- virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
+ virtual Primitive2DReference create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
public:
/// constructor
WallpaperBitmapPrimitive2D(
const basegfx::B2DRange& rObjectRange,
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
WallpaperStyle eWallpaperStyle);
/// data read access
const basegfx::B2DRange& getLocalObjectRange() const { return maObjectRange; }
- const BitmapEx& getBitmapEx() const { return maBitmapEx ; }
+ const Bitmap& getBitmap() const { return maBitmap; }
WallpaperStyle getWallpaperStyle() const { return meWallpaperStyle; }
/// compare operator
@@ -74,7 +70,7 @@ namespace drawinglayer
/// provide unique ID
virtual sal_uInt32 getPrimitive2DID() const override;
};
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/hatchtextureprimitive3d.hxx b/drawinglayer/inc/primitive3d/hatchtextureprimitive3d.hxx
index 1329bf70647f..a60c4da9d0a8 100644
--- a/drawinglayer/inc/primitive3d/hatchtextureprimitive3d.hxx
+++ b/drawinglayer/inc/primitive3d/hatchtextureprimitive3d.hxx
@@ -19,15 +19,11 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <primitive3d/textureprimitive3d.hxx>
#include <drawinglayer/attribute/fillhatchattribute.hxx>
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** HatchTexturePrimitive3D class
@@ -53,7 +49,7 @@ namespace drawinglayer
public:
/// constructor
HatchTexturePrimitive3D(
- const attribute::FillHatchAttribute& rHatch,
+ attribute::FillHatchAttribute aHatch,
const Primitive3DContainer& rChildren,
const basegfx::B2DVector& rTextureSize,
bool bModulate,
@@ -71,8 +67,8 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/hiddengeometryprimitive3d.hxx b/drawinglayer/inc/primitive3d/hiddengeometryprimitive3d.hxx
index 246abe38a664..45de83380bf5 100644
--- a/drawinglayer/inc/primitive3d/hiddengeometryprimitive3d.hxx
+++ b/drawinglayer/inc/primitive3d/hiddengeometryprimitive3d.hxx
@@ -19,14 +19,10 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive3d/groupprimitive3d.hxx>
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
// This primitive is used to represent geometry for non-visible objects,
// e.g. a 3D cube without fill attributes. To still be able to use
@@ -54,8 +50,8 @@ namespace drawinglayer
// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/polygontubeprimitive3d.hxx b/drawinglayer/inc/primitive3d/polygontubeprimitive3d.hxx
index e27201ad6a12..38372977e1c4 100644
--- a/drawinglayer/inc/primitive3d/polygontubeprimitive3d.hxx
+++ b/drawinglayer/inc/primitive3d/polygontubeprimitive3d.hxx
@@ -19,14 +19,10 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** PolygonStrokePrimitive3D class
@@ -85,8 +81,8 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/sdrdecompositiontools3d.hxx b/drawinglayer/inc/primitive3d/sdrdecompositiontools3d.hxx
index 9a4d62cbc24f..6e549289b24c 100644
--- a/drawinglayer/inc/primitive3d/sdrdecompositiontools3d.hxx
+++ b/drawinglayer/inc/primitive3d/sdrdecompositiontools3d.hxx
@@ -19,8 +19,6 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive3d/baseprimitive3d.hxx>
#include <com/sun/star/drawing/TextureProjectionMode.hpp>
#include <vector>
@@ -43,9 +41,7 @@ namespace drawinglayer::attribute {
}
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
// #i98295#
basegfx::B3DRange getRangeFrom3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill);
@@ -85,8 +81,7 @@ namespace drawinglayer
const basegfx::B2DVector& rTextureSize,
const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute);
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/shadowprimitive3d.hxx b/drawinglayer/inc/primitive3d/shadowprimitive3d.hxx
index 60ec61fe7dff..06d4e9f49d77 100644
--- a/drawinglayer/inc/primitive3d/shadowprimitive3d.hxx
+++ b/drawinglayer/inc/primitive3d/shadowprimitive3d.hxx
@@ -19,16 +19,12 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive3d/groupprimitive3d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/color/bcolor.hxx>
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** ShadowPrimitive3D class
@@ -52,7 +48,7 @@ namespace drawinglayer
public:
/// constructor
ShadowPrimitive3D(
- const basegfx::B2DHomMatrix& rShadowTransform,
+ basegfx::B2DHomMatrix aShadowTransform,
const basegfx::BColor& rShadowColor,
double fShadowTransparence,
bool bShadow3D,
@@ -70,8 +66,8 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/primitive3d/textureprimitive3d.hxx b/drawinglayer/inc/primitive3d/textureprimitive3d.hxx
index 0dc3ed4d3b19..56586217bdff 100644
--- a/drawinglayer/inc/primitive3d/textureprimitive3d.hxx
+++ b/drawinglayer/inc/primitive3d/textureprimitive3d.hxx
@@ -19,17 +19,13 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/primitive3d/groupprimitive3d.hxx>
#include <drawinglayer/attribute/fillgraphicattribute.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <drawinglayer/attribute/fillgradientattribute.hxx>
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** TexturePrimitive3D class
@@ -65,13 +61,11 @@ namespace drawinglayer
/// compare operator
virtual bool operator==(const BasePrimitive3D& rPrimitive) const override;
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** UnifiedTransparenceTexturePrimitive3D class
@@ -106,13 +100,11 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::primitive3d
-namespace drawinglayer
-{
- namespace primitive3d
+
+namespace drawinglayer::primitive3d
{
/** GradientTexturePrimitive3D class
@@ -129,7 +121,7 @@ namespace drawinglayer
public:
/// constructor
GradientTexturePrimitive3D(
- const attribute::FillGradientAttribute& rGradient,
+ attribute::FillGradientAttribute aGradient,
const Primitive3DContainer& rChildren,
const basegfx::B2DVector& rTextureSize,
bool bModulate,
@@ -144,13 +136,11 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::primitive3d
-namespace drawinglayer
-{
- namespace primitive3d
+
+namespace drawinglayer::primitive3d
{
/** BitmapTexturePrimitive3D class
@@ -182,13 +172,11 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
-namespace drawinglayer
-{
- namespace primitive3d
+namespace drawinglayer::primitive3d
{
/** TransparenceTexturePrimitive3D class
@@ -212,8 +200,8 @@ namespace drawinglayer
/// provide unique ID
DeclPrimitive3DIDBlock()
};
- } // end of namespace primitive3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::primitive3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/processor3d/defaultprocessor3d.hxx b/drawinglayer/inc/processor3d/defaultprocessor3d.hxx
index f23a826a669e..aace2ef87742 100644
--- a/drawinglayer/inc/processor3d/defaultprocessor3d.hxx
+++ b/drawinglayer/inc/processor3d/defaultprocessor3d.hxx
@@ -22,7 +22,6 @@
#include <drawinglayer/processor3d/baseprocessor3d.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/color/bcolormodifier.hxx>
-#include <svtools/optionsdrawinglayer.hxx>
// predefines
@@ -52,9 +51,7 @@ namespace drawinglayer::texture {
}
-namespace drawinglayer
-{
- namespace processor3d
+namespace drawinglayer::processor3d
{
/** DefaultProcessor3D class
@@ -85,9 +82,6 @@ namespace drawinglayer
/// the current active transparence texture
std::shared_ptr< texture::GeoTexSvx > mpTransparenceGeoTexSvx;
- /// SvtOptionsDrawinglayer incarnation to react on diverse settings
- const SvtOptionsDrawinglayer maDrawinglayerOpt;
-
/// counter for entered transparence textures
sal_uInt32 mnTransparenceCounter;
@@ -135,12 +129,9 @@ namespace drawinglayer
bool getModulate() const { return mbModulate; }
bool getFilter() const { return mbFilter; }
bool getSimpleTextureActive() const { return mbSimpleTextureActive; }
-
- /// access to Drawinglayer configuration options
- const SvtOptionsDrawinglayer& getOptionsDrawinglayer() const { return maDrawinglayerOpt; }
};
- } // end of namespace processor3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::processor3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/processor3d/geometry2dextractor.hxx b/drawinglayer/inc/processor3d/geometry2dextractor.hxx
index ae3050fb2850..8d78110c8dcf 100644
--- a/drawinglayer/inc/processor3d/geometry2dextractor.hxx
+++ b/drawinglayer/inc/processor3d/geometry2dextractor.hxx
@@ -19,17 +19,13 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/processor3d/baseprocessor3d.hxx>
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/color/bcolormodifier.hxx>
-namespace drawinglayer
-{
- namespace processor3d
+namespace drawinglayer::processor3d
{
/** Geometry2DExtractingProcessor class
@@ -57,14 +53,14 @@ namespace drawinglayer
public:
Geometry2DExtractingProcessor(
const geometry::ViewInformation3D& rViewInformation,
- const basegfx::B2DHomMatrix& rObjectTransformation);
+ basegfx::B2DHomMatrix aObjectTransformation);
// data read access
const primitive2d::Primitive2DContainer& getPrimitive2DSequence() const { return maPrimitive2DSequence; }
const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
};
- } // end of namespace processor3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::processor3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/processor3d/shadow3dextractor.hxx b/drawinglayer/inc/processor3d/shadow3dextractor.hxx
index 37c1c0f0e6fc..64890b7a630a 100644
--- a/drawinglayer/inc/processor3d/shadow3dextractor.hxx
+++ b/drawinglayer/inc/processor3d/shadow3dextractor.hxx
@@ -19,10 +19,8 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <drawinglayer/processor3d/baseprocessor3d.hxx>
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
@@ -32,9 +30,7 @@ namespace basegfx { class B3DPolyPolygon; }
namespace basegfx { class B3DPolygon; }
-namespace drawinglayer
-{
- namespace processor3d
+namespace drawinglayer::processor3d
{
/** Shadow3DExtractingProcessor class
@@ -82,7 +78,7 @@ namespace drawinglayer
public:
Shadow3DExtractingProcessor(
const geometry::ViewInformation3D& rViewInformation,
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
const basegfx::B3DVector& rLightNormal,
double fShadowSlant,
const basegfx::B3DRange& rContained3DRange);
@@ -93,7 +89,7 @@ namespace drawinglayer
const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
const basegfx::B3DHomMatrix& getWorldToEye() const { return maWorldToEye; }
};
- } // end of namespace processor3d
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::processor3d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/processor3d/zbufferprocessor3d.hxx b/drawinglayer/inc/processor3d/zbufferprocessor3d.hxx
index 9a0b422ac380..0348c56f1f3c 100644
--- a/drawinglayer/inc/processor3d/zbufferprocessor3d.hxx
+++ b/drawinglayer/inc/processor3d/zbufferprocessor3d.hxx
@@ -27,20 +27,16 @@ namespace basegfx {
class BZPixelRaster;
}
-namespace drawinglayer {
- namespace attribute {
+namespace drawinglayer::attribute {
class SdrSceneAttribute;
class SdrLightingAttribute;
- class MaterialAttribute3D;
- }
}
+
class ZBufferRasterConverter3D;
class RasterPrimitive3D;
-namespace drawinglayer
-{
- namespace processor3d
+namespace drawinglayer::processor3d
{
/**
This 3D renderer derived from DefaultProcessor3D renders all fed primitives to a 2D
@@ -64,7 +60,7 @@ namespace drawinglayer
/* remembered RasterPrimitive3D's which need to be painted back to front
for transparent 3D parts
*/
- std::unique_ptr<std::vector< RasterPrimitive3D >> mpRasterPrimitive3Ds;
+ mutable std::vector< RasterPrimitive3D > maRasterPrimitive3Ds;
sal_uInt32 mnStartLine;
sal_uInt32 mnStopLine;
@@ -90,7 +86,7 @@ namespace drawinglayer
void finish();
};
- }
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/texture/texture.hxx b/drawinglayer/inc/texture/texture.hxx
index 24e23a4b241c..aa6e79515b37 100644
--- a/drawinglayer/inc/texture/texture.hxx
+++ b/drawinglayer/inc/texture/texture.hxx
@@ -19,8 +19,6 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/color/bcolor.hxx>
@@ -45,28 +43,24 @@ namespace drawinglayer::texture
virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const;
};
- /// helper class for processing equal number of matrices and colors
- /// for texture processing
- struct B2DHomMatrixAndBColor
- {
- basegfx::B2DHomMatrix maB2DHomMatrix;
- basegfx::BColor maBColor;
- };
-
class GeoTexSvxGradient : public GeoTexSvx
{
protected:
basegfx::ODFGradientInfo maGradientInfo;
basegfx::B2DRange maDefinitionRange;
- basegfx::BColor maStart;
- basegfx::BColor maEnd;
+ sal_uInt32 mnRequestedSteps;
+ basegfx::BColorStops mnColorStops;
double mfBorder;
+ // provide a single buffer entry used for gradient texture
+ // mapping, see ::modifyBColor implementations
+ mutable basegfx::BColorStops::BColorStopRange maLastColorStopRange;
+
public:
GeoTexSvxGradient(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder);
virtual ~GeoTexSvxGradient() override;
@@ -75,8 +69,7 @@ namespace drawinglayer::texture
// virtual base methods
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) = 0;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) = 0;
};
class GeoTexSvxGradientLinear final : public GeoTexSvxGradient
@@ -89,16 +82,14 @@ namespace drawinglayer::texture
GeoTexSvxGradientLinear(
const basegfx::B2DRange& rDefinitionRange,
const basegfx::B2DRange& rOutputRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fAngle);
virtual ~GeoTexSvxGradientLinear() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
@@ -111,16 +102,14 @@ namespace drawinglayer::texture
GeoTexSvxGradientAxial(
const basegfx::B2DRange& rDefinitionRange,
const basegfx::B2DRange& rOutputRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fAngle);
virtual ~GeoTexSvxGradientAxial() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
@@ -129,17 +118,15 @@ namespace drawinglayer::texture
public:
GeoTexSvxGradientRadial(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY);
virtual ~GeoTexSvxGradientRadial() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
@@ -148,9 +135,8 @@ namespace drawinglayer::texture
public:
GeoTexSvxGradientElliptical(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
@@ -158,8 +144,7 @@ namespace drawinglayer::texture
virtual ~GeoTexSvxGradientElliptical() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
@@ -168,9 +153,8 @@ namespace drawinglayer::texture
public:
GeoTexSvxGradientSquare(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
@@ -178,8 +162,7 @@ namespace drawinglayer::texture
virtual ~GeoTexSvxGradientSquare() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
@@ -188,9 +171,8 @@ namespace drawinglayer::texture
public:
GeoTexSvxGradientRect(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
@@ -198,8 +180,7 @@ namespace drawinglayer::texture
virtual ~GeoTexSvxGradientRect() override;
virtual void appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) override;
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback) override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
};
diff --git a/drawinglayer/inc/texture/texture3d.hxx b/drawinglayer/inc/texture/texture3d.hxx
index 47ef9ff450a1..cf076881a061 100644
--- a/drawinglayer/inc/texture/texture3d.hxx
+++ b/drawinglayer/inc/texture/texture3d.hxx
@@ -19,18 +19,15 @@
#pragma once
-#include <drawinglayer/drawinglayerdllapi.h>
-
#include <texture/texture.hxx>
-#include <vcl/bitmapex.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/BitmapReadAccess.hxx>
namespace drawinglayer::primitive3d {
class HatchTexturePrimitive3D;
}
-namespace drawinglayer
-{
- namespace texture
+namespace drawinglayer::texture
{
class GeoTexSvxMono final : public GeoTexSvx
{
@@ -47,48 +44,37 @@ namespace drawinglayer
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const override;
};
- } // end of namespace texture
-} // end of namespace drawinglayer
-namespace drawinglayer
-{
- namespace texture
+} // end of namespace drawinglayer::texture
+
+namespace drawinglayer::texture
{
class GeoTexSvxBitmapEx : public GeoTexSvx
{
protected:
- BitmapEx maBitmapEx;
- Bitmap maBitmap; // Bitmap held within maBitmapEx, to exist during mpReadBitmap scope
- Bitmap::ScopedReadAccess mpReadBitmap;
- Bitmap maTransparence;
- Bitmap::ScopedReadAccess mpReadTransparence;
+ Bitmap maBitmap;
+ BitmapScopedReadAccess mpReadBitmap;
basegfx::B2DPoint maTopLeft;
basegfx::B2DVector maSize;
double mfMulX;
double mfMulY;
- bool mbIsAlpha : 1;
- bool mbIsTransparent : 1;
-
// helpers
bool impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const;
- sal_uInt8 impGetTransparence(sal_Int32 rX, sal_Int32 rY) const;
public:
GeoTexSvxBitmapEx(
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
const basegfx::B2DRange& rRange);
virtual ~GeoTexSvxBitmapEx() override;
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const override;
};
- } // end of namespace texture
-} // end of namespace drawinglayer
-namespace drawinglayer
-{
- namespace texture
+} // end of namespace drawinglayer::texture
+
+namespace drawinglayer::texture
{
class GeoTexSvxBitmapExTiled final : public GeoTexSvxBitmapEx
{
@@ -103,7 +89,7 @@ namespace drawinglayer
public:
GeoTexSvxBitmapExTiled(
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
const basegfx::B2DRange& rRange,
double fOffsetX,
double fOffsetY);
@@ -111,12 +97,10 @@ namespace drawinglayer
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const override;
};
- } // end of namespace texture
-} // end of namespace drawinglayer
-namespace drawinglayer
-{
- namespace texture
+} // end of namespace drawinglayer::texture
+
+namespace drawinglayer::texture
{
class GeoTexSvxMultiHatch final : public GeoTexSvx
{
@@ -137,7 +121,7 @@ namespace drawinglayer
virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const override;
virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const override;
};
- } // end of namespace texture
-} // end of namespace drawinglayer
+
+} // end of namespace drawinglayer::texture
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/wmfemfhelper.hxx b/drawinglayer/inc/wmfemfhelper.hxx
index 214d2a5d785c..f085065c1ea6 100644
--- a/drawinglayer/inc/wmfemfhelper.hxx
+++ b/drawinglayer/inc/wmfemfhelper.hxx
@@ -22,10 +22,10 @@
#include <sal/config.h>
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <vcl/font.hxx>
-#include <vcl/outdevstate.hxx>
+#include <rtl/ref.hxx>
+#include <vcl/rendercontext/State.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <memory>
// predefines
namespace drawinglayer::geometry { class ViewInformation2D; }
@@ -43,19 +43,24 @@ namespace wmfemfhelper
class TargetHolder
{
private:
- std::vector< std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> > aTargets;
+ drawinglayer::primitive2d::Primitive2DContainer aTargets;
public:
TargetHolder();
~TargetHolder();
sal_uInt32 size() const;
- void append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> pCandidate);
+ void append(const rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> & pCandidate)
+ {
+ append(pCandidate.get());
+ }
+ void append(drawinglayer::primitive2d::Primitive2DContainer xCandidate)
+ {
+ aTargets.append(std::move(xCandidate));
+ }
+ void append(drawinglayer::primitive2d::BasePrimitive2D* pCandidate);
drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequence(const PropertyHolder& rPropertyHolder);
};
-}
-namespace wmfemfhelper
-{
/** Helper class which builds a stack on the TargetHolder class */
class TargetHolders
{
@@ -70,10 +75,7 @@ namespace wmfemfhelper
TargetHolder& Current();
~TargetHolders();
};
-}
-namespace wmfemfhelper
-{
/** helper class for graphic context
This class allows to hold a complete representation of classic
@@ -96,14 +98,14 @@ namespace wmfemfhelper
basegfx::BColor maOverlineColor;
/// clipping
- basegfx::B2DPolyPolygon maClipPolyPoygon;
+ basegfx::B2DPolyPolygon maClipPolyPolygon;
/// font, etc.
vcl::Font maFont;
RasterOp maRasterOp;
- ComplexTextLayoutFlags mnLayoutMode;
+ vcl::text::ComplexTextLayoutFlags mnLayoutMode;
LanguageType maLanguageType;
- PushFlags mnPushFlags;
+ vcl::PushFlags mnPushFlags;
/// contains all active markers
bool mbLineColor : 1;
@@ -154,8 +156,8 @@ namespace wmfemfhelper
bool getOverlineColorActive() const { return mbOverlineColor; }
void setOverlineColorActive(bool bNew) { if (bNew != mbOverlineColor) mbOverlineColor = bNew; }
- const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; }
- void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if (rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; }
+ const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPolygon; }
+ void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if (rNew != maClipPolyPolygon) maClipPolyPolygon = rNew; }
bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; }
void setClipPolyPolygonActive(bool bNew) { if (bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; }
@@ -168,21 +170,18 @@ namespace wmfemfhelper
bool isRasterOpForceBlack() const { return RasterOp::N0 == maRasterOp; }
bool isRasterOpActive() const { return isRasterOpInvert() || isRasterOpForceBlack(); }
- ComplexTextLayoutFlags getLayoutMode() const { return mnLayoutMode; }
- void setLayoutMode(ComplexTextLayoutFlags nNew) { if (nNew != mnLayoutMode) mnLayoutMode = nNew; }
+ vcl::text::ComplexTextLayoutFlags getLayoutMode() const { return mnLayoutMode; }
+ void setLayoutMode(vcl::text::ComplexTextLayoutFlags nNew) { if (nNew != mnLayoutMode) mnLayoutMode = nNew; }
LanguageType getLanguageType() const { return maLanguageType; }
void setLanguageType(LanguageType aNew) { if (aNew != maLanguageType) maLanguageType = aNew; }
- PushFlags getPushFlags() const { return mnPushFlags; }
- void setPushFlags(PushFlags nNew) { if (nNew != mnPushFlags) mnPushFlags = nNew; }
+ vcl::PushFlags getPushFlags() const { return mnPushFlags; }
+ void setPushFlags(vcl::PushFlags nNew) { if (nNew != mnPushFlags) mnPushFlags = nNew; }
bool getLineOrFillActive() const { return (mbLineColor || mbFillColor); }
};
-}
-namespace wmfemfhelper
-{
/** stack for properties
This class builds a stack based on the PropertyHolder
@@ -200,15 +199,12 @@ namespace wmfemfhelper
public:
PropertyHolders();
void PushDefault();
- void Push(PushFlags nPushFlags);
+ void Push(vcl::PushFlags nPushFlags);
void Pop();
PropertyHolder& Current();
~PropertyHolders();
};
-}
-namespace wmfemfhelper
-{
drawinglayer::primitive2d::Primitive2DContainer interpretMetafile(
const GDIMetaFile& rMetaFile,
const drawinglayer::geometry::ViewInformation2D& rViewInformation);
diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx
index 8c4e6e08419b..682bfeb17281 100644
--- a/drawinglayer/qa/unit/border.cxx
+++ b/drawinglayer/qa/unit/border.cxx
@@ -13,9 +13,10 @@
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
-#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
#include <rtl/ref.hxx>
#include <test/bootstrapfixture.hxx>
#include <vcl/metaact.hxx>
@@ -47,22 +48,23 @@ CPPUNIT_TEST_FIXTURE(DrawinglayerBorderTest, testDoubleDecompositionSolid)
double const fExtendRightEnd = 0;
basegfx::BColor aColorRight;
basegfx::BColor aColorLeft;
- const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
- const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
- std::vector<drawinglayer::primitive2d::BorderLine> aBorderlines;
+ std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(std::move(aDashing));
+ std::vector<drawinglayer::primitive2d::BorderLine> aBorderlines{
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(
- drawinglayer::attribute::LineAttribute(aColorLeft, fLeftWidth), fExtendLeftStart,
- fExtendLeftStart, fExtendLeftEnd, fExtendLeftEnd));
+ drawinglayer::primitive2d::BorderLine(
+ drawinglayer::attribute::LineAttribute(aColorLeft, fLeftWidth), fExtendLeftStart,
+ fExtendLeftStart, fExtendLeftEnd, fExtendLeftEnd),
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(fDistance));
+ drawinglayer::primitive2d::BorderLine(fDistance),
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(
- drawinglayer::attribute::LineAttribute(aColorRight, fRightWidth), fExtendRightStart,
- fExtendRightStart, fExtendRightEnd, fExtendRightEnd));
+ drawinglayer::primitive2d::BorderLine(
+ drawinglayer::attribute::LineAttribute(aColorRight, fRightWidth), fExtendRightStart,
+ fExtendRightStart, fExtendRightEnd, fExtendRightEnd)
+ };
rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder(
- new drawinglayer::primitive2d::BorderLinePrimitive2D(aStart, aEnd, aBorderlines,
+ new drawinglayer::primitive2d::BorderLinePrimitive2D(aStart, aEnd, std::move(aBorderlines),
aStrokeAttribute));
// Decompose it into polygons.
@@ -71,11 +73,14 @@ CPPUNIT_TEST_FIXTURE(DrawinglayerBorderTest, testDoubleDecompositionSolid)
aBorder->get2DDecomposition(aContainer, aView);
// Make sure it results in two borders as it's a double one.
- CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), aContainer.size());
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), aContainer.size());
+ auto* pGroupPrimitive
+ = dynamic_cast<const drawinglayer::primitive2d::GroupPrimitive2D*>(aContainer[0].get());
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), pGroupPrimitive->getChildren().size());
// Get the inside line, now a PolygonStrokePrimitive2D
auto pInside = dynamic_cast<const drawinglayer::primitive2d::PolygonStrokePrimitive2D*>(
- aContainer[0].get());
+ pGroupPrimitive->getChildren()[0].get());
CPPUNIT_ASSERT(pInside);
// Make sure the inside line's height is fLeftWidth.
@@ -88,15 +93,23 @@ CPPUNIT_TEST_FIXTURE(DrawinglayerBorderTest, testDoubleDecompositionSolid)
CPPUNIT_TEST_FIXTURE(DrawinglayerBorderTest, testDoublePixelProcessing)
{
- // Create a pixel processor.
+ // Creating a pixel-processor and after that attaching a metafile
+ // recording is not possible anymore, the pixel-processor may be
+ // a SDPR, e.g. a CairoSDPR, and *not* a VclPixelProcessor2D anymore.
+ // Since the intention had changed already (see comments below
+ // where it is explained why two lines are expected nowadays)
+ // it is also okay to just use a VclMetafileProcessor2D - to record
+ // a metafile.
ScopedVclPtrInstance<VirtualDevice> pDev;
+ GDIMetaFile aMetaFile;
+ aMetaFile.Record(pDev);
drawinglayer::geometry::ViewInformation2D aView;
+
+ // This creates a VclMetafileProcessor2D - the only processor that
+ // (as the name states) can record metafiles
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
- drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*pDev, aView));
+ drawinglayer::processor2d::createProcessor2DFromOutputDevice(*pDev, aView));
CPPUNIT_ASSERT(pProcessor);
- GDIMetaFile aMetaFile;
- // Start recording after the processor is created, so we can test the pixel processor.
- aMetaFile.Record(pDev);
// Create a border line primitive that's similar to the one from the bugdoc:
// 1.47 pixels is 0.03cm at 130% zoom and 96 DPI.
@@ -111,26 +124,26 @@ CPPUNIT_TEST_FIXTURE(DrawinglayerBorderTest, testDoublePixelProcessing)
double const fExtendRightEnd = 0;
basegfx::BColor aColorRight;
basegfx::BColor aColorLeft;
- const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
- const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
- std::vector<drawinglayer::primitive2d::BorderLine> aBorderlines;
-
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(
- drawinglayer::attribute::LineAttribute(aColorLeft, fLeftWidth), fExtendLeftStart,
- fExtendLeftStart, fExtendLeftEnd, fExtendLeftEnd));
+ std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(std::move(aDashing));
+ std::vector<drawinglayer::primitive2d::BorderLine> aBorderlines{
+ drawinglayer::primitive2d::BorderLine(
+ drawinglayer::attribute::LineAttribute(aColorLeft, fLeftWidth), fExtendLeftStart,
+ fExtendLeftStart, fExtendLeftEnd, fExtendLeftEnd),
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(fDistance));
+ drawinglayer::primitive2d::BorderLine(fDistance),
- aBorderlines.push_back(drawinglayer::primitive2d::BorderLine(
- drawinglayer::attribute::LineAttribute(aColorRight, fRightWidth), fExtendRightStart,
- fExtendRightStart, fExtendRightEnd, fExtendRightEnd));
+ drawinglayer::primitive2d::BorderLine(
+ drawinglayer::attribute::LineAttribute(aColorRight, fRightWidth), fExtendRightStart,
+ fExtendRightStart, fExtendRightEnd, fExtendRightEnd)
+ };
rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder(
- new drawinglayer::primitive2d::BorderLinePrimitive2D(aStart, aEnd, aBorderlines,
+ new drawinglayer::primitive2d::BorderLinePrimitive2D(aStart, aEnd, std::move(aBorderlines),
aStrokeAttribute));
drawinglayer::primitive2d::Primitive2DContainer aPrimitives;
- aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(aBorder.get()));
+ aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(aBorder));
// Process the primitives.
pProcessor->process(aPrimitives);
diff --git a/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx b/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx
new file mode 100644
index 000000000000..7845e1623693
--- /dev/null
+++ b/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx
@@ -0,0 +1,156 @@
+/* -*- 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/.
+ *
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+#include <tools/stream.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <cppcanvas/vclfactory.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+using namespace drawinglayer;
+using namespace com::sun::star;
+
+class VclMetaFileProcessor2DTest : public test::BootstrapFixture
+{
+ VclPtr<VirtualDevice> mVclDevice;
+ uno::Reference<rendering::XCanvas> mCanvas;
+
+ // if enabled - check the result images with:
+ // "xdg-open ./workdir/CppunitTest/drawinglayer_processors.test.core/"
+ static constexpr const bool mbExportBitmap = false;
+
+ void exportDevice(const OUString& filename, const VclPtr<VirtualDevice>& device)
+ {
+ if (mbExportBitmap)
+ {
+ Bitmap aBitmap(device->GetBitmap(Point(0, 0), device->GetOutputSizePixel()));
+ SvFileStream aStream(filename, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmap, aStream);
+ }
+ }
+
+public:
+ VclMetaFileProcessor2DTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ virtual void tearDown() override
+ {
+ mVclDevice.reset();
+ mCanvas = uno::Reference<rendering::XCanvas>();
+ BootstrapFixture::tearDown();
+ }
+
+ void setupCanvas(const Size& size, Color backgroundColor = COL_WHITE, bool alpha = false)
+ {
+ mVclDevice = alpha ? VclPtr<VirtualDevice>::Create(DeviceFormat::WITH_ALPHA)
+ : VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
+ mVclDevice->SetOutputSizePixel(size);
+ mVclDevice->SetBackground(Wallpaper(backgroundColor));
+ mVclDevice->Erase();
+ mCanvas = mVclDevice->GetCanvas();
+ CPPUNIT_ASSERT(mCanvas.is());
+ }
+
+ // Test drawing a dotted line in Impress presentation mode.
+ void testTdf136957()
+ {
+ // Impress presentation mode first draws the slide to a metafile.
+ GDIMetaFile metafile;
+ // I got these values by adding debug output to cppcanvas::internal::ImplRenderer::ImplRenderer().
+ metafile.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ metafile.SetPrefSize(Size(14548, 3350));
+ ScopedVclPtrInstance<VirtualDevice> metadevice;
+ metafile.Record(metadevice);
+ drawinglayer::geometry::ViewInformation2D view;
+ std::unique_ptr<processor2d::BaseProcessor2D> processor(
+ processor2d::createProcessor2DFromOutputDevice(*metadevice, view));
+ CPPUNIT_ASSERT(processor);
+ // Match the values Impress uses.
+ basegfx::B2DPolygon polygon = { { 15601, 0 }, { 15602, 5832 } };
+ attribute::LineAttribute lineAttributes(
+ basegfx::BColor(0.047058823529411764, 0.19607843137254902, 0.17254901960784313), 35,
+ basegfx::B2DLineJoin::Miter, css::drawing::LineCap_ROUND);
+ attribute::StrokeAttribute strokeAttributes({ 0.35, 69.65 });
+ rtl::Reference<primitive2d::PolygonStrokePrimitive2D> strokePrimitive(
+ new primitive2d::PolygonStrokePrimitive2D(polygon, lineAttributes, strokeAttributes));
+ primitive2d::Primitive2DContainer primitives;
+ primitives.push_back(strokePrimitive);
+ processor->process(primitives);
+ metafile.Stop();
+ metafile.WindStart();
+
+ // Now verify that the metafile has the one PolyLine action with the right dashing.
+ int lineActionCount = 0;
+ for (std::size_t i = 0; i < metafile.GetActionSize(); ++i)
+ {
+ const MetaAction* metaAction = metafile.GetAction(i);
+ if (metaAction->GetType() == MetaActionType::POLYLINE)
+ {
+ const MetaPolyLineAction* action
+ = static_cast<const MetaPolyLineAction*>(metaAction);
+
+ CPPUNIT_ASSERT_EQUAL(35.0, action->GetLineInfo().GetWidth());
+ CPPUNIT_ASSERT_EQUAL(LineStyle::Dash, action->GetLineInfo().GetStyle());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), action->GetLineInfo().GetDashCount());
+ CPPUNIT_ASSERT_EQUAL(0.35, action->GetLineInfo().GetDashLen());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), action->GetLineInfo().GetDotCount());
+ CPPUNIT_ASSERT_EQUAL(0.0, action->GetLineInfo().GetDotLen());
+ CPPUNIT_ASSERT_EQUAL(69.65, action->GetLineInfo().GetDistance());
+ lineActionCount++;
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(1, lineActionCount);
+
+ // Now draw the metafile using canvas and verify that the line is drawn.
+ setupCanvas(Size(1920, 1080));
+ cppcanvas::CanvasSharedPtr cppCanvas = cppcanvas::VCLFactory::createCanvas(mCanvas);
+ // I got these matrices from a breakpoint in drawing the polyline, and walking up
+ // the stack to the canvas code.
+ cppCanvas->setTransformation(
+ basegfx::B2DHomMatrix(0.056662828121770453, 0, 0, 0, 0.056640419947506564, 0));
+ cppcanvas::RendererSharedPtr renderer = cppcanvas::VCLFactory::createRenderer(
+ cppCanvas, metafile, cppcanvas::Renderer::Parameters());
+ renderer->setTransformation(basegfx::B2DHomMatrix(14548, 0, -2, 0, 3350, 3431));
+ CPPUNIT_ASSERT(renderer->draw());
+ exportDevice(u"test-tdf136957"_ustr, mVclDevice);
+ Bitmap bitmap = mVclDevice->GetBitmap(Point(), Size(1920, 1080));
+ BitmapScopedReadAccess access(bitmap);
+ // There should be a dotted line, without the fix it wouldn't be there, so check
+ // there's a sufficient amount of non-white pixels and that's the line.
+ int nonWhiteCount = 0;
+ for (tools::Long y = 193; y <= 524; ++y)
+ for (tools::Long x = 883; x <= 885; ++x)
+ if (access->GetColor(y, x) != COL_WHITE)
+ ++nonWhiteCount;
+ CPPUNIT_ASSERT_GREATER(100, nonWhiteCount);
+ }
+
+ CPPUNIT_TEST_SUITE(VclMetaFileProcessor2DTest);
+ CPPUNIT_TEST(testTdf136957);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclMetaFileProcessor2DTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/qa/unit/vclpixelprocessor2d.cxx b/drawinglayer/qa/unit/vclpixelprocessor2d.cxx
new file mode 100644
index 000000000000..bdb46ffeb5af
--- /dev/null
+++ b/drawinglayer/qa/unit/vclpixelprocessor2d.cxx
@@ -0,0 +1,138 @@
+/* -*- 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/.
+ *
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
+
+using namespace drawinglayer;
+
+class VclPixelProcessor2DTest : public test::BootstrapFixture
+{
+ // if enabled - check the result images with:
+ // "xdg-open ./workdir/CppunitTest/drawinglayer_processors.test.core/"
+ static constexpr const bool mbExportBitmap = false;
+
+ void exportDevice(const OUString& filename, const VclPtr<VirtualDevice>& device)
+ {
+ if (mbExportBitmap)
+ {
+ Bitmap aBitmap(device->GetBitmap(Point(0, 0), device->GetOutputSizePixel()));
+ SvFileStream aStream(filename, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmap, aStream);
+ }
+ }
+
+public:
+ VclPixelProcessor2DTest()
+ : BootstrapFixture(true, false)
+ {
+ }
+
+ // Test that drawing only a part of a gradient draws the proper part of it.
+ void testTdf139000()
+ {
+ ScopedVclPtr<VirtualDevice> device
+ = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
+ device->SetOutputSizePixel(Size(100, 200));
+ device->SetBackground(Wallpaper(COL_RED));
+ device->Erase();
+
+ drawinglayer::geometry::ViewInformation2D view;
+ std::unique_ptr<processor2d::BaseProcessor2D> processor(
+ processor2d::createProcessor2DFromOutputDevice(*device, view));
+ CPPUNIT_ASSERT(processor);
+
+ // I stumbled over this when hunting another problem, but I have to correct
+ // this: This test does test something that is not supported. It seems to be
+ // based on the *misunderstanding* that in the version of the constructor of
+ // FillGradientPrimitive2D (and similar others) with two ranges the 2nd
+ // B2DRange parameter 'OutputRange' is a 'clipping' parameter. This is *not*
+ // the case --- it is in fact the *contrary*, it is there to *extend* the
+ // usual definition/paintRange of a gradient:
+ // It was originally needed to correctly display TextFrames (TF) in Writer: If you
+ // have a TF in SW filled with a gradient and that TF has sub-frames, it inherits
+ // the gradient fill. Since you can freely move those sub-TFs even outside the
+ // parent TF there has to be a way to not only paint gradients in their definition
+ // range (classical, all DrawObjects do that), but extended from that. This is
+ // needed e.g. for linear gradients, but - dependent of e.g. the center settings -
+ // also for all other ones, all can have geometry 'outside' the DefinitionRange.
+ // This is now also used in various other locations which is proof that this is
+ // useful and needed. It is possible to see that basic history/reason for this
+ // parameter by following the git history and why and under which circumstances
+ // that parameter was originally added. Other hints are: It is *not* named
+ // 'ClipRange'. Using a B2DRange to define a ClipRange topology would be bad due
+ // to not being transformable, a PolyPolygon would be used in that case. Using as
+ // clipping mechanism would offer a 2nd principle to add clipping for primitives
+ // besides MaskPrimitive2D - always bad style in a sub-system. A quick look
+ // on it's usages gives hints, too.
+ // This means that when defining an outputRange that resides completely *inside*
+ // the definitionRange *no change* at all is done by definition since this does
+ // not *extend* the target area of the gradient paint region at all. If an
+ // implementation does clip and limit output to 'outputRange' that should do no
+ // harm, but is not the expected/reliable way to paint primitives clipped.
+ // That's why all DrawObjects with gradient fill (and other fills do the same)
+ // embed the fill that is defined for a range (usually the BoundRange of a
+ // PolyPolygon) in a MaskPrimitive2D defined by the outline PolyPolygon of the
+ // shape. Nothing speaks against renderers detecting that combination and do
+ // something optimized if they want to, especially SDPRs, but this is not
+ // required. The standard embedded clipping of the implementations of the
+ // MaskPrimitive2D do the right thing.
+ // This test intends to paint the lower part of a gradient, so define the
+ // gradient for the full target range and embed it to a MaskPrimitive2D
+ // defining the lower part of that area to do that.
+
+ basegfx::B2DRange definitionRange(0, 0, 100, 200);
+ basegfx::B2DRange outputRange(0, 100, 100, 200); // Paint only lower half of the gradient.
+
+ const primitive2d::Primitive2DContainer primitives{
+ rtl::Reference<primitive2d::MaskPrimitive2D>(new primitive2d::MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(outputRange)),
+ primitive2d::Primitive2DContainer{
+ rtl::Reference<primitive2d::FillGradientPrimitive2D>(
+ new primitive2d::FillGradientPrimitive2D(
+ definitionRange, attribute::FillGradientAttribute(
+ css::awt::GradientStyle_LINEAR, 0, 0, 0, 0,
+ basegfx::BColorStops(COL_WHITE.getBColor(),
+ COL_BLACK.getBColor())))) }))
+ };
+ processor->process(primitives);
+
+ exportDevice(u"test-tdf139000.png"_ustr, device);
+ Bitmap bitmap = device->GetBitmap(Point(), device->GetOutputSizePixel());
+ BitmapScopedReadAccess access(bitmap);
+ // The upper half should keep its red background color.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), access->GetColor(Point(0, 99)));
+ // First line of the gradient should not be the start color, but something halfway.
+ CPPUNIT_ASSERT_LESS(static_cast<sal_uInt16>(16),
+ access->GetColor(Point(0, 100)).GetColorError(COL_GRAY));
+ // Last line of the gradient should be the end color, or close.
+ CPPUNIT_ASSERT_LESS(static_cast<sal_uInt16>(16),
+ access->GetColor(Point(0, 199)).GetColorError(COL_BLACK));
+ }
+
+ CPPUNIT_TEST_SUITE(VclPixelProcessor2DTest);
+ CPPUNIT_TEST(testTdf139000);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclPixelProcessor2DTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/animation/animationtiming.cxx b/drawinglayer/source/animation/animationtiming.cxx
index 7be8ac2d94e8..364ae899c9ca 100644
--- a/drawinglayer/source/animation/animationtiming.cxx
+++ b/drawinglayer/source/animation/animationtiming.cxx
@@ -116,7 +116,7 @@ namespace drawinglayer::animation
double AnimationEntryLinear::getStateAtTime(double fTime) const
{
- if(basegfx::fTools::more(mfDuration, 0.0))
+ if(mfDuration > 0.0)
{
const double fFactor(fTime / mfDuration);
@@ -193,19 +193,15 @@ namespace drawinglayer::animation
bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const
{
- const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate);
+ const AnimationEntryList* pCompare = dynamic_cast<const AnimationEntryList*>(&rCandidate);
- if(pCompare && mfDuration == pCompare->mfDuration)
+ if (pCompare && mfDuration == pCompare->mfDuration)
{
- for(size_t a(0); a < maEntries.size(); a++)
- {
- if(!(*maEntries[a] == *pCompare->maEntries[a]))
- {
- return false;
- }
- }
-
- return true;
+ return std::equal(maEntries.cbegin(), maEntries.cend(),
+ pCompare->maEntries.cbegin(), pCompare->maEntries.cend(),
+ [](const auto& lhs, const auto& rhs) {
+ return *lhs == *rhs;
+ });
}
return false;
@@ -263,8 +259,7 @@ namespace drawinglayer::animation
AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat)
- : AnimationEntryList(),
- mnRepeat(nRepeat)
+ : mnRepeat(nRepeat)
{
}
diff --git a/drawinglayer/source/attribute/fillgradientattribute.cxx b/drawinglayer/source/attribute/fillgradientattribute.cxx
index fe38a07d41ac..54f455f647ef 100644
--- a/drawinglayer/source/attribute/fillgradientattribute.cxx
+++ b/drawinglayer/source/attribute/fillgradientattribute.cxx
@@ -18,9 +18,7 @@
*/
#include <drawinglayer/attribute/fillgradientattribute.hxx>
-#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
-
+#include <basegfx/utils/gradienttools.hxx>
namespace drawinglayer::attribute
{
@@ -28,55 +26,68 @@ namespace drawinglayer::attribute
{
public:
// data definitions
- GradientStyle meStyle;
double mfBorder;
double mfOffsetX;
double mfOffsetY;
double mfAngle;
- basegfx::BColor maStartColor;
- basegfx::BColor maEndColor;
+ basegfx::BColorStops maColorStops;
+ css::awt::GradientStyle meStyle;
sal_uInt16 mnSteps;
ImpFillGradientAttribute(
- GradientStyle eStyle,
+ css::awt::GradientStyle eStyle,
double fBorder,
double fOffsetX,
double fOffsetY,
double fAngle,
- const basegfx::BColor& rStartColor,
- const basegfx::BColor& rEndColor,
+ const basegfx::BColorStops& rColorStops,
sal_uInt16 nSteps)
- : meStyle(eStyle),
- mfBorder(fBorder),
+ : mfBorder(fBorder),
mfOffsetX(fOffsetX),
mfOffsetY(fOffsetY),
mfAngle(fAngle),
- maStartColor(rStartColor),
- maEndColor(rEndColor),
+ maColorStops(rColorStops), // copy ColorStops
+ meStyle(eStyle),
mnSteps(nSteps)
{
+ // Correct the local ColorStops. That will guarantee that the
+ // content does contain no offsets < 0.0, > 1.0 or double
+ // ones, also secures sorted arrangement and checks for
+ // double colors, too (see there for more information).
+ // This is what the usages of this in primitives need.
+ // Since FillGradientAttribute is read-only doing this
+ // once here in the constructor is sufficient
+ maColorStops.sortAndCorrect();
+
+ // sortAndCorrectColorStops is rigid and can return
+ // an empty result. To keep things simple, add a single
+ // fallback value
+ if (maColorStops.empty())
+ {
+ maColorStops.emplace_back(0.0, basegfx::BColor());
+ }
}
ImpFillGradientAttribute()
- : meStyle(GradientStyle::Linear),
- mfBorder(0.0),
+ : mfBorder(0.0),
mfOffsetX(0.0),
mfOffsetY(0.0),
mfAngle(0.0),
- maStartColor(basegfx::BColor()),
- maEndColor(basegfx::BColor()),
+ maColorStops(),
+ meStyle(css::awt::GradientStyle_LINEAR),
mnSteps(0)
{
+ // always add a fallback color, see above
+ maColorStops.emplace_back(0.0, basegfx::BColor());
}
// data read access
- GradientStyle getStyle() const { return meStyle; }
+ css::awt::GradientStyle getStyle() const { return meStyle; }
double getBorder() const { return mfBorder; }
double getOffsetX() const { return mfOffsetX; }
double getOffsetY() const { return mfOffsetY; }
double getAngle() const { return mfAngle; }
- const basegfx::BColor& getStartColor() const { return maStartColor; }
- const basegfx::BColor& getEndColor() const { return maEndColor; }
+ const basegfx::BColorStops& getColorStops() const { return maColorStops; }
sal_uInt16 getSteps() const { return mnSteps; }
bool operator==(const ImpFillGradientAttribute& rCandidate) const
@@ -86,34 +97,35 @@ namespace drawinglayer::attribute
&& getOffsetX() == rCandidate.getOffsetX()
&& getOffsetY() == rCandidate.getOffsetY()
&& getAngle() == rCandidate.getAngle()
- && getStartColor() == rCandidate.getStartColor()
- && getEndColor() == rCandidate.getEndColor()
+ && getColorStops() == rCandidate.getColorStops()
&& getSteps() == rCandidate.getSteps());
}
};
namespace
{
- struct theGlobalDefault :
- public rtl::Static< FillGradientAttribute::ImplType, theGlobalDefault > {};
+ FillGradientAttribute::ImplType& theGlobalDefault()
+ {
+ static FillGradientAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
FillGradientAttribute::FillGradientAttribute(
- GradientStyle eStyle,
+ css::awt::GradientStyle eStyle,
double fBorder,
double fOffsetX,
double fOffsetY,
double fAngle,
- const basegfx::BColor& rStartColor,
- const basegfx::BColor& rEndColor,
+ const basegfx::BColorStops& rColorStops,
sal_uInt16 nSteps)
: mpFillGradientAttribute(ImpFillGradientAttribute(
- eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rStartColor, rEndColor, nSteps))
+ eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rColorStops, nSteps))
{
}
FillGradientAttribute::FillGradientAttribute()
- : mpFillGradientAttribute(theGlobalDefault::get())
+ : mpFillGradientAttribute(theGlobalDefault())
{
}
@@ -125,7 +137,42 @@ namespace drawinglayer::attribute
bool FillGradientAttribute::isDefault() const
{
- return mpFillGradientAttribute.same_object(theGlobalDefault::get());
+ return mpFillGradientAttribute.same_object(theGlobalDefault());
+ }
+
+ // MCGR: Check if rendering cannot be handled by old vcl stuff
+ bool FillGradientAttribute::cannotBeHandledByVCL() const
+ {
+ // MCGR: If GradientStops are used, use decomposition since vcl is not able
+ // to render multi-color gradients
+ if (getColorStops().size() != 2)
+ {
+ return true;
+ }
+
+ // MCGR: If GradientStops do not start and stop at traditional Start/EndColor,
+ // use decomposition since vcl is not able to render this
+ if (!getColorStops().empty())
+ {
+ if (!basegfx::fTools::equalZero(getColorStops().front().getStopOffset())
+ || !basegfx::fTools::equal(getColorStops().back().getStopOffset(), 1.0))
+ {
+ return true;
+ }
+ }
+
+ // VCL should be able to handle all styles, but for tdf#133477 the VCL result
+ // is different from processing the gradient manually by drawinglayer
+ // (and the Writer unittest for it fails). Keep using the drawinglayer code
+ // until somebody founds out what's wrong and fixes it.
+ if (getStyle() != css::awt::GradientStyle_LINEAR
+ && getStyle() != css::awt::GradientStyle_AXIAL
+ && getStyle() != css::awt::GradientStyle_RADIAL)
+ {
+ return true;
+ }
+
+ return false;
}
FillGradientAttribute& FillGradientAttribute::operator=(const FillGradientAttribute&) = default;
@@ -141,14 +188,9 @@ namespace drawinglayer::attribute
return rCandidate.mpFillGradientAttribute == mpFillGradientAttribute;
}
- const basegfx::BColor& FillGradientAttribute::getStartColor() const
- {
- return mpFillGradientAttribute->getStartColor();
- }
-
- const basegfx::BColor& FillGradientAttribute::getEndColor() const
+ const basegfx::BColorStops& FillGradientAttribute::getColorStops() const
{
- return mpFillGradientAttribute->getEndColor();
+ return mpFillGradientAttribute->getColorStops();
}
double FillGradientAttribute::getBorder() const
@@ -171,7 +213,7 @@ namespace drawinglayer::attribute
return mpFillGradientAttribute->getAngle();
}
- GradientStyle FillGradientAttribute::getStyle() const
+ css::awt::GradientStyle FillGradientAttribute::getStyle() const
{
return mpFillGradientAttribute->getStyle();
}
@@ -181,6 +223,39 @@ namespace drawinglayer::attribute
return mpFillGradientAttribute->getSteps();
}
+ bool FillGradientAttribute::sameDefinitionThanAlpha(const FillGradientAttribute& rAlpha) const
+ {
+ // entries that are used by all gradient styles
+ if (getStyle() != rAlpha.getStyle()
+ || getBorder() != rAlpha.getBorder()
+ || getSteps() != rAlpha.getSteps())
+ {
+ return false;
+ }
+
+ // check for offsets if not ignored
+ const bool bIgnoreOffset(css::awt::GradientStyle_LINEAR == getStyle() || css::awt::GradientStyle_AXIAL == getStyle());
+ if (!bIgnoreOffset && (getOffsetX() != rAlpha.getOffsetX() || getOffsetY() != rAlpha.getOffsetY()))
+ {
+ return false;
+ }
+
+ // check for angle if not ignored
+ const bool bIgnoreAngle(css::awt::GradientStyle_RADIAL == getStyle());
+ if (!bIgnoreAngle && getAngle() != rAlpha.getAngle())
+ {
+ return false;
+ }
+
+ // check for same count & offsets in the gradients (all except 'colors')
+ if (!getColorStops().sameSizeAndDistances(rAlpha.getColorStops()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/attribute/fillgraphicattribute.cxx b/drawinglayer/source/attribute/fillgraphicattribute.cxx
index fa9b4fd57138..5a401dbc0133 100644
--- a/drawinglayer/source/attribute/fillgraphicattribute.cxx
+++ b/drawinglayer/source/attribute/fillgraphicattribute.cxx
@@ -22,6 +22,7 @@
#include <algorithm>
#include <drawinglayer/attribute/fillgraphicattribute.hxx>
+#include <utility>
#include <vcl/graph.hxx>
namespace drawinglayer::attribute
@@ -41,12 +42,12 @@ namespace drawinglayer::attribute
double mfOffsetY;
ImpFillGraphicAttribute(
- const Graphic& rGraphic,
+ Graphic aGraphic,
const basegfx::B2DRange& rGraphicRange,
bool bTiling,
double fOffsetX,
double fOffsetY)
- : maGraphic(rGraphic),
+ : maGraphic(std::move(aGraphic)),
maGraphicRange(rGraphicRange),
mbTiling(bTiling),
mfOffsetX(fOffsetX),
@@ -57,13 +58,11 @@ namespace drawinglayer::attribute
// available when a renderer works with multi-threading.
// When changing this, please check if it is still possible to
// use a metafile as texture for a 3D object
- maGraphic.GetBitmapEx();
+ maGraphic.GetBitmap();
}
ImpFillGraphicAttribute()
- : maGraphic(Graphic()),
- maGraphicRange(basegfx::B2DRange()),
- mbTiling(false),
+ : mbTiling(false),
mfOffsetX(0.0),
mfOffsetY(0.0)
{
@@ -88,8 +87,16 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< FillGraphicAttribute::ImplType, theGlobalDefault > {};
+ FillGraphicAttribute::ImplType& theGlobalDefault()
+ {
+ static FillGraphicAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
+ }
+
+ FillGraphicAttribute::FillGraphicAttribute()
+ : mpFillGraphicAttribute(theGlobalDefault())
+ {
}
FillGraphicAttribute::FillGraphicAttribute(
@@ -111,7 +118,7 @@ namespace drawinglayer::attribute
bool FillGraphicAttribute::isDefault() const
{
- return mpFillGraphicAttribute.same_object(theGlobalDefault::get());
+ return mpFillGraphicAttribute.same_object(theGlobalDefault());
}
FillGraphicAttribute& FillGraphicAttribute::operator=(const FillGraphicAttribute&) = default;
diff --git a/drawinglayer/source/attribute/fillhatchattribute.cxx b/drawinglayer/source/attribute/fillhatchattribute.cxx
index 69dd76c53d97..bc892a024842 100644
--- a/drawinglayer/source/attribute/fillhatchattribute.cxx
+++ b/drawinglayer/source/attribute/fillhatchattribute.cxx
@@ -19,7 +19,6 @@
#include <drawinglayer/attribute/fillhatchattribute.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -56,7 +55,6 @@ namespace drawinglayer::attribute
: meStyle(HatchStyle::Single),
mfDistance(0.0),
mfAngle(0.0),
- maColor(basegfx::BColor()),
mnMinimalDiscreteDistance(3), // same as VCL
mbFillBackground(false)
{
@@ -83,8 +81,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< FillHatchAttribute::ImplType, theGlobalDefault > {};
+ FillHatchAttribute::ImplType& theGlobalDefault()
+ {
+ static FillHatchAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
FillHatchAttribute::FillHatchAttribute(
@@ -101,7 +102,7 @@ namespace drawinglayer::attribute
}
FillHatchAttribute::FillHatchAttribute()
- : mpFillHatchAttribute(theGlobalDefault::get())
+ : mpFillHatchAttribute(theGlobalDefault())
{
}
@@ -113,7 +114,7 @@ namespace drawinglayer::attribute
bool FillHatchAttribute::isDefault() const
{
- return mpFillHatchAttribute.same_object(theGlobalDefault::get());
+ return mpFillHatchAttribute.same_object(theGlobalDefault());
}
FillHatchAttribute& FillHatchAttribute::operator=(const FillHatchAttribute&) = default;
diff --git a/drawinglayer/source/attribute/fontattribute.cxx b/drawinglayer/source/attribute/fontattribute.cxx
index 33903003f8c7..c1f0ab000d86 100644
--- a/drawinglayer/source/attribute/fontattribute.cxx
+++ b/drawinglayer/source/attribute/fontattribute.cxx
@@ -18,185 +18,134 @@
*/
#include <drawinglayer/attribute/fontattribute.hxx>
-#include <rtl/instance.hxx>
#include <rtl/ustring.hxx>
-
+#include <utility>
namespace drawinglayer::attribute
{
- class ImpFontAttribute
- {
- public:
- /// core data
- OUString maFamilyName; // Font Family Name
- OUString maStyleName; // Font Style Name
- sal_uInt16 mnWeight; // Font weight
-
- bool mbSymbol : 1; // Symbol Font Flag
- bool mbVertical : 1; // Vertical Text Flag
- bool mbItalic : 1; // Italic Flag
- bool mbOutline : 1; // Outline Flag
- bool mbRTL : 1; // RTL Flag
- bool mbBiDiStrong : 1; // BiDi Flag
- bool mbMonospaced : 1;
-
- ImpFontAttribute(
- const OUString& rFamilyName,
- const OUString& rStyleName,
- sal_uInt16 nWeight,
- bool bSymbol,
- bool bVertical,
- bool bItalic,
- bool bMonospaced,
- bool bOutline,
- bool bRTL,
- bool bBiDiStrong)
- : maFamilyName(rFamilyName),
- maStyleName(rStyleName),
- mnWeight(nWeight),
- mbSymbol(bSymbol),
- mbVertical(bVertical),
- mbItalic(bItalic),
- mbOutline(bOutline),
- mbRTL(bRTL),
- mbBiDiStrong(bBiDiStrong),
- mbMonospaced(bMonospaced)
- {
- }
-
- ImpFontAttribute()
- : maFamilyName(),
- maStyleName(),
- mnWeight(0),
- mbSymbol(false),
- mbVertical(false),
- mbItalic(false),
- mbOutline(false),
- mbRTL(false),
- mbBiDiStrong(false),
- mbMonospaced(false)
- {
- }
-
- // data read access
- const OUString& getFamilyName() const { return maFamilyName; }
- const OUString& getStyleName() const { return maStyleName; }
- sal_uInt16 getWeight() const { return mnWeight; }
- bool getSymbol() const { return mbSymbol; }
- bool getVertical() const { return mbVertical; }
- bool getItalic() const { return mbItalic; }
- bool getOutline() const { return mbOutline; }
- bool getRTL() const { return mbRTL; }
- bool getBiDiStrong() const { return mbBiDiStrong; }
- bool getMonospaced() const { return mbMonospaced; }
-
- bool operator==(const ImpFontAttribute& rCompare) const
- {
- return (getFamilyName() == rCompare.getFamilyName()
- && getStyleName() == rCompare.getStyleName()
- && getWeight() == rCompare.getWeight()
- && getSymbol() == rCompare.getSymbol()
- && getVertical() == rCompare.getVertical()
- && getItalic() == rCompare.getItalic()
- && getOutline() == rCompare.getOutline()
- && getRTL() == rCompare.getRTL()
- && getBiDiStrong() == rCompare.getBiDiStrong()
- && getMonospaced() == rCompare.getMonospaced());
- }
- };
-
- namespace
- {
- struct theGlobalDefault :
- public rtl::Static< FontAttribute::ImplType, theGlobalDefault > {};
- }
-
- FontAttribute::FontAttribute(
- const OUString& rFamilyName,
- const OUString& rStyleName,
- sal_uInt16 nWeight,
- bool bSymbol,
- bool bVertical,
- bool bItalic,
- bool bMonospaced,
- bool bOutline,
- bool bRTL,
- bool bBiDiStrong)
- : mpFontAttribute(ImpFontAttribute(
- rFamilyName, rStyleName, nWeight, bSymbol, bVertical, bItalic, bMonospaced, bOutline, bRTL, bBiDiStrong))
- {
- }
-
- FontAttribute::FontAttribute()
- : mpFontAttribute(theGlobalDefault::get())
- {
- }
-
- FontAttribute::FontAttribute(const FontAttribute&) = default;
-
- FontAttribute::FontAttribute(FontAttribute&&) = default;
-
- FontAttribute::~FontAttribute() = default;
-
- FontAttribute& FontAttribute::operator=(const FontAttribute&) = default;
-
- FontAttribute& FontAttribute::operator=(FontAttribute&&) = default;
-
- bool FontAttribute::operator==(const FontAttribute& rCandidate) const
- {
- return rCandidate.mpFontAttribute == mpFontAttribute;
- }
-
- const OUString& FontAttribute::getFamilyName() const
- {
- return mpFontAttribute->getFamilyName();
- }
-
- const OUString& FontAttribute::getStyleName() const
- {
- return mpFontAttribute->getStyleName();
- }
-
- sal_uInt16 FontAttribute::getWeight() const
- {
- return mpFontAttribute->getWeight();
- }
-
- bool FontAttribute::getSymbol() const
- {
- return mpFontAttribute->getSymbol();
- }
-
- bool FontAttribute::getVertical() const
- {
- return mpFontAttribute->getVertical();
- }
-
- bool FontAttribute::getItalic() const
- {
- return mpFontAttribute->getItalic();
- }
-
- bool FontAttribute::getOutline() const
- {
- return mpFontAttribute->getOutline();
- }
-
- bool FontAttribute::getRTL() const
- {
- return mpFontAttribute->getRTL();
- }
-
- bool FontAttribute::getBiDiStrong() const
- {
- return mpFontAttribute->getBiDiStrong();
- }
-
- bool FontAttribute::getMonospaced() const
- {
- return mpFontAttribute->getMonospaced();
- }
+class ImpFontAttribute
+{
+public:
+ /// core data
+ OUString maFamilyName; // Font Family Name
+ OUString maStyleName; // Font Style Name
+ sal_uInt16 mnWeight; // Font weight
+
+ bool mbSymbol : 1; // Symbol Font Flag
+ bool mbVertical : 1; // Vertical Text Flag
+ bool mbItalic : 1; // Italic Flag
+ bool mbOutline : 1; // Outline Flag
+ bool mbRTL : 1; // RTL Flag
+ bool mbBiDiStrong : 1; // BiDi Flag
+ bool mbMonospaced : 1;
+
+ ImpFontAttribute(OUString aFamilyName, OUString aStyleName, sal_uInt16 nWeight, bool bSymbol,
+ bool bVertical, bool bItalic, bool bMonospaced, bool bOutline, bool bRTL,
+ bool bBiDiStrong)
+ : maFamilyName(std::move(aFamilyName))
+ , maStyleName(std::move(aStyleName))
+ , mnWeight(nWeight)
+ , mbSymbol(bSymbol)
+ , mbVertical(bVertical)
+ , mbItalic(bItalic)
+ , mbOutline(bOutline)
+ , mbRTL(bRTL)
+ , mbBiDiStrong(bBiDiStrong)
+ , mbMonospaced(bMonospaced)
+ {
+ }
+
+ ImpFontAttribute()
+ : mnWeight(0)
+ , mbSymbol(false)
+ , mbVertical(false)
+ , mbItalic(false)
+ , mbOutline(false)
+ , mbRTL(false)
+ , mbBiDiStrong(false)
+ , mbMonospaced(false)
+ {
+ }
+
+ // data read access
+ const OUString& getFamilyName() const { return maFamilyName; }
+ const OUString& getStyleName() const { return maStyleName; }
+ sal_uInt16 getWeight() const { return mnWeight; }
+ bool getSymbol() const { return mbSymbol; }
+ bool getVertical() const { return mbVertical; }
+ bool getItalic() const { return mbItalic; }
+ bool getOutline() const { return mbOutline; }
+ bool getRTL() const { return mbRTL; }
+ bool getBiDiStrong() const { return mbBiDiStrong; }
+ bool getMonospaced() const { return mbMonospaced; }
+
+ bool operator==(const ImpFontAttribute& rCompare) const
+ {
+ return (getFamilyName() == rCompare.getFamilyName()
+ && getStyleName() == rCompare.getStyleName() && getWeight() == rCompare.getWeight()
+ && getSymbol() == rCompare.getSymbol() && getVertical() == rCompare.getVertical()
+ && getItalic() == rCompare.getItalic() && getOutline() == rCompare.getOutline()
+ && getRTL() == rCompare.getRTL() && getBiDiStrong() == rCompare.getBiDiStrong()
+ && getMonospaced() == rCompare.getMonospaced());
+ }
+};
+
+namespace
+{
+FontAttribute::ImplType& theGlobalDefault()
+{
+ static FontAttribute::ImplType SINGLETON;
+ return SINGLETON;
+}
+}
+
+FontAttribute::FontAttribute(const OUString& rFamilyName, const OUString& rStyleName,
+ sal_uInt16 nWeight, bool bSymbol, bool bVertical, bool bItalic,
+ bool bMonospaced, bool bOutline, bool bRTL, bool bBiDiStrong)
+ : mpFontAttribute(ImpFontAttribute(rFamilyName, rStyleName, nWeight, bSymbol, bVertical,
+ bItalic, bMonospaced, bOutline, bRTL, bBiDiStrong))
+{
+}
+
+FontAttribute::FontAttribute()
+ : mpFontAttribute(theGlobalDefault())
+{
+}
+
+FontAttribute::FontAttribute(const FontAttribute&) = default;
+
+FontAttribute::FontAttribute(FontAttribute&&) = default;
+
+FontAttribute::~FontAttribute() = default;
+
+FontAttribute& FontAttribute::operator=(const FontAttribute&) = default;
+
+FontAttribute& FontAttribute::operator=(FontAttribute&&) = default;
+
+bool FontAttribute::operator==(const FontAttribute& rCandidate) const
+{
+ return rCandidate.mpFontAttribute == mpFontAttribute;
+}
+
+const OUString& FontAttribute::getFamilyName() const { return mpFontAttribute->getFamilyName(); }
+
+const OUString& FontAttribute::getStyleName() const { return mpFontAttribute->getStyleName(); }
+
+sal_uInt16 FontAttribute::getWeight() const { return mpFontAttribute->getWeight(); }
+
+bool FontAttribute::getSymbol() const { return mpFontAttribute->getSymbol(); }
+
+bool FontAttribute::getVertical() const { return mpFontAttribute->getVertical(); }
+
+bool FontAttribute::getItalic() const { return mpFontAttribute->getItalic(); }
+
+bool FontAttribute::getOutline() const { return mpFontAttribute->getOutline(); }
+
+bool FontAttribute::getRTL() const { return mpFontAttribute->getRTL(); }
+
+bool FontAttribute::getBiDiStrong() const { return mpFontAttribute->getBiDiStrong(); }
+bool FontAttribute::getMonospaced() const { return mpFontAttribute->getMonospaced(); }
} // end of namespace
diff --git a/drawinglayer/source/attribute/lineattribute.cxx b/drawinglayer/source/attribute/lineattribute.cxx
index 48d1f73380eb..d4f2418c1354 100644
--- a/drawinglayer/source/attribute/lineattribute.cxx
+++ b/drawinglayer/source/attribute/lineattribute.cxx
@@ -19,7 +19,6 @@
#include <drawinglayer/attribute/lineattribute.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -49,8 +48,7 @@ namespace drawinglayer::attribute
}
ImpLineAttribute()
- : maColor(basegfx::BColor()),
- mfWidth(0.0),
+ : mfWidth(0.0),
meLineJoin(basegfx::B2DLineJoin::Round),
meLineCap(css::drawing::LineCap_BUTT),
mfMiterMinimumAngle(basegfx::deg2rad(15.0))
@@ -76,8 +74,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< LineAttribute::ImplType, theGlobalDefault > {};
+ LineAttribute::ImplType& theGlobalDefault()
+ {
+ static LineAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
LineAttribute::LineAttribute(
@@ -97,7 +98,7 @@ namespace drawinglayer::attribute
}
LineAttribute::LineAttribute()
- : mpLineAttribute(theGlobalDefault::get())
+ : mpLineAttribute(theGlobalDefault())
{
}
@@ -107,7 +108,7 @@ namespace drawinglayer::attribute
bool LineAttribute::isDefault() const
{
- return mpLineAttribute.same_object(theGlobalDefault::get());
+ return mpLineAttribute.same_object(theGlobalDefault());
}
LineAttribute& LineAttribute::operator=(const LineAttribute&) = default;
diff --git a/drawinglayer/source/attribute/linestartendattribute.cxx b/drawinglayer/source/attribute/linestartendattribute.cxx
index dcfa94f35c39..33ac17c70599 100644
--- a/drawinglayer/source/attribute/linestartendattribute.cxx
+++ b/drawinglayer/source/attribute/linestartendattribute.cxx
@@ -20,7 +20,7 @@
#include <drawinglayer/attribute/linestartendattribute.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <rtl/instance.hxx>
+#include <utility>
namespace drawinglayer::attribute
@@ -36,17 +36,16 @@ namespace drawinglayer::attribute
ImpLineStartEndAttribute(
double fWidth,
- const basegfx::B2DPolyPolygon& rPolyPolygon,
+ basegfx::B2DPolyPolygon aPolyPolygon,
bool bCentered)
: mfWidth(fWidth),
- maPolyPolygon(rPolyPolygon),
+ maPolyPolygon(std::move(aPolyPolygon)),
mbCentered(bCentered)
{
}
ImpLineStartEndAttribute()
: mfWidth(0.0),
- maPolyPolygon(basegfx::B2DPolyPolygon()),
mbCentered(false)
{
}
@@ -66,8 +65,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< LineStartEndAttribute::ImplType, theGlobalDefault > {};
+ LineStartEndAttribute::ImplType& theGlobalDefault()
+ {
+ static LineStartEndAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
LineStartEndAttribute::LineStartEndAttribute(
@@ -80,7 +82,7 @@ namespace drawinglayer::attribute
}
LineStartEndAttribute::LineStartEndAttribute()
- : mpLineStartEndAttribute(theGlobalDefault::get())
+ : mpLineStartEndAttribute(theGlobalDefault())
{
}
@@ -90,7 +92,7 @@ namespace drawinglayer::attribute
bool LineStartEndAttribute::isDefault() const
{
- return mpLineStartEndAttribute.same_object(theGlobalDefault::get());
+ return mpLineStartEndAttribute.same_object(theGlobalDefault());
}
LineStartEndAttribute& LineStartEndAttribute::operator=(const LineStartEndAttribute&) = default;
diff --git a/drawinglayer/source/attribute/materialattribute3d.cxx b/drawinglayer/source/attribute/materialattribute3d.cxx
index f9473b480337..7206ad54bed9 100644
--- a/drawinglayer/source/attribute/materialattribute3d.cxx
+++ b/drawinglayer/source/attribute/materialattribute3d.cxx
@@ -19,7 +19,6 @@
#include <drawinglayer/attribute/materialattribute3d.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -44,16 +43,12 @@ namespace drawinglayer::attribute
explicit ImpMaterialAttribute3D(const basegfx::BColor& rColor)
: maColor(rColor),
maSpecular(1.0, 1.0, 1.0),
- maEmission(),
mnSpecularIntensity(15)
{
}
ImpMaterialAttribute3D()
- : maColor(basegfx::BColor()),
- maSpecular(basegfx::BColor()),
- maEmission(basegfx::BColor()),
- mnSpecularIntensity(0)
+ : mnSpecularIntensity(0)
{
}
@@ -74,8 +69,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< MaterialAttribute3D::ImplType, theGlobalDefault > {};
+ MaterialAttribute3D::ImplType& theGlobalDefault()
+ {
+ static MaterialAttribute3D::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
MaterialAttribute3D::MaterialAttribute3D(
@@ -95,7 +93,7 @@ namespace drawinglayer::attribute
}
MaterialAttribute3D::MaterialAttribute3D()
- : mpMaterialAttribute3D(theGlobalDefault::get())
+ : mpMaterialAttribute3D(theGlobalDefault())
{
}
diff --git a/drawinglayer/source/attribute/sdrallattribute3d.cxx b/drawinglayer/source/attribute/sdrallattribute3d.cxx
index 079f655796d9..8c74306ca1dd 100644
--- a/drawinglayer/source/attribute/sdrallattribute3d.cxx
+++ b/drawinglayer/source/attribute/sdrallattribute3d.cxx
@@ -18,21 +18,22 @@
*/
#include <drawinglayer/attribute/sdrallattribute3d.hxx>
+#include <utility>
namespace drawinglayer::attribute
{
SdrLineFillShadowAttribute3D::SdrLineFillShadowAttribute3D(
- const SdrLineAttribute& rLine,
- const SdrFillAttribute& rFill,
- const SdrLineStartEndAttribute& rLineStartEnd,
- const SdrShadowAttribute& rShadow,
- const FillGradientAttribute& rFillFloatTransGradient)
- : maLine(rLine),
- maFill(rFill),
- maLineStartEnd(rLineStartEnd),
- maShadow(rShadow),
- maFillFloatTransGradient(rFillFloatTransGradient)
+ SdrLineAttribute aLine,
+ SdrFillAttribute aFill,
+ SdrLineStartEndAttribute aLineStartEnd,
+ SdrShadowAttribute aShadow,
+ FillGradientAttribute aFillFloatTransGradient)
+ : maLine(std::move(aLine)),
+ maFill(std::move(aFill)),
+ maLineStartEnd(std::move(aLineStartEnd)),
+ maShadow(std::move(aShadow)),
+ maFillFloatTransGradient(std::move(aFillFloatTransGradient))
{
}
diff --git a/drawinglayer/source/attribute/sdrfillattribute.cxx b/drawinglayer/source/attribute/sdrfillattribute.cxx
index 393df42637c5..8cee8f98d1e9 100644
--- a/drawinglayer/source/attribute/sdrfillattribute.cxx
+++ b/drawinglayer/source/attribute/sdrfillattribute.cxx
@@ -22,7 +22,7 @@
#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
#include <drawinglayer/attribute/fillhatchattribute.hxx>
#include <drawinglayer/attribute/fillgradientattribute.hxx>
-#include <rtl/instance.hxx>
+#include <utility>
namespace drawinglayer::attribute
@@ -41,23 +41,19 @@ namespace drawinglayer::attribute
ImpSdrFillAttribute(
double fTransparence,
const basegfx::BColor& rColor,
- const FillGradientAttribute& rGradient,
- const FillHatchAttribute& rHatch,
- const SdrFillGraphicAttribute& rFillGraphic)
+ FillGradientAttribute aGradient,
+ FillHatchAttribute aHatch,
+ SdrFillGraphicAttribute aFillGraphic)
: mfTransparence(fTransparence),
maColor(rColor),
- maGradient(rGradient),
- maHatch(rHatch),
- maFillGraphic(rFillGraphic)
+ maGradient(std::move(aGradient)),
+ maHatch(std::move(aHatch)),
+ maFillGraphic(std::move(aFillGraphic))
{
}
ImpSdrFillAttribute()
- : mfTransparence(0.0),
- maColor(basegfx::BColor()),
- maGradient(FillGradientAttribute()),
- maHatch(FillHatchAttribute()),
- maFillGraphic(SdrFillGraphicAttribute())
+ : mfTransparence(0.0)
{
}
@@ -81,8 +77,16 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrFillAttribute::ImplType, theGlobalDefault > {};
+ SdrFillAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrFillAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
+ SdrFillAttribute::ImplType& slideBackgroundFillGlobalDefault()
+ {
+ static SdrFillAttribute::ImplType SINGLETON2;
+ return SINGLETON2;
+ }
}
SdrFillAttribute::SdrFillAttribute(
@@ -96,8 +100,10 @@ namespace drawinglayer::attribute
{
}
- SdrFillAttribute::SdrFillAttribute()
- : mpSdrFillAttribute(theGlobalDefault::get())
+ SdrFillAttribute::SdrFillAttribute(bool bSlideBackgroundFill)
+ : mpSdrFillAttribute(bSlideBackgroundFill
+ ? slideBackgroundFillGlobalDefault()
+ : theGlobalDefault())
{
}
@@ -109,7 +115,12 @@ namespace drawinglayer::attribute
bool SdrFillAttribute::isDefault() const
{
- return mpSdrFillAttribute.same_object(theGlobalDefault::get());
+ return mpSdrFillAttribute.same_object(theGlobalDefault());
+ }
+
+ bool SdrFillAttribute::isSlideBackgroundFill() const
+ {
+ return mpSdrFillAttribute.same_object(slideBackgroundFillGlobalDefault());
}
SdrFillAttribute& SdrFillAttribute::operator=(const SdrFillAttribute&) = default;
diff --git a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx
index a00c45521e17..b78f3e322c38 100644
--- a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx
+++ b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx
@@ -23,7 +23,7 @@
#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
#include <drawinglayer/attribute/fillgraphicattribute.hxx>
-#include <rtl/instance.hxx>
+#include <utility>
#include <vcl/graph.hxx>
@@ -45,7 +45,7 @@ namespace drawinglayer::attribute
bool mbLogSize : 1;
ImpSdrFillGraphicAttribute(
- const Graphic& rFillGraphic,
+ Graphic aFillGraphic,
const basegfx::B2DVector& rGraphicLogicSize,
const basegfx::B2DVector& rSize,
const basegfx::B2DVector& rOffset,
@@ -54,7 +54,7 @@ namespace drawinglayer::attribute
bool bTiling,
bool bStretch,
bool bLogSize)
- : maFillGraphic(rFillGraphic),
+ : maFillGraphic(std::move(aFillGraphic)),
maGraphicLogicSize(rGraphicLogicSize),
maSize(rSize),
maOffset(rOffset),
@@ -67,13 +67,7 @@ namespace drawinglayer::attribute
}
ImpSdrFillGraphicAttribute()
- : maFillGraphic(Graphic()),
- maGraphicLogicSize(basegfx::B2DVector()),
- maSize(basegfx::B2DVector()),
- maOffset(basegfx::B2DVector()),
- maOffsetPosition(basegfx::B2DVector()),
- maRectPoint(basegfx::B2DVector()),
- mbTiling(false),
+ : mbTiling(false),
mbStretch(false),
mbLogSize(false)
{
@@ -105,8 +99,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrFillGraphicAttribute::ImplType, theGlobalDefault > {};
+ SdrFillGraphicAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrFillGraphicAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
SdrFillGraphicAttribute::SdrFillGraphicAttribute(
@@ -134,7 +131,7 @@ namespace drawinglayer::attribute
}
SdrFillGraphicAttribute::SdrFillGraphicAttribute()
- : mpSdrFillGraphicAttribute(theGlobalDefault::get())
+ : mpSdrFillGraphicAttribute(theGlobalDefault())
{
}
@@ -146,7 +143,7 @@ namespace drawinglayer::attribute
bool SdrFillGraphicAttribute::isDefault() const
{
- return mpSdrFillGraphicAttribute.same_object(theGlobalDefault::get());
+ return mpSdrFillGraphicAttribute.same_object(theGlobalDefault());
}
SdrFillGraphicAttribute& SdrFillGraphicAttribute::operator=(const SdrFillGraphicAttribute&) = default;
diff --git a/drawinglayer/source/attribute/sdrglowattribute.cxx b/drawinglayer/source/attribute/sdrglowattribute.cxx
index 90367ff67ea0..c27390d64d6d 100644
--- a/drawinglayer/source/attribute/sdrglowattribute.cxx
+++ b/drawinglayer/source/attribute/sdrglowattribute.cxx
@@ -8,18 +8,8 @@
*/
#include <drawinglayer/attribute/sdrglowattribute.hxx>
-#include <basegfx/vector/b2dvector.hxx>
-#include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
-#include <utility>
-
-#include <sal/log.hxx>
-
-namespace drawinglayer
-{
-namespace attribute
+namespace drawinglayer::attribute
{
SdrGlowAttribute::SdrGlowAttribute(sal_Int32 nRadius, const Color& rColor)
: m_nRadius(nRadius)
@@ -33,8 +23,6 @@ SdrGlowAttribute::SdrGlowAttribute(const SdrGlowAttribute&) = default;
SdrGlowAttribute::SdrGlowAttribute(SdrGlowAttribute&&) = default;
-SdrGlowAttribute::~SdrGlowAttribute() = default;
-
SdrGlowAttribute& SdrGlowAttribute::operator=(const SdrGlowAttribute&) = default;
SdrGlowAttribute& SdrGlowAttribute::operator=(SdrGlowAttribute&&) = default;
@@ -44,7 +32,6 @@ bool SdrGlowAttribute::operator==(const SdrGlowAttribute& rCandidate) const
return m_nRadius == rCandidate.m_nRadius && m_color == rCandidate.m_color;
}
-} // end of namespace attribute
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::attribute
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/attribute/sdrglowtextattribute.cxx b/drawinglayer/source/attribute/sdrglowtextattribute.cxx
new file mode 100644
index 000000000000..f456955624c3
--- /dev/null
+++ b/drawinglayer/source/attribute/sdrglowtextattribute.cxx
@@ -0,0 +1,37 @@
+/* -*- 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/.
+ */
+
+#include <drawinglayer/attribute/sdrglowtextattribute.hxx>
+
+namespace drawinglayer::attribute
+{
+SdrGlowTextAttribute::SdrGlowTextAttribute(sal_Int32 nTextRadius, const Color& rTextColor)
+ : m_nTextRadius(nTextRadius)
+ , m_TextColor(rTextColor)
+{
+}
+
+SdrGlowTextAttribute::SdrGlowTextAttribute() = default;
+
+SdrGlowTextAttribute::SdrGlowTextAttribute(const SdrGlowTextAttribute&) = default;
+
+SdrGlowTextAttribute::SdrGlowTextAttribute(SdrGlowTextAttribute&&) = default;
+
+SdrGlowTextAttribute& SdrGlowTextAttribute::operator=(const SdrGlowTextAttribute&) = default;
+
+SdrGlowTextAttribute& SdrGlowTextAttribute::operator=(SdrGlowTextAttribute&&) = default;
+
+bool SdrGlowTextAttribute::operator==(const SdrGlowTextAttribute& rCandidate) const
+{
+ return m_nTextRadius == rCandidate.m_nTextRadius && m_TextColor == rCandidate.m_TextColor;
+}
+
+} // end of namespace drawinglayer::attribute
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/attribute/sdrlightattribute3d.cxx b/drawinglayer/source/attribute/sdrlightattribute3d.cxx
index 56f0b384129a..511590f5ffd4 100644
--- a/drawinglayer/source/attribute/sdrlightattribute3d.cxx
+++ b/drawinglayer/source/attribute/sdrlightattribute3d.cxx
@@ -20,7 +20,6 @@
#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/vector/b3dvector.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -57,12 +56,6 @@ namespace drawinglayer::attribute
}
};
- namespace
- {
- struct theGlobalDefault :
- public rtl::Static< Sdr3DLightAttribute::ImplType, theGlobalDefault > {};
- }
-
Sdr3DLightAttribute::Sdr3DLightAttribute(
const basegfx::BColor& rColor,
const basegfx::B3DVector& rDirection,
diff --git a/drawinglayer/source/attribute/sdrlightingattribute3d.cxx b/drawinglayer/source/attribute/sdrlightingattribute3d.cxx
index 93b4cf4cec0a..0f625756383c 100644
--- a/drawinglayer/source/attribute/sdrlightingattribute3d.cxx
+++ b/drawinglayer/source/attribute/sdrlightingattribute3d.cxx
@@ -21,7 +21,6 @@
#include <basegfx/color/bcolor.hxx>
#include <basegfx/vector/b3dvector.hxx>
#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -35,15 +34,13 @@ namespace drawinglayer::attribute
ImpSdrLightingAttribute(
const basegfx::BColor& rAmbientLight,
- const std::vector< Sdr3DLightAttribute >& rLightVector)
+ std::vector< Sdr3DLightAttribute >&& rLightVector)
: maAmbientLight(rAmbientLight),
- maLightVector(rLightVector)
+ maLightVector(std::move(rLightVector))
{
}
ImpSdrLightingAttribute()
- : maAmbientLight(basegfx::BColor()),
- maLightVector(std::vector< Sdr3DLightAttribute >())
{
}
@@ -60,20 +57,23 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrLightingAttribute::ImplType, theGlobalDefault > {};
+ SdrLightingAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrLightingAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
SdrLightingAttribute::SdrLightingAttribute(
const basegfx::BColor& rAmbientLight,
- const std::vector< Sdr3DLightAttribute >& rLightVector)
+ std::vector< Sdr3DLightAttribute >&& rLightVector)
: mpSdrLightingAttribute(ImpSdrLightingAttribute(
- rAmbientLight, rLightVector))
+ rAmbientLight, std::move(rLightVector)))
{
}
SdrLightingAttribute::SdrLightingAttribute()
- : mpSdrLightingAttribute(theGlobalDefault::get())
+ : mpSdrLightingAttribute(theGlobalDefault())
{
}
@@ -86,7 +86,7 @@ namespace drawinglayer::attribute
bool SdrLightingAttribute::isDefault() const
{
- return mpSdrLightingAttribute.same_object(theGlobalDefault::get());
+ return mpSdrLightingAttribute.same_object(theGlobalDefault());
}
SdrLightingAttribute& SdrLightingAttribute::operator=(const SdrLightingAttribute&) = default;
@@ -107,6 +107,11 @@ namespace drawinglayer::attribute
return mpSdrLightingAttribute->getLightVector();
}
+ const basegfx::BColor& SdrLightingAttribute::getAmbientLightColor() const
+ {
+ return mpSdrLightingAttribute->maAmbientLight;
+ }
+
// color model solver
basegfx::BColor SdrLightingAttribute::solveColorModel(
const basegfx::B3DVector& rNormalInEyeCoordinates,
@@ -135,7 +140,7 @@ namespace drawinglayer::attribute
const Sdr3DLightAttribute& rLight(rLightVector[a]);
const double fCosFac(rLight.getDirection().scalar(aEyeNormal));
- if(basegfx::fTools::more(fCosFac, 0.0))
+ if(fCosFac > 0.0)
{
aRetval += (rLight.getColor() * rColor) * fCosFac;
@@ -146,7 +151,7 @@ namespace drawinglayer::attribute
aSpecularNormal.normalize();
double fCosFac2(aSpecularNormal.scalar(aEyeNormal));
- if(basegfx::fTools::more(fCosFac2, 0.0))
+ if(fCosFac2 > 0.0)
{
fCosFac2 = pow(fCosFac2, static_cast<double>(nSpecularIntensity));
aRetval += rSpecular * fCosFac2;
diff --git a/drawinglayer/source/attribute/sdrlineattribute.cxx b/drawinglayer/source/attribute/sdrlineattribute.cxx
index 257d934d83bd..f8d4aefb0a95 100644
--- a/drawinglayer/source/attribute/sdrlineattribute.cxx
+++ b/drawinglayer/source/attribute/sdrlineattribute.cxx
@@ -19,7 +19,6 @@
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -28,13 +27,13 @@ namespace drawinglayer::attribute
{
public:
// line definitions
- basegfx::B2DLineJoin meJoin; // B2DLINEJOIN_* defines
double mfWidth; // 1/100th mm, 0.0==hair
double mfTransparence; // [0.0 .. 1.0], 0.0==no transp.
+ double mfFullDotDashLen; // sum of maDotDashArray (for convenience)
basegfx::BColor maColor; // color of line
+ std::vector< double > maDotDashArray; // array of double which defines the dot-dash pattern
+ basegfx::B2DLineJoin meJoin; // B2DLINEJOIN_* defines
css::drawing::LineCap meCap; // BUTT, ROUND, or SQUARE
- std::vector< double > maDotDashArray; // array of double which defines the dot-dash pattern
- double mfFullDotDashLen; // sum of maDotDashArray (for convenience)
ImpSdrLineAttribute(
basegfx::B2DLineJoin eJoin,
@@ -42,26 +41,24 @@ namespace drawinglayer::attribute
double fTransparence,
const basegfx::BColor& rColor,
css::drawing::LineCap eCap,
- const std::vector< double >& rDotDashArray,
+ std::vector< double >&& rDotDashArray,
double fFullDotDashLen)
- : meJoin(eJoin),
- mfWidth(fWidth),
+ : mfWidth(fWidth),
mfTransparence(fTransparence),
+ mfFullDotDashLen(fFullDotDashLen),
maColor(rColor),
- meCap(eCap),
- maDotDashArray(rDotDashArray),
- mfFullDotDashLen(fFullDotDashLen)
+ maDotDashArray(std::move(rDotDashArray)),
+ meJoin(eJoin),
+ meCap(eCap)
{
}
ImpSdrLineAttribute()
- : meJoin(basegfx::B2DLineJoin::Round),
- mfWidth(0.0),
+ : mfWidth(0.0),
mfTransparence(0.0),
- maColor(basegfx::BColor()),
- meCap(css::drawing::LineCap_BUTT),
- maDotDashArray(std::vector< double >()),
- mfFullDotDashLen(0.0)
+ mfFullDotDashLen(0.0),
+ meJoin(basegfx::B2DLineJoin::Round),
+ meCap(css::drawing::LineCap_BUTT)
{
}
@@ -87,8 +84,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrLineAttribute::ImplType, theGlobalDefault > {};
+ SdrLineAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrLineAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
SdrLineAttribute::SdrLineAttribute(
@@ -97,7 +97,7 @@ namespace drawinglayer::attribute
double fTransparence,
const basegfx::BColor& rColor,
css::drawing::LineCap eCap,
- const std::vector< double >& rDotDashArray,
+ std::vector< double >&& rDotDashArray,
double fFullDotDashLen)
: mpSdrLineAttribute(
ImpSdrLineAttribute(
@@ -106,14 +106,14 @@ namespace drawinglayer::attribute
fTransparence,
rColor,
eCap,
- rDotDashArray,
+ std::move(rDotDashArray),
fFullDotDashLen))
{
}
SdrLineAttribute::SdrLineAttribute()
- : mpSdrLineAttribute(theGlobalDefault::get())
+ : mpSdrLineAttribute(theGlobalDefault())
{
}
@@ -125,7 +125,7 @@ namespace drawinglayer::attribute
bool SdrLineAttribute::isDefault() const
{
- return mpSdrLineAttribute.same_object(theGlobalDefault::get());
+ return mpSdrLineAttribute.same_object(theGlobalDefault());
}
SdrLineAttribute& SdrLineAttribute::operator=(const SdrLineAttribute&) = default;
diff --git a/drawinglayer/source/attribute/sdrlinestartendattribute.cxx b/drawinglayer/source/attribute/sdrlinestartendattribute.cxx
index c0a88b6f8c0b..911f8aef8bf5 100644
--- a/drawinglayer/source/attribute/sdrlinestartendattribute.cxx
+++ b/drawinglayer/source/attribute/sdrlinestartendattribute.cxx
@@ -19,7 +19,7 @@
#include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <rtl/instance.hxx>
+#include <utility>
namespace drawinglayer::attribute
@@ -39,16 +39,16 @@ namespace drawinglayer::attribute
bool mbEndCentered : 1; // Line is centered on line end point
ImpSdrLineStartEndAttribute(
- const basegfx::B2DPolyPolygon& rStartPolyPolygon,
- const basegfx::B2DPolyPolygon& rEndPolyPolygon,
+ basegfx::B2DPolyPolygon aStartPolyPolygon,
+ basegfx::B2DPolyPolygon aEndPolyPolygon,
double fStartWidth,
double fEndWidth,
bool bStartActive,
bool bEndActive,
bool bStartCentered,
bool bEndCentered)
- : maStartPolyPolygon(rStartPolyPolygon),
- maEndPolyPolygon(rEndPolyPolygon),
+ : maStartPolyPolygon(std::move(aStartPolyPolygon)),
+ maEndPolyPolygon(std::move(aEndPolyPolygon)),
mfStartWidth(fStartWidth),
mfEndWidth(fEndWidth),
mbStartActive(bStartActive),
@@ -59,9 +59,7 @@ namespace drawinglayer::attribute
}
ImpSdrLineStartEndAttribute()
- : maStartPolyPolygon(basegfx::B2DPolyPolygon()),
- maEndPolyPolygon(basegfx::B2DPolyPolygon()),
- mfStartWidth(0.0),
+ : mfStartWidth(0.0),
mfEndWidth(0.0),
mbStartActive(false),
mbEndActive(false),
@@ -95,8 +93,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrLineStartEndAttribute::ImplType, theGlobalDefault > {};
+ SdrLineStartEndAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrLineStartEndAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
SdrLineStartEndAttribute::SdrLineStartEndAttribute(
@@ -114,7 +115,7 @@ namespace drawinglayer::attribute
}
SdrLineStartEndAttribute::SdrLineStartEndAttribute()
- : mpSdrLineStartEndAttribute(theGlobalDefault::get())
+ : mpSdrLineStartEndAttribute(theGlobalDefault())
{
}
@@ -126,7 +127,7 @@ namespace drawinglayer::attribute
bool SdrLineStartEndAttribute::isDefault() const
{
- return mpSdrLineStartEndAttribute.same_object(theGlobalDefault::get());
+ return mpSdrLineStartEndAttribute.same_object(theGlobalDefault());
}
SdrLineStartEndAttribute& SdrLineStartEndAttribute::operator=(const SdrLineStartEndAttribute&) = default;
diff --git a/drawinglayer/source/attribute/sdrobjectattribute3d.cxx b/drawinglayer/source/attribute/sdrobjectattribute3d.cxx
index 78e919d9ab3f..dad8a07eebc5 100644
--- a/drawinglayer/source/attribute/sdrobjectattribute3d.cxx
+++ b/drawinglayer/source/attribute/sdrobjectattribute3d.cxx
@@ -19,7 +19,6 @@
#include <drawinglayer/attribute/sdrobjectattribute3d.hxx>
#include <drawinglayer/attribute/materialattribute3d.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -96,12 +95,6 @@ namespace drawinglayer::attribute
}
};
- namespace
- {
- struct theGlobalDefault :
- public rtl::Static< Sdr3DObjectAttribute::ImplType, theGlobalDefault > {};
- }
-
Sdr3DObjectAttribute::Sdr3DObjectAttribute(
css::drawing::NormalsKind aNormalsKind,
css::drawing::TextureProjectionMode aTextureProjectionX,
diff --git a/drawinglayer/source/attribute/sdrsceneattribute3d.cxx b/drawinglayer/source/attribute/sdrsceneattribute3d.cxx
index 128abf2027cf..840fe2e3074c 100644
--- a/drawinglayer/source/attribute/sdrsceneattribute3d.cxx
+++ b/drawinglayer/source/attribute/sdrsceneattribute3d.cxx
@@ -18,7 +18,6 @@
*/
#include <drawinglayer/attribute/sdrsceneattribute3d.hxx>
-#include <rtl/instance.hxx>
namespace drawinglayer::attribute
@@ -76,8 +75,11 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrSceneAttribute::ImplType, theGlobalDefault > {};
+ SdrSceneAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrSceneAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
SdrSceneAttribute::SdrSceneAttribute(
@@ -92,7 +94,7 @@ namespace drawinglayer::attribute
}
SdrSceneAttribute::SdrSceneAttribute()
- : mpSdrSceneAttribute(theGlobalDefault::get())
+ : mpSdrSceneAttribute(theGlobalDefault())
{
}
@@ -104,7 +106,7 @@ namespace drawinglayer::attribute
bool SdrSceneAttribute::isDefault() const
{
- return mpSdrSceneAttribute.same_object(theGlobalDefault::get());
+ return mpSdrSceneAttribute.same_object(theGlobalDefault());
}
SdrSceneAttribute& SdrSceneAttribute::operator=(const SdrSceneAttribute&) = default;
diff --git a/drawinglayer/source/attribute/sdrshadowattribute.cxx b/drawinglayer/source/attribute/sdrshadowattribute.cxx
index 9e379acaae28..1eb1b3ea687c 100644
--- a/drawinglayer/source/attribute/sdrshadowattribute.cxx
+++ b/drawinglayer/source/attribute/sdrshadowattribute.cxx
@@ -20,7 +20,7 @@
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <rtl/instance.hxx>
+#include <docmodel/theme/FormatScheme.hxx>
namespace drawinglayer::attribute
@@ -33,6 +33,7 @@ namespace drawinglayer::attribute
basegfx::B2DVector maSize; // [0.0 .. 2.0]
double mfTransparence; // [0.0 .. 1.0], 0.0==no transp.
sal_Int32 mnBlur; // [0 .. 180], radius of the blur
+ model::RectangleAlignment meAlignment{model::RectangleAlignment::Unset}; // alignment of the shadow
basegfx::BColor maColor; // color of shadow
ImpSdrShadowAttribute(
@@ -40,21 +41,20 @@ namespace drawinglayer::attribute
const basegfx::B2DVector& rSize,
double fTransparence,
sal_Int32 nBlur,
+ model::RectangleAlignment eAlignment,
const basegfx::BColor& rColor)
: maOffset(rOffset),
maSize(rSize),
mfTransparence(fTransparence),
mnBlur(nBlur),
+ meAlignment(eAlignment),
maColor(rColor)
{
}
ImpSdrShadowAttribute()
- : maOffset(basegfx::B2DVector()),
- maSize(basegfx::B2DVector()),
- mfTransparence(0.0),
- mnBlur(0),
- maColor(basegfx::BColor())
+ : mfTransparence(0.0),
+ mnBlur(0)
{
}
@@ -71,14 +71,18 @@ namespace drawinglayer::attribute
&& getSize() == rCandidate.getSize()
&& getTransparence() == rCandidate.getTransparence()
&& getBlur() == rCandidate.getBlur()
+ && meAlignment == rCandidate.meAlignment
&& getColor() == rCandidate.getColor());
}
};
namespace
{
- struct theGlobalDefault :
- public rtl::Static< SdrShadowAttribute::ImplType, theGlobalDefault > {};
+ SdrShadowAttribute::ImplType& theGlobalDefault()
+ {
+ static SdrShadowAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
@@ -87,14 +91,15 @@ namespace drawinglayer::attribute
const basegfx::B2DVector& rSize,
double fTransparence,
sal_Int32 nBlur,
+ model::RectangleAlignment eAlignment,
const basegfx::BColor& rColor)
: mpSdrShadowAttribute(ImpSdrShadowAttribute(
- rOffset, rSize, fTransparence,nBlur, rColor))
+ rOffset, rSize, fTransparence, nBlur, eAlignment, rColor))
{
}
SdrShadowAttribute::SdrShadowAttribute()
- : mpSdrShadowAttribute(theGlobalDefault::get())
+ : mpSdrShadowAttribute(theGlobalDefault())
{
}
@@ -106,7 +111,7 @@ namespace drawinglayer::attribute
bool SdrShadowAttribute::isDefault() const
{
- return mpSdrShadowAttribute.same_object(theGlobalDefault::get());
+ return mpSdrShadowAttribute.same_object(theGlobalDefault());
}
SdrShadowAttribute& SdrShadowAttribute::operator=(const SdrShadowAttribute&) = default;
@@ -142,6 +147,11 @@ namespace drawinglayer::attribute
return mpSdrShadowAttribute->getBlur();
}
+ model::RectangleAlignment SdrShadowAttribute::getAlignment() const
+ {
+ return mpSdrShadowAttribute->meAlignment;
+ }
+
const basegfx::BColor& SdrShadowAttribute::getColor() const
{
return mpSdrShadowAttribute->getColor();
diff --git a/drawinglayer/source/attribute/strokeattribute.cxx b/drawinglayer/source/attribute/strokeattribute.cxx
index 493c906ba91b..d925eb65acbe 100644
--- a/drawinglayer/source/attribute/strokeattribute.cxx
+++ b/drawinglayer/source/attribute/strokeattribute.cxx
@@ -18,7 +18,6 @@
*/
#include <drawinglayer/attribute/strokeattribute.hxx>
-#include <rtl/instance.hxx>
#include <numeric>
@@ -32,16 +31,15 @@ namespace drawinglayer::attribute
double mfFullDotDashLen; // sum of maDotDashArray (for convenience)
ImpStrokeAttribute(
- const std::vector< double >& rDotDashArray,
+ std::vector< double >&& rDotDashArray,
double fFullDotDashLen)
- : maDotDashArray(rDotDashArray),
+ : maDotDashArray(std::move(rDotDashArray)),
mfFullDotDashLen(fFullDotDashLen)
{
}
ImpStrokeAttribute()
- : maDotDashArray(std::vector< double >()),
- mfFullDotDashLen(0.0)
+ : mfFullDotDashLen(0.0)
{
}
@@ -68,20 +66,23 @@ namespace drawinglayer::attribute
namespace
{
- struct theGlobalDefault :
- public rtl::Static< StrokeAttribute::ImplType, theGlobalDefault > {};
+ StrokeAttribute::ImplType& theGlobalDefault()
+ {
+ static StrokeAttribute::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
StrokeAttribute::StrokeAttribute(
- const std::vector< double >& rDotDashArray,
+ std::vector< double >&& rDotDashArray,
double fFullDotDashLen)
: mpStrokeAttribute(ImpStrokeAttribute(
- rDotDashArray, fFullDotDashLen))
+ std::move(rDotDashArray), fFullDotDashLen))
{
}
StrokeAttribute::StrokeAttribute()
- : mpStrokeAttribute(theGlobalDefault::get())
+ : mpStrokeAttribute(theGlobalDefault())
{
}
@@ -93,7 +94,7 @@ namespace drawinglayer::attribute
bool StrokeAttribute::isDefault() const
{
- return mpStrokeAttribute.same_object(theGlobalDefault::get());
+ return mpStrokeAttribute.same_object(theGlobalDefault());
}
StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute&) = default;
diff --git a/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx
index 66b29591df7e..91f2ad89af3d 100644
--- a/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx
+++ b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx
@@ -24,16 +24,16 @@
#include <com/sun/star/uno/XComponentContext.hpp>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/supportsservice.hxx>
-#include <comphelper/sequence.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/numeric/ftools.hxx>
-#include <vcl/bitmapex.hxx>
+#include <vcl/bitmap.hxx>
#include <vcl/canvastools.hxx>
#include <com/sun/star/geometry/RealRectangle2D.hpp>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-#include <converters.hxx>
+#include <drawinglayer/converters.hxx>
+#include <comphelper/sequenceashashmap.hxx>
using namespace ::com::sun::star;
@@ -43,7 +43,7 @@ namespace drawinglayer::unorenderer
namespace {
class XPrimitive2DRenderer:
- public cppu::WeakAggImplHelper2<
+ public cppu::WeakImplHelper<
css::graphic::XPrimitive2DRenderer, css::lang::XServiceInfo>
{
public:
@@ -81,6 +81,16 @@ namespace drawinglayer::unorenderer
const css::geometry::RealRectangle2D& Range,
::sal_uInt32 MaximumQuadraticPixels)
{
+ o3tl::Length eRangeUnit = o3tl::Length::mm100;
+ comphelper::SequenceAsHashMap aViewInformationMap(aViewInformationSequence);
+ auto it = aViewInformationMap.find(u"RangeUnit"_ustr);
+ if (it != aViewInformationMap.end())
+ {
+ sal_Int32 nVal{};
+ it->second >>= nVal;
+ eRangeUnit = static_cast<o3tl::Length>(nVal);
+ }
+
uno::Reference< rendering::XBitmap > XBitmap;
if(aPrimitive2DSequence.hasElements())
@@ -89,7 +99,7 @@ namespace drawinglayer::unorenderer
const double fWidth(aRange.getWidth());
const double fHeight(aRange.getHeight());
- if(basegfx::fTools::more(fWidth, 0.0) && basegfx::fTools::more(fHeight, 0.0))
+ if(fWidth > 0.0 && fHeight > 0.0)
{
if(0 == DPI_X)
{
@@ -106,10 +116,17 @@ namespace drawinglayer::unorenderer
MaximumQuadraticPixels = 500000;
}
- const geometry::ViewInformation2D aViewInformation2D(aViewInformationSequence);
- const double fFactor100th_mmToInch(1.0 / (2.54 * 1000.0));
- const sal_uInt32 nDiscreteWidth(basegfx::fround((fWidth * fFactor100th_mmToInch) * DPI_X));
- const sal_uInt32 nDiscreteHeight(basegfx::fround((fHeight * fFactor100th_mmToInch) * DPI_Y));
+ auto aViewInformation2D = geometry::createViewInformation2D(aViewInformationSequence);
+
+ if(aViewInformation2D.getViewport().isEmpty())
+ {
+ // we have a Viewport since we create a discrete pixel device, use it
+ // if none is given
+ aViewInformation2D.setViewport(aRange);
+ }
+
+ const sal_uInt32 nDiscreteWidth(basegfx::fround(o3tl::convert(fWidth, eRangeUnit, o3tl::Length::in) * DPI_X));
+ const sal_uInt32 nDiscreteHeight(basegfx::fround(o3tl::convert(fHeight, eRangeUnit, o3tl::Length::in) * DPI_Y));
basegfx::B2DHomMatrix aEmbedding(
basegfx::utils::createTranslateB2DHomMatrix(
@@ -123,22 +140,22 @@ namespace drawinglayer::unorenderer
const primitive2d::Primitive2DReference xEmbedRef(
new primitive2d::TransformPrimitive2D(
aEmbedding,
- comphelper::sequenceToContainer<primitive2d::Primitive2DContainer>(aPrimitive2DSequence)));
- const primitive2d::Primitive2DContainer xEmbedSeq { xEmbedRef };
+ aPrimitive2DSequence));
+ primitive2d::Primitive2DContainer xEmbedSeq { xEmbedRef };
- BitmapEx aBitmapEx(
- convertToBitmapEx(
- xEmbedSeq,
+ Bitmap aBitmap(
+ convertToBitmap(
+ std::move(xEmbedSeq),
aViewInformation2D,
nDiscreteWidth,
nDiscreteHeight,
MaximumQuadraticPixels));
- if(!aBitmapEx.IsEmpty())
+ if(!aBitmap.IsEmpty())
{
- aBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
- aBitmapEx.SetPrefSize(Size(basegfx::fround(fWidth), basegfx::fround(fHeight)));
- XBitmap = vcl::unotools::xBitmapFromBitmapEx(aBitmapEx);
+ aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ aBitmap.SetPrefSize(Size(basegfx::fround<tools::Long>(fWidth), basegfx::fround<tools::Long>(fHeight)));
+ XBitmap = vcl::unotools::xBitmapFromBitmap(aBitmap);
}
}
}
@@ -148,7 +165,7 @@ namespace drawinglayer::unorenderer
OUString SAL_CALL XPrimitive2DRenderer::getImplementationName()
{
- return "drawinglayer::unorenderer::XPrimitive2DRenderer";
+ return u"drawinglayer::unorenderer::XPrimitive2DRenderer"_ustr;
}
sal_Bool SAL_CALL XPrimitive2DRenderer::supportsService(const OUString& rServiceName)
@@ -158,7 +175,7 @@ namespace drawinglayer::unorenderer
uno::Sequence< OUString > SAL_CALL XPrimitive2DRenderer::getSupportedServiceNames()
{
- return { "com.sun.star.graphic.Primitive2DTools" };
+ return { u"com.sun.star.graphic.Primitive2DTools"_ustr };
}
} // end of namespace
diff --git a/drawinglayer/source/dumper/EnhancedShapeDumper.cxx b/drawinglayer/source/dumper/EnhancedShapeDumper.cxx
index 84fbc58dbb3b..333bf4bff7c7 100644
--- a/drawinglayer/source/dumper/EnhancedShapeDumper.cxx
+++ b/drawinglayer/source/dumper/EnhancedShapeDumper.cxx
@@ -19,139 +19,139 @@ using namespace com::sun::star;
void EnhancedShapeDumper::dumpEnhancedCustomShapeExtrusionService(const uno::Reference< beans::XPropertySet >& xPropSet)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Extrusion");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Extrusion"_ustr);
bool bExtrusion;
if(anotherAny >>= bExtrusion)
dumpExtrusionAsAttribute(bExtrusion);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Brightness");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Brightness"_ustr);
double aBrightness = double();
if(anotherAny >>= aBrightness)
dumpBrightnessAsAttribute(aBrightness);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Depth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Depth"_ustr);
drawing::EnhancedCustomShapeParameterPair aDepth;
if(anotherAny >>= aDepth)
dumpDepthAsElement(aDepth);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Diffusion");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Diffusion"_ustr);
double aDiffusion = double();
if(anotherAny >>= aDiffusion)
dumpDiffusionAsAttribute(aDiffusion);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("NumberOfLineSegments");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"NumberOfLineSegments"_ustr);
sal_Int32 aNumberOfLineSegments = sal_Int32();
if(anotherAny >>= aNumberOfLineSegments)
dumpNumberOfLineSegmentsAsAttribute(aNumberOfLineSegments);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LightFace");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LightFace"_ustr);
bool bLightFace;
if(anotherAny >>= bLightFace)
dumpLightFaceAsAttribute(bLightFace);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FirstLightHarsh");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FirstLightHarsh"_ustr);
bool bFirstLightHarsh;
if(anotherAny >>= bFirstLightHarsh)
dumpFirstLightHarshAsAttribute(bFirstLightHarsh);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("SecondLightHarsh");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"SecondLightHarsh"_ustr);
bool bSecondLightHarsh;
if(anotherAny >>= bSecondLightHarsh)
dumpSecondLightHarshAsAttribute(bSecondLightHarsh);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FirstLightLevel");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FirstLightLevel"_ustr);
double aFirstLightLevel = double();
if(anotherAny >>= aFirstLightLevel)
dumpFirstLightLevelAsAttribute(aFirstLightLevel);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("SecondLightLevel");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"SecondLightLevel"_ustr);
double aSecondLightLevel = double();
if(anotherAny >>= aSecondLightLevel)
dumpSecondLightLevelAsAttribute(aSecondLightLevel);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FirstLightDirection");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FirstLightDirection"_ustr);
drawing::Direction3D aFirstLightDirection;
if(anotherAny >>= aFirstLightDirection)
dumpFirstLightDirectionAsElement(aFirstLightDirection);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("SecondLightDirection");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"SecondLightDirection"_ustr);
drawing::Direction3D aSecondLightDirection;
if(anotherAny >>= aSecondLightDirection)
dumpSecondLightDirectionAsElement(aSecondLightDirection);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Metal");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Metal"_ustr);
bool bMetal;
if(anotherAny >>= bMetal)
dumpMetalAsAttribute(bMetal);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ShadeMode");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ShadeMode"_ustr);
drawing::ShadeMode eShadeMode;
if(anotherAny >>= eShadeMode)
dumpShadeModeAsAttribute(eShadeMode);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RotateAngle");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RotateAngle"_ustr);
drawing::EnhancedCustomShapeParameterPair aRotateAngle;
if(anotherAny >>= aRotateAngle)
dumpRotateAngleAsElement(aRotateAngle);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RotationCenter");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RotationCenter"_ustr);
drawing::Direction3D aRotationCenter;
if(anotherAny >>= aRotationCenter)
dumpRotationCenterAsElement(aRotationCenter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Shininess");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Shininess"_ustr);
double aShininess = double();
if(anotherAny >>= aShininess)
dumpShininessAsAttribute(aShininess);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Skew");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Skew"_ustr);
drawing::EnhancedCustomShapeParameterPair aSkew;
if(anotherAny >>= aSkew)
dumpSkewAsElement(aSkew);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Specularity");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Specularity"_ustr);
double aSpecularity = double();
if(anotherAny >>= aSpecularity)
dumpSpecularityAsAttribute(aSpecularity);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ProjectionMode");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ProjectionMode"_ustr);
drawing::ProjectionMode eProjectionMode;
if(anotherAny >>= eProjectionMode)
dumpProjectionModeAsAttribute(eProjectionMode);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ViewPoint");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ViewPoint"_ustr);
drawing::Position3D aViewPoint;
if(anotherAny >>= aViewPoint)
dumpViewPointAsElement(aViewPoint);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Origin");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Origin"_ustr);
drawing::EnhancedCustomShapeParameterPair aOrigin;
if(anotherAny >>= aOrigin)
dumpOriginAsElement(aOrigin);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ExtrusionColor");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ExtrusionColor"_ustr);
bool bExtrusionColor;
if(anotherAny >>= bExtrusionColor)
dumpExtrusionColorAsAttribute(bExtrusionColor);
@@ -160,109 +160,109 @@ void EnhancedShapeDumper::dumpEnhancedCustomShapeExtrusionService(const uno::Ref
void EnhancedShapeDumper::dumpExtrusionAsAttribute(bool bExtrusion)
{
if(bExtrusion)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusion"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusion"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusion"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusion"), "%s", "false");
}
void EnhancedShapeDumper::dumpBrightnessAsAttribute(double aBrightness)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("brightness"), "%f", aBrightness);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("brightness"), "%f", aBrightness);
}
void EnhancedShapeDumper::dumpEnhancedCustomShapeParameterPair(
const drawing::EnhancedCustomShapeParameterPair& aParameterPair)
{
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "First" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "First" ));
dumpEnhancedCustomShapeParameter(aParameterPair.First);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Second" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Second" ));
dumpEnhancedCustomShapeParameter(aParameterPair.Second);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
}
void EnhancedShapeDumper::dumpDepthAsElement(const drawing::EnhancedCustomShapeParameterPair& aDepth)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Depth" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Depth" ));
dumpEnhancedCustomShapeParameterPair(aDepth);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpDiffusionAsAttribute(double aDiffusion)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("diffusion"), "%f", aDiffusion);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("diffusion"), "%f", aDiffusion);
}
void EnhancedShapeDumper::dumpNumberOfLineSegmentsAsAttribute(sal_Int32 aNumberOfLineSegments)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("numberOfLineSegments"), "%" SAL_PRIdINT32, aNumberOfLineSegments);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("numberOfLineSegments"), "%" SAL_PRIdINT32, aNumberOfLineSegments);
}
void EnhancedShapeDumper::dumpLightFaceAsAttribute(bool bLightFace)
{
if(bLightFace)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lightFace"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lightFace"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lightFace"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lightFace"), "%s", "false");
}
void EnhancedShapeDumper::dumpFirstLightHarshAsAttribute(bool bFirstLightHarsh)
{
if(bFirstLightHarsh)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightHarsh"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightHarsh"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightHarsh"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightHarsh"), "%s", "false");
}
void EnhancedShapeDumper::dumpSecondLightHarshAsAttribute(bool bSecondLightHarsh)
{
if(bSecondLightHarsh)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightHarsh"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightHarsh"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightHarsh"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightHarsh"), "%s", "false");
}
void EnhancedShapeDumper::dumpFirstLightLevelAsAttribute(double aFirstLightLevel)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightLevel"), "%f", aFirstLightLevel);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("firstLightLevel"), "%f", aFirstLightLevel);
}
void EnhancedShapeDumper::dumpSecondLightLevelAsAttribute(double aSecondLightLevel)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightLevel"), "%f", aSecondLightLevel);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("secondLightLevel"), "%f", aSecondLightLevel);
}
void EnhancedShapeDumper::dumpDirection3D(drawing::Direction3D aDirection3D)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionX"), "%f", aDirection3D.DirectionX);
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionY"), "%f", aDirection3D.DirectionY);
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionZ"), "%f", aDirection3D.DirectionZ);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionX"), "%f", aDirection3D.DirectionX);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionY"), "%f", aDirection3D.DirectionY);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("directionZ"), "%f", aDirection3D.DirectionZ);
}
void EnhancedShapeDumper::dumpFirstLightDirectionAsElement(drawing::Direction3D aFirstLightDirection)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FirstLightDirection" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FirstLightDirection" ));
dumpDirection3D(aFirstLightDirection);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpSecondLightDirectionAsElement(drawing::Direction3D aSecondLightDirection)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "SecondLightDirection" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "SecondLightDirection" ));
dumpDirection3D(aSecondLightDirection);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpMetalAsAttribute(bool bMetal)
{
if(bMetal)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("metal"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("metal"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("metal"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("metal"), "%s", "false");
}
void EnhancedShapeDumper::dumpShadeModeAsAttribute(drawing::ShadeMode eShadeMode)
@@ -270,16 +270,16 @@ void EnhancedShapeDumper::dumpShadeModeAsAttribute(drawing::ShadeMode eShadeMode
switch(eShadeMode)
{
case drawing::ShadeMode_FLAT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "FLAT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "FLAT");
break;
case drawing::ShadeMode_PHONG:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "PHONG");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "PHONG");
break;
case drawing::ShadeMode_SMOOTH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "SMOOTH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "SMOOTH");
break;
case drawing::ShadeMode_DRAFT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "DRAFT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadeMode"), "%s", "DRAFT");
break;
default:
break;
@@ -288,33 +288,33 @@ void EnhancedShapeDumper::dumpShadeModeAsAttribute(drawing::ShadeMode eShadeMode
void EnhancedShapeDumper::dumpRotateAngleAsElement(const drawing::EnhancedCustomShapeParameterPair& aRotateAngle)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RotateAngle" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RotateAngle" ));
dumpEnhancedCustomShapeParameterPair(aRotateAngle);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRotationCenterAsElement(drawing::Direction3D aRotationCenter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RotationCenter" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RotationCenter" ));
dumpDirection3D(aRotationCenter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpShininessAsAttribute(double aShininess)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shininess"), "%f", aShininess);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shininess"), "%f", aShininess);
}
void EnhancedShapeDumper::dumpSkewAsElement(const drawing::EnhancedCustomShapeParameterPair& aSkew)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Skew" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Skew" ));
dumpEnhancedCustomShapeParameterPair(aSkew);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpSpecularityAsAttribute(double aSpecularity)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("specularity"), "%f", aSpecularity);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("specularity"), "%f", aSpecularity);
}
void EnhancedShapeDumper::dumpProjectionModeAsAttribute(drawing::ProjectionMode eProjectionMode)
@@ -322,10 +322,10 @@ void EnhancedShapeDumper::dumpProjectionModeAsAttribute(drawing::ProjectionMode
switch(eProjectionMode)
{
case drawing::ProjectionMode_PARALLEL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("projectionMode"), "%s", "PARALLEL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("projectionMode"), "%s", "PARALLEL");
break;
case drawing::ProjectionMode_PERSPECTIVE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("projectionMode"), "%s", "PERSPECTIVE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("projectionMode"), "%s", "PERSPECTIVE");
break;
default:
break;
@@ -334,26 +334,26 @@ void EnhancedShapeDumper::dumpProjectionModeAsAttribute(drawing::ProjectionMode
void EnhancedShapeDumper::dumpViewPointAsElement(drawing::Position3D aViewPoint)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ViewPoint" ));
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionX"), "%f", aViewPoint.PositionX);
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionY"), "%f", aViewPoint.PositionY);
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionZ"), "%f", aViewPoint.PositionZ);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ViewPoint" ));
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionX"), "%f", aViewPoint.PositionX);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionY"), "%f", aViewPoint.PositionY);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("positionZ"), "%f", aViewPoint.PositionZ);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpOriginAsElement(const drawing::EnhancedCustomShapeParameterPair& aOrigin)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Origin" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Origin" ));
dumpEnhancedCustomShapeParameterPair(aOrigin);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpExtrusionColorAsAttribute(bool bExtrusionColor)
{
if(bExtrusionColor)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionColor"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionColor"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionColor"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionColor"), "%s", "false");
}
@@ -363,233 +363,228 @@ void EnhancedShapeDumper::dumpExtrusionColorAsAttribute(bool bExtrusionColor)
void EnhancedShapeDumper::dumpEnhancedCustomShapeGeometryService(const uno::Reference< beans::XPropertySet >& xPropSet)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Type");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Type"_ustr);
OUString sType;
if(anotherAny >>= sType)
dumpTypeAsAttribute(sType);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ViewBox");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ViewBox"_ustr);
awt::Rectangle aViewBox;
if(anotherAny >>= aViewBox)
dumpViewBoxAsElement(aViewBox);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("MirroredX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"MirroredX"_ustr);
bool bMirroredX;
if(anotherAny >>= bMirroredX)
dumpMirroredXAsAttribute(bMirroredX);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("MirroredY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"MirroredY"_ustr);
bool bMirroredY;
if(anotherAny >>= bMirroredY)
dumpMirroredYAsAttribute(bMirroredY);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextRotateAngle");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextRotateAngle"_ustr);
double aTextRotateAngle = double();
if(anotherAny >>= aTextRotateAngle)
dumpTextRotateAngleAsAttribute(aTextRotateAngle);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("AdjustmentValues");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"AdjustmentValues"_ustr);
uno::Sequence< drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
if(anotherAny >>= aAdjustmentValues)
dumpAdjustmentValuesAsElement(aAdjustmentValues);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Extrusion");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Extrusion"_ustr);
uno::Sequence< beans::PropertyValue > aExtrusion;
if(anotherAny >>= aExtrusion)
dumpExtrusionAsElement(aExtrusion);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Path");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Path"_ustr);
uno::Sequence< beans::PropertyValue > aPath;
if(anotherAny >>= aPath)
dumpPathAsElement(aPath);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextPath");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextPath"_ustr);
uno::Sequence< beans::PropertyValue > aTextPath;
if(anotherAny >>= aTextPath)
dumpTextPathAsElement(aTextPath);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Equations");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Equations"_ustr);
uno::Sequence< OUString > aEquations;
if(anotherAny >>= aEquations)
dumpEquationsAsElement(aEquations);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Handles");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Handles"_ustr);
uno::Sequence< beans::PropertyValues > aHandles;
if(anotherAny >>= aHandles)
dumpHandlesAsElement(aHandles);
}
}
-void EnhancedShapeDumper::dumpTypeAsAttribute(const OUString& sType)
+void EnhancedShapeDumper::dumpTypeAsAttribute(std::u16string_view sType)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%s",
OUStringToOString(sType, RTL_TEXTENCODING_UTF8).getStr());
}
void EnhancedShapeDumper::dumpViewBoxAsElement(awt::Rectangle aViewBox)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ViewBox" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("x"), "%" SAL_PRIdINT32, aViewBox.X);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("y"), "%" SAL_PRIdINT32, aViewBox.Y);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, aViewBox.Width);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, aViewBox.Height);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ViewBox" ));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("x"), "%" SAL_PRIdINT32, aViewBox.X);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("y"), "%" SAL_PRIdINT32, aViewBox.Y);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, aViewBox.Width);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, aViewBox.Height);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpMirroredXAsAttribute(bool bMirroredX)
{
if(bMirroredX)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredX"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredX"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredX"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredX"), "%s", "false");
}
void EnhancedShapeDumper::dumpMirroredYAsAttribute(bool bMirroredY)
{
if(bMirroredY)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredY"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredY"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredY"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("mirroredY"), "%s", "false");
}
void EnhancedShapeDumper::dumpTextRotateAngleAsAttribute(double aTextRotateAngle)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textRotateAngle"), "%f", aTextRotateAngle);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textRotateAngle"), "%f", aTextRotateAngle);
}
void EnhancedShapeDumper::dumpAdjustmentValuesAsElement(const uno::Sequence< drawing::EnhancedCustomShapeAdjustmentValue>& aAdjustmentValues)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "AdjustmentValues" ));
- sal_Int32 nLength = aAdjustmentValues.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "AdjustmentValues" ));
+ for (const auto& i : aAdjustmentValues)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeAdjustmentValue" ));
- uno::Any aAny = aAdjustmentValues[i].Value;
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeAdjustmentValue" ));
+ uno::Any aAny = i.Value;
OUString sValue;
float fValue;
sal_Int32 nValue;
bool bValue;
if(aAny >>= sValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
OUStringToOString(sValue, RTL_TEXTENCODING_UTF8).getStr());
}
else if(aAny >>= nValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
}
else if(aAny >>= fValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
}
else if(aAny >>= bValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
}
- switch(aAdjustmentValues[i].State)
+ switch(i.State)
{
case beans::PropertyState_DIRECT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
break;
case beans::PropertyState_DEFAULT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
break;
case beans::PropertyState_AMBIGUOUS_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
break;
default:
break;
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpPropertyValueAsElement(const beans::PropertyValue& aPropertyValue)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValue" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValue" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
OUStringToOString(aPropertyValue.Name, RTL_TEXTENCODING_UTF8).getStr());
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("handle"), "%" SAL_PRIdINT32, aPropertyValue.Handle);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("handle"), "%" SAL_PRIdINT32, aPropertyValue.Handle);
uno::Any aAny = aPropertyValue.Value;
OUString sValue;
if(aAny >>= sValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
OUStringToOString(sValue, RTL_TEXTENCODING_UTF8).getStr());
}
switch(aPropertyValue.State)
{
case beans::PropertyState_DIRECT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
break;
case beans::PropertyState_DEFAULT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
break;
case beans::PropertyState_AMBIGUOUS_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
break;
default:
break;
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpExtrusionAsElement(const uno::Sequence< beans::PropertyValue >& aExtrusion)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Extrusion" ));
- sal_Int32 nLength = aExtrusion.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Extrusion" ));
+ for (const auto& i : aExtrusion)
{
- dumpPropertyValueAsElement(aExtrusion[i]);
+ dumpPropertyValueAsElement(i);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpPathAsElement(const uno::Sequence< beans::PropertyValue >& aPath)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Path" ));
- sal_Int32 nLength = aPath.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Path" ));
+ for (const auto& i : aPath)
{
- dumpPropertyValueAsElement(aPath[i]);
+ dumpPropertyValueAsElement(i);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpTextPathAsElement(const uno::Sequence< beans::PropertyValue >& aTextPath)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TextPath" ));
- sal_Int32 nLength = aTextPath.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TextPath" ));
+ for (const auto& i : aTextPath)
{
- dumpPropertyValueAsElement(aTextPath[i]);
+ dumpPropertyValueAsElement(i);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpEquationsAsElement(const uno::Sequence< OUString >& aEquations)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Equations" ));
- sal_Int32 nLength = aEquations.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Equations" ));
+ for (const auto& i : aEquations)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
- OUStringToOString(aEquations[i], RTL_TEXTENCODING_UTF8).getStr());
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
+ OUStringToOString(i, RTL_TEXTENCODING_UTF8).getStr());
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
// PropertyValues specifies a sequence of PropertyValue instances.
@@ -597,20 +592,18 @@ void EnhancedShapeDumper::dumpEquationsAsElement(const uno::Sequence< OUString >
// Welcome to Sequenception again.
void EnhancedShapeDumper::dumpHandlesAsElement(const uno::Sequence< beans::PropertyValues >& aHandles)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Handles" ));
- sal_Int32 nSequenceLength = aHandles.getLength();
- for (sal_Int32 i = 0; i < nSequenceLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Handles" ));
+ for (const auto& i : aHandles)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValues" ));
- uno::Sequence< beans::PropertyValue > propertyValueSequence = aHandles[i];
- sal_Int32 nLength = propertyValueSequence.getLength();
- for (sal_Int32 j = 0; j < nLength; ++j)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValues" ));
+ uno::Sequence< beans::PropertyValue > propertyValueSequence = i;
+ for (const auto& j : propertyValueSequence)
{
- dumpPropertyValueAsElement(propertyValueSequence[j]);
+ dumpPropertyValueAsElement(j);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
@@ -620,91 +613,91 @@ void EnhancedShapeDumper::dumpHandlesAsElement(const uno::Sequence< beans::Prope
void EnhancedShapeDumper::dumpEnhancedCustomShapeHandleService(const uno::Reference< beans::XPropertySet >& xPropSet)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("MirroredX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"MirroredX"_ustr);
bool bMirroredX;
if(anotherAny >>= bMirroredX)
dumpMirroredXAsAttribute(bMirroredX);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("MirroredY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"MirroredY"_ustr);
bool bMirroredY;
if(anotherAny >>= bMirroredY)
dumpMirroredYAsAttribute(bMirroredY);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Switched");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Switched"_ustr);
bool bSwitched;
if(anotherAny >>= bSwitched)
dumpSwitchedAsAttribute(bSwitched);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Position");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Position"_ustr);
drawing::EnhancedCustomShapeParameterPair aPosition;
if(anotherAny >>= aPosition)
dumpPositionAsElement(aPosition);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Polar");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Polar"_ustr);
drawing::EnhancedCustomShapeParameterPair aPolar;
if(anotherAny >>= aPolar)
dumpPolarAsElement(aPolar);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RefX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RefX"_ustr);
sal_Int32 aRefX = sal_Int32();
if(anotherAny >>= aRefX)
dumpRefXAsAttribute(aRefX);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RefY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RefY"_ustr);
sal_Int32 aRefY = sal_Int32();
if(anotherAny >>= aRefY)
dumpRefYAsAttribute(aRefY);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RefAngle");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RefAngle"_ustr);
sal_Int32 aRefAngle = sal_Int32();
if(anotherAny >>= aRefAngle)
dumpRefAngleAsAttribute(aRefAngle);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RefR");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RefR"_ustr);
sal_Int32 aRefR = sal_Int32();
if(anotherAny >>= aRefR)
dumpRefRAsAttribute(aRefR);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RangeXMinimum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RangeXMinimum"_ustr);
drawing::EnhancedCustomShapeParameter aRangeXMinimum;
if(anotherAny >>= aRangeXMinimum)
dumpRangeXMinimumAsElement(aRangeXMinimum);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RangeXMaximum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RangeXMaximum"_ustr);
drawing::EnhancedCustomShapeParameter aRangeXMaximum;
if(anotherAny >>= aRangeXMaximum)
dumpRangeXMaximumAsElement(aRangeXMaximum);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RangeYMinimum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RangeYMinimum"_ustr);
drawing::EnhancedCustomShapeParameter aRangeYMinimum;
if(anotherAny >>= aRangeYMinimum)
dumpRangeYMinimumAsElement(aRangeYMinimum);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RangeYMaximum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RangeYMaximum"_ustr);
drawing::EnhancedCustomShapeParameter aRangeYMaximum;
if(anotherAny >>= aRangeYMaximum)
dumpRangeYMaximumAsElement(aRangeYMaximum);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RadiusRangeMinimum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RadiusRangeMinimum"_ustr);
drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
if(anotherAny >>= aRadiusRangeMinimum)
dumpRadiusRangeMinimumAsElement(aRadiusRangeMinimum);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("RadiusRangeMaximum");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"RadiusRangeMaximum"_ustr);
drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
if(anotherAny >>= aRadiusRangeMaximum)
dumpRadiusRangeMaximumAsElement(aRadiusRangeMaximum);
@@ -714,43 +707,43 @@ void EnhancedShapeDumper::dumpEnhancedCustomShapeHandleService(const uno::Refere
void EnhancedShapeDumper::dumpSwitchedAsAttribute(bool bSwitched)
{
if(bSwitched)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("switched"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("switched"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("switched"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("switched"), "%s", "false");
}
void EnhancedShapeDumper::dumpPositionAsElement(const drawing::EnhancedCustomShapeParameterPair& aPosition)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Position" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Position" ));
dumpEnhancedCustomShapeParameterPair(aPosition);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpPolarAsElement(const drawing::EnhancedCustomShapeParameterPair& aPolar)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Polar" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Polar" ));
dumpEnhancedCustomShapeParameterPair(aPolar);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRefXAsAttribute(sal_Int32 aRefX)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refX"), "%" SAL_PRIdINT32, aRefX);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refX"), "%" SAL_PRIdINT32, aRefX);
}
void EnhancedShapeDumper::dumpRefYAsAttribute(sal_Int32 aRefY)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refY"), "%" SAL_PRIdINT32, aRefY);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refY"), "%" SAL_PRIdINT32, aRefY);
}
void EnhancedShapeDumper::dumpRefAngleAsAttribute(sal_Int32 aRefAngle)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refAngle"), "%" SAL_PRIdINT32, aRefAngle);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refAngle"), "%" SAL_PRIdINT32, aRefAngle);
}
void EnhancedShapeDumper::dumpRefRAsAttribute(sal_Int32 aRefR)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refR"), "%" SAL_PRIdINT32, aRefR);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("refR"), "%" SAL_PRIdINT32, aRefR);
}
void EnhancedShapeDumper::dumpEnhancedCustomShapeParameter(
@@ -763,65 +756,65 @@ void EnhancedShapeDumper::dumpEnhancedCustomShapeParameter(
bool bValue;
if(aAny >>= sValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
OUStringToOString(sValue, RTL_TEXTENCODING_UTF8).getStr());
}
else if(aAny >>= nValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
}
else if(aAny >>= fValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
}
else if(aAny >>= bValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
}
sal_Int32 aType = aParameter.Type;
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%" SAL_PRIdINT32, aType);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%" SAL_PRIdINT32, aType);
}
void EnhancedShapeDumper::dumpRangeXMinimumAsElement(const drawing::EnhancedCustomShapeParameter& aRangeXMinimum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeXMinimum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeXMinimum" ));
dumpEnhancedCustomShapeParameter(aRangeXMinimum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRangeXMaximumAsElement(const drawing::EnhancedCustomShapeParameter& aRangeXMaximum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeXMaximum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeXMaximum" ));
dumpEnhancedCustomShapeParameter(aRangeXMaximum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRangeYMinimumAsElement(const drawing::EnhancedCustomShapeParameter& aRangeYMinimum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeYMinimum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeYMinimum" ));
dumpEnhancedCustomShapeParameter(aRangeYMinimum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRangeYMaximumAsElement(const drawing::EnhancedCustomShapeParameter& aRangeYMaximum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeYMaximum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RangeYMaximum" ));
dumpEnhancedCustomShapeParameter(aRangeYMaximum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRadiusRangeMinimumAsElement(const drawing::EnhancedCustomShapeParameter& aRadiusRangeMinimum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RadiusRangeMinimum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RadiusRangeMinimum" ));
dumpEnhancedCustomShapeParameter(aRadiusRangeMinimum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpRadiusRangeMaximumAsElement(const drawing::EnhancedCustomShapeParameter& aRadiusRangeMaximum)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RadiusRangeMaximum" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "RadiusRangeMaximum" ));
dumpEnhancedCustomShapeParameter(aRadiusRangeMaximum);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
@@ -831,73 +824,73 @@ void EnhancedShapeDumper::dumpRadiusRangeMaximumAsElement(const drawing::Enhance
void EnhancedShapeDumper::dumpEnhancedCustomShapePathService(const uno::Reference< beans::XPropertySet >& xPropSet)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Coordinates");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Coordinates"_ustr);
uno::Sequence< drawing::EnhancedCustomShapeParameterPair > aCoordinates;
if(anotherAny >>= aCoordinates)
dumpCoordinatesAsElement(aCoordinates);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Segments");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Segments"_ustr);
uno::Sequence< drawing::EnhancedCustomShapeSegment > aSegments;
if(anotherAny >>= aSegments)
dumpSegmentsAsElement(aSegments);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("StretchX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"StretchX"_ustr);
sal_Int32 aStretchX = sal_Int32();
if(anotherAny >>= aStretchX)
dumpStretchXAsAttribute(aStretchX);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("StretchY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"StretchY"_ustr);
sal_Int32 aStretchY = sal_Int32();
if(anotherAny >>= aStretchY)
dumpStretchYAsAttribute(aStretchY);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextFrames");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextFrames"_ustr);
uno::Sequence< drawing::EnhancedCustomShapeTextFrame > aTextFrames;
if(anotherAny >>= aTextFrames)
dumpTextFramesAsElement(aTextFrames);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("GluePoints");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"GluePoints"_ustr);
uno::Sequence< drawing::EnhancedCustomShapeParameterPair > aGluePoints;
if(anotherAny >>= aGluePoints)
dumpGluePointsAsElement(aGluePoints);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("GluePointLeavingDirections");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"GluePointLeavingDirections"_ustr);
uno::Sequence< double > aGluePointLeavingDirections;
if(anotherAny >>= aGluePointLeavingDirections)
dumpGluePointLeavingDirectionsAsElement(aGluePointLeavingDirections);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("GluePointType");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"GluePointType"_ustr);
sal_Int32 aGluePointType = sal_Int32();
if(anotherAny >>= aGluePointType)
dumpGluePointTypeAsAttribute(aGluePointType);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ExtrusionAllowed");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ExtrusionAllowed"_ustr);
bool bExtrusionAllowed;
if(anotherAny >>= bExtrusionAllowed)
dumpExtrusionAllowedAsAttribute(bExtrusionAllowed);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ConcentricGradientFillAllowed");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ConcentricGradientFillAllowed"_ustr);
bool bConcentricGradientFillAllowed;
if(anotherAny >>= bConcentricGradientFillAllowed)
dumpConcentricGradientFillAllowedAsAttribute(bConcentricGradientFillAllowed);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextPathAllowed");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextPathAllowed"_ustr);
bool bTextPathAllowed;
if(anotherAny >>= bTextPathAllowed)
dumpTextPathAllowedAsAttribute(bTextPathAllowed);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("SubViewSize");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"SubViewSize"_ustr);
uno::Sequence< awt::Size > aSubViewSize;
if(anotherAny >>= aSubViewSize)
dumpSubViewSizeAsElement(aSubViewSize);
@@ -906,129 +899,123 @@ void EnhancedShapeDumper::dumpEnhancedCustomShapePathService(const uno::Referenc
void EnhancedShapeDumper::dumpCoordinatesAsElement(const uno::Sequence< drawing::EnhancedCustomShapeParameterPair >& aCoordinates)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Coordinates" ));
- sal_Int32 nLength = aCoordinates.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Coordinates" ));
+ for (const auto& i : aCoordinates)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeParameterPair" ));
- dumpEnhancedCustomShapeParameterPair(aCoordinates[i]);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeParameterPair" ));
+ dumpEnhancedCustomShapeParameterPair(i);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpSegmentsAsElement(const uno::Sequence< drawing::EnhancedCustomShapeSegment >& aSegments)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Segments" ));
- sal_Int32 nLength = aSegments.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Segments" ));
+ for (const auto& i : aSegments)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeSegment" ));
- sal_Int32 aCommand = aSegments[i].Command;
- sal_Int32 aCount = aSegments[i].Count;
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("command"), "%" SAL_PRIdINT32, aCommand);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("count"), "%" SAL_PRIdINT32, aCount);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeSegment" ));
+ sal_Int32 aCommand = i.Command;
+ sal_Int32 aCount = i.Count;
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("command"), "%" SAL_PRIdINT32, aCommand);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("count"), "%" SAL_PRIdINT32, aCount);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpStretchXAsAttribute(sal_Int32 aStretchX)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stretchX"), "%" SAL_PRIdINT32, aStretchX);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stretchX"), "%" SAL_PRIdINT32, aStretchX);
}
void EnhancedShapeDumper::dumpStretchYAsAttribute(sal_Int32 aStretchY)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stretchY"), "%" SAL_PRIdINT32, aStretchY);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stretchY"), "%" SAL_PRIdINT32, aStretchY);
}
void EnhancedShapeDumper::dumpTextFramesAsElement(const uno::Sequence< drawing::EnhancedCustomShapeTextFrame >& aTextFrames)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TextFrames" ));
- sal_Int32 nLength = aTextFrames.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TextFrames" ));
+ for (const auto& i : aTextFrames)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeTextFrame" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeTextFrame" ));
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TopLeft" ));
- dumpEnhancedCustomShapeParameterPair(aTextFrames[i].TopLeft);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "TopLeft" ));
+ dumpEnhancedCustomShapeParameterPair(i.TopLeft);
+ (void)xmlTextWriterEndElement( xmlWriter );
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "BottomRight" ));
- dumpEnhancedCustomShapeParameterPair(aTextFrames[i].BottomRight);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "BottomRight" ));
+ dumpEnhancedCustomShapeParameterPair(i.BottomRight);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpGluePointsAsElement(const uno::Sequence< drawing::EnhancedCustomShapeParameterPair >& aGluePoints)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "GluePoints" ));
- sal_Int32 nLength = aGluePoints.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "GluePoints" ));
+ for (const auto& i : aGluePoints)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeParameterPair" ));
- dumpEnhancedCustomShapeParameterPair(aGluePoints[i]);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "EnhancedCustomShapeParameterPair" ));
+ dumpEnhancedCustomShapeParameterPair(i);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpGluePointLeavingDirectionsAsElement(const uno::Sequence< double >& aGluePointLeavingDirections)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "GluePointLeavingDirections" ));
- sal_Int32 nLength = aGluePointLeavingDirections.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "GluePointLeavingDirections" ));
+ for (const auto& i : aGluePointLeavingDirections)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("value"), "%f", aGluePointLeavingDirections[i]);
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("value"), "%f", i);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void EnhancedShapeDumper::dumpGluePointTypeAsAttribute(sal_Int32 aGluePointType)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("gluePointType"), "%" SAL_PRIdINT32, aGluePointType);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("gluePointType"), "%" SAL_PRIdINT32, aGluePointType);
}
void EnhancedShapeDumper::dumpExtrusionAllowedAsAttribute(bool bExtrusionAllowed)
{
if(bExtrusionAllowed)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionAllowed"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionAllowed"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionAllowed"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("extrusionAllowed"), "%s", "false");
}
void EnhancedShapeDumper::dumpConcentricGradientFillAllowedAsAttribute(bool bConcentricGradientFillAllowed)
{
if(bConcentricGradientFillAllowed)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("concentricGradientFillAllowed"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("concentricGradientFillAllowed"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("concentricGradientFillAllowed"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("concentricGradientFillAllowed"), "%s", "false");
}
void EnhancedShapeDumper::dumpTextPathAllowedAsAttribute(bool bTextPathAllowed)
{
if(bTextPathAllowed)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathAllowed"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathAllowed"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathAllowed"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathAllowed"), "%s", "false");
}
void EnhancedShapeDumper::dumpSubViewSizeAsElement(const uno::Sequence< awt::Size >& aSubViewSize)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "SubViewSize" ));
- sal_Int32 nLength = aSubViewSize.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "SubViewSize" ));
+ for (const auto& i : aSubViewSize)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Size" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, aSubViewSize[i].Width);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, aSubViewSize[i].Height);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Size" ));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, i.Width);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, i.Height);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
@@ -1038,19 +1025,19 @@ void EnhancedShapeDumper::dumpSubViewSizeAsElement(const uno::Sequence< awt::Siz
void EnhancedShapeDumper::dumpEnhancedCustomShapeTextPathService(const uno::Reference< beans::XPropertySet >& xPropSet)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextPath");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextPath"_ustr);
bool bTextPath;
if(anotherAny >>= bTextPath)
dumpTextPathAsAttribute(bTextPath);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextPathMode");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextPathMode"_ustr);
drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
if(anotherAny >>= eTextPathMode)
dumpTextPathModeAsAttribute(eTextPathMode);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ScaleX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ScaleX"_ustr);
bool bScaleX;
if(anotherAny >>= bScaleX)
dumpScaleXAsAttribute(bScaleX);
@@ -1060,9 +1047,9 @@ void EnhancedShapeDumper::dumpEnhancedCustomShapeTextPathService(const uno::Refe
void EnhancedShapeDumper::dumpTextPathAsAttribute(bool bTextPath)
{
if(bTextPath)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPath"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPath"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPath"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPath"), "%s", "false");
}
void EnhancedShapeDumper::dumpTextPathModeAsAttribute(drawing::EnhancedCustomShapeTextPathMode eTextPathMode)
@@ -1070,13 +1057,13 @@ void EnhancedShapeDumper::dumpTextPathModeAsAttribute(drawing::EnhancedCustomSha
switch(eTextPathMode)
{
case drawing::EnhancedCustomShapeTextPathMode_NORMAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "NORMAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "NORMAL");
break;
case drawing::EnhancedCustomShapeTextPathMode_PATH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "PATH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "PATH");
break;
case drawing::EnhancedCustomShapeTextPathMode_SHAPE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "SHAPE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textPathMode"), "%s", "SHAPE");
break;
default:
break;
@@ -1086,9 +1073,9 @@ void EnhancedShapeDumper::dumpTextPathModeAsAttribute(drawing::EnhancedCustomSha
void EnhancedShapeDumper::dumpScaleXAsAttribute(bool bScaleX)
{
if(bScaleX)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("scaleX"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("scaleX"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("scaleX"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("scaleX"), "%s", "false");
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/dumper/EnhancedShapeDumper.hxx b/drawinglayer/source/dumper/EnhancedShapeDumper.hxx
index 9de2ca3e9097..f6c8453e9087 100644
--- a/drawinglayer/source/dumper/EnhancedShapeDumper.hxx
+++ b/drawinglayer/source/dumper/EnhancedShapeDumper.hxx
@@ -6,8 +6,11 @@
* 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/.
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_DUMPER_ENHANCEDSHAPEDUMPER_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_DUMPER_ENHANCEDSHAPEDUMPER_HXX
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
#include <libxml/xmlwriter.h>
@@ -74,7 +77,7 @@ public:
// EnhancedCustomShapeGeometry.idl
void dumpEnhancedCustomShapeGeometryService(const css::uno::Reference< css::beans::XPropertySet >& xPropSet);
- void dumpTypeAsAttribute(const OUString& sType);
+ void dumpTypeAsAttribute(std::u16string_view sType);
void dumpViewBoxAsElement(css::awt::Rectangle aViewBox);
void dumpMirroredXAsAttribute(bool bMirroredX); // also used in EnhancedCustomShapeHandle
void dumpMirroredYAsAttribute(bool bMirroredY); // also used in EnhancedCustomShapeHandle
@@ -126,6 +129,5 @@ public:
private:
xmlTextWriterPtr xmlWriter;
};
-#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/dumper/XShapeDumper.cxx b/drawinglayer/source/dumper/XShapeDumper.cxx
index be72eeb2b8a9..5a9fef72a941 100644
--- a/drawinglayer/source/dumper/XShapeDumper.cxx
+++ b/drawinglayer/source/dumper/XShapeDumper.cxx
@@ -42,6 +42,7 @@
#include <rtl/strbuf.hxx>
#include <libxml/xmlwriter.h>
#include <iostream>
+#include <string_view>
#include <rtl/ustring.hxx>
#define DEBUG_DUMPER 0
@@ -62,9 +63,9 @@ void dumpPropertyValueAsElement(const beans::PropertyValue& rPropertyValue, xmlT
void dumpFillStyleAsAttribute(css::drawing::FillStyle eFillStyle, xmlTextWriterPtr xmlWriter);
void dumpFillColorAsAttribute(sal_Int32 aColor, xmlTextWriterPtr xmlWriter);
void dumpFillTransparenceAsAttribute(sal_Int32 aTransparence, xmlTextWriterPtr xmlWriter);
-void dumpFillTransparenceGradientNameAsAttribute(const OUString& sTranspGradName, xmlTextWriterPtr xmlWriter);
+void dumpFillTransparenceGradientNameAsAttribute(std::u16string_view sTranspGradName, xmlTextWriterPtr xmlWriter);
void dumpFillTransparenceGradientAsElement(const css::awt::Gradient& rTranspGrad, xmlTextWriterPtr xmlWriter);
-void dumpFillGradientNameAsAttribute(const OUString& sGradName, xmlTextWriterPtr xmlWriter);
+void dumpFillGradientNameAsAttribute(std::u16string_view sGradName, xmlTextWriterPtr xmlWriter);
void dumpFillGradientAsElement(const css::awt::Gradient& rGradient, xmlTextWriterPtr xmlWriter);
void dumpFillHatchAsElement(const css::drawing::Hatch& rHatch, xmlTextWriterPtr xmlWriter);
void dumpFillBackgroundAsAttribute(bool bBackground, xmlTextWriterPtr xmlWriter);
@@ -84,13 +85,13 @@ void dumpFillBitmapTileAsAttribute(bool bBitmapTile, xmlTextWriterPtr xmlWriter)
// LineProperties.idl
void dumpLineStyleAsAttribute(css::drawing::LineStyle eLineStyle, xmlTextWriterPtr xmlWriter);
void dumpLineDashAsElement(const css::drawing::LineDash& rLineDash, xmlTextWriterPtr xmlWriter);
-void dumpLineDashNameAsAttribute(const OUString& sLineDashName, xmlTextWriterPtr xmlWriter);
+void dumpLineDashNameAsAttribute(std::u16string_view sLineDashName, xmlTextWriterPtr xmlWriter);
void dumpLineColorAsAttribute(sal_Int32 aLineColor, xmlTextWriterPtr xmlWriter);
void dumpLineTransparenceAsAttribute(sal_Int32 aLineTransparence, xmlTextWriterPtr xmlWriter);
void dumpLineWidthAsAttribute(sal_Int32 aLineWidth, xmlTextWriterPtr xmlWriter);
void dumpLineJointAsAttribute(css::drawing::LineJoint eLineJoint, xmlTextWriterPtr xmlWriter);
-void dumpLineStartNameAsAttribute(const OUString& sLineStartName, xmlTextWriterPtr xmlWriter);
-void dumpLineEndNameAsAttribute(const OUString& sLineEndName, xmlTextWriterPtr xmlWriter);
+void dumpLineStartNameAsAttribute(std::u16string_view sLineStartName, xmlTextWriterPtr xmlWriter);
+void dumpLineEndNameAsAttribute(std::u16string_view sLineEndName, xmlTextWriterPtr xmlWriter);
void dumpLineStartAsElement(const css::drawing::PolyPolygonBezierCoords& rLineStart, xmlTextWriterPtr xmlWriter);
void dumpLineEndAsElement(const css::drawing::PolyPolygonBezierCoords& rLineEnd, xmlTextWriterPtr xmlWriter);
void dumpLineStartCenterAsAttribute(bool bLineStartCenter, xmlTextWriterPtr xmlWriter);
@@ -142,23 +143,24 @@ void dumpShadowYDistanceAsAttribute(sal_Int32 aShadowYDistance, xmlTextWriterPtr
//Shape.idl
void dumpZOrderAsAttribute(sal_Int32 aZOrder, xmlTextWriterPtr xmlWriter);
void dumpLayerIDAsAttribute(sal_Int32 aLayerID, xmlTextWriterPtr xmlWriter);
-void dumpLayerNameAsAttribute(const OUString& sLayerName, xmlTextWriterPtr xmlWriter);
+void dumpLayerNameAsAttribute(std::u16string_view sLayerName, xmlTextWriterPtr xmlWriter);
void dumpVisibleAsAttribute(bool bVisible, xmlTextWriterPtr xmlWriter);
void dumpPrintableAsAttribute(bool bPrintable, xmlTextWriterPtr xmlWriter);
void dumpMoveProtectAsAttribute(bool bMoveProtect, xmlTextWriterPtr xmlWriter);
-void dumpNameAsAttribute(const OUString& sName, xmlTextWriterPtr xmlWriter);
+void dumpNameAsAttribute(std::u16string_view sName, xmlTextWriterPtr xmlWriter);
void dumpSizeProtectAsAttribute(bool bSizeProtect, xmlTextWriterPtr xmlWriter);
void dumpHomogenMatrixLine3(const css::drawing::HomogenMatrixLine3& rLine, xmlTextWriterPtr xmlWriter);
void dumpTransformationAsElement(const css::drawing::HomogenMatrix3& rTransformation, xmlTextWriterPtr xmlWriter);
void dumpNavigationOrderAsAttribute(sal_Int32 aNavigationOrder, xmlTextWriterPtr xmlWriter);
-void dumpHyperlinkAsAttribute(const OUString& sHyperlink, xmlTextWriterPtr xmlWriter);
+void dumpHyperlinkAsAttribute(std::u16string_view sHyperlink, xmlTextWriterPtr xmlWriter);
void dumpInteropGrabBagAsElement(const uno::Sequence< beans::PropertyValue>& aInteropGrabBag, xmlTextWriterPtr xmlWriter);
// CustomShape.idl
-void dumpCustomShapeEngineAsAttribute(const OUString& sCustomShapeEngine, xmlTextWriterPtr xmlWriter);
-void dumpCustomShapeDataAsAttribute(const OUString& sCustomShapeData, xmlTextWriterPtr xmlWriter);
+void dumpCustomShapeEngineAsAttribute(std::u16string_view sCustomShapeEngine, xmlTextWriterPtr xmlWriter);
+void dumpCustomShapeDataAsAttribute(
+ std::u16string_view sCustomShapeData, xmlTextWriterPtr xmlWriter);
void dumpCustomShapeGeometryAsElement(const css::uno::Sequence< css::beans::PropertyValue>& aCustomShapeGeometry, xmlTextWriterPtr xmlWriter);
-void dumpCustomShapeReplacementURLAsAttribute(const OUString& sCustomShapeReplacementURL, xmlTextWriterPtr xmlWriter);
+void dumpCustomShapeReplacementURLAsAttribute(std::u16string_view sCustomShapeReplacementURL, xmlTextWriterPtr xmlWriter);
// XShape.idl
void dumpPositionAsAttribute(const css::awt::Point& rPoint, xmlTextWriterPtr xmlWriter);
@@ -200,19 +202,19 @@ void dumpFillStyleAsAttribute(drawing::FillStyle eFillStyle, xmlTextWriterPtr xm
switch(eFillStyle)
{
case drawing::FillStyle_NONE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "NONE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "NONE");
break;
case drawing::FillStyle_SOLID:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "SOLID");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "SOLID");
break;
case drawing::FillStyle_GRADIENT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "GRADIENT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "GRADIENT");
break;
case drawing::FillStyle_HATCH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "HATCH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "HATCH");
break;
case drawing::FillStyle_BITMAP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "BITMAP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillStyle"), "%s", "BITMAP");
break;
default:
break;
@@ -221,17 +223,17 @@ void dumpFillStyleAsAttribute(drawing::FillStyle eFillStyle, xmlTextWriterPtr xm
void dumpFillColorAsAttribute(sal_Int32 aColor, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillColor"), "%06x", static_cast<unsigned int>(aColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillColor"), "%06x", static_cast<unsigned int>(aColor));
}
void dumpFillTransparenceAsAttribute(sal_Int32 aTransparence, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillTransparence"), "%" SAL_PRIdINT32, aTransparence);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillTransparence"), "%" SAL_PRIdINT32, aTransparence);
}
-void dumpFillTransparenceGradientNameAsAttribute(const OUString& sTranspGradName, xmlTextWriterPtr xmlWriter)
+void dumpFillTransparenceGradientNameAsAttribute(std::u16string_view sTranspGradName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillTransparenceGradientName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillTransparenceGradientName"), "%s",
OUStringToOString(sTranspGradName, RTL_TEXTENCODING_UTF8).getStr());
}
@@ -241,118 +243,118 @@ void dumpGradientProperty(const awt::Gradient& rGradient, xmlTextWriterPtr xmlWr
switch (rGradient.Style) //enum GradientStyle
{
case awt::GradientStyle_LINEAR:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "LINEAR");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "LINEAR");
break;
case awt::GradientStyle_AXIAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "AXIAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "AXIAL");
break;
case awt::GradientStyle_RADIAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RADIAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RADIAL");
break;
case awt::GradientStyle_ELLIPTICAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ELLIPTICAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ELLIPTICAL");
break;
case awt::GradientStyle_SQUARE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "SQUARE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "SQUARE");
break;
case awt::GradientStyle_RECT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECT");
break;
default:
break;
}
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("startColor"), "%06x", static_cast<unsigned int>(rGradient.StartColor));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("endColor"), "%06x", static_cast<unsigned int>(rGradient.EndColor));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("angle"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.Angle));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("border"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.Border));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("xOffset"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.XOffset));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("yOffset"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.YOffset));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("startIntensity"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.StartIntensity));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("endIntensity"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.EndIntensity));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stepCount"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.StepCount));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("startColor"), "%06x", static_cast<unsigned int>(rGradient.StartColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("endColor"), "%06x", static_cast<unsigned int>(rGradient.EndColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("angle"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.Angle));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("border"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.Border));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("xOffset"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.XOffset));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("yOffset"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.YOffset));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("startIntensity"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.StartIntensity));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("endIntensity"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.EndIntensity));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("stepCount"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rGradient.StepCount));
}
void dumpFillTransparenceGradientAsElement(const awt::Gradient& rTranspGrad, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillTransparenceGradient" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillTransparenceGradient" ));
dumpGradientProperty(rTranspGrad, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
-void dumpFillGradientNameAsAttribute(const OUString& sGradName, xmlTextWriterPtr xmlWriter)
+void dumpFillGradientNameAsAttribute(std::u16string_view sGradName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillGradientName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillGradientName"), "%s",
OUStringToOString(sGradName, RTL_TEXTENCODING_UTF8).getStr());
}
void dumpFillGradientAsElement(const awt::Gradient& rGradient, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillGradient" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillGradient" ));
dumpGradientProperty(rGradient, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpFillHatchAsElement(const drawing::Hatch& rHatch, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillHatch" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillHatch" ));
switch (rHatch.Style)
{
case drawing::HatchStyle_SINGLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "SINGLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "SINGLE");
break;
case drawing::HatchStyle_DOUBLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "DOUBLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "DOUBLE");
break;
case drawing::HatchStyle_TRIPLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "TRIPLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "TRIPLE");
break;
default:
break;
}
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("color"), "%06x", static_cast<unsigned int>(rHatch.Color));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("distance"), "%" SAL_PRIdINT32, rHatch.Distance);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("angle"), "%" SAL_PRIdINT32, rHatch.Angle);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("color"), "%06x", static_cast<unsigned int>(rHatch.Color));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("distance"), "%" SAL_PRIdINT32, rHatch.Distance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("angle"), "%" SAL_PRIdINT32, rHatch.Angle);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpFillBackgroundAsAttribute(bool bBackground, xmlTextWriterPtr xmlWriter)
{
if(bBackground)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBackground"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBackground"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBackground"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBackground"), "%s", "false");
}
void dumpFillBitmapAsElement(const uno::Reference<awt::XBitmap>& xBitmap, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillBitmap" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "FillBitmap" ));
if (xBitmap.is())
{
awt::Size const aSize = xBitmap->getSize();
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, aSize.Width);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, aSize.Height);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("width"), "%" SAL_PRIdINT32, aSize.Width);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("height"), "%" SAL_PRIdINT32, aSize.Height);
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpFillBitmapPositionOffsetXAsAttribute(sal_Int32 aBitmapPositionOffsetX, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapPositionOffsetX"), "%" SAL_PRIdINT32, aBitmapPositionOffsetX);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapPositionOffsetX"), "%" SAL_PRIdINT32, aBitmapPositionOffsetX);
}
void dumpFillBitmapPositionOffsetYAsAttribute(sal_Int32 aBitmapPositionOffsetY, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapPositionOffsetY"), "%" SAL_PRIdINT32, aBitmapPositionOffsetY);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapPositionOffsetY"), "%" SAL_PRIdINT32, aBitmapPositionOffsetY);
}
void dumpFillBitmapOffsetXAsAttribute(sal_Int32 aBitmapOffsetX, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapOffsetX"), "%" SAL_PRIdINT32, aBitmapOffsetX);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapOffsetX"), "%" SAL_PRIdINT32, aBitmapOffsetX);
}
void dumpFillBitmapOffsetYAsAttribute(sal_Int32 aBitmapOffsetY, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapOffsetY"), "%" SAL_PRIdINT32, aBitmapOffsetY);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapOffsetY"), "%" SAL_PRIdINT32, aBitmapOffsetY);
}
void dumpFillBitmapRectanglePointAsAttribute(drawing::RectanglePoint eBitmapRectanglePoint, xmlTextWriterPtr xmlWriter)
@@ -360,31 +362,31 @@ void dumpFillBitmapRectanglePointAsAttribute(drawing::RectanglePoint eBitmapRect
switch(eBitmapRectanglePoint)
{
case drawing::RectanglePoint_LEFT_TOP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_TOP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_TOP");
break;
case drawing::RectanglePoint_MIDDLE_TOP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_TOP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_TOP");
break;
case drawing::RectanglePoint_RIGHT_TOP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_TOP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_TOP");
break;
case drawing::RectanglePoint_LEFT_MIDDLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_MIDDLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_MIDDLE");
break;
case drawing::RectanglePoint_MIDDLE_MIDDLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_MIDDLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_MIDDLE");
break;
case drawing::RectanglePoint_RIGHT_MIDDLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_MIDDLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_MIDDLE");
break;
case drawing::RectanglePoint_LEFT_BOTTOM:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_BOTTOM");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "LEFT_BOTTOM");
break;
case drawing::RectanglePoint_MIDDLE_BOTTOM:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_BOTTOM");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "MIDDLE_BOTTOM");
break;
case drawing::RectanglePoint_RIGHT_BOTTOM:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_BOTTOM");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapRectanglePoint"), "%s", "RIGHT_BOTTOM");
break;
default:
break;
@@ -394,19 +396,19 @@ void dumpFillBitmapRectanglePointAsAttribute(drawing::RectanglePoint eBitmapRect
void dumpFillBitmapLogicalSizeAsAttribute(bool bBitmapLogicalSize, xmlTextWriterPtr xmlWriter)
{
if(bBitmapLogicalSize)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapLogicalSize"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapLogicalSize"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapLogicalSize"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapLogicalSize"), "%s", "false");
}
void dumpFillBitmapSizeXAsAttribute(sal_Int32 aBitmapSizeX, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapSizeX"), "%" SAL_PRIdINT32, aBitmapSizeX);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapSizeX"), "%" SAL_PRIdINT32, aBitmapSizeX);
}
void dumpFillBitmapSizeYAsAttribute(sal_Int32 aBitmapSizeY, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapSizeY"), "%" SAL_PRIdINT32, aBitmapSizeY);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fillBitmapSizeY"), "%" SAL_PRIdINT32, aBitmapSizeY);
}
void dumpFillBitmapModeAsAttribute(drawing::BitmapMode eBitmapMode, xmlTextWriterPtr xmlWriter)
@@ -414,13 +416,13 @@ void dumpFillBitmapModeAsAttribute(drawing::BitmapMode eBitmapMode, xmlTextWrite
switch(eBitmapMode)
{
case drawing::BitmapMode_REPEAT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "REPEAT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "REPEAT");
break;
case drawing::BitmapMode_STRETCH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "STRETCH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "STRETCH");
break;
case drawing::BitmapMode_NO_REPEAT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "NO_REPEAT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapMode"), "%s", "NO_REPEAT");
break;
default:
break;
@@ -430,17 +432,17 @@ void dumpFillBitmapModeAsAttribute(drawing::BitmapMode eBitmapMode, xmlTextWrite
void dumpFillBitmapStretchAsAttribute(bool bBitmapStretch, xmlTextWriterPtr xmlWriter)
{
if(bBitmapStretch)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapStretch"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapStretch"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapStretch"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapStretch"), "%s", "false");
}
void dumpFillBitmapTileAsAttribute(bool bBitmapTile, xmlTextWriterPtr xmlWriter)
{
if(bBitmapTile)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapTile"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapTile"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapTile"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fillBitmapTile"), "%s", "false");
}
@@ -452,13 +454,13 @@ void dumpLineStyleAsAttribute(drawing::LineStyle eLineStyle, xmlTextWriterPtr xm
switch(eLineStyle)
{
case drawing::LineStyle_NONE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "NONE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "NONE");
break;
case drawing::LineStyle_SOLID:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "SOLID");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "SOLID");
break;
case drawing::LineStyle_DASH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "DASH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStyle"), "%s", "DASH");
break;
default:
break;
@@ -467,51 +469,51 @@ void dumpLineStyleAsAttribute(drawing::LineStyle eLineStyle, xmlTextWriterPtr xm
void dumpLineDashAsElement(const drawing::LineDash& rLineDash, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineDash" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineDash" ));
switch (rLineDash.Style)
{
case drawing::DashStyle_RECT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECT");
break;
case drawing::DashStyle_ROUND:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ROUND");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ROUND");
break;
case drawing::DashStyle_RECTRELATIVE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECTRELATIVE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "RECTRELATIVE");
break;
case drawing::DashStyle_ROUNDRELATIVE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ROUNDRELATIVE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("style"), "%s", "ROUNDRELATIVE");
break;
default:
break;
}
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dots"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rLineDash.Dots));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dotLen"), "%" SAL_PRIdINT32, rLineDash.DotLen);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dashes"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rLineDash.Dashes));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dashLen"), "%" SAL_PRIdINT32, rLineDash.DashLen);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("distance"), "%" SAL_PRIdINT32, rLineDash.Distance);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dots"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rLineDash.Dots));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dotLen"), "%" SAL_PRIdINT32, rLineDash.DotLen);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dashes"), "%" SAL_PRIdINT32, static_cast<sal_Int32>(rLineDash.Dashes));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("dashLen"), "%" SAL_PRIdINT32, rLineDash.DashLen);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("distance"), "%" SAL_PRIdINT32, rLineDash.Distance);
+ (void)xmlTextWriterEndElement( xmlWriter );
}
-void dumpLineDashNameAsAttribute(const OUString& sLineDashName, xmlTextWriterPtr xmlWriter)
+void dumpLineDashNameAsAttribute(std::u16string_view sLineDashName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineDashName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineDashName"), "%s",
OUStringToOString(sLineDashName, RTL_TEXTENCODING_UTF8).getStr());
}
void dumpLineColorAsAttribute(sal_Int32 aLineColor, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineColor"), "%06x", static_cast<unsigned int>(aLineColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineColor"), "%06x", static_cast<unsigned int>(aLineColor));
}
void dumpLineTransparenceAsAttribute(sal_Int32 aLineTransparence, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineTransparence"), "%" SAL_PRIdINT32, aLineTransparence);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineTransparence"), "%" SAL_PRIdINT32, aLineTransparence);
}
void dumpLineWidthAsAttribute(sal_Int32 aLineWidth, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineWidth"), "%" SAL_PRIdINT32, aLineWidth);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineWidth"), "%" SAL_PRIdINT32, aLineWidth);
}
void dumpLineJointAsAttribute(drawing::LineJoint eLineJoint, xmlTextWriterPtr xmlWriter)
@@ -519,34 +521,34 @@ void dumpLineJointAsAttribute(drawing::LineJoint eLineJoint, xmlTextWriterPtr xm
switch(eLineJoint)
{
case drawing::LineJoint_NONE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "NONE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "NONE");
break;
case drawing::LineJoint_MIDDLE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "MIDDLE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "MIDDLE");
break;
case drawing::LineJoint_BEVEL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "BEVEL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "BEVEL");
break;
case drawing::LineJoint_MITER:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "MITER");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "MITER");
break;
case drawing::LineJoint_ROUND:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "ROUND");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineJoint"), "%s", "ROUND");
break;
default:
break;
}
}
-void dumpLineStartNameAsAttribute(const OUString& sLineStartName, xmlTextWriterPtr xmlWriter)
+void dumpLineStartNameAsAttribute(std::u16string_view sLineStartName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineStartName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineStartName"), "%s",
OUStringToOString(sLineStartName, RTL_TEXTENCODING_UTF8).getStr());
}
-void dumpLineEndNameAsAttribute(const OUString& sLineEndName, xmlTextWriterPtr xmlWriter)
+void dumpLineEndNameAsAttribute(std::u16string_view sLineEndName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineEndName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineEndName"), "%s",
OUStringToOString(sLineEndName, RTL_TEXTENCODING_UTF8).getStr());
}
@@ -557,42 +559,42 @@ void dumpPolyPolygonBezierCoords(const drawing::PolyPolygonBezierCoords& rPolyPo
void dumpLineStartAsElement(const drawing::PolyPolygonBezierCoords& rLineStart, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineStart" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineStart" ));
dumpPolyPolygonBezierCoords(rLineStart, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpLineEndAsElement(const drawing::PolyPolygonBezierCoords& rLineEnd, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineEnd" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "LineEnd" ));
dumpPolyPolygonBezierCoords(rLineEnd, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpLineStartCenterAsAttribute(bool bLineStartCenter, xmlTextWriterPtr xmlWriter)
{
if(bLineStartCenter)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStartCenter"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStartCenter"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStartCenter"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineStartCenter"), "%s", "false");
}
void dumpLineStartWidthAsAttribute(sal_Int32 aLineStartWidth, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineStartWidth"), "%" SAL_PRIdINT32, aLineStartWidth);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineStartWidth"), "%" SAL_PRIdINT32, aLineStartWidth);
}
void dumpLineEndCenterAsAttribute(bool bLineEndCenter, xmlTextWriterPtr xmlWriter)
{
if(bLineEndCenter)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineEndCenter"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineEndCenter"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineEndCenter"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("lineEndCenter"), "%s", "false");
}
void dumpLineEndWidthAsAttribute(sal_Int32 aLineEndWidth, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineEndWidth"), "%" SAL_PRIdINT32, aLineEndWidth);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("lineEndWidth"), "%" SAL_PRIdINT32, aLineEndWidth);
}
@@ -604,31 +606,31 @@ void dumpPolygonKindAsAttribute(drawing::PolygonKind ePolygonKind, xmlTextWriter
switch(ePolygonKind)
{
case drawing::PolygonKind_LINE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "LINE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "LINE");
break;
case drawing::PolygonKind_POLY:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "POLY");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "POLY");
break;
case drawing::PolygonKind_PLIN:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PLIN");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PLIN");
break;
case drawing::PolygonKind_PATHLINE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHLINE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHLINE");
break;
case drawing::PolygonKind_PATHFILL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHFILL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHFILL");
break;
case drawing::PolygonKind_FREELINE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "FREELINE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "FREELINE");
break;
case drawing::PolygonKind_FREEFILL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "FREEFILL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "FREEFILL");
break;
case drawing::PolygonKind_PATHPOLY:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHPOLY");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHPOLY");
break;
case drawing::PolygonKind_PATHPLIN:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHPLIN");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonKind"), "%s", "PATHPLIN");
break;
default:
break;
@@ -638,76 +640,75 @@ void dumpPolygonKindAsAttribute(drawing::PolygonKind ePolygonKind, xmlTextWriter
void dumpPointSequenceSequence(const drawing::PointSequenceSequence& aPointSequenceSequence, const uno::Sequence<uno::Sequence< drawing::PolygonFlags > >* pFlags, xmlTextWriterPtr xmlWriter)
{
// LibreOffice proudly presents - The Sequenception
- uno::Sequence<uno::Sequence< awt::Point > > pointSequenceSequence = aPointSequenceSequence;
- sal_Int32 nPointsSequence = pointSequenceSequence.getLength();
+ sal_Int32 nPointsSequence = aPointSequenceSequence.getLength();
for (sal_Int32 i = 0; i < nPointsSequence; ++i)
{
- uno::Sequence< awt::Point > pointSequence = pointSequenceSequence[i];
+ const uno::Sequence< awt::Point >& pointSequence = aPointSequenceSequence[i];
sal_Int32 nPoints = pointSequence.getLength();
uno::Sequence< drawing::PolygonFlags> flagsSequence;
if(pFlags)
flagsSequence = (*pFlags)[i];
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "pointSequence" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "pointSequence" ));
for(sal_Int32 j = 0; j < nPoints; ++j)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "point" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionX"), "%" SAL_PRIdINT32, pointSequence[j].X);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionY"), "%" SAL_PRIdINT32, pointSequence[j].Y);
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "point" ));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionX"), "%" SAL_PRIdINT32, pointSequence[j].X);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionY"), "%" SAL_PRIdINT32, pointSequence[j].Y);
if(pFlags)
{
switch(flagsSequence[j])
{
case drawing::PolygonFlags_NORMAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "NORMAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "NORMAL");
break;
case drawing::PolygonFlags_SMOOTH:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "SMOOTH");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "SMOOTH");
break;
case drawing::PolygonFlags_CONTROL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "CONTROL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "CONTROL");
break;
case drawing::PolygonFlags_SYMMETRIC:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "SYMMETRIC");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("polygonFlags"), "%s", "SYMMETRIC");
break;
default:
break;
}
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
}
void dumpPolyPolygonAsElement(const drawing::PointSequenceSequence& rPolyPolygon, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PolyPolygon" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PolyPolygon" ));
dumpPointSequenceSequence(rPolyPolygon, nullptr, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpGeometryAsElement(const drawing::PointSequenceSequence& aGeometry, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Geometry" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Geometry" ));
dumpPointSequenceSequence(aGeometry, nullptr, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
// CharacterProperties.idl
void dumpCharHeightAsAttribute(float fHeight, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fontHeight"), "%f", fHeight );
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("fontHeight"), "%f", fHeight );
}
void dumpCharColorAsAttribute(sal_Int32 aColor, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fontColor"), "%06x", static_cast<unsigned int>(aColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("fontColor"), "%06x", static_cast<unsigned int>(aColor));
}
@@ -717,33 +718,33 @@ void dumpCharColorAsAttribute(sal_Int32 aColor, xmlTextWriterPtr xmlWriter)
void dumpIsNumberingAsAttribute(bool bIsNumbering, xmlTextWriterPtr xmlWriter)
{
if(bIsNumbering)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("isNumbering"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("isNumbering"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("isNumbering"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("isNumbering"), "%s", "false");
}
void dumpTextAutoGrowHeightAsAttribute(bool bTextAutoGrowHeight, xmlTextWriterPtr xmlWriter)
{
if(bTextAutoGrowHeight)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowHeight"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowHeight"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowHeight"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowHeight"), "%s", "false");
}
void dumpTextAutoGrowWidthAsAttribute(bool bTextAutoGrowWidth, xmlTextWriterPtr xmlWriter)
{
if(bTextAutoGrowWidth)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowWidth"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowWidth"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowWidth"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAutoGrowWidth"), "%s", "false");
}
void dumpTextContourFrameAsAttribute(bool bTextContourFrame, xmlTextWriterPtr xmlWriter)
{
if(bTextContourFrame)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textContourFrame"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textContourFrame"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textContourFrame"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textContourFrame"), "%s", "false");
}
void dumpTextFitToSizeAsAttribute(drawing::TextFitToSizeType eTextFitToSize, xmlTextWriterPtr xmlWriter)
@@ -751,16 +752,16 @@ void dumpTextFitToSizeAsAttribute(drawing::TextFitToSizeType eTextFitToSize, xml
switch(eTextFitToSize)
{
case drawing::TextFitToSizeType_NONE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "NONE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "NONE");
break;
case drawing::TextFitToSizeType_PROPORTIONAL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "PROPORTIONAL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "PROPORTIONAL");
break;
case drawing::TextFitToSizeType_ALLLINES:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "ALLLINES");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "ALLLINES");
break;
case drawing::TextFitToSizeType_AUTOFIT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "AUTOFIT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textFitToSize"), "%s", "AUTOFIT");
break;
default:
break;
@@ -772,16 +773,16 @@ void dumpTextHorizontalAdjustAsAttribute(drawing::TextHorizontalAdjust eTextHori
switch(eTextHorizontalAdjust)
{
case drawing::TextHorizontalAdjust_LEFT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "LEFT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "LEFT");
break;
case drawing::TextHorizontalAdjust_CENTER:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "CENTER");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "CENTER");
break;
case drawing::TextHorizontalAdjust_RIGHT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "RIGHT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "RIGHT");
break;
case drawing::TextHorizontalAdjust_BLOCK:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "BLOCK");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textHorizontalAdjust"), "%s", "BLOCK");
break;
default:
break;
@@ -793,16 +794,16 @@ void dumpTextVerticalAdjustAsAttribute(drawing::TextVerticalAdjust eTextVertical
switch(eTextVerticalAdjust)
{
case drawing::TextVerticalAdjust_TOP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "TOP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "TOP");
break;
case drawing::TextVerticalAdjust_CENTER:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "CENTER");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "CENTER");
break;
case drawing::TextVerticalAdjust_BOTTOM:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "BOTTOM");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "BOTTOM");
break;
case drawing::TextVerticalAdjust_BLOCK:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "BLOCK");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textVerticalAdjust"), "%s", "BLOCK");
break;
default:
break;
@@ -811,57 +812,57 @@ void dumpTextVerticalAdjustAsAttribute(drawing::TextVerticalAdjust eTextVertical
void dumpTextLeftDistanceAsAttribute(sal_Int32 aTextLeftDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textLeftDistance"), "%" SAL_PRIdINT32, aTextLeftDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textLeftDistance"), "%" SAL_PRIdINT32, aTextLeftDistance);
}
void dumpTextRightDistanceAsAttribute(sal_Int32 aTextRightDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textRightDistance"), "%" SAL_PRIdINT32, aTextRightDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textRightDistance"), "%" SAL_PRIdINT32, aTextRightDistance);
}
void dumpTextUpperDistanceAsAttribute(sal_Int32 aTextUpperDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textUpperDistance"), "%" SAL_PRIdINT32, aTextUpperDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textUpperDistance"), "%" SAL_PRIdINT32, aTextUpperDistance);
}
void dumpTextLowerDistanceAsAttribute(sal_Int32 aTextLowerDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textLowerDistance"), "%" SAL_PRIdINT32, aTextLowerDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textLowerDistance"), "%" SAL_PRIdINT32, aTextLowerDistance);
}
void dumpTextMaximumFrameHeightAsAttribute(sal_Int32 aTextMaximumFrameHeight, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMaximumFrameHeight"), "%" SAL_PRIdINT32, aTextMaximumFrameHeight);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMaximumFrameHeight"), "%" SAL_PRIdINT32, aTextMaximumFrameHeight);
}
void dumpTextMaximumFrameWidthAsAttribute(sal_Int32 aTextMaximumFrameWidth, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMaximumFrameWidth"), "%" SAL_PRIdINT32, aTextMaximumFrameWidth);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMaximumFrameWidth"), "%" SAL_PRIdINT32, aTextMaximumFrameWidth);
}
void dumpTextMinimumFrameHeightAsAttribute(sal_Int32 aTextMinimumFrameHeight, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMinimumFrameHeight"), "%" SAL_PRIdINT32, aTextMinimumFrameHeight);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMinimumFrameHeight"), "%" SAL_PRIdINT32, aTextMinimumFrameHeight);
}
void dumpTextMinimumFrameWidthAsAttribute(sal_Int32 aTextMinimumFrameWidth, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMinimumFrameWidth"), "%" SAL_PRIdINT32, aTextMinimumFrameWidth);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textMinimumFrameWidth"), "%" SAL_PRIdINT32, aTextMinimumFrameWidth);
}
void dumpTextAnimationAmountAsAttribute(sal_Int32 aTextAnimationAmount, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationAmount"), "%" SAL_PRIdINT32, aTextAnimationAmount);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationAmount"), "%" SAL_PRIdINT32, aTextAnimationAmount);
}
void dumpTextAnimationCountAsAttribute(sal_Int32 aTextAnimationCount, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationCount"), "%" SAL_PRIdINT32, aTextAnimationCount);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationCount"), "%" SAL_PRIdINT32, aTextAnimationCount);
}
void dumpTextAnimationDelayAsAttribute(sal_Int32 aTextAnimationDelay, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationDelay"), "%" SAL_PRIdINT32, aTextAnimationDelay);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("textAnimationDelay"), "%" SAL_PRIdINT32, aTextAnimationDelay);
}
void dumpTextAnimationDirectionAsAttribute(drawing::TextAnimationDirection eTextAnimationDirection, xmlTextWriterPtr xmlWriter)
@@ -869,16 +870,16 @@ void dumpTextAnimationDirectionAsAttribute(drawing::TextAnimationDirection eText
switch(eTextAnimationDirection)
{
case drawing::TextAnimationDirection_LEFT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "LEFT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "LEFT");
break;
case drawing::TextAnimationDirection_RIGHT:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "RIGHT");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "RIGHT");
break;
case drawing::TextAnimationDirection_UP:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "UP");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "UP");
break;
case drawing::TextAnimationDirection_DOWN:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "DOWN");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationDirection"), "%s", "DOWN");
break;
default:
break;
@@ -890,19 +891,19 @@ void dumpTextAnimationKindAsAttribute(drawing::TextAnimationKind eTextAnimationK
switch(eTextAnimationKind)
{
case drawing::TextAnimationKind_NONE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "NONE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "NONE");
break;
case drawing::TextAnimationKind_BLINK:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "BLINK");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "BLINK");
break;
case drawing::TextAnimationKind_SCROLL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "SCROLL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "SCROLL");
break;
case drawing::TextAnimationKind_ALTERNATE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "ALTERNATE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "ALTERNATE");
break;
case drawing::TextAnimationKind_SLIDE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "SLIDE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationKind"), "%s", "SLIDE");
break;
default:
break;
@@ -912,17 +913,17 @@ void dumpTextAnimationKindAsAttribute(drawing::TextAnimationKind eTextAnimationK
void dumpTextAnimationStartInsideAsAttribute(bool bTextAnimationStartInside, xmlTextWriterPtr xmlWriter)
{
if(bTextAnimationStartInside)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStartInside"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStartInside"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStartInside"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStartInside"), "%s", "false");
}
void dumpTextAnimationStopInsideAsAttribute(bool bTextAnimationStopInside, xmlTextWriterPtr xmlWriter)
{
if(bTextAnimationStopInside)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStopInside"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStopInside"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStopInside"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textAnimationStopInside"), "%s", "false");
}
void dumpTextWritingModeAsAttribute(text::WritingMode eTextWritingMode, xmlTextWriterPtr xmlWriter)
@@ -930,13 +931,13 @@ void dumpTextWritingModeAsAttribute(text::WritingMode eTextWritingMode, xmlTextW
switch(eTextWritingMode)
{
case text::WritingMode_LR_TB:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "LR_TB");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "LR_TB");
break;
case text::WritingMode_RL_TB:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "RL_TB");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "RL_TB");
break;
case text::WritingMode_TB_RL:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "TB_RL");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("textWritingMode"), "%s", "TB_RL");
break;
default:
break;
@@ -950,29 +951,29 @@ void dumpTextWritingModeAsAttribute(text::WritingMode eTextWritingMode, xmlTextW
void dumpShadowAsAttribute(bool bShadow, xmlTextWriterPtr xmlWriter)
{
if(bShadow)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadow"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadow"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadow"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("shadow"), "%s", "false");
}
void dumpShadowColorAsAttribute(sal_Int32 aShadowColor, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowColor"), "%06x", static_cast<unsigned int>(aShadowColor));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowColor"), "%06x", static_cast<unsigned int>(aShadowColor));
}
void dumpShadowTransparenceAsAttribute(sal_Int32 aShadowTransparence, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowTransparence"), "%" SAL_PRIdINT32, aShadowTransparence);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowTransparence"), "%" SAL_PRIdINT32, aShadowTransparence);
}
void dumpShadowXDistanceAsAttribute(sal_Int32 aShadowXDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowXDistance"), "%" SAL_PRIdINT32, aShadowXDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowXDistance"), "%" SAL_PRIdINT32, aShadowXDistance);
}
void dumpShadowYDistanceAsAttribute(sal_Int32 aShadowYDistance, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowYDistance"), "%" SAL_PRIdINT32, aShadowYDistance);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("shadowYDistance"), "%" SAL_PRIdINT32, aShadowYDistance);
}
@@ -981,49 +982,49 @@ void dumpShadowYDistanceAsAttribute(sal_Int32 aShadowYDistance, xmlTextWriterPtr
void dumpZOrderAsAttribute(sal_Int32 aZOrder, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("zOrder"), "%" SAL_PRIdINT32, aZOrder);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("zOrder"), "%" SAL_PRIdINT32, aZOrder);
}
void dumpLayerIDAsAttribute(sal_Int32 aLayerID, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("layerID"), "%" SAL_PRIdINT32, aLayerID);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("layerID"), "%" SAL_PRIdINT32, aLayerID);
}
-void dumpLayerNameAsAttribute(const OUString& sLayerName, xmlTextWriterPtr xmlWriter)
+void dumpLayerNameAsAttribute(std::u16string_view sLayerName, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("layerName"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("layerName"), "%s",
OUStringToOString(sLayerName, RTL_TEXTENCODING_UTF8).getStr());
}
void dumpVisibleAsAttribute(bool bVisible, xmlTextWriterPtr xmlWriter)
{
if(bVisible)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("visible"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("visible"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("visible"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("visible"), "%s", "false");
}
void dumpPrintableAsAttribute(bool bPrintable, xmlTextWriterPtr xmlWriter)
{
if(bPrintable)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("printable"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("printable"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("printable"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("printable"), "%s", "false");
}
void dumpMoveProtectAsAttribute(bool bMoveProtect, xmlTextWriterPtr xmlWriter)
{
if(bMoveProtect)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("moveProtect"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("moveProtect"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("moveProtect"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("moveProtect"), "%s", "false");
}
-void dumpNameAsAttribute(const OUString& sName, xmlTextWriterPtr xmlWriter)
+void dumpNameAsAttribute(std::u16string_view sName, xmlTextWriterPtr xmlWriter)
{
- if(!sName.isEmpty() && !m_bNameDumped)
+ if(!sName.empty() && !m_bNameDumped)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s", OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s", OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
m_bNameDumped = true;
}
}
@@ -1031,55 +1032,54 @@ void dumpNameAsAttribute(const OUString& sName, xmlTextWriterPtr xmlWriter)
void dumpSizeProtectAsAttribute(bool bSizeProtect, xmlTextWriterPtr xmlWriter)
{
if(bSizeProtect)
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("sizeProtect"), "%s", "true");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("sizeProtect"), "%s", "true");
else
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("sizeProtect"), "%s", "false");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("sizeProtect"), "%s", "false");
}
void dumpHomogenMatrixLine3(const drawing::HomogenMatrixLine3& rHomogenMatrixLine3, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column1"), "%f", rHomogenMatrixLine3.Column1);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column2"), "%f", rHomogenMatrixLine3.Column2);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column3"), "%f", rHomogenMatrixLine3.Column3);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column1"), "%f", rHomogenMatrixLine3.Column1);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column2"), "%f", rHomogenMatrixLine3.Column2);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("column3"), "%f", rHomogenMatrixLine3.Column3);
}
void dumpTransformationAsElement(const drawing::HomogenMatrix3& rTransformation, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Transformation" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Transformation" ));
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line1" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line1" ));
dumpHomogenMatrixLine3(rTransformation.Line1, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line2" ));
+ (void)xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line2" ));
dumpHomogenMatrixLine3(rTransformation.Line2, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line3" ));
+ (void)xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "Line3" ));
dumpHomogenMatrixLine3(rTransformation.Line3, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpNavigationOrderAsAttribute(sal_Int32 aNavigationOrder, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("navigationOrder"), "%" SAL_PRIdINT32, aNavigationOrder);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("navigationOrder"), "%" SAL_PRIdINT32, aNavigationOrder);
}
-void dumpHyperlinkAsAttribute(const OUString& sHyperlink, xmlTextWriterPtr xmlWriter)
+void dumpHyperlinkAsAttribute(std::u16string_view sHyperlink, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("hyperlink"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("hyperlink"), "%s",
OUStringToOString(sHyperlink, RTL_TEXTENCODING_UTF8).getStr());
}
void dumpInteropGrabBagAsElement(const uno::Sequence< beans::PropertyValue>& aInteropGrabBag, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "InteropGrabBag" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "InteropGrabBag" ));
- sal_Int32 nLength = aInteropGrabBag.getLength();
- for (sal_Int32 i = 0; i < nLength; ++i)
- dumpPropertyValueAsElement(aInteropGrabBag[i], xmlWriter);
+ for (const auto& item: aInteropGrabBag)
+ dumpPropertyValueAsElement(item, xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
@@ -1088,19 +1088,19 @@ void dumpInteropGrabBagAsElement(const uno::Sequence< beans::PropertyValue>& aIn
void dumpPositionAsAttribute(const awt::Point& rPoint, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionX"), "%" SAL_PRIdINT32, rPoint.X);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionY"), "%" SAL_PRIdINT32, rPoint.Y);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionX"), "%" SAL_PRIdINT32, rPoint.X);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("positionY"), "%" SAL_PRIdINT32, rPoint.Y);
}
void dumpSizeAsAttribute(const awt::Size& rSize, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("sizeX"), "%" SAL_PRIdINT32, rSize.Width);
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("sizeY"), "%" SAL_PRIdINT32, rSize.Height);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("sizeX"), "%" SAL_PRIdINT32, rSize.Width);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("sizeY"), "%" SAL_PRIdINT32, rSize.Height);
}
void dumpShapeDescriptorAsAttribute( const uno::Reference< drawing::XShapeDescriptor >& xDescr, xmlTextWriterPtr xmlWriter )
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("type"), "%s",
OUStringToOString(xDescr->getShapeType(), RTL_TEXTENCODING_UTF8).getStr());
}
@@ -1108,81 +1108,77 @@ void dumpShapeDescriptorAsAttribute( const uno::Reference< drawing::XShapeDescri
// ---------- CustomShape.idl ----------
-void dumpCustomShapeEngineAsAttribute(const OUString& sCustomShapeEngine, xmlTextWriterPtr xmlWriter)
+void dumpCustomShapeEngineAsAttribute(std::u16string_view sCustomShapeEngine, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeEngine"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeEngine"), "%s",
OUStringToOString(sCustomShapeEngine, RTL_TEXTENCODING_UTF8).getStr());
}
-void dumpCustomShapeDataAsAttribute(const OUString& sCustomShapeData, xmlTextWriterPtr xmlWriter)
+void dumpCustomShapeDataAsAttribute(
+ std::u16string_view sCustomShapeData, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeData"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeData"), "%s",
OUStringToOString(sCustomShapeData, RTL_TEXTENCODING_UTF8).getStr());
}
void dumpPropertyValueAsElement(const beans::PropertyValue& rPropertyValue, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValue" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "PropertyValue" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("name"), "%s",
OUStringToOString(rPropertyValue.Name, RTL_TEXTENCODING_UTF8).getStr());
uno::Any aAny = rPropertyValue.Value;
- OUString sValue;
- float fValue;
- sal_Int32 nValue;
- bool bValue;
- awt::Rectangle aRectangleValue;
- uno::Sequence< drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
- uno::Sequence< drawing::EnhancedCustomShapeParameterPair > aCoordinates;
- uno::Sequence< drawing::EnhancedCustomShapeSegment > aSegments;
- uno::Sequence< beans::PropertyValue > aPropSeq;
- if(aAny >>= sValue)
- {
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
+ if(OUString sValue; aAny >>= sValue)
+ {
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s",
OUStringToOString(sValue, RTL_TEXTENCODING_UTF8).getStr());
}
- else if(aAny >>= nValue)
+ else if(sal_Int32 nValue; aAny >>= nValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%" SAL_PRIdINT32, nValue);
}
- else if(aAny >>= fValue)
+ else if(float fValue; aAny >>= fValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%f", fValue);
}
- else if(aAny >>= bValue)
+ else if(bool bValue; aAny >>= bValue)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("value"), "%s", (bValue? "true": "false"));
}
- else if(rPropertyValue.Name == "ViewBox" && (aAny >>= aRectangleValue))
+ else if(awt::Rectangle aRectangleValue;
+ rPropertyValue.Name == "ViewBox" && (aAny >>= aRectangleValue))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpViewBoxAsElement(aRectangleValue);
}
- else if(rPropertyValue.Name == "AdjustmentValues" && (aAny >>= aAdjustmentValues))
+ else if(uno::Sequence< drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
+ rPropertyValue.Name == "AdjustmentValues" && (aAny >>= aAdjustmentValues))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpAdjustmentValuesAsElement(aAdjustmentValues);
}
- else if(rPropertyValue.Name == "Coordinates" && (aAny >>= aCoordinates))
+ else if(uno::Sequence< drawing::EnhancedCustomShapeParameterPair > aCoordinates;
+ rPropertyValue.Name == "Coordinates" && (aAny >>= aCoordinates))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpCoordinatesAsElement(aCoordinates);
}
- else if(rPropertyValue.Name == "Segments" && (aAny >>= aSegments))
+ else if(uno::Sequence< drawing::EnhancedCustomShapeSegment > aSegments;
+ rPropertyValue.Name == "Segments" && (aAny >>= aSegments))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpSegmentsAsElement(aSegments);
}
- else if(aAny >>= aPropSeq)
+ else if(uno::Sequence< beans::PropertyValue > aPropSeq; aAny >>= aPropSeq)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( OUStringToOString(rPropertyValue.Name, RTL_TEXTENCODING_UTF8).getStr() ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( OUStringToOString(rPropertyValue.Name, RTL_TEXTENCODING_UTF8).getStr() ));
sal_Int32 i = 0, nCount = aPropSeq.getLength();
for ( ; i < nCount; i++ )
dumpPropertyValueAsElement(aPropSeq[ i ], xmlWriter);
- xmlTextWriterEndElement(xmlWriter);
+ (void)xmlTextWriterEndElement(xmlWriter);
}
// TODO: Add here dumping of XDocument for future OOX Smart-Art
@@ -1190,39 +1186,39 @@ void dumpPropertyValueAsElement(const beans::PropertyValue& rPropertyValue, xmlT
// TODO more, if necessary
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("handle"), "%" SAL_PRIdINT32, rPropertyValue.Handle);
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("handle"), "%" SAL_PRIdINT32, rPropertyValue.Handle);
switch(rPropertyValue.State)
{
case beans::PropertyState_DIRECT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DIRECT_VALUE");
break;
case beans::PropertyState_DEFAULT_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "DEFAULT_VALUE");
break;
case beans::PropertyState_AMBIGUOUS_VALUE:
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("propertyState"), "%s", "AMBIGUOUS_VALUE");
break;
default:
break;
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpCustomShapeGeometryAsElement(const uno::Sequence< beans::PropertyValue>& aCustomShapeGeometry, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "CustomShapeGeometry" ));
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "CustomShapeGeometry" ));
sal_Int32 nLength = aCustomShapeGeometry.getLength();
for (sal_Int32 i = 0; i < nLength; ++i)
dumpPropertyValueAsElement(aCustomShapeGeometry[i], xmlWriter);
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
-void dumpCustomShapeReplacementURLAsAttribute(const OUString& sCustomShapeReplacementURL, xmlTextWriterPtr xmlWriter)
+void dumpCustomShapeReplacementURLAsAttribute(std::u16string_view sCustomShapeReplacementURL, xmlTextWriterPtr xmlWriter)
{
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeReplacementURL"), "%s",
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST("customShapeReplacementURL"), "%s",
OUStringToOString(sCustomShapeReplacementURL, RTL_TEXTENCODING_UTF8).getStr());
}
@@ -1231,157 +1227,157 @@ void dumpCustomShapeReplacementURLAsAttribute(const OUString& sCustomShapeReplac
void dumpTextPropertiesService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
- if(xInfo->hasPropertyByName("CharHeight"))
+ if(xInfo->hasPropertyByName(u"CharHeight"_ustr))
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CharHeight");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CharHeight"_ustr);
float fHeight;
if(anotherAny >>= fHeight)
dumpCharHeightAsAttribute(fHeight, xmlWriter);
}
- if(xInfo->hasPropertyByName("CharColor"))
+ if(xInfo->hasPropertyByName(u"CharColor"_ustr))
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CharColor");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CharColor"_ustr);
sal_Int32 aColor = sal_Int32();
if(anotherAny >>= aColor)
dumpCharColorAsAttribute(aColor, xmlWriter);
}
// TODO - more properties from CharacterProperties.idl (similar to above)
- if(xInfo->hasPropertyByName("IsNumbering"))
+ if(xInfo->hasPropertyByName(u"IsNumbering"_ustr))
{
- uno::Any anotherAny = xPropSet->getPropertyValue("IsNumbering");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"IsNumbering"_ustr);
bool bIsNumbering;
if(anotherAny >>= bIsNumbering)
dumpIsNumberingAsAttribute(bIsNumbering, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAutoGrowHeight");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAutoGrowHeight"_ustr);
bool bTextAutoGrowHeight;
if(anotherAny >>= bTextAutoGrowHeight)
dumpTextAutoGrowHeightAsAttribute(bTextAutoGrowHeight, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAutoGrowWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAutoGrowWidth"_ustr);
bool bTextAutoGrowWidth;
if(anotherAny >>= bTextAutoGrowWidth)
dumpTextAutoGrowWidthAsAttribute(bTextAutoGrowWidth, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextContourFrame");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextContourFrame"_ustr);
bool bTextContourFrame;
if(anotherAny >>= bTextContourFrame)
dumpTextContourFrameAsAttribute(bTextContourFrame, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextFitToSize");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextFitToSize"_ustr);
drawing::TextFitToSizeType eTextFitToSize;
if(anotherAny >>= eTextFitToSize)
dumpTextFitToSizeAsAttribute(eTextFitToSize, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextHorizontalAdjust");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextHorizontalAdjust"_ustr);
drawing::TextHorizontalAdjust eTextHorizontalAdjust;
if(anotherAny >>= eTextHorizontalAdjust)
dumpTextHorizontalAdjustAsAttribute(eTextHorizontalAdjust, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextVerticalAdjust");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextVerticalAdjust"_ustr);
drawing::TextVerticalAdjust eTextVerticalAdjust;
if(anotherAny >>= eTextVerticalAdjust)
dumpTextVerticalAdjustAsAttribute(eTextVerticalAdjust, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextLeftDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextLeftDistance"_ustr);
sal_Int32 aTextLeftDistance = sal_Int32();
if(anotherAny >>= aTextLeftDistance)
dumpTextLeftDistanceAsAttribute(aTextLeftDistance, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextRightDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextRightDistance"_ustr);
sal_Int32 aTextRightDistance = sal_Int32();
if(anotherAny >>= aTextRightDistance)
dumpTextRightDistanceAsAttribute(aTextRightDistance, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextUpperDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextUpperDistance"_ustr);
sal_Int32 aTextUpperDistance = sal_Int32();
if(anotherAny >>= aTextUpperDistance)
dumpTextUpperDistanceAsAttribute(aTextUpperDistance, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextLowerDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextLowerDistance"_ustr);
sal_Int32 aTextLowerDistance = sal_Int32();
if(anotherAny >>= aTextLowerDistance)
dumpTextLowerDistanceAsAttribute(aTextLowerDistance, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextMaximumFrameHeight");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextMaximumFrameHeight"_ustr);
sal_Int32 aTextMaximumFrameHeight = sal_Int32();
if(anotherAny >>= aTextMaximumFrameHeight)
dumpTextMaximumFrameHeightAsAttribute(aTextMaximumFrameHeight, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextMaximumFrameWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextMaximumFrameWidth"_ustr);
sal_Int32 aTextMaximumFrameWidth = sal_Int32();
if(anotherAny >>= aTextMaximumFrameWidth)
dumpTextMaximumFrameWidthAsAttribute(aTextMaximumFrameWidth, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextMinimumFrameHeight");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextMinimumFrameHeight"_ustr);
sal_Int32 aTextMinimumFrameHeight = sal_Int32();
if(anotherAny >>= aTextMinimumFrameHeight)
dumpTextMinimumFrameHeightAsAttribute(aTextMinimumFrameHeight, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextMinimumFrameWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextMinimumFrameWidth"_ustr);
sal_Int32 aTextMinimumFrameWidth = sal_Int32();
if(anotherAny >>= aTextMinimumFrameWidth)
dumpTextMinimumFrameWidthAsAttribute(aTextMinimumFrameWidth, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationAmount");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationAmount"_ustr);
sal_Int32 aTextAnimationAmount = sal_Int32();
if(anotherAny >>= aTextAnimationAmount)
dumpTextAnimationAmountAsAttribute(aTextAnimationAmount, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationCount");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationCount"_ustr);
sal_Int32 aTextAnimationCount = sal_Int32();
if(anotherAny >>= aTextAnimationCount)
dumpTextAnimationCountAsAttribute(aTextAnimationCount, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationDelay");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationDelay"_ustr);
sal_Int32 aTextAnimationDelay = sal_Int32();
if(anotherAny >>= aTextAnimationDelay)
dumpTextAnimationDelayAsAttribute(aTextAnimationDelay, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationDirection");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationDirection"_ustr);
drawing::TextAnimationDirection eTextAnimationDirection;
if(anotherAny >>= eTextAnimationDirection)
dumpTextAnimationDirectionAsAttribute(eTextAnimationDirection, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationKind");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationKind"_ustr);
drawing::TextAnimationKind eTextAnimationKind;
if(anotherAny >>= eTextAnimationKind)
dumpTextAnimationKindAsAttribute(eTextAnimationKind, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationStartInside");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationStartInside"_ustr);
bool bTextAnimationStartInside;
if(anotherAny >>= bTextAnimationStartInside)
dumpTextAnimationStartInsideAsAttribute(bTextAnimationStartInside, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextAnimationStopInside");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextAnimationStopInside"_ustr);
bool bTextAnimationStopInside;
if(anotherAny >>= bTextAnimationStopInside)
dumpTextAnimationStopInsideAsAttribute(bTextAnimationStopInside, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("TextWritingMode");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"TextWritingMode"_ustr);
text::WritingMode eTextWritingMode;
if(anotherAny >>= eTextWritingMode)
dumpTextWritingModeAsAttribute(eTextWritingMode, xmlWriter);
@@ -1391,139 +1387,139 @@ void dumpTextPropertiesService(const uno::Reference< beans::XPropertySet >& xPro
void dumpFillPropertiesService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillStyle");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillStyle"_ustr);
drawing::FillStyle eFillStyle;
if(anotherAny >>= eFillStyle)
dumpFillStyleAsAttribute(eFillStyle, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillColor");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillColor"_ustr);
sal_Int32 aColor = sal_Int32();
if(anotherAny >>= aColor)
dumpFillColorAsAttribute(aColor, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillTransparence");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillTransparence"_ustr);
sal_Int32 aTransparence = sal_Int32();
if(anotherAny >>= aTransparence)
dumpFillTransparenceAsAttribute(aTransparence, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillTransparenceGradientName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillTransparenceGradientName"_ustr);
OUString sTranspGradName;
if(anotherAny >>= sTranspGradName)
dumpFillTransparenceGradientNameAsAttribute(sTranspGradName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillTransparenceGradient");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillTransparenceGradient"_ustr);
awt::Gradient aTranspGrad;
if(anotherAny >>= aTranspGrad)
dumpFillTransparenceGradientAsElement(aTranspGrad, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillGradientName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillGradientName"_ustr);
OUString sGradName;
if(anotherAny >>= sGradName)
dumpFillGradientNameAsAttribute(sGradName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillGradient");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillGradient"_ustr);
awt::Gradient aGradient;
if(anotherAny >>= aGradient)
dumpFillGradientAsElement(aGradient, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillHatchName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillHatchName"_ustr);
OUString sHatchName;
if(anotherAny >>= sHatchName)
dumpFillGradientNameAsAttribute(sHatchName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillHatch");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillHatch"_ustr);
drawing::Hatch aHatch;
if(anotherAny >>= aHatch)
dumpFillHatchAsElement(aHatch, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBackground");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBackground"_ustr);
bool bFillBackground;
if(anotherAny >>= bFillBackground)
dumpFillBackgroundAsAttribute(bFillBackground, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapName"_ustr);
OUString sBitmapName;
if(anotherAny >>= sBitmapName)
dumpFillGradientNameAsAttribute(sBitmapName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmap");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmap"_ustr);
uno::Reference<awt::XBitmap> xBitmap;
if(anotherAny >>= xBitmap)
dumpFillBitmapAsElement(xBitmap, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapPositionOffsetX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapPositionOffsetX"_ustr);
sal_Int32 aBitmapPositionOffsetX = sal_Int32();
if(anotherAny >>= aBitmapPositionOffsetX)
dumpFillBitmapPositionOffsetXAsAttribute(aBitmapPositionOffsetX, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapPositionOffsetY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapPositionOffsetY"_ustr);
sal_Int32 aBitmapPositionOffsetY = sal_Int32();
if(anotherAny >>= aBitmapPositionOffsetY)
dumpFillBitmapPositionOffsetYAsAttribute(aBitmapPositionOffsetY, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapOffsetX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapOffsetX"_ustr);
sal_Int32 aBitmapOffsetX = sal_Int32();
if(anotherAny >>= aBitmapOffsetX)
dumpFillBitmapOffsetXAsAttribute(aBitmapOffsetX, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapOffsetY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapOffsetY"_ustr);
sal_Int32 aBitmapOffsetY = sal_Int32();
if(anotherAny >>= aBitmapOffsetY)
dumpFillBitmapOffsetYAsAttribute(aBitmapOffsetY, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapRectanglePoint");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapRectanglePoint"_ustr);
drawing::RectanglePoint eBitmapRectanglePoint;
if(anotherAny >>= eBitmapRectanglePoint)
dumpFillBitmapRectanglePointAsAttribute(eBitmapRectanglePoint, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapLogicalSize");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapLogicalSize"_ustr);
bool bBitmapLogicalSize;
if(anotherAny >>= bBitmapLogicalSize)
dumpFillBitmapLogicalSizeAsAttribute(bBitmapLogicalSize, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapSizeX");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapSizeX"_ustr);
sal_Int32 aBitmapSizeX = sal_Int32();
if(anotherAny >>= aBitmapSizeX)
dumpFillBitmapSizeXAsAttribute(aBitmapSizeX, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapSizeY");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapSizeY"_ustr);
sal_Int32 aBitmapSizeY = sal_Int32();
if(anotherAny >>= aBitmapSizeY)
dumpFillBitmapSizeYAsAttribute(aBitmapSizeY, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapMode");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapMode"_ustr);
drawing::BitmapMode eBitmapMode;
if(anotherAny >>= eBitmapMode)
dumpFillBitmapModeAsAttribute(eBitmapMode, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapStretch");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapStretch"_ustr);
bool bBitmapStretch;
if(anotherAny >>= bBitmapStretch)
dumpFillBitmapStretchAsAttribute(bBitmapStretch, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("FillBitmapTile");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"FillBitmapTile"_ustr);
bool bBitmapTile;
if(anotherAny >>= bBitmapTile)
dumpFillBitmapTileAsAttribute(bBitmapTile, xmlWriter);
@@ -1533,91 +1529,91 @@ void dumpFillPropertiesService(const uno::Reference< beans::XPropertySet >& xPro
void dumpLinePropertiesService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineStyle");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineStyle"_ustr);
drawing::LineStyle eLineStyle;
if(anotherAny >>= eLineStyle)
dumpLineStyleAsAttribute(eLineStyle, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineDash");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineDash"_ustr);
drawing::LineDash aLineDash;
if(anotherAny >>= aLineDash)
dumpLineDashAsElement(aLineDash, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineDashName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineDashName"_ustr);
OUString sLineDashName;
if(anotherAny >>= sLineDashName)
dumpLineDashNameAsAttribute(sLineDashName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineColor");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineColor"_ustr);
sal_Int32 aLineColor = sal_Int32();
if(anotherAny >>= aLineColor)
dumpLineColorAsAttribute(aLineColor, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineTransparence");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineTransparence"_ustr);
sal_Int32 aLineTransparence = sal_Int32();
if(anotherAny >>= aLineTransparence)
dumpLineTransparenceAsAttribute(aLineTransparence, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineWidth"_ustr);
sal_Int32 aLineWidth = sal_Int32();
if(anotherAny >>= aLineWidth)
dumpLineWidthAsAttribute(aLineWidth, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineJoint");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineJoint"_ustr);
drawing::LineJoint eLineJoint;
if(anotherAny >>= eLineJoint)
dumpLineJointAsAttribute(eLineJoint, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineStartName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineStartName"_ustr);
OUString sLineStartName;
if(anotherAny >>= sLineStartName)
dumpLineStartNameAsAttribute(sLineStartName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineEndName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineEndName"_ustr);
OUString sLineEndName;
if(anotherAny >>= sLineEndName)
dumpLineEndNameAsAttribute(sLineEndName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineStart");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineStart"_ustr);
drawing::PolyPolygonBezierCoords aLineStart;
if(anotherAny >>= aLineStart)
dumpLineStartAsElement(aLineStart, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineEnd");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineEnd"_ustr);
drawing::PolyPolygonBezierCoords aLineEnd;
if(anotherAny >>= aLineEnd)
dumpLineEndAsElement(aLineEnd, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineStartCenter");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineStartCenter"_ustr);
bool bLineStartCenter;
if(anotherAny >>= bLineStartCenter)
dumpLineStartCenterAsAttribute(bLineStartCenter, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineStartWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineStartWidth"_ustr);
sal_Int32 aLineStartWidth = sal_Int32();
if(anotherAny >>= aLineStartWidth)
dumpLineStartWidthAsAttribute(aLineStartWidth, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineEndCenter");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineEndCenter"_ustr);
bool bLineEndCenter;
if(anotherAny >>= bLineEndCenter)
dumpLineEndCenterAsAttribute(bLineEndCenter, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LineEndWidth");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LineEndWidth"_ustr);
sal_Int32 aLineEndWidth = sal_Int32();
if(anotherAny >>= aLineEndWidth)
dumpLineEndWidthAsAttribute(aLineEndWidth, xmlWriter);
@@ -1627,31 +1623,31 @@ void dumpLinePropertiesService(const uno::Reference< beans::XPropertySet >& xPro
void dumpShadowPropertiesService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Shadow");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Shadow"_ustr);
bool bShadow;
if(anotherAny >>= bShadow)
dumpShadowAsAttribute(bShadow, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ShadowColor");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ShadowColor"_ustr);
sal_Int32 aShadowColor = sal_Int32();
if(anotherAny >>= aShadowColor)
dumpShadowColorAsAttribute(aShadowColor, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ShadowTransparence");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ShadowTransparence"_ustr);
sal_Int32 aShadowTransparence = sal_Int32();
if(anotherAny >>= aShadowTransparence)
dumpShadowTransparenceAsAttribute(aShadowTransparence, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ShadowXDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ShadowXDistance"_ustr);
sal_Int32 aShadowXDistance = sal_Int32();
if(anotherAny >>= aShadowXDistance)
dumpShadowXDistanceAsAttribute(aShadowXDistance, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ShadowYDistance");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ShadowYDistance"_ustr);
sal_Int32 aShadowYDistance = sal_Int32();
if(anotherAny >>= aShadowYDistance)
dumpShadowYDistanceAsAttribute(aShadowYDistance, xmlWriter);
@@ -1661,19 +1657,19 @@ void dumpShadowPropertiesService(const uno::Reference< beans::XPropertySet >& xP
void dumpPolyPolygonDescriptorService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("PolygonKind");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"PolygonKind"_ustr);
drawing::PolygonKind ePolygonKind;
if(anotherAny >>= ePolygonKind)
dumpPolygonKindAsAttribute(ePolygonKind, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("PolyPolygon");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"PolyPolygon"_ustr);
drawing::PointSequenceSequence aPolyPolygon;
if(anotherAny >>= aPolyPolygon)
dumpPolyPolygonAsElement(aPolyPolygon, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Geometry");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Geometry"_ustr);
drawing::PointSequenceSequence aGeometry;
if(anotherAny >>= aGeometry)
dumpGeometryAsElement(aGeometry, xmlWriter);
@@ -1684,75 +1680,75 @@ void dumpShapeService(const uno::Reference< beans::XPropertySet >& xPropSet, xml
{
uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
{
- uno::Any anotherAny = xPropSet->getPropertyValue("ZOrder");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"ZOrder"_ustr);
sal_Int32 aZOrder = sal_Int32();
if(anotherAny >>= aZOrder)
dumpZOrderAsAttribute(aZOrder, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LayerID");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LayerID"_ustr);
sal_Int32 aLayerID = sal_Int32();
if(anotherAny >>= aLayerID)
dumpLayerIDAsAttribute(aLayerID, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("LayerName");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"LayerName"_ustr);
OUString sLayerName;
if(anotherAny >>= sLayerName)
dumpLayerNameAsAttribute(sLayerName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Visible");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Visible"_ustr);
bool bVisible;
if(anotherAny >>= bVisible)
dumpVisibleAsAttribute(bVisible, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Printable");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Printable"_ustr);
bool bPrintable;
if(anotherAny >>= bPrintable)
dumpPrintableAsAttribute(bPrintable, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("MoveProtect");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"MoveProtect"_ustr);
bool bMoveProtect;
if(anotherAny >>= bMoveProtect)
dumpMoveProtectAsAttribute(bMoveProtect, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Name");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Name"_ustr);
OUString sName;
if(anotherAny >>= sName)
dumpNameAsAttribute(sName, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("SizeProtect");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"SizeProtect"_ustr);
bool bSizeProtect;
if(anotherAny >>= bSizeProtect)
dumpSizeProtectAsAttribute(bSizeProtect, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Transformation");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Transformation"_ustr);
drawing::HomogenMatrix3 aTransformation;
if(anotherAny >>= aTransformation)
dumpTransformationAsElement(aTransformation, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("NavigationOrder");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"NavigationOrder"_ustr);
sal_Int32 aNavigationOrder = sal_Int32();
if(anotherAny >>= aNavigationOrder)
dumpNavigationOrderAsAttribute(aNavigationOrder, xmlWriter);
}
- if(xInfo->hasPropertyByName("Hyperlink"))
+ if(xInfo->hasPropertyByName(u"Hyperlink"_ustr))
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Hyperlink");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Hyperlink"_ustr);
OUString sHyperlink;
if(anotherAny >>= sHyperlink)
dumpHyperlinkAsAttribute(sHyperlink, xmlWriter);
}
- if(xInfo->hasPropertyByName("InteropGrabBag") && bDumpInteropProperties)
+ if(xInfo->hasPropertyByName(u"InteropGrabBag"_ustr) && bDumpInteropProperties)
{
- uno::Any anotherAny = xPropSet->getPropertyValue("InteropGrabBag");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"InteropGrabBag"_ustr);
uno::Sequence< beans::PropertyValue> aInteropGrabBag;
if(anotherAny >>= aInteropGrabBag)
dumpInteropGrabBagAsElement(aInteropGrabBag, xmlWriter);
@@ -1762,19 +1758,19 @@ void dumpShapeService(const uno::Reference< beans::XPropertySet >& xPropSet, xml
void dumpPolyPolygonBezierDescriptorService(const uno::Reference< beans::XPropertySet >& xPropSet, xmlTextWriterPtr xmlWriter)
{
{
- uno::Any anotherAny = xPropSet->getPropertyValue("PolygonKind");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"PolygonKind"_ustr);
drawing::PolygonKind ePolygonKind;
if(anotherAny >>= ePolygonKind)
dumpPolygonKindAsAttribute(ePolygonKind, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("PolyPolygonBezier");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"PolyPolygonBezier"_ustr);
drawing::PolyPolygonBezierCoords aPolyPolygonBezier;
if(anotherAny >>= aPolyPolygonBezier)
dumpPolyPolygonBezierCoords(aPolyPolygonBezier, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("Geometry");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"Geometry"_ustr);
drawing::PolyPolygonBezierCoords aGeometry;
if(anotherAny >>= aGeometry)
dumpPolyPolygonBezierCoords(aGeometry, xmlWriter);
@@ -1785,26 +1781,26 @@ void dumpCustomShapeService(const uno::Reference< beans::XPropertySet >& xPropSe
{
uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CustomShapeEngine");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CustomShapeEngine"_ustr);
OUString sCustomShapeEngine;
if(anotherAny >>= sCustomShapeEngine)
dumpCustomShapeEngineAsAttribute(sCustomShapeEngine, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CustomShapeData");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CustomShapeData"_ustr);
OUString sCustomShapeData;
if(anotherAny >>= sCustomShapeData)
dumpCustomShapeDataAsAttribute(sCustomShapeData, xmlWriter);
}
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CustomShapeGeometry");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CustomShapeGeometry"_ustr);
uno::Sequence< beans::PropertyValue> aCustomShapeGeometry;
if(anotherAny >>= aCustomShapeGeometry)
dumpCustomShapeGeometryAsElement(aCustomShapeGeometry, xmlWriter);
}
- if(xInfo->hasPropertyByName("CustomShapeReplacementURL"))
+ if(xInfo->hasPropertyByName(u"CustomShapeReplacementURL"_ustr))
{
- uno::Any anotherAny = xPropSet->getPropertyValue("CustomShapeReplacementURL");
+ uno::Any anotherAny = xPropSet->getPropertyValue(u"CustomShapeReplacementURL"_ustr);
OUString sCustomShapeReplacementURL;
if(anotherAny >>= sCustomShapeReplacementURL)
dumpCustomShapeReplacementURLAsAttribute(sCustomShapeReplacementURL, xmlWriter);
@@ -1813,7 +1809,7 @@ void dumpCustomShapeService(const uno::Reference< beans::XPropertySet >& xPropSe
void dumpXShape(const uno::Reference< drawing::XShape >& xShape, xmlTextWriterPtr xmlWriter, bool bDumpInteropProperties)
{
- xmlTextWriterStartElement( xmlWriter, BAD_CAST( "XShape" ) );
+ (void)xmlTextWriterStartElement( xmlWriter, BAD_CAST( "XShape" ) );
uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY_THROW);
OUString aName;
m_bNameDumped = false;
@@ -1828,77 +1824,77 @@ void dumpXShape(const uno::Reference< drawing::XShape >& xShape, xmlTextWriterPt
uno::Reference< lang::XServiceInfo > xServiceInfo( xShape, uno::UNO_QUERY_THROW );
uno::Reference< beans::XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
- if(xInfo->hasPropertyByName("Name"))
+ if(xInfo->hasPropertyByName(u"Name"_ustr))
{
- uno::Any aAny = xPropSet->getPropertyValue("Name");
+ uno::Any aAny = xPropSet->getPropertyValue(u"Name"_ustr);
if ((aAny >>= aName) && !aName.isEmpty())
{
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("name"), "%s", OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("name"), "%s", OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
m_bNameDumped = true;
}
}
try
{
- if (xServiceInfo->supportsService("com.sun.star.drawing.Text"))
+ if (xServiceInfo->supportsService(u"com.sun.star.drawing.Text"_ustr))
{
uno::Reference< text::XText > xText(xShape, uno::UNO_QUERY_THROW);
OUString aText = xText->getString();
if(!aText.isEmpty())
- xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("text"), "%s", OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
+ (void)xmlTextWriterWriteFormatAttribute( xmlWriter, BAD_CAST("text"), "%s", OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.TextProperties"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.TextProperties"_ustr))
dumpTextPropertiesService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.GroupShape"_ustr))
{
uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY_THROW);
dumpXShapes(xShapes, xmlWriter, bDumpInteropProperties);
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.FillProperties"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.FillProperties"_ustr))
dumpFillPropertiesService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.LineProperties"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.LineProperties"_ustr))
dumpLinePropertiesService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonDescriptor"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.PolyPolygonDescriptor"_ustr))
dumpPolyPolygonDescriptorService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.ShadowProperties"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.ShadowProperties"_ustr))
dumpShadowPropertiesService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.Shape"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.Shape"_ustr))
dumpShapeService(xPropSet, xmlWriter, bDumpInteropProperties);
- if(xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonBezierDescriptor"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.PolyPolygonBezierDescriptor"_ustr))
dumpPolyPolygonBezierDescriptorService(xPropSet, xmlWriter);
- if(xServiceInfo->supportsService("com.sun.star.drawing.CustomShape"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.CustomShape"_ustr))
dumpCustomShapeService(xPropSet, xmlWriter);
// EnhancedShapeDumper used
- if(xServiceInfo->supportsService("com.sun.star.drawing.EnhancedCustomShapeExtrusion"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.EnhancedCustomShapeExtrusion"_ustr))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpEnhancedCustomShapeExtrusionService(xPropSet);
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.EnhancedCustomShapeGeometry"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.EnhancedCustomShapeGeometry"_ustr))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpEnhancedCustomShapeGeometryService(xPropSet);
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.EnhancedCustomShapeHandle"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.EnhancedCustomShapeHandle"_ustr))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpEnhancedCustomShapeHandleService(xPropSet);
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.EnhancedCustomShapePath"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.EnhancedCustomShapePath"_ustr))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpEnhancedCustomShapePathService(xPropSet);
}
- if(xServiceInfo->supportsService("com.sun.star.drawing.EnhancedCustomShapeTextPath"))
+ if(xServiceInfo->supportsService(u"com.sun.star.drawing.EnhancedCustomShapeTextPath"_ustr))
{
EnhancedShapeDumper enhancedDumper(xmlWriter);
enhancedDumper.dumpEnhancedCustomShapeTextPathService(xPropSet);
@@ -1914,18 +1910,18 @@ void dumpXShape(const uno::Reference< drawing::XShape >& xShape, xmlTextWriterPt
sal_Int32 nServices = aServiceNames.getLength();
for (sal_Int32 i = 0; i < nServices; ++i)
{
- xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ServiceName" ));
- xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST( "name" ), "%s", OUStringToOString(aServiceNames[i], RTL_TEXTENCODING_UTF8).getStr());
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterStartElement(xmlWriter, BAD_CAST( "ServiceName" ));
+ (void)xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST( "name" ), "%s", OUStringToOString(aServiceNames[i], RTL_TEXTENCODING_UTF8).getStr());
+ (void)xmlTextWriterEndElement( xmlWriter );
}
#endif
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
void dumpXShapes( const uno::Reference< drawing::XShapes >& xShapes, xmlTextWriterPtr xmlWriter, bool bDumpInteropProperties )
{
- xmlTextWriterStartElement( xmlWriter, BAD_CAST( "XShapes" ) );
+ (void)xmlTextWriterStartElement( xmlWriter, BAD_CAST( "XShapes" ) );
uno::Reference< container::XIndexAccess > xIA( xShapes, uno::UNO_QUERY_THROW);
sal_Int32 nLength = xIA->getCount();
for (sal_Int32 i = 0; i < nLength; ++i)
@@ -1934,7 +1930,7 @@ void dumpXShapes( const uno::Reference< drawing::XShapes >& xShapes, xmlTextWrit
dumpXShape( xShape, xmlWriter, bDumpInteropProperties );
}
- xmlTextWriterEndElement( xmlWriter );
+ (void)xmlTextWriterEndElement( xmlWriter );
}
} //end of namespace
@@ -1945,7 +1941,7 @@ OUString XShapeDumper::dump(const uno::Reference<drawing::XShapes>& xPageShapes,
xmlTextWriterPtr xmlWriter = xmlNewTextWriter( xmlOutBuffer );
xmlTextWriterSetIndent( xmlWriter, 1 );
- xmlTextWriterStartDocument( xmlWriter, nullptr, nullptr, nullptr );
+ (void)xmlTextWriterStartDocument( xmlWriter, nullptr, nullptr, nullptr );
try
{
@@ -1956,10 +1952,10 @@ OUString XShapeDumper::dump(const uno::Reference<drawing::XShapes>& xPageShapes,
std::cout << "Exception caught in XShapeDumper: " << e.Message << std::endl;
}
- xmlTextWriterEndDocument( xmlWriter );
+ (void)xmlTextWriterEndDocument( xmlWriter );
xmlFreeTextWriter( xmlWriter );
- return OUString::fromUtf8(aString.makeStringAndClear());
+ return OUString::fromUtf8(aString);
}
OUString XShapeDumper::dump(const uno::Reference<drawing::XShape>& xPageShapes, bool bDumpInteropProperties)
@@ -1969,7 +1965,7 @@ OUString XShapeDumper::dump(const uno::Reference<drawing::XShape>& xPageShapes,
xmlTextWriterPtr xmlWriter = xmlNewTextWriter( xmlOutBuffer );
xmlTextWriterSetIndent( xmlWriter, 1 );
- xmlTextWriterStartDocument( xmlWriter, nullptr, nullptr, nullptr );
+ (void)xmlTextWriterStartDocument( xmlWriter, nullptr, nullptr, nullptr );
try
{
@@ -1980,10 +1976,10 @@ OUString XShapeDumper::dump(const uno::Reference<drawing::XShape>& xPageShapes,
std::cout << "Exception caught in XShapeDumper: " << e.Message << std::endl;
}
- xmlTextWriterEndDocument( xmlWriter );
+ (void)xmlTextWriterEndDocument( xmlWriter );
xmlFreeTextWriter( xmlWriter );
- return OUString::fromUtf8(aString.makeStringAndClear());
+ return OUString::fromUtf8(aString);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx
index 08a88b23d564..d3e6bd0371a3 100644
--- a/drawinglayer/source/geometry/viewinformation2d.cxx
+++ b/drawinglayer/source/geometry/viewinformation2d.cxx
@@ -25,8 +25,13 @@
#include <com/sun/star/drawing/XDrawPage.hpp>
#include <com/sun/star/geometry/AffineMatrix2D.hpp>
#include <com/sun/star/geometry/RealRectangle2D.hpp>
-#include <rtl/instance.hxx>
-#include <com/sun/star/uno/Sequence.hxx>
+#include <o3tl/temporary.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/rendercontext/DrawModeFlags.hxx>
+
+#include <atomic>
+#include <utility>
using namespace com::sun::star;
@@ -34,12 +39,14 @@ namespace drawinglayer::geometry
{
namespace
{
-constexpr OUStringLiteral g_PropertyName_ObjectTransformation = "ObjectTransformation";
-constexpr OUStringLiteral g_PropertyName_ViewTransformation = "ViewTransformation";
-constexpr OUStringLiteral g_PropertyName_Viewport = "Viewport";
-constexpr OUStringLiteral g_PropertyName_Time = "Time";
-constexpr OUStringLiteral g_PropertyName_VisualizedPage = "VisualizedPage";
-constexpr OUStringLiteral g_PropertyName_ReducedDisplayQuality = "ReducedDisplayQuality";
+constexpr OUStringLiteral g_PropertyName_ObjectTransformation = u"ObjectTransformation";
+constexpr OUStringLiteral g_PropertyName_ViewTransformation = u"ViewTransformation";
+constexpr OUStringLiteral g_PropertyName_Viewport = u"Viewport";
+constexpr OUStringLiteral g_PropertyName_Time = u"Time";
+constexpr OUStringLiteral g_PropertyName_VisualizedPage = u"VisualizedPage";
+constexpr OUStringLiteral g_PropertyName_ReducedDisplayQuality = u"ReducedDisplayQuality";
+constexpr OUStringLiteral g_PropertyName_UseAntiAliasing = u"UseAntiAliasing";
+constexpr OUStringLiteral g_PropertyName_PixelSnapHairline = u"PixelSnapHairline";
}
class ImpViewInformation2D
@@ -75,185 +82,32 @@ protected:
// the point in time
double mfViewTime;
- bool mbReducedDisplayQuality : 1;
-
- // the complete PropertyValue representation (if already created)
- uno::Sequence<beans::PropertyValue> mxViewInformation;
-
- // the extra PropertyValues; not represented by ViewTransformation,
- // Viewport, VisualizedPage or ViewTime
- uno::Sequence<beans::PropertyValue> mxExtendedInformation;
-
- void impInterpretPropertyValues(const uno::Sequence<beans::PropertyValue>& rViewParameters)
- {
- if (!rViewParameters.hasElements())
- return;
-
- const sal_Int32 nCount(rViewParameters.getLength());
- sal_Int32 nExtendedInsert(0);
-
- // prepare extended information for filtering. Maximum size is nCount
- mxExtendedInformation.realloc(nCount);
-
- for (sal_Int32 a(0); a < nCount; a++)
- {
- const beans::PropertyValue& rProp = rViewParameters[a];
-
- if (rProp.Name == g_PropertyName_ReducedDisplayQuality)
- {
- // extra information; add to filtered information
- mxExtendedInformation[nExtendedInsert++] = rProp;
-
- // for performance reasons, also cache content locally
- bool bSalBool(false);
- rProp.Value >>= bSalBool;
- mbReducedDisplayQuality = bSalBool;
- }
- else if (rProp.Name == g_PropertyName_ObjectTransformation)
- {
- css::geometry::AffineMatrix2D aAffineMatrix2D;
- rProp.Value >>= aAffineMatrix2D;
- basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation,
- aAffineMatrix2D);
- }
- else if (rProp.Name == g_PropertyName_ViewTransformation)
- {
- css::geometry::AffineMatrix2D aAffineMatrix2D;
- rProp.Value >>= aAffineMatrix2D;
- basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D);
- }
- else if (rProp.Name == g_PropertyName_Viewport)
- {
- css::geometry::RealRectangle2D aViewport;
- rProp.Value >>= aViewport;
- maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport);
- }
- else if (rProp.Name == g_PropertyName_Time)
- {
- rProp.Value >>= mfViewTime;
- }
- else if (rProp.Name == g_PropertyName_VisualizedPage)
- {
- rProp.Value >>= mxVisualizedPage;
- }
- else
- {
- // extra information; add to filtered information
- mxExtendedInformation[nExtendedInsert++] = rProp;
- }
- }
+ // color to use for automatic color
+ Color maAutoColor;
- // extra information size is now known; realloc to final size
- mxExtendedInformation.realloc(nExtendedInsert);
- }
+ // DrawModeFlags to use, these may ask to modify the
+ // colors/Bitmap paint according to the flags
+ DrawModeFlags maDrawModeFlags;
- void impFillViewInformationFromContent()
- {
- const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
- const bool bViewTransformationUsed(!maViewTransformation.isIdentity());
- const bool bViewportUsed(!maViewport.isEmpty());
- const bool bTimeUsed(0.0 < mfViewTime);
- const bool bVisualizedPageUsed(mxVisualizedPage.is());
- const bool bReducedDisplayQualityUsed(mbReducedDisplayQuality);
- const bool bExtraInformation(mxExtendedInformation.hasElements());
- sal_uInt32 nIndex(0);
- const sal_uInt32 nCount((bObjectTransformationUsed ? 1 : 0)
- + (bViewTransformationUsed ? 1 : 0) + (bViewportUsed ? 1 : 0)
- + (bTimeUsed ? 1 : 0) + (bVisualizedPageUsed ? 1 : 0)
- + (bReducedDisplayQualityUsed ? 1 : 0)
- + (bExtraInformation ? mxExtendedInformation.getLength() : 0));
-
- mxViewInformation.realloc(nCount);
-
- if (bObjectTransformationUsed)
- {
- css::geometry::AffineMatrix2D aAffineMatrix2D;
- basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maObjectTransformation);
- mxViewInformation[nIndex].Name = g_PropertyName_ObjectTransformation;
- mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
- nIndex++;
- }
+ // a hint that the View that is being painted has an active TextEdit. This
+ // is important for handling of TextHierarchyEditPrimitive2D to suppress
+ // the text for objects in TextEdit - the text is visualized by the
+ // active EditEngine/Outliner overlay, so it would be double visualized
+ bool mbTextEditActive : 1;
- if (bViewTransformationUsed)
- {
- css::geometry::AffineMatrix2D aAffineMatrix2D;
- basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maViewTransformation);
- mxViewInformation[nIndex].Name = g_PropertyName_ViewTransformation;
- mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
- nIndex++;
- }
+ // processed view is an EditView
+ bool mbEditViewActive : 1;
- if (bViewportUsed)
- {
- const css::geometry::RealRectangle2D aViewport(
- basegfx::unotools::rectangle2DFromB2DRectangle(maViewport));
- mxViewInformation[nIndex].Name = g_PropertyName_Viewport;
- mxViewInformation[nIndex].Value <<= aViewport;
- nIndex++;
- }
-
- if (bTimeUsed)
- {
- mxViewInformation[nIndex].Name = g_PropertyName_Time;
- mxViewInformation[nIndex].Value <<= mfViewTime;
- nIndex++;
- }
+ // allow to reduce DisplayQuality (e.g. sw 3d fallback renderer for interactions)
+ bool mbReducedDisplayQuality : 1;
- if (bVisualizedPageUsed)
- {
- mxViewInformation[nIndex].Name = g_PropertyName_VisualizedPage;
- mxViewInformation[nIndex].Value <<= mxVisualizedPage;
- nIndex++;
- }
+ // determine if to use AntiAliasing on target pixel device
+ bool mbUseAntiAliasing : 1;
- if (bExtraInformation)
- {
- const sal_Int32 nExtra(mxExtendedInformation.getLength());
-
- for (sal_Int32 a(0); a < nExtra; a++)
- {
- mxViewInformation[nIndex++] = mxExtendedInformation[a];
- }
- }
- }
+ // determine if to use PixelSnapHairline on target pixel device
+ bool mbPixelSnapHairline : 1;
public:
- ImpViewInformation2D(const basegfx::B2DHomMatrix& rObjectTransformation,
- const basegfx::B2DHomMatrix& rViewTransformation,
- const basegfx::B2DRange& rViewport,
- const uno::Reference<drawing::XDrawPage>& rxDrawPage, double fViewTime,
- const uno::Sequence<beans::PropertyValue>& rExtendedParameters)
- : maObjectTransformation(rObjectTransformation)
- , maViewTransformation(rViewTransformation)
- , maObjectToViewTransformation()
- , maInverseObjectToViewTransformation()
- , maViewport(rViewport)
- , maDiscreteViewport()
- , mxVisualizedPage(rxDrawPage)
- , mfViewTime(fViewTime)
- , mbReducedDisplayQuality(false)
- , mxViewInformation()
- , mxExtendedInformation()
- {
- impInterpretPropertyValues(rExtendedParameters);
- }
-
- explicit ImpViewInformation2D(const uno::Sequence<beans::PropertyValue>& rViewParameters)
- : maObjectTransformation()
- , maViewTransformation()
- , maObjectToViewTransformation()
- , maInverseObjectToViewTransformation()
- , maViewport()
- , maDiscreteViewport()
- , mxVisualizedPage()
- , mfViewTime()
- , mbReducedDisplayQuality(false)
- , mxViewInformation(rViewParameters)
- , mxExtendedInformation()
- {
- impInterpretPropertyValues(rViewParameters);
- }
-
ImpViewInformation2D()
: maObjectTransformation()
, maViewTransformation()
@@ -262,18 +116,45 @@ public:
, maViewport()
, maDiscreteViewport()
, mxVisualizedPage()
- , mfViewTime()
+ , mfViewTime(0.0)
+ , maAutoColor(COL_AUTO)
+ , maDrawModeFlags(DrawModeFlags::Default)
+ , mbTextEditActive(false)
+ , mbEditViewActive(false)
, mbReducedDisplayQuality(false)
- , mxViewInformation()
- , mxExtendedInformation()
+ , mbUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing())
{
+ if (comphelper::IsFuzzing())
+ mbPixelSnapHairline = false;
+ else
+ mbPixelSnapHairline
+ = mbUseAntiAliasing
+ && officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get();
}
const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
+ void setObjectTransformation(const basegfx::B2DHomMatrix& rNew)
+ {
+ maObjectTransformation = rNew;
+ maObjectToViewTransformation.identity();
+ maInverseObjectToViewTransformation.identity();
+ }
const basegfx::B2DHomMatrix& getViewTransformation() const { return maViewTransformation; }
+ void setViewTransformation(const basegfx::B2DHomMatrix& rNew)
+ {
+ maViewTransformation = rNew;
+ maDiscreteViewport.reset();
+ maObjectToViewTransformation.identity();
+ maInverseObjectToViewTransformation.identity();
+ }
const basegfx::B2DRange& getViewport() const { return maViewport; }
+ void setViewport(const basegfx::B2DRange& rNew)
+ {
+ maViewport = rNew;
+ maDiscreteViewport.reset();
+ }
const basegfx::B2DRange& getDiscreteViewport() const
{
@@ -315,64 +196,74 @@ public:
}
double getViewTime() const { return mfViewTime; }
-
- const uno::Reference<drawing::XDrawPage>& getVisualizedPage() const { return mxVisualizedPage; }
-
- bool getReducedDisplayQuality() const { return mbReducedDisplayQuality; }
-
- const uno::Sequence<beans::PropertyValue>& getViewInformationSequence() const
+ void setViewTime(double fNew)
{
- if (!mxViewInformation.hasElements())
+ if (fNew >= 0.0)
{
- const_cast<ImpViewInformation2D*>(this)->impFillViewInformationFromContent();
+ mfViewTime = fNew;
}
-
- return mxViewInformation;
}
- const uno::Sequence<beans::PropertyValue>& getExtendedInformationSequence() const
+ const uno::Reference<drawing::XDrawPage>& getVisualizedPage() const { return mxVisualizedPage; }
+ void setVisualizedPage(const uno::Reference<drawing::XDrawPage>& rNew)
{
- return mxExtendedInformation;
+ mxVisualizedPage = rNew;
}
+ Color getAutoColor() const { return maAutoColor; }
+ void setAutoColor(Color aNew) { maAutoColor = aNew; }
+
+ DrawModeFlags getDrawModeFlags() const { return maDrawModeFlags; }
+ void setDrawModeFlags(DrawModeFlags aNew) { maDrawModeFlags = aNew; }
+
+ bool getTextEditActive() const { return mbTextEditActive; }
+ void setTextEditActive(bool bNew) { mbTextEditActive = bNew; }
+
+ bool getEditViewActive() const { return mbEditViewActive; }
+ void setEditViewActive(bool bNew) { mbEditViewActive = bNew; }
+
+ bool getReducedDisplayQuality() const { return mbReducedDisplayQuality; }
+ void setReducedDisplayQuality(bool bNew) { mbReducedDisplayQuality = bNew; }
+
+ bool getUseAntiAliasing() const { return mbUseAntiAliasing; }
+ void setUseAntiAliasing(bool bNew) { mbUseAntiAliasing = bNew; }
+
+ bool getPixelSnapHairline() const { return mbPixelSnapHairline; }
+ void setPixelSnapHairline(bool bNew) { mbPixelSnapHairline = bNew; }
+
bool operator==(const ImpViewInformation2D& rCandidate) const
{
return (maObjectTransformation == rCandidate.maObjectTransformation
&& maViewTransformation == rCandidate.maViewTransformation
&& maViewport == rCandidate.maViewport
&& mxVisualizedPage == rCandidate.mxVisualizedPage
- && mfViewTime == rCandidate.mfViewTime
- && mxExtendedInformation == rCandidate.mxExtendedInformation);
+ && mfViewTime == rCandidate.mfViewTime && maAutoColor == rCandidate.maAutoColor
+ && maDrawModeFlags == rCandidate.maDrawModeFlags
+ && mbTextEditActive == rCandidate.mbTextEditActive
+ && mbEditViewActive == rCandidate.mbEditViewActive
+ && mbReducedDisplayQuality == rCandidate.mbReducedDisplayQuality
+ && mbUseAntiAliasing == rCandidate.mbUseAntiAliasing
+ && mbPixelSnapHairline == rCandidate.mbPixelSnapHairline);
}
};
namespace
{
-struct theGlobalDefault : public rtl::Static<ViewInformation2D::ImplType, theGlobalDefault>
+ViewInformation2D::ImplType& theGlobalDefault()
{
-};
+ static ViewInformation2D::ImplType SINGLETON;
+ return SINGLETON;
}
-
-ViewInformation2D::ViewInformation2D(const basegfx::B2DHomMatrix& rObjectTransformation,
- const basegfx::B2DHomMatrix& rViewTransformation,
- const basegfx::B2DRange& rViewport,
- const uno::Reference<drawing::XDrawPage>& rxDrawPage,
- double fViewTime,
- const uno::Sequence<beans::PropertyValue>& rExtendedParameters)
- : mpViewInformation2D(ImpViewInformation2D(rObjectTransformation, rViewTransformation,
- rViewport, rxDrawPage, fViewTime,
- rExtendedParameters))
-{
-}
-
-ViewInformation2D::ViewInformation2D(const uno::Sequence<beans::PropertyValue>& rViewParameters)
- : mpViewInformation2D(ImpViewInformation2D(rViewParameters))
-{
}
ViewInformation2D::ViewInformation2D()
- : mpViewInformation2D(theGlobalDefault::get())
+ : mpViewInformation2D(theGlobalDefault())
{
+ setUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing());
+ if (!comphelper::IsFuzzing())
+ setPixelSnapHairline(
+ getUseAntiAliasing()
+ && officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get());
}
ViewInformation2D::ViewInformation2D(const ViewInformation2D&) = default;
@@ -395,23 +286,53 @@ const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
return mpViewInformation2D->getObjectTransformation();
}
+void ViewInformation2D::setObjectTransformation(const basegfx::B2DHomMatrix& rNew)
+{
+ if (std::as_const(mpViewInformation2D)->getObjectTransformation() != rNew)
+ mpViewInformation2D->setObjectTransformation(rNew);
+}
+
const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
{
return mpViewInformation2D->getViewTransformation();
}
+void ViewInformation2D::setViewTransformation(const basegfx::B2DHomMatrix& rNew)
+{
+ if (std::as_const(mpViewInformation2D)->getViewTransformation() != rNew)
+ mpViewInformation2D->setViewTransformation(rNew);
+}
+
const basegfx::B2DRange& ViewInformation2D::getViewport() const
{
return mpViewInformation2D->getViewport();
}
+void ViewInformation2D::setViewport(const basegfx::B2DRange& rNew)
+{
+ if (rNew != std::as_const(mpViewInformation2D)->getViewport())
+ mpViewInformation2D->setViewport(rNew);
+}
+
double ViewInformation2D::getViewTime() const { return mpViewInformation2D->getViewTime(); }
+void ViewInformation2D::setViewTime(double fNew)
+{
+ if (fNew != std::as_const(mpViewInformation2D)->getViewTime())
+ mpViewInformation2D->setViewTime(fNew);
+}
+
const uno::Reference<drawing::XDrawPage>& ViewInformation2D::getVisualizedPage() const
{
return mpViewInformation2D->getVisualizedPage();
}
+void ViewInformation2D::setVisualizedPage(const uno::Reference<drawing::XDrawPage>& rNew)
+{
+ if (rNew != std::as_const(mpViewInformation2D)->getVisualizedPage())
+ mpViewInformation2D->setVisualizedPage(rNew);
+}
+
const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const
{
return mpViewInformation2D->getObjectToViewTransformation();
@@ -432,14 +353,160 @@ bool ViewInformation2D::getReducedDisplayQuality() const
return mpViewInformation2D->getReducedDisplayQuality();
}
-const uno::Sequence<beans::PropertyValue>& ViewInformation2D::getViewInformationSequence() const
+void ViewInformation2D::setReducedDisplayQuality(bool bNew)
+{
+ if (bNew != std::as_const(mpViewInformation2D)->getReducedDisplayQuality())
+ mpViewInformation2D->setReducedDisplayQuality(bNew);
+}
+
+bool ViewInformation2D::getUseAntiAliasing() const
{
- return mpViewInformation2D->getViewInformationSequence();
+ return mpViewInformation2D->getUseAntiAliasing();
}
-const uno::Sequence<beans::PropertyValue>& ViewInformation2D::getExtendedInformationSequence() const
+void ViewInformation2D::setUseAntiAliasing(bool bNew)
{
- return mpViewInformation2D->getExtendedInformationSequence();
+ if (bNew != std::as_const(mpViewInformation2D)->getUseAntiAliasing())
+ mpViewInformation2D->setUseAntiAliasing(bNew);
+}
+
+Color ViewInformation2D::getAutoColor() const { return mpViewInformation2D->getAutoColor(); }
+
+void ViewInformation2D::setAutoColor(Color aNew) { mpViewInformation2D->setAutoColor(aNew); }
+
+DrawModeFlags ViewInformation2D::getDrawModeFlags() const
+{
+ return mpViewInformation2D->getDrawModeFlags();
+}
+
+void ViewInformation2D::setDrawModeFlags(DrawModeFlags aNew)
+{
+ mpViewInformation2D->setDrawModeFlags(aNew);
+}
+
+bool ViewInformation2D::getTextEditActive() const
+{
+ return mpViewInformation2D->getTextEditActive();
+}
+
+void ViewInformation2D::setTextEditActive(bool bNew)
+{
+ mpViewInformation2D->setTextEditActive(bNew);
+}
+
+bool ViewInformation2D::getEditViewActive() const
+{
+ return mpViewInformation2D->getEditViewActive();
+}
+
+void ViewInformation2D::setEditViewActive(bool bNew)
+{
+ mpViewInformation2D->setEditViewActive(bNew);
+}
+
+bool ViewInformation2D::getPixelSnapHairline() const
+{
+ return mpViewInformation2D->getPixelSnapHairline();
+}
+
+void ViewInformation2D::setPixelSnapHairline(bool bNew)
+{
+ if (bNew != std::as_const(mpViewInformation2D)->getPixelSnapHairline())
+ mpViewInformation2D->setPixelSnapHairline(bNew);
+}
+
+static std::atomic<bool>& globalAntiAliasing()
+{
+ static std::atomic<bool> g_GlobalAntiAliasing
+ = comphelper::IsFuzzing() || officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
+ return g_GlobalAntiAliasing;
+}
+
+/**
+ * Some code like to turn this stuff on and off during a drawing operation
+ * so it can "tunnel" information down through several layers,
+ * so we don't want to actually do a config write all the time.
+ */
+void ViewInformation2D::setGlobalAntiAliasing(bool bAntiAliasing, bool bTemporary)
+{
+ if (globalAntiAliasing().compare_exchange_strong(o3tl::temporary(!bAntiAliasing), bAntiAliasing)
+ && !bTemporary)
+ {
+ auto batch = comphelper::ConfigurationChanges::create();
+ officecfg::Office::Common::Drawinglayer::AntiAliasing::set(bAntiAliasing, batch);
+ batch->commit();
+ }
+}
+bool ViewInformation2D::getGlobalAntiAliasing() { return globalAntiAliasing(); }
+
+ViewInformation2D
+createViewInformation2D(const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters)
+{
+ if (!rViewParameters.hasElements())
+ return ViewInformation2D();
+
+ ViewInformation2D aRetval;
+
+ for (auto const& rPropertyValue : rViewParameters)
+ {
+ if (rPropertyValue.Name == g_PropertyName_ReducedDisplayQuality)
+ {
+ bool bNew(false);
+ rPropertyValue.Value >>= bNew;
+ aRetval.setReducedDisplayQuality(bNew);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_PixelSnapHairline)
+ {
+ bool bNew(
+ true); //SvtOptionsDrawinglayer::IsAntiAliasing() && SvtOptionsDrawinglayer::IsSnapHorVerLinesToDiscrete());
+ rPropertyValue.Value >>= bNew;
+ aRetval.setPixelSnapHairline(bNew);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_UseAntiAliasing)
+ {
+ bool bNew(true); //SvtOptionsDrawinglayer::IsAntiAliasing());
+ rPropertyValue.Value >>= bNew;
+ aRetval.setUseAntiAliasing(bNew);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_ObjectTransformation)
+ {
+ css::geometry::AffineMatrix2D aAffineMatrix2D;
+ rPropertyValue.Value >>= aAffineMatrix2D;
+ basegfx::B2DHomMatrix aTransformation;
+ basegfx::unotools::homMatrixFromAffineMatrix(aTransformation, aAffineMatrix2D);
+ aRetval.setObjectTransformation(aTransformation);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_ViewTransformation)
+ {
+ css::geometry::AffineMatrix2D aAffineMatrix2D;
+ rPropertyValue.Value >>= aAffineMatrix2D;
+ basegfx::B2DHomMatrix aTransformation;
+ basegfx::unotools::homMatrixFromAffineMatrix(aTransformation, aAffineMatrix2D);
+ aRetval.setViewTransformation(aTransformation);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_Viewport)
+ {
+ css::geometry::RealRectangle2D aUnoViewport;
+ rPropertyValue.Value >>= aUnoViewport;
+ const basegfx::B2DRange aViewport(
+ basegfx::unotools::b2DRectangleFromRealRectangle2D(aUnoViewport));
+ aRetval.setViewport(aViewport);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_Time)
+ {
+ double fViewTime(0.0);
+ rPropertyValue.Value >>= fViewTime;
+ aRetval.setViewTime(fViewTime);
+ }
+ else if (rPropertyValue.Name == g_PropertyName_VisualizedPage)
+ {
+ css::uno::Reference<css::drawing::XDrawPage> xVisualizedPage;
+ rPropertyValue.Value >>= xVisualizedPage;
+ aRetval.setVisualizedPage(xVisualizedPage);
+ }
+ }
+
+ return aRetval;
}
} // end of namespace drawinglayer::geometry
diff --git a/drawinglayer/source/geometry/viewinformation3d.cxx b/drawinglayer/source/geometry/viewinformation3d.cxx
index b3e75bffa6dd..bfe601f976e8 100644
--- a/drawinglayer/source/geometry/viewinformation3d.cxx
+++ b/drawinglayer/source/geometry/viewinformation3d.cxx
@@ -22,8 +22,8 @@
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/geometry/AffineMatrix3D.hpp>
#include <basegfx/utils/canvastools.hxx>
-#include <rtl/instance.hxx>
#include <com/sun/star/uno/Sequence.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -66,57 +66,19 @@ namespace drawinglayer::geometry
// the point in time
double mfViewTime;
- // the complete PropertyValue representation (if already created)
- uno::Sequence< beans::PropertyValue > mxViewInformation;
-
// the extra PropertyValues; does not contain the transformations
uno::Sequence< beans::PropertyValue > mxExtendedInformation;
// the local UNO API strings
- static OUString getNamePropertyObjectTransformation()
- {
- return "ObjectTransformation";
- }
-
- static OUString getNamePropertyOrientation()
- {
- return "Orientation";
- }
-
- static OUString getNamePropertyProjection()
- {
- return "Projection";
- }
-
- static OUString getNamePropertyProjection_30()
- {
- return "Projection30";
- }
-
- static OUString getNamePropertyProjection_31()
- {
- return "Projection31";
- }
-
- static OUString getNamePropertyProjection_32()
- {
- return "Projection32";
- }
-
- static OUString getNamePropertyProjection_33()
- {
- return "Projection33";
- }
-
- static OUString getNamePropertyDeviceToView()
- {
- return "DeviceToView";
- }
-
- static OUString getNamePropertyTime()
- {
- return "Time";
- }
+ static constexpr OUString OBJECT_TRANSFORMATION = u"ObjectTransformation"_ustr;
+ static constexpr OUString ORIENTATION = u"Orientation"_ustr;
+ static constexpr OUString PROJECTION = u"Projection"_ustr;
+ static constexpr OUString PROJECTION30 = u"Projection30"_ustr;
+ static constexpr OUString PROJECTION31 = u"Projection31"_ustr;
+ static constexpr OUString PROJECTION32 = u"Projection32"_ustr;
+ static constexpr OUString PROJECTION33 = u"Projection33"_ustr;
+ static constexpr OUString DEVICE_TO_VIEW = u"DeviceToView"_ustr;
+ static constexpr OUString TIME = u"Time"_ustr;
// a central PropertyValue parsing method to allow transportation of
// all ViewParameters using UNO API
@@ -130,24 +92,25 @@ namespace drawinglayer::geometry
// prepare extended information for filtering. Maximum size is nCount
mxExtendedInformation.realloc(nCount);
+ auto pExtendedInformation = mxExtendedInformation.getArray();
for(sal_Int32 a(0); a < nCount; a++)
{
const beans::PropertyValue& rProp = rViewParameters[a];
- if(rProp.Name == getNamePropertyObjectTransformation())
+ if(rProp.Name == OBJECT_TRANSFORMATION)
{
css::geometry::AffineMatrix3D aAffineMatrix3D;
rProp.Value >>= aAffineMatrix3D;
maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
}
- else if(rProp.Name == getNamePropertyOrientation())
+ else if(rProp.Name == ORIENTATION)
{
css::geometry::AffineMatrix3D aAffineMatrix3D;
rProp.Value >>= aAffineMatrix3D;
maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
}
- else if(rProp.Name == getNamePropertyProjection())
+ else if(rProp.Name == PROJECTION)
{
// projection may be defined using a frustum in which case the last line of
// the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
@@ -166,44 +129,44 @@ namespace drawinglayer::geometry
maProjection.set(3, 2, f_32);
maProjection.set(3, 3, f_33);
}
- else if(rProp.Name == getNamePropertyProjection_30())
+ else if(rProp.Name == PROJECTION30)
{
double f_30(0.0);
rProp.Value >>= f_30;
maProjection.set(3, 0, f_30);
}
- else if(rProp.Name == getNamePropertyProjection_31())
+ else if(rProp.Name == PROJECTION31)
{
double f_31(0.0);
rProp.Value >>= f_31;
maProjection.set(3, 1, f_31);
}
- else if(rProp.Name == getNamePropertyProjection_32())
+ else if(rProp.Name == PROJECTION32)
{
double f_32(0.0);
rProp.Value >>= f_32;
maProjection.set(3, 2, f_32);
}
- else if(rProp.Name == getNamePropertyProjection_33())
+ else if(rProp.Name == PROJECTION33)
{
double f_33(1.0);
rProp.Value >>= f_33;
maProjection.set(3, 3, f_33);
}
- else if(rProp.Name == getNamePropertyDeviceToView())
+ else if(rProp.Name == DEVICE_TO_VIEW)
{
css::geometry::AffineMatrix3D aAffineMatrix3D;
rProp.Value >>= aAffineMatrix3D;
maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
}
- else if(rProp.Name == getNamePropertyTime())
+ else if(rProp.Name == TIME)
{
rProp.Value >>= mfViewTime;
}
else
{
// extra information; add to filtered information
- mxExtendedInformation[nExtendedInsert++] = rProp;
+ pExtendedInformation[nExtendedInsert++] = rProp;
}
}
@@ -211,161 +174,31 @@ namespace drawinglayer::geometry
mxExtendedInformation.realloc(nExtendedInsert);
}
- // central method to create a Sequence of PropertyValues containing he complete
- // data set
- void impFillViewInformationFromContent()
- {
- const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
- const bool bOrientationUsed(!maOrientation.isIdentity());
- const bool bProjectionUsed(!maProjection.isIdentity());
- const bool bDeviceToViewUsed(!maDeviceToView.isIdentity());
- const bool bTimeUsed(0.0 < mfViewTime);
- const bool bExtraInformation(mxExtendedInformation.hasElements());
-
- // projection may be defined using a frustum in which case the last line of
- // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
- // these four values need to be treated extra
- const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0)));
- const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1)));
- const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2)));
- const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0));
-
- sal_uInt32 nIndex(0);
- const sal_uInt32 nCount(
- (bObjectTransformationUsed ? 1 : 0) +
- (bOrientationUsed ? 1 : 0) +
- (bProjectionUsed ? 1 : 0) +
- (bProjectionUsed_30 ? 1 : 0) +
- (bProjectionUsed_31 ? 1 : 0) +
- (bProjectionUsed_32 ? 1 : 0) +
- (bProjectionUsed_33 ? 1 : 0) +
- (bDeviceToViewUsed ? 1 : 0) +
- (bTimeUsed ? 1 : 0) +
- (bExtraInformation ? mxExtendedInformation.getLength() : 0));
-
- mxViewInformation.realloc(nCount);
-
- if(bObjectTransformationUsed)
- {
- css::geometry::AffineMatrix3D aAffineMatrix3D;
- basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation);
- mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
- mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
- nIndex++;
- }
-
- if(bOrientationUsed)
- {
- css::geometry::AffineMatrix3D aAffineMatrix3D;
- basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation);
- mxViewInformation[nIndex].Name = getNamePropertyOrientation();
- mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
- nIndex++;
- }
-
- if(bProjectionUsed)
- {
- css::geometry::AffineMatrix3D aAffineMatrix3D;
- basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection);
- mxViewInformation[nIndex].Name = getNamePropertyProjection();
- mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
- nIndex++;
- }
-
- if(bProjectionUsed_30)
- {
- mxViewInformation[nIndex].Name = getNamePropertyProjection_30();
- mxViewInformation[nIndex].Value <<= maProjection.get(3, 0);
- nIndex++;
- }
-
- if(bProjectionUsed_31)
- {
- mxViewInformation[nIndex].Name = getNamePropertyProjection_31();
- mxViewInformation[nIndex].Value <<= maProjection.get(3, 1);
- nIndex++;
- }
-
- if(bProjectionUsed_32)
- {
- mxViewInformation[nIndex].Name = getNamePropertyProjection_32();
- mxViewInformation[nIndex].Value <<= maProjection.get(3, 2);
- nIndex++;
- }
-
- if(bProjectionUsed_33)
- {
- mxViewInformation[nIndex].Name = getNamePropertyProjection_33();
- mxViewInformation[nIndex].Value <<= maProjection.get(3, 3);
- nIndex++;
- }
-
- if(bDeviceToViewUsed)
- {
- css::geometry::AffineMatrix3D aAffineMatrix3D;
- basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView);
- mxViewInformation[nIndex].Name = getNamePropertyDeviceToView();
- mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
- nIndex++;
- }
-
- if(bTimeUsed)
- {
- mxViewInformation[nIndex].Name = getNamePropertyTime();
- mxViewInformation[nIndex].Value <<= mfViewTime;
- nIndex++;
- }
-
- if(bExtraInformation)
- {
- const sal_Int32 nExtra(mxExtendedInformation.getLength());
-
- for(sal_Int32 a(0); a < nExtra; a++)
- {
- mxViewInformation[nIndex++] = mxExtendedInformation[a];
- }
- }
- }
-
public:
ImpViewInformation3D(
- const basegfx::B3DHomMatrix& rObjectTransformation,
- const basegfx::B3DHomMatrix& rOrientation,
- const basegfx::B3DHomMatrix& rProjection,
- const basegfx::B3DHomMatrix& rDeviceToView,
+ basegfx::B3DHomMatrix aObjectTransformation,
+ basegfx::B3DHomMatrix aOrientation,
+ basegfx::B3DHomMatrix aProjection,
+ basegfx::B3DHomMatrix aDeviceToView,
double fViewTime,
const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
- : maObjectTransformation(rObjectTransformation),
- maOrientation(rOrientation),
- maProjection(rProjection),
- maDeviceToView(rDeviceToView),
- mfViewTime(fViewTime),
- mxViewInformation(),
- mxExtendedInformation()
+ : maObjectTransformation(std::move(aObjectTransformation)),
+ maOrientation(std::move(aOrientation)),
+ maProjection(std::move(aProjection)),
+ maDeviceToView(std::move(aDeviceToView)),
+ mfViewTime(fViewTime)
{
impInterpretPropertyValues(rExtendedParameters);
}
explicit ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
- : maObjectTransformation(),
- maOrientation(),
- maProjection(),
- maDeviceToView(),
- mfViewTime(),
- mxViewInformation(rViewParameters),
- mxExtendedInformation()
+ : mfViewTime()
{
impInterpretPropertyValues(rViewParameters);
}
ImpViewInformation3D()
- : maObjectTransformation(),
- maOrientation(),
- maProjection(),
- maDeviceToView(),
- mfViewTime(),
- mxViewInformation(),
- mxExtendedInformation()
+ : mfViewTime()
{
}
@@ -387,16 +220,6 @@ namespace drawinglayer::geometry
return maObjectToView;
}
- const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
- {
- if(!mxViewInformation.hasElements())
- {
- const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent();
- }
-
- return mxViewInformation;
- }
-
const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
{
return mxExtendedInformation;
@@ -419,8 +242,11 @@ namespace drawinglayer::geometry
{
namespace
{
- struct theGlobalDefault :
- public rtl::Static< ViewInformation3D::ImplType, theGlobalDefault > {};
+ ViewInformation3D::ImplType& theGlobalDefault()
+ {
+ static ViewInformation3D::ImplType SINGLETON;
+ return SINGLETON;
+ }
}
ViewInformation3D::ViewInformation3D(
@@ -442,7 +268,7 @@ namespace drawinglayer::geometry
}
ViewInformation3D::ViewInformation3D()
- : mpViewInformation3D(theGlobalDefault::get())
+ : mpViewInformation3D(theGlobalDefault())
{
}
@@ -454,7 +280,7 @@ namespace drawinglayer::geometry
bool ViewInformation3D::isDefault() const
{
- return mpViewInformation3D.same_object(theGlobalDefault::get());
+ return mpViewInformation3D.same_object(theGlobalDefault());
}
ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D&) = default;
@@ -496,11 +322,6 @@ namespace drawinglayer::geometry
return mpViewInformation3D->getViewTime();
}
- const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const
- {
- return mpViewInformation3D->getViewInformationSequence();
- }
-
const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const
{
return mpViewInformation3D->getExtendedInformationSequence();
diff --git a/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx b/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx
new file mode 100644
index 000000000000..3fe9301054e8
--- /dev/null
+++ b/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <utility>
+
+using namespace com::sun::star;
+
+namespace drawinglayer::primitive2d
+{
+Primitive2DReference BitmapAlphaPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (basegfx::fTools::equal(getTransparency(), 1.0))
+ {
+ // completely transparent, done
+ return nullptr;
+ }
+
+ if (getBitmap().IsEmpty())
+ {
+ // no geometry, done
+ return nullptr;
+ }
+
+ if (basegfx::fTools::equalZero(getTransparency()))
+ {
+ // no transparency, use simple BitmapPrimitive2D
+ return Primitive2DReference{ new BitmapPrimitive2D(getBitmap(), getTransform()) };
+ }
+
+ // default: embed to UnifiedTransparencePrimitive2D
+ Primitive2DContainer aContent{ new BitmapPrimitive2D(getBitmap(), getTransform()) };
+ return Primitive2DReference{ new UnifiedTransparencePrimitive2D(std::move(aContent),
+ getTransparency()) };
+}
+
+BitmapAlphaPrimitive2D::BitmapAlphaPrimitive2D(Bitmap xXBitmap, basegfx::B2DHomMatrix aTransform,
+ double fTransparency)
+ : maBitmap(std::move(xXBitmap))
+ , maTransform(std::move(aTransform))
+ , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
+{
+}
+
+bool BitmapAlphaPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const BitmapAlphaPrimitive2D& rCompare
+ = static_cast<const BitmapAlphaPrimitive2D&>(rPrimitive);
+
+ return (getBitmap() == rCompare.getBitmap() && getTransform() == rCompare.getTransform()
+ && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()));
+ }
+
+ return false;
+}
+
+basegfx::B2DRange
+BitmapAlphaPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
+ aRetval.transform(maTransform);
+ return aRetval;
+}
+
+sal_Int64 BitmapAlphaPrimitive2D::estimateUsage()
+{
+ if (getBitmap().IsEmpty())
+ {
+ return 0;
+ }
+ return getBitmap().GetSizeBytes();
+}
+
+// provide unique ID
+sal_uInt32 BitmapAlphaPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D;
+}
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx
new file mode 100644
index 000000000000..6a3c18b2bc44
--- /dev/null
+++ b/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx
@@ -0,0 +1,178 @@
+/* -*- 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 <comphelper/solarmutex.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionFlusher.hxx>
+
+namespace drawinglayer::primitive2d
+{
+/**
+ This is a "garbage collection" approach to flushing.
+
+ We store entries in a set. Every 2 seconds, we scan the set for entries that have not
+ been used for 10 seconds or more, and if so, we flush the buffer primitives in those entries.
+
+ This mechanism is __deliberately__ not perfect.
+ Sometimes things will be flushed a little too soon, sometimes things will wait a little too long,
+ since we only have a granularity of 2 seconds.
+ But what is gains from not being perfect, is scalability.
+
+ It is very simple, scales to lots and lots of primitives without needing lots of timers, and performs
+ very little work in the common case.
+
+ Shutdown notes
+ --------------------
+ The process of handling shutdown is more complicated here than it should be, because we are interacting with
+ various vcl-level things (by virtue of calling into drawinglayer primitives that use vcl facilities), but we
+ do not have access to vcl-level API here (like SolarMutexReleaser and vcl::Timer).
+*/
+
+static BufferedDecompositionFlusher* getInstance()
+{
+ static std::unique_ptr<BufferedDecompositionFlusher> gaTimer(new BufferedDecompositionFlusher);
+ return gaTimer.get();
+}
+
+// static
+void BufferedDecompositionFlusher::shutdown()
+{
+ BufferedDecompositionFlusher* pFlusher = getInstance();
+ pFlusher->onTeardown();
+ // We have to wait for the thread to exit, otherwise we might end up with the background thread
+ // trying to process stuff while it has things ripped out underneath it.
+ pFlusher->join();
+}
+
+// static
+void BufferedDecompositionFlusher::update(const BufferedDecompositionPrimitive2D* p)
+{
+ getInstance()->updateImpl(p);
+}
+
+// static
+void BufferedDecompositionFlusher::update(const BufferedDecompositionGroupPrimitive2D* p)
+{
+ getInstance()->updateImpl(p);
+}
+
+// static
+void BufferedDecompositionFlusher::remove(const BufferedDecompositionPrimitive2D* p)
+{
+ getInstance()->removeImpl(p);
+}
+
+// static
+void BufferedDecompositionFlusher::remove(const BufferedDecompositionGroupPrimitive2D* p)
+{
+ getInstance()->removeImpl(p);
+}
+
+BufferedDecompositionFlusher::BufferedDecompositionFlusher() { create(); }
+
+void BufferedDecompositionFlusher::updateImpl(const BufferedDecompositionPrimitive2D* p)
+{
+ std::unique_lock l(maMutex);
+ if (!mbShutdown)
+ maRegistered1.insert(const_cast<BufferedDecompositionPrimitive2D*>(p));
+}
+
+void BufferedDecompositionFlusher::updateImpl(const BufferedDecompositionGroupPrimitive2D* p)
+{
+ std::unique_lock l(maMutex);
+ if (!mbShutdown)
+ maRegistered2.insert(const_cast<BufferedDecompositionGroupPrimitive2D*>(p));
+}
+
+void BufferedDecompositionFlusher::removeImpl(const BufferedDecompositionPrimitive2D* p)
+{
+ std::unique_lock l(maMutex);
+ if (!mbShutdown)
+ maRegistered1.erase(const_cast<BufferedDecompositionPrimitive2D*>(p));
+}
+
+void BufferedDecompositionFlusher::removeImpl(const BufferedDecompositionGroupPrimitive2D* p)
+{
+ std::unique_lock l(maMutex);
+ if (!mbShutdown)
+ maRegistered2.erase(const_cast<BufferedDecompositionGroupPrimitive2D*>(p));
+}
+
+void SAL_CALL BufferedDecompositionFlusher::run()
+{
+ setName("BufferedDecompositionFlusher");
+ for (;;)
+ {
+ auto aNow = std::chrono::steady_clock::now();
+ std::vector<rtl::Reference<BufferedDecompositionPrimitive2D>> aRemoved1;
+ std::vector<rtl::Reference<BufferedDecompositionGroupPrimitive2D>> aRemoved2;
+ {
+ std::unique_lock l1(maMutex);
+ // exit if we have been shutdown
+ if (mbShutdown)
+ break;
+ for (auto it = maRegistered1.begin(); it != maRegistered1.end();)
+ {
+ if (aNow - (*it)->maLastAccess.load() > std::chrono::seconds(10))
+ {
+ aRemoved1.push_back(*it);
+ it = maRegistered1.erase(it);
+ }
+ else
+ ++it;
+ }
+ for (auto it = maRegistered2.begin(); it != maRegistered2.end();)
+ {
+ if (aNow - (*it)->maLastAccess.load() > std::chrono::seconds(10))
+ {
+ aRemoved2.push_back(*it);
+ it = maRegistered2.erase(it);
+ }
+ else
+ ++it;
+ }
+ }
+
+ {
+ // some parts of skia do not take kindly to being accessed from multiple threads
+ osl::Guard<comphelper::SolarMutex> aGuard(comphelper::SolarMutex::get());
+
+ for (const auto& r : aRemoved1)
+ r->setBuffered2DDecomposition(nullptr);
+ for (const auto& r : aRemoved2)
+ r->setBuffered2DDecomposition(Primitive2DContainer{});
+ }
+
+ wait(TimeValue(2, 0));
+ }
+}
+
+/// Only called by FlusherDeinit
+void BufferedDecompositionFlusher::onTeardown()
+{
+ std::unique_lock l2(maMutex);
+ mbShutdown = true;
+ maRegistered1.clear();
+ maRegistered2.clear();
+}
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx
new file mode 100644
index 000000000000..61891a333b4b
--- /dev/null
+++ b/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx
@@ -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 .
+ */
+
+#include <sal/config.h>
+
+#include <comphelper/configuration.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionGroupPrimitive2D.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionFlusher.hxx>
+
+namespace drawinglayer::primitive2d
+{
+bool BufferedDecompositionGroupPrimitive2D::hasBuffered2DDecomposition() const
+{
+ if (!mbFlushOnTimer)
+ return !maBuffered2DDecomposition.empty();
+ else
+ {
+ std::lock_guard Guard(maCallbackLock);
+ return !maBuffered2DDecomposition.empty();
+ }
+}
+
+void BufferedDecompositionGroupPrimitive2D::setBuffered2DDecomposition(Primitive2DContainer&& rNew)
+{
+ if (!mbFlushOnTimer)
+ {
+ // no flush used, just set
+ maBuffered2DDecomposition = std::move(rNew);
+ }
+ else
+ {
+ // decomposition changed, touch
+ maLastAccess = std::chrono::steady_clock::now();
+ BufferedDecompositionFlusher::update(this);
+
+ // tdf#158913 need to secure change when flush/multithreading is in use
+ std::lock_guard Guard(maCallbackLock);
+ maBuffered2DDecomposition = std::move(rNew);
+ }
+}
+
+BufferedDecompositionGroupPrimitive2D::BufferedDecompositionGroupPrimitive2D(
+ Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
+ , maCallbackLock()
+ , mbFlushOnTimer(false)
+{
+}
+
+BufferedDecompositionGroupPrimitive2D::~BufferedDecompositionGroupPrimitive2D()
+{
+ if (mbFlushOnTimer)
+ BufferedDecompositionFlusher::remove(this);
+}
+
+void BufferedDecompositionGroupPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (!mbFlushOnTimer)
+ {
+ // no flush/multithreading is in use, just call
+ if (maBuffered2DDecomposition.empty())
+ create2DDecomposition(maBuffered2DDecomposition, rViewInformation);
+ rVisitor.visit(maBuffered2DDecomposition);
+ }
+ else
+ {
+ // tdf#158913 need to secure 'visit' when flush/multithreading is in use,
+ // so that the local non-ref-Counted instance of the decomposition gets not
+ // manipulated (e.g. deleted)
+ Primitive2DContainer xTmp;
+ {
+ maLastAccess = std::chrono::steady_clock::now();
+ // only hold the lock for long enough to get a valid reference
+ std::lock_guard Guard(maCallbackLock);
+ if (maBuffered2DDecomposition.empty())
+ {
+ create2DDecomposition(maBuffered2DDecomposition, rViewInformation);
+ BufferedDecompositionFlusher::update(this);
+ }
+ xTmp = maBuffered2DDecomposition;
+ }
+ rVisitor.visit(xTmp);
+ }
+}
+
+void BufferedDecompositionGroupPrimitive2D::activateFlushOnTimer()
+{
+ if (comphelper::IsFuzzing())
+ return;
+ mbFlushOnTimer = true;
+}
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx
new file mode 100644
index 000000000000..293edc32a7a6
--- /dev/null
+++ b/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx
@@ -0,0 +1,113 @@
+/* -*- 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 <comphelper/configuration.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/BufferedDecompositionFlusher.hxx>
+
+namespace drawinglayer::primitive2d
+{
+bool BufferedDecompositionPrimitive2D::hasBuffered2DDecomposition() const
+{
+ if (!mbFlushOnTimer)
+ return maBuffered2DDecomposition.is();
+ else
+ {
+ std::lock_guard Guard(maCallbackLock);
+ return maBuffered2DDecomposition.is();
+ }
+}
+
+void BufferedDecompositionPrimitive2D::setBuffered2DDecomposition(Primitive2DReference rNew)
+{
+ if (!mbFlushOnTimer)
+ {
+ // no flush used, just set
+ maBuffered2DDecomposition = std::move(rNew);
+ }
+ else
+ {
+ // decomposition changed, touch
+ maLastAccess = std::chrono::steady_clock::now();
+ BufferedDecompositionFlusher::update(this);
+
+ // tdf#158913 need to secure change when flush/multithreading is in use
+ std::lock_guard Guard(maCallbackLock);
+ maBuffered2DDecomposition = std::move(rNew);
+ }
+}
+
+BufferedDecompositionPrimitive2D::BufferedDecompositionPrimitive2D()
+ : maBuffered2DDecomposition()
+ , maCallbackLock()
+ , mbFlushOnTimer(false)
+{
+}
+
+BufferedDecompositionPrimitive2D::~BufferedDecompositionPrimitive2D()
+{
+ if (mbFlushOnTimer)
+ BufferedDecompositionFlusher::remove(this);
+}
+
+void BufferedDecompositionPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (!mbFlushOnTimer)
+ {
+ // no flush/multithreading is in use, just call
+ if (!maBuffered2DDecomposition)
+ maBuffered2DDecomposition = create2DDecomposition(rViewInformation);
+ rVisitor.visit(maBuffered2DDecomposition);
+ }
+ else
+ {
+ // tdf#158913 need to secure 'visit' when flush/multithreading is in use,
+ // so that the local non-ref-Counted instance of the decomposition gets not
+ // manipulated (e.g. deleted)
+ Primitive2DReference xTmp;
+ {
+ maLastAccess = std::chrono::steady_clock::now();
+ // only hold the lock for long enough to get a valid reference
+ std::lock_guard Guard(maCallbackLock);
+ if (!maBuffered2DDecomposition)
+ {
+ maBuffered2DDecomposition = create2DDecomposition(rViewInformation);
+ BufferedDecompositionFlusher::update(this);
+ }
+ xTmp = maBuffered2DDecomposition;
+ }
+ rVisitor.visit(xTmp);
+ }
+}
+
+void BufferedDecompositionPrimitive2D::activateFlushOnTimer()
+{
+ if (comphelper::IsFuzzing())
+ return;
+ mbFlushOnTimer = true;
+}
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx
new file mode 100644
index 000000000000..0f07c2210670
--- /dev/null
+++ b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.cxx
@@ -0,0 +1,96 @@
+/* -*- 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 "GlowSoftEgdeShadowTools.hxx"
+#include <vcl/bitmap/BitmapBasicMorphologyFilter.hxx>
+#include <vcl/bitmap/BitmapFilterStackBlur.hxx>
+
+namespace drawinglayer::primitive2d
+{
+/* Returns 8-bit alpha mask created from passed mask.
+
+ Negative fErodeDilateRadius values mean erode, positive - dilate.
+ nTransparency defines minimal transparency level.
+*/
+AlphaMask ProcessAndBlurAlphaMask(const AlphaMask& rMask, double fErodeDilateRadius,
+ double fBlurRadius, sal_uInt8 nTransparency, bool bConvertTo1Bit)
+{
+ // Invert it to operate in the transparency domain. Trying to update this method to
+ // work in the alpha domain is fraught with hazards.
+ AlphaMask tmpMask = rMask;
+ tmpMask.Invert();
+
+ // Only completely white pixels on the initial mask must be considered for transparency. Any
+ // other color must be treated as black. This creates 1-bit B&W bitmap.
+ Bitmap mask = bConvertTo1Bit ? tmpMask.GetBitmap().CreateMask(COL_WHITE) : tmpMask.GetBitmap();
+
+ // Scaling down increases performance without noticeable quality loss. Additionally,
+ // current blur implementation can only handle blur radius between 2 and 254.
+ Size aSize = mask.GetSizePixel();
+ double fScale = 1.0;
+ while (fBlurRadius > 254 || aSize.Height() > 1000 || aSize.Width() > 1000)
+ {
+ fScale /= 2;
+ fBlurRadius /= 2;
+ fErodeDilateRadius /= 2;
+ aSize /= 2;
+ }
+
+ // BmpScaleFlag::NearestNeighbor is important for following color replacement
+ mask.Scale(fScale, fScale, BmpScaleFlag::NearestNeighbor);
+
+ if (fErodeDilateRadius > 0)
+ BitmapFilter::Filter(mask, BitmapDilateFilter(fErodeDilateRadius));
+ else if (fErodeDilateRadius < 0)
+ BitmapFilter::Filter(mask, BitmapErodeFilter(-fErodeDilateRadius, 0xFF));
+
+ if (nTransparency)
+ {
+ const Color aTransparency(nTransparency, nTransparency, nTransparency);
+ mask.Replace(COL_BLACK, aTransparency);
+ }
+
+ // We need 8-bit grey mask for blurring
+ mask.Convert(BmpConversion::N8BitGreys);
+
+ // calculate blurry effect
+ BitmapFilter::Filter(mask, BitmapFilterStackBlur(fBlurRadius));
+
+ mask.Scale(rMask.GetSizePixel());
+
+ // And switch to the alpha domain.
+ mask.Invert();
+
+ return AlphaMask(mask);
+}
+
+drawinglayer::geometry::ViewInformation2D
+expandB2DRangeAtViewInformation2D(const drawinglayer::geometry::ViewInformation2D& rViewInfo,
+ double nAmount)
+{
+ drawinglayer::geometry::ViewInformation2D aRetval(rViewInfo);
+ basegfx::B2DRange viewport(rViewInfo.getViewport());
+ viewport.grow(nAmount);
+ aRetval.setViewport(viewport);
+ return aRetval;
+}
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.hxx
index 886ce99bb7ff..b6a62be8863e 100644
--- a/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx
+++ b/drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.hxx
@@ -19,29 +19,24 @@
#pragma once
-class OutputDevice;
+#include <vcl/alpha.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
namespace drawinglayer::primitive2d
{
-class WrongSpellPrimitive2D;
-}
+/* Returns 8-bit alpha mask created from passed mask.
-namespace basegfx
-{
-class B2DHomMatrix;
-class BColorModifierStack;
-}
-
-// support WrongSpell rendering using VCL from primitives due to VCLs nice
-// and fast solution with wavelines
+ Negative fErodeDilateRadius values mean erode, positive - dilate.
+ nTransparency defines minimal transparency level.
+*/
+AlphaMask ProcessAndBlurAlphaMask(const AlphaMask& rMask, double fErodeDilateRadius,
+ double fBlurRadius, sal_uInt8 nTransparency,
+ bool bConvertTo1Bit = true);
-namespace drawinglayer
-{
-bool renderWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate,
- OutputDevice& rOutputDevice,
- const basegfx::B2DHomMatrix& rObjectToViewTransformation,
- const basegfx::BColorModifierStack& rBColorModifierStack);
+drawinglayer::geometry::ViewInformation2D
+expandB2DRangeAtViewInformation2D(const drawinglayer::geometry::ViewInformation2D& rViewInfo,
+ double nAmount);
-} // end of namespace drawinglayer
+} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx
new file mode 100644
index 000000000000..63de94bb39ad
--- /dev/null
+++ b/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx
@@ -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 <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <basegfx/utils/bgradient.hxx>
+
+using namespace com::sun::star;
+
+namespace drawinglayer::primitive2d
+{
+Primitive2DReference PolyPolygonAlphaGradientPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (0 == getB2DPolyPolygon().count())
+ {
+ // no geometry, done
+ return nullptr;
+ }
+
+ if (getAlphaGradient().isDefault())
+ {
+ // default is a single ColorStop at 0.0 with black (0, 0, 0). The
+ // luminance is then 0.0, too -> not transparent at all
+ return new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(), getBColor());
+ }
+
+ basegfx::BColor aSingleColor;
+ if (getAlphaGradient().getColorStops().isSingleColor(aSingleColor))
+ {
+ // no real transparence gradient, only unified alpha,
+ // we can use PolyPolygonRGBAPrimitive2D
+ return new PolyPolygonRGBAPrimitive2D(getB2DPolyPolygon(), getBColor(),
+ aSingleColor.luminance());
+ }
+
+ // transparency gradient is a real gradient, create TransparencePrimitive2D
+ Primitive2DContainer aContent{ new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(),
+ getBColor()) };
+
+ Primitive2DContainer aAlpha{ new FillGradientPrimitive2D(
+ basegfx::utils::getRange(getB2DPolyPolygon()), getAlphaGradient()) };
+
+ return new TransparencePrimitive2D(std::move(aContent), std::move(aAlpha));
+}
+
+PolyPolygonAlphaGradientPrimitive2D::PolyPolygonAlphaGradientPrimitive2D(
+ const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor,
+ const attribute::FillGradientAttribute& rAlphaGradient)
+ : maPolyPolygon(rPolyPolygon)
+ , maBColor(rBColor)
+ , maAlphaGradient(rAlphaGradient)
+{
+}
+
+bool PolyPolygonAlphaGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const PolyPolygonAlphaGradientPrimitive2D& rCompare
+ = static_cast<const PolyPolygonAlphaGradientPrimitive2D&>(rPrimitive);
+
+ return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
+ && getBColor() == rCompare.getBColor()
+ && getAlphaGradient() == rCompare.getAlphaGradient());
+ }
+
+ return false;
+}
+
+basegfx::B2DRange PolyPolygonAlphaGradientPrimitive2D::getB2DRange(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ // return range - without decompose
+ return basegfx::utils::getRange(getB2DPolyPolygon());
+}
+
+// provide unique ID
+sal_uInt32 PolyPolygonAlphaGradientPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D;
+}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D.cxx
index aa48a965e692..6c7cf4bb365a 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D.cxx
@@ -20,16 +20,17 @@
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor)
- : BasePrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon,
+ const basegfx::BColor& rBColor)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maBColor(rBColor)
{
}
@@ -61,6 +62,54 @@ sal_uInt32 PolyPolygonColorPrimitive2D::getPrimitive2DID() const
return PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D;
}
+FilledRectanglePrimitive2D::FilledRectanglePrimitive2D(const basegfx::B2DRange& rB2DRange,
+ const basegfx::BColor& rBColor)
+ : BasePrimitive2D()
+ , maB2DRange(rB2DRange)
+ , maBColor(rBColor)
+{
+}
+
+bool FilledRectanglePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const FilledRectanglePrimitive2D& rCompare(
+ static_cast<const FilledRectanglePrimitive2D&>(rPrimitive));
+
+ return (getB2DRange() == rCompare.getB2DRange() && getBColor() == rCompare.getBColor());
+ }
+
+ return false;
+}
+
+basegfx::B2DRange FilledRectanglePrimitive2D::getB2DRange(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ return getB2DRange();
+}
+
+sal_uInt32 FilledRectanglePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_FILLEDRECTANGLEPRIMITIVE2D;
+}
+
+void FilledRectanglePrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(getB2DRange()));
+ Primitive2DContainer aSequence
+ = { new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), getBColor()) };
+ rVisitor.visit(aSequence);
+}
+
} // end drawinglayer::primitive2d namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D.cxx
index 076436b40655..d37e3d71225b 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D.cxx
@@ -22,61 +22,83 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <rtl/ref.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonGradientPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonGradientPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if (!getFillGradient().isDefault())
{
// create SubSequence with FillGradientPrimitive2D
const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
- FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(
- aPolyPolygonRange, getDefinitionRange(), getFillGradient());
- const Primitive2DReference xSubRef(pNewGradient);
- const Primitive2DContainer aSubSequence{ xSubRef };
+ rtl::Reference<FillGradientPrimitive2D> pNewGradient = new FillGradientPrimitive2D(
+ aPolyPolygonRange, getDefinitionRange(), getFillGradient(),
+ hasAlphaGradient() ? &getAlphaGradient() : nullptr, getTransparency());
+ Primitive2DContainer aSubSequence{ pNewGradient };
// create mask primitive
- rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence));
+ return new MaskPrimitive2D(getB2DPolyPolygon(), std::move(aSubSequence));
}
+ return nullptr;
}
PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D(
const basegfx::B2DPolyPolygon& rPolyPolygon,
const attribute::FillGradientAttribute& rFillGradient)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ : maPolyPolygon(rPolyPolygon)
, maDefinitionRange(rPolyPolygon.getB2DRange())
, maFillGradient(rFillGradient)
+ , maAlphaGradient()
+ , mfTransparency(0.0)
{
}
PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DRange& rDefinitionRange,
- const attribute::FillGradientAttribute& rFillGradient)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ basegfx::B2DPolyPolygon aPolyPolygon, const basegfx::B2DRange& rDefinitionRange,
+ const attribute::FillGradientAttribute& rFillGradient,
+ const attribute::FillGradientAttribute* pAlphaGradient, double fTransparency)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maDefinitionRange(rDefinitionRange)
, maFillGradient(rFillGradient)
+ , maAlphaGradient()
+ , mfTransparency(fTransparency)
{
+ // copy alpha gradient if we got one
+ if (nullptr != pAlphaGradient)
+ maAlphaGradient = *pAlphaGradient;
}
bool PolyPolygonGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const PolyPolygonGradientPrimitive2D& rCompare
- = static_cast<const PolyPolygonGradientPrimitive2D&>(rPrimitive);
+ if (!(BufferedDecompositionPrimitive2D::operator==(rPrimitive)))
+ return false;
- return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
- && getDefinitionRange() == rCompare.getDefinitionRange()
- && getFillGradient() == rCompare.getFillGradient());
- }
+ const PolyPolygonGradientPrimitive2D& rCompare(
+ static_cast<const PolyPolygonGradientPrimitive2D&>(rPrimitive));
+
+ if (getB2DPolyPolygon() != rCompare.getB2DPolyPolygon())
+ return false;
+
+ if (getDefinitionRange() != rCompare.getDefinitionRange())
+ return false;
- return false;
+ if (getFillGradient() != rCompare.getFillGradient())
+ return false;
+
+ if (maAlphaGradient != rCompare.maAlphaGradient)
+ return false;
+
+ if (!basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()))
+ return false;
+
+ return true;
}
// provide unique ID
@@ -84,7 +106,6 @@ sal_uInt32 PolyPolygonGradientPrimitive2D::getPrimitive2DID() const
{
return PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D;
}
-
} // end drawinglayer::primitive2d namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
index c857ba5c8e3d..fee818e23d65 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
@@ -24,37 +24,53 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
+#include <utility>
#include <vcl/graph.hxx>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonGraphicPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonGraphicPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
+ if (basegfx::fTools::equal(getTransparency(), 1.0))
+ {
+ // completely transparent, done
+ return nullptr;
+ }
+
if (getFillGraphic().isDefault())
- return;
+ {
+ // no geometry data, done
+ return nullptr;
+ }
- const Graphic& rGraphic = getFillGraphic().getGraphic();
+ const Graphic& rGraphic(getFillGraphic().getGraphic());
const GraphicType aType(rGraphic.GetType());
// is there a bitmap or a metafile (do we have content)?
if (GraphicType::Bitmap != aType && GraphicType::GdiMetafile != aType)
- return;
+ {
+ // no geometry data, done
+ return nullptr;
+ }
const Size aPrefSize(rGraphic.GetPrefSize());
// does content have a size?
if (!(aPrefSize.Width() && aPrefSize.Height()))
- return;
+ {
+ // no geometry data with size, done
+ return nullptr;
+ }
// create SubSequence with FillGraphicPrimitive2D based on polygon range
const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange());
- const basegfx::B2DHomMatrix aNewObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(aOutRange.getRange(),
- aOutRange.getMinimum()));
- Primitive2DReference xSubRef;
+ const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aOutRange.getRange(), aOutRange.getMinimum()));
+ drawinglayer::attribute::FillGraphicAttribute aFillGraphicAttribute(getFillGraphic());
if (aOutRange != getDefinitionRange())
{
@@ -80,28 +96,27 @@ void PolyPolygonGraphicPrimitive2D::create2DDecomposition(
aAdaptedRange.transform(aFromGlobalToOutRange);
- const drawinglayer::attribute::FillGraphicAttribute aAdaptedFillGraphicAttribute(
+ aFillGraphicAttribute = drawinglayer::attribute::FillGraphicAttribute(
getFillGraphic().getGraphic(), aAdaptedRange, getFillGraphic().getTiling(),
getFillGraphic().getOffsetX(), getFillGraphic().getOffsetY());
-
- xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, aAdaptedFillGraphicAttribute);
- }
- else
- {
- xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, getFillGraphic());
}
+ // use tooling due to evtl. animation info needs to be created if
+ // the Graphic is animated somehow
+ Primitive2DReference aContent(
+ createFillGraphicPrimitive2D(aTransform, aFillGraphicAttribute, getTransparency()));
+
// embed to mask primitive
- rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), Primitive2DContainer{ xSubRef }));
+ return new MaskPrimitive2D(getB2DPolyPolygon(), Primitive2DContainer{ aContent });
}
PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DRange& rDefinitionRange,
- const attribute::FillGraphicAttribute& rFillGraphic)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ basegfx::B2DPolyPolygon aPolyPolygon, const basegfx::B2DRange& rDefinitionRange,
+ const attribute::FillGraphicAttribute& rFillGraphic, double fTransparency)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maDefinitionRange(rDefinitionRange)
, maFillGraphic(rFillGraphic)
+ , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
{
}
@@ -114,7 +129,8 @@ bool PolyPolygonGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive
return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
&& getDefinitionRange() == rCompare.getDefinitionRange()
- && getFillGraphic() == rCompare.getFillGraphic());
+ && getFillGraphic() == rCompare.getFillGraphic()
+ && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()));
}
return false;
diff --git a/drawinglayer/source/primitive2d/PolyPolygonHairlinePrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonHairlinePrimitive2D.cxx
index e4c73f9191a5..88b15160e2c0 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonHairlinePrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonHairlinePrimitive2D.cxx
@@ -18,35 +18,35 @@
*/
#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonHairlinePrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonHairlinePrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
const sal_uInt32 nCount(aPolyPolygon.count());
- if (nCount)
+ Primitive2DContainer aContainer;
+ for (sal_uInt32 a(0); a < nCount; a++)
{
- for (sal_uInt32 a(0); a < nCount; a++)
- {
- rContainer.push_back(
- new PolygonHairlinePrimitive2D(aPolyPolygon.getB2DPolygon(a), getBColor()));
- }
+ aContainer.push_back(
+ new PolygonHairlinePrimitive2D(aPolyPolygon.getB2DPolygon(a), getBColor()));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
-PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon,
+ const basegfx::BColor& rBColor)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maBColor(rBColor)
{
}
diff --git a/drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D.cxx
index ad85c02f22c1..2379e54e3de8 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D.cxx
@@ -22,47 +22,48 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
+#include <rtl/ref.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonHatchPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonHatchPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if (!getFillHatch().isDefault())
{
// create SubSequence with FillHatchPrimitive2D
const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
- FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(
+ rtl::Reference<FillHatchPrimitive2D> pNewHatch = new FillHatchPrimitive2D(
aPolyPolygonRange, getDefinitionRange(), getBackgroundColor(), getFillHatch());
- const Primitive2DReference xSubRef(pNewHatch);
- const Primitive2DContainer aSubSequence{ xSubRef };
+ Primitive2DContainer aSubSequence{ pNewHatch };
// create mask primitive
- rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence));
+ return new MaskPrimitive2D(getB2DPolyPolygon(), std::move(aSubSequence));
}
+ return nullptr;
}
PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(
const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBackgroundColor,
- const attribute::FillHatchAttribute& rFillHatch)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ attribute::FillHatchAttribute rFillHatch)
+ : maPolyPolygon(rPolyPolygon)
, maDefinitionRange(rPolyPolygon.getB2DRange())
, maBackgroundColor(rBackgroundColor)
- , maFillHatch(rFillHatch)
+ , maFillHatch(std::move(rFillHatch))
{
}
-PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rBackgroundColor, const attribute::FillHatchAttribute& rFillHatch)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon,
+ const basegfx::B2DRange& rDefinitionRange,
+ const basegfx::BColor& rBackgroundColor,
+ attribute::FillHatchAttribute rFillHatch)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maDefinitionRange(rDefinitionRange)
, maBackgroundColor(rBackgroundColor)
- , maFillHatch(rFillHatch)
+ , maFillHatch(std::move(rFillHatch))
{
}
diff --git a/drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D.cxx
index b545ec9465fa..9c9e3b1ae81f 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D.cxx
@@ -18,37 +18,38 @@
*/
#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonMarkerPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonMarkerPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
const sal_uInt32 nCount(aPolyPolygon.count());
- if (nCount)
+ Primitive2DContainer aContainer;
+ for (sal_uInt32 a(0); a < nCount; a++)
{
- for (sal_uInt32 a(0); a < nCount; a++)
- {
- rContainer.push_back(new PolygonMarkerPrimitive2D(aPolyPolygon.getB2DPolygon(a),
- getRGBColorA(), getRGBColorB(),
- getDiscreteDashLength()));
- }
+ aContainer.push_back(new PolygonMarkerPrimitive2D(aPolyPolygon.getB2DPolygon(a),
+ getRGBColorA(), getRGBColorB(),
+ getDiscreteDashLength()));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
-PolyPolygonMarkerPrimitive2D::PolyPolygonMarkerPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rRGBColorA,
- const basegfx::BColor& rRGBColorB, double fDiscreteDashLength)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+PolyPolygonMarkerPrimitive2D::PolyPolygonMarkerPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon,
+ const basegfx::BColor& rRGBColorA,
+ const basegfx::BColor& rRGBColorB,
+ double fDiscreteDashLength)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maRGBColorA(rRGBColorA)
, maRGBColorB(rRGBColorB)
, mfDiscreteDashLength(fDiscreteDashLength)
diff --git a/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx
new file mode 100644
index 000000000000..fb230af8712e
--- /dev/null
+++ b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx
@@ -0,0 +1,99 @@
+/* -*- 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 <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+
+using namespace com::sun::star;
+
+namespace drawinglayer::primitive2d
+{
+Primitive2DReference PolyPolygonRGBAPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (basegfx::fTools::equal(getTransparency(), 1.0))
+ {
+ // completely transparent, done
+ return nullptr;
+ }
+
+ if (0 == getB2DPolyPolygon().count())
+ {
+ // no geometry, done
+ return nullptr;
+ }
+
+ if (basegfx::fTools::equalZero(getTransparency()))
+ {
+ // no transparency, use simple PolyPolygonColorPrimitive2D
+ return Primitive2DReference{ new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(),
+ getBColor()) };
+ }
+
+ // default: embed to UnifiedTransparencePrimitive2D
+ Primitive2DContainer aContent{ new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(),
+ getBColor()) };
+ return Primitive2DReference{ new UnifiedTransparencePrimitive2D(std::move(aContent),
+ getTransparency()) };
+}
+
+PolyPolygonRGBAPrimitive2D::PolyPolygonRGBAPrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const basegfx::BColor& rBColor,
+ double fTransparency)
+ : maPolyPolygon(rPolyPolygon)
+ , maBColor(rBColor)
+ , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
+{
+}
+
+bool PolyPolygonRGBAPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const PolyPolygonRGBAPrimitive2D& rCompare
+ = static_cast<const PolyPolygonRGBAPrimitive2D&>(rPrimitive);
+
+ return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
+ && getBColor() == rCompare.getBColor()
+ && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()));
+ }
+
+ return false;
+}
+
+basegfx::B2DRange PolyPolygonRGBAPrimitive2D::getB2DRange(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ // return range - without decompose
+ return basegfx::utils::getRange(getB2DPolyPolygon());
+}
+
+// provide unique ID
+sal_uInt32 PolyPolygonRGBAPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D;
+}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D.cxx
index 7be684c2f71e..a5595a4bcaeb 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonSelectionPrimitive2D.cxx
@@ -25,16 +25,17 @@
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonSelectionPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonSelectionPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if (getTransparence() >= 1.0 || !getB2DPolyPolygon().count())
- return;
+ return nullptr;
Primitive2DContainer aRetval;
@@ -61,19 +62,18 @@ void PolyPolygonSelectionPrimitive2D::create2DDecomposition(
if (!aRetval.empty() && getTransparence() > 0.0)
{
const Primitive2DReference aTrans(
- new UnifiedTransparencePrimitive2D(aRetval, getTransparence()));
+ new UnifiedTransparencePrimitive2D(std::move(aRetval), getTransparence()));
aRetval = Primitive2DContainer{ aTrans };
}
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
+ return new GroupPrimitive2D(std::move(aRetval));
}
PolyPolygonSelectionPrimitive2D::PolyPolygonSelectionPrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rColor,
- double fTransparence, double fDiscreteGrow, bool bFill)
- : DiscreteMetricDependentPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ basegfx::B2DPolyPolygon aPolyPolygon, const basegfx::BColor& rColor, double fTransparence,
+ double fDiscreteGrow, bool bFill)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maColor(rColor)
, mfTransparence(fTransparence)
, mfDiscreteGrow(fabs(fDiscreteGrow))
diff --git a/drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D.cxx
index 53abec1138c3..9c32d8853d8d 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D.cxx
@@ -21,44 +21,42 @@
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-void PolyPolygonStrokePrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+Primitive2DReference PolyPolygonStrokePrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
const sal_uInt32 nCount(aPolyPolygon.count());
- if (nCount)
+ Primitive2DContainer aContainer;
+ for (sal_uInt32 a(0); a < nCount; a++)
{
- for (sal_uInt32 a(0); a < nCount; a++)
- {
- rContainer.push_back(new PolygonStrokePrimitive2D(
- aPolyPolygon.getB2DPolygon(a), getLineAttribute(), getStrokeAttribute()));
- }
+ aContainer.push_back(new PolygonStrokePrimitive2D(
+ aPolyPolygon.getB2DPolygon(a), getLineAttribute(), getStrokeAttribute()));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const attribute::LineAttribute& rLineAttribute,
- const attribute::StrokeAttribute& rStrokeAttribute)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ basegfx::B2DPolyPolygon aPolyPolygon, const attribute::LineAttribute& rLineAttribute,
+ attribute::StrokeAttribute aStrokeAttribute)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maLineAttribute(rLineAttribute)
- , maStrokeAttribute(rStrokeAttribute)
+ , maStrokeAttribute(std::move(aStrokeAttribute))
{
}
PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
- const basegfx::B2DPolyPolygon& rPolyPolygon, const attribute::LineAttribute& rLineAttribute)
- : BufferedDecompositionPrimitive2D()
- , maPolyPolygon(rPolyPolygon)
+ basegfx::B2DPolyPolygon aPolyPolygon, const attribute::LineAttribute& rLineAttribute)
+ : maPolyPolygon(std::move(aPolyPolygon))
, maLineAttribute(rLineAttribute)
- , maStrokeAttribute()
{
}
diff --git a/drawinglayer/source/primitive2d/Primitive2DContainer.cxx b/drawinglayer/source/primitive2d/Primitive2DContainer.cxx
index 3df6dd791528..48b0c625e1ba 100644
--- a/drawinglayer/source/primitive2d/Primitive2DContainer.cxx
+++ b/drawinglayer/source/primitive2d/Primitive2DContainer.cxx
@@ -20,33 +20,45 @@
#include <sal/config.h>
#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
-#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <drawinglayer/primitive2d/Tools.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
-#include <basegfx/utils/canvastools.hxx>
using namespace css;
namespace drawinglayer::primitive2d
{
-Primitive2DContainer Primitive2DContainer::maybeInvert(bool bInvert) const
+Primitive2DContainer::Primitive2DContainer(
+ const css::uno::Sequence<css::uno::Reference<css::graphic::XPrimitive2D>>& rSource)
{
- const sal_uInt32 nSize(size());
- Primitive2DContainer aRetval;
-
- aRetval.resize(nSize);
+ for (const auto& rPrimitive : rSource)
+ append(static_cast<const UnoPrimitive2D*>(rPrimitive.get())->getBasePrimitive2D());
+}
+Primitive2DContainer::Primitive2DContainer(
+ const std::deque<css::uno::Reference<css::graphic::XPrimitive2D>>& rSource)
+{
+ for (const auto& rPrimitive : rSource)
+ append(static_cast<const UnoPrimitive2D*>(rPrimitive.get())->getBasePrimitive2D());
+}
- for (sal_uInt32 a(0); a < nSize; a++)
+css::uno::Sequence<css::uno::Reference<css::graphic::XPrimitive2D>>
+Primitive2DContainer::toSequence() const
+{
+ css::uno::Sequence<css::uno::Reference<css::graphic::XPrimitive2D>> aVal(size());
+ auto p = aVal.getArray();
+ for (const auto& rPrimitive : *this)
{
- aRetval[bInvert ? nSize - 1 - a : a] = (*this)[a];
+ *p = new UnoPrimitive2D(rPrimitive);
+ ++p;
}
+ return aVal;
+}
- // all entries taken over to Uno References as owners. To avoid
- // errors with users of this mechanism to delete pointers to BasePrimitive2D
- // itself, clear given vector
- const_cast<Primitive2DContainer&>(*this).clear();
-
- return aRetval;
+Primitive2DContainer Primitive2DContainer::maybeInvert(bool bInvert)
+{
+ if (bInvert)
+ std::reverse(begin(), end());
+ return std::move(*this);
}
// get B2DRange from a given Primitive2DSequence
@@ -115,9 +127,27 @@ void Primitive2DContainer::append(Primitive2DContainer&& rSource)
std::make_move_iterator(rSource.end()));
}
-void Primitive2DContainer::append(const Primitive2DSequence& rSource)
+UnoPrimitive2D::~UnoPrimitive2D() {}
+
+css::uno::Sequence<::css::uno::Reference<::css::graphic::XPrimitive2D>>
+ SAL_CALL UnoPrimitive2D::getDecomposition(
+ const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters)
+{
+ std::unique_lock aGuard(m_aMutex);
+ return mxPrimitive->getDecomposition(rViewParameters).toSequence();
+}
+
+css::geometry::RealRectangle2D SAL_CALL
+UnoPrimitive2D::getRange(const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters)
+{
+ std::unique_lock aGuard(m_aMutex);
+ return mxPrimitive->getRange(rViewParameters);
+}
+
+sal_Int64 SAL_CALL UnoPrimitive2D::estimateUsage()
{
- this->insert(this->end(), rSource.begin(), rSource.end());
+ std::unique_lock aGuard(m_aMutex);
+ return mxPrimitive->estimateUsage();
}
} // end of namespace drawinglayer::primitive2d
diff --git a/drawinglayer/source/primitive2d/Tools.cxx b/drawinglayer/source/primitive2d/Tools.cxx
index 7db3a94c8d04..e1c3dfe96e80 100644
--- a/drawinglayer/source/primitive2d/Tools.cxx
+++ b/drawinglayer/source/primitive2d/Tools.cxx
@@ -21,7 +21,6 @@
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
-#include <basegfx/utils/canvastools.hxx>
using namespace css;
@@ -32,29 +31,10 @@ basegfx::B2DRange
getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate,
const geometry::ViewInformation2D& aViewInformation)
{
- basegfx::B2DRange aRetval;
+ if (!rCandidate)
+ return basegfx::B2DRange();
- if (rCandidate.is())
- {
- // try to get C++ implementation base
- const BasePrimitive2D* pCandidate(dynamic_cast<BasePrimitive2D*>(rCandidate.get()));
-
- if (pCandidate)
- {
- // use it if possible
- aRetval.expand(pCandidate->getB2DRange(aViewInformation));
- }
- else
- {
- // use UNO API call instead
- const uno::Sequence<beans::PropertyValue>& rViewParameters(
- aViewInformation.getViewInformationSequence());
- aRetval.expand(basegfx::unotools::b2DRectangleFromRealRectangle2D(
- rCandidate->getRange(rViewParameters)));
- }
- }
-
- return aRetval;
+ return rCandidate->getB2DRange(aViewInformation);
}
bool arePrimitive2DReferencesEqual(const Primitive2DReference& rxA, const Primitive2DReference& rxB)
@@ -71,15 +51,28 @@ bool arePrimitive2DReferencesEqual(const Primitive2DReference& rxA, const Primit
return true;
}
- const BasePrimitive2D* pA(dynamic_cast<const BasePrimitive2D*>(rxA.get()));
- const BasePrimitive2D* pB(dynamic_cast<const BasePrimitive2D*>(rxB.get()));
+ return rxA->operator==(*rxB);
+}
+
+bool arePrimitive2DReferencesEqual(const css::uno::Reference<css::graphic::XPrimitive2D>& rxA,
+ const css::uno::Reference<css::graphic::XPrimitive2D>& rxB)
+{
+ const bool bAIs(rxA.is());
- if (!pA || !pB)
+ if (bAIs != rxB.is())
{
return false;
}
- return pA->operator==(*pB);
+ if (!bAIs)
+ {
+ return true;
+ }
+
+ auto pA = static_cast<const UnoPrimitive2D*>(rxA.get());
+ auto pB = static_cast<const UnoPrimitive2D*>(rxB.get());
+
+ return (*pA->getBasePrimitive2D()) == (*pB->getBasePrimitive2D());
}
OUString idToString(sal_uInt32 nId)
@@ -87,151 +80,169 @@ OUString idToString(sal_uInt32 nId)
switch (nId)
{
case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D:
- return "TRANSPARENCE";
+ return u"TRANSPARENCE"_ustr;
case PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D:
- return "ANIMATEDSWITCH";
+ return u"ANIMATEDSWITCH"_ustr;
case PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D:
- return "ANIMATEDBLINK";
+ return u"ANIMATEDBLINK"_ustr;
case PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D:
- return "ANIMATEDINTERPOLATE";
+ return u"ANIMATEDINTERPOLATE"_ustr;
case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D:
- return "BACKGROUNDCOLOR";
+ return u"BACKGROUNDCOLOR"_ustr;
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
- return "BITMAP";
+ return u"BITMAP"_ustr;
case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D:
- return "CONTROL";
+ return u"CONTROL"_ustr;
case PRIMITIVE2D_ID_EMBEDDED3DPRIMITIVE2D:
- return "EMBEDDED3D";
+ return u"EMBEDDED3D"_ustr;
case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
- return "FILLGRAPHIC";
+ return u"FILLGRAPHIC"_ustr;
case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D:
- return "FILLGRADIENT";
+ return u"FILLGRADIENT"_ustr;
case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D:
- return "FILLHATCH";
+ return u"FILLHATCH"_ustr;
case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D:
- return "GRAPHIC";
+ return u"GRAPHIC"_ustr;
case PRIMITIVE2D_ID_GRIDPRIMITIVE2D:
- return "GRID";
+ return u"GRID"_ustr;
case PRIMITIVE2D_ID_GROUPPRIMITIVE2D:
- return "GROUP";
+ return u"GROUP"_ustr;
case PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D:
- return "HELPLINE";
+ return u"HELPLINE"_ustr;
case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
- return "MARKERARRAY";
+ return u"MARKERARRAY"_ustr;
case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
- return "MASK";
+ return u"MASK"_ustr;
case PRIMITIVE2D_ID_MEDIAPRIMITIVE2D:
- return "MEDIA";
+ return u"MEDIA"_ustr;
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D:
- return "METAFILE";
+ return u"METAFILE"_ustr;
case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
- return "MODIFIEDCOLOR";
+ return u"MODIFIEDCOLOR"_ustr;
case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
- return "POLYGONHAIRLINE";
+ return u"POLYGONHAIRLINE"_ustr;
case PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D:
- return "POLYGONMARKER";
+ return u"POLYGONMARKER"_ustr;
case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
- return "POLYGONSTROKE";
+ return u"POLYGONSTROKE"_ustr;
case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D:
- return "POLYGONSTROKEARROW";
+ return u"POLYGONSTROKEARROW"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D:
- return "POLYPOLYGONSTROKE";
+ return u"POLYPOLYGONSTROKE"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONSTROKEARROWPRIMITIVE2D:
- return "POLYPOLYGONSTROKEARROW";
+ return u"POLYPOLYGONSTROKEARROW"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
- return "POLYPOLYGONCOLOR";
+ return u"POLYPOLYGONCOLOR"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D:
- return "POLYPOLYGONGRADIENT";
+ return u"POLYPOLYGONGRADIENT"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D:
- return "POLYPOLYGONHATCH";
+ return u"POLYPOLYGONHATCH"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D:
- return "POLYPOLYGONGRAPHIC";
+ return u"POLYPOLYGONGRAPHIC"_ustr;
case PRIMITIVE2D_ID_SCENEPRIMITIVE2D:
- return "SCENE";
+ return u"SCENE"_ustr;
case PRIMITIVE2D_ID_SHADOWPRIMITIVE2D:
- return "SHADOW";
+ return u"SHADOW"_ustr;
case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
- return "TEXTSIMPLEPORTION";
+ return u"TEXTSIMPLEPORTION"_ustr;
case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
- return "TEXTDECORATEDPORTION";
+ return u"TEXTDECORATEDPORTION"_ustr;
case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
- return "TRANSFORM";
+ return u"TRANSFORM"_ustr;
case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
- return "UNIFIEDTRANSPARENCE";
+ return u"UNIFIEDTRANSPARENCE"_ustr;
case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
- return "POINTARRAY";
+ return u"POINTARRAY"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D:
- return "TEXTHIERARCHYFIELD";
+ return u"TEXTHIERARCHYFIELD"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D:
- return "TEXTHIERARCHYLINE";
+ return u"TEXTHIERARCHYLINE"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D:
- return "TEXTHIERARCHYPARAGRAPH";
+ return u"TEXTHIERARCHYPARAGRAPH"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D:
- return "TEXTHIERARCHYBLOCK";
+ return u"TEXTHIERARCHYBLOCK"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D:
- return "TEXTHIERARCHYEDIT";
+ return u"TEXTHIERARCHYEDIT"_ustr;
case PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D:
- return "POLYGONWAVE";
+ return u"POLYGONWAVE"_ustr;
case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D:
- return "WRONGSPELL";
+ return u"WRONGSPELL"_ustr;
case PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D:
- return "TEXTEFFECT";
+ return u"TEXTEFFECT"_ustr;
case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D:
- return "TEXTHIERARCHYBULLET";
+ return u"TEXTHIERARCHYBULLET"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D:
- return "POLYPOLYGONHAIRLINE";
+ return u"POLYPOLYGONHAIRLINE"_ustr;
case PRIMITIVE2D_ID_EXECUTEPRIMITIVE2D:
- return "EXECUTE";
+ return u"EXECUTE"_ustr;
case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D:
- return "PAGEPREVIEW";
+ return u"PAGEPREVIEW"_ustr;
case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D:
- return "STRUCTURETAG";
+ return u"STRUCTURETAG"_ustr;
case PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D:
- return "BORDERLINE";
+ return u"BORDERLINE"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D:
- return "POLYPOLYGONMARKER";
+ return u"POLYPOLYGONMARKER"_ustr;
case PRIMITIVE2D_ID_HITTESTPRIMITIVE2D:
- return "HITTEST";
+ return u"HITTEST"_ustr;
case PRIMITIVE2D_ID_INVERTPRIMITIVE2D:
- return "INVERT";
+ return u"INVERT"_ustr;
case PRIMITIVE2D_ID_DISCRETEBITMAPPRIMITIVE2D:
- return "DISCRETEBITMAP";
+ return u"DISCRETEBITMAP"_ustr;
case PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D:
- return "WALLPAPERBITMAP";
+ return u"WALLPAPERBITMAP"_ustr;
case PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D:
- return "TEXTLINE";
+ return u"TEXTLINE"_ustr;
case PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D:
- return "TEXTCHARACTERSTRIKEOUT";
+ return u"TEXTCHARACTERSTRIKEOUT"_ustr;
case PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D:
- return "TEXTGEOMETRYSTRIKEOUT";
+ return u"TEXTGEOMETRYSTRIKEOUT"_ustr;
case PRIMITIVE2D_ID_EPSPRIMITIVE2D:
- return "EPS";
+ return u"EPS"_ustr;
case PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D:
- return "DISCRETESHADOW";
+ return u"DISCRETESHADOW"_ustr;
case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D:
- return "HIDDENGEOMETRY";
+ return u"HIDDENGEOMETRY"_ustr;
case PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D:
- return "SVGLINEARGRADIENT";
+ return u"SVGLINEARGRADIENT"_ustr;
case PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D:
- return "SVGRADIALGRADIENT";
+ return u"SVGRADIALGRADIENT"_ustr;
case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D:
- return "SVGLINEARATOM";
+ return u"SVGLINEARATOM"_ustr;
case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D:
- return "SVGRADIALATOM";
+ return u"SVGRADIALATOM"_ustr;
case PRIMITIVE2D_ID_CROPPRIMITIVE2D:
- return "CROP";
+ return u"CROP"_ustr;
case PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D:
- return "PATTERNFILL";
+ return u"PATTERNFILL"_ustr;
case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D:
- return "OBJECTINFO";
+ return u"OBJECTINFO"_ustr;
case PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D:
- return "POLYPOLYGONSELECTION";
+ return u"POLYPOLYGONSELECTION"_ustr;
case PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D:
- return "PAGEHIERARCHY";
+ return u"PAGEHIERARCHY"_ustr;
case PRIMITIVE2D_ID_GLOWPRIMITIVE2D:
- return "GLOWPRIMITIVE";
+ return u"GLOWPRIMITIVE"_ustr;
case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D:
- return "SOFTEDGEPRIMITIVE";
+ return u"SOFTEDGEPRIMITIVE"_ustr;
+ case PRIMITIVE2D_ID_LINERECTANGLEPRIMITIVE2D:
+ return u"LINERECTANGLEPRIMITIVE"_ustr;
+ case PRIMITIVE2D_ID_FILLEDRECTANGLEPRIMITIVE2D:
+ return u"FILLEDRECTANGLEPRIMITIVE"_ustr;
+ case PRIMITIVE2D_ID_SINGLELINEPRIMITIVE2D:
+ return u"SINGLELINEPRIMITIVE"_ustr;
+ case PRIMITIVE2D_ID_EXCLUSIVEEDITVIEWPRIMITIVE2D:
+ return u"EXCLUSIVEEDITVIEWPRIMITIVE2D"_ustr;
+ case PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D:
+ return u"ANIMATEDGRAPHICPRIMITIVE2D"_ustr;
+ case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D:
+ return u"POLYPOLYGONRGBAPRIMITIVE2D"_ustr;
+ case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D:
+ return u"BITMAPALPHAPRIMITIVE2D"_ustr;
+ case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+ return u"POLYPOLYGONALPHAGRADIENTPRIMITIVE2D"_ustr;
+ case PRIMITIVE2D_ID_TEXTHIERARCHYEMPHASISMARKPRIMITIVE2D:
+ return u"TEXTHIERARCHYEMPHASISMARKPRIMITIVE2D"_ustr;
default:
return OUString::number((nId >> 16) & 0xFF) + "|" + OUString::number(nId & 0xFF);
}
diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
index d2c8d4a6571a..87f524180fbe 100644
--- a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
@@ -37,9 +37,9 @@ namespace drawinglayer::primitive2d
AnimatedSwitchPrimitive2D::AnimatedSwitchPrimitive2D(
const animation::AnimationEntry& rAnimationEntry,
- const Primitive2DContainer& rChildren,
+ Primitive2DContainer&& aChildren,
bool bIsTextAnimation)
- : GroupPrimitive2D(rChildren),
+ : GroupPrimitive2D(std::move(aChildren)),
mbIsTextAnimation(bIsTextAnimation)
{
// clone given animation description
@@ -76,12 +76,14 @@ namespace drawinglayer::primitive2d
nIndex = nLen - 1;
}
- const Primitive2DReference xRef(getChildren()[nIndex], uno::UNO_SET_THROW);
- rVisitor.append(xRef);
+ rVisitor.visit(getChildren()[nIndex]);
}
// provide unique ID
- ImplPrimitive2DIDBlock(AnimatedSwitchPrimitive2D, PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D)
+ sal_uInt32 AnimatedSwitchPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -90,8 +92,8 @@ namespace drawinglayer::primitive2d
{
AnimatedBlinkPrimitive2D::AnimatedBlinkPrimitive2D(
const animation::AnimationEntry& rAnimationEntry,
- const Primitive2DContainer& rChildren)
- : AnimatedSwitchPrimitive2D(rAnimationEntry, rChildren, true/*bIsTextAnimation*/)
+ Primitive2DContainer&& aChildren)
+ : AnimatedSwitchPrimitive2D(rAnimationEntry, std::move(aChildren), true/*bIsTextAnimation*/)
{
}
@@ -109,7 +111,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(AnimatedBlinkPrimitive2D, PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D)
+ sal_uInt32 AnimatedBlinkPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -119,17 +124,16 @@ namespace drawinglayer::primitive2d
AnimatedInterpolatePrimitive2D::AnimatedInterpolatePrimitive2D(
const std::vector< basegfx::B2DHomMatrix >& rmMatrixStack,
const animation::AnimationEntry& rAnimationEntry,
- const Primitive2DContainer& rChildren)
- : AnimatedSwitchPrimitive2D(rAnimationEntry, rChildren, true/*bIsTextAnimation*/),
- maMatrixStack()
+ Primitive2DContainer&& aChildren)
+ : AnimatedSwitchPrimitive2D(rAnimationEntry, std::move(aChildren), true/*bIsTextAnimation*/)
{
// copy matrices to locally pre-decomposed matrix stack
const sal_uInt32 nCount(rmMatrixStack.size());
maMatrixStack.reserve(nCount);
- for(sal_uInt32 a(0); a < nCount; a++)
+ for(const auto& a : rmMatrixStack)
{
- maMatrixStack.emplace_back(rmMatrixStack[a]);
+ maMatrixStack.emplace_back(a);
}
}
@@ -179,8 +183,8 @@ namespace drawinglayer::primitive2d
}
// create new transform primitive reference, return new sequence
- const Primitive2DReference xRef(new TransformPrimitive2D(aTargetTransform, getChildren()));
- rVisitor.append(xRef);
+ Primitive2DReference xRef(new TransformPrimitive2D(aTargetTransform, Primitive2DContainer(getChildren())));
+ rVisitor.visit(xRef);
}
else
{
@@ -189,8 +193,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(AnimatedInterpolatePrimitive2D, PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D)
-
+ sal_uInt32 AnimatedInterpolatePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D;
+ }
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx
index ba0f47193b49..7d73cdbee4d1 100644
--- a/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx
@@ -21,6 +21,7 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
@@ -30,22 +31,39 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void BackgroundColorPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference BackgroundColorPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
- if(!rViewInformation.getViewport().isEmpty())
+ // transparency invalid or completely transparent, done
+ if(getTransparency() < 0.0 || getTransparency() >= 1.0)
+ return nullptr;
+
+ // no viewport, not visible, done
+ if(rViewInformation.getViewport().isEmpty())
+ return nullptr;
+
+ // create decompose geometry
+ const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(rViewInformation.getViewport()));
+
+ if (getTransparency() <= 0.0)
{
- const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(rViewInformation.getViewport()));
- rContainer.push_back(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), getBColor()));
+ // no transparency
+ return Primitive2DReference {
+ new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), getBColor()) };
}
+
+ // if transparent, use PolyPolygonRGBAPrimitive2D
+ return Primitive2DReference {
+ new PolyPolygonRGBAPrimitive2D(
+ basegfx::B2DPolyPolygon(aOutline),
+ getBColor(),
+ getTransparency()) };
}
BackgroundColorPrimitive2D::BackgroundColorPrimitive2D(
const basegfx::BColor& rBColor,
double fTransparency)
- : BufferedDecompositionPrimitive2D(),
- maBColor(rBColor),
- mfTransparency(fTransparency),
- maLastViewport()
+ : maBColor(rBColor),
+ mfTransparency(fTransparency)
{
}
@@ -69,15 +87,13 @@ namespace drawinglayer::primitive2d
void BackgroundColorPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- if(!getBuffered2DDecomposition().empty() && (maLastViewport != rViewInformation.getViewport()))
+ if(hasBuffered2DDecomposition() && (maLastViewport != rViewInformation.getViewport()))
{
// conditions of last local decomposition have changed, delete
- const_cast< BackgroundColorPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< BackgroundColorPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember ViewRange
const_cast< BackgroundColorPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport();
@@ -88,7 +104,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(BackgroundColorPrimitive2D, PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D)
+ sal_uInt32 BackgroundColorPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx
index ef7055ebdaa4..a2e0eaf6b6ba 100644
--- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx
@@ -19,23 +19,17 @@
#include <sal/config.h>
-#include <iterator>
-#include <utility>
-
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <drawinglayer/primitive2d/Tools.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/utils/canvastools.hxx>
-#include <comphelper/sequence.hxx>
using namespace css;
namespace drawinglayer::primitive2d
{
-BasePrimitive2D::BasePrimitive2D()
- : BasePrimitive2DImplBase(m_aMutex)
-{
-}
+BasePrimitive2D::BasePrimitive2D() {}
BasePrimitive2D::~BasePrimitive2D() {}
@@ -57,15 +51,15 @@ public:
: mrViewInformation(rViewInformation)
{
}
- virtual void append(const Primitive2DReference& r) override
+ virtual void visit(const Primitive2DReference& r) override
{
maRetval.expand(getB2DRangeFromPrimitive2DReference(r, mrViewInformation));
}
- virtual void append(const Primitive2DContainer& r) override
+ virtual void visit(const Primitive2DContainer& r) override
{
maRetval.expand(r.getB2DRange(mrViewInformation));
}
- virtual void append(Primitive2DContainer&& r) override
+ virtual void visit(Primitive2DContainer&& r) override
{
maRetval.expand(r.getB2DRange(mrViewInformation));
}
@@ -86,56 +80,27 @@ void BasePrimitive2D::get2DDecomposition(
{
}
-css::uno::Sequence<::css::uno::Reference<::css::graphic::XPrimitive2D>> SAL_CALL
+Primitive2DContainer
BasePrimitive2D::getDecomposition(const uno::Sequence<beans::PropertyValue>& rViewParameters)
{
- const geometry::ViewInformation2D aViewInformation(rViewParameters);
+ const auto aViewInformation = geometry::createViewInformation2D(rViewParameters);
Primitive2DContainer aContainer;
get2DDecomposition(aContainer, aViewInformation);
- return comphelper::containerToSequence(aContainer);
+ return aContainer;
}
-css::geometry::RealRectangle2D SAL_CALL
+css::geometry::RealRectangle2D
BasePrimitive2D::getRange(const uno::Sequence<beans::PropertyValue>& rViewParameters)
{
- const geometry::ViewInformation2D aViewInformation(rViewParameters);
+ const auto aViewInformation = geometry::createViewInformation2D(rViewParameters);
return basegfx::unotools::rectangle2DFromB2DRectangle(getB2DRange(aViewInformation));
}
-sal_Int64 SAL_CALL BasePrimitive2D::estimateUsage()
+sal_Int64 BasePrimitive2D::estimateUsage()
{
return 0; // for now ignore the objects themselves
}
-void BufferedDecompositionPrimitive2D::create2DDecomposition(
- Primitive2DContainer& /*rContainer*/,
- const geometry::ViewInformation2D& /*rViewInformation*/) const
-{
-}
-
-BufferedDecompositionPrimitive2D::BufferedDecompositionPrimitive2D()
- : BasePrimitive2D()
- , maBuffered2DDecomposition()
-{
-}
-
-void BufferedDecompositionPrimitive2D::get2DDecomposition(
- Primitive2DDecompositionVisitor& rVisitor,
- const geometry::ViewInformation2D& rViewInformation) const
-{
- ::osl::MutexGuard aGuard(m_aMutex);
-
- if (getBuffered2DDecomposition().empty())
- {
- Primitive2DContainer aNewSequence;
- create2DDecomposition(aNewSequence, rViewInformation);
- const_cast<BufferedDecompositionPrimitive2D*>(this)->setBuffered2DDecomposition(
- aNewSequence);
- }
-
- rVisitor.append(getBuffered2DDecomposition());
-}
-
} // end of namespace drawinglayer::primitive2d
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx b/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx
index f495d531d8ff..82f45be77b6f 100644
--- a/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx
@@ -20,16 +20,15 @@
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <com/sun/star/awt/XBitmap.hpp>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
-BitmapPrimitive2D::BitmapPrimitive2D(const css::uno::Reference<css::awt::XBitmap>& rXBitmap,
- const basegfx::B2DHomMatrix& rTransform)
- : BasePrimitive2D()
- , maXBitmap(rXBitmap)
- , maTransform(rTransform)
+BitmapPrimitive2D::BitmapPrimitive2D(Bitmap xXBitmap, basegfx::B2DHomMatrix aTransform)
+ : maBitmap(std::move(xXBitmap))
+ , maTransform(std::move(aTransform))
{
}
@@ -39,7 +38,7 @@ bool BitmapPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
const BitmapPrimitive2D& rCompare = static_cast<const BitmapPrimitive2D&>(rPrimitive);
- return (getXBitmap() == rCompare.getXBitmap() && getTransform() == rCompare.getTransform());
+ return (getBitmap() == rCompare.getBitmap() && getTransform() == rCompare.getTransform());
}
return false;
@@ -53,25 +52,17 @@ BitmapPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInforma
return aRetval;
}
-sal_Int64 SAL_CALL BitmapPrimitive2D::estimateUsage()
+sal_Int64 BitmapPrimitive2D::estimateUsage()
{
- if (!getXBitmap().is())
+ if (getBitmap().IsEmpty())
{
return 0;
}
-
- uno::Reference<util::XAccounting> const xAcc(getXBitmap(), uno::UNO_QUERY);
-
- if (!xAcc.is())
- {
- return 0;
- }
-
- return xAcc->estimateUsage();
+ return getBitmap().GetSizeBytes();
}
// provide unique ID
-ImplPrimitive2DIDBlock(BitmapPrimitive2D, PRIMITIVE2D_ID_BITMAPPRIMITIVE2D)
+sal_uInt32 BitmapPrimitive2D::getPrimitive2DID() const { return PRIMITIVE2D_ID_BITMAPPRIMITIVE2D; }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index b264e2c028af..79e34ec972ce 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -21,11 +21,13 @@
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <rtl/math.hxx>
#include <algorithm>
+#include <utility>
namespace drawinglayer::primitive2d
@@ -87,14 +89,14 @@ namespace drawinglayer::primitive2d
{
rContainer.push_back(
new PolygonStrokePrimitive2D(
- aPolygon,
+ std::move(aPolygon),
rLineAttribute));
}
else
{
rContainer.push_back(
new PolygonStrokePrimitive2D(
- aPolygon,
+ std::move(aPolygon),
rLineAttribute,
rStrokeAttribute));
}
@@ -112,10 +114,10 @@ namespace drawinglayer::primitive2d
return fRetval;
}
- void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference BorderLinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if (getStart().equal(getEnd()) || getBorderLines().empty())
- return;
+ return nullptr;
// get data and vectors
basegfx::B2DVector aVector(getEnd() - getStart());
@@ -124,6 +126,7 @@ namespace drawinglayer::primitive2d
const double fFullWidth(getFullWidth());
double fOffset(fFullWidth * -0.5);
+ Primitive2DContainer aContainer;
for(const auto& candidate : maBorderLines)
{
const double fWidth(candidate.getLineAttribute().getWidth());
@@ -141,7 +144,7 @@ namespace drawinglayer::primitive2d
// start and end extends lead to an edge perpendicular to the line, so we can just use
// a PolygonStrokePrimitive2D for representation
addPolygonStrokePrimitive2D(
- rContainer,
+ aContainer,
aStart - (aVector * candidate.getStartLeft()),
aEnd + (aVector * candidate.getEndLeft()),
candidate.getLineAttribute(),
@@ -162,7 +165,7 @@ namespace drawinglayer::primitive2d
aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight()));
aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight()));
- rContainer.push_back(
+ aContainer.push_back(
new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aPolygon),
candidate.getLineAttribute().getColor()));
@@ -197,7 +200,7 @@ namespace drawinglayer::primitive2d
aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight()));
}
- rContainer.push_back(
+ aContainer.push_back(
new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aPolygon),
candidate.getLineAttribute().getColor()));
@@ -226,7 +229,7 @@ namespace drawinglayer::primitive2d
aPolygon.append(aEnd + aHalfLineOffset + (aVector * fMin));
aPolygon.append(aEnd - aHalfLineOffset + (aVector * fMin));
- rContainer.push_back(
+ aContainer.push_back(
new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aPolygon),
candidate.getLineAttribute().getColor()));
@@ -236,7 +239,7 @@ namespace drawinglayer::primitive2d
}
addPolygonStrokePrimitive2D(
- rContainer,
+ aContainer,
aStrokeStart,
aStrokeEnd,
candidate.getLineAttribute(),
@@ -247,6 +250,7 @@ namespace drawinglayer::primitive2d
fOffset += fWidth;
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
bool BorderLinePrimitive2D::isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const
@@ -265,44 +269,33 @@ namespace drawinglayer::primitive2d
BorderLinePrimitive2D::BorderLinePrimitive2D(
const basegfx::B2DPoint& rStart,
const basegfx::B2DPoint& rEnd,
- const std::vector< BorderLine >& rBorderLines,
- const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute)
- : BufferedDecompositionPrimitive2D(),
- maStart(rStart),
+ std::vector< BorderLine >&& rBorderLines,
+ drawinglayer::attribute::StrokeAttribute aStrokeAttribute)
+ : maStart(rStart),
maEnd(rEnd),
- maBorderLines(rBorderLines),
- maStrokeAttribute(rStrokeAttribute)
+ maBorderLines(std::move(rBorderLines)),
+ maStrokeAttribute(std::move(aStrokeAttribute))
{
}
bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const BorderLinePrimitive2D& rCompare = static_cast<const BorderLinePrimitive2D&>(rPrimitive);
+ if(!BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ return false;
- if (getStart() == rCompare.getStart()
- && getEnd() == rCompare.getEnd()
- && getStrokeAttribute() == rCompare.getStrokeAttribute())
- {
- if (getBorderLines().size() == rCompare.getBorderLines().size())
- {
- for (size_t a(0); a < getBorderLines().size(); a++)
- {
- if (!(getBorderLines()[a] == rCompare.getBorderLines()[a]))
- {
- return false;
- }
- }
- }
- }
- }
+ const BorderLinePrimitive2D& rCompare = static_cast<const BorderLinePrimitive2D&>(rPrimitive);
- return false;
+ return (getStart() == rCompare.getStart()
+ && getEnd() == rCompare.getEnd()
+ && getStrokeAttribute() == rCompare.getStrokeAttribute()
+ && getBorderLines() == rCompare.getBorderLines());
}
// provide unique ID
- ImplPrimitive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)
+ sal_uInt32 BorderLinePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D;
+ }
Primitive2DReference tryMergeBorderLinePrimitive2D(
const BorderLinePrimitive2D* pCandidateA,
@@ -338,7 +331,7 @@ namespace drawinglayer::primitive2d
// direction has to be equal -> cross product == 0.0
const basegfx::B2DVector aVT(pCandidateA->getEnd() - pCandidateA->getStart());
const basegfx::B2DVector aVC(pCandidateB->getEnd() - pCandidateB->getStart());
- if(!rtl::math::approxEqual(0.0, aVC.cross(aVT)))
+ if(aVC.cross(aVT) != 0)
{
return Primitive2DReference();
}
@@ -415,12 +408,12 @@ namespace drawinglayer::primitive2d
}
}
- return Primitive2DReference(
+ return
new BorderLinePrimitive2D(
pCandidateA->getStart(),
pCandidateB->getEnd(),
- aMergedBorderLines,
- pCandidateA->getStrokeAttribute()));
+ std::move(aMergedBorderLines),
+ pCandidateA->getStrokeAttribute());
}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx
index c3b030dcf1ac..de20ede62c24 100644
--- a/drawinglayer/source/primitive2d/controlprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx
@@ -18,26 +18,30 @@
*/
#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <utility>
+#include <rtl/ustrbuf.hxx>
#include <vcl/virdev.hxx>
#include <vcl/svapp.hxx>
#include <com/sun/star/awt/PosSize.hpp>
-#include <vcl/bitmapex.hxx>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <vcl/bitmap.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <svtools/optionsdrawinglayer.hxx>
-#include <toolkit/awt/vclxwindow.hxx>
#include <vcl/window.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <toolkit/helper/vclunohelper.hxx>
+#include <officecfg/Office/Common.hxx>
using namespace com::sun::star;
@@ -45,7 +49,7 @@ namespace drawinglayer::primitive2d
{
void ControlPrimitive2D::createXControl()
{
- if(!(!mxXControl.is() && getControlModel().is()))
+ if(mxXControl.is() || !getControlModel().is())
return;
uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY);
@@ -53,7 +57,7 @@ namespace drawinglayer::primitive2d
if(!xSet.is())
return;
- uno::Any aValue(xSet->getPropertyValue("DefaultControl"));
+ uno::Any aValue(xSet->getPropertyValue(u"DefaultControl"_ustr));
OUString aUnoControlTypeName;
if(!(aValue >>= aUnoControlTypeName))
@@ -62,7 +66,7 @@ namespace drawinglayer::primitive2d
if(aUnoControlTypeName.isEmpty())
return;
- uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ const uno::Reference< uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() );
uno::Reference< awt::XControl > xXControl(
xContext->getServiceManager()->createInstanceWithContext(aUnoControlTypeName, xContext), uno::UNO_QUERY);
@@ -71,7 +75,7 @@ namespace drawinglayer::primitive2d
xXControl->setModel(getControlModel());
// remember XControl
- mxXControl = xXControl;
+ mxXControl = std::move(xXControl);
}
}
@@ -96,8 +100,7 @@ namespace drawinglayer::primitive2d
basegfx::B2DVector aDiscreteSize(rViewInformation.getObjectToViewTransformation() * aScale);
// limit to a maximum square size, e.g. 300x150 pixels (45000)
- const SvtOptionsDrawinglayer aDrawinglayerOpt;
- const double fDiscreteMax(aDrawinglayerOpt.GetQuadraticFormControlRenderLimit());
+ const double fDiscreteMax(officecfg::Office::Common::Drawinglayer::QuadraticFormControlRenderLimit::get());
const double fDiscreteQuadratic(aDiscreteSize.getX() * aDiscreteSize.getY());
const bool bScaleUsed(fDiscreteQuadratic > fDiscreteMax);
double fFactor(1.0);
@@ -144,26 +147,12 @@ namespace drawinglayer::primitive2d
if(xControl.is())
{
- uno::Reference< awt::XWindowPeer > xWindowPeer(xControl->getPeer());
-
- if(xWindowPeer.is())
+ uno::Reference<awt::XWindowPeer> xWindowPeer(xControl->getPeer());
+ if (xWindowPeer)
{
- VCLXWindow* pVCLXWindow = comphelper::getUnoTunnelImplementation<VCLXWindow>(xWindowPeer);
-
- if(pVCLXWindow)
- {
- VclPtr<vcl::Window> pWindow = pVCLXWindow->GetWindow();
-
- if(pWindow)
- {
- pWindow = pWindow->GetParent();
-
- if(pWindow && MapUnit::Map100thMM == pWindow->GetMapMode().GetMapUnit())
- {
- bUserIs100thmm = true;
- }
- }
- }
+ uno::Reference<awt::XVclWindowPeer> xPeerProps(xWindowPeer, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPeerProps->getProperty(u"ParentIs100thmm"_ustr); // see VCLXWindow::getProperty
+ aAny >>= bUserIs100thmm;
}
}
@@ -187,27 +176,21 @@ namespace drawinglayer::primitive2d
xControlView->draw(0, 0);
// get bitmap
- const BitmapEx aContent(aVirtualDevice->GetBitmapEx(Point(), aSizePixel));
+ const Bitmap aContent(aVirtualDevice->GetBitmap(Point(), aSizePixel));
- // to avoid scaling, use the Bitmap pixel size as primitive size
- const Size aBitmapSize(aContent.GetSizePixel());
- basegfx::B2DVector aBitmapSizeLogic(
- rViewInformation.getInverseObjectToViewTransformation() *
- basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1));
-
- if(bScaleUsed)
- {
- // if scaled adapt to scaled size
- aBitmapSizeLogic /= fFactor;
- }
+ // snap translate and scale to discrete position (pixel) to avoid sub-pixel offset and blurring further
+ basegfx::B2DVector aSnappedTranslate(basegfx::fround(rViewInformation.getObjectToViewTransformation() * aTranslate));
+ aSnappedTranslate = rViewInformation.getInverseObjectToViewTransformation() * aSnappedTranslate;
+ basegfx::B2DVector aSnappedScale(basegfx::fround(rViewInformation.getObjectToViewTransformation() * aScale));
+ aSnappedScale = rViewInformation.getInverseObjectToViewTransformation() * aSnappedScale;
// short form for scale and translate transformation
const basegfx::B2DHomMatrix aBitmapTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(
- aBitmapSizeLogic.getX(), aBitmapSizeLogic.getY(), aTranslate.getX(), aTranslate.getY()));
+ aSnappedScale.getX(), aSnappedScale.getY(), aSnappedTranslate.getX(), aSnappedTranslate.getY()));
// create primitive
xRetval = new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(aContent),
+ aContent,
aBitmapTransform);
}
catch( const uno::Exception& )
@@ -227,16 +210,16 @@ namespace drawinglayer::primitive2d
// create a gray placeholder hairline polygon in object size
basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
aObjectRange.transform(getTransform());
- const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aObjectRange));
+ basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aObjectRange));
const basegfx::BColor aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0);
// The replacement object may also get a text like 'empty group' here later
- Primitive2DReference xRetval(new PolygonHairlinePrimitive2D(aOutline, aGrayTone));
+ Primitive2DReference xRetval(new PolygonHairlinePrimitive2D(std::move(aOutline), aGrayTone));
return xRetval;
}
- void ControlPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference ControlPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
// try to create a bitmap decomposition. If that fails for some reason,
// at least create a replacement decomposition.
@@ -247,30 +230,28 @@ namespace drawinglayer::primitive2d
xReference = createPlaceholderDecomposition();
}
- rContainer.push_back(xReference);
+ return xReference;
}
ControlPrimitive2D::ControlPrimitive2D(
- const basegfx::B2DHomMatrix& rTransform,
- const uno::Reference< awt::XControlModel >& rxControlModel)
- : BufferedDecompositionPrimitive2D(),
- maTransform(rTransform),
- mxControlModel(rxControlModel),
- mxXControl(),
- maLastViewScaling()
- {
- }
-
- ControlPrimitive2D::ControlPrimitive2D(
- const basegfx::B2DHomMatrix& rTransform,
- const uno::Reference< awt::XControlModel >& rxControlModel,
- const uno::Reference< awt::XControl >& rxXControl)
- : BufferedDecompositionPrimitive2D(),
- maTransform(rTransform),
- mxControlModel(rxControlModel),
- mxXControl(rxXControl),
- maLastViewScaling()
+ basegfx::B2DHomMatrix aTransform,
+ uno::Reference< awt::XControlModel > xControlModel,
+ uno::Reference<awt::XControl> xXControl,
+ ::std::u16string_view const rTitle,
+ ::std::u16string_view const rDescription,
+ void const*const pAnchorKey)
+ : maTransform(std::move(aTransform)),
+ mxControlModel(std::move(xControlModel)),
+ mxXControl(std::move(xXControl))
+ , m_pAnchorStructureElementKey(pAnchorKey)
{
+ ::rtl::OUStringBuffer buf(rTitle);
+ if (!rTitle.empty() && !rDescription.empty())
+ {
+ buf.append(" - ");
+ }
+ buf.append(rDescription);
+ m_AltText = buf.makeStringAndClear();
}
const uno::Reference< awt::XControl >& ControlPrimitive2D::getXControl() const
@@ -286,38 +267,37 @@ namespace drawinglayer::primitive2d
bool ControlPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
// use base class compare operator
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const ControlPrimitive2D& rCompare = static_cast<const ControlPrimitive2D&>(rPrimitive);
+ if(!BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ return false;
- if(getTransform() == rCompare.getTransform())
- {
- // check if ControlModel references both are/are not
- bool bRetval(getControlModel().is() == rCompare.getControlModel().is());
+ const ControlPrimitive2D& rCompare = static_cast<const ControlPrimitive2D&>(rPrimitive);
- if(bRetval && getControlModel().is())
- {
- // both exist, check for equality
- bRetval = (getControlModel() == rCompare.getControlModel());
- }
+ if(getTransform() != rCompare.getTransform())
+ return false;
- if(bRetval)
- {
- // check if XControl references both are/are not
- bRetval = (getXControl().is() == rCompare.getXControl().is());
- }
+ // check if ControlModel references both are/are not
+ if (getControlModel().is() != rCompare.getControlModel().is())
+ return false;
- if(bRetval && getXControl().is())
- {
- // both exist, check for equality
- bRetval = (getXControl() == rCompare.getXControl());
- }
+ if(getControlModel().is())
+ {
+ // both exist, check for equality
+ if (getControlModel() != rCompare.getControlModel())
+ return false;
+ }
- return bRetval;
- }
+ // check if XControl references both are/are not
+ if (getXControl().is() != rCompare.getXControl().is())
+ return false;
+
+ if(getXControl().is())
+ {
+ // both exist, check for equality
+ if (getXControl() != rCompare.getXControl())
+ return false;
}
- return false;
+ return true;
}
basegfx::B2DRange ControlPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
@@ -328,23 +308,41 @@ namespace drawinglayer::primitive2d
return aRetval;
}
+ bool ControlPrimitive2D::isVisibleAsChildWindow() const
+ {
+ // find out if the control is already visualized as a VCL-ChildWindow
+ const uno::Reference<awt::XControl>& rXControl(getXControl());
+
+ try
+ {
+ uno::Reference<awt::XWindow2> xControlWindow(rXControl, uno::UNO_QUERY_THROW);
+ return rXControl->getPeer().is() && xControlWindow->isVisible();
+ }
+ catch (const uno::Exception&)
+ {
+ // #i116763# since there is a good alternative when the xControlView
+ // is not found and it is allowed to happen
+ }
+
+ return false;
+ }
+
void ControlPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
// this primitive is view-dependent related to the scaling. If scaling has changed,
// destroy existing decomposition. To detect change, use size of unit size in view coordinates
- ::osl::MutexGuard aGuard( m_aMutex );
const basegfx::B2DVector aNewScaling(rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
- if(!getBuffered2DDecomposition().empty())
+ if(hasBuffered2DDecomposition())
{
if(!maLastViewScaling.equal(aNewScaling))
{
// conditions of last local decomposition have changed, delete
- const_cast< ControlPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ControlPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember ViewTransformation
const_cast< ControlPrimitive2D* >(this)->maLastViewScaling = aNewScaling;
@@ -355,7 +353,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(ControlPrimitive2D, PRIMITIVE2D_ID_CONTROLPRIMITIVE2D)
+ sal_uInt32 ControlPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_CONTROLPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
index 2d780ac2645c..da28d9e41663 100644
--- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
@@ -24,6 +24,7 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -32,14 +33,14 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
CropPrimitive2D::CropPrimitive2D(
- const Primitive2DContainer& rChildren,
- const basegfx::B2DHomMatrix& rTransformation,
+ Primitive2DContainer&& aChildren,
+ basegfx::B2DHomMatrix aTransformation,
double fCropLeft,
double fCropTop,
double fCropRight,
double fCropBottom)
- : GroupPrimitive2D(rChildren),
- maTransformation(rTransformation),
+ : GroupPrimitive2D(std::move(aChildren)),
+ maTransformation(std::move(aTransformation)),
mfCropLeft(fCropLeft),
mfCropTop(fCropTop),
mfCropRight(fCropRight),
@@ -120,13 +121,13 @@ namespace drawinglayer::primitive2d
const Primitive2DReference xTransformPrimitive(
new TransformPrimitive2D(
aNewTransform,
- getChildren()));
+ Primitive2DContainer(getChildren())));
if(aUnitRange.isInside(aNewRange))
{
// the new range is completely inside the old range (unit range),
// so no masking is needed
- rVisitor.append(xTransformPrimitive);
+ rVisitor.visit(xTransformPrimitive);
}
else
{
@@ -137,15 +138,18 @@ namespace drawinglayer::primitive2d
// create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
const Primitive2DReference xMask(
new MaskPrimitive2D(
- aMaskPolyPolygon,
+ std::move(aMaskPolyPolygon),
Primitive2DContainer { xTransformPrimitive }));
- rVisitor.append(xMask);
+ rVisitor.visit(xMask);
}
}
// provide unique ID
- ImplPrimitive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D)
+ sal_uInt32 CropPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_CROPPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx b/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx
index 17d6f2301a43..610df57a95e3 100644
--- a/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx
@@ -25,18 +25,18 @@
namespace drawinglayer::primitive2d
{
- void DiscreteBitmapPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference DiscreteBitmapPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
// use getViewTransformation() and getObjectTransformation() from
// ObjectAndViewTransformationDependentPrimitive2D to create a BitmapPrimitive2D
// with the correct mapping
- if(getBitmapEx().IsEmpty())
- return;
+ if(getBitmap().IsEmpty())
+ return nullptr;
// get discrete size
- const Size& rSizePixel = getBitmapEx().GetSizePixel();
- const basegfx::B2DVector aDiscreteSize(rSizePixel.Width(), rSizePixel.Height());
+ const Size aSizePixel = getBitmap().GetSizePixel();
+ const basegfx::B2DVector aDiscreteSize(aSizePixel.Width(), aSizePixel.Height());
// get inverse ViewTransformation
basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation());
@@ -64,17 +64,16 @@ namespace drawinglayer::primitive2d
aObjectTransform = aInverseObjectTransformation * aObjectTransform;
// create BitmapPrimitive2D with now object-local coordinate data
- rContainer.push_back(
+ return
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()),
- aObjectTransform));
+ getBitmap(),
+ aObjectTransform);
}
DiscreteBitmapPrimitive2D::DiscreteBitmapPrimitive2D(
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
const basegfx::B2DPoint& rTopLeft)
- : ObjectAndViewTransformationDependentPrimitive2D(),
- maBitmapEx(rBitmapEx),
+ : maBitmap(rBitmap),
maTopLeft(rTopLeft)
{
}
@@ -85,7 +84,7 @@ namespace drawinglayer::primitive2d
{
const DiscreteBitmapPrimitive2D& rCompare = static_cast<const DiscreteBitmapPrimitive2D&>(rPrimitive);
- return (getBitmapEx() == rCompare.getBitmapEx()
+ return (getBitmap() == rCompare.getBitmap()
&& getTopLeft() == rCompare.getTopLeft());
}
@@ -93,7 +92,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(DiscreteBitmapPrimitive2D, PRIMITIVE2D_ID_DISCRETEBITMAPPRIMITIVE2D)
+ sal_uInt32 DiscreteBitmapPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_DISCRETEBITMAPPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
index 3100db147345..0e48bf1ff78b 100644
--- a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx
@@ -23,37 +23,31 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <osl/diagnose.h>
#include <toolkit/helper/vclunohelper.hxx>
namespace drawinglayer::primitive2d
{
- DiscreteShadow::DiscreteShadow(const BitmapEx& rBitmapEx)
- : maBitmapEx(rBitmapEx),
- maTopLeft(),
- maTop(),
- maTopRight(),
- maRight(),
- maBottomRight(),
- maBottom(),
- maBottomLeft(),
- maLeft()
+ DiscreteShadow::DiscreteShadow(const Bitmap& rBitmap)
+ : maBitmap(rBitmap)
{
- const Size& rBitmapSize = getBitmapEx().GetSizePixel();
+ maBitmap.Invert(); // convert transparency to alpha
+ const Size aBitmapSize = getBitmap().GetSizePixel();
- if(rBitmapSize.Width() != rBitmapSize.Height() || rBitmapSize.Width() < 7)
+ if(aBitmapSize.Width() != aBitmapSize.Height() || aBitmapSize.Width() < 7)
{
OSL_ENSURE(false, "DiscreteShadowPrimitive2D: wrong bitmap format (!)");
- maBitmapEx = BitmapEx();
+ maBitmap = Bitmap();
}
}
- const BitmapEx& DiscreteShadow::getTopLeft() const
+ const Bitmap& DiscreteShadow::getTopLeft() const
{
if(maTopLeft.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maTopLeft = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maTopLeft = getBitmap();
const_cast< DiscreteShadow* >(this)->maTopLeft.Crop(
::tools::Rectangle(Point(0, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
}
@@ -61,12 +55,12 @@ namespace drawinglayer::primitive2d
return maTopLeft;
}
- const BitmapEx& DiscreteShadow::getTop() const
+ const Bitmap& DiscreteShadow::getTop() const
{
if(maTop.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maTop = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maTop = getBitmap();
const_cast< DiscreteShadow* >(this)->maTop.Crop(
::tools::Rectangle(Point((nQuarter * 2) + 1, 0), Size(1, nQuarter)));
}
@@ -74,12 +68,12 @@ namespace drawinglayer::primitive2d
return maTop;
}
- const BitmapEx& DiscreteShadow::getTopRight() const
+ const Bitmap& DiscreteShadow::getTopRight() const
{
if(maTopRight.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maTopRight = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maTopRight = getBitmap();
const_cast< DiscreteShadow* >(this)->maTopRight.Crop(
::tools::Rectangle(Point((nQuarter * 2) + 2, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
}
@@ -87,12 +81,12 @@ namespace drawinglayer::primitive2d
return maTopRight;
}
- const BitmapEx& DiscreteShadow::getRight() const
+ const Bitmap& DiscreteShadow::getRight() const
{
if(maRight.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maRight = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maRight = getBitmap();
const_cast< DiscreteShadow* >(this)->maRight.Crop(
::tools::Rectangle(Point((nQuarter * 3) + 3, (nQuarter * 2) + 1), Size(nQuarter, 1)));
}
@@ -100,12 +94,12 @@ namespace drawinglayer::primitive2d
return maRight;
}
- const BitmapEx& DiscreteShadow::getBottomRight() const
+ const Bitmap& DiscreteShadow::getBottomRight() const
{
if(maBottomRight.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maBottomRight = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maBottomRight = getBitmap();
const_cast< DiscreteShadow* >(this)->maBottomRight.Crop(
::tools::Rectangle(Point((nQuarter * 2) + 2, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
}
@@ -113,12 +107,12 @@ namespace drawinglayer::primitive2d
return maBottomRight;
}
- const BitmapEx& DiscreteShadow::getBottom() const
+ const Bitmap& DiscreteShadow::getBottom() const
{
if(maBottom.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maBottom = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maBottom = getBitmap();
const_cast< DiscreteShadow* >(this)->maBottom.Crop(
::tools::Rectangle(Point((nQuarter * 2) + 1, (nQuarter * 3) + 3), Size(1, nQuarter)));
}
@@ -126,12 +120,12 @@ namespace drawinglayer::primitive2d
return maBottom;
}
- const BitmapEx& DiscreteShadow::getBottomLeft() const
+ const Bitmap& DiscreteShadow::getBottomLeft() const
{
if(maBottomLeft.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maBottomLeft = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maBottomLeft = getBitmap();
const_cast< DiscreteShadow* >(this)->maBottomLeft.Crop(
::tools::Rectangle(Point(0, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
}
@@ -139,12 +133,12 @@ namespace drawinglayer::primitive2d
return maBottomLeft;
}
- const BitmapEx& DiscreteShadow::getLeft() const
+ const Bitmap& DiscreteShadow::getLeft() const
{
if(maLeft.IsEmpty())
{
- const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
- const_cast< DiscreteShadow* >(this)->maLeft = getBitmapEx();
+ const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
+ const_cast< DiscreteShadow* >(this)->maLeft = getBitmap();
const_cast< DiscreteShadow* >(this)->maLeft.Crop(
::tools::Rectangle(Point(0, (nQuarter * 2) + 1), Size(nQuarter, 1)));
}
@@ -157,14 +151,14 @@ namespace drawinglayer::primitive2d
namespace drawinglayer::primitive2d
{
- void DiscreteShadowPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference DiscreteShadowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
Primitive2DContainer xRetval;
- if(getDiscreteShadow().getBitmapEx().IsEmpty())
- return;
+ if(getDiscreteShadow().getBitmap().IsEmpty())
+ return nullptr;
- const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2);
+ const sal_Int32 nQuarter((getDiscreteShadow().getBitmap().GetSizePixel().Width() - 3) >> 2);
const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0));
const double fSingleX(getDiscreteUnit() / aScale.getX());
const double fSingleY(getDiscreteUnit() / aScale.getY());
@@ -176,97 +170,96 @@ namespace drawinglayer::primitive2d
xRetval.resize(8);
// TopLeft
- xRetval[0] = Primitive2DReference(
+ xRetval[0] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopLeft()),
+ getDiscreteShadow().getTopLeft(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBigLenX,
fBigLenY,
-fBorderX,
- -fBorderY)));
+ -fBorderY));
// Top
- xRetval[1] = Primitive2DReference(
+ xRetval[1] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTop()),
+ getDiscreteShadow().getTop(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
fBorderY,
fBorderX + fSingleX,
- -fBorderY)));
+ -fBorderY));
// TopRight
- xRetval[2] = Primitive2DReference(
+ xRetval[2] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopRight()),
+ getDiscreteShadow().getTopRight(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBigLenX,
fBigLenY,
1.0 - fBorderX,
- -fBorderY)));
+ -fBorderY));
// Right
- xRetval[3] = Primitive2DReference(
+ xRetval[3] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getRight()),
+ getDiscreteShadow().getRight(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBorderX,
1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
1.0 + fSingleX,
- fBorderY + fSingleY)));
+ fBorderY + fSingleY));
// BottomRight
- xRetval[4] = Primitive2DReference(
+ xRetval[4] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomRight()),
+ getDiscreteShadow().getBottomRight(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBigLenX,
fBigLenY,
1.0 - (fBorderX + fSingleX) + fSingleX,
- 1.0 - (fBorderY + fSingleY) + fSingleY)));
+ 1.0 - (fBorderY + fSingleY) + fSingleY));
// Bottom
- xRetval[5] = Primitive2DReference(
+ xRetval[5] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottom()),
+ getDiscreteShadow().getBottom(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
fBorderY,
fBorderX + fSingleX,
- 1.0 + fSingleY)));
+ 1.0 + fSingleY));
// BottomLeft
- xRetval[6] = Primitive2DReference(
+ xRetval[6] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomLeft()),
+ getDiscreteShadow().getBottomLeft(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBigLenX,
fBigLenY,
-fBorderX,
- 1.0 - fBorderY)));
+ 1.0 - fBorderY));
// Left
- xRetval[7] = Primitive2DReference(
+ xRetval[7] =
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getLeft()),
+ getDiscreteShadow().getLeft(),
basegfx::utils::createScaleTranslateB2DHomMatrix(
fBorderX,
1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
-fBorderX,
- fBorderY + fSingleY)));
+ fBorderY + fSingleY));
// put all in object transformation to get to target positions
- rContainer.push_back(
+ return
new TransformPrimitive2D(
getTransform(),
- xRetval));
+ std::move(xRetval));
}
DiscreteShadowPrimitive2D::DiscreteShadowPrimitive2D(
const basegfx::B2DHomMatrix& rTransform,
const DiscreteShadow& rDiscreteShadow)
- : DiscreteMetricDependentPrimitive2D(),
- maTransform(rTransform),
+ : maTransform(rTransform),
maDiscreteShadow(rDiscreteShadow)
{
}
@@ -286,7 +279,7 @@ namespace drawinglayer::primitive2d
basegfx::B2DRange DiscreteShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
{
- if(getDiscreteShadow().getBitmapEx().IsEmpty())
+ if(getDiscreteShadow().getBitmap().IsEmpty())
{
// no graphics without valid bitmap definition
return basegfx::B2DRange();
@@ -299,7 +292,7 @@ namespace drawinglayer::primitive2d
// extract discrete shadow size and grow
const basegfx::B2DVector aScale(rViewInformation.getViewTransformation() * basegfx::B2DVector(1.0, 1.0));
- const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2);
+ const sal_Int32 nQuarter((getDiscreteShadow().getBitmap().GetSizePixel().Width() - 3) >> 2);
const double fGrowX((1.0 / aScale.getX()) * nQuarter);
const double fGrowY((1.0 / aScale.getY()) * nQuarter);
aRetval.grow(std::max(fGrowX, fGrowY));
@@ -309,7 +302,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(DiscreteShadowPrimitive2D, PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D)
+ sal_uInt32 DiscreteShadowPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx b/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx
index e38afeb4d612..6c7ebd113a43 100644
--- a/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx
@@ -21,11 +21,12 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/color/bcolor.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/geometry/viewinformation3d.hxx>
#include <processor3d/shadow3dextractor.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -35,8 +36,6 @@ namespace drawinglayer::primitive2d
{
bool Embedded3DPrimitive2D::impGetShadow3D() const
{
- osl::MutexGuard aGuard( m_aMutex );
-
// create on demand
if(!mbShadow3DChecked && !getChildren3D().empty())
{
@@ -60,31 +59,28 @@ namespace drawinglayer::primitive2d
return !maShadowPrimitives.empty();
}
- void Embedded3DPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference Embedded3DPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
// use info to create a yellow 2d rectangle, similar to empty 3d scenes and/or groups
const basegfx::B2DRange aLocal2DRange(getB2DRange(rViewInformation));
- const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aLocal2DRange));
+ basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aLocal2DRange));
const basegfx::BColor aYellow(1.0, 1.0, 0.0);
- rContainer.push_back(new PolygonHairlinePrimitive2D(aOutline, aYellow));
+ return new PolygonHairlinePrimitive2D(std::move(aOutline), aYellow);
}
Embedded3DPrimitive2D::Embedded3DPrimitive2D(
- const primitive3d::Primitive3DContainer& rxChildren3D,
- const basegfx::B2DHomMatrix& rObjectTransformation,
- const geometry::ViewInformation3D& rViewInformation3D,
+ primitive3d::Primitive3DContainer aChildren3D,
+ basegfx::B2DHomMatrix aObjectTransformation,
+ geometry::ViewInformation3D aViewInformation3D,
const basegfx::B3DVector& rLightNormal,
double fShadowSlant,
const basegfx::B3DRange& rScene3DRange)
- : BufferedDecompositionPrimitive2D(),
- mxChildren3D(rxChildren3D),
- maObjectTransformation(rObjectTransformation),
- maViewInformation3D(rViewInformation3D),
+ : mxChildren3D(std::move(aChildren3D)),
+ maObjectTransformation(std::move(aObjectTransformation)),
+ maViewInformation3D(std::move(aViewInformation3D)),
maLightNormal(rLightNormal),
mfShadowSlant(fShadowSlant),
maScene3DRange(rScene3DRange),
- maShadowPrimitives(),
- maB2DRange(),
mbShadow3DChecked(false)
{
maLightNormal.normalize();
@@ -141,7 +137,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(Embedded3DPrimitive2D, PRIMITIVE2D_ID_EMBEDDED3DPRIMITIVE2D)
+ sal_uInt32 Embedded3DPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_EMBEDDED3DPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/epsprimitive2d.cxx b/drawinglayer/source/primitive2d/epsprimitive2d.cxx
index b519547c00d7..760d5d764c41 100644
--- a/drawinglayer/source/primitive2d/epsprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/epsprimitive2d.cxx
@@ -20,10 +20,11 @@
#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <utility>
namespace drawinglayer::primitive2d
{
- void EpsPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference EpsPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const GDIMetaFile& rSubstituteContent = getMetaFile();
@@ -33,20 +34,20 @@ namespace drawinglayer::primitive2d
// To really use the Eps data, a renderer has to know and interpret this primitive
// directly.
- rContainer.push_back(
+ return
new MetafilePrimitive2D(
getEpsTransform(),
- rSubstituteContent));
+ rSubstituteContent);
}
+ return nullptr;
}
EpsPrimitive2D::EpsPrimitive2D(
- const basegfx::B2DHomMatrix& rEpsTransform,
- const GfxLink& rGfxLink,
+ basegfx::B2DHomMatrix aEpsTransform,
+ GfxLink aGfxLink,
const GDIMetaFile& rMetaFile)
- : BufferedDecompositionPrimitive2D(),
- maEpsTransform(rEpsTransform),
- maGfxLink(rGfxLink),
+ : maEpsTransform(std::move(aEpsTransform)),
+ maGfxLink(std::move(aGfxLink)),
maMetaFile(rMetaFile)
{
}
@@ -75,7 +76,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(EpsPrimitive2D, PRIMITIVE2D_ID_EPSPRIMITIVE2D)
+ sal_uInt32 EpsPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_EPSPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/exclusiveeditviewprimitive2d.cxx b/drawinglayer/source/primitive2d/exclusiveeditviewprimitive2d.cxx
new file mode 100644
index 000000000000..a510b97b5b02
--- /dev/null
+++ b/drawinglayer/source/primitive2d/exclusiveeditviewprimitive2d.cxx
@@ -0,0 +1,55 @@
+/* -*- 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 <drawinglayer/primitive2d/exclusiveeditviewprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+
+using namespace com::sun::star;
+
+namespace drawinglayer::primitive2d
+{
+ExclusiveEditViewPrimitive2D::ExclusiveEditViewPrimitive2D(Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
+{
+}
+
+basegfx::B2DRange
+ExclusiveEditViewPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ return getChildren().getB2DRange(rViewInformation);
+}
+
+void ExclusiveEditViewPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ // check if EditView is visualized. if yes, use content by calling parent class. if no, suppress it
+ if (rViewInformation.getEditViewActive())
+ GroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+}
+
+// provide unique ID
+sal_uInt32 ExclusiveEditViewPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_EXCLUSIVEEDITVIEWPRIMITIVE2D;
+}
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
index fba740e833c5..8c2e339f8fbb 100644
--- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
@@ -23,6 +23,11 @@
#include <texture/texture.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <utility>
+#include <algorithm>
using namespace com::sun::star;
@@ -30,293 +35,330 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void FillGradientPrimitive2D::generateMatricesAndColors(
- std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor) const
+ // Get the OuterColor. Take into account that for css::awt::GradientStyle_AXIAL
+ // this is the last one due to inverted gradient usage (see constructor there)
+ basegfx::BColor FillGradientPrimitive2D::getOuterColor() const
{
- rEntries.clear();
+ if (getFillGradient().getColorStops().empty())
+ return basegfx::BColor();
- // make sure steps is not too high/low
- const basegfx::BColor aStart(getFillGradient().getStartColor());
- const basegfx::BColor aEnd(getFillGradient().getEndColor());
- const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
- sal_uInt32 nSteps(getFillGradient().getSteps());
+ if (css::awt::GradientStyle_AXIAL == getFillGradient().getStyle())
+ return getFillGradient().getColorStops().back().getStopColor();
- if(nSteps == 0)
- {
- nSteps = nMaxSteps;
- }
-
- if(nSteps < 2)
- {
- nSteps = 2;
- }
+ return getFillGradient().getColorStops().front().getStopColor();
+ }
- if(nSteps > nMaxSteps)
+ // Get the needed UnitPolygon dependent on the GradientStyle
+ basegfx::B2DPolygon FillGradientPrimitive2D::getUnitPolygon() const
+ {
+ if (css::awt::GradientStyle_RADIAL == getFillGradient().getStyle()
+ || css::awt::GradientStyle_ELLIPTICAL == getFillGradient().getStyle())
{
- nSteps = nMaxSteps;
+ return basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), 1.0);
}
- nSteps = std::max(sal_uInt32(1), nSteps);
+ return basegfx::utils::createPolygonFromRect(basegfx::B2DRange(-1.0, -1.0, 1.0, 1.0));
+ }
+ void FillGradientPrimitive2D::generateMatricesAndColors(
+ std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)> aCallback) const
+ {
switch(getFillGradient().getStyle())
{
- case attribute::GradientStyle::Linear:
+ default: // GradientStyle_MAKE_FIXED_SIZE
+ case css::awt::GradientStyle_LINEAR:
{
texture::GeoTexSvxGradientLinear aGradient(
getDefinitionRange(),
getOutputRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getAngle());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
- case attribute::GradientStyle::Axial:
+ case css::awt::GradientStyle_AXIAL:
{
texture::GeoTexSvxGradientAxial aGradient(
getDefinitionRange(),
getOutputRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getAngle());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
- case attribute::GradientStyle::Radial:
+ case css::awt::GradientStyle_RADIAL:
{
texture::GeoTexSvxGradientRadial aGradient(
getDefinitionRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getOffsetX(),
getFillGradient().getOffsetY());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
- case attribute::GradientStyle::Elliptical:
+ case css::awt::GradientStyle_ELLIPTICAL:
{
texture::GeoTexSvxGradientElliptical aGradient(
getDefinitionRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getOffsetX(),
getFillGradient().getOffsetY(),
getFillGradient().getAngle());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
- case attribute::GradientStyle::Square:
+ case css::awt::GradientStyle_SQUARE:
{
texture::GeoTexSvxGradientSquare aGradient(
getDefinitionRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getOffsetX(),
getFillGradient().getOffsetY(),
getFillGradient().getAngle());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
- case attribute::GradientStyle::Rect:
+ case css::awt::GradientStyle_RECT:
{
texture::GeoTexSvxGradientRect aGradient(
getDefinitionRange(),
- aStart,
- aEnd,
- nSteps,
+ getFillGradient().getSteps(),
+ getFillGradient().getColorStops(),
getFillGradient().getBorder(),
getFillGradient().getOffsetX(),
getFillGradient().getOffsetY(),
getFillGradient().getAngle());
- aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
+ aGradient.appendTransformationsAndColors(aCallback);
break;
}
}
}
- void FillGradientPrimitive2D::createOverlappingFill(
- Primitive2DContainer& rContainer,
- const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
- const basegfx::BColor& rOuterColor,
- const basegfx::B2DPolygon& rUnitPolygon) const
+ Primitive2DReference FillGradientPrimitive2D::createFill(bool bOverlapping) const
{
- // create solid fill with outmost color
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- basegfx::B2DPolyPolygon(
- basegfx::utils::createPolygonFromRect(getOutputRange())),
- rOuterColor));
-
- // create solid fill steps
- for(size_t a(0); a < rEntries.size(); a++)
+ Primitive2DContainer aContainer;
+ if (bOverlapping)
{
- // create part polygon
- basegfx::B2DPolygon aNewPoly(rUnitPolygon);
-
- aNewPoly.transform(rEntries[a].maB2DHomMatrix);
-
- // create solid fill
- rContainer.push_back(
+ // OverlappingFill: create solid fill with outmost color
+ aContainer.push_back(
new PolyPolygonColorPrimitive2D(
- basegfx::B2DPolyPolygon(aNewPoly),
- rEntries[a].maBColor));
- }
- }
-
- void FillGradientPrimitive2D::createNonOverlappingFill(
- Primitive2DContainer& rContainer,
- const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
- const basegfx::BColor& rOuterColor,
- const basegfx::B2DPolygon& rUnitPolygon) const
- {
- // get outmost visible range from object
- basegfx::B2DRange aOutmostRange(getOutputRange());
- basegfx::B2DPolyPolygon aCombinedPolyPoly;
-
- if(!rEntries.empty())
- {
- // extend aOutmostRange with first polygon
- basegfx::B2DPolygon aFirstPoly(rUnitPolygon);
-
- aFirstPoly.transform(rEntries[0].maB2DHomMatrix);
- aCombinedPolyPoly.append(aFirstPoly);
- aOutmostRange.expand(aFirstPoly.getB2DRange());
+ basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect(getOutputRange())),
+ getOuterColor()));
+
+ // create solid fill steps by providing callback as lambda
+ auto aCallback([&aContainer,this](
+ const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::BColor& rColor)
+ {
+ // create part polygon
+ basegfx::B2DPolygon aNewPoly(getUnitPolygon());
+ aNewPoly.transform(rMatrix);
+
+ // create solid fill
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aNewPoly),
+ rColor));
+ });
+
+ // call value generator to trigger callbacks
+ generateMatricesAndColors(aCallback);
}
-
- // add outmost range to combined polypolygon (in 1st place), create first primitive
- aCombinedPolyPoly.insert(0, basegfx::utils::createPolygonFromRect(aOutmostRange));
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- aCombinedPolyPoly,
- rOuterColor));
-
- if(rEntries.empty())
- return;
-
- // reuse first polygon, it's the second one
- aCombinedPolyPoly.remove(0);
-
- for(size_t a(0); a < rEntries.size() - 1; a++)
+ else
{
- // create next inner polygon, combined with last one
- basegfx::B2DPolygon aNextPoly(rUnitPolygon);
-
- aNextPoly.transform(rEntries[a + 1].maB2DHomMatrix);
- aCombinedPolyPoly.append(aNextPoly);
-
- // create primitive with correct color
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- aCombinedPolyPoly,
- rEntries[a].maBColor));
-
- // reuse inner polygon, it's the 2nd one
- aCombinedPolyPoly.remove(0);
+ // NonOverlappingFill
+ if (getFillGradient().getColorStops().size() < 2)
+ {
+ // not really a gradient, we need to create a start primitive
+ // entry using the single color and the covered area
+ const basegfx::B2DRange aOutmostRange(getOutputRange());
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aOutmostRange)),
+ getOuterColor()));
+ }
+ else
+ {
+ // gradient with stops, prepare CombinedPolyPoly, use callback
+ basegfx::B2DPolyPolygon aCombinedPolyPoly;
+ basegfx::BColor aLastColor;
+
+ auto aCallback([&aContainer,&aCombinedPolyPoly,&aLastColor,this](
+ const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::BColor& rColor)
+ {
+ if (aContainer.empty())
+ {
+ // 1st callback, init CombinedPolyPoly & create 1st entry
+ basegfx::B2DRange aOutmostRange(getOutputRange());
+
+ // expand aOutmostRange with transformed first polygon
+ // to ensure confinement
+ basegfx::B2DPolygon aFirstPoly(getUnitPolygon());
+ aFirstPoly.transform(rMatrix);
+ aOutmostRange.expand(aFirstPoly.getB2DRange());
+
+ // build 1st combined polygon; outmost range 1st, then
+ // the shaped, transformed polygon
+ aCombinedPolyPoly.append(basegfx::utils::createPolygonFromRect(aOutmostRange));
+ aCombinedPolyPoly.append(aFirstPoly);
+
+ // create first primitive
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aCombinedPolyPoly,
+ getOuterColor()));
+
+ // save first polygon for re-use in next call, it's the second
+ // one, so remove 1st
+ aCombinedPolyPoly.remove(0);
+
+ // remember color for next primitive creation
+ aLastColor = rColor;
+ }
+ else
+ {
+ // regular n-th callback, create combined entry by re-using
+ // CombinedPolyPoly and aLastColor
+ basegfx::B2DPolygon aNextPoly(getUnitPolygon());
+ aNextPoly.transform(rMatrix);
+ aCombinedPolyPoly.append(aNextPoly);
+
+ // create primitive with correct color
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aCombinedPolyPoly,
+ aLastColor));
+
+ // prepare re-use of inner polygon, save color
+ aCombinedPolyPoly.remove(0);
+ aLastColor = rColor;
+ }
+ });
+
+ // call value generator to trigger callbacks
+ generateMatricesAndColors(aCallback);
+
+ // add last inner polygon with last color
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(
+ std::move(aCombinedPolyPoly),
+ aLastColor));
+ }
}
-
- // add last inner polygon with last color
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- aCombinedPolyPoly,
- rEntries[rEntries.size() - 1].maBColor));
+ return new GroupPrimitive2D(std::move(aContainer));
}
- void FillGradientPrimitive2D::createFill(Primitive2DContainer& rContainer, bool bOverlapping) const
+ Primitive2DReference FillGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
- // prepare shape of the Unit Polygon
- basegfx::B2DPolygon aUnitPolygon;
-
- switch(getFillGradient().getStyle())
+ // SDPR: support alpha directly now. If a primitive processor
+ // cannot deal with it, use it's decomposition. For that purpose
+ // this decomposition has two stages now: This 1st one will
+ // (if needed) separate content and alpha into a TransparencePrimitive2D
+ // and (if needed) embed that to a UnifiedTransparencePrimitive2D,
+ // so all processors can work as before
+ if (hasAlphaGradient() || hasTransparency())
{
- case attribute::GradientStyle::Radial:
- case attribute::GradientStyle::Elliptical:
+ Primitive2DReference aRetval(
+ new FillGradientPrimitive2D(
+ getOutputRange(),
+ getDefinitionRange(),
+ getFillGradient()));
+
+ if (hasAlphaGradient())
{
- aUnitPolygon = basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), 1.0);
- break;
+ Primitive2DContainer aAlpha{ new FillGradientPrimitive2D(
+ getOutputRange(),
+ getDefinitionRange(),
+ getAlphaGradient()) };
+
+ aRetval = new TransparencePrimitive2D(Primitive2DContainer{ aRetval }, std::move(aAlpha));
}
- default: // GradientStyle::Linear, attribute::GradientStyle::Axial, attribute::GradientStyle::Square, attribute::GradientStyle::Rect
+
+ if (hasTransparency())
{
- aUnitPolygon = basegfx::utils::createPolygonFromRect(basegfx::B2DRange(-1.0, -1.0, 1.0, 1.0));
- break;
+ aRetval = new UnifiedTransparencePrimitive2D(Primitive2DContainer{ aRetval }, getTransparency());
}
- }
- // get the transform matrices and colors (where colors
- // will have one more entry that matrices)
- std::vector< drawinglayer::texture::B2DHomMatrixAndBColor > aEntries;
- basegfx::BColor aOuterColor;
-
- generateMatricesAndColors(aEntries, aOuterColor);
-
- if(bOverlapping)
- {
- createOverlappingFill(rContainer, aEntries, aOuterColor, aUnitPolygon);
+ return aRetval;
}
- else
- {
- createNonOverlappingFill(rContainer, aEntries, aOuterColor, aUnitPolygon);
- }
- }
- void FillGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
// default creates overlapping fill which works with AntiAliasing and without.
// The non-overlapping version does not create single filled polygons, but
// PolyPolygons where each one describes a 'ring' for the gradient such
// that the rings will not overlap. This is useful for the old XOR-paint
// 'trick' of VCL which is recorded in Metafiles; so this version may be
// used from the MetafilePrimitive2D in its decomposition.
-
if(!getFillGradient().isDefault())
{
- createFill(rContainer, /*bOverlapping*/true);
+ return createFill(/*bOverlapping*/true);
}
+
+ return nullptr;
}
FillGradientPrimitive2D::FillGradientPrimitive2D(
const basegfx::B2DRange& rOutputRange,
const attribute::FillGradientAttribute& rFillGradient)
- : BufferedDecompositionPrimitive2D(),
- maOutputRange(rOutputRange),
- maDefinitionRange(rOutputRange),
- maFillGradient(rFillGradient)
+ : maOutputRange(rOutputRange)
+ , maDefinitionRange(rOutputRange)
+ , maFillGradient(rFillGradient)
+ , maAlphaGradient()
+ , mfTransparency(0.0)
{
}
FillGradientPrimitive2D::FillGradientPrimitive2D(
const basegfx::B2DRange& rOutputRange,
const basegfx::B2DRange& rDefinitionRange,
- const attribute::FillGradientAttribute& rFillGradient)
- : BufferedDecompositionPrimitive2D(),
- maOutputRange(rOutputRange),
- maDefinitionRange(rDefinitionRange),
- maFillGradient(rFillGradient)
+ const attribute::FillGradientAttribute& rFillGradient,
+ const attribute::FillGradientAttribute* pAlphaGradient,
+ double fTransparency)
+ : maOutputRange(rOutputRange)
+ , maDefinitionRange(rDefinitionRange)
+ , maFillGradient(rFillGradient)
+ , maAlphaGradient()
+ , mfTransparency(fTransparency)
{
+ // copy alpha gradient if we got one
+ if (nullptr != pAlphaGradient)
+ maAlphaGradient = *pAlphaGradient;
}
bool FillGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const FillGradientPrimitive2D& rCompare = static_cast<const FillGradientPrimitive2D&>(rPrimitive);
+ if(!BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ return false;
- return (getOutputRange() == rCompare.getOutputRange()
- && getDefinitionRange() == rCompare.getDefinitionRange()
- && getFillGradient() == rCompare.getFillGradient());
- }
+ const FillGradientPrimitive2D& rCompare(static_cast<const FillGradientPrimitive2D&>(rPrimitive));
+
+ if (getOutputRange() != rCompare.getOutputRange())
+ return false;
+
+ if (getDefinitionRange() != rCompare.getDefinitionRange())
+ return false;
+
+ if (getFillGradient() != rCompare.getFillGradient())
+ return false;
- return false;
+ if (maAlphaGradient != rCompare.maAlphaGradient)
+ return false;
+
+ if (!basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()))
+ return false;
+
+ return true;
}
basegfx::B2DRange FillGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
@@ -326,7 +368,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(FillGradientPrimitive2D, PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D)
+ sal_uInt32 FillGradientPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
index 708b3f2ce48d..5ef71c97aa33 100644
--- a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
@@ -24,7 +24,9 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <primitive2d/graphicprimitivehelper2d.hxx>
+#include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
+#include <utility>
+#include <vcl/graph.hxx>
using namespace com::sun::star;
@@ -32,24 +34,25 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void FillGraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference FillGraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const attribute::FillGraphicAttribute& rAttribute = getFillGraphic();
if(rAttribute.isDefault())
- return;
+ return nullptr;
const Graphic& rGraphic = rAttribute.getGraphic();
if(GraphicType::Bitmap != rGraphic.GetType() && GraphicType::GdiMetafile != rGraphic.GetType())
- return;
+ return nullptr;
const Size aSize(rGraphic.GetPrefSize());
if(!(aSize.Width() && aSize.Height()))
- return;
+ return nullptr;
// we have a graphic (bitmap or metafile) with some size
+ Primitive2DContainer aContainer;
if(rAttribute.getTiling())
{
// get object range and create tiling matrices
@@ -66,13 +69,15 @@ namespace drawinglayer::primitive2d
Primitive2DContainer xSeq;
create2DDecompositionOfGraphic(xSeq,
rGraphic,
- basegfx::B2DHomMatrix());
+ basegfx::B2DHomMatrix(),
+ getTransparency());
- for(size_t a(0); a < aMatrices.size(); a++)
+ rtl::Reference<GroupPrimitive2D> xGroup = new GroupPrimitive2D(std::move(xSeq));
+ for(const auto &a : aMatrices)
{
- rContainer.push_back(new TransformPrimitive2D(
- getTransformation() * aMatrices[a],
- xSeq));
+ aContainer.push_back(new TransformPrimitive2D(
+ getTransformation() * a,
+ *xGroup));
}
}
else
@@ -83,18 +88,23 @@ namespace drawinglayer::primitive2d
rAttribute.getGraphicRange().getRange(),
rAttribute.getGraphicRange().getMinimum()));
- create2DDecompositionOfGraphic(rContainer,
+ create2DDecompositionOfGraphic(aContainer,
rGraphic,
- aObjectTransform);
+ aObjectTransform,
+ getTransparency());
}
+
+ return new GroupPrimitive2D(std::move(aContainer));
}
FillGraphicPrimitive2D::FillGraphicPrimitive2D(
- const basegfx::B2DHomMatrix& rTransformation,
- const attribute::FillGraphicAttribute& rFillGraphic)
- : BufferedDecompositionPrimitive2D(),
- maTransformation(rTransformation),
- maFillGraphic(rFillGraphic)
+ basegfx::B2DHomMatrix aTransformation,
+ const attribute::FillGraphicAttribute& rFillGraphic,
+ double fTransparency)
+ : maTransformation(std::move(aTransformation))
+ , maFillGraphic(rFillGraphic)
+ , maOffsetXYCreatedBitmap()
+ , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
{
}
@@ -105,7 +115,8 @@ namespace drawinglayer::primitive2d
const FillGraphicPrimitive2D& rCompare = static_cast< const FillGraphicPrimitive2D& >(rPrimitive);
return (getTransformation() == rCompare.getTransformation()
- && getFillGraphic() == rCompare.getFillGraphic());
+ && getFillGraphic() == rCompare.getFillGraphic()
+ && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency()));
}
return false;
@@ -121,7 +132,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(FillGraphicPrimitive2D, PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D)
+ sal_uInt32 FillGraphicPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx
index 9c4ef03bfba3..c855460824e7 100644
--- a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx
@@ -19,12 +19,14 @@
#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
#include <texture/texture.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -32,10 +34,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void FillHatchPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference FillHatchPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if(getFillHatch().isDefault())
- return;
+ return nullptr;
// create hatch
const basegfx::BColor aHatchColor(getFillHatch().getColor());
@@ -65,7 +67,7 @@ namespace drawinglayer::primitive2d
getDefinitionRange(),
getOutputRange(),
fDistance,
- fAngle - F_PI4);
+ fAngle - M_PI_4);
aHatch.appendTransformations(aMatrices);
@@ -78,7 +80,7 @@ namespace drawinglayer::primitive2d
getDefinitionRange(),
getOutputRange(),
fDistance,
- fAngle - F_PI2);
+ fAngle - M_PI_2);
aHatch.appendTransformations(aMatrices);
@@ -99,12 +101,12 @@ namespace drawinglayer::primitive2d
// prepare return value
const bool bFillBackground(getFillHatch().isFillBackground());
-
+ Primitive2DContainer aContainer;
// evtl. create filled background
if(bFillBackground)
{
// create primitive for background
- rContainer.push_back(
+ aContainer.push_back(
new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(
basegfx::utils::createPolygonFromRect(getOutputRange())), getBColor()));
@@ -114,27 +116,27 @@ namespace drawinglayer::primitive2d
const basegfx::B2DPoint aStart(0.0, 0.0);
const basegfx::B2DPoint aEnd(1.0, 0.0);
- for(size_t a(0); a < aMatrices.size(); a++)
+ for (const auto &a : aMatrices)
{
- const basegfx::B2DHomMatrix& rMatrix = aMatrices[a];
+ const basegfx::B2DHomMatrix& rMatrix = a;
basegfx::B2DPolygon aNewLine;
aNewLine.append(rMatrix * aStart);
aNewLine.append(rMatrix * aEnd);
// create hairline
- rContainer.push_back(new PolygonHairlinePrimitive2D(aNewLine, aHatchColor));
+ aContainer.push_back(new PolygonHairlinePrimitive2D(std::move(aNewLine), aHatchColor));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
FillHatchPrimitive2D::FillHatchPrimitive2D(
const basegfx::B2DRange& rOutputRange,
const basegfx::BColor& rBColor,
- const attribute::FillHatchAttribute& rFillHatch)
- : DiscreteMetricDependentPrimitive2D(),
- maOutputRange(rOutputRange),
+ attribute::FillHatchAttribute aFillHatch)
+ : maOutputRange(rOutputRange),
maDefinitionRange(rOutputRange),
- maFillHatch(rFillHatch),
+ maFillHatch(std::move(aFillHatch)),
maBColor(rBColor)
{
}
@@ -143,11 +145,10 @@ namespace drawinglayer::primitive2d
const basegfx::B2DRange& rOutputRange,
const basegfx::B2DRange& rDefinitionRange,
const basegfx::BColor& rBColor,
- const attribute::FillHatchAttribute& rFillHatch)
- : DiscreteMetricDependentPrimitive2D(),
- maOutputRange(rOutputRange),
+ attribute::FillHatchAttribute aFillHatch)
+ : maOutputRange(rOutputRange),
maDefinitionRange(rDefinitionRange),
- maFillHatch(rFillHatch),
+ maFillHatch(std::move(aFillHatch)),
maBColor(rBColor)
{
}
@@ -175,7 +176,6 @@ namespace drawinglayer::primitive2d
void FillHatchPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
bool bAdaptDistance(0 != getFillHatch().getMinimalDiscreteDistance());
if(bAdaptDistance)
@@ -191,7 +191,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(FillHatchPrimitive2D, PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D)
+ sal_uInt32 FillHatchPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/glowprimitive2d.cxx b/drawinglayer/source/primitive2d/glowprimitive2d.cxx
index fb6a599ab4e2..5f565c28341f 100644
--- a/drawinglayer/source/primitive2d/glowprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/glowprimitive2d.cxx
@@ -18,29 +18,39 @@
*/
#include <drawinglayer/primitive2d/glowprimitive2d.hxx>
-#include <basegfx/color/bcolormodifier.hxx>
-#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <drawinglayer/converters.hxx>
+#include "GlowSoftEgdeShadowTools.hxx"
-#include <sal/log.hxx>
-#include <memory>
+#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
+#include <tools/stream.hxx>
+#include <vcl/filter/PngImageWriter.hxx>
+#endif
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
GlowPrimitive2D::GlowPrimitive2D(const Color& rGlowColor, double fRadius,
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ Primitive2DContainer&& rChildren)
+ : BufferedDecompositionGroupPrimitive2D(std::move(rChildren))
, maGlowColor(rGlowColor)
, mfGlowRadius(fRadius)
+ , mfLastDiscreteGlowRadius(0.0)
+ , maLastClippedRange()
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
bool GlowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if (BasePrimitive2D::operator==(rPrimitive))
+ if (BufferedDecompositionGroupPrimitive2D::operator==(rPrimitive))
{
const GlowPrimitive2D& rCompare = static_cast<const GlowPrimitive2D&>(rPrimitive);
@@ -51,17 +61,298 @@ bool GlowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
return false;
}
+bool GlowPrimitive2D::prepareValuesAndcheckValidity(
+ basegfx::B2DRange& rGlowRange, basegfx::B2DRange& rClippedRange,
+ basegfx::B2DVector& rDiscreteGlowSize, double& rfDiscreteGlowRadius,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ // no GlowRadius defined, done
+ if (getGlowRadius() <= 0.0)
+ return false;
+
+ // no geometry, done
+ if (getChildren().empty())
+ return false;
+
+ // no pixel target, done
+ if (rViewInformation.getObjectToViewTransformation().isIdentity())
+ return false;
+
+ // get geometry range that defines area that needs to be pixelated
+ rGlowRange = getChildren().getB2DRange(rViewInformation);
+
+ // no range of geometry, done
+ if (rGlowRange.isEmpty())
+ return false;
+
+ // extend range by GlowRadius in all directions
+ rGlowRange.grow(getGlowRadius());
+
+ // initialize ClippedRange to full GlowRange -> all is visible
+ rClippedRange = rGlowRange;
+
+ // get Viewport and check if used. If empty, all is visible (see
+ // ViewInformation2D definition in viewinformation2d.hxx)
+ if (!rViewInformation.getViewport().isEmpty())
+ {
+ // if used, extend by GlowRadius to ensure needed parts are included
+ basegfx::B2DRange aVisibleArea(rViewInformation.getViewport());
+ aVisibleArea.grow(getGlowRadius());
+
+ // To do this correctly, it needs to be done in discrete coordinates.
+ // The object may be transformed relative to the original#
+ // ObjectTransformation, e.g. when re-used in shadow
+ aVisibleArea.transform(rViewInformation.getViewTransformation());
+ rClippedRange.transform(rViewInformation.getObjectToViewTransformation());
+
+ // calculate ClippedRange
+ rClippedRange.intersect(aVisibleArea);
+
+ // if GlowRange is completely outside of VisibleArea, ClippedRange
+ // will be empty and we are done
+ if (rClippedRange.isEmpty())
+ return false;
+
+ // convert result back to object coordinates
+ rClippedRange.transform(rViewInformation.getInverseObjectToViewTransformation());
+ }
+
+ // calculate discrete pixel size of GlowRange. If it's too small to visualize, we are done
+ rDiscreteGlowSize = rViewInformation.getObjectToViewTransformation() * rGlowRange.getRange();
+ if (ceil(rDiscreteGlowSize.getX()) < 2.0 || ceil(rDiscreteGlowSize.getY()) < 2.0)
+ return false;
+
+ // calculate discrete pixel size of GlowRadius. If it's too small to visualize, we are done
+ rfDiscreteGlowRadius = ceil(
+ (rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(getGlowRadius(), 0))
+ .getLength());
+ if (rfDiscreteGlowRadius < 1.0)
+ return false;
+
+ return true;
+}
+
+void GlowPrimitive2D::create2DDecomposition(
+ Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+{
+ basegfx::B2DRange aGlowRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteGlowSize;
+ double fDiscreteGlowRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aGlowRange, aClippedRange, aDiscreteGlowSize,
+ fDiscreteGlowRadius, rViewInformation))
+ return;
+
+ // Create embedding transformation from object to top-left zero-aligned
+ // target pixel geometry (discrete form of ClippedRange)
+ // First, move to top-left of GlowRange
+ const sal_uInt32 nDiscreteGlowWidth(ceil(aDiscreteGlowSize.getX()));
+ const sal_uInt32 nDiscreteGlowHeight(ceil(aDiscreteGlowSize.getY()));
+ basegfx::B2DHomMatrix aEmbedding(basegfx::utils::createTranslateB2DHomMatrix(
+ -aClippedRange.getMinX(), -aClippedRange.getMinY()));
+ // Second, scale to discrete bitmap size
+ // Even when using the offset from ClippedRange, we need to use the
+ // scaling from the full representation, thus from GlowRange
+ aEmbedding.scale(nDiscreteGlowWidth / aGlowRange.getWidth(),
+ nDiscreteGlowHeight / aGlowRange.getHeight());
+
+ // Embed content graphics to TransformPrimitive2D
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(aEmbedding, Primitive2DContainer(getChildren())));
+ primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ // Create Bitmap using drawinglayer tooling, including a MaximumQuadraticPixel
+ // limitation to be safe and not go runtime/memory havoc. Use a pretty small
+ // limit due to this is glow functionality and will look good with bitmap scaling
+ // anyways. The value of 250.000 square pixels below maybe adapted as needed.
+ const basegfx::B2DVector aDiscreteClippedSize(rViewInformation.getObjectToViewTransformation()
+ * aClippedRange.getRange());
+ const sal_uInt32 nDiscreteClippedWidth(ceil(aDiscreteClippedSize.getX()));
+ const sal_uInt32 nDiscreteClippedHeight(ceil(aDiscreteClippedSize.getY()));
+ const geometry::ViewInformation2D aViewInformation2D;
+ const sal_uInt32 nMaximumQuadraticPixels(250000);
+
+ // I have now added a helper that just creates the mask without having
+ // to render the content, use it, it's faster
+ const AlphaMask aAlpha(::drawinglayer::createAlphaMask(
+ std::move(xEmbedSeq), aViewInformation2D, nDiscreteClippedWidth, nDiscreteClippedHeight,
+ nMaximumQuadraticPixels));
+
+ if (aAlpha.IsEmpty())
+ return;
+
+ const Size aBitmapExSizePixel(aAlpha.GetSizePixel());
+
+ if (aBitmapExSizePixel.Width() <= 0 || aBitmapExSizePixel.Height() <= 0)
+ return;
+
+ // We may have to take a corrective scaling into account when the
+ // MaximumQuadraticPixel limit was used/triggered
+ double fScale(1.0);
+
+ if (static_cast<sal_uInt32>(aBitmapExSizePixel.Width()) != nDiscreteClippedWidth
+ || static_cast<sal_uInt32>(aBitmapExSizePixel.Height()) != nDiscreteClippedHeight)
+ {
+ // scale in X and Y should be the same (see fReduceFactor in createAlphaMask),
+ // so adapt numerically to a single scale value, they are integer rounded values
+ const double fScaleX(static_cast<double>(aBitmapExSizePixel.Width())
+ / static_cast<double>(nDiscreteClippedWidth));
+ const double fScaleY(static_cast<double>(aBitmapExSizePixel.Height())
+ / static_cast<double>(nDiscreteClippedHeight));
+
+ fScale = (fScaleX + fScaleY) * 0.5;
+ }
+
+ // fDiscreteGlowRadius is the size of the halo from each side of the object. The halo is the
+ // border of glow color that fades from glow transparency level to fully transparent
+ // When blurring a sharp boundary (our case), it gets 50% of original intensity, and
+ // fades to both sides by the blur radius; thus blur radius is half of glow radius.
+ // Consider glow transparency (initial transparency near the object edge)
+ AlphaMask mask(ProcessAndBlurAlphaMask(aAlpha, fDiscreteGlowRadius * fScale / 2.0,
+ fDiscreteGlowRadius * fScale / 2.0,
+ 255 - getGlowColor().GetAlpha()));
+
+ // The end result is the bitmap filled with glow color and blurred 8-bit alpha mask
+ Bitmap bmp(aAlpha.GetSizePixel(), vcl::PixelFormat::N24_BPP);
+ bmp.Erase(getGlowColor());
+ Bitmap result(bmp, mask);
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ if (bDoSaveForVisualControl)
+ {
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
+ {
+ SvFileStream aNew(sDumpPath + "test_glow.png", StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PngImageWriter aPNGWriter(aNew);
+ aPNGWriter.write(result);
+ }
+ }
+#endif
+
+ // Independent from discrete sizes of glow alpha creation, always
+ // map and project glow result to geometry range extended by glow
+ // radius, but to the eventually clipped instance (ClippedRange)
+ const primitive2d::Primitive2DReference xEmbedRefBitmap(
+ new BitmapPrimitive2D(result, basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aClippedRange.getWidth(), aClippedRange.getHeight(),
+ aClippedRange.getMinX(), aClippedRange.getMinY())));
+
+ rContainer = primitive2d::Primitive2DContainer{ xEmbedRefBitmap };
+}
+
+// Using tooling class BufferedDecompositionGroupPrimitive2D now, so
+// no more need to locally do the buffered get2DDecomposition here,
+// see BufferedDecompositionGroupPrimitive2D::get2DDecomposition
+void GlowPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ basegfx::B2DRange aGlowRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteGlowSize;
+ double fDiscreteGlowRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aGlowRange, aClippedRange, aDiscreteGlowSize,
+ fDiscreteGlowRadius, rViewInformation))
+ return;
+
+ if (hasBuffered2DDecomposition())
+ {
+ // First check is to detect if the last created decompose is capable
+ // to represent the now requested visualization.
+ // ClippedRange is the needed visualizationArea for the current glow
+ // effect, LastClippedRange is the one from the existing/last rendering.
+ // Check if last created area is sufficient and can be re-used
+ if (!maLastClippedRange.isEmpty() && !maLastClippedRange.isInside(aClippedRange))
+ {
+ // To avoid unnecessary invalidations due to being *very* correct
+ // with HairLines (which are view-dependent and thus change the
+ // result(s) here slightly when changing zoom), add a slight unsharp
+ // component if we have a ViewTransform. The derivation is inside
+ // the range of half a pixel (due to one pixel hairline)
+ basegfx::B2DRange aLastClippedRangeAndHairline(maLastClippedRange);
+
+ if (!rViewInformation.getObjectToViewTransformation().isIdentity())
+ {
+ // Grow by view-dependent size of 1/2 pixel
+ const double fHalfPixel((rViewInformation.getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(0.5, 0))
+ .getLength());
+ aLastClippedRangeAndHairline.grow(fHalfPixel);
+ }
+
+ if (!aLastClippedRangeAndHairline.isInside(aClippedRange))
+ {
+ // Conditions of last local decomposition have changed, delete
+ const_cast<GlowPrimitive2D*>(this)->setBuffered2DDecomposition(
+ Primitive2DContainer());
+ }
+ }
+ }
+
+ if (hasBuffered2DDecomposition())
+ {
+ // Second check is to react on changes of the DiscreteGlowRadius when
+ // zooming in/out.
+ // Use the known last and current DiscreteGlowRadius to decide
+ // if the visualization can be re-used. Be a little 'creative' here
+ // and make it dependent on a *relative* change - it is not necessary
+ // to re-create everytime if the exact value is missed since zooming
+ // pixel-based glow effect is pretty good due to it's smooth nature
+ bool bFree(mfLastDiscreteGlowRadius <= 0.0 || fDiscreteGlowRadius <= 0.0);
+
+ if (!bFree)
+ {
+ const double fDiff(fabs(mfLastDiscreteGlowRadius - fDiscreteGlowRadius));
+ const double fLen(fabs(mfLastDiscreteGlowRadius) + fabs(fDiscreteGlowRadius));
+ const double fRelativeChange(fDiff / fLen);
+
+ // Use lower fixed values here to change more often, higher to change less often.
+ // Value is in the range of ]0.0 .. 1.0]
+ bFree = fRelativeChange >= 0.15;
+ }
+
+ if (bFree)
+ {
+ // Conditions of last local decomposition have changed, delete
+ const_cast<GlowPrimitive2D*>(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ }
+ }
+
+ if (!hasBuffered2DDecomposition())
+ {
+ // refresh last used DiscreteGlowRadius and ClippedRange to new remembered values
+ const_cast<GlowPrimitive2D*>(this)->mfLastDiscreteGlowRadius = fDiscreteGlowRadius;
+ const_cast<GlowPrimitive2D*>(this)->maLastClippedRange = aClippedRange;
+ }
+
+ // call parent, that will check for empty, call create2DDecomposition and
+ // set as decomposition
+ BufferedDecompositionGroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+}
+
basegfx::B2DRange
GlowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
{
- basegfx::B2DRange aRetval(GroupPrimitive2D::getB2DRange(rViewInformation));
+ // Hint: Do *not* use GroupPrimitive2D::getB2DRange, that will (unnecessarily)
+ // use the decompose - what works, but is not needed here.
+ // We know the to-be-visualized geometry and the radius it needs to be extended,
+ // so simply calculate the exact needed range.
+ basegfx::B2DRange aRetval(getChildren().getB2DRange(rViewInformation));
+
// We need additional space for the glow from all sides
aRetval.grow(getGlowRadius());
+
return aRetval;
}
// provide unique ID
-ImplPrimitive2DIDBlock(GlowPrimitive2D, PRIMITIVE2D_ID_GLOWPRIMITIVE2D)
+sal_uInt32 GlowPrimitive2D::getPrimitive2DID() const { return PRIMITIVE2D_ID_GLOWPRIMITIVE2D; }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
index f86b1585b13f..0f0d3771867f 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -24,19 +24,20 @@
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
#include <primitive2d/cropprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <primitive2d/graphicprimitivehelper2d.hxx>
+#include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <utility>
namespace drawinglayer::primitive2d
{
-void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer,
- const geometry::ViewInformation2D&) const
+Primitive2DReference
+GraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D&) const
{
- if (255 == getGraphicAttr().GetTransparency())
+ if (0 == getGraphicAttr().GetAlpha())
{
// content is invisible, done
- return;
+ return nullptr;
}
// do not apply mirroring from GraphicAttr to the Metafile by calling
@@ -68,45 +69,60 @@ void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer,
GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
- aSuppressGraphicAttr.SetRotation(0);
+ aSuppressGraphicAttr.SetRotation(0_deg10);
aSuppressGraphicAttr.SetMirrorFlags(BmpMirrorFlags::NONE);
- aSuppressGraphicAttr.SetTransparency(0);
+ aSuppressGraphicAttr.SetAlpha(255);
const GraphicObject& rGraphicObject = getGraphicObject();
Graphic aTransformedGraphic(rGraphicObject.GetGraphic());
- const bool isBitmap(GraphicType::Bitmap == aTransformedGraphic.GetType()
- && !aTransformedGraphic.getVectorGraphicData());
const bool isAdjusted(getGraphicAttr().IsAdjusted());
const bool isDrawMode(GraphicDrawMode::Standard != getGraphicAttr().GetDrawMode());
- if (isBitmap && (isAdjusted || isDrawMode))
+ // I have now added buffering BColorModifierStack-adapted Bitmaps,
+ // see Bitmap::Modify, thus the primitive case is fast now.
+ // It buffers the adapted bitmap and at that the SDPRs can then buffer
+ // the system-dependent representation.
+ // I keep the code below (adding a static switch). It modifies the
+ // Graphic and is a reliable fallback - just in case. Remember that
+ // it does *not* buffer and has to modify again at each re-use...
+ static bool bUseOldModification(false);
+
+ if (bUseOldModification)
{
- // the pure primitive solution with the color modifiers works well, too, but when
- // it is a bitmap graphic the old modification currently is faster; so use it here
- // instead of creating all as in create2DColorModifierEmbeddingsAsNeeded (see below).
- // Still, crop, rotation, mirroring and transparency is handled by primitives already
- // (see above).
- // This could even be done when vector graphic, but we explicitly want to have the
- // pure primitive solution for this; this will allow vector graphics to stay vector
- // graphics, independent from the color filtering stuff. This will enhance e.g.
- // SVG and print quality while reducing data size at the same time.
- // The other way around the old modifications when only used on already bitmap objects
- // will not lose any quality.
- aTransformedGraphic = rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
-
- // reset GraphicAttr after use to not apply double
- aSuppressGraphicAttr = GraphicAttr();
+ const bool isBitmap(GraphicType::Bitmap == aTransformedGraphic.GetType()
+ && !aTransformedGraphic.getVectorGraphicData());
+
+ if (isBitmap && (isAdjusted || isDrawMode))
+ {
+ // the pure primitive solution with the color modifiers works well, too, but when
+ // it is a bitmap graphic the old modification currently is faster; so use it here
+ // instead of creating all as in create2DColorModifierEmbeddingsAsNeeded (see below).
+ // Still, crop, rotation, mirroring and transparency is handled by primitives already
+ // (see above).
+ // This could even be done when vector graphic, but we explicitly want to have the
+ // pure primitive solution for this; this will allow vector graphics to stay vector
+ // graphics, independent from the color filtering stuff. This will enhance e.g.
+ // SVG and print quality while reducing data size at the same time.
+ // The other way around the old modifications when only used on already bitmap objects
+ // will not lose any quality.
+ aTransformedGraphic = rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
+
+ // reset GraphicAttr after use to not apply double
+ aSuppressGraphicAttr = GraphicAttr();
+ }
}
// create sub-content; helper takes care of correct handling of
- // bitmap, svg or metafile content
+ // bitmap, svg or metafile content. also handle alpha there directly
Primitive2DContainer aRetval;
- create2DDecompositionOfGraphic(aRetval, aTransformedGraphic, aTransform);
+ const double fTransparency(
+ std::clamp((255 - getGraphicAttr().GetAlpha()) * (1.0 / 255.0), 0.0, 1.0));
+ create2DDecompositionOfGraphic(aRetval, aTransformedGraphic, aTransform, fTransparency);
if (aRetval.empty())
{
// content is invisible, done
- return;
+ return nullptr;
}
if (isAdjusted || isDrawMode)
@@ -114,7 +130,7 @@ void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer,
// embed to needed ModifiedColorPrimitive2D's if necessary. Do this for
// adjustments and draw mode specials
aRetval = create2DColorModifierEmbeddingsAsNeeded(
- aRetval, aSuppressGraphicAttr.GetDrawMode(),
+ std::move(aRetval), aSuppressGraphicAttr.GetDrawMode(),
std::clamp(aSuppressGraphicAttr.GetLuminance() * 0.01, -1.0, 1.0),
std::clamp(aSuppressGraphicAttr.GetContrast() * 0.01, -1.0, 1.0),
std::clamp(aSuppressGraphicAttr.GetChannelR() * 0.01, -1.0, 1.0),
@@ -126,22 +142,7 @@ void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer,
if (aRetval.empty())
{
// content is invisible, done
- return;
- }
- }
-
- if (getGraphicAttr().IsTransparent())
- {
- // check for transparency
- const double fTransparency(
- std::clamp(getGraphicAttr().GetTransparency() * (1.0 / 255.0), 0.0, 1.0));
-
- if (!basegfx::fTools::equalZero(fTransparency))
- {
- const Primitive2DReference aUnifiedTransparence(
- new UnifiedTransparencePrimitive2D(aRetval, fTransparency));
-
- aRetval = Primitive2DContainer{ aUnifiedTransparence };
+ return nullptr;
}
}
@@ -157,35 +158,35 @@ void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer,
getGraphicAttr().GetBottomCrop()));
// embed content in cropPrimitive
- Primitive2DReference xPrimitive(new CropPrimitive2D(
- aRetval, aTransform, getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
+ aRetval = Primitive2DContainer{ new CropPrimitive2D(
+ std::move(aRetval), aTransform,
+ getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(),
getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(),
- getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()));
-
- aRetval = Primitive2DContainer{ xPrimitive };
+ getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()) };
}
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
+ return new GroupPrimitive2D(std::move(aRetval));
}
-GraphicPrimitive2D::GraphicPrimitive2D(const basegfx::B2DHomMatrix& rTransform,
+GraphicPrimitive2D::GraphicPrimitive2D(basegfx::B2DHomMatrix aTransform,
const GraphicObject& rGraphicObject,
const GraphicAttr& rGraphicAttr)
- : BufferedDecompositionPrimitive2D()
- , maTransform(rTransform)
+ : maTransform(std::move(aTransform))
, maGraphicObject(rGraphicObject)
, maGraphicAttr(rGraphicAttr)
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
-GraphicPrimitive2D::GraphicPrimitive2D(const basegfx::B2DHomMatrix& rTransform,
+GraphicPrimitive2D::GraphicPrimitive2D(basegfx::B2DHomMatrix aTransform,
const GraphicObject& rGraphicObject)
- : BufferedDecompositionPrimitive2D()
- , maTransform(rTransform)
+ : maTransform(std::move(aTransform))
, maGraphicObject(rGraphicObject)
- , maGraphicAttr()
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
bool GraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -211,7 +212,10 @@ GraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInform
}
// provide unique ID
-ImplPrimitive2DIDBlock(GraphicPrimitive2D, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D)
+sal_uInt32 GraphicPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D;
+}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
index 9c441dc0d876..092c7b86dcdf 100644
--- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
@@ -21,14 +21,18 @@
#include <algorithm>
-#include <primitive2d/graphicprimitivehelper2d.hxx>
+#include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
#include <drawinglayer/animation/animationtiming.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
@@ -36,7 +40,9 @@
// helper class for animated graphics
+#include <utility>
#include <vcl/animate/Animation.hxx>
+#include <vcl/alpha.hxx>
#include <vcl/graph.hxx>
#include <vcl/virdev.hxx>
#include <vcl/svapp.hxx>
@@ -58,11 +64,20 @@ namespace drawinglayer::primitive2d
an instance of Graphic is used here since it's ref-counted
and thus a safe copy for now
*/
- const Graphic maGraphic;
+ Graphic maGraphic;
+
+ /** defines parameters for tiling if this AnimatedGraphicPrimitive2D
+ is to be used for a FillGraphicPrimitive2D. In that case,
+ maFillGraphicAttribute.isDefault() will be false
+ */
+ drawinglayer::attribute::FillGraphicAttribute maFillGraphicAttribute;
/// local animation processing data, excerpt from maGraphic
::Animation maAnimation;
+ /// the transparency in range [0.0 .. 1.0]
+ double mfTransparency;
+
/// the on-demand created VirtualDevices for frame creation
ScopedVclPtrInstance< VirtualDevice > maVirtualDevice;
ScopedVclPtrInstance< VirtualDevice > maVirtualDeviceMask;
@@ -74,7 +89,7 @@ namespace drawinglayer::primitive2d
Primitive2DReference maBufferedFirstFrame;
/// buffering of all frames
- Primitive2DContainer maBufferedPrimitives;
+ std::vector<Primitive2DReference> maBufferedPrimitives;
bool mbBufferingAllowed;
/// set if the animation is huge so that just always the next frame
@@ -86,7 +101,8 @@ namespace drawinglayer::primitive2d
{
return (GraphicType::Bitmap == maGraphic.GetType()
&& maGraphic.IsAnimated()
- && maAnimation.Count());
+ && maAnimation.Count()
+ && !basegfx::fTools::equal(getTransparency(), 1.0));
}
void ensureVirtualDeviceSizeAndState()
@@ -103,6 +119,10 @@ namespace drawinglayer::primitive2d
maVirtualDeviceMask->EnableMapMode(false);
maVirtualDevice->SetOutputSizePixel(aTarget);
maVirtualDeviceMask->SetOutputSizePixel(aTarget);
+
+ // tdf#156630 make erase calls fill with transparency
+ maVirtualDevice->SetBackground(COL_BLACK);
+ maVirtualDeviceMask->SetBackground(COL_ALPHA_TRANSPARENT);
}
maVirtualDevice->Erase();
@@ -115,13 +135,13 @@ namespace drawinglayer::primitive2d
sal_uInt32 generateStepTime(sal_uInt32 nIndex) const
{
- const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(nIndex));
- sal_uInt32 nWaitTime(rAnimationBitmap.mnWait * 10);
+ const AnimationFrame& rAnimationFrame = maAnimation.Get(sal_uInt16(nIndex));
+ sal_uInt32 nWaitTime(rAnimationFrame.mnWait * 10);
// Take care of special value for MultiPage TIFFs. ATM these shall just
// show their first page. Later we will offer some switching when object
// is selected.
- if (ANIMATION_TIMEOUT_ON_CLICK == rAnimationBitmap.mnWait)
+ if (ANIMATION_TIMEOUT_ON_CLICK == rAnimationFrame.mnWait)
{
// ATM the huge value would block the timer, so
// use a long time to show first page (whole day)
@@ -162,7 +182,7 @@ namespace drawinglayer::primitive2d
Primitive2DReference createFromBuffer() const
{
- // create BitmapEx by extracting from VirtualDevices
+ // create Bitmap by extracting from VirtualDevices
const Bitmap aMainBitmap(maVirtualDevice->GetBitmap(Point(), maVirtualDevice->GetOutputSizePixel()));
bool useAlphaMask = false;
#if defined(MACOSX) || defined(IOS)
@@ -172,22 +192,41 @@ namespace drawinglayer::primitive2d
if( SkiaHelper::isVCLSkiaEnabled())
useAlphaMask = true;
#endif
- BitmapEx bitmap;
+ Bitmap bitmap;
if( useAlphaMask )
{
const AlphaMask aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
- bitmap = BitmapEx(aMainBitmap, aMaskBitmap);
+ bitmap = Bitmap(aMainBitmap, aMaskBitmap);
}
else
{
- const Bitmap aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
- bitmap = BitmapEx(aMainBitmap, aMaskBitmap);
+ Bitmap aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
+ // tdf#156630 invert the alpha mask
+ aMaskBitmap.Invert(); // convert from transparency to alpha
+ bitmap = Bitmap(aMainBitmap, aMaskBitmap);
+ }
+
+ if (!maFillGraphicAttribute.isDefault())
+ {
+ // need to create FillGraphicPrimitive2D
+ const drawinglayer::attribute::FillGraphicAttribute aAttribute(
+ Graphic(bitmap),
+ maFillGraphicAttribute.getGraphicRange(),
+ maFillGraphicAttribute.getTiling(),
+ maFillGraphicAttribute.getOffsetX(),
+ maFillGraphicAttribute.getOffsetY());
+
+ return new FillGraphicPrimitive2D(
+ getTransform(),
+ aAttribute,
+ getTransparency());
}
- return Primitive2DReference(
- new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(bitmap),
- getTransform()));
+ // need to create BitmapAlphaPrimitive2D/BitmapPrimitive2D
+ if (basegfx::fTools::equal(getTransparency(), 0.0))
+ return new BitmapPrimitive2D(bitmap, getTransform());
+
+ return new BitmapAlphaPrimitive2D(bitmap, getTransform(), getTransparency());
}
void checkSafeToBuffer(sal_uInt32 nIndex)
@@ -249,16 +288,24 @@ namespace drawinglayer::primitive2d
while (mnNextFrameToPrepare <= nTarget)
{
// prepare step
- const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare));
+ const AnimationFrame& rAnimationFrame = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare));
+
+ bool bSourceBlending = rAnimationFrame.meBlend == Blend::Source;
+
+ if (bSourceBlending)
+ {
+ tools::Rectangle aArea(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap.GetSizePixel());
+ maVirtualDevice->Erase(aArea);
+ maVirtualDeviceMask->Erase(aArea);
+ }
- switch (rAnimationBitmap.meDisposal)
+ switch (rAnimationFrame.meDisposal)
{
case Disposal::Not:
{
- maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx);
- Bitmap aMask = rAnimationBitmap.maBitmapEx.GetMask();
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap);
- if (aMask.IsEmpty())
+ if (!rAnimationFrame.maBitmap.HasAlpha())
{
const Point aEmpty;
const ::tools::Rectangle aRect(aEmpty, maVirtualDeviceMask->GetOutputSizePixel());
@@ -267,8 +314,9 @@ namespace drawinglayer::primitive2d
}
else
{
- BitmapEx aExpandVisibilityMask(aMask, aMask);
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ AlphaMask aAlphaMask = rAnimationFrame.maBitmap.CreateAlphaMask();
+ Bitmap aExpandVisibilityMask(aAlphaMask.GetBitmap(), aAlphaMask);
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
}
break;
@@ -276,32 +324,31 @@ namespace drawinglayer::primitive2d
case Disposal::Back:
{
// #i70772# react on no mask, for primitives, too.
- const Bitmap & rMask(rAnimationBitmap.maBitmapEx.GetMask());
- const Bitmap & rContent(rAnimationBitmap.maBitmapEx.GetBitmap());
maVirtualDeviceMask->Erase();
- maVirtualDevice->DrawBitmap(rAnimationBitmap.maPositionPixel, rContent);
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap);
- if (rMask.IsEmpty())
+ if (!rAnimationFrame.maBitmap.HasAlpha())
{
- const ::tools::Rectangle aRect(rAnimationBitmap.maPositionPixel, rContent.GetSizePixel());
+ const ::tools::Rectangle aRect(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap.GetSizePixel());
maVirtualDeviceMask->SetFillColor(COL_BLACK);
maVirtualDeviceMask->SetLineColor();
maVirtualDeviceMask->DrawRect(aRect);
}
else
{
- BitmapEx aExpandVisibilityMask(rMask, rMask);
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ const AlphaMask aMask(rAnimationFrame.maBitmap.CreateAlphaMask());
+ Bitmap aExpandVisibilityMask(aMask.GetBitmap(), aMask);
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
}
break;
}
case Disposal::Previous:
{
- maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx);
- BitmapEx aExpandVisibilityMask(rAnimationBitmap.maBitmapEx.GetMask(), rAnimationBitmap.maBitmapEx.GetMask());
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap);
+ Bitmap aExpandVisibilityMask(rAnimationFrame.maBitmap.CreateAlphaMask().GetBitmap(), rAnimationFrame.maBitmap.CreateAlphaMask());
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
break;
}
}
@@ -342,38 +389,54 @@ namespace drawinglayer::primitive2d
/// constructor
AnimatedGraphicPrimitive2D(
const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform);
+ const drawinglayer::attribute::FillGraphicAttribute* pFillGraphicAttribute,
+ basegfx::B2DHomMatrix aTransform,
+ double fTransparency = 0.0);
+ virtual ~AnimatedGraphicPrimitive2D();
/// data read access
const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
+ double getTransparency() const { return mfTransparency; }
+
+ /// provide unique ID
+ virtual sal_uInt32 getPrimitive2DID() const override { return PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D; }
/// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
/// override to deliver the correct expected frame dependent of timing
virtual void get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const override;
+
+ /// get range
+ virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
};
}
AnimatedGraphicPrimitive2D::AnimatedGraphicPrimitive2D(
const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform)
+ const drawinglayer::attribute::FillGraphicAttribute* pFillGraphicAttribute,
+ basegfx::B2DHomMatrix aTransform,
+ double fTransparency)
: AnimatedSwitchPrimitive2D(
animation::AnimationEntryList(),
Primitive2DContainer(),
false),
- maTransform(rTransform),
+ maTransform(std::move(aTransform)),
maGraphic(rGraphic),
+ maFillGraphicAttribute(),
maAnimation(rGraphic.GetAnimation()),
+ mfTransparency(std::max(0.0, std::min(1.0, fTransparency))),
maVirtualDevice(*Application::GetDefaultDevice()),
- maVirtualDeviceMask(*Application::GetDefaultDevice(), DeviceFormat::BITMASK),
+ maVirtualDeviceMask(*Application::GetDefaultDevice()),
mnNextFrameToPrepare(SAL_MAX_UINT32),
- maBufferedFirstFrame(),
- maBufferedPrimitives(),
mbBufferingAllowed(false),
mbHugeSize(false)
{
+ // if FillGraphicAttribute copy it -> FillGraphicPrimitive2D is intended
+ if (nullptr != pFillGraphicAttribute)
+ maFillGraphicAttribute = *pFillGraphicAttribute;
+
// initialize AnimationTiming, needed to detect which frame is requested
// in get2DDecomposition
createAndSetAnimationTiming();
@@ -404,10 +467,29 @@ namespace drawinglayer::primitive2d
// prepare buffer space
if (mbBufferingAllowed && isValidData())
{
- maBufferedPrimitives = Primitive2DContainer(maAnimation.Count());
+ maBufferedPrimitives.resize(maAnimation.Count());
}
}
+ AnimatedGraphicPrimitive2D::~AnimatedGraphicPrimitive2D()
+ {
+ // Related: tdf#158807 mutex must be locked when disposing a VirtualDevice
+ // If the following .ppt document is opened in a debug build
+ // and the document is left open for a minute or two without
+ // changing any content, this destructor will be called on a
+ // non-main thread with the mutex unlocked:
+ // https://bugs.documentfoundation.org/attachment.cgi?id=46801
+ // This hits an assert in VirtualDevice::ReleaseGraphics() so
+ // explicitly lock the mutex and explicitly dispose and clear
+ // the VirtualDevice instances variables.
+ const SolarMutexGuard aSolarGuard;
+
+ maVirtualDevice.disposeAndClear();
+ maVirtualDeviceMask.disposeAndClear();
+ maAnimation.Clear();
+ maGraphic.Clear();
+ }
+
bool AnimatedGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
// do not use 'GroupPrimitive2D::operator==' here, that would compare
@@ -444,7 +526,7 @@ namespace drawinglayer::primitive2d
if (aRetval.is())
{
- rVisitor.append(aRetval);
+ rVisitor.visit(aRetval);
return;
}
@@ -463,26 +545,72 @@ namespace drawinglayer::primitive2d
if (aRetval.is())
{
- rVisitor.append(aRetval);
+ rVisitor.visit(aRetval);
return;
}
// did not work (not buffered and not 1st frame), create from buffer
aRetval = createFromBuffer();
- rVisitor.append(aRetval);
+ rVisitor.visit(aRetval);
+ }
+
+ basegfx::B2DRange AnimatedGraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ // get object's range
+ basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+ aUnitRange.transform(getTransform());
+
+ // intersect with visible part
+ aUnitRange.intersect(rViewInformation.getViewport());
+
+ return aUnitRange;
}
} // end of namespace
namespace drawinglayer::primitive2d
{
+ Primitive2DReference createFillGraphicPrimitive2D(
+ const basegfx::B2DHomMatrix& rTransform,
+ const drawinglayer::attribute::FillGraphicAttribute& rFillGraphicAttribute,
+ double fTransparency)
+ {
+ if (basegfx::fTools::equal(fTransparency, 1.0))
+ {
+ // completely transparent, done
+ return nullptr;
+ }
+
+ const Graphic& rGraphic(rFillGraphicAttribute.getGraphic());
+ const GraphicType aType(rGraphic.GetType());
+
+ if (GraphicType::Bitmap == aType && rGraphic.IsAnimated())
+ {
+ return new AnimatedGraphicPrimitive2D(
+ rGraphic,
+ &rFillGraphicAttribute,
+ rTransform,
+ fTransparency);
+ }
+
+ return new FillGraphicPrimitive2D(
+ rTransform,
+ rFillGraphicAttribute,
+ fTransparency);
+ }
+
void create2DDecompositionOfGraphic(
Primitive2DContainer& rContainer,
const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform)
+ const basegfx::B2DHomMatrix& rTransform,
+ double fTransparency)
{
- Primitive2DContainer aRetval;
+ if (basegfx::fTools::equal(fTransparency, 1.0))
+ {
+ // completely transparent, done
+ return;
+ }
switch(rGraphic.GetType())
{
@@ -490,18 +618,20 @@ namespace drawinglayer::primitive2d
{
if(rGraphic.IsAnimated())
{
- // prepare specialized AnimatedGraphicPrimitive2D
- aRetval.resize(1);
- aRetval[0] = new AnimatedGraphicPrimitive2D(
+ // prepare specialized AnimatedGraphicPrimitive2D, now with
+ // support for alpha
+ rContainer.append(new AnimatedGraphicPrimitive2D(
rGraphic,
- rTransform);
+ nullptr,
+ rTransform,
+ fTransparency));
}
else if(rGraphic.getVectorGraphicData())
{
// embedded Vector Graphic Data fill, create embed transform
const basegfx::B2DRange& rSvgRange(rGraphic.getVectorGraphicData()->getRange());
- if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0))
+ if(rSvgRange.getWidth() > 0.0 && rSvgRange.getHeight() > 0.0)
{
// translate back to origin, scale to unit coordinates
basegfx::B2DHomMatrix aEmbedVectorGraphic(
@@ -517,18 +647,37 @@ namespace drawinglayer::primitive2d
aEmbedVectorGraphic = rTransform * aEmbedVectorGraphic;
// add Vector Graphic Data primitives embedded
- aRetval.resize(1);
- aRetval[0] = new TransformPrimitive2D(
- aEmbedVectorGraphic,
- rGraphic.getVectorGraphicData()->getPrimitive2DSequence());
+ rtl::Reference<BasePrimitive2D> aPrimitive(
+ new TransformPrimitive2D(
+ aEmbedVectorGraphic,
+ Primitive2DContainer(rGraphic.getVectorGraphicData()->getPrimitive2DSequence())));
+
+ // if needed embed to UnifiedTransparencePrimitive2D
+ if (!basegfx::fTools::equalZero(fTransparency, 0.0))
+ aPrimitive = new UnifiedTransparencePrimitive2D(
+ Primitive2DContainer { aPrimitive }, fTransparency);
+
+ rContainer.append(aPrimitive);
}
}
else
{
- aRetval.resize(1);
- aRetval[0] = new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(rGraphic.GetBitmapEx()),
- rTransform);
+ // dependent of transparency used create the needed bitmap primitive
+ if (basegfx::fTools::equalZero(fTransparency))
+ {
+ rContainer.append(
+ new BitmapPrimitive2D(
+ rGraphic.GetBitmap(),
+ rTransform));
+ }
+ else
+ {
+ rContainer.append(
+ new BitmapAlphaPrimitive2D(
+ rGraphic.GetBitmap(),
+ rTransform,
+ fTransparency));
+ }
}
break;
@@ -539,10 +688,10 @@ namespace drawinglayer::primitive2d
// create MetafilePrimitive2D
const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile();
- aRetval.resize(1);
- aRetval[0] = new MetafilePrimitive2D(
- rTransform,
- rMetafile);
+ rtl::Reference<BasePrimitive2D> aPrimitive(
+ new MetafilePrimitive2D(
+ rTransform,
+ rMetafile));
// #i100357# find out if clipping is needed for this primitive. Unfortunately,
// there exist Metafiles who's content is bigger than the proposed PrefSize set
@@ -559,11 +708,17 @@ namespace drawinglayer::primitive2d
basegfx::B2DPolygon aMaskPolygon(basegfx::utils::createUnitPolygon());
aMaskPolygon.transform(rTransform);
- Primitive2DReference mask = new MaskPrimitive2D(
+ aPrimitive = new MaskPrimitive2D(
basegfx::B2DPolyPolygon(aMaskPolygon),
- aRetval);
- aRetval[0] = mask;
+ Primitive2DContainer { aPrimitive });
}
+
+ // if needed embed to UnifiedTransparencePrimitive2D
+ if (!basegfx::fTools::equalZero(fTransparency, 0.0))
+ aPrimitive = new UnifiedTransparencePrimitive2D(
+ Primitive2DContainer { aPrimitive }, fTransparency);
+
+ rContainer.append(aPrimitive);
break;
}
@@ -573,12 +728,10 @@ namespace drawinglayer::primitive2d
break;
}
}
-
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
}
Primitive2DContainer create2DColorModifierEmbeddingsAsNeeded(
- const Primitive2DContainer& rChildren,
+ Primitive2DContainer&& rChildren,
GraphicDrawMode aGraphicDrawMode,
double fLuminance,
double fContrast,
@@ -598,7 +751,7 @@ namespace drawinglayer::primitive2d
// set child content as retval; that is what will be used as child content in all
// embeddings from here
- aRetval = rChildren;
+ aRetval = std::move(rChildren);
if(GraphicDrawMode::Watermark == aGraphicDrawMode)
{
@@ -620,7 +773,7 @@ namespace drawinglayer::primitive2d
// convert to grey
const Primitive2DReference aPrimitiveGrey(
new ModifiedColorPrimitive2D(
- aRetval,
+ std::move(aRetval),
std::make_shared<basegfx::BColorModifier_gray>()));
aRetval = Primitive2DContainer { aPrimitiveGrey };
@@ -631,7 +784,7 @@ namespace drawinglayer::primitive2d
// convert to mono (black/white with threshold 0.5)
const Primitive2DReference aPrimitiveBlackAndWhite(
new ModifiedColorPrimitive2D(
- aRetval,
+ std::move(aRetval),
std::make_shared<basegfx::BColorModifier_black_and_white>(0.5)));
aRetval = Primitive2DContainer { aPrimitiveBlackAndWhite };
@@ -657,7 +810,7 @@ namespace drawinglayer::primitive2d
{
const Primitive2DReference aPrimitiveRGBLuminannceContrast(
new ModifiedColorPrimitive2D(
- aRetval,
+ std::move(aRetval),
std::make_shared<basegfx::BColorModifier_RGBLuminanceContrast>(
fRed,
fGreen,
@@ -673,7 +826,7 @@ namespace drawinglayer::primitive2d
{
const Primitive2DReference aPrimitiveGamma(
new ModifiedColorPrimitive2D(
- aRetval,
+ std::move(aRetval),
std::make_shared<basegfx::BColorModifier_gamma>(
fGamma)));
@@ -685,7 +838,7 @@ namespace drawinglayer::primitive2d
{
const Primitive2DReference aPrimitiveInvert(
new ModifiedColorPrimitive2D(
- aRetval,
+ std::move(aRetval),
std::make_shared<basegfx::BColorModifier_invert>()));
aRetval = Primitive2DContainer { aPrimitiveInvert };
diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
index e1d0841678e2..dd6cca55fad6 100644
--- a/drawinglayer/source/primitive2d/gridprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
@@ -20,9 +20,11 @@
#include <drawinglayer/primitive2d/gridprimitive2d.hxx>
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -30,10 +32,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void GridPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference GridPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
if(!(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0))
- return;
+ return nullptr;
// decompose grid matrix to get logic size
basegfx::B2DVector aScale, aTranslate;
@@ -158,7 +160,7 @@ namespace drawinglayer::primitive2d
}
if(aExtendedViewport.isEmpty())
- return;
+ return nullptr;
// prepare point vectors for point and cross markers
std::vector< basegfx::B2DPoint > aPositionsPoint;
@@ -228,29 +230,31 @@ namespace drawinglayer::primitive2d
const sal_uInt32 nCountCross(aPositionsCross.size());
// add PointArrayPrimitive2D if point markers were added
+ Primitive2DContainer aContainer;
if(nCountPoint)
{
- rContainer.push_back(new PointArrayPrimitive2D(aPositionsPoint, getBColor()));
+ aContainer.push_back(new PointArrayPrimitive2D(std::move(aPositionsPoint), getBColor()));
}
// add MarkerArrayPrimitive2D if cross markers were added
if(!nCountCross)
- return;
+ return new GroupPrimitive2D(std::move(aContainer));
if(!getSubdivisionsX() && !getSubdivisionsY())
{
// no subdivisions, so fall back to points at grid positions, no need to
// visualize a difference between divisions and sub-divisions
- rContainer.push_back(new PointArrayPrimitive2D(aPositionsCross, getBColor()));
+ aContainer.push_back(new PointArrayPrimitive2D(std::move(aPositionsCross), getBColor()));
}
else
{
- rContainer.push_back(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker()));
+ aContainer.push_back(new MarkerArrayPrimitive2D(std::move(aPositionsCross), getCrossMarker()));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
GridPrimitive2D::GridPrimitive2D(
- const basegfx::B2DHomMatrix& rTransform,
+ basegfx::B2DHomMatrix aTransform,
double fWidth,
double fHeight,
double fSmallestViewDistance,
@@ -258,9 +262,8 @@ namespace drawinglayer::primitive2d
sal_uInt32 nSubdivisionsX,
sal_uInt32 nSubdivisionsY,
const basegfx::BColor& rBColor,
- const BitmapEx& rCrossMarker)
- : BufferedDecompositionPrimitive2D(),
- maTransform(rTransform),
+ const Bitmap& rCrossMarker)
+ : maTransform(std::move(aTransform)),
mfWidth(fWidth),
mfHeight(fHeight),
mfSmallestViewDistance(fSmallestViewDistance),
@@ -268,9 +271,7 @@ namespace drawinglayer::primitive2d
mnSubdivisionsX(nSubdivisionsX),
mnSubdivisionsY(nSubdivisionsY),
maBColor(rBColor),
- maCrossMarker(rCrossMarker),
- maLastObjectToViewTransformation(),
- maLastViewport()
+ maCrossMarker(rCrossMarker)
{
}
@@ -308,18 +309,16 @@ namespace drawinglayer::primitive2d
void GridPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- if(!getBuffered2DDecomposition().empty())
+ if(hasBuffered2DDecomposition())
{
if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
{
// conditions of last local decomposition have changed, delete
- const_cast< GridPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< GridPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember ViewRange and ViewTransformation
const_cast< GridPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
@@ -331,7 +330,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(GridPrimitive2D, PRIMITIVE2D_ID_GRIDPRIMITIVE2D)
+ sal_uInt32 GridPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_GRIDPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/groupprimitive2d.cxx b/drawinglayer/source/primitive2d/groupprimitive2d.cxx
index 63f21f842b2b..e6428c09e8cd 100644
--- a/drawinglayer/source/primitive2d/groupprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/groupprimitive2d.cxx
@@ -26,13 +26,12 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- GroupPrimitive2D::GroupPrimitive2D( const Primitive2DContainer& rChildren )
- : BasePrimitive2D(),
- maChildren(rChildren)
+ GroupPrimitive2D::GroupPrimitive2D( Primitive2DContainer&& aChildren )
+ : maChildren(std::move(aChildren))
{
}
- /** The compare opertator uses the Sequence::==operator, so only checking if
+ /** The compare operator uses the Sequence::==operator, so only checking if
the references are equal. All non-equal references are interpreted as
non-equal.
*/
@@ -54,22 +53,22 @@ namespace drawinglayer::primitive2d
getChildren(rVisitor);
}
- sal_Int64 SAL_CALL GroupPrimitive2D::estimateUsage()
+ sal_Int64 GroupPrimitive2D::estimateUsage()
{
size_t nRet(0);
for (auto& it : getChildren())
{
- uno::Reference<util::XAccounting> const xAcc(it, uno::UNO_QUERY);
- if (xAcc.is())
- {
- nRet += xAcc->estimateUsage();
- }
+ if (it)
+ nRet += it->estimateUsage();
}
return nRet;
}
// provide unique ID
- ImplPrimitive2DIDBlock(GroupPrimitive2D, PRIMITIVE2D_ID_GROUPPRIMITIVE2D)
+ sal_uInt32 GroupPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_GROUPPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/helplineprimitive2d.cxx b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx
index 86c3b88ca6d5..e09c4db606d0 100644
--- a/drawinglayer/source/primitive2d/helplineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx
@@ -19,10 +19,11 @@
#include <drawinglayer/primitive2d/helplineprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
using namespace com::sun::star;
@@ -30,14 +31,14 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void HelplinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference HelplinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
if(rViewInformation.getViewport().isEmpty() || getDirection().equalZero())
- return;
+ return nullptr;
// position to view coordinates, DashLen and DashLen in logic
const basegfx::B2DPoint aViewPosition(rViewInformation.getObjectToViewTransformation() * getPosition());
-
+ Primitive2DReference xRet;
switch(getStyle())
{
default : // HelplineStyle2D::Point
@@ -52,8 +53,7 @@ namespace drawinglayer::primitive2d
aLineA.append(aStartA);
aLineA.append(aEndA);
aLineA.transform(rViewInformation.getInverseObjectToViewTransformation());
- PolygonMarkerPrimitive2D* pNewA = new PolygonMarkerPrimitive2D(aLineA, getRGBColA(), getRGBColB(), getDiscreteDashLength());
- rContainer.push_back(pNewA);
+ auto xMarker1 = new PolygonMarkerPrimitive2D(std::move(aLineA), getRGBColA(), getRGBColB(), getDiscreteDashLength());
const basegfx::B2DVector aPerpendicularNormalizedDirection(basegfx::getPerpendicular(aNormalizedDirection));
const basegfx::B2DPoint aStartB(aViewPosition - aPerpendicularNormalizedDirection);
@@ -62,9 +62,9 @@ namespace drawinglayer::primitive2d
aLineB.append(aStartB);
aLineB.append(aEndB);
aLineB.transform(rViewInformation.getInverseObjectToViewTransformation());
- PolygonMarkerPrimitive2D* pNewB = new PolygonMarkerPrimitive2D(aLineB, getRGBColA(), getRGBColB(), getDiscreteDashLength());
- rContainer.push_back(pNewB);
+ auto xMarker2 = new PolygonMarkerPrimitive2D(std::move(aLineB), getRGBColA(), getRGBColB(), getDiscreteDashLength());
+ xRet = new GroupPrimitive2D(Primitive2DContainer{xMarker1, xMarker2});
break;
}
case HelplineStyle2D::Line :
@@ -108,19 +108,20 @@ namespace drawinglayer::primitive2d
{
// clip against visible area
const basegfx::B2DPolyPolygon aResult(basegfx::utils::clipPolygonOnRange(aLine, rViewInformation.getDiscreteViewport(), true, true));
-
+ Primitive2DContainer aContainer;
for(sal_uInt32 a(0); a < aResult.count(); a++)
{
basegfx::B2DPolygon aPart(aResult.getB2DPolygon(a));
aPart.transform(rViewInformation.getInverseObjectToViewTransformation());
- PolygonMarkerPrimitive2D* pNew = new PolygonMarkerPrimitive2D(aPart, getRGBColA(), getRGBColB(), getDiscreteDashLength());
- rContainer.push_back(pNew);
+ aContainer.push_back(new PolygonMarkerPrimitive2D(std::move(aPart), getRGBColA(), getRGBColB(), getDiscreteDashLength()));
}
+ xRet = new GroupPrimitive2D(std::move(aContainer));
}
break;
}
}
+ return xRet;
}
HelplinePrimitive2D::HelplinePrimitive2D(
@@ -130,15 +131,12 @@ namespace drawinglayer::primitive2d
const basegfx::BColor& rRGBColA,
const basegfx::BColor& rRGBColB,
double fDiscreteDashLength)
- : BufferedDecompositionPrimitive2D(),
- maPosition(rPosition),
+ : maPosition(rPosition),
maDirection(rDirection),
meStyle(eStyle),
maRGBColA(rRGBColA),
maRGBColB(rRGBColB),
- mfDiscreteDashLength(fDiscreteDashLength),
- maLastObjectToViewTransformation(),
- maLastViewport()
+ mfDiscreteDashLength(fDiscreteDashLength)
{
}
@@ -161,18 +159,16 @@ namespace drawinglayer::primitive2d
void HelplinePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- if(!getBuffered2DDecomposition().empty())
+ if(hasBuffered2DDecomposition())
{
if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
{
// conditions of last local decomposition have changed, delete
- const_cast< HelplinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< HelplinePrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember ViewRange and ViewTransformation
const_cast< HelplinePrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
@@ -184,7 +180,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(HelplinePrimitive2D, PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D)
+ sal_uInt32 HelplinePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/hiddengeometryprimitive2d.cxx b/drawinglayer/source/primitive2d/hiddengeometryprimitive2d.cxx
index cdce8a750274..c1a5442b25af 100644
--- a/drawinglayer/source/primitive2d/hiddengeometryprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/hiddengeometryprimitive2d.cxx
@@ -27,8 +27,8 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
HiddenGeometryPrimitive2D::HiddenGeometryPrimitive2D(
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
@@ -42,7 +42,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(HiddenGeometryPrimitive2D, PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D)
+ sal_uInt32 HiddenGeometryPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/invertprimitive2d.cxx b/drawinglayer/source/primitive2d/invertprimitive2d.cxx
index 63c4be5246ac..e2d01381e1a9 100644
--- a/drawinglayer/source/primitive2d/invertprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/invertprimitive2d.cxx
@@ -27,13 +27,16 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
InvertPrimitive2D::InvertPrimitive2D(
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(InvertPrimitive2D, PRIMITIVE2D_ID_INVERTPRIMITIVE2D)
+ sal_uInt32 InvertPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_INVERTPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx
index d4b604e79c9f..64364f0df407 100644
--- a/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx
@@ -22,6 +22,7 @@
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <toolkit/helper/vclunohelper.hxx>
@@ -30,19 +31,19 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void MarkerArrayPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference MarkerArrayPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
const std::vector< basegfx::B2DPoint >& rPositions = getPositions();
const sal_uInt32 nMarkerCount(rPositions.size());
- if(!(nMarkerCount && !getMarker().IsEmpty()))
- return;
+ if(!nMarkerCount || getMarker().IsEmpty())
+ return nullptr;
// get pixel size
Size aBitmapSize(getMarker().GetSizePixel());
if(!(aBitmapSize.Width() && aBitmapSize.Height()))
- return;
+ return nullptr;
// get logic half pixel size
basegfx::B2DVector aLogicHalfSize(rViewInformation.getInverseObjectToViewTransformation() *
@@ -51,9 +52,9 @@ namespace drawinglayer::primitive2d
// use half size for expand
aLogicHalfSize *= 0.5;
- for(sal_uInt32 a(0); a < nMarkerCount; a++)
+ Primitive2DContainer aContainer;
+ for(const auto& rPosition : rPositions)
{
- const basegfx::B2DPoint& rPosition(rPositions[a]);
const basegfx::B2DRange aRange(rPosition - aLogicHalfSize, rPosition + aLogicHalfSize);
basegfx::B2DHomMatrix aTransform;
@@ -62,18 +63,18 @@ namespace drawinglayer::primitive2d
aTransform.set(0, 2, aRange.getMinX());
aTransform.set(1, 2, aRange.getMinY());
- rContainer.push_back(
+ aContainer.push_back(
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getMarker()),
+ getMarker(),
aTransform));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
MarkerArrayPrimitive2D::MarkerArrayPrimitive2D(
- const std::vector< basegfx::B2DPoint >& rPositions,
- const BitmapEx& rMarker)
- : BufferedDecompositionPrimitive2D(),
- maPositions(rPositions),
+ std::vector< basegfx::B2DPoint >&& rPositions,
+ const Bitmap& rMarker)
+ : maPositions(std::move(rPositions)),
maMarker(rMarker)
{
}
@@ -128,7 +129,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(MarkerArrayPrimitive2D, PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D)
+ sal_uInt32 MarkerArrayPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/maskprimitive2d.cxx b/drawinglayer/source/primitive2d/maskprimitive2d.cxx
index 1e8af509c157..630548861a90 100644
--- a/drawinglayer/source/primitive2d/maskprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/maskprimitive2d.cxx
@@ -19,6 +19,7 @@
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -27,10 +28,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
MaskPrimitive2D::MaskPrimitive2D(
- const basegfx::B2DPolyPolygon& rMask,
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren),
- maMask(rMask)
+ basegfx::B2DPolyPolygon aMask,
+ Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren)),
+ maMask(std::move(aMask))
{
}
@@ -52,7 +53,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(MaskPrimitive2D, PRIMITIVE2D_ID_MASKPRIMITIVE2D)
+ sal_uInt32 MaskPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_MASKPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/mediaprimitive2d.cxx b/drawinglayer/source/primitive2d/mediaprimitive2d.cxx
index 5158c6822492..eb70c7602c8c 100644
--- a/drawinglayer/source/primitive2d/mediaprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/mediaprimitive2d.cxx
@@ -21,6 +21,7 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <utility>
#include <vcl/GraphicObject.hxx>
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
@@ -31,7 +32,7 @@
namespace drawinglayer::primitive2d
{
- void MediaPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference MediaPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
Primitive2DContainer xRetval;
xRetval.resize(1);
@@ -69,7 +70,7 @@ namespace drawinglayer::primitive2d
{
// shrunk primitive has no content (zero size in X or Y), nothing to display. Still create
// invisible content for HitTest and BoundRect
- const Primitive2DReference xHiddenLines(new HiddenGeometryPrimitive2D(xRetval));
+ const Primitive2DReference xHiddenLines(new HiddenGeometryPrimitive2D(std::move(xRetval)));
xRetval = Primitive2DContainer { xHiddenLines, };
}
@@ -82,26 +83,26 @@ namespace drawinglayer::primitive2d
aTransform.translate(aDestRange.getMinX(), aDestRange.getMinY());
// add transform primitive
- const Primitive2DReference aScaled(new TransformPrimitive2D(aTransform, xRetval));
- xRetval = Primitive2DContainer { aScaled };
+ xRetval = Primitive2DContainer {
+ new TransformPrimitive2D(aTransform, std::move(xRetval)) // Scaled
+ };
}
}
- rContainer.insert(rContainer.end(), xRetval.begin(), xRetval.end());
+ return new GroupPrimitive2D(std::move(xRetval));
}
MediaPrimitive2D::MediaPrimitive2D(
- const basegfx::B2DHomMatrix& rTransform,
- const OUString& rURL,
+ basegfx::B2DHomMatrix aTransform,
+ OUString aURL,
const basegfx::BColor& rBackgroundColor,
sal_uInt32 nDiscreteBorder,
- const Graphic &rSnapshot)
- : BufferedDecompositionPrimitive2D(),
- maTransform(rTransform),
- maURL(rURL),
+ Graphic aSnapshot)
+ : maTransform(std::move(aTransform)),
+ maURL(std::move(aURL)),
maBackgroundColor(rBackgroundColor),
mnDiscreteBorder(nDiscreteBorder),
- maSnapshot(rSnapshot)
+ maSnapshot(std::move(aSnapshot))
{
}
@@ -114,7 +115,8 @@ namespace drawinglayer::primitive2d
return (getTransform() == rCompare.getTransform()
&& maURL == rCompare.maURL
&& getBackgroundColor() == rCompare.getBackgroundColor()
- && getDiscreteBorder() == rCompare.getDiscreteBorder());
+ && getDiscreteBorder() == rCompare.getDiscreteBorder()
+ && maSnapshot.IsNone() == rCompare.maSnapshot.IsNone());
}
return false;
@@ -138,7 +140,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(MediaPrimitive2D, PRIMITIVE2D_ID_MEDIAPRIMITIVE2D)
+ sal_uInt32 MediaPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_MEDIAPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 362ae446fd99..a0a1550d1b66 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -18,6 +18,7 @@
*/
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <utility>
#include <wmfemfhelper.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
@@ -30,68 +31,67 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void MetafilePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference MetafilePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
// Interpret the Metafile and get the content. There should be only one target, as in the start condition,
// but iterating will be the right thing to do when some push/pop is not closed
Primitive2DContainer xRetval(wmfemfhelper::interpretMetafile(getMetaFile(), rViewInformation));
- if(!xRetval.empty())
+ if(xRetval.empty())
+ return nullptr;
+
+ // get target size
+ const ::tools::Rectangle aMtfTarget(getMetaFile().GetPrefMapMode().GetOrigin(), getMetaFile().GetPrefSize());
+ const basegfx::B2DRange aMtfRange(vcl::unotools::b2DRectangleFromRectangle(aMtfTarget));
+
+ // tdf#113197 get content range and check if we have an overlap with
+ // defined target range (aMtfRange)
+ if (!aMtfRange.isEmpty())
{
- // get target size
- const ::tools::Rectangle aMtfTarget(getMetaFile().GetPrefMapMode().GetOrigin(), getMetaFile().GetPrefSize());
- const basegfx::B2DRange aMtfRange(vcl::unotools::b2DRectangleFromRectangle(aMtfTarget));
+ const basegfx::B2DRange aContentRange(xRetval.getB2DRange(rViewInformation));
- // tdf#113197 get content range and check if we have an overlap with
- // defined target range (aMtfRange)
- if (!aMtfRange.isEmpty())
+ // also test equal since isInside gives also true for equal
+ if (!aMtfRange.equal(aContentRange) && !aMtfRange.isInside(aContentRange))
{
- const basegfx::B2DRange aContentRange(xRetval.getB2DRange(rViewInformation));
-
- // also test equal since isInside gives also true for equal
- if (!aMtfRange.equal(aContentRange) && !aMtfRange.isInside(aContentRange))
- {
- // contentRange is partly larger than aMtfRange (stuff sticks
- // outside), clipping is needed
- const drawinglayer::primitive2d::Primitive2DReference xMask(
- new drawinglayer::primitive2d::MaskPrimitive2D(
- basegfx::B2DPolyPolygon(
- basegfx::utils::createPolygonFromRect(
- aMtfRange)),
- xRetval));
-
- xRetval = drawinglayer::primitive2d::Primitive2DContainer{ xMask };
- }
+ // contentRange is partly larger than aMtfRange (stuff sticks
+ // outside), clipping is needed
+ const drawinglayer::primitive2d::Primitive2DReference xMask(
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect(
+ aMtfRange)),
+ std::move(xRetval)));
+
+ xRetval = drawinglayer::primitive2d::Primitive2DContainer{ xMask };
}
+ }
- // create transformation
- basegfx::B2DHomMatrix aAdaptedTransform;
+ // create transformation
+ basegfx::B2DHomMatrix aAdaptedTransform;
- aAdaptedTransform.translate(-aMtfTarget.Left(), -aMtfTarget.Top());
- aAdaptedTransform.scale(
- aMtfTarget.getWidth() ? 1.0 / aMtfTarget.getWidth() : 1.0,
- aMtfTarget.getHeight() ? 1.0 / aMtfTarget.getHeight() : 1.0);
- aAdaptedTransform = getTransform() * aAdaptedTransform;
+ aAdaptedTransform.translate(-aMtfTarget.Left(), -aMtfTarget.Top());
+ aAdaptedTransform.scale(
+ aMtfTarget.getOpenWidth() ? 1.0 / aMtfTarget.getOpenWidth() : 1.0,
+ aMtfTarget.getOpenHeight() ? 1.0 / aMtfTarget.getOpenHeight() : 1.0);
+ aAdaptedTransform = getTransform() * aAdaptedTransform;
- // embed to target transformation
- const Primitive2DReference aEmbeddedTransform(
- new TransformPrimitive2D(
- aAdaptedTransform,
- xRetval));
+ // embed to target transformation
+ const Primitive2DReference aEmbeddedTransform(
+ new TransformPrimitive2D(
+ aAdaptedTransform,
+ std::move(xRetval)));
- xRetval = Primitive2DContainer { aEmbeddedTransform };
- }
-
- rContainer.insert(rContainer.end(), xRetval.begin(), xRetval.end());
+ return aEmbeddedTransform;
}
MetafilePrimitive2D::MetafilePrimitive2D(
- const basegfx::B2DHomMatrix& rMetaFileTransform,
+ basegfx::B2DHomMatrix aMetaFileTransform,
const GDIMetaFile& rMetaFile)
- : BufferedDecompositionPrimitive2D(),
- maMetaFileTransform(rMetaFileTransform),
+ : maMetaFileTransform(std::move(aMetaFileTransform)),
maMetaFile(rMetaFile)
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
bool MetafilePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -126,7 +126,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(MetafilePrimitive2D, PRIMITIVE2D_ID_METAFILEPRIMITIVE2D)
+ sal_uInt32 MetafilePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_METAFILEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
index 4c0e8e6ccd18..9786f9164e7f 100644
--- a/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
@@ -19,6 +19,7 @@
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -27,10 +28,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
ModifiedColorPrimitive2D::ModifiedColorPrimitive2D(
- const Primitive2DContainer& rChildren,
- const basegfx::BColorModifierSharedPtr& rColorModifier)
- : GroupPrimitive2D(rChildren),
- maColorModifier(rColorModifier)
+ Primitive2DContainer&& aChildren,
+ basegfx::BColorModifierSharedPtr xColorModifier)
+ : GroupPrimitive2D(std::move(aChildren)),
+ maColorModifier(std::move(xColorModifier))
{
}
@@ -57,7 +58,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(ModifiedColorPrimitive2D, PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D)
+ sal_uInt32 ModifiedColorPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/objectinfoprimitive2d.cxx b/drawinglayer/source/primitive2d/objectinfoprimitive2d.cxx
index 32e66c705e62..0c91957766a4 100644
--- a/drawinglayer/source/primitive2d/objectinfoprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/objectinfoprimitive2d.cxx
@@ -18,20 +18,21 @@
*/
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <utility>
using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
ObjectInfoPrimitive2D::ObjectInfoPrimitive2D(
- const Primitive2DContainer& rChildren,
- const OUString& rName,
- const OUString& rTitle,
- const OUString& rDesc)
- : GroupPrimitive2D(rChildren),
- maName(rName),
- maTitle(rTitle),
- maDesc(rDesc)
+ Primitive2DContainer&& aChildren,
+ OUString aName,
+ OUString aTitle,
+ OUString aDesc)
+ : GroupPrimitive2D(std::move(aChildren)),
+ maName(std::move(aName)),
+ maTitle(std::move(aTitle)),
+ maDesc(std::move(aDesc))
{
}
@@ -50,7 +51,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(ObjectInfoPrimitive2D, PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D)
+ sal_uInt32 ObjectInfoPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx
index ff52e1c6e7b5..8ffd7735abd8 100644
--- a/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx
@@ -24,13 +24,16 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- PageHierarchyPrimitive2D::PageHierarchyPrimitive2D(const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ PageHierarchyPrimitive2D::PageHierarchyPrimitive2D(Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(PageHierarchyPrimitive2D, PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D)
+ sal_uInt32 PageHierarchyPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx
index b7c67bf8fd0c..a4280ea1aba0 100644
--- a/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx
@@ -24,6 +24,7 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -31,22 +32,22 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- void PagePreviewPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference PagePreviewPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
Primitive2DContainer aContent(getPageContent());
if(!(!aContent.empty()
- && basegfx::fTools::more(getContentWidth(), 0.0)
- && basegfx::fTools::more(getContentHeight(), 0.0)))
- return;
+ && getContentWidth() > 0.0)
+ && getContentHeight() > 0.0)
+ return nullptr;
// the decomposed matrix will be needed
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
- if(!(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0)))
- return;
+ if(!(aScale.getX() > 0.0 && aScale.getY() > 0.0))
+ return nullptr;
// check if content overlaps with target size and needs to be embedded with a
// clipping primitive
@@ -58,7 +59,7 @@ namespace drawinglayer::primitive2d
const Primitive2DReference xReferenceA(
new MaskPrimitive2D(
basegfx::B2DPolyPolygon(
- basegfx::utils::createPolygonFromRect(aAllowedContentRange)), aContent));
+ basegfx::utils::createPolygonFromRect(aAllowedContentRange)), std::move(aContent)));
aContent = Primitive2DContainer { xReferenceA };
}
@@ -97,19 +98,18 @@ namespace drawinglayer::primitive2d
aPageTrans = aCombined * aPageTrans;
// embed in necessary transformation to map from SdrPage to SdrPageObject
- rContainer.push_back(new TransformPrimitive2D(aPageTrans, aContent));
+ return new TransformPrimitive2D(aPageTrans, std::move(aContent));
}
PagePreviewPrimitive2D::PagePreviewPrimitive2D(
- const css::uno::Reference< css::drawing::XDrawPage >& rxDrawPage,
- const basegfx::B2DHomMatrix& rTransform,
+ css::uno::Reference< css::drawing::XDrawPage > xDrawPage,
+ basegfx::B2DHomMatrix aTransform,
double fContentWidth,
double fContentHeight,
- const Primitive2DContainer& rPageContent)
- : BufferedDecompositionPrimitive2D(),
- mxDrawPage(rxDrawPage),
- maPageContent(rPageContent),
- maTransform(rTransform),
+ Primitive2DContainer&& rPageContent)
+ : mxDrawPage(std::move(xDrawPage)),
+ maPageContent(std::move(rPageContent)),
+ maTransform(std::move(aTransform)),
mfContentWidth(fContentWidth),
mfContentHeight(fContentHeight)
{
@@ -141,7 +141,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(PagePreviewPrimitive2D, PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D)
+ sal_uInt32 PagePreviewPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
index ec1f9621452a..cf0b6ff55d4d 100644
--- a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
@@ -28,7 +28,8 @@
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <toolkit/helper/vclunohelper.hxx>
-#include <converters.hxx>
+#include <drawinglayer/converters.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -93,6 +94,30 @@ namespace drawinglayer::primitive2d
}
}
+ void PatternFillPrimitive2D::getTileSize(
+ sal_uInt32& rWidth,
+ sal_uInt32& rHeight,
+ const geometry::ViewInformation2D& rViewInformation) const
+ {
+ const basegfx::B2DRange aMaskRange(getMask().getB2DRange());
+
+ // get discrete rounded up square size of a single tile
+ const basegfx::B2DHomMatrix aMaskRangeTransformation(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aMaskRange.getRange(),
+ aMaskRange.getMinimum()));
+ const basegfx::B2DHomMatrix aTransform(
+ rViewInformation.getObjectToViewTransformation() * aMaskRangeTransformation);
+ const basegfx::B2DPoint aTopLeft(aTransform * getReferenceRange().getMinimum());
+ const basegfx::B2DPoint aX(aTransform * basegfx::B2DPoint(getReferenceRange().getMaxX(), getReferenceRange().getMinY()));
+ const basegfx::B2DPoint aY(aTransform * basegfx::B2DPoint(getReferenceRange().getMinX(), getReferenceRange().getMaxY()));
+ const double fW(basegfx::B2DVector(aX - aTopLeft).getLength());
+ const double fH(basegfx::B2DVector(aY - aTopLeft).getLength());
+
+ rWidth = basegfx::fround(ceil(fW));
+ rHeight = basegfx::fround(ceil(fH));
+ }
+
Primitive2DContainer PatternFillPrimitive2D::createContent(const geometry::ViewInformation2D& rViewInformation) const
{
Primitive2DContainer aContent;
@@ -101,29 +126,29 @@ namespace drawinglayer::primitive2d
if(0 != mnDiscreteWidth && 0 != mnDiscreteHeight)
{
const geometry::ViewInformation2D aViewInformation2D;
- const primitive2d::Primitive2DReference xEmbedRef(
- new primitive2d::TransformPrimitive2D(
- basegfx::utils::createScaleB2DHomMatrix(mnDiscreteWidth, mnDiscreteHeight),
- getChildren()));
- const primitive2d::Primitive2DContainer xEmbedSeq { xEmbedRef };
-
- const BitmapEx aBitmapEx(
- convertToBitmapEx(
- xEmbedSeq,
+ primitive2d::Primitive2DContainer xEmbedSeq {
+ new primitive2d::TransformPrimitive2D(
+ basegfx::utils::createScaleB2DHomMatrix(mnDiscreteWidth, mnDiscreteHeight),
+ Primitive2DContainer(getChildren()))
+ };
+
+ const Bitmap aBitmap(
+ convertToBitmap(
+ std::move(xEmbedSeq),
aViewInformation2D,
mnDiscreteWidth,
mnDiscreteHeight,
mnDiscreteWidth * mnDiscreteHeight));
- if(!aBitmapEx.IsEmpty())
+ if(!aBitmap.IsEmpty())
{
- const Size& rBmpPix = aBitmapEx.GetSizePixel();
+ const Size aBmpPix = aBitmap.GetSizePixel();
- if(rBmpPix.Width() > 0 && rBmpPix.Height() > 0)
+ if(aBmpPix.Width() > 0 && aBmpPix.Height() > 0)
{
const primitive2d::Primitive2DReference xEmbedRefBitmap(
new primitive2d::BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(aBitmapEx),
+ aBitmap,
basegfx::B2DHomMatrix()));
aContent = primitive2d::Primitive2DContainer { xEmbedRefBitmap };
}
@@ -142,14 +167,14 @@ namespace drawinglayer::primitive2d
// check if content needs to be clipped
const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
- const basegfx::B2DRange aContentRange(getChildren().getB2DRange(rViewInformation));
+ const basegfx::B2DRange aContentRange(aContent.getB2DRange(rViewInformation));
if(!aUnitRange.isInside(aContentRange))
{
const Primitive2DReference xRef(
new MaskPrimitive2D(
basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aUnitRange)),
- aContent));
+ std::move(aContent)));
aContent = Primitive2DContainer { xRef };
}
@@ -158,20 +183,39 @@ namespace drawinglayer::primitive2d
return aContent;
}
- void PatternFillPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ // create buffered content in given resolution
+ Bitmap PatternFillPrimitive2D::createTileImage(sal_uInt32 nWidth, sal_uInt32 nHeight) const
+ {
+ const geometry::ViewInformation2D aViewInformation2D;
+ Primitive2DContainer aContent(createContent(aViewInformation2D));
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(
+ basegfx::utils::createScaleB2DHomMatrix(nWidth, nHeight),
+ std::move(aContent)));
+ primitive2d::Primitive2DContainer xEmbedSeq { xEmbedRef };
+
+ return convertToBitmap(
+ std::move(xEmbedSeq),
+ aViewInformation2D,
+ nWidth,
+ nHeight,
+ nWidth * nHeight);
+ }
+
+ Primitive2DReference PatternFillPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
Primitive2DContainer aRetval;
if(getChildren().empty())
- return;
+ return nullptr;
if(!(!getReferenceRange().isEmpty() && getReferenceRange().getWidth() > 0.0 && getReferenceRange().getHeight() > 0.0))
- return;
+ return nullptr;
const basegfx::B2DRange aMaskRange(getMask().getB2DRange());
if(!(!aMaskRange.isEmpty() && aMaskRange.getWidth() > 0.0 && aMaskRange.getHeight() > 0.0))
- return;
+ return nullptr;
// create tiling matrices
std::vector< basegfx::B2DHomMatrix > aMatrices;
@@ -180,7 +224,7 @@ namespace drawinglayer::primitive2d
aTiling.appendTransformations(aMatrices);
// create content
- const Primitive2DContainer aContent(createContent(rViewInformation));
+ Primitive2DContainer aContent(createContent(rViewInformation));
// resize result
aRetval.resize(aMatrices.size());
@@ -190,7 +234,7 @@ namespace drawinglayer::primitive2d
{
aRetval[a] = new TransformPrimitive2D(
aMatrices[a],
- aContent);
+ Primitive2DContainer(aContent));
}
// transform result which is in unit coordinates to mask's object coordinates
@@ -200,30 +244,26 @@ namespace drawinglayer::primitive2d
aMaskRange.getRange(),
aMaskRange.getMinimum()));
- const Primitive2DReference xRef(
- new TransformPrimitive2D(
- aMaskTransform,
- aRetval));
-
- aRetval = Primitive2DContainer { xRef };
+ aRetval = Primitive2DContainer {
+ new TransformPrimitive2D(
+ aMaskTransform,
+ std::move(aRetval))
+ };
}
// embed result in mask
- {
- rContainer.push_back(
- new MaskPrimitive2D(
- getMask(),
- aRetval));
- }
+ return
+ new MaskPrimitive2D(
+ getMask(),
+ std::move(aRetval));
}
PatternFillPrimitive2D::PatternFillPrimitive2D(
- const basegfx::B2DPolyPolygon& rMask,
- const Primitive2DContainer& rChildren,
+ basegfx::B2DPolyPolygon aMask,
+ Primitive2DContainer&& rChildren,
const basegfx::B2DRange& rReferenceRange)
- : BufferedDecompositionPrimitive2D(),
- maMask(rMask),
- maChildren(rChildren),
+ : maMask(std::move(aMask)),
+ maChildren(std::move(rChildren)),
maReferenceRange(rReferenceRange),
mnDiscreteWidth(0),
mnDiscreteHeight(0)
@@ -301,29 +341,27 @@ namespace drawinglayer::primitive2d
PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
pThat->mnDiscreteWidth = nW;
pThat->mnDiscreteHeight = nH;
- pThat->setBuffered2DDecomposition(Primitive2DContainer());
+ pThat->setBuffered2DDecomposition(nullptr);
}
// call parent
BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
}
- sal_Int64 SAL_CALL PatternFillPrimitive2D::estimateUsage()
+ sal_Int64 PatternFillPrimitive2D::estimateUsage()
{
size_t nRet(0);
for (auto& it : getChildren())
- {
- uno::Reference<util::XAccounting> const xAcc(it, uno::UNO_QUERY);
- if (xAcc.is())
- {
- nRet += xAcc->estimateUsage();
- }
- }
+ if (it)
+ nRet += it->estimateUsage();
return nRet;
}
// provide unique ID
- ImplPrimitive2DIDBlock(PatternFillPrimitive2D, PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D)
+ sal_uInt32 PatternFillPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx b/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx
index 7e527487eb85..6299e185083c 100644
--- a/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx
@@ -27,12 +27,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
PointArrayPrimitive2D::PointArrayPrimitive2D(
- const std::vector< basegfx::B2DPoint >& rPositions,
+ std::vector< basegfx::B2DPoint >&& rPositions,
const basegfx::BColor& rRGBColor)
- : BasePrimitive2D(),
- maPositions(rPositions),
- maRGBColor(rRGBColor),
- maB2DRange()
+ : maPositions(std::move(rPositions)),
+ maRGBColor(rRGBColor)
{
}
@@ -69,7 +67,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(PointArrayPrimitive2D, PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D)
+ sal_uInt32 PointArrayPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx
index 0251910e8252..329911541d4e 100644
--- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx
@@ -17,587 +17,812 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokeArrowPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <com/sun/star/drawing/LineCap.hpp>
-
-#include <converters.hxx>
+#include <utility>
using namespace com::sun::star;
-using namespace std;
-
-namespace drawinglayer::primitive2d
+namespace
+{
+void implGrowHairline(basegfx::B2DRange& rRange,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation)
{
- PolygonHairlinePrimitive2D::PolygonHairlinePrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const basegfx::BColor& rBColor)
- : BasePrimitive2D(),
- maPolygon(rPolygon),
- maBColor(rBColor)
+ if (!rRange.isEmpty())
+ {
+ // Calculate view-dependent hairline width
+ const basegfx::B2DVector aDiscreteSize(
+ rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
+ const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
+
+ if (fDiscreteHalfLineWidth > 0.0)
{
+ rRange.grow(fDiscreteHalfLineWidth);
}
+ }
+}
+}
- bool PolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BasePrimitive2D::operator==(rPrimitive))
- {
- const PolygonHairlinePrimitive2D& rCompare = static_cast<const PolygonHairlinePrimitive2D&>(rPrimitive);
+namespace drawinglayer::primitive2d
+{
+PolygonHairlinePrimitive2D::PolygonHairlinePrimitive2D(basegfx::B2DPolygon aPolygon,
+ const basegfx::BColor& rBColor)
+ : maPolygon(std::move(aPolygon))
+ , maBColor(rBColor)
+{
+}
- return (getB2DPolygon() == rCompare.getB2DPolygon()
- && getBColor() == rCompare.getBColor());
- }
+bool PolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const PolygonHairlinePrimitive2D& rCompare
+ = static_cast<const PolygonHairlinePrimitive2D&>(rPrimitive);
- return false;
- }
+ return (getB2DPolygon() == rCompare.getB2DPolygon() && getBColor() == rCompare.getBColor());
+ }
- basegfx::B2DRange PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
- {
- // this is a hairline, thus the line width is view-dependent. Get range of polygon
- // as base size
- basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
+ return false;
+}
- if(!aRetval.isEmpty())
- {
- // Calculate view-dependent hairline width
- const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
- const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
-
- if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
- {
- aRetval.grow(fDiscreteHalfLineWidth);
- }
- }
+basegfx::B2DRange
+PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // this is a hairline, thus the line width is view-dependent. Get range of polygon
+ // as base size
+ basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
- // return range
- return aRetval;
- }
+ // Calculate and grow by view-dependent hairline width
+ implGrowHairline(aRetval, rViewInformation);
- // provide unique ID
- ImplPrimitive2DIDBlock(PolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D)
+ // return range
+ return aRetval;
+}
+// provide unique ID
+sal_uInt32 PolygonHairlinePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D;
+}
+
+SingleLinePrimitive2D::SingleLinePrimitive2D(const basegfx::B2DPoint& rStart,
+ const basegfx::B2DPoint& rEnd,
+ const basegfx::BColor& rBColor)
+ : BasePrimitive2D()
+ , maStart(rStart)
+ , maEnd(rEnd)
+ , maBColor(rBColor)
+{
+}
- void PolygonMarkerPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
- {
- // calculate logic DashLength
- const basegfx::B2DVector aDashVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(getDiscreteDashLength(), 0.0));
- const double fLogicDashLength(aDashVector.getX());
+bool SingleLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const SingleLinePrimitive2D& rCompare(
+ static_cast<const SingleLinePrimitive2D&>(rPrimitive));
- if(fLogicDashLength > 0.0 && !getRGBColorA().equal(getRGBColorB()))
- {
- // apply dashing; get line and gap snippets
- std::vector< double > aDash;
- basegfx::B2DPolyPolygon aDashedPolyPolyA;
- basegfx::B2DPolyPolygon aDashedPolyPolyB;
+ return (getStart() == rCompare.getStart() && getEnd() == rCompare.getEnd()
+ && getBColor() == rCompare.getBColor());
+ }
- aDash.push_back(fLogicDashLength);
- aDash.push_back(fLogicDashLength);
- basegfx::utils::applyLineDashing(getB2DPolygon(), aDash, &aDashedPolyPolyA, &aDashedPolyPolyB, 2.0 * fLogicDashLength);
+ return false;
+}
- rContainer.push_back(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyA, getRGBColorA()));
- rContainer.push_back(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyB, getRGBColorB()));
- }
- else
- {
- rContainer.push_back(new PolygonHairlinePrimitive2D(getB2DPolygon(), getRGBColorA()));
- }
- }
+basegfx::B2DRange
+SingleLinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ basegfx::B2DRange aRetval(getStart(), getEnd());
- PolygonMarkerPrimitive2D::PolygonMarkerPrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const basegfx::BColor& rRGBColorA,
- const basegfx::BColor& rRGBColorB,
- double fDiscreteDashLength)
- : BufferedDecompositionPrimitive2D(),
- maPolygon(rPolygon),
- maRGBColorA(rRGBColorA),
- maRGBColorB(rRGBColorB),
- mfDiscreteDashLength(fDiscreteDashLength),
- maLastInverseObjectToViewTransformation()
- {
- }
+ // Calculate and grow by view-dependent hairline width
+ implGrowHairline(aRetval, rViewInformation);
- bool PolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const PolygonMarkerPrimitive2D& rCompare = static_cast<const PolygonMarkerPrimitive2D&>(rPrimitive);
+ return aRetval;
+}
- return (getB2DPolygon() == rCompare.getB2DPolygon()
- && getRGBColorA() == rCompare.getRGBColorA()
- && getRGBColorB() == rCompare.getRGBColorB()
- && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
- }
+sal_uInt32 SingleLinePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_SINGLELINEPRIMITIVE2D;
+}
- return false;
- }
+void SingleLinePrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (getStart() == getEnd())
+ {
+ // single point
+ Primitive2DContainer aSequence = { new PointArrayPrimitive2D(
+ std::vector<basegfx::B2DPoint>{ getStart() }, getBColor()) };
+ rVisitor.visit(aSequence);
+ }
+ else
+ {
+ // line
+ Primitive2DContainer aSequence = { new PolygonHairlinePrimitive2D(
+ basegfx::B2DPolygon{ getStart(), getEnd() }, getBColor()) };
+ rVisitor.visit(aSequence);
+ }
+}
- basegfx::B2DRange PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
- {
- // this is a hairline, thus the line width is view-dependent. Get range of polygon
- // as base size
- basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
+LineRectanglePrimitive2D::LineRectanglePrimitive2D(const basegfx::B2DRange& rB2DRange,
+ const basegfx::BColor& rBColor)
+ : BasePrimitive2D()
+ , maB2DRange(rB2DRange)
+ , maBColor(rBColor)
+{
+}
- if(!aRetval.isEmpty())
- {
- // Calculate view-dependent hairline width
- const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
- const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
-
- if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
- {
- aRetval.grow(fDiscreteHalfLineWidth);
- }
- }
+bool LineRectanglePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const LineRectanglePrimitive2D& rCompare(
+ static_cast<const LineRectanglePrimitive2D&>(rPrimitive));
- // return range
- return aRetval;
- }
+ return (getB2DRange() == rCompare.getB2DRange() && getBColor() == rCompare.getBColor());
+ }
- void PolygonMarkerPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
- {
- ::osl::MutexGuard aGuard( m_aMutex );
- bool bNeedNewDecomposition(false);
+ return false;
+}
- if(!getBuffered2DDecomposition().empty())
- {
- if(rViewInformation.getInverseObjectToViewTransformation() != maLastInverseObjectToViewTransformation)
- {
- bNeedNewDecomposition = true;
- }
- }
+basegfx::B2DRange
+LineRectanglePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ basegfx::B2DRange aRetval(getB2DRange());
- if(bNeedNewDecomposition)
- {
- // conditions of last local decomposition have changed, delete
- const_cast< PolygonMarkerPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
- }
+ // Calculate and grow by view-dependent hairline width
+ implGrowHairline(aRetval, rViewInformation);
- if(getBuffered2DDecomposition().empty())
- {
- // remember last used InverseObjectToViewTransformation
- PolygonMarkerPrimitive2D* pThat = const_cast< PolygonMarkerPrimitive2D* >(this);
- pThat->maLastInverseObjectToViewTransformation = rViewInformation.getInverseObjectToViewTransformation();
- }
+ return aRetval;
+}
- // use parent implementation
- BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
- }
+sal_uInt32 LineRectanglePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_LINERECTANGLEPRIMITIVE2D;
+}
- // provide unique ID
- ImplPrimitive2DIDBlock(PolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D)
+void LineRectanglePrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
-} // end of namespace
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(getB2DRange()));
+ Primitive2DContainer aSequence = { new PolygonHairlinePrimitive2D(aPolygon, getBColor()) };
+ rVisitor.visit(aSequence);
+}
-namespace drawinglayer
+Primitive2DReference PolygonMarkerPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& rViewInformation) const
{
- namespace primitive2d
+ // calculate logic DashLength
+ const basegfx::B2DVector aDashVector(rViewInformation.getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(getDiscreteDashLength(), 0.0));
+ const double fLogicDashLength(aDashVector.getX());
+
+ if (fLogicDashLength > 0.0 && !getRGBColorA().equal(getRGBColorB()))
{
- void PolygonStrokePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
- if(!getB2DPolygon().count())
- return;
+ // apply dashing; get line and gap snippets
+ std::vector<double> aDash;
+ basegfx::B2DPolyPolygon aDashedPolyPolyA;
+ basegfx::B2DPolyPolygon aDashedPolyPolyB;
+
+ aDash.push_back(fLogicDashLength);
+ aDash.push_back(fLogicDashLength);
+ basegfx::utils::applyLineDashing(getB2DPolygon(), aDash, &aDashedPolyPolyA,
+ &aDashedPolyPolyB, 2.0 * fLogicDashLength);
+
+ Primitive2DContainer aContainer;
+ aContainer.push_back(
+ new PolyPolygonHairlinePrimitive2D(std::move(aDashedPolyPolyA), getRGBColorA()));
+ aContainer.push_back(
+ new PolyPolygonHairlinePrimitive2D(std::move(aDashedPolyPolyB), getRGBColorB()));
+ return new GroupPrimitive2D(std::move(aContainer));
+ }
+ else
+ {
+ return new PolygonHairlinePrimitive2D(getB2DPolygon(), getRGBColorA());
+ }
+}
+
+PolygonMarkerPrimitive2D::PolygonMarkerPrimitive2D(basegfx::B2DPolygon aPolygon,
+ const basegfx::BColor& rRGBColorA,
+ const basegfx::BColor& rRGBColorB,
+ double fDiscreteDashLength)
+ : maPolygon(std::move(aPolygon))
+ , maRGBColorA(rRGBColorA)
+ , maRGBColorB(rRGBColorB)
+ , mfDiscreteDashLength(fDiscreteDashLength)
+{
+}
+
+bool PolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const PolygonMarkerPrimitive2D& rCompare
+ = static_cast<const PolygonMarkerPrimitive2D&>(rPrimitive);
- // #i102241# try to simplify before usage
- const basegfx::B2DPolygon aB2DPolygon(basegfx::utils::simplifyCurveSegments(getB2DPolygon()));
- basegfx::B2DPolyPolygon aHairLinePolyPolygon;
+ return (getB2DPolygon() == rCompare.getB2DPolygon()
+ && getRGBColorA() == rCompare.getRGBColorA()
+ && getRGBColorB() == rCompare.getRGBColorB()
+ && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
+ }
- if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen())
- {
- // no line dashing, just copy
- aHairLinePolyPolygon.append(aB2DPolygon);
- }
- else
- {
- // apply LineStyle
- basegfx::utils::applyLineDashing(
- aB2DPolygon, getStrokeAttribute().getDotDashArray(),
- &aHairLinePolyPolygon, nullptr, getStrokeAttribute().getFullDotDashLen());
- }
+ return false;
+}
- const sal_uInt32 nCount(aHairLinePolyPolygon.count());
+basegfx::B2DRange
+PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // this is a hairline, thus the line width is view-dependent. Get range of polygon
+ // as base size
+ basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
- if(!getLineAttribute().isDefault() && getLineAttribute().getWidth())
- {
- // create fat line data
- const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0);
- const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
- const css::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
- basegfx::B2DPolyPolygon aAreaPolyPolygon;
- const double fMiterMinimumAngle(getLineAttribute().getMiterMinimumAngle());
-
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- // New version of createAreaGeometry; now creates bezier polygons
- aAreaPolyPolygon.append(basegfx::utils::createAreaGeometry(
- aHairLinePolyPolygon.getB2DPolygon(a),
- fHalfLineWidth,
- aLineJoin,
- aLineCap,
- basegfx::deg2rad(12.5) /* default fMaxAllowedAngle*/ ,
- 0.4 /* default fMaxPartOfEdge*/ ,
- fMiterMinimumAngle));
- }
-
- // create primitive
- for(sal_uInt32 b(0); b < aAreaPolyPolygon.count(); b++)
- {
- // put into single polyPolygon primitives to make clear that this is NOT meant
- // to be painted as a single tools::PolyPolygon (XORed as fill rule). Alternatively, a
- // melting process may be used here one day.
- const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b));
- const basegfx::BColor aColor(getLineAttribute().getColor());
- rContainer.push_back(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor));
- }
- }
- else
- {
- rContainer.push_back(
- new PolyPolygonHairlinePrimitive2D(
- aHairLinePolyPolygon,
- getLineAttribute().getColor()));
- }
- }
+ if (!aRetval.isEmpty())
+ {
+ // Calculate view-dependent hairline width
+ const basegfx::B2DVector aDiscreteSize(
+ rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
+ const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
- PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute,
- const attribute::StrokeAttribute& rStrokeAttribute)
- : BufferedDecompositionPrimitive2D(),
- maPolygon(rPolygon),
- maLineAttribute(rLineAttribute),
- maStrokeAttribute(rStrokeAttribute)
+ if (fDiscreteHalfLineWidth > 0.0)
{
- // MM01: keep these - these are no curve-decompposers but just checks
- // simplify curve segments: moved here to not need to use it
- // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect
- maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon);
+ aRetval.grow(fDiscreteHalfLineWidth);
}
+ }
+
+ // return range
+ return aRetval;
+}
+
+void PolygonMarkerPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ bool bNeedNewDecomposition(false);
- PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute)
- : BufferedDecompositionPrimitive2D(),
- maPolygon(rPolygon),
- maLineAttribute(rLineAttribute),
- maStrokeAttribute()
+ if (hasBuffered2DDecomposition())
+ {
+ if (rViewInformation.getInverseObjectToViewTransformation()
+ != maLastInverseObjectToViewTransformation)
{
- // MM01: keep these - these are no curve-decompposers but just checks
- // simplify curve segments: moved here to not need to use it
- // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect
- maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon);
+ bNeedNewDecomposition = true;
}
+ }
- bool PolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
- {
- const PolygonStrokePrimitive2D& rCompare = static_cast<const PolygonStrokePrimitive2D&>(rPrimitive);
+ if (bNeedNewDecomposition)
+ {
+ // conditions of last local decomposition have changed, delete
+ const_cast<PolygonMarkerPrimitive2D*>(this)->setBuffered2DDecomposition(nullptr);
+ }
- return (getB2DPolygon() == rCompare.getB2DPolygon()
- && getLineAttribute() == rCompare.getLineAttribute()
- && getStrokeAttribute() == rCompare.getStrokeAttribute());
- }
+ if (!hasBuffered2DDecomposition())
+ {
+ // remember last used InverseObjectToViewTransformation
+ PolygonMarkerPrimitive2D* pThat = const_cast<PolygonMarkerPrimitive2D*>(this);
+ pThat->maLastInverseObjectToViewTransformation
+ = rViewInformation.getInverseObjectToViewTransformation();
+ }
+
+ // use parent implementation
+ BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+}
+
+// provide unique ID
+sal_uInt32 PolygonMarkerPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D;
+}
+
+} // end of namespace
+
+namespace drawinglayer::primitive2d
+{
+Primitive2DReference PolygonStrokePrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (!getB2DPolygon().count())
+ return nullptr;
+
+ // #i102241# try to simplify before usage
+ const basegfx::B2DPolygon aB2DPolygon(basegfx::utils::simplifyCurveSegments(getB2DPolygon()));
+ basegfx::B2DPolyPolygon aHairLinePolyPolygon;
+
+ if (getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen())
+ {
+ // no line dashing, just copy
+ aHairLinePolyPolygon.append(aB2DPolygon);
+ }
+ else
+ {
+ // apply LineStyle
+ basegfx::utils::applyLineDashing(aB2DPolygon, getStrokeAttribute().getDotDashArray(),
+ &aHairLinePolyPolygon, nullptr,
+ getStrokeAttribute().getFullDotDashLen());
+ }
+
+ const sal_uInt32 nCount(aHairLinePolyPolygon.count());
- return false;
+ if (!getLineAttribute().isDefault() && getLineAttribute().getWidth())
+ {
+ // create fat line data
+ const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0);
+ const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
+ const css::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
+ basegfx::B2DPolyPolygon aAreaPolyPolygon;
+ const double fMiterMinimumAngle(getLineAttribute().getMiterMinimumAngle());
+
+ for (sal_uInt32 a(0); a < nCount; a++)
+ {
+ // New version of createAreaGeometry; now creates bezier polygons
+ aAreaPolyPolygon.append(basegfx::utils::createAreaGeometry(
+ aHairLinePolyPolygon.getB2DPolygon(a), fHalfLineWidth, aLineJoin, aLineCap,
+ basegfx::deg2rad(12.5) /* default fMaxAllowedAngle*/,
+ 0.4 /* default fMaxPartOfEdge*/, fMiterMinimumAngle));
}
- basegfx::B2DRange PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ // create primitive
+ Primitive2DContainer aContainer;
+ for (sal_uInt32 b(0); b < aAreaPolyPolygon.count(); b++)
{
- basegfx::B2DRange aRetval;
+ // put into single polyPolygon primitives to make clear that this is NOT meant
+ // to be painted as a single tools::PolyPolygon (XORed as fill rule). Alternatively, a
+ // melting process may be used here one day.
+ basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b));
+ const basegfx::BColor aColor(getLineAttribute().getColor());
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(std::move(aNewPolyPolygon), aColor));
+ }
+ return new GroupPrimitive2D(std::move(aContainer));
+ }
+ else
+ {
+ return new PolyPolygonHairlinePrimitive2D(std::move(aHairLinePolyPolygon),
+ getLineAttribute().getColor());
+ }
+}
+
+PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(basegfx::B2DPolygon aPolygon,
+ const attribute::LineAttribute& rLineAttribute,
+ attribute::StrokeAttribute aStrokeAttribute)
+ : maPolygon(std::move(aPolygon))
+ , maLineAttribute(rLineAttribute)
+ , maStrokeAttribute(std::move(aStrokeAttribute))
+ , maBufferedRange()
+{
+ // MM01: keep these - these are no curve-decompposers but just checks
+ // simplify curve segments: moved here to not need to use it
+ // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect
+ maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon);
+}
+
+PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(basegfx::B2DPolygon aPolygon,
+ const attribute::LineAttribute& rLineAttribute)
+ : maPolygon(std::move(aPolygon))
+ , maLineAttribute(rLineAttribute)
+ , maBufferedRange()
+{
+ // MM01: keep these - these are no curve-decompposers but just checks
+ // simplify curve segments: moved here to not need to use it
+ // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect
+ maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon);
+}
- if(getLineAttribute().getWidth())
- {
- bool bUseDecomposition(false);
-
- if(basegfx::B2DLineJoin::Miter == getLineAttribute().getLineJoin())
- {
- // if line is mitered, use parent call since mitered line
- // geometry may use more space than the geometry grown by half line width
- bUseDecomposition = true;
- }
-
- if(!bUseDecomposition && css::drawing::LineCap_SQUARE == getLineAttribute().getLineCap())
- {
- // when drawing::LineCap_SQUARE is used the below method to grow the polygon
- // range by half line width will not work, so use decomposition. Interestingly,
- // the grow method below works perfectly for LineCap_ROUND since the grow is in
- // all directions and the rounded cap needs the same grow in all directions independent
- // from its orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE
- bUseDecomposition = true;
- }
-
- if (bUseDecomposition)
- {
- // get correct range by using the decomposition fallback, reasons see above cases
-
- // ofz#947 to optimize calculating the range, turn any slow dashes into a solid line
- // when just calculating bounds
- attribute::StrokeAttribute aOrigStrokeAttribute = maStrokeAttribute;
- const_cast<PolygonStrokePrimitive2D*>(this)->maStrokeAttribute = attribute::StrokeAttribute();
- aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
- const_cast<PolygonStrokePrimitive2D*>(this)->maStrokeAttribute = aOrigStrokeAttribute;
- }
- else
- {
- // for all other B2DLINEJOIN_* get the range from the base geometry
- // and expand by half the line width
- aRetval = getB2DPolygon().getB2DRange();
- aRetval.grow(getLineAttribute().getWidth() * 0.5);
- }
- }
- else
- {
- // this is a hairline, thus the line width is view-dependent. Get range of polygon
- // as base size
- aRetval = getB2DPolygon().getB2DRange();
-
- if(!aRetval.isEmpty())
- {
- // Calculate view-dependent hairline width
- const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
- const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
-
- if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
- {
- aRetval.grow(fDiscreteHalfLineWidth);
- }
- }
- }
+bool PolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const PolygonStrokePrimitive2D& rCompare
+ = static_cast<const PolygonStrokePrimitive2D&>(rPrimitive);
- return aRetval;
- }
+ return (getB2DPolygon() == rCompare.getB2DPolygon()
+ && getLineAttribute() == rCompare.getLineAttribute()
+ && getStrokeAttribute() == rCompare.getStrokeAttribute());
+ }
- // provide unique ID
- ImplPrimitive2DIDBlock(PolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D)
+ return false;
+}
+basegfx::B2DRange
+PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (!maBufferedRange.isEmpty())
+ {
+ // use the view-independent, buffered B2DRange
+ return maBufferedRange;
+ }
+ if (getLineAttribute().getWidth())
+ {
+ bool bUseDecomposition(false);
- void PolygonWavePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ if (basegfx::B2DLineJoin::Miter == getLineAttribute().getLineJoin())
{
- if(!getB2DPolygon().count())
- return;
+ // if line is mitered, use parent call since mitered line
+ // geometry may use more space than the geometry grown by half line width
+ bUseDecomposition = true;
+ }
- const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth()));
- const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight()));
+ if (!bUseDecomposition && css::drawing::LineCap_SQUARE == getLineAttribute().getLineCap())
+ {
+ // when drawing::LineCap_SQUARE is used the below method to grow the polygon
+ // range by half line width will not work, so use decomposition. Interestingly,
+ // the grow method below works perfectly for LineCap_ROUND since the grow is in
+ // all directions and the rounded cap needs the same grow in all directions independent
+ // from its orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE
+
+ // NOTE: I thought about using [sqrt(2) * 0.5] a a factor for LineCap_SQUARE and not
+ // set bUseDecomposition. I even tried that it works. Then an auto-test failing showed
+ // not only that view-dependent stuff needs to be considered (what is done for the
+ // hairline case below), *BUT* also e.g. conversions to PNG/exports use the B2DRange
+ // of the geometry, so:
+ // - expanding by 1/2 LineWidth is OK for rounded
+ // - expanding by more (like sqrt(2) * 0.5 * LineWidth) immediately extends the size
+ // of e.g. geometry converted to PNG, plus many similar cases that cannot be thought
+ // of in advance.
+ // This means that converting those thought-experiment examples in (4) will and do lead
+ // to bigger e.g. Bitmap conversion(s), not avoiding but painting the free space. That
+ // could only be done by correctly and fully decomposing the geometry, including
+ // stroke, and accepting the cost...
+ bUseDecomposition = true;
+ }
- if(bHasWidth && bHasHeight)
+ if (bUseDecomposition)
+ {
+ // get correct range by using the decomposition fallback, reasons see above cases
+
+ // It is not a good idea to temporarily (re)set the PolygonStrokePrimitive2D
+ // to default. While it is understandable to use the speed advantage, it is
+ // bad for quite some reasons:
+ //
+ // (1) As described in include/drawinglayer/primitive2d/baseprimitive2d.hxx
+ // a Primitive is "noncopyable to make clear that a primitive is a read-only
+ // instance and copying or changing values is not intended". This is the base
+ // assumption for many decisions for Primitive handling.
+ // (2) For example, that the decomposition is *always* re-usable. It cannot change
+ // and is correct when it already exists since the values the decomposition is
+ // based on cannot change.
+ // (3) If this *is* done (like it was here) and the Primitive is derived from
+ // BufferedDecompositionPrimitive2D and thus buffers it's decomposition,
+ // the risk is that in this case the *wrong* decomposition will be used by
+ // other PrimitiveProcessors. Maybe not by the VclPixelProcessor2D/VclProcessor2D
+ // since it handles this primitive directly - not even sure for all cases.
+ // Sooner or later another PrimitiveProcessor will re-use this wrong temporary
+ // decomposition, and as an error, a non-stroked line will be painted/used.
+ // (4) The B2DRange is not strictly defined as minimal bound for the geometry,
+ // but it should be as small/tight as possible. Making it larger risks more
+ // area to be invalidated (repaint) and processed (all geometric stuff,l may
+ // include future and existing exports to other formats which are or will be
+ // implemented as PrimitiveProcessor). It is easy to imagine cases with much
+ // too large B2DRange - a line with a pattern that would solve to a single
+ // small start-rectangle and rest is empty, or a circle with a stroke that
+ // makes only a quarter of it visible.
+ //
+ // The reason to do this is speed, what is a good argument. But speed should
+ // only be used if the pair of [correctness/speed] does not sacrifice the correctness
+ // over the speed.
+ // Luckily there are alternatives to solve this and to keep [correctness/speed]
+ // valid:
+ //
+ // (a) Reset the temporary decomposition after having const-casted and
+ // changed maStrokeAttribute.
+ // Disadvantage: More const-cast hacks, plus this temporary decomposition
+ // will be potentially done repeatedly (every time
+ // PolygonStrokePrimitive2D::getB2DRange is called)
+ // (b) Use a temporary, local PolygonStrokePrimitive2D here, with neutral
+ // PolygonStrokePrimitive2D and call ::getB2DRange() at it. That way
+ // the buffered decomposition will not be harmed.
+ // Disadvantage: Same as (a), decomposition will be potentially done repeatedly
+ // (c) Use a temporary, local PolygonStrokePrimitive2D and buffer B2DRange
+ // locally for this Primitive. Due to (1)/(2) this cannot change, so
+ // when calculated once it is totally legal to use it.
+ //
+ // Thus here I would use (c): It accepts the disadvantages of (4) over speed, but
+ // avoids the errors/problems from (1-4).
+ // Additional argument for this: The hairline case below *also* uses the full
+ // B2DRange of the polygon, ignoring an evtl. stroke, so (4) applies
+ if (!getStrokeAttribute().isDefault())
{
- // create waveline curve
- const basegfx::B2DPolygon aWaveline(basegfx::utils::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight()));
- rContainer.push_back(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute()));
+ // only do this if StrokeAttribute is used, else recursion may happen (!)
+ const rtl::Reference<primitive2d::PolygonStrokePrimitive2D>
+ aTemporaryPrimitiveWithoutStroke(new primitive2d::PolygonStrokePrimitive2D(
+ getB2DPolygon(), getLineAttribute()));
+ maBufferedRange
+ = aTemporaryPrimitiveWithoutStroke
+ ->BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
}
else
{
- // flat waveline, decompose to simple line primitive
- rContainer.push_back(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute()));
+ // fallback to normal decompose, that result can be used for visualization
+ // later, too. Still buffer B2DRange in maBufferedRange, so it needs to be
+ // merged into one B2DRange only once
+ maBufferedRange = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
}
}
-
- PolygonWavePrimitive2D::PolygonWavePrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute,
- const attribute::StrokeAttribute& rStrokeAttribute,
- double fWaveWidth,
- double fWaveHeight)
- : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
- mfWaveWidth(fWaveWidth),
- mfWaveHeight(fWaveHeight)
+ else
{
- if(mfWaveWidth < 0.0)
- {
- mfWaveWidth = 0.0;
- }
-
- if(mfWaveHeight < 0.0)
- {
- mfWaveHeight = 0.0;
- }
+ // for all other B2DLINEJOIN_* get the range from the base geometry
+ // and expand by half the line width.
+ maBufferedRange = getB2DPolygon().getB2DRange();
+ maBufferedRange.grow(getLineAttribute().getWidth() * 0.5);
}
- PolygonWavePrimitive2D::PolygonWavePrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute,
- double fWaveWidth,
- double fWaveHeight)
- : PolygonStrokePrimitive2D(rPolygon, rLineAttribute),
- mfWaveWidth(fWaveWidth),
- mfWaveHeight(fWaveHeight)
- {
- if(mfWaveWidth < 0.0)
- {
- mfWaveWidth = 0.0;
- }
+ return maBufferedRange;
+ }
- if(mfWaveHeight < 0.0)
- {
- mfWaveHeight = 0.0;
- }
- }
+ // It is a hairline, thus the line width is view-dependent. Get range of polygon
+ // as base size.
+ // CAUTION: Since a hairline *is* view-dependent,
+ // - either use maBufferedRange, additionally remember view-dependent
+ // factor & reset if that changes
+ // - or do not buffer for hairline -> not really needed, the range is buffered
+ // in the B2DPolygon, no decomposition is needed and a simple grow is cheap
+ basegfx::B2DRange aHairlineRange = getB2DPolygon().getB2DRange();
- bool PolygonWavePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ if (!aHairlineRange.isEmpty())
+ {
+ // Calculate view-dependent hairline width
+ const basegfx::B2DVector aDiscreteSize(
+ rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
+ const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
+
+ if (fDiscreteHalfLineWidth > 0.0)
{
- if(PolygonStrokePrimitive2D::operator==(rPrimitive))
- {
- const PolygonWavePrimitive2D& rCompare = static_cast<const PolygonWavePrimitive2D&>(rPrimitive);
+ aHairlineRange.grow(fDiscreteHalfLineWidth);
+ }
+ }
- return (getWaveWidth() == rCompare.getWaveWidth()
- && getWaveHeight() == rCompare.getWaveHeight());
- }
+ return aHairlineRange;
+}
- return false;
- }
+// provide unique ID
+sal_uInt32 PolygonStrokePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D;
+}
- basegfx::B2DRange PolygonWavePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
- {
- // get range of parent
- basegfx::B2DRange aRetval(PolygonStrokePrimitive2D::getB2DRange(rViewInformation));
+Primitive2DReference PolygonWavePrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (!getB2DPolygon().count())
+ return nullptr;
- // if WaveHeight, grow by it
- if(basegfx::fTools::more(getWaveHeight(), 0.0))
- {
- aRetval.grow(getWaveHeight());
- }
+ const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth()));
+ const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight()));
- // if line width, grow by it
- if(basegfx::fTools::more(getLineAttribute().getWidth(), 0.0))
- {
- aRetval.grow(getLineAttribute().getWidth() * 0.5);
- }
+ if (bHasWidth && bHasHeight)
+ {
+ // create waveline curve
+ basegfx::B2DPolygon aWaveline(
+ basegfx::utils::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight()));
+ return new PolygonStrokePrimitive2D(std::move(aWaveline), getLineAttribute(),
+ getStrokeAttribute());
+ }
+ else
+ {
+ // flat waveline, decompose to simple line primitive
+ return new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(),
+ getStrokeAttribute());
+ }
+}
+
+PolygonWavePrimitive2D::PolygonWavePrimitive2D(const basegfx::B2DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute,
+ const attribute::StrokeAttribute& rStrokeAttribute,
+ double fWaveWidth, double fWaveHeight)
+ : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute)
+ , mfWaveWidth(fWaveWidth)
+ , mfWaveHeight(fWaveHeight)
+{
+ if (mfWaveWidth < 0.0)
+ {
+ mfWaveWidth = 0.0;
+ }
- return aRetval;
- }
+ if (mfWaveHeight < 0.0)
+ {
+ mfWaveHeight = 0.0;
+ }
+}
+
+PolygonWavePrimitive2D::PolygonWavePrimitive2D(const basegfx::B2DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute,
+ double fWaveWidth, double fWaveHeight)
+ : PolygonStrokePrimitive2D(rPolygon, rLineAttribute)
+ , mfWaveWidth(fWaveWidth)
+ , mfWaveHeight(fWaveHeight)
+{
+ if (mfWaveWidth < 0.0)
+ {
+ mfWaveWidth = 0.0;
+ }
- // provide unique ID
- ImplPrimitive2DIDBlock(PolygonWavePrimitive2D, PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D)
+ if (mfWaveHeight < 0.0)
+ {
+ mfWaveHeight = 0.0;
+ }
+}
+bool PolygonWavePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (PolygonStrokePrimitive2D::operator==(rPrimitive))
+ {
+ const PolygonWavePrimitive2D& rCompare
+ = static_cast<const PolygonWavePrimitive2D&>(rPrimitive);
- void PolygonStrokeArrowPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
- // copy local polygon, it may be changed
- basegfx::B2DPolygon aLocalPolygon(getB2DPolygon());
- aLocalPolygon.removeDoublePoints();
- basegfx::B2DPolyPolygon aArrowA;
- basegfx::B2DPolyPolygon aArrowB;
+ return (getWaveWidth() == rCompare.getWaveWidth()
+ && getWaveHeight() == rCompare.getWaveHeight());
+ }
- if(!aLocalPolygon.isClosed() && aLocalPolygon.count() > 1)
- {
- // apply arrows
- const double fPolyLength(basegfx::utils::getLength(aLocalPolygon));
- double fStart(0.0);
- double fEnd(0.0);
- double fStartOverlap(0.0);
- double fEndOverlap(0.0);
-
- if(!getStart().isDefault() && getStart().isActive())
- {
- // create start arrow primitive and consume
- aArrowA = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(),
- fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart);
-
- // create some overlapping, compromise between straight and peaked markers
- // for marker width 0.3cm and marker line width 0.02cm
- fStartOverlap = getStart().getWidth() / 15.0;
- }
-
- if(!getEnd().isDefault() && getEnd().isActive())
- {
- // create end arrow primitive and consume
- aArrowB = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(),
- fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd);
-
- // create some overlapping
- fEndOverlap = getEnd().getWidth() / 15.0;
- }
-
- if(0.0 != fStart || 0.0 != fEnd)
- {
- // build new poly, consume something from old poly
- aLocalPolygon = basegfx::utils::getSnippetAbsolute(aLocalPolygon, fStart-fStartOverlap, fPolyLength - fEnd + fEndOverlap, fPolyLength);
- }
- }
+ return false;
+}
- // add shaft
- rContainer.push_back(new
- PolygonStrokePrimitive2D(
- aLocalPolygon, getLineAttribute(), getStrokeAttribute()));
+basegfx::B2DRange
+PolygonWavePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // get range of parent
+ basegfx::B2DRange aRetval(PolygonStrokePrimitive2D::getB2DRange(rViewInformation));
- if(aArrowA.count())
- {
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- aArrowA, getLineAttribute().getColor()));
- }
+ // if WaveHeight, grow by it
+ if (getWaveHeight() > 0.0)
+ {
+ aRetval.grow(getWaveHeight());
+ }
- if(aArrowB.count())
- {
- rContainer.push_back(
- new PolyPolygonColorPrimitive2D(
- aArrowB, getLineAttribute().getColor()));
- }
- }
+ // if line width, grow by it
+ if (getLineAttribute().getWidth() > 0.0)
+ {
+ aRetval.grow(getLineAttribute().getWidth() * 0.5);
+ }
- PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute,
- const attribute::StrokeAttribute& rStrokeAttribute,
- const attribute::LineStartEndAttribute& rStart,
- const attribute::LineStartEndAttribute& rEnd)
- : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
- maStart(rStart),
- maEnd(rEnd)
- {
- }
+ return aRetval;
+}
+
+// provide unique ID
+sal_uInt32 PolygonWavePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D;
+}
- PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
- const basegfx::B2DPolygon& rPolygon,
- const attribute::LineAttribute& rLineAttribute,
- const attribute::LineStartEndAttribute& rStart,
- const attribute::LineStartEndAttribute& rEnd)
- : PolygonStrokePrimitive2D(rPolygon, rLineAttribute),
- maStart(rStart),
- maEnd(rEnd)
+Primitive2DReference PolygonStrokeArrowPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ // copy local polygon, it may be changed
+ basegfx::B2DPolygon aLocalPolygon(getB2DPolygon());
+ aLocalPolygon.removeDoublePoints();
+ basegfx::B2DPolyPolygon aArrowA;
+ basegfx::B2DPolyPolygon aArrowB;
+
+ if (!aLocalPolygon.isClosed() && aLocalPolygon.count() > 1)
+ {
+ // apply arrows
+ const double fPolyLength(basegfx::utils::getLength(aLocalPolygon));
+ double fStart(0.0);
+ double fEnd(0.0);
+ double fStartOverlap(0.0);
+ double fEndOverlap(0.0);
+
+ if (!getStart().isDefault() && getStart().isActive())
{
+ // create start arrow primitive and consume
+ aArrowA = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(),
+ fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart);
+
+ // create some overlapping, compromise between straight and peaked markers
+ // for marker width 0.3cm and marker line width 0.02cm
+ fStartOverlap = getStart().getWidth() / 15.0;
}
- bool PolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ if (!getEnd().isDefault() && getEnd().isActive())
{
- if(PolygonStrokePrimitive2D::operator==(rPrimitive))
- {
- const PolygonStrokeArrowPrimitive2D& rCompare = static_cast<const PolygonStrokeArrowPrimitive2D&>(rPrimitive);
-
- return (getStart() == rCompare.getStart()
- && getEnd() == rCompare.getEnd());
- }
+ // create end arrow primitive and consume
+ aArrowB = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(),
+ fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd);
- return false;
+ // create some overlapping
+ fEndOverlap = getEnd().getWidth() / 15.0;
}
- basegfx::B2DRange PolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ if (0.0 != fStart || 0.0 != fEnd)
{
- if(getStart().isActive() || getEnd().isActive())
- {
- // use decomposition when line start/end is used
- return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
- }
- else
- {
- // get range from parent
- return PolygonStrokePrimitive2D::getB2DRange(rViewInformation);
- }
+ // build new poly, consume something from old poly
+ aLocalPolygon
+ = basegfx::utils::getSnippetAbsolute(aLocalPolygon, fStart - fStartOverlap,
+ fPolyLength - fEnd + fEndOverlap, fPolyLength);
}
+ }
+
+ // add shaft
+ Primitive2DContainer aContainer;
+ aContainer.push_back(new PolygonStrokePrimitive2D(std::move(aLocalPolygon), getLineAttribute(),
+ getStrokeAttribute()));
+
+ if (aArrowA.count())
+ {
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(std::move(aArrowA), getLineAttribute().getColor()));
+ }
+
+ if (aArrowB.count())
+ {
+ aContainer.push_back(
+ new PolyPolygonColorPrimitive2D(std::move(aArrowB), getLineAttribute().getColor()));
+ }
+ return new GroupPrimitive2D(std::move(aContainer));
+}
+
+PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
+ const basegfx::B2DPolygon& rPolygon, const attribute::LineAttribute& rLineAttribute,
+ const attribute::StrokeAttribute& rStrokeAttribute,
+ const attribute::LineStartEndAttribute& rStart, const attribute::LineStartEndAttribute& rEnd)
+ : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute)
+ , maStart(rStart)
+ , maEnd(rEnd)
+{
+}
+
+PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
+ const basegfx::B2DPolygon& rPolygon, const attribute::LineAttribute& rLineAttribute,
+ const attribute::LineStartEndAttribute& rStart, const attribute::LineStartEndAttribute& rEnd)
+ : PolygonStrokePrimitive2D(rPolygon, rLineAttribute)
+ , maStart(rStart)
+ , maEnd(rEnd)
+{
+}
- // provide unique ID
- ImplPrimitive2DIDBlock(PolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D)
+bool PolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (PolygonStrokePrimitive2D::operator==(rPrimitive))
+ {
+ const PolygonStrokeArrowPrimitive2D& rCompare
+ = static_cast<const PolygonStrokeArrowPrimitive2D&>(rPrimitive);
+ return (getStart() == rCompare.getStart() && getEnd() == rCompare.getEnd());
}
+
+ return false;
+}
+
+basegfx::B2DRange PolygonStrokeArrowPrimitive2D::getB2DRange(
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (getStart().isActive() || getEnd().isActive())
+ {
+ // use decomposition when line start/end is used
+ return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
+ }
+ else
+ {
+ // get range from parent
+ return PolygonStrokePrimitive2D::getB2DRange(rViewInformation);
+ }
+}
+
+// provide unique ID
+sal_uInt32 PolygonStrokeArrowPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D;
+}
+
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/primitivetools2d.cxx b/drawinglayer/source/primitive2d/primitivetools2d.cxx
index da0a378a0089..cf98fd9b26c0 100644
--- a/drawinglayer/source/primitive2d/primitivetools2d.cxx
+++ b/drawinglayer/source/primitive2d/primitivetools2d.cxx
@@ -26,19 +26,17 @@ namespace drawinglayer::primitive2d
{
void DiscreteMetricDependentPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// get the current DiscreteUnit, look at X and Y and use the maximum
const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY())));
- if(!getBuffered2DDecomposition().empty() && !basegfx::fTools::equal(fDiscreteUnit, getDiscreteUnit()))
+ if(hasBuffered2DDecomposition() && !basegfx::fTools::equal(fDiscreteUnit, getDiscreteUnit()))
{
// conditions of last local decomposition have changed, delete
- const_cast< DiscreteMetricDependentPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< DiscreteMetricDependentPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember new valid DiscreteUnit
const_cast< DiscreteMetricDependentPrimitive2D* >(this)->mfDiscreteUnit = fDiscreteUnit;
@@ -53,18 +51,16 @@ namespace drawinglayer::primitive2d
void ViewportDependentPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// get the current Viewport
const basegfx::B2DRange& rViewport = rViewInformation.getViewport();
- if(!getBuffered2DDecomposition().empty() && !rViewport.equal(getViewport()))
+ if(hasBuffered2DDecomposition() && !rViewport.equal(getViewport()))
{
// conditions of last local decomposition have changed, delete
- const_cast< ViewportDependentPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ViewportDependentPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember new valid DiscreteUnit
const_cast< ViewportDependentPrimitive2D* >(this)->maViewport = rViewport;
@@ -76,18 +72,16 @@ namespace drawinglayer::primitive2d
void ViewTransformationDependentPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// get the current ViewTransformation
const basegfx::B2DHomMatrix& rViewTransformation = rViewInformation.getViewTransformation();
- if(!getBuffered2DDecomposition().empty() && rViewTransformation != getViewTransformation())
+ if(hasBuffered2DDecomposition() && rViewTransformation != getViewTransformation())
{
// conditions of last local decomposition have changed, delete
- const_cast< ViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember new valid ViewTransformation
const_cast< ViewTransformationDependentPrimitive2D* >(this)->maViewTransformation = rViewTransformation;
@@ -99,27 +93,25 @@ namespace drawinglayer::primitive2d
void ObjectAndViewTransformationDependentPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// get the current ViewTransformation
const basegfx::B2DHomMatrix& rViewTransformation = rViewInformation.getViewTransformation();
- if(!getBuffered2DDecomposition().empty() && rViewTransformation != getViewTransformation())
+ if(hasBuffered2DDecomposition() && rViewTransformation != getViewTransformation())
{
// conditions of last local decomposition have changed, delete
- const_cast< ObjectAndViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ObjectAndViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
// get the current ObjectTransformation
const basegfx::B2DHomMatrix& rObjectTransformation = rViewInformation.getObjectTransformation();
- if(!getBuffered2DDecomposition().empty() && rObjectTransformation != getObjectTransformation())
+ if(hasBuffered2DDecomposition() && rObjectTransformation != getObjectTransformation())
{
// conditions of last local decomposition have changed, delete
- const_cast< ObjectAndViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ObjectAndViewTransformationDependentPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
// remember new valid ViewTransformation, and ObjectTransformation
const_cast< ObjectAndViewTransformationDependentPrimitive2D* >(this)->maViewTransformation = rViewTransformation;
diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
index e58c05e406af..b57f0fabbdf8 100644
--- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx
@@ -23,25 +23,30 @@
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <processor3d/zbufferprocessor3d.hxx>
#include <processor3d/shadow3dextractor.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <svtools/optionsdrawinglayer.hxx>
#include <processor3d/geometry2dextractor.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <basegfx/raster/bzpixelraster.hxx>
+#include <utility>
#include <vcl/BitmapTools.hxx>
+#include <vcl/skia/SkiaHelper.hxx>
#include <comphelper/threadpool.hxx>
+#include <comphelper/lok.hxx>
#include <toolkit/helper/vclunohelper.hxx>
+#include <officecfg/Office/Common.hxx>
using namespace com::sun::star;
namespace
{
- BitmapEx BPixelRasterToBitmapEx(const basegfx::BZPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
+ Bitmap BPixelRasterToBitmap(const basegfx::BZPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
{
- BitmapEx aRetval;
+ Bitmap aRetval;
const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
@@ -61,7 +66,7 @@ namespace
sal_uInt16 nRed(0);
sal_uInt16 nGreen(0);
sal_uInt16 nBlue(0);
- sal_uInt16 nOpacity(0);
+ sal_uInt16 nAlpha(0);
sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize));
for(sal_uInt32 c(0); c < mnAntiAlialize; c++)
@@ -69,27 +74,27 @@ namespace
for(sal_uInt32 d(0); d < mnAntiAlialize; d++)
{
const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
- nRed = nRed + rPixel.getRed();
- nGreen = nGreen + rPixel.getGreen();
- nBlue = nBlue + rPixel.getBlue();
- nOpacity = nOpacity + rPixel.getOpacity();
+ nRed += rPixel.getRed();
+ nGreen += rPixel.getGreen();
+ nBlue += rPixel.getBlue();
+ nAlpha += rPixel.getAlpha();
}
nIndex += rRaster.getWidth() - mnAntiAlialize;
}
- nOpacity = nOpacity / nDivisor;
+ nAlpha /= nDivisor;
- if(nOpacity)
+ if(nAlpha)
{
- aContent.SetPixel(y, x, Color(
- 255 - static_cast<sal_uInt8>(nOpacity),
+ aContent.SetPixel(y, x, Color(ColorAlpha,
+ static_cast<sal_uInt8>(nAlpha),
static_cast<sal_uInt8>(nRed / nDivisor),
static_cast<sal_uInt8>(nGreen / nDivisor),
static_cast<sal_uInt8>(nBlue / nDivisor) ));
}
else
- aContent.SetPixel(y, x, Color(255, 0, 0, 0));
+ aContent.SetPixel(y, x, Color(ColorAlpha, 0, 0, 0, 0));
}
}
}
@@ -103,12 +108,12 @@ namespace
{
const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
- if(rPixel.getOpacity())
+ if(rPixel.getAlpha())
{
- aContent.SetPixel(y, x, Color(255 - rPixel.getOpacity(), rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue()));
+ aContent.SetPixel(y, x, Color(ColorAlpha, rPixel.getAlpha(), rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue()));
}
else
- aContent.SetPixel(y, x, Color(255, 0, 0, 0));
+ aContent.SetPixel(y, x, Color(ColorAlpha, 0, 0, 0, 0));
}
}
}
@@ -128,8 +133,6 @@ namespace drawinglayer::primitive2d
{
bool ScenePrimitive2D::impGetShadow3D() const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// create on demand
if(!mbShadow3DChecked && !getChildren3D().empty())
{
@@ -211,8 +214,9 @@ namespace drawinglayer::primitive2d
}
}
- void ScenePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ Primitive2DReference ScenePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
+ Primitive2DContainer aContainer;
// create 2D shadows from contained 3D primitives. This creates the shadow primitives on demand and tells if
// there are some or not. Do this at start, the shadow might still be visible even when the scene is not
if(impGetShadow3D())
@@ -225,7 +229,7 @@ namespace drawinglayer::primitive2d
if(aViewRange.isEmpty() || aShadow2DRange.overlaps(aViewRange))
{
// add extracted 2d shadows (before 3d scene creations itself)
- rContainer.insert(rContainer.end(), maShadowPrimitives.begin(), maShadowPrimitives.end());
+ aContainer.append(maShadowPrimitives);
}
}
@@ -237,14 +241,13 @@ namespace drawinglayer::primitive2d
calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange);
if(aVisibleDiscreteRange.isEmpty())
- return;
+ return new GroupPrimitive2D(std::move(aContainer));
// test if discrete view size (pixel) maybe too big and limit it
double fViewSizeX(aVisibleDiscreteRange.getWidth());
double fViewSizeY(aVisibleDiscreteRange.getHeight());
const double fViewVisibleArea(fViewSizeX * fViewSizeY);
- const SvtOptionsDrawinglayer aDrawinglayerOpt;
- const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit());
+ const double fMaximumVisibleArea(officecfg::Office::Common::Drawinglayer::Quadratic3DRenderLimit::get());
double fReduceFactor(1.0);
if(fViewVisibleArea > fMaximumVisibleArea)
@@ -282,7 +285,7 @@ namespace drawinglayer::primitive2d
// determine the oversample value
static const sal_uInt16 nDefaultOversampleValue(3);
- const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0);
+ sal_uInt16 nOversampleValue(SvtOptionsDrawinglayer::IsAntiAliasing() ? nDefaultOversampleValue : 0);
geometry::ViewInformation3D aViewInformation3D(getViewInformation3D());
{
@@ -354,15 +357,65 @@ namespace drawinglayer::primitive2d
const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength());
// generate ViewSizes
- const double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength());
- const double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength());
+ double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength());
+ double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength());
// generate RasterWidth and RasterHeight for visible part
- const sal_Int32 nRasterWidth(basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1);
- const sal_Int32 nRasterHeight(basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1);
+ sal_Int32 nRasterWidth(basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1);
+ sal_Int32 nRasterHeight(basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1);
+
+ if(!rViewInformation.getReducedDisplayQuality() && comphelper::LibreOfficeKit::isActive())
+ {
+ // for this purpose allow reduced 3D quality and make a compromise
+ // between quality and speed. This is balanced between those two
+ // targets, fine-tuning/experimenting can be done with the values
+ // below.
+
+ // define some values which allow fine-tuning this feature
+ static const double fMin(80.0);
+ static const double fSqareMin(fMin * fMin);
+ static const double fMax(800.0);
+ static const double fSqareMax(fMax * fMax);
+ static const double fMaxReduction(0.65);
+
+ // get the square pixels (work on pixel numbers to get same
+ // behaviour independent of width/height relations)
+ const double fSquarePixels(nRasterWidth * nRasterHeight);
+
+ if (fSquarePixels > fSqareMin)
+ {
+ // only reduce at all when more than fSqareMin pixels needed
+ double fReduction(fMaxReduction);
+
+ if (fSquarePixels < fSqareMax)
+ {
+ // range between fSqareMin and fSqareMax, calculate a
+ // linear interpolated reduction based on square root
+ fReduction = sqrt(fSquarePixels); // [fMin .. fMax]
+ fReduction = fReduction - fMin; // [0 .. (fMax - fMin)]
+ fReduction = fReduction / (fMax - fMin); // [0 .. 1]
+ fReduction = 1.0 - (fReduction * (1.0 - fMaxReduction)); // [1 .. fMaxReduction]
+
+ // reduce oversampling for this range
+ if(nOversampleValue > 2)
+ nOversampleValue--;
+ }
+ else
+ {
+ // more than fSqareMax pixels, disable oversampling
+ nOversampleValue = 0;
+ }
+
+ // adapt needed values to reduction
+ nRasterWidth = basegfx::fround(fReduction * nRasterWidth);
+ nRasterHeight = basegfx::fround(fReduction * nRasterHeight);
+ fFullViewSizeX *= fReduction;
+ fFullViewSizeY *= fReduction;
+ }
+ }
if(!(nRasterWidth && nRasterHeight))
- return;
+ return new GroupPrimitive2D(std::move(aContainer));
// create view unit buffer
basegfx::BZPixelRaster aBZPixelRaster(
@@ -370,7 +423,10 @@ namespace drawinglayer::primitive2d
nOversampleValue ? nRasterHeight * nOversampleValue : nRasterHeight);
// check for parallel execution possibilities
- static bool bMultithreadAllowed = false; // loplugin:constvars:ignore
+ // Skia does not like being touched from multiple threads
+ // at the same time, and methods like DefaultProcessor3D::impRenderBitmapTexturePrimitive3D
+ // are going to do that.
+ static bool bMultithreadAllowed = !SkiaHelper::isVCLSkiaEnabled(); // loplugin:constvars:ignore
sal_Int32 nThreadCount(0);
comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
@@ -437,7 +493,7 @@ namespace drawinglayer::primitive2d
}
else
{
- // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process
+ // use default 3D primitive processor to create Bitmap for aUnitVisiblePart and process
processor3d::ZBufferProcessor3D aZBufferProcessor3D(
aViewInformation3D,
getSdrSceneAttribute(),
@@ -454,11 +510,11 @@ namespace drawinglayer::primitive2d
aZBufferProcessor3D.finish();
}
- const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmapEx(aBZPixelRaster, nOversampleValue);
+ const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmap(aBZPixelRaster, nOversampleValue);
const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
if(!(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()))
- return;
+ return new GroupPrimitive2D(std::move(aContainer));
// create transform for the created bitmap in discrete coordinates first.
basegfx::B2DHomMatrix aNew2DTransform;
@@ -472,9 +528,9 @@ namespace drawinglayer::primitive2d
aNew2DTransform *= aInverseOToV;
// create bitmap primitive and add
- rContainer.push_back(
+ aContainer.push_back(
new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(maOldRenderedBitmap),
+ maOldRenderedBitmap,
aNew2DTransform));
// test: Allow to add an outline in the debugger when tests are needed
@@ -484,8 +540,9 @@ namespace drawinglayer::primitive2d
{
basegfx::B2DPolygon aOutline(basegfx::utils::createUnitPolygon());
aOutline.transform(aNew2DTransform);
- rContainer.push_back(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0)));
+ aContainer.push_back(new PolygonHairlinePrimitive2D(std::move(aOutline), basegfx::BColor(1.0, 0.0, 0.0)));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
Primitive2DContainer ScenePrimitive2D::getGeometry2D() const
@@ -526,64 +583,61 @@ namespace drawinglayer::primitive2d
bool ScenePrimitive2D::tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const
{
- if(!maOldRenderedBitmap.IsEmpty() && !maOldUnitVisiblePart.isEmpty())
- {
- basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation());
- aInverseSceneTransform.invert();
- const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint);
-
- if(maOldUnitVisiblePart.isInside(aRelativePoint))
- {
- // calculate coordinates relative to visualized part
- double fDivisorX(maOldUnitVisiblePart.getWidth());
- double fDivisorY(maOldUnitVisiblePart.getHeight());
+ if(maOldRenderedBitmap.IsEmpty() || maOldUnitVisiblePart.isEmpty())
+ return false;
- if(basegfx::fTools::equalZero(fDivisorX))
- {
- fDivisorX = 1.0;
- }
+ basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation());
+ aInverseSceneTransform.invert();
+ const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint);
- if(basegfx::fTools::equalZero(fDivisorY))
- {
- fDivisorY = 1.0;
- }
+ if(!maOldUnitVisiblePart.isInside(aRelativePoint))
+ return false;
- const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX);
- const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY);
+ // calculate coordinates relative to visualized part
+ double fDivisorX(maOldUnitVisiblePart.getWidth());
+ double fDivisorY(maOldUnitVisiblePart.getHeight());
- // combine with real BitmapSizePixel to get bitmap coordinates
- const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
- const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width()));
- const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height()));
+ if(basegfx::fTools::equalZero(fDivisorX))
+ {
+ fDivisorX = 1.0;
+ }
- // try to get a statement about transparency in that pixel
- o_rResult = (0xff != maOldRenderedBitmap.GetTransparency(nX, nY));
- return true;
- }
+ if(basegfx::fTools::equalZero(fDivisorY))
+ {
+ fDivisorY = 1.0;
}
- return false;
+ const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX);
+ const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY);
+
+ // combine with real BitmapSizePixel to get bitmap coordinates
+ const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
+ const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width()));
+ const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height()));
+
+ // try to get a statement about transparency in that pixel
+ o_rResult = (0 != maOldRenderedBitmap.GetPixelColor(nX, nY).GetAlpha());
+ return true;
}
ScenePrimitive2D::ScenePrimitive2D(
- const primitive3d::Primitive3DContainer& rxChildren3D,
- const attribute::SdrSceneAttribute& rSdrSceneAttribute,
- const attribute::SdrLightingAttribute& rSdrLightingAttribute,
- const basegfx::B2DHomMatrix& rObjectTransformation,
- const geometry::ViewInformation3D& rViewInformation3D)
+ primitive3d::Primitive3DContainer aChildren3D,
+ attribute::SdrSceneAttribute aSdrSceneAttribute,
+ attribute::SdrLightingAttribute aSdrLightingAttribute,
+ basegfx::B2DHomMatrix aObjectTransformation,
+ geometry::ViewInformation3D aViewInformation3D)
: BufferedDecompositionPrimitive2D(),
- mxChildren3D(rxChildren3D),
- maSdrSceneAttribute(rSdrSceneAttribute),
- maSdrLightingAttribute(rSdrLightingAttribute),
- maObjectTransformation(rObjectTransformation),
- maViewInformation3D(rViewInformation3D),
- maShadowPrimitives(),
+ mxChildren3D(std::move(aChildren3D)),
+ maSdrSceneAttribute(std::move(aSdrSceneAttribute)),
+ maSdrLightingAttribute(std::move(aSdrLightingAttribute)),
+ maObjectTransformation(std::move(aObjectTransformation)),
+ maViewInformation3D(std::move(aViewInformation3D)),
mbShadow3DChecked(false),
mfOldDiscreteSizeX(0.0),
- mfOldDiscreteSizeY(0.0),
- maOldUnitVisiblePart(),
- maOldRenderedBitmap()
+ mfOldDiscreteSizeY(0.0)
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
bool ScenePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -631,15 +685,13 @@ namespace drawinglayer::primitive2d
void ScenePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
// get the involved ranges (see helper method calculateDiscreteSizes for details)
basegfx::B2DRange aDiscreteRange;
basegfx::B2DRange aUnitVisibleRange;
bool bNeedNewDecomposition(false);
bool bDiscreteSizesAreCalculated(false);
- if(!getBuffered2DDecomposition().empty())
+ if(hasBuffered2DDecomposition())
{
basegfx::B2DRange aVisibleDiscreteRange;
calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange);
@@ -667,10 +719,10 @@ namespace drawinglayer::primitive2d
if(bNeedNewDecomposition)
{
// conditions of last local decomposition have changed, delete
- const_cast< ScenePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+ const_cast< ScenePrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
}
- if(getBuffered2DDecomposition().empty())
+ if(!hasBuffered2DDecomposition())
{
if(!bDiscreteSizesAreCalculated)
{
@@ -690,7 +742,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(ScenePrimitive2D, PRIMITIVE2D_ID_SCENEPRIMITIVE2D)
+ sal_uInt32 ScenePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SCENEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/sdrdecompositiontools2d.cxx b/drawinglayer/source/primitive2d/sdrdecompositiontools2d.cxx
index 5080a92a8cd6..7768c1f6af2b 100644
--- a/drawinglayer/source/primitive2d/sdrdecompositiontools2d.cxx
+++ b/drawinglayer/source/primitive2d/sdrdecompositiontools2d.cxx
@@ -84,7 +84,7 @@ namespace drawinglayer::primitive2d
if(bFilled)
{
xReference = new PolyPolygonColorPrimitive2D(
- aScaledOutline,
+ std::move(aScaledOutline),
basegfx::BColor(0.0, 0.0, 0.0));
}
else
@@ -92,13 +92,12 @@ namespace drawinglayer::primitive2d
const basegfx::BColor aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0);
xReference = new PolyPolygonHairlinePrimitive2D(
- aScaledOutline,
+ std::move(aScaledOutline),
aGrayTone);
}
// create HiddenGeometryPrimitive2D
- return Primitive2DReference(
- new HiddenGeometryPrimitive2D(Primitive2DContainer { xReference }));
+ return new HiddenGeometryPrimitive2D(Primitive2DContainer { xReference });
}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
index e2c0be36ec9e..c364523b076c 100644
--- a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
@@ -22,70 +22,382 @@
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <drawinglayer/converters.hxx>
+#include "GlowSoftEgdeShadowTools.hxx"
+
+#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
+#include <tools/stream.hxx>
+#include <vcl/filter/PngImageWriter.hxx>
+#endif
-#include <sal/log.hxx>
#include <memory>
+#include <utility>
using namespace com::sun::star;
-
namespace drawinglayer::primitive2d
{
- ShadowPrimitive2D::ShadowPrimitive2D(
- const basegfx::B2DHomMatrix& rShadowTransform,
- const basegfx::BColor& rShadowColor,
- double fShadowBlur,
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren),
- maShadowTransform(rShadowTransform),
- maShadowColor(rShadowColor),
- mfShadowBlur(fShadowBlur)
+ShadowPrimitive2D::ShadowPrimitive2D(basegfx::B2DHomMatrix aShadowTransform,
+ const basegfx::BColor& rShadowColor, double fShadowBlur,
+ Primitive2DContainer&& aChildren)
+ : BufferedDecompositionGroupPrimitive2D(std::move(aChildren))
+ , maShadowTransform(std::move(aShadowTransform))
+ , maShadowColor(rShadowColor)
+ , mfShadowBlur(fShadowBlur)
+ , mfLastDiscreteBlurRadius(0.0)
+ , maLastClippedRange()
+{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
+}
+
+bool ShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionGroupPrimitive2D::operator==(rPrimitive))
+ {
+ const ShadowPrimitive2D& rCompare = static_cast<const ShadowPrimitive2D&>(rPrimitive);
+
+ return (getShadowTransform() == rCompare.getShadowTransform()
+ && getShadowColor() == rCompare.getShadowColor()
+ && getShadowBlur() == rCompare.getShadowBlur());
+ }
+
+ return false;
+}
+
+// Helper to get the to-be-shadowed geometry completely embedded to
+// a ModifiedColorPrimitive2D (change to ShadowColor) and TransformPrimitive2D
+// (direction/offset/transformation of shadow). Since this is used pretty
+// often, pack into a helper
+void ShadowPrimitive2D::getFullyEmbeddedShadowPrimitives(Primitive2DContainer& rContainer) const
+{
+ if (getChildren().empty())
+ return;
+
+ // create a modifiedColorPrimitive containing the shadow color and the content
+ basegfx::BColorModifierSharedPtr aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_replace>(getShadowColor());
+ Primitive2DReference xRefA(new ModifiedColorPrimitive2D(Primitive2DContainer(getChildren()),
+ std::move(aBColorModifier)));
+ Primitive2DContainer aSequenceB{ xRefA };
+
+ // build transformed primitiveVector with shadow offset and add to target
+ rContainer.visit(new TransformPrimitive2D(getShadowTransform(), std::move(aSequenceB)));
+}
+
+bool ShadowPrimitive2D::prepareValuesAndcheckValidity(
+ basegfx::B2DRange& rBlurRange, basegfx::B2DRange& rClippedRange,
+ basegfx::B2DVector& rDiscreteBlurSize, double& rfDiscreteBlurRadius,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ // no BlurRadius defined, done
+ if (getShadowBlur() <= 0.0)
+ return false;
+
+ // no geometry, done
+ if (getChildren().empty())
+ return false;
+
+ // no pixel target, done
+ if (rViewInformation.getObjectToViewTransformation().isIdentity())
+ return false;
+
+ // get fully embedded ShadowPrimitive
+ Primitive2DContainer aEmbedded;
+ getFullyEmbeddedShadowPrimitives(aEmbedded);
+
+ // get geometry range that defines area that needs to be pixelated
+ rBlurRange = aEmbedded.getB2DRange(rViewInformation);
+
+ // no range of geometry, done
+ if (rBlurRange.isEmpty())
+ return false;
+
+ // extend range by BlurRadius in all directions
+ rBlurRange.grow(getShadowBlur());
+
+ // initialize ClippedRange to full BlurRange -> all is visible
+ rClippedRange = rBlurRange;
+
+ // get Viewport and check if used. If empty, all is visible (see
+ // ViewInformation2D definition in viewinformation2d.hxx)
+ if (!rViewInformation.getViewport().isEmpty())
+ {
+ // if used, extend by BlurRadius to ensure needed parts are included
+ basegfx::B2DRange aVisibleArea(rViewInformation.getViewport());
+ aVisibleArea.grow(getShadowBlur());
+
+ // calculate ClippedRange
+ rClippedRange.intersect(aVisibleArea);
+
+ // if BlurRange is completely outside of VisibleArea, ClippedRange
+ // will be empty and we are done
+ if (rClippedRange.isEmpty())
+ return false;
+ }
+
+ // calculate discrete pixel size of BlurRange. If it's too small to visualize, we are done
+ rDiscreteBlurSize = rViewInformation.getObjectToViewTransformation() * rBlurRange.getRange();
+ if (ceil(rDiscreteBlurSize.getX()) < 2.0 || ceil(rDiscreteBlurSize.getY()) < 2.0)
+ return false;
+
+ // calculate discrete pixel size of BlurRadius. If it's too small to visualize, we are done
+ rfDiscreteBlurRadius = ceil(
+ (rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(getShadowBlur(), 0))
+ .getLength());
+ if (rfDiscreteBlurRadius < 1.0)
+ return false;
+
+ return true;
+}
+
+void ShadowPrimitive2D::create2DDecomposition(
+ Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (getShadowBlur() <= 0.0)
+ {
+ // Normal (non-blurred) shadow is already completely
+ // handled by get2DDecomposition and not buffered. It
+ // does not need to be since it's a simple embedding
+ // to a ModifiedColorPrimitive2D and TransformPrimitive2D
+ return;
+ }
+
+ // from here on we process a blurred shadow
+ basegfx::B2DRange aBlurRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteBlurSize;
+ double fDiscreteBlurRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aBlurRange, aClippedRange, aDiscreteBlurSize,
+ fDiscreteBlurRadius, rViewInformation))
+ return;
+
+ // Create embedding transformation from object to top-left zero-aligned
+ // target pixel geometry (discrete form of ClippedRange)
+ // First, move to top-left of BlurRange
+ const sal_uInt32 nDiscreteBlurWidth(ceil(aDiscreteBlurSize.getX()));
+ const sal_uInt32 nDiscreteBlurHeight(ceil(aDiscreteBlurSize.getY()));
+ basegfx::B2DHomMatrix aEmbedding(basegfx::utils::createTranslateB2DHomMatrix(
+ -aClippedRange.getMinX(), -aClippedRange.getMinY()));
+ // Second, scale to discrete bitmap size
+ // Even when using the offset from ClippedRange, we need to use the
+ // scaling from the full representation, thus from BlurRange
+ aEmbedding.scale(nDiscreteBlurWidth / aBlurRange.getWidth(),
+ nDiscreteBlurHeight / aBlurRange.getHeight());
+
+ // Get fully embedded ShadowPrimitives. This will also embed to
+ // ModifiedColorPrimitive2D (what is not urgently needed) to create
+ // the alpha channel, but a paint with all colors set to a single
+ // one (like shadowColor here) is often less expensive due to possible
+ // simplifications painting the primitives (e.g. gradient)
+ Primitive2DContainer aEmbedded;
+ getFullyEmbeddedShadowPrimitives(aEmbedded);
+
+ // Embed content graphics to TransformPrimitive2D
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(aEmbedding, std::move(aEmbedded)));
+ primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ // Create Bitmap using drawinglayer tooling, including a MaximumQuadraticPixel
+ // limitation to be safe and not go runtime/memory havoc. Use a pretty small
+ // limit due to this is Blurred Shadow functionality and will look good with bitmap
+ // scaling anyways. The value of 250.000 square pixels below maybe adapted as needed.
+ const basegfx::B2DVector aDiscreteClippedSize(rViewInformation.getObjectToViewTransformation()
+ * aClippedRange.getRange());
+ const sal_uInt32 nDiscreteClippedWidth(ceil(aDiscreteClippedSize.getX()));
+ const sal_uInt32 nDiscreteClippedHeight(ceil(aDiscreteClippedSize.getY()));
+ const geometry::ViewInformation2D aViewInformation2D;
+ const sal_uInt32 nMaximumQuadraticPixels(250000);
+
+ // I have now added a helper that just creates the mask without having
+ // to render the content, use it, it's faster
+ const AlphaMask aAlpha(::drawinglayer::createAlphaMask(
+ std::move(xEmbedSeq), aViewInformation2D, nDiscreteClippedWidth, nDiscreteClippedHeight,
+ nMaximumQuadraticPixels));
+
+ // if we have no shadow, we are done
+ if (aAlpha.IsEmpty())
+ return;
+
+ const Size aBitmapExSizePixel(aAlpha.GetSizePixel());
+ if (!(aBitmapExSizePixel.Width() > 0 && aBitmapExSizePixel.Height() > 0))
+ return;
+
+ // We may have to take a corrective scaling into account when the
+ // MaximumQuadraticPixel limit was used/triggered
+ double fScale(1.0);
+
+ if (static_cast<sal_uInt32>(aBitmapExSizePixel.Width()) != nDiscreteClippedWidth
+ || static_cast<sal_uInt32>(aBitmapExSizePixel.Height()) != nDiscreteClippedHeight)
+ {
+ // scale in X and Y should be the same (see fReduceFactor in createAlphaMask),
+ // so adapt numerically to a single scale value, they are integer rounded values
+ const double fScaleX(static_cast<double>(aBitmapExSizePixel.Width())
+ / static_cast<double>(nDiscreteClippedWidth));
+ const double fScaleY(static_cast<double>(aBitmapExSizePixel.Height())
+ / static_cast<double>(nDiscreteClippedHeight));
+
+ fScale = (fScaleX + fScaleY) * 0.5;
+ }
+
+ // Use the Alpha as base to blur and apply the effect
+ const AlphaMask mask(drawinglayer::primitive2d::ProcessAndBlurAlphaMask(
+ aAlpha, 0, fDiscreteBlurRadius * fScale, 0, false));
+
+ // The end result is the bitmap filled with blur color and blurred 8-bit alpha mask
+ Bitmap bmp(aAlpha.GetSizePixel(), vcl::PixelFormat::N24_BPP);
+ bmp.Erase(Color(getShadowColor()));
+ Bitmap result(bmp, mask);
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ if (bDoSaveForVisualControl)
+ {
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
{
+ SvFileStream aNew(sDumpPath + "test_shadowblur.png",
+ StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PngImageWriter aPNGWriter(aNew);
+ aPNGWriter.write(result);
}
+ }
+#endif
+
+ // Independent from discrete sizes of blur alpha creation, always
+ // map and project blur result to geometry range extended by blur
+ // radius, but to the eventually clipped instance (ClippedRange)
+ const primitive2d::Primitive2DReference xEmbedRefBitmap(
+ new BitmapPrimitive2D(result, basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aClippedRange.getWidth(), aClippedRange.getHeight(),
+ aClippedRange.getMinX(), aClippedRange.getMinY())));
+
+ rContainer = primitive2d::Primitive2DContainer{ xEmbedRefBitmap };
+}
+
+void ShadowPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (getShadowBlur() <= 0.0)
+ {
+ // normal (non-blurred) shadow
+ if (getChildren().empty())
+ return;
+
+ // get fully embedded ShadowPrimitives
+ Primitive2DContainer aEmbedded;
+ getFullyEmbeddedShadowPrimitives(aEmbedded);
- bool ShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ rVisitor.visit(aEmbedded);
+ return;
+ }
+
+ // here we have a blurred shadow, check conditions of last
+ // buffered decompose and decide re-use or re-create by using
+ // setBuffered2DDecomposition to reset local buffered version
+ basegfx::B2DRange aBlurRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteBlurSize;
+ double fDiscreteBlurRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aBlurRange, aClippedRange, aDiscreteBlurSize,
+ fDiscreteBlurRadius, rViewInformation))
+ return;
+
+ if (hasBuffered2DDecomposition())
+ {
+ // First check is to detect if the last created decompose is capable
+ // to represent the now requested visualization (see similar
+ // implementation at GlowPrimitive2D).
+ if (!maLastClippedRange.isEmpty() && !maLastClippedRange.isInside(aClippedRange))
{
- if(BasePrimitive2D::operator==(rPrimitive))
- {
- const ShadowPrimitive2D& rCompare = static_cast< const ShadowPrimitive2D& >(rPrimitive);
+ basegfx::B2DRange aLastClippedRangeAndHairline(maLastClippedRange);
- return (getShadowTransform() == rCompare.getShadowTransform()
- && getShadowColor() == rCompare.getShadowColor()
- && getShadowBlur() == rCompare.getShadowBlur());
+ if (!rViewInformation.getObjectToViewTransformation().isIdentity())
+ {
+ // Grow by view-dependent size of 1/2 pixel
+ const double fHalfPixel((rViewInformation.getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(0.5, 0))
+ .getLength());
+ aLastClippedRangeAndHairline.grow(fHalfPixel);
}
- return false;
+ if (!aLastClippedRangeAndHairline.isInside(aClippedRange))
+ {
+ // Conditions of last local decomposition have changed, delete
+ const_cast<ShadowPrimitive2D*>(this)->setBuffered2DDecomposition(
+ Primitive2DContainer());
+ }
}
+ }
- basegfx::B2DRange ShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ if (hasBuffered2DDecomposition())
+ {
+ // Second check is to react on changes of the DiscreteSoftRadius when
+ // zooming in/out (see similar implementation at ShadowPrimitive2D).
+ bool bFree(mfLastDiscreteBlurRadius <= 0.0 || fDiscreteBlurRadius <= 0.0);
+
+ if (!bFree)
{
- basegfx::B2DRange aRetval(getChildren().getB2DRange(rViewInformation));
- aRetval.grow(getShadowBlur());
- aRetval.transform(getShadowTransform());
- return aRetval;
+ const double fDiff(fabs(mfLastDiscreteBlurRadius - fDiscreteBlurRadius));
+ const double fLen(fabs(mfLastDiscreteBlurRadius) + fabs(fDiscreteBlurRadius));
+ const double fRelativeChange(fDiff / fLen);
+
+ // Use lower fixed values here to change more often, higher to change less often.
+ // Value is in the range of ]0.0 .. 1.0]
+ bFree = fRelativeChange >= 0.15;
}
- void ShadowPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ if (bFree)
{
- if(getChildren().empty())
- return;
-
- // create a modifiedColorPrimitive containing the shadow color and the content
- const basegfx::BColorModifierSharedPtr aBColorModifier =
- std::make_shared<basegfx::BColorModifier_replace>(
- getShadowColor());
- const Primitive2DReference xRefA(
- new ModifiedColorPrimitive2D(
- getChildren(),
- aBColorModifier));
- const Primitive2DContainer aSequenceB { xRefA };
-
- // build transformed primitiveVector with shadow offset and add to target
- rVisitor.append(new TransformPrimitive2D(getShadowTransform(), aSequenceB));
+ // Conditions of last local decomposition have changed, delete
+ const_cast<ShadowPrimitive2D*>(this)->setBuffered2DDecomposition(
+ Primitive2DContainer());
}
+ }
+
+ if (!hasBuffered2DDecomposition())
+ {
+ // refresh last used DiscreteBlurRadius and ClippedRange to new remembered values
+ const_cast<ShadowPrimitive2D*>(this)->mfLastDiscreteBlurRadius = fDiscreteBlurRadius;
+ const_cast<ShadowPrimitive2D*>(this)->maLastClippedRange = aClippedRange;
+ }
+
+ // call parent, that will check for empty, call create2DDecomposition and
+ // set as decomposition
+ BufferedDecompositionGroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+}
+
+basegfx::B2DRange
+ShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // Hint: Do *not* use GroupPrimitive2D::getB2DRange, that will (unnecessarily)
+ // use the decompose - what works, but is not needed here.
+ // We know the to-be-visualized geometry and the radius it needs to be extended,
+ // so simply calculate the exact needed range.
+ basegfx::B2DRange aRetval(getChildren().getB2DRange(rViewInformation));
+
+ if (getShadowBlur() > 0.0)
+ {
+ // blurred shadow, that extends the geometry
+ aRetval.grow(getShadowBlur());
+ }
+
+ aRetval.transform(getShadowTransform());
+ return aRetval;
+}
- // provide unique ID
- ImplPrimitive2DIDBlock(ShadowPrimitive2D, PRIMITIVE2D_ID_SHADOWPRIMITIVE2D)
+// provide unique ID
+sal_uInt32 ShadowPrimitive2D::getPrimitive2DID() const { return PRIMITIVE2D_ID_SHADOWPRIMITIVE2D; }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx b/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx
index 4c5b1b2c6102..66cbe5490278 100644
--- a/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx
@@ -18,20 +18,35 @@
*/
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <drawinglayer/converters.hxx>
+#include "GlowSoftEgdeShadowTools.hxx"
+
+#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
+#include <tools/stream.hxx>
+#include <vcl/filter/PngImageWriter.hxx>
+#endif
namespace drawinglayer::primitive2d
{
-SoftEdgePrimitive2D::SoftEdgePrimitive2D(double fRadius, const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+SoftEdgePrimitive2D::SoftEdgePrimitive2D(double fRadius, Primitive2DContainer&& aChildren)
+ : BufferedDecompositionGroupPrimitive2D(std::move(aChildren))
, mfRadius(fRadius)
+ , mfLastDiscreteSoftRadius(0.0)
+ , maLastClippedRange()
{
+ // activate callback to flush buffered decomposition content
+ activateFlushOnTimer();
}
bool SoftEdgePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if (GroupPrimitive2D::operator==(rPrimitive))
+ if (BufferedDecompositionGroupPrimitive2D::operator==(rPrimitive))
{
auto& rCompare = static_cast<const SoftEdgePrimitive2D&>(rPrimitive);
return getRadius() == rCompare.getRadius();
@@ -40,29 +55,305 @@ bool SoftEdgePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
return false;
}
-void SoftEdgePrimitive2D::get2DDecomposition(
- Primitive2DDecompositionVisitor& rVisitor,
+bool SoftEdgePrimitive2D::prepareValuesAndcheckValidity(
+ basegfx::B2DRange& rSoftRange, basegfx::B2DRange& rClippedRange,
+ basegfx::B2DVector& rDiscreteSoftSize, double& rfDiscreteSoftRadius,
const geometry::ViewInformation2D& rViewInformation) const
{
+ // no SoftRadius defined, done
+ if (getRadius() <= 0.0)
+ return false;
+
+ // no geometry, done
if (getChildren().empty())
+ return false;
+
+ // no pixel target, done
+ if (rViewInformation.getObjectToViewTransformation().isIdentity())
+ return false;
+
+ // get geometry range that defines area that needs to be pixelated
+ rSoftRange = getChildren().getB2DRange(rViewInformation);
+
+ // no range of geometry, done
+ if (rSoftRange.isEmpty())
+ return false;
+
+ // initialize ClippedRange to full SoftRange -> all is visible
+ rClippedRange = rSoftRange;
+
+ // get Viewport and check if used. If empty, all is visible (see
+ // ViewInformation2D definition in viewinformation2d.hxx)
+ if (!rViewInformation.getViewport().isEmpty())
+ {
+ // if used, extend by SoftRadius to ensure needed parts are included
+ // that are not visible, but influence the visible parts
+ basegfx::B2DRange aVisibleArea(rViewInformation.getViewport());
+ aVisibleArea.grow(getRadius() * 2);
+
+ // To do this correctly, it needs to be done in discrete coordinates.
+ // The object may be transformed relative to the original#
+ // ObjectTransformation, e.g. when re-used in shadow
+ aVisibleArea.transform(rViewInformation.getViewTransformation());
+ rClippedRange.transform(rViewInformation.getObjectToViewTransformation());
+
+ // calculate ClippedRange
+ rClippedRange.intersect(aVisibleArea);
+
+ // if SoftRange is completely outside of VisibleArea, ClippedRange
+ // will be empty and we are done
+ if (rClippedRange.isEmpty())
+ return false;
+
+ // convert result back to object coordinates
+ rClippedRange.transform(rViewInformation.getInverseObjectToViewTransformation());
+ }
+
+ // calculate discrete pixel size of SoftRange. If it's too small to visualize, we are done
+ rDiscreteSoftSize = rViewInformation.getObjectToViewTransformation() * rSoftRange.getRange();
+ if (ceil(rDiscreteSoftSize.getX()) < 2.0 || ceil(rDiscreteSoftSize.getY()) < 2.0)
+ return false;
+
+ // calculate discrete pixel size of SoftRadius. If it's too small to visualize, we are done
+ rfDiscreteSoftRadius = ceil(
+ (rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(getRadius(), 0))
+ .getLength());
+ if (rfDiscreteSoftRadius < 1.0)
+ return false;
+
+ return true;
+}
+
+void SoftEdgePrimitive2D::create2DDecomposition(
+ Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+{
+ // Use endless while-loop-and-break mechanism due to having multiple
+ // exit scenarios that all have to do the same thing when exiting
+ while (true)
+ {
+ basegfx::B2DRange aSoftRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteSoftSize;
+ double fDiscreteSoftRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aSoftRange, aClippedRange, aDiscreteSoftSize,
+ fDiscreteSoftRadius, rViewInformation))
+ break;
+
+ // Create embedding transformation from object to top-left zero-aligned
+ // target pixel geometry (discrete form of ClippedRange)
+ // First, move to top-left of SoftRange
+ const sal_uInt32 nDiscreteSoftWidth(ceil(aDiscreteSoftSize.getX()));
+ const sal_uInt32 nDiscreteSoftHeight(ceil(aDiscreteSoftSize.getY()));
+ basegfx::B2DHomMatrix aEmbedding(basegfx::utils::createTranslateB2DHomMatrix(
+ -aClippedRange.getMinX(), -aClippedRange.getMinY()));
+ // Second, scale to discrete bitmap size
+ // Even when using the offset from ClippedRange, we need to use the
+ // scaling from the full representation, thus from SoftRange
+ aEmbedding.scale(nDiscreteSoftWidth / aSoftRange.getWidth(),
+ nDiscreteSoftHeight / aSoftRange.getHeight());
+
+ // Embed content graphics to TransformPrimitive2D
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(aEmbedding, Primitive2DContainer(getChildren())));
+ primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ // Create Bitmap using drawinglayer tooling, including a MaximumQuadraticPixel
+ // limitation to be safe and not go runtime/memory havoc. Use a pretty small
+ // limit due to this is softEdge functionality and will look good with bitmap scaling
+ // anyways. The value of 250.000 square pixels below maybe adapted as needed.
+ const basegfx::B2DVector aDiscreteClippedSize(
+ rViewInformation.getObjectToViewTransformation() * aClippedRange.getRange());
+ const sal_uInt32 nDiscreteClippedWidth(ceil(aDiscreteClippedSize.getX()));
+ const sal_uInt32 nDiscreteClippedHeight(ceil(aDiscreteClippedSize.getY()));
+ const geometry::ViewInformation2D aViewInformation2D;
+ const sal_uInt32 nMaximumQuadraticPixels(250000);
+ // tdf#156808 force an alpha mask to be created even if it has no alpha
+ // We need an alpha mask, even if it is totally opaque, so that
+ // drawinglayer::primitive2d::ProcessAndBlurAlphaMask() can be called.
+ // Otherwise, blurring of edges will fail in cases like running in a
+ // slideshow or exporting to PDF.
+ const Bitmap aBitmap(::drawinglayer::convertToBitmap(
+ std::move(xEmbedSeq), aViewInformation2D, nDiscreteClippedWidth, nDiscreteClippedHeight,
+ nMaximumQuadraticPixels, true));
+
+ if (aBitmap.IsEmpty())
+ break;
+
+ // Get Bitmap and check size. If no content, we are done
+ const Size aBitmapSizePixel(aBitmap.GetSizePixel());
+ if (!(aBitmapSizePixel.Width() > 0 && aBitmapSizePixel.Height() > 0))
+ break;
+
+ // We may have to take a corrective scaling into account when the
+ // MaximumQuadraticPixel limit was used/triggered
+ double fScale(1.0);
+
+ if (static_cast<sal_uInt32>(aBitmapSizePixel.Width()) != nDiscreteClippedWidth
+ || static_cast<sal_uInt32>(aBitmapSizePixel.Height()) != nDiscreteClippedHeight)
+ {
+ // scale in X and Y should be the same (see fReduceFactor in convertToBitmapEx),
+ // so adapt numerically to a single scale value, they are integer rounded values
+ const double fScaleX(static_cast<double>(aBitmapSizePixel.Width())
+ / static_cast<double>(nDiscreteClippedWidth));
+ const double fScaleY(static_cast<double>(aBitmapSizePixel.Height())
+ / static_cast<double>(nDiscreteClippedHeight));
+
+ fScale = (fScaleX + fScaleY) * 0.5;
+ }
+
+ // Get the Alpha and use as base to blur and apply the effect
+ AlphaMask aMask(aBitmap.CreateAlphaMask());
+ if (aMask.IsEmpty()) // There is no mask, fully opaque
+ break;
+ AlphaMask blurMask(drawinglayer::primitive2d::ProcessAndBlurAlphaMask(
+ aMask, -fDiscreteSoftRadius * fScale, fDiscreteSoftRadius * fScale, 0));
+ aMask.BlendWith(blurMask);
+
+ // The end result is the original bitmap with blurred 8-bit alpha mask
+ Bitmap result(aBitmap.CreateColorBitmap(), aMask);
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ if (bDoSaveForVisualControl)
+ {
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
+ {
+ SvFileStream aNew(sDumpPath + "test_softedge.png",
+ StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PngImageWriter aPNGWriter(aNew);
+ aPNGWriter.write(result);
+ }
+ }
+#endif
+
+ // Independent from discrete sizes of soft alpha creation, always
+ // map and project soft result to geometry range extended by soft
+ // radius, but to the eventually clipped instance (ClippedRange)
+ const primitive2d::Primitive2DReference xEmbedRefBitmap(
+ new BitmapPrimitive2D(result, basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aClippedRange.getWidth(), aClippedRange.getHeight(),
+ aClippedRange.getMinX(), aClippedRange.getMinY())));
+
+ rContainer = primitive2d::Primitive2DContainer{ xEmbedRefBitmap };
+
+ // we made it, return
return;
+ }
- if (!mbInMaskGeneration)
+ // creation failed for some of many possible reasons, use original
+ // content, so the unmodified original geometry will be the result,
+ // just without any softEdge effect
+ rContainer = getChildren();
+}
+
+void SoftEdgePrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ // Use endless while-loop-and-break mechanism due to having multiple
+ // exit scenarios that all have to do the same thing when exiting
+ while (true)
{
- GroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+ basegfx::B2DRange aSoftRange;
+ basegfx::B2DRange aClippedRange;
+ basegfx::B2DVector aDiscreteSoftSize;
+ double fDiscreteSoftRadius(0.0);
+
+ // Check various validity details and calculate/prepare values. If false, we are done
+ if (!prepareValuesAndcheckValidity(aSoftRange, aClippedRange, aDiscreteSoftSize,
+ fDiscreteSoftRadius, rViewInformation))
+ break;
+
+ if (hasBuffered2DDecomposition())
+ {
+ // First check is to detect if the last created decompose is capable
+ // to represent the now requested visualization (see similar
+ // implementation at GlowPrimitive2D).
+ if (!maLastClippedRange.isEmpty() && !maLastClippedRange.isInside(aClippedRange))
+ {
+ basegfx::B2DRange aLastClippedRangeAndHairline(maLastClippedRange);
+
+ if (!rViewInformation.getObjectToViewTransformation().isIdentity())
+ {
+ // Grow by view-dependent size of 1/2 pixel
+ const double fHalfPixel((rViewInformation.getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(0.5, 0))
+ .getLength());
+ aLastClippedRangeAndHairline.grow(fHalfPixel);
+ }
+
+ if (!aLastClippedRangeAndHairline.isInside(aClippedRange))
+ {
+ // Conditions of last local decomposition have changed, delete
+ const_cast<SoftEdgePrimitive2D*>(this)->setBuffered2DDecomposition(
+ Primitive2DContainer());
+ }
+ }
+ }
+
+ if (hasBuffered2DDecomposition())
+ {
+ // Second check is to react on changes of the DiscreteSoftRadius when
+ // zooming in/out (see similar implementation at GlowPrimitive2D).
+ bool bFree(mfLastDiscreteSoftRadius <= 0.0 || fDiscreteSoftRadius <= 0.0);
+
+ if (!bFree)
+ {
+ const double fDiff(fabs(mfLastDiscreteSoftRadius - fDiscreteSoftRadius));
+ const double fLen(fabs(mfLastDiscreteSoftRadius) + fabs(fDiscreteSoftRadius));
+ const double fRelativeChange(fDiff / fLen);
+
+ // Use a lower value here, soft edge keeps it's content so avoid that it gets too
+ // unsharp in the pixel visualization
+ // Value is in the range of ]0.0 .. 1.0]
+ bFree = fRelativeChange >= 0.075;
+ }
+
+ if (bFree)
+ {
+ // Conditions of last local decomposition have changed, delete
+ const_cast<SoftEdgePrimitive2D*>(this)->setBuffered2DDecomposition(
+ Primitive2DContainer());
+ }
+ }
+
+ if (!hasBuffered2DDecomposition())
+ {
+ // refresh last used DiscreteSoftRadius and ClippedRange to new remembered values
+ const_cast<SoftEdgePrimitive2D*>(this)->mfLastDiscreteSoftRadius = fDiscreteSoftRadius;
+ const_cast<SoftEdgePrimitive2D*>(this)->maLastClippedRange = aClippedRange;
+ }
+
+ // call parent, that will check for empty, call create2DDecomposition and
+ // set as decomposition
+ BufferedDecompositionGroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+
+ // we made it, return
return;
}
- // create a modifiedColorPrimitive containing the *black* color and the content. Using black
- // on white allows creating useful mask in VclPixelProcessor2D::processSoftEdgePrimitive2D.
- basegfx::BColorModifierSharedPtr aBColorModifier
- = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor());
+ // No soft edge needed for some of many possible reasons, use original content
+ rVisitor.visit(getChildren());
+}
- const Primitive2DReference xRef(new ModifiedColorPrimitive2D(getChildren(), aBColorModifier));
- rVisitor.append(xRef);
+basegfx::B2DRange
+SoftEdgePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // Hint: Do *not* use GroupPrimitive2D::getB2DRange, that will (unnecessarily)
+ // use the decompose - what works, but is not needed here.
+ // We know the to-be-visualized geometry and the radius it needs to be extended,
+ // so simply calculate the exact needed range.
+ return getChildren().getB2DRange(rViewInformation);
}
-ImplPrimitive2DIDBlock(SoftEdgePrimitive2D, PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D)
+sal_uInt32 SoftEdgePrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D;
+}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
index c46b7df87fc5..e34a1a2a1f6d 100644
--- a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
@@ -27,15 +27,24 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
StructureTagPrimitive2D::StructureTagPrimitive2D(
- const vcl::PDFWriter::StructElement& rStructureElement,
+ const vcl::pdf::StructElement& rStructureElement,
bool bBackground,
bool bIsImage,
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren),
+ bool bIsDecorative,
+ Primitive2DContainer&& aChildren,
+ void const*const pAnchorStructureElementKey,
+ ::std::vector<sal_Int32> const*const pAnnotIds)
+ : GroupPrimitive2D(std::move(aChildren)),
maStructureElement(rStructureElement),
mbBackground(bBackground),
- mbIsImage(bIsImage)
+ mbIsImage(bIsImage),
+ mbIsDecorative(bIsDecorative)
+ , m_pAnchorStructureElementKey(pAnchorStructureElementKey)
{
+ if (pAnnotIds)
+ {
+ m_AnnotIds = *pAnnotIds;
+ }
}
bool StructureTagPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -52,7 +61,17 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(StructureTagPrimitive2D, PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D)
+ sal_uInt32 StructureTagPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D;
+ }
+
+ bool StructureTagPrimitive2D::isTaggedSdrObject() const
+ {
+ // note at the moment *all* StructureTagPrimitive2D are created for
+ // SdrObjects - if that ever changes, need another condition here
+ return !isBackground() || isImage();
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
index d3e32e22ea46..ea848dd6d21e 100644
--- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
@@ -27,10 +27,13 @@
#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <osl/diagnose.h>
#include <sal/log.hxx>
#include <cmath>
-
+#include <utility>
+#include <vcl/skia/SkiaHelper.hxx>
using namespace com::sun::star;
@@ -61,45 +64,46 @@ namespace
namespace drawinglayer::primitive2d
{
- void SvgGradientHelper::createSingleGradientEntryFill(Primitive2DContainer& rContainer) const
+ Primitive2DReference SvgGradientHelper::createSingleGradientEntryFill() const
{
- const SvgGradientEntryVector& rEntries = getGradientEntries();
+ const SvgGradientEntryVector& rEntries(getGradientEntries());
const sal_uInt32 nCount(rEntries.size());
- if(nCount)
+ if(0 == nCount)
{
- const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1];
- const double fOpacity(rSingleEntry.getOpacity());
-
- if(fOpacity > 0.0)
- {
- Primitive2DReference xRef(
- new PolyPolygonColorPrimitive2D(
- getPolyPolygon(),
- rSingleEntry.getColor()));
-
- if(fOpacity < 1.0)
- {
- const Primitive2DContainer aContent { xRef };
+ // no entries, done
+ OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
+ return nullptr;
+ }
- xRef = Primitive2DReference(
- new UnifiedTransparencePrimitive2D(
- aContent,
- 1.0 - fOpacity));
- }
+ const SvgGradientEntry& rSingleEntry(rEntries[nCount - 1]);
+ const double fOpacity(rSingleEntry.getOpacity());
- rContainer.push_back(xRef);
- }
+ if (fOpacity <= 0.0 || basegfx::fTools::equalZero(fOpacity))
+ {
+ // completely opaque, done
+ return nullptr;
}
- else
+
+ if (basegfx::fTools::moreOrEqual(fOpacity, 1.0))
{
- OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
+ // no opacity
+ return Primitive2DReference {
+ new PolyPolygonColorPrimitive2D(
+ getPolyPolygon(),
+ rSingleEntry.getColor()) };
}
+
+ // if transparent, use PolyPolygonRGBAPrimitive2D
+ return Primitive2DReference {
+ new PolyPolygonRGBAPrimitive2D(
+ getPolyPolygon(),
+ rSingleEntry.getColor(),
+ 1.0 - fOpacity) };
}
void SvgGradientHelper::checkPreconditions()
{
- mbPreconditionsChecked = true;
const SvgGradientEntryVector& rEntries = getGradientEntries();
if(rEntries.empty())
@@ -186,7 +190,7 @@ namespace drawinglayer::primitive2d
const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
const SvgGradientEntryVector& rCurrent(bMirror ? getMirroredGradientEntries() : getGradientEntries());
- for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); aIter++)
+ for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); ++aIter)
{
if(basegfx::fTools::lessOrEqual(aIter->getOffset(), fFrac))
{
@@ -208,7 +212,7 @@ namespace drawinglayer::primitive2d
const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
const SvgGradientEntryVector& rCurrent(bMirror ? getMirroredGradientEntries() : getGradientEntries());
- for(SvgGradientEntryVector::const_iterator aIter(rCurrent.begin()); aIter != rCurrent.end(); aIter++)
+ for(SvgGradientEntryVector::const_iterator aIter(rCurrent.begin()); aIter != rCurrent.end(); ++aIter)
{
if(basegfx::fTools::more(aIter->getOffset(), fFrac))
{
@@ -303,26 +307,25 @@ namespace drawinglayer::primitive2d
}
}
- void SvgGradientHelper::createResult(
- Primitive2DContainer& rContainer,
- const Primitive2DContainer& rTargetColor,
- const Primitive2DContainer& rTargetOpacity,
+ Primitive2DReference SvgGradientHelper::createResult(
+ Primitive2DContainer aTargetColor,
+ Primitive2DContainer aTargetOpacity,
const basegfx::B2DHomMatrix& rUnitGradientToObject,
bool bInvert) const
{
- const Primitive2DContainer aTargetColorEntries(rTargetColor.maybeInvert(bInvert));
- const Primitive2DContainer aTargetOpacityEntries(rTargetOpacity.maybeInvert(bInvert));
+ Primitive2DContainer aTargetColorEntries(aTargetColor.maybeInvert(bInvert));
+ Primitive2DContainer aTargetOpacityEntries(aTargetOpacity.maybeInvert(bInvert));
if(aTargetColorEntries.empty())
- return;
+ return nullptr;
Primitive2DReference xRefContent;
if(!aTargetOpacityEntries.empty())
{
const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
- aTargetColorEntries,
- aTargetOpacityEntries);
+ std::move(aTargetColorEntries),
+ std::move(aTargetOpacityEntries));
xRefContent = new TransformPrimitive2D(
rUnitGradientToObject,
@@ -332,28 +335,26 @@ namespace drawinglayer::primitive2d
{
xRefContent = new TransformPrimitive2D(
rUnitGradientToObject,
- aTargetColorEntries);
+ std::move(aTargetColorEntries));
}
- rContainer.push_back(new MaskPrimitive2D(
+ return new MaskPrimitive2D(
getPolyPolygon(),
- Primitive2DContainer { xRefContent }));
+ Primitive2DContainer { xRefContent });
}
SvgGradientHelper::SvgGradientHelper(
- const basegfx::B2DHomMatrix& rGradientTransform,
- const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ basegfx::B2DHomMatrix aGradientTransform,
+ basegfx::B2DPolyPolygon aPolyPolygon,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod)
- : maGradientTransform(rGradientTransform),
- maPolyPolygon(rPolyPolygon),
- maGradientEntries(rGradientEntries),
- maMirroredGradientEntries(),
+ : maGradientTransform(std::move(aGradientTransform)),
+ maPolyPolygon(std::move(aPolyPolygon)),
+ maGradientEntries(std::move(rGradientEntries)),
maStart(rStart),
maSpreadMethod(aSpreadMethod),
- mbPreconditionsChecked(false),
mbCreatesContent(false),
mbSingleEntry(false),
mbFullyOpaque(true),
@@ -377,7 +378,7 @@ namespace drawinglayer::primitive2d
void SvgGradientHelper::createMirroredGradientEntries()
{
- if(!(maMirroredGradientEntries.empty() && !getGradientEntries().empty()))
+ if(!maMirroredGradientEntries.empty() || getGradientEntries().empty())
return;
const sal_uInt32 nCount(getGradientEntries().size());
@@ -465,64 +466,66 @@ namespace drawinglayer::primitive2d
}
}
- void SvgLinearGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ basegfx::B2DHomMatrix SvgLinearGradientPrimitive2D::createUnitGradientToObjectTransformation() const
{
- if(!getPreconditionsChecked())
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+ basegfx::B2DHomMatrix aUnitGradientToObject;
+
+ if(getUseUnitCoordinates())
{
- const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions();
+ // interpret in unit coordinate system -> object aspect ratio will scale result
+ // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
+ // gradient vector defined by Start,End
+ const basegfx::B2DVector aVector(getEnd() - getStart());
+ const double fVectorLength(aVector.getLength());
+
+ aUnitGradientToObject.scale(fVectorLength, 1.0);
+ aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
+ aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
+
+ aUnitGradientToObject *= getGradientTransform();
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ aUnitGradientToObject *= aObjectTransform;
}
+ else
+ {
+ // interpret in object coordinate system -> object aspect ratio will not scale result
+ const basegfx::B2DPoint aStart(aObjectTransform * getStart());
+ const basegfx::B2DPoint aEnd(aObjectTransform * getEnd());
+ const basegfx::B2DVector aVector(aEnd - aStart);
+
+ aUnitGradientToObject.scale(aVector.getLength(), 1.0);
+ aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
+ aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
+
+ aUnitGradientToObject *= getGradientTransform();
+ }
+
+ return aUnitGradientToObject;
+ }
+ Primitive2DReference SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
if(getSingleEntry())
{
// fill with last existing color
- createSingleGradientEntryFill(rContainer);
+ return createSingleGradientEntryFill();
}
else if(getCreatesContent())
{
// at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
// invisible, width and height to fill are not empty
- const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
- const double fPolyWidth(aPolyRange.getWidth());
- const double fPolyHeight(aPolyRange.getHeight());
-
- // create ObjectTransform based on polygon range
- const basegfx::B2DHomMatrix aObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- fPolyWidth, fPolyHeight,
- aPolyRange.getMinX(), aPolyRange.getMinY()));
- basegfx::B2DHomMatrix aUnitGradientToObject;
-
- if(getUseUnitCoordinates())
- {
- // interpret in unit coordinate system -> object aspect ratio will scale result
- // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
- // gradient vector defined by Start,End
- const basegfx::B2DVector aVector(getEnd() - getStart());
- const double fVectorLength(aVector.getLength());
-
- aUnitGradientToObject.scale(fVectorLength, 1.0);
- aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
- aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
-
- aUnitGradientToObject *= getGradientTransform();
-
- // create full transform from unit gradient coordinates to object coordinates
- // including the SvgGradient transformation
- aUnitGradientToObject *= aObjectTransform;
- }
- else
- {
- // interpret in object coordinate system -> object aspect ratio will not scale result
- const basegfx::B2DPoint aStart(aObjectTransform * getStart());
- const basegfx::B2DPoint aEnd(aObjectTransform * getEnd());
- const basegfx::B2DVector aVector(aEnd - aStart);
-
- aUnitGradientToObject.scale(aVector.getLength(), 1.0);
- aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
- aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
-
- aUnitGradientToObject *= getGradientTransform();
- }
+ basegfx::B2DHomMatrix aUnitGradientToObject(createUnitGradientToObjectTransformation());
// create inverse from it
basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
@@ -538,7 +541,7 @@ namespace drawinglayer::primitive2d
Primitive2DContainer aTargetColor;
Primitive2DContainer aTargetOpacity;
- if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0))
+ if(aUnitRange.getWidth() > 0.0)
{
// add a pre-multiply to aUnitGradientToObject to allow
// multiplication of the polygon(xl, 0.0, xr, 1.0)
@@ -555,22 +558,24 @@ namespace drawinglayer::primitive2d
aUnitRange.getMaxX());
}
- createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject);
+ return createResult(std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject);
}
+ return nullptr;
}
SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
const basegfx::B2DHomMatrix& rGradientTransform,
const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
const basegfx::B2DPoint& rEnd,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod)
- : BufferedDecompositionPrimitive2D(),
- SvgGradientHelper(rGradientTransform, rPolyPolygon, rGradientEntries, rStart, bUseUnitCoordinates, aSpreadMethod),
+ : SvgGradientHelper(rGradientTransform, rPolyPolygon, std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
maEnd(rEnd)
{
+ // ensure Preconditions are checked
+ checkPreconditions();
}
SvgLinearGradientPrimitive2D::~SvgLinearGradientPrimitive2D()
@@ -598,7 +603,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
+ sal_uInt32 SvgLinearGradientPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -641,8 +649,9 @@ namespace drawinglayer::primitive2d
if(isFocalSet())
{
- const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
- const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+ const basegfx::B2DVector aFocalVector(getFocal() - getStart());
+ const basegfx::B2DVector aTranslateFrom(aFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(aFocalVector * (maFocalLength - fScaleTo));
rTargetColor.push_back(
new SvgRadialAtomPrimitive2D(
@@ -666,8 +675,9 @@ namespace drawinglayer::primitive2d
if(isFocalSet())
{
- const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
- const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+ const basegfx::B2DVector aFocalVector(getFocal() - getStart());
+ const basegfx::B2DVector aTranslateFrom(aFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(aFocalVector * (maFocalLength - fScaleTo));
rTargetOpacity.push_back(
new SvgRadialAtomPrimitive2D(
@@ -685,62 +695,64 @@ namespace drawinglayer::primitive2d
}
}
- void SvgRadialGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ basegfx::B2DHomMatrix SvgRadialGradientPrimitive2D::createUnitGradientToObjectTransformation() const
{
- if(!getPreconditionsChecked())
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+ basegfx::B2DHomMatrix aUnitGradientToObject;
+
+ if(getUseUnitCoordinates())
+ {
+ // interpret in unit coordinate system -> object aspect ratio will scale result
+ // create unit transform from unit vector to given linear gradient vector
+ aUnitGradientToObject.scale(getRadius(), getRadius());
+ aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
+
+ if(!getGradientTransform().isIdentity())
+ {
+ aUnitGradientToObject = getGradientTransform() * aUnitGradientToObject;
+ }
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ aUnitGradientToObject = aObjectTransform * aUnitGradientToObject;
+ }
+ else
{
- const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions();
+ // interpret in object coordinate system -> object aspect ratio will not scale result
+ // use X-Axis with radius, it was already made relative to object width when coming from
+ // SVG import
+ const double fRadius((aObjectTransform * basegfx::B2DVector(getRadius(), 0.0)).getLength());
+ const basegfx::B2DPoint aStart(aObjectTransform * getStart());
+
+ aUnitGradientToObject.scale(fRadius, fRadius);
+ aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
+
+ aUnitGradientToObject *= getGradientTransform();
}
+ return aUnitGradientToObject;
+ }
+
+ Primitive2DReference SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
if(getSingleEntry())
{
// fill with last existing color
- createSingleGradientEntryFill(rContainer);
+ return createSingleGradientEntryFill();
}
else if(getCreatesContent())
{
// at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
// invisible, width and height to fill are not empty
- const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
- const double fPolyWidth(aPolyRange.getWidth());
- const double fPolyHeight(aPolyRange.getHeight());
-
- // create ObjectTransform based on polygon range
- const basegfx::B2DHomMatrix aObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- fPolyWidth, fPolyHeight,
- aPolyRange.getMinX(), aPolyRange.getMinY()));
- basegfx::B2DHomMatrix aUnitGradientToObject;
-
- if(getUseUnitCoordinates())
- {
- // interpret in unit coordinate system -> object aspect ratio will scale result
- // create unit transform from unit vector to given linear gradient vector
- aUnitGradientToObject.scale(getRadius(), getRadius());
- aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
-
- if(!getGradientTransform().isIdentity())
- {
- aUnitGradientToObject = getGradientTransform() * aUnitGradientToObject;
- }
-
- // create full transform from unit gradient coordinates to object coordinates
- // including the SvgGradient transformation
- aUnitGradientToObject = aObjectTransform * aUnitGradientToObject;
- }
- else
- {
- // interpret in object coordinate system -> object aspect ratio will not scale result
- // use X-Axis with radius, it was already made relative to object width when coming from
- // SVG import
- const double fRadius((aObjectTransform * basegfx::B2DVector(getRadius(), 0.0)).getLength());
- const basegfx::B2DPoint aStart(aObjectTransform * getStart());
-
- aUnitGradientToObject.scale(fRadius, fRadius);
- aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
-
- aUnitGradientToObject *= getGradientTransform();
- }
+ basegfx::B2DHomMatrix aUnitGradientToObject(createUnitGradientToObjectTransformation());
// create inverse from it
basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
@@ -779,33 +791,32 @@ namespace drawinglayer::primitive2d
fMax);
}
- createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject, true);
+ return createResult(std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject, true);
}
+ return nullptr;
}
SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
const basegfx::B2DHomMatrix& rGradientTransform,
const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
double fRadius,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod,
const basegfx::B2DPoint* pFocal)
- : BufferedDecompositionPrimitive2D(),
- SvgGradientHelper(rGradientTransform, rPolyPolygon, rGradientEntries, rStart, bUseUnitCoordinates, aSpreadMethod),
+ : SvgGradientHelper(rGradientTransform, rPolyPolygon, std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
mfRadius(fRadius),
maFocal(rStart),
- maFocalVector(0.0, 0.0),
- maFocalLength(0.0),
- mbFocalSet(false)
+ maFocalLength(0.0)
{
if(pFocal && !pFocal->equal(getStart()))
{
maFocal = *pFocal;
- maFocalVector = maFocal - getStart();
- mbFocalSet = true;
}
+
+ // ensure Preconditions are checked
+ checkPreconditions();
}
SvgRadialGradientPrimitive2D::~SvgRadialGradientPrimitive2D()
@@ -816,22 +827,22 @@ namespace drawinglayer::primitive2d
{
const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
- if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
- {
- const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
+ if(!pSvgGradientHelper || !SvgGradientHelper::operator==(*pSvgGradientHelper))
+ return false;
+
+ const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
- if(getRadius() == rCompare.getRadius())
+ if(getRadius() == rCompare.getRadius())
+ {
+ if(isFocalSet() == rCompare.isFocalSet())
{
- if(isFocalSet() == rCompare.isFocalSet())
+ if(isFocalSet())
{
- if(isFocalSet())
- {
- return getFocal() == rCompare.getFocal();
- }
- else
- {
- return true;
- }
+ return getFocal() == rCompare.getFocal();
+ }
+ else
+ {
+ return true;
}
}
}
@@ -846,7 +857,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
+ sal_uInt32 SvgRadialGradientPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -855,12 +869,12 @@ namespace drawinglayer::primitive2d
namespace drawinglayer::primitive2d
{
- void SvgLinearAtomPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const double fDelta(getOffsetB() - getOffsetA());
if(basegfx::fTools::equalZero(fDelta))
- return;
+ return nullptr;
// use one discrete unit for overlap (one pixel)
const double fDiscreteUnit(getDiscreteUnit());
@@ -868,6 +882,12 @@ namespace drawinglayer::primitive2d
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit));
+ // HACK: Splitting a gradient into adjacent polygons with gradually changing color is silly.
+ // If antialiasing is used to draw them, the AA-ed adjacent edges won't line up perfectly
+ // because of the AA (see SkiaSalGraphicsImpl::mergePolyPolygonToPrevious()).
+ // Make the polygons a bit wider, so they the partial overlap "fixes" this.
+ const double fixup = SkiaHelper::isVCLSkiaEnabled() ? fDiscreteUnit / 2 : 0;
+
// tdf#117949 Use a small amount of discrete overlap at the edges. Usually this
// should be exactly 0.0 and 1.0, but there were cases when this gets clipped
// against the mask polygon which got numerically problematic.
@@ -881,29 +901,31 @@ namespace drawinglayer::primitive2d
basegfx::B2DRange(
getOffsetA() - fDiscreteUnit,
-0.0001, // TTTT -> should be 0.0, see comment above
- getOffsetA() + (fDelta / nSteps) + fDiscreteUnit,
+ getOffsetA() + (fDelta / nSteps) + fDiscreteUnit + fixup,
1.0001))); // TTTT -> should be 1.0, see comment above
// prepare loop (inside to outside, [0.0 .. 1.0[)
double fUnitScale(0.0);
const double fUnitStep(1.0 / nSteps);
+ Primitive2DContainer aContainer;
+ aContainer.resize(nSteps);
for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
{
basegfx::B2DPolygon aNew(aPolygon);
- aNew.transform(basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0));
- rContainer.push_back(new PolyPolygonColorPrimitive2D(
+ aNew.translate(fDelta * fUnitScale, 0.0);
+ aContainer[a] = new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aNew),
- basegfx::interpolate(getColorA(), getColorB(), fUnitScale)));
+ basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
SvgLinearAtomPrimitive2D::SvgLinearAtomPrimitive2D(
const basegfx::BColor& aColorA, double fOffsetA,
const basegfx::BColor& aColorB, double fOffsetB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfOffsetA(fOffsetA),
mfOffsetB(fOffsetB)
@@ -931,7 +953,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
+ sal_uInt32 SvgLinearAtomPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -940,12 +965,12 @@ namespace drawinglayer::primitive2d
namespace drawinglayer::primitive2d
{
- void SvgRadialAtomPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const double fDeltaScale(getScaleB() - getScaleA());
if(basegfx::fTools::equalZero(fDeltaScale))
- return;
+ return nullptr;
// use one discrete unit for overlap (one pixel)
const double fDiscreteUnit(getDiscreteUnit());
@@ -957,6 +982,8 @@ namespace drawinglayer::primitive2d
double fUnitScale(0.0);
const double fUnitStep(1.0 / nSteps);
+ Primitive2DContainer aContainer;
+ aContainer.resize(nSteps);
for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
{
basegfx::B2DHomMatrix aTransform;
@@ -986,17 +1013,17 @@ namespace drawinglayer::primitive2d
basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle());
aNew.transform(aTransform);
- rContainer.push_back(new PolyPolygonColorPrimitive2D(
+ aContainer[a] = new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aNew),
- basegfx::interpolate(getColorB(), getColorA(), fUnitScale)));
+ basegfx::interpolate(getColorB(), getColorA(), fUnitScale));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfScaleA(fScaleA),
mfScaleB(fScaleB)
@@ -1027,8 +1054,7 @@ namespace drawinglayer::primitive2d
SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
const basegfx::BColor& aColorA, double fScaleA,
const basegfx::BColor& aColorB, double fScaleB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfScaleA(fScaleA),
mfScaleB(fScaleB)
@@ -1051,24 +1077,24 @@ namespace drawinglayer::primitive2d
bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
- {
- const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+ if(!DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ return false;
- if(getColorA() == rCompare.getColorA()
- && getColorB() == rCompare.getColorB()
- && getScaleA() == rCompare.getScaleA()
- && getScaleB() == rCompare.getScaleB())
+ const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+
+ if(getColorA() == rCompare.getColorA()
+ && getColorB() == rCompare.getColorB()
+ && getScaleA() == rCompare.getScaleA()
+ && getScaleB() == rCompare.getScaleB())
+ {
+ if(isTranslateSet() && rCompare.isTranslateSet())
{
- if(isTranslateSet() && rCompare.isTranslateSet())
- {
- return (getTranslateA() == rCompare.getTranslateA()
- && getTranslateB() == rCompare.getTranslateB());
- }
- else if(!isTranslateSet() && !rCompare.isTranslateSet())
- {
- return true;
- }
+ return (getTranslateA() == rCompare.getTranslateA()
+ && getTranslateB() == rCompare.getTranslateB());
+ }
+ else if(!isTranslateSet() && !rCompare.isTranslateSet())
+ {
+ return true;
}
}
@@ -1076,7 +1102,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
+ sal_uInt32 SvgRadialAtomPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
index df37aa01356e..eac53589a7ff 100644
--- a/drawinglayer/source/primitive2d/textbreakuphelper.cxx
+++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
@@ -30,9 +30,6 @@ namespace drawinglayer::primitive2d
{
TextBreakupHelper::TextBreakupHelper(const TextSimplePortionPrimitive2D& rSource)
: mrSource(rSource),
- mxResult(),
- maTextLayouter(),
- maDecTrans(),
mbNoDXArray(false)
{
maDecTrans = mrSource.getTextTransform();
@@ -61,6 +58,7 @@ namespace drawinglayer::primitive2d
// prepare values for new portion
basegfx::B2DHomMatrix aNewTransform;
std::vector< double > aNewDXArray;
+ std::vector< sal_Bool > aNewKashidaArray;
const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition());
if(!mbNoDXArray)
@@ -71,6 +69,13 @@ namespace drawinglayer::primitive2d
mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
}
+ if(!mbNoDXArray && !mrSource.getKashidaArray().empty())
+ {
+ aNewKashidaArray = std::vector< sal_Bool >(
+ mrSource.getKashidaArray().begin() + (nIndex - mrSource.getTextPosition()),
+ mrSource.getKashidaArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
+ }
+
if(bNewStartIsNotOldStart)
{
// needs to be moved to a new start position
@@ -107,17 +112,14 @@ namespace drawinglayer::primitive2d
{
// DXArray values need to be corrected with the offset, too. Here,
// take the scaled offset since the DXArray is scaled
- const sal_uInt32 nArraySize(aNewDXArray.size());
-
- for(sal_uInt32 a(0); a < nArraySize; a++)
+ for(double &rNewDX: aNewDXArray)
{
- aNewDXArray[a] -= fOffset;
+ rNewDX -= fOffset;
}
}
}
// add text transformation to new transformation
- // coverity[swapped_arguments : FALSE] - this is in the correct order
aNewTransform *= maDecTrans.getB2DHomMatrix();
// callback to allow evtl. changes
@@ -139,7 +141,8 @@ namespace drawinglayer::primitive2d
mrSource.getText(),
nIndex,
nLength,
- aNewDXArray,
+ std::move(aNewDXArray),
+ std::move(aNewKashidaArray),
mrSource.getFontAttribute(),
mrSource.getLocale(),
mrSource.getFontColor(),
@@ -170,7 +173,8 @@ namespace drawinglayer::primitive2d
mrSource.getText(),
nIndex,
nLength,
- aNewDXArray,
+ std::move(aNewDXArray),
+ std::move(aNewKashidaArray),
mrSource.getFontAttribute(),
mrSource.getLocale(),
mrSource.getFontColor()));
@@ -192,7 +196,7 @@ namespace drawinglayer::primitive2d
if(!xBreakIterator.is())
{
- css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ const css::uno::Reference< css::uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() );
xBreakIterator = css::i18n::BreakIterator::create(xContext);
}
@@ -261,17 +265,17 @@ namespace drawinglayer::primitive2d
}
}
- mxResult = aTempResult;
+ mxResult = std::move(aTempResult);
}
- const Primitive2DContainer& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const
+ Primitive2DContainer TextBreakupHelper::extractResult(BreakupUnit aBreakupUnit)
{
if(mxResult.empty())
{
- const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit);
+ breakup(aBreakupUnit);
}
- return mxResult;
+ return std::move(mxResult);
}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
index afc841fcf3bd..bfa5ebbb7eea 100644
--- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
@@ -22,52 +22,81 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <primitive2d/texteffectprimitive2d.hxx>
#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
#include <primitive2d/textlineprimitive2d.hxx>
#include <primitive2d/textstrikeoutprimitive2d.hxx>
#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
-
+#include <vcl/vcllayout.hxx>
namespace drawinglayer::primitive2d
{
void TextDecoratedPortionPrimitive2D::impCreateGeometryContent(
- std::vector< Primitive2DReference >& rTarget,
+ Primitive2DContainer& rTarget,
basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose const & rDecTrans,
const OUString& rText,
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
const std::vector< double >& rDXArray,
+ const std::vector< sal_Bool >& rKashidaArray,
const attribute::FontAttribute& rFontAttribute) const
{
// create the SimpleTextPrimitive needed in any case
- rTarget.push_back(Primitive2DReference(
+ rTarget.push_back(
new TextSimplePortionPrimitive2D(
rDecTrans.getB2DHomMatrix(),
rText,
nTextPosition,
nTextLength,
- rDXArray,
+ std::vector(rDXArray),
+ std::vector(rKashidaArray),
rFontAttribute,
getLocale(),
- getFontColor())));
+ getFontColor()));
+
+ // create and add decoration
+ const Primitive2DContainer& rDecorationGeometryContent(
+ getOrCreateDecorationGeometryContent(
+ rDecTrans,
+ rText,
+ nTextPosition,
+ nTextLength,
+ rDXArray));
+
+ rTarget.insert(rTarget.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end());
+ }
+ const Primitive2DContainer& TextDecoratedPortionPrimitive2D::getOrCreateDecorationGeometryContent(
+ basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose const & rDecTrans,
+ const OUString& rText,
+ sal_Int32 nTextPosition,
+ sal_Int32 nTextLength,
+ const std::vector< double >& rDXArray) const
+ {
// see if something else needs to be done
const bool bOverlineUsed(TEXT_LINE_NONE != getFontOverline());
const bool bUnderlineUsed(TEXT_LINE_NONE != getFontUnderline());
const bool bStrikeoutUsed(TEXT_STRIKEOUT_NONE != getTextStrikeout());
+ const bool bEmphasisMarkUsed(TEXT_FONT_EMPHASIS_MARK_NONE != getTextEmphasisMark()
+ && (getEmphasisMarkAbove() || getEmphasisMarkBelow()));
- if(!(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed))
- return;
+ if(!(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed || bEmphasisMarkUsed))
+ {
+ // not used, return empty Primitive2DContainer
+ return maBufferedDecorationGeometry;
+ }
- // common preparations
- TextLayouterDevice aTextLayouter;
+ if (!maBufferedDecorationGeometry.empty())
+ {
+ // if not empty it is used -> append and return Primitive2DContainer
+ return maBufferedDecorationGeometry;
+ }
- // TextLayouterDevice is needed to get metrics for text decorations like
- // underline/strikeout/emphasis marks from it. For setup, the font size is needed
- aTextLayouter.setFontAttribute(
- getFontAttribute(),
- rDecTrans.getScale().getX(),
- rDecTrans.getScale().getY(),
- getLocale());
+ // common preparations - create TextLayouterDevice
+ primitive2d::TextLayouterDevice aTextLayouter;
+ createTextLayouter(aTextLayouter);
// get text width
double fTextWidth(0.0);
@@ -91,86 +120,209 @@ namespace drawinglayer::primitive2d
if(bOverlineUsed)
{
+ // for Relief we have to manipulate the OverlineColor
+ basegfx::BColor aOverlineColor(getOverlineColor());
+ if (hasTextRelief() && COL_BLACK.getBColor() == aOverlineColor)
+ aOverlineColor = COL_WHITE.getBColor();
+
// create primitive geometry for overline
- rTarget.push_back(Primitive2DReference(
+ maBufferedDecorationGeometry.push_back(
new TextLinePrimitive2D(
rDecTrans.getB2DHomMatrix(),
fTextWidth,
aTextLayouter.getOverlineOffset(),
aTextLayouter.getOverlineHeight(),
getFontOverline(),
- getOverlineColor())));
+ aOverlineColor));
}
if(bUnderlineUsed)
{
+ // for Relief we have to manipulate the TextlineColor
+ basegfx::BColor aTextlineColor(getTextlineColor());
+ if (hasTextRelief() && COL_BLACK.getBColor() == aTextlineColor)
+ aTextlineColor = COL_WHITE.getBColor();
+
// create primitive geometry for underline
- rTarget.push_back(Primitive2DReference(
+ maBufferedDecorationGeometry.push_back(
new TextLinePrimitive2D(
rDecTrans.getB2DHomMatrix(),
fTextWidth,
aTextLayouter.getUnderlineOffset(),
aTextLayouter.getUnderlineHeight(),
getFontUnderline(),
- getTextlineColor())));
+ aTextlineColor));
}
- if(!bStrikeoutUsed)
- return;
-
- // create primitive geometry for strikeout
- if(TEXT_STRIKEOUT_SLASH == getTextStrikeout() || TEXT_STRIKEOUT_X == getTextStrikeout())
+ if(bStrikeoutUsed)
{
- // strikeout with character
- const sal_Unicode aStrikeoutChar(TEXT_STRIKEOUT_SLASH == getTextStrikeout() ? '/' : 'X');
+ // for Relief we have to manipulate the FontColor
+ basegfx::BColor aFontColor(getFontColor());
+ if (hasTextRelief() && COL_BLACK.getBColor() == aFontColor)
+ aFontColor = COL_WHITE.getBColor();
- rTarget.push_back(Primitive2DReference(
- new TextCharacterStrikeoutPrimitive2D(
- rDecTrans.getB2DHomMatrix(),
- fTextWidth,
- getFontColor(),
- aStrikeoutChar,
- getFontAttribute(),
- getLocale())));
+ // create primitive geometry for strikeout
+ if(TEXT_STRIKEOUT_SLASH == getTextStrikeout() || TEXT_STRIKEOUT_X == getTextStrikeout())
+ {
+ // strikeout with character
+ const sal_Unicode aStrikeoutChar(TEXT_STRIKEOUT_SLASH == getTextStrikeout() ? '/' : 'X');
+
+ maBufferedDecorationGeometry.push_back(
+ new TextCharacterStrikeoutPrimitive2D(
+ rDecTrans.getB2DHomMatrix(),
+ fTextWidth,
+ aFontColor,
+ aStrikeoutChar,
+ getFontAttribute(),
+ getLocale()));
+ }
+ else
+ {
+ // strikeout with geometry
+ maBufferedDecorationGeometry.push_back(
+ new TextGeometryStrikeoutPrimitive2D(
+ rDecTrans.getB2DHomMatrix(),
+ fTextWidth,
+ aFontColor,
+ aTextLayouter.getUnderlineHeight(),
+ aTextLayouter.getStrikeoutOffset(),
+ getTextStrikeout()));
+ }
}
- else
+
+ if (bEmphasisMarkUsed)
{
- // strikeout with geometry
- rTarget.push_back(Primitive2DReference(
- new TextGeometryStrikeoutPrimitive2D(
- rDecTrans.getB2DHomMatrix(),
- fTextWidth,
- getFontColor(),
- aTextLayouter.getUnderlineHeight(),
- aTextLayouter.getStrikeoutOffset(),
- getTextStrikeout())));
+ // create primitives for EmphasisMark visualization - we need a SalLayout
+ std::unique_ptr<SalLayout> pSalLayout(createSalLayout(aTextLayouter));
+
+ if (pSalLayout)
+ {
+ // for Relief we have to manipulate the FontColor
+ basegfx::BColor aFontColor(getFontColor());
+ if (hasTextRelief() && COL_BLACK.getBColor() == aFontColor)
+ aFontColor = COL_WHITE.getBColor();
+
+ // placeholders for repeated content, only created once
+ Primitive2DReference aShape;
+ Primitive2DReference aRect1;
+ Primitive2DReference aRect2;
+
+ // space to collect primitives for EmphasisMark
+ Primitive2DContainer aEmphasisContent;
+
+ // callback collector will produce geometry already scaled, so
+ // prepare local transform without FontScale
+ const basegfx::B2DHomMatrix aObjTransformWithoutScale(
+ basegfx::utils::createShearXRotateTranslateB2DHomMatrix(
+ rDecTrans.getShearX(), rDecTrans.getRotate(), rDecTrans.getTranslate()));
+
+ // the callback from OutputDevice::createEmphasisMarks providing the data
+ // for each EmphasisMark
+ auto aEmphasisCallback([&aShape, &aRect1, &aRect2, &aEmphasisContent, &aObjTransformWithoutScale, &aFontColor](
+ const basegfx::B2DPoint& rOutPoint, const basegfx::B2DPolyPolygon& rShape,
+ bool isPolyLine, const tools::Rectangle& rRect1, const tools::Rectangle& rRect2)
+ {
+ // prepare complete ObjectTransform
+ const basegfx::B2DHomMatrix aTransform(
+ aObjTransformWithoutScale * basegfx::utils::createTranslateB2DHomMatrix(rOutPoint));
+
+ if (rShape.count())
+ {
+ // create PolyPolygon if provided
+ if (!aShape)
+ {
+ if (isPolyLine)
+ aShape = new PolyPolygonHairlinePrimitive2D(rShape, aFontColor);
+ else
+ aShape = new PolyPolygonColorPrimitive2D(rShape, aFontColor);
+ }
+
+ aEmphasisContent.push_back(
+ new TransformPrimitive2D(
+ aTransform,
+ Primitive2DContainer { aShape } ));
+ }
+
+ if (!rRect1.IsEmpty())
+ {
+ // create Rectangle1 if provided
+ if (!aRect1)
+ aRect1 = new FilledRectanglePrimitive2D(
+ basegfx::B2DRange(rRect1.Left(), rRect1.Top(), rRect1.Right(), rRect1.Bottom()), aFontColor);
+
+ aEmphasisContent.push_back(
+ new TransformPrimitive2D(
+ aTransform,
+ Primitive2DContainer { aRect1 } ));
+ }
+
+ if (!rRect2.IsEmpty())
+ {
+ // create Rectangle2 if provided
+ if (!aRect2)
+ aRect2 = new FilledRectanglePrimitive2D(
+ basegfx::B2DRange(rRect2.Left(), rRect2.Top(), rRect2.Right(), rRect2.Bottom()), aFontColor);
+
+ aEmphasisContent.push_back(
+ new TransformPrimitive2D(
+ aTransform,
+ Primitive2DContainer { aRect2 } ));
+ }
+ });
+
+ // call tooling method in vcl to generate the graphic representations
+ aTextLayouter.createEmphasisMarks(
+ *pSalLayout,
+ getTextEmphasisMark(),
+ getEmphasisMarkAbove(),
+ aEmphasisCallback);
+
+ if (!aEmphasisContent.empty())
+ {
+ // if we got graphic representations of EmphasisMark, add
+ // them to BufferedDecorationGeometry. Also embed them to
+ // a TextHierarchyEmphasisMarkPrimitive2D GroupPrimitive
+ // to be able to evtl. handle these in a special way
+ maBufferedDecorationGeometry.push_back(
+ new TextHierarchyEmphasisMarkPrimitive2D(std::move(aEmphasisContent)));
+ }
+ }
}
- // TODO: Handle Font Emphasis Above/Below
+ // append local result and return
+ return maBufferedDecorationGeometry;
}
- void TextDecoratedPortionPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ const Primitive2DContainer& TextDecoratedPortionPrimitive2D::getOrCreateBrokenUpText() const
{
- if(getWordLineMode())
+ if(!getWordLineMode())
{
- // support for single word mode; split to single word primitives
- // using TextBreakupHelper
- const TextBreakupHelper aTextBreakupHelper(*this);
- const Primitive2DContainer& aBroken(aTextBreakupHelper.getResult(BreakupUnit::Word));
+ // return empty Primitive2DContainer
+ return maBufferedBrokenUpText;
+ }
- if(!aBroken.empty())
- {
- // was indeed split to several words, use as result
- rContainer.insert(rContainer.end(), aBroken.begin(), aBroken.end());
- return;
- }
- else
- {
- // no split, was already a single word. Continue to
- // decompose local entity
- }
+ if (!maBufferedBrokenUpText.empty())
+ {
+ // if not empty it is used -> return Primitive2DContainer
+ return maBufferedBrokenUpText;
+ }
+
+ // support for single word mode; split to single word primitives
+ // using TextBreakupHelper
+ TextBreakupHelper aTextBreakupHelper(*this);
+ maBufferedBrokenUpText = aTextBreakupHelper.extractResult(BreakupUnit::Word);
+ return maBufferedBrokenUpText;
+ }
+
+ Primitive2DReference TextDecoratedPortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ if (!getOrCreateBrokenUpText().empty())
+ {
+ // if BrokenUpText/WordLineMode is used, go into recursion
+ Primitive2DContainer aContent(getOrCreateBrokenUpText());
+ return new GroupPrimitive2D(std::move(aContent));
}
- std::vector< Primitive2DReference > aNewPrimitives;
+
basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(getTextTransform());
Primitive2DContainer aRetval;
@@ -190,115 +342,113 @@ namespace drawinglayer::primitive2d
getFontAttribute().getBiDiStrong());
// handle as one word
- impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute);
+ impCreateGeometryContent(aRetval, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), getKashidaArray(), aNewFontAttribute);
- // convert to Primitive2DSequence
- const sal_uInt32 nMemberCount(aNewPrimitives.size());
+ // Handle Shadow, Outline and TextRelief
+ if(aRetval.empty())
+ return nullptr;
- if(nMemberCount)
+ if(hasShadow() || hasTextRelief() || hasOutline())
{
- aRetval.resize(nMemberCount);
+ Primitive2DReference aShadow;
- for(sal_uInt32 a(0); a < nMemberCount; a++)
+ if(hasShadow())
{
- aRetval[a] = aNewPrimitives[a];
+ // create shadow with current content (in aRetval). Text shadow
+ // is constant, relative to font size, rotated with the text and has a
+ // constant color.
+ // shadow parameter values
+ static const double fFactor(1.0 / 24.0);
+ const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor);
+
+ // see OutputDevice::ImplDrawSpecialText -> no longer simple fixed color
+ const basegfx::BColor aBlack(0.0, 0.0, 0.0);
+ basegfx::BColor aShadowColor(aBlack);
+ if (aBlack == getFontColor() || getFontColor().luminance() < (8.0 / 255.0))
+ aShadowColor = COL_LIGHTGRAY.getBColor();
+
+ // prepare shadow transform matrix
+ const basegfx::B2DHomMatrix aShadowTransform(basegfx::utils::createTranslateB2DHomMatrix(
+ fTextShadowOffset, fTextShadowOffset));
+
+ // create shadow primitive
+ aShadow = new ShadowPrimitive2D(
+ aShadowTransform,
+ aShadowColor,
+ 0, // fShadowBlur = 0, there's no blur for text shadow yet.
+ Primitive2DContainer(aRetval));
}
- }
- // Handle Shadow, Outline and TextRelief
- if(!aRetval.empty())
- {
- // outline AND shadow depend on NO TextRelief (see dialog)
- const bool bHasTextRelief(TEXT_RELIEF_NONE != getTextRelief());
- const bool bHasShadow(!bHasTextRelief && getShadow());
- const bool bHasOutline(!bHasTextRelief && getFontAttribute().getOutline());
-
- if(bHasShadow || bHasTextRelief || bHasOutline)
+ if(hasTextRelief())
{
- Primitive2DReference aShadow;
+ // create emboss using an own helper primitive since this will
+ // be view-dependent
+ const basegfx::BColor aBBlack(0.0, 0.0, 0.0);
+ const bool bDefaultTextColor(aBBlack == getFontColor());
+ TextEffectStyle2D aTextEffectStyle2D(TextEffectStyle2D::ReliefEmbossed);
- if(bHasShadow)
+ if(bDefaultTextColor)
{
- // create shadow with current content (in aRetval). Text shadow
- // is constant, relative to font size, rotated with the text and has a
- // constant color.
- // shadow parameter values
- static const double fFactor(1.0 / 24.0);
- const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor);
- static basegfx::BColor aShadowColor(0.3, 0.3, 0.3);
-
- // prepare shadow transform matrix
- const basegfx::B2DHomMatrix aShadowTransform(basegfx::utils::createTranslateB2DHomMatrix(
- fTextShadowOffset, fTextShadowOffset));
-
- // create shadow primitive
- aShadow = new ShadowPrimitive2D(
- aShadowTransform,
- aShadowColor,
- 0, // fShadowBlur = 0, there's no blur for text shadow yet.
- aRetval);
- }
-
- if(bHasTextRelief)
- {
- // create emboss using an own helper primitive since this will
- // be view-dependent
- const basegfx::BColor aBBlack(0.0, 0.0, 0.0);
- const bool bDefaultTextColor(aBBlack == getFontColor());
- TextEffectStyle2D aTextEffectStyle2D(TextEffectStyle2D::ReliefEmbossed);
-
- if(bDefaultTextColor)
+ if(TEXT_RELIEF_ENGRAVED == getTextRelief())
{
- if(TEXT_RELIEF_ENGRAVED == getTextRelief())
- {
- aTextEffectStyle2D = TextEffectStyle2D::ReliefEngravedDefault;
- }
- else
- {
- aTextEffectStyle2D = TextEffectStyle2D::ReliefEmbossedDefault;
- }
+ aTextEffectStyle2D = TextEffectStyle2D::ReliefEngravedDefault;
}
else
{
- if(TEXT_RELIEF_ENGRAVED == getTextRelief())
- {
- aTextEffectStyle2D = TextEffectStyle2D::ReliefEngraved;
- }
- else
- {
- aTextEffectStyle2D = TextEffectStyle2D::ReliefEmbossed;
- }
+ aTextEffectStyle2D = TextEffectStyle2D::ReliefEmbossedDefault;
}
- Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
- aRetval,
- aDecTrans.getTranslate(),
- aDecTrans.getRotate(),
- aTextEffectStyle2D));
- aRetval = Primitive2DContainer { aNewTextEffect };
+ aRetval = Primitive2DContainer {
+ new TextEffectPrimitive2D(
+ std::move(aRetval),
+ aDecTrans.getTranslate(),
+ aDecTrans.getRotate(),
+ aTextEffectStyle2D)
+ };
}
- else if(bHasOutline)
+ else
{
// create outline using an own helper primitive since this will
// be view-dependent
- Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
- aRetval,
+ aRetval = Primitive2DContainer {
+ new TextEffectPrimitive2D(
+ std::move(aRetval),
+ aDecTrans.getTranslate(),
+ aDecTrans.getRotate(),
+ TextEffectStyle2D::Outline)
+ };
+ }
+
+ aRetval = Primitive2DContainer {
+ Primitive2DReference(new TextEffectPrimitive2D(
+ std::move(aRetval),
aDecTrans.getTranslate(),
aDecTrans.getRotate(),
- TextEffectStyle2D::Outline));
- aRetval = Primitive2DContainer { aNewTextEffect };
- }
+ aTextEffectStyle2D))
+ };
+ }
+ else if(hasOutline())
+ {
+ // create outline using an own helper primitive since this will
+ // be view-dependent
+ aRetval = Primitive2DContainer {
+ Primitive2DReference(new TextEffectPrimitive2D(
+ std::move(aRetval),
+ aDecTrans.getTranslate(),
+ aDecTrans.getRotate(),
+ TextEffectStyle2D::Outline))
+ };
+ }
- if(aShadow.is())
- {
- // put shadow in front if there is one to paint timely before
- // but placed behind content
- aRetval.insert(aRetval.begin(), aShadow);
- }
+ if(aShadow.is())
+ {
+ // put shadow in front if there is one to paint timely before
+ // but placed behind content
+ aRetval.insert(aRetval.begin(), aShadow);
}
}
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
+ return new GroupPrimitive2D(std::move(aRetval));
}
TextDecoratedPortionPrimitive2D::TextDecoratedPortionPrimitive2D(
@@ -307,7 +457,8 @@ namespace drawinglayer::primitive2d
const OUString& rText,
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
- const std::vector< double >& rDXArray,
+ std::vector< double >&& rDXArray,
+ std::vector< sal_Bool >&& rKashidaArray,
const attribute::FontAttribute& rFontAttribute,
const css::lang::Locale& rLocale,
const basegfx::BColor& rFontColor,
@@ -326,7 +477,19 @@ namespace drawinglayer::primitive2d
bool bEmphasisMarkBelow,
TextRelief eTextRelief,
bool bShadow)
- : TextSimplePortionPrimitive2D(rNewTransform, rText, nTextPosition, nTextLength, rDXArray, rFontAttribute, rLocale, rFontColor, false, 0, rFillColor),
+ : TextSimplePortionPrimitive2D(
+ rNewTransform,
+ rText,
+ nTextPosition,
+ nTextLength,
+ std::move(rDXArray),
+ std::move(rKashidaArray),
+ rFontAttribute,
+ rLocale,
+ rFontColor,
+ rFillColor),
+ maBufferedBrokenUpText(),
+ maBufferedDecorationGeometry(),
maOverlineColor(rOverlineColor),
maTextlineColor(rTextlineColor),
meFontOverline(eFontOverline),
@@ -342,6 +505,25 @@ namespace drawinglayer::primitive2d
{
}
+ bool TextDecoratedPortionPrimitive2D::hasTextRelief() const
+ {
+ return TEXT_RELIEF_NONE != getTextRelief();
+ }
+
+ bool TextDecoratedPortionPrimitive2D::hasShadow() const
+ {
+ // not allowed with TextRelief, else defined in FontAttributes
+ return !hasTextRelief() && getShadow();
+ }
+
+ bool TextDecoratedPortionPrimitive2D::hasTextDecoration() const
+ {
+ return TEXT_LINE_NONE != getFontOverline()
+ || TEXT_LINE_NONE != getFontUnderline()
+ || TEXT_STRIKEOUT_NONE != getTextStrikeout()
+ || TEXT_FONT_EMPHASIS_MARK_NONE != getTextEmphasisMark();
+ }
+
bool TextDecoratedPortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
if(TextSimplePortionPrimitive2D::operator==(rPrimitive))
@@ -392,7 +574,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextDecoratedPortionPrimitive2D, PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
+ sal_uInt32 TextDecoratedPortionPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
index abfe28e3ecca..f1bb6812bfd2 100644
--- a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
@@ -24,222 +24,221 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
-
namespace drawinglayer::primitive2d
{
- const double fDiscreteSize(1.1);
+const double fDiscreteSize(1.1);
- void TextEffectPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+Primitive2DReference TextEffectPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to
+ // have good results on rotated objects, too
+ const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(fDiscreteSize, fDiscreteSize));
+ const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44));
+
+ Primitive2DContainer aContainer;
+ switch (getTextEffectStyle2D())
+ {
+ case TextEffectStyle2D::ReliefEmbossed:
+ case TextEffectStyle2D::ReliefEmbossedDefault:
+ case TextEffectStyle2D::ReliefEngravedDefault:
{
- // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to
- // have good results on rotated objects, too
- const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation() *
- basegfx::B2DVector(fDiscreteSize, fDiscreteSize));
- const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44));
-
- switch(getTextEffectStyle2D())
+ // prepare transform of sub-group back to (0,0) and align to X-Axis
+ basegfx::B2DHomMatrix aBackTransform(basegfx::utils::createTranslateB2DHomMatrix(
+ -getRotationCenter().getX(), -getRotationCenter().getY()));
+ aBackTransform.rotate(-getDirection());
+
+ // prepare transform of sub-group back to its position and rotation
+ basegfx::B2DHomMatrix aForwardTransform(
+ basegfx::utils::createRotateB2DHomMatrix(getDirection()));
+ aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY());
+
+ // create transformation for one discrete unit
+ const bool bEmbossed(TextEffectStyle2D::ReliefEmbossed == getTextEffectStyle2D()
+ || TextEffectStyle2D::ReliefEmbossedDefault
+ == getTextEffectStyle2D());
+ const bool bDefaultTextColor(
+ TextEffectStyle2D::ReliefEmbossedDefault == getTextEffectStyle2D()
+ || TextEffectStyle2D::ReliefEngravedDefault == getTextEffectStyle2D());
+ basegfx::B2DHomMatrix aTransform(aBackTransform);
+
+ if (bEmbossed)
{
- case TextEffectStyle2D::ReliefEmbossed:
- case TextEffectStyle2D::ReliefEngraved:
- case TextEffectStyle2D::ReliefEmbossedDefault:
- case TextEffectStyle2D::ReliefEngravedDefault:
- {
- // prepare transform of sub-group back to (0,0) and align to X-Axis
- basegfx::B2DHomMatrix aBackTransform(basegfx::utils::createTranslateB2DHomMatrix(
- -getRotationCenter().getX(), -getRotationCenter().getY()));
- aBackTransform.rotate(-getDirection());
-
- // prepare transform of sub-group back to its position and rotation
- basegfx::B2DHomMatrix aForwardTransform(basegfx::utils::createRotateB2DHomMatrix(getDirection()));
- aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY());
-
- // create transformation for one discrete unit
- const bool bEmbossed(
- TextEffectStyle2D::ReliefEmbossed == getTextEffectStyle2D()
- || TextEffectStyle2D::ReliefEmbossedDefault == getTextEffectStyle2D());
- const bool bDefaultTextColor(
- TextEffectStyle2D::ReliefEmbossedDefault == getTextEffectStyle2D()
- || TextEffectStyle2D::ReliefEngravedDefault == getTextEffectStyle2D());
- basegfx::B2DHomMatrix aTransform(aBackTransform);
-
- if(bEmbossed)
- {
- // to bottom-right
- aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY());
- }
- else
- {
- // to top-left
- aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY());
- }
-
- aTransform *= aForwardTransform;
-
- if(bDefaultTextColor)
- {
- // emboss/engrave in black, original forced to white
- const basegfx::BColorModifierSharedPtr aBColorModifierToGray =
- std::make_shared<basegfx::BColorModifier_replace>(
- basegfx::BColor(0.0));
- const Primitive2DReference xModifiedColor(
- new ModifiedColorPrimitive2D(
- getTextContent(),
- aBColorModifierToGray));
-
- rContainer.push_back(
- new TransformPrimitive2D(
- aTransform,
- Primitive2DContainer { xModifiedColor }));
-
- // add original, too
- const basegfx::BColorModifierSharedPtr aBColorModifierToWhite =
- std::make_shared<basegfx::BColorModifier_replace>(
- basegfx::BColor(1.0));
-
- rContainer.push_back(
- new ModifiedColorPrimitive2D(
- getTextContent(),
- aBColorModifierToWhite));
- }
- else
- {
- // emboss/engrave in gray, keep original's color
- const basegfx::BColorModifierSharedPtr aBColorModifierToGray =
- std::make_shared<basegfx::BColorModifier_replace>(
- basegfx::BColor(0.75)); // 192
- const Primitive2DReference xModifiedColor(
- new ModifiedColorPrimitive2D(
- getTextContent(),
- aBColorModifierToGray));
-
- rContainer.push_back(
- new TransformPrimitive2D(
- aTransform,
- Primitive2DContainer { xModifiedColor }));
-
- // add original, too
- rContainer.push_back(new GroupPrimitive2D(getTextContent()));
- }
-
- break;
- }
- case TextEffectStyle2D::Outline:
- {
- // create transform primitives in all directions
- basegfx::B2DHomMatrix aTransform;
-
- aTransform.set(0, 2, aDistance.getX());
- aTransform.set(1, 2, 0.0);
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, aDiagonalDistance.getX());
- aTransform.set(1, 2, aDiagonalDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, 0.0);
- aTransform.set(1, 2, aDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, -aDiagonalDistance.getX());
- aTransform.set(1, 2, aDiagonalDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, -aDistance.getX());
- aTransform.set(1, 2, 0.0);
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, -aDiagonalDistance.getX());
- aTransform.set(1, 2, -aDiagonalDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, 0.0);
- aTransform.set(1, 2, -aDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- aTransform.set(0, 2, aDiagonalDistance.getX());
- aTransform.set(1, 2, -aDiagonalDistance.getY());
- rContainer.push_back(new TransformPrimitive2D(aTransform, getTextContent()));
-
- // at last, place original over it, but force to white
- const basegfx::BColorModifierSharedPtr aBColorModifierToWhite =
- std::make_shared<basegfx::BColorModifier_replace>(
- basegfx::BColor(1.0, 1.0, 1.0));
- rContainer.push_back(
- new ModifiedColorPrimitive2D(
- getTextContent(),
- aBColorModifierToWhite));
-
- break;
- }
+ // to bottom-right
+ aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY());
+ }
+ else
+ {
+ // to top-left
+ aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY());
}
- }
- TextEffectPrimitive2D::TextEffectPrimitive2D(
- const Primitive2DContainer& rTextContent,
- const basegfx::B2DPoint& rRotationCenter,
- double fDirection,
- TextEffectStyle2D eTextEffectStyle2D)
- : BufferedDecompositionPrimitive2D(),
- maTextContent(rTextContent),
- maRotationCenter(rRotationCenter),
- mfDirection(fDirection),
- meTextEffectStyle2D(eTextEffectStyle2D)
- {
- }
+ aTransform *= aForwardTransform;
- bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BasePrimitive2D::operator==(rPrimitive))
+ if (bDefaultTextColor)
{
- const TextEffectPrimitive2D& rCompare = static_cast<const TextEffectPrimitive2D&>(rPrimitive);
+ // emboss/engrave in black, original forced to white
+ basegfx::BColorModifierSharedPtr aBColorModifierToGray
+ = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0.0));
+ Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(
+ Primitive2DContainer(getTextContent()), std::move(aBColorModifierToGray)));
+
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer{ xModifiedColor }));
- return (getTextContent() == rCompare.getTextContent()
- && getRotationCenter() == rCompare.getRotationCenter()
- && getDirection() == rCompare.getDirection()
- && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D());
+ // add original, too
+ basegfx::BColorModifierSharedPtr aBColorModifierToWhite
+ = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(1.0));
+
+ aContainer.push_back(new ModifiedColorPrimitive2D(
+ Primitive2DContainer(getTextContent()), std::move(aBColorModifierToWhite)));
+ }
+ else
+ {
+ // emboss/engrave in gray, keep original's color
+ basegfx::BColorModifierSharedPtr aBColorModifierToGray
+ = std::make_shared<basegfx::BColorModifier_replace>(
+ basegfx::BColor(0.75)); // 192
+ Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(
+ Primitive2DContainer(getTextContent()), std::move(aBColorModifierToGray)));
+
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer{ xModifiedColor }));
+
+ // add original, too
+ aContainer.push_back(new GroupPrimitive2D(Primitive2DContainer(getTextContent())));
}
- return false;
+ break;
}
-
- basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ case TextEffectStyle2D::Outline:
{
- // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask
- // the whole decomposition for its ranges (which may be expensive with outline mode which
- // then will ask 9 times at nearly the same content. This may even be refined here using the
- // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to
- // be in two directions
- basegfx::B2DRange aRetval(getTextContent().getB2DRange(rViewInformation));
- aRetval.grow(fDiscreteSize);
-
- return aRetval;
+ // create transform primitives in all directions
+ basegfx::B2DHomMatrix aTransform;
+
+ aTransform.set(0, 2, aDistance.getX());
+ aTransform.set(1, 2, 0.0);
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, aDiagonalDistance.getX());
+ aTransform.set(1, 2, aDiagonalDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, 0.0);
+ aTransform.set(1, 2, aDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, -aDiagonalDistance.getX());
+ aTransform.set(1, 2, aDiagonalDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, -aDistance.getX());
+ aTransform.set(1, 2, 0.0);
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, -aDiagonalDistance.getX());
+ aTransform.set(1, 2, -aDiagonalDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, 0.0);
+ aTransform.set(1, 2, -aDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ aTransform.set(0, 2, aDiagonalDistance.getX());
+ aTransform.set(1, 2, -aDiagonalDistance.getY());
+ aContainer.push_back(
+ new TransformPrimitive2D(aTransform, Primitive2DContainer(getTextContent())));
+
+ // at last, place original over it, but force to white
+ basegfx::BColorModifierSharedPtr aBColorModifierToWhite
+ = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(1.0, 1.0, 1.0));
+ aContainer.push_back(new ModifiedColorPrimitive2D(
+ Primitive2DContainer(getTextContent()), std::move(aBColorModifierToWhite)));
+
+ break;
}
+ }
+ return new GroupPrimitive2D(std::move(aContainer));
+}
+
+TextEffectPrimitive2D::TextEffectPrimitive2D(Primitive2DContainer&& rTextContent,
+ const basegfx::B2DPoint& rRotationCenter,
+ double fDirection,
+ TextEffectStyle2D eTextEffectStyle2D)
+ : maTextContent(std::move(rTextContent))
+ , maRotationCenter(rRotationCenter)
+ , mfDirection(fDirection)
+ , meTextEffectStyle2D(eTextEffectStyle2D)
+{
+}
- void TextEffectPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
+bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BasePrimitive2D::operator==(rPrimitive))
+ {
+ const TextEffectPrimitive2D& rCompare
+ = static_cast<const TextEffectPrimitive2D&>(rPrimitive);
+
+ return (getTextContent() == rCompare.getTextContent()
+ && getRotationCenter() == rCompare.getRotationCenter()
+ && getDirection() == rCompare.getDirection()
+ && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D());
+ }
+
+ return false;
+}
+
+basegfx::B2DRange
+TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+{
+ // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask
+ // the whole decomposition for its ranges (which may be expensive with outline mode which
+ // then will ask 9 times at nearly the same content. This may even be refined here using the
+ // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to
+ // be in two directions
+ basegfx::B2DRange aRetval(getTextContent().getB2DRange(rViewInformation));
+ aRetval.grow(fDiscreteSize);
+
+ return aRetval;
+}
+
+void TextEffectPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+{
+ if (hasBuffered2DDecomposition())
+ {
+ if (maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- if(!getBuffered2DDecomposition().empty())
- {
- if(maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
- {
- // conditions of last local decomposition have changed, delete
- const_cast< TextEffectPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
- }
- }
+ // conditions of last local decomposition have changed, delete
+ const_cast<TextEffectPrimitive2D*>(this)->setBuffered2DDecomposition(nullptr);
+ }
+ }
- if(getBuffered2DDecomposition().empty())
- {
- // remember ViewRange and ViewTransformation
- const_cast< TextEffectPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
- }
+ if (!hasBuffered2DDecomposition())
+ {
+ // remember ViewRange and ViewTransformation
+ const_cast<TextEffectPrimitive2D*>(this)->maLastObjectToViewTransformation
+ = rViewInformation.getObjectToViewTransformation();
+ }
- // use parent implementation
- BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
- }
+ // use parent implementation
+ BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+}
- // provide unique ID
- ImplPrimitive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D)
+// provide unique ID
+sal_uInt32 TextEffectPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D;
+}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
index 77f7f659739c..d0a69ad9a336 100644
--- a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
@@ -19,6 +19,7 @@
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <comphelper/lok.hxx>
using namespace com::sun::star;
@@ -26,19 +27,22 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
- TextHierarchyLinePrimitive2D::TextHierarchyLinePrimitive2D(const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ TextHierarchyLinePrimitive2D::TextHierarchyLinePrimitive2D(Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyLinePrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D)
+ sal_uInt32 TextHierarchyLinePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D;
+ }
TextHierarchyParagraphPrimitive2D::TextHierarchyParagraphPrimitive2D(
- const Primitive2DContainer& rChildren,
+ Primitive2DContainer&& aChildren,
sal_Int16 nOutlineLevel)
- : GroupPrimitive2D(rChildren),
+ : GroupPrimitive2D(std::move(aChildren)),
mnOutlineLevel(nOutlineLevel)
{
}
@@ -56,35 +60,43 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyParagraphPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D)
+ sal_uInt32 TextHierarchyParagraphPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D;
+ }
- TextHierarchyBulletPrimitive2D::TextHierarchyBulletPrimitive2D(const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ TextHierarchyBulletPrimitive2D::TextHierarchyBulletPrimitive2D(Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyBulletPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D)
+ sal_uInt32 TextHierarchyBulletPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D;
+ }
- TextHierarchyBlockPrimitive2D::TextHierarchyBlockPrimitive2D(const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ TextHierarchyBlockPrimitive2D::TextHierarchyBlockPrimitive2D(Primitive2DContainer&& aChildren)
+ : GroupPrimitive2D(std::move(aChildren))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyBlockPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D)
+ sal_uInt32 TextHierarchyBlockPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D;
+ }
TextHierarchyFieldPrimitive2D::TextHierarchyFieldPrimitive2D(
- const Primitive2DContainer& rChildren,
+ Primitive2DContainer&& aChildren,
const FieldType& rFieldType,
const std::vector< std::pair< OUString, OUString>>* pNameValue)
- : GroupPrimitive2D(rChildren),
- meType(rFieldType),
- meNameValue()
+ : GroupPrimitive2D(std::move(aChildren)),
+ meType(rFieldType)
{
if (nullptr != pNameValue)
{
@@ -119,14 +131,44 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyFieldPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D)
- TextHierarchyEditPrimitive2D::TextHierarchyEditPrimitive2D(const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren)
+ sal_uInt32 TextHierarchyFieldPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D;
+ }
+
+
+ TextHierarchyEditPrimitive2D::TextHierarchyEditPrimitive2D(Primitive2DContainer&& aContent)
+ : GroupPrimitive2D(std::move(aContent))
+ {
+ }
+
+ void TextHierarchyEditPrimitive2D::get2DDecomposition(
+ Primitive2DDecompositionVisitor& rVisitor,
+ const geometry::ViewInformation2D& rViewInformation) const
+ {
+ // check if TextEdit is active. If not, process. If yes, suppress the content
+ // lok case: always decompose it when we're rendering a slide show
+ if (!rViewInformation.getTextEditActive() || comphelper::LibreOfficeKit::isSlideshowRendering())
+ GroupPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
+ }
+
+ // provide unique ID
+ sal_uInt32 TextHierarchyEditPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D;
+ }
+
+
+ TextHierarchyEmphasisMarkPrimitive2D::TextHierarchyEmphasisMarkPrimitive2D(Primitive2DContainer&& aContent)
+ : GroupPrimitive2D(std::move(aContent))
{
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextHierarchyEditPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D)
+ sal_uInt32 TextHierarchyEmphasisMarkPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTHIERARCHYEMPHASISMARKPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index e3e57b2b5997..e92732fd1751 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -22,6 +22,8 @@
#include <algorithm>
#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/attribute/fontattribute.hxx>
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
#include <comphelper/processfactory.hxx>
@@ -29,455 +31,496 @@
#include <osl/diagnose.h>
#include <tools/gen.hxx>
#include <vcl/canvastools.hxx>
+#include <vcl/kernarray.hxx>
#include <vcl/timer.hxx>
#include <vcl/virdev.hxx>
#include <vcl/font.hxx>
#include <vcl/metric.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <vcl/svapp.hxx>
+#include <vcl/vcllayout.hxx>
+#include <vcl/glyphitemcache.hxx>
+namespace drawinglayer::primitive2d
+{
+namespace
+{
+class ImpTimedRefDev;
// VDev RevDevice provider
-namespace
+//the scoped_timed_RefDev owns an ImpTimeRefDev and releases it on dtor
+//or disposing of the default XComponentContext which causes the underlying
+//OutputDevice to get released
+
+//The ImpTimerRefDev itself, if the timeout ever gets hit, will call
+//reset on the scoped_timed_RefDev to release the ImpTimerRefDev early
+//if it's unused for a few minutes
+class scoped_timed_RefDev : public comphelper::unique_disposing_ptr<ImpTimedRefDev>
{
- class ImpTimedRefDev;
+public:
+ scoped_timed_RefDev()
+ : comphelper::unique_disposing_ptr<ImpTimedRefDev>(
+ (css::uno::Reference<css::lang::XComponent>(
+ ::comphelper::getProcessComponentContext(), css::uno::UNO_QUERY_THROW)))
+ {
+ }
+};
- //the scoped_timed_RefDev owns an ImpTimeRefDev and releases it on dtor
- //or disposing of the default XComponentContext which causes the underlying
- //OutputDevice to get released
+class the_scoped_timed_RefDev : public rtl::Static<scoped_timed_RefDev, the_scoped_timed_RefDev>
+{
+};
- //The ImpTimerRefDev itself, if the timeout ever gets hit, will call
- //reset on the scoped_timed_RefDev to release the ImpTimerRefDev early
- //if it's unused for a few minutes
- class scoped_timed_RefDev : public comphelper::unique_disposing_ptr<ImpTimedRefDev>
- {
- public:
- scoped_timed_RefDev() : comphelper::unique_disposing_ptr<ImpTimedRefDev>((css::uno::Reference<css::lang::XComponent>(::comphelper::getProcessComponentContext(), css::uno::UNO_QUERY_THROW)))
- {
- }
- };
+class ImpTimedRefDev : public Timer
+{
+ scoped_timed_RefDev& mrOwnerOfMe;
+ VclPtr<VirtualDevice> mpVirDev;
+ sal_uInt32 mnUseCount;
+
+public:
+ explicit ImpTimedRefDev(scoped_timed_RefDev& rOwnerofMe);
+ virtual ~ImpTimedRefDev() override;
+ virtual void Invoke() override;
+
+ VirtualDevice& acquireVirtualDevice();
+ void releaseVirtualDevice();
+};
+
+ImpTimedRefDev::ImpTimedRefDev(scoped_timed_RefDev& rOwnerOfMe)
+ : Timer("drawinglayer ImpTimedRefDev destroy mpVirDev")
+ , mrOwnerOfMe(rOwnerOfMe)
+ , mpVirDev(nullptr)
+ , mnUseCount(0)
+{
+ SetTimeout(3L * 60L * 1000L); // three minutes
+ Start();
+}
- class the_scoped_timed_RefDev : public rtl::Static<scoped_timed_RefDev, the_scoped_timed_RefDev> {};
+ImpTimedRefDev::~ImpTimedRefDev()
+{
+ OSL_ENSURE(0 == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
+ const SolarMutexGuard aSolarGuard;
+ mpVirDev.disposeAndClear();
+}
- class ImpTimedRefDev : public Timer
- {
- scoped_timed_RefDev& mrOwnerOfMe;
- VclPtr<VirtualDevice> mpVirDev;
- sal_uInt32 mnUseCount;
-
- public:
- explicit ImpTimedRefDev(scoped_timed_RefDev& rOwnerofMe);
- virtual ~ImpTimedRefDev() override;
- virtual void Invoke() override;
-
- VirtualDevice& acquireVirtualDevice();
- void releaseVirtualDevice();
- };
-
- ImpTimedRefDev::ImpTimedRefDev(scoped_timed_RefDev& rOwnerOfMe)
- : Timer( "drawinglayer ImpTimedRefDev destroy mpVirDev" ),
- mrOwnerOfMe(rOwnerOfMe),
- mpVirDev(nullptr),
- mnUseCount(0)
+void ImpTimedRefDev::Invoke()
+{
+ // for obvious reasons, do not call anything after this
+ mrOwnerOfMe.reset();
+}
+
+VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
+{
+ if (!mpVirDev)
{
- SetTimeout(3L * 60L * 1000L); // three minutes
- Start();
+ mpVirDev = VclPtr<VirtualDevice>::Create();
+ mpVirDev->SetReferenceDevice(VirtualDevice::RefDevMode::MSO1);
}
- ImpTimedRefDev::~ImpTimedRefDev()
+ if (!mnUseCount)
{
- OSL_ENSURE(0 == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
- const SolarMutexGuard aSolarGuard;
- mpVirDev.disposeAndClear();
+ Stop();
}
- void ImpTimedRefDev::Invoke()
+ mnUseCount++;
+
+ return *mpVirDev;
+}
+
+void ImpTimedRefDev::releaseVirtualDevice()
+{
+ OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
+ mnUseCount--;
+
+ if (!mnUseCount)
{
- // for obvious reasons, do not call anything after this
- mrOwnerOfMe.reset();
+ Start();
}
+}
- VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
- {
- if(!mpVirDev)
- {
- mpVirDev = VclPtr<VirtualDevice>::Create();
- mpVirDev->SetReferenceDevice( VirtualDevice::RefDevMode::MSO1 );
- }
+VirtualDevice& acquireGlobalVirtualDevice()
+{
+ scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
- if(!mnUseCount)
- {
- Stop();
- }
+ if (!rStdRefDevice)
+ rStdRefDevice.reset(new ImpTimedRefDev(rStdRefDevice));
- mnUseCount++;
+ return rStdRefDevice->acquireVirtualDevice();
+}
- return *mpVirDev;
- }
+void releaseGlobalVirtualDevice()
+{
+ scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
- void ImpTimedRefDev::releaseVirtualDevice()
- {
- OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
- mnUseCount--;
+ OSL_ENSURE(rStdRefDevice,
+ "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
+ rStdRefDevice->releaseVirtualDevice();
+}
- if(!mnUseCount)
- {
- Start();
- }
- }
} // end of anonymous namespace
+TextLayouterDevice::TextLayouterDevice()
+ : mrDevice(acquireGlobalVirtualDevice())
+{
+ // tdf#168002 activate SubpixelPositioning for al TextLayouterDevice-calls
+ mrDevice.setSubpixelPositioning(true);
+}
-// access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive
+TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE { releaseGlobalVirtualDevice(); }
-namespace drawinglayer::primitive2d
+void TextLayouterDevice::setFont(const vcl::Font& rFont)
{
- // static methods here
- static VirtualDevice& acquireGlobalVirtualDevice()
- {
- scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
+ mrDevice.SetFont(rFont);
+ mnFontScalingFixX = 1.0;
+ mnFontScalingFixY = 1.0;
+}
+
+void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontAttribute,
+ double fFontScaleX, double fFontScaleY,
+ const css::lang::Locale& rLocale)
+{
+ vcl::Font aFont
+ = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale);
+ setFont(aFont);
+ Size aFontSize = aFont.GetFontSize();
+ if (aFontSize.Height())
+ {
+ mnFontScalingFixY = fFontScaleY / aFontSize.Height();
+ // aFontSize.Width() is 0 for uninformly scaled fonts: see getVclFontFromFontAttribute
+ mnFontScalingFixX
+ = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height());
+ }
+ else
+ {
+ mnFontScalingFixX = mnFontScalingFixY = 1.0;
+ }
+}
- if(!rStdRefDevice)
- rStdRefDevice.reset(new ImpTimedRefDev(rStdRefDevice));
+void TextLayouterDevice::setLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
+{
+ mrDevice.SetLayoutMode(nTextLayoutMode);
+}
- return rStdRefDevice->acquireVirtualDevice();
- }
+vcl::text::ComplexTextLayoutFlags TextLayouterDevice::getLayoutMode() const
+{
+ return mrDevice.GetLayoutMode();
+}
- static void releaseGlobalVirtualDevice()
- {
- scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
+void TextLayouterDevice::setTextColor(const basegfx::BColor& rColor)
+{
+ mrDevice.SetTextColor(Color(rColor));
+}
- OSL_ENSURE(rStdRefDevice, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
- rStdRefDevice->releaseVirtualDevice();
- }
+double TextLayouterDevice::getOverlineOffset() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ double fRet = (aMetric.GetInternalLeading() / 2.0) - aMetric.GetAscent();
+ return fRet * mnFontScalingFixY;
+}
- TextLayouterDevice::TextLayouterDevice()
- : maSolarGuard(),
- mrDevice(acquireGlobalVirtualDevice())
- {
- }
+double TextLayouterDevice::getUnderlineOffset() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ double fRet = aMetric.GetDescent() / 2.0;
+ return fRet * mnFontScalingFixY;
+}
- TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE
- {
- releaseGlobalVirtualDevice();
- }
+double TextLayouterDevice::getStrikeoutOffset() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ double fRet = (aMetric.GetAscent() - aMetric.GetInternalLeading()) / 3.0;
+ return fRet * mnFontScalingFixY;
+}
- void TextLayouterDevice::setFont(const vcl::Font& rFont)
- {
- mrDevice.SetFont( rFont );
- }
+double TextLayouterDevice::getOverlineHeight() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ double fRet = aMetric.GetInternalLeading() / 2.5;
+ return fRet * mnFontScalingFixY;
+}
- void TextLayouterDevice::setFontAttribute(
- const attribute::FontAttribute& rFontAttribute,
- double fFontScaleX,
- double fFontScaleY,
- const css::lang::Locale& rLocale)
- {
- setFont(getVclFontFromFontAttribute(
- rFontAttribute,
- fFontScaleX,
- fFontScaleY,
- 0.0,
- rLocale));
- }
+double TextLayouterDevice::getUnderlineHeight() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ double fRet = aMetric.GetDescent() / 4.0;
+ return fRet * mnFontScalingFixY;
+}
- double TextLayouterDevice::getOverlineOffset() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- double fRet = (rMetric.GetInternalLeading() / 2.0) - rMetric.GetAscent();
- return fRet;
- }
+double TextLayouterDevice::getTextHeight() const
+{
+ return mrDevice.GetTextHeightDouble() * mnFontScalingFixY;
+}
- double TextLayouterDevice::getUnderlineOffset() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- double fRet = rMetric.GetDescent() / 2.0;
- return fRet;
- }
+double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 nIndex,
+ sal_uInt32 nLength) const
+{
+ return mrDevice.GetTextWidthDouble(rText, nIndex, nLength) * mnFontScalingFixX;
+}
- double TextLayouterDevice::getStrikeoutOffset() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- double fRet = (rMetric.GetAscent() - rMetric.GetInternalLeading()) / 3.0;
- return fRet;
- }
+void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
+ const OUString& rText, sal_uInt32 nIndex,
+ sal_uInt32 nLength, const std::vector<double>& rDXArray,
+ const std::vector<sal_Bool>& rKashidaArray) const
+{
+ const sal_uInt32 nDXArrayCount(rDXArray.size());
+ sal_uInt32 nTextLength(nLength);
+ const sal_uInt32 nStringLength(rText.getLength());
- double TextLayouterDevice::getOverlineHeight() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- double fRet = rMetric.GetInternalLeading() / 2.5;
- return fRet;
- }
+ if (nTextLength + nIndex > nStringLength)
+ {
+ nTextLength = nStringLength - nIndex;
+ }
- double TextLayouterDevice::getUnderlineHeight() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- double fRet = rMetric.GetDescent() / 4.0;
- return fRet;
- }
+ if (nDXArrayCount)
+ {
+ OSL_ENSURE(nDXArrayCount == nTextLength,
+ "DXArray size does not correspond to text portion size (!)");
- double TextLayouterDevice::getTextHeight() const
- {
- return mrDevice.GetTextHeight();
- }
+ mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength, 0, rDXArray,
+ rKashidaArray);
+ }
+ else
+ {
+ mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength);
+ }
+ if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+ || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
+ {
+ auto scale = basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY);
+ for (auto& poly : rB2DPolyPolyVector)
+ poly.transform(scale);
+ }
+}
- double TextLayouterDevice::getTextWidth(
- const OUString& rText,
- sal_uInt32 nIndex,
- sal_uInt32 nLength) const
- {
- return mrDevice.GetTextWidth(rText, nIndex, nLength);
- }
+basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sal_uInt32 nIndex,
+ sal_uInt32 nLength) const
+{
+ sal_uInt32 nTextLength(nLength);
+ const sal_uInt32 nStringLength(rText.getLength());
- void TextLayouterDevice::getTextOutlines(
- basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
- const OUString& rText,
- sal_uInt32 nIndex,
- sal_uInt32 nLength,
- const std::vector< double >& rDXArray) const
- {
- const sal_uInt32 nDXArrayCount(rDXArray.size());
- sal_uInt32 nTextLength(nLength);
- const sal_uInt32 nStringLength(rText.getLength());
-
- if(nTextLength + nIndex > nStringLength)
- {
- nTextLength = nStringLength - nIndex;
- }
-
- if(nDXArrayCount)
- {
- OSL_ENSURE(nDXArrayCount == nTextLength, "DXArray size does not correspond to text portion size (!)");
- std::vector< long > aIntegerDXArray(nDXArrayCount);
-
- for(sal_uInt32 a(0); a < nDXArrayCount; a++)
- {
- aIntegerDXArray[a] = basegfx::fround(rDXArray[a]);
- }
-
- mrDevice.GetTextOutlines(
- rB2DPolyPolyVector,
- rText,
- nIndex,
- nIndex,
- nLength,
- 0,
- aIntegerDXArray.data());
- }
- else
- {
- mrDevice.GetTextOutlines(
- rB2DPolyPolyVector,
- rText,
- nIndex,
- nIndex,
- nLength);
- }
- }
+ if (nTextLength + nIndex > nStringLength)
+ {
+ nTextLength = nStringLength - nIndex;
+ }
- basegfx::B2DRange TextLayouterDevice::getTextBoundRect(
- const OUString& rText,
- sal_uInt32 nIndex,
- sal_uInt32 nLength) const
+ if (nTextLength)
+ {
+ basegfx::B2DRange aRect;
+ mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength);
+ if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+ || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
{
- sal_uInt32 nTextLength(nLength);
- const sal_uInt32 nStringLength(rText.getLength());
-
- if(nTextLength + nIndex > nStringLength)
- {
- nTextLength = nStringLength - nIndex;
- }
-
- if(nTextLength)
- {
- ::tools::Rectangle aRect;
-
- mrDevice.GetTextBoundRect(
- aRect,
- rText,
- nIndex,
- nIndex,
- nLength);
-
- // #i104432#, #i102556# take empty results into account
- if(!aRect.IsEmpty())
- {
- return vcl::unotools::b2DRectangleFromRectangle(aRect);
- }
- }
-
- return basegfx::B2DRange();
+ aRect.transform(
+ basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY));
}
+ return aRect;
+ }
- double TextLayouterDevice::getFontAscent() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- return rMetric.GetAscent();
- }
+ return basegfx::B2DRange();
+}
- double TextLayouterDevice::getFontDescent() const
- {
- const ::FontMetric& rMetric = mrDevice.GetFontMetric();
- return rMetric.GetDescent();
- }
+double TextLayouterDevice::getFontAscent() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ return aMetric.GetAscent() * mnFontScalingFixY;
+}
- void TextLayouterDevice::addTextRectActions(
- const ::tools::Rectangle& rRectangle,
- const OUString& rText,
- DrawTextFlags nStyle,
- GDIMetaFile& rGDIMetaFile) const
- {
- mrDevice.AddTextRectActions(
- rRectangle, rText, nStyle, rGDIMetaFile);
- }
+double TextLayouterDevice::getFontDescent() const
+{
+ const ::FontMetric aMetric = mrDevice.GetFontMetric();
+ return aMetric.GetDescent() * mnFontScalingFixY;
+}
- std::vector< double > TextLayouterDevice::getTextArray(
- const OUString& rText,
- sal_uInt32 nIndex,
- sal_uInt32 nLength) const
- {
- std::vector< double > aRetval;
- sal_uInt32 nTextLength(nLength);
- const sal_uInt32 nStringLength(rText.getLength());
-
- if(nTextLength + nIndex > nStringLength)
- {
- nTextLength = nStringLength - nIndex;
- }
-
- if(nTextLength)
- {
- aRetval.reserve(nTextLength);
- std::vector<long> aArray(nTextLength);
- mrDevice.GetTextArray(rText, aArray.data(), nIndex, nLength);
- aRetval.assign(aArray.begin(), aArray.end());
- }
-
- return aRetval;
- }
+void TextLayouterDevice::addTextRectActions(const ::tools::Rectangle& rRectangle,
+ const OUString& rText, DrawTextFlags nStyle,
+ GDIMetaFile& rGDIMetaFile) const
+{
+ mrDevice.AddTextRectActions(rRectangle, rText, nStyle, rGDIMetaFile);
+}
+std::vector<double> TextLayouterDevice::getTextArray(const OUString& rText, sal_uInt32 nIndex,
+ sal_uInt32 nLength, bool bCaret) const
+{
+ std::vector<double> aRetval;
+ sal_uInt32 nTextLength(nLength);
+ const sal_uInt32 nStringLength(rText.getLength());
+
+ if (nTextLength + nIndex > nStringLength)
+ {
+ nTextLength = nStringLength - nIndex;
+ }
+
+ if (nTextLength)
+ {
+ KernArray aArray;
+ mrDevice.GetTextArray(rText, &aArray, nIndex, nTextLength, bCaret);
+ aRetval.reserve(aArray.size());
+ for (size_t i = 0, nEnd = aArray.size(); i < nEnd; ++i)
+ aRetval.push_back(aArray[i] * mnFontScalingFixX);
+ }
+
+ return aRetval;
+}
+
+std::unique_ptr<SalLayout>
+TextLayouterDevice::getSalLayout(const OUString& rText, sal_uInt32 nIndex, sal_uInt32 nLength,
+ const basegfx::B2DPoint& rStartPoint, const KernArray& rDXArray,
+ std::span<const sal_Bool> pKashidaAry) const
+{
+ const SalLayoutGlyphs* pGlyphs(
+ SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&mrDevice, rText, nIndex, nLength));
+ const Point aStartPoint(basegfx::fround<tools::Long>(rStartPoint.getX()),
+ basegfx::fround<tools::Long>(rStartPoint.getY()));
+ return mrDevice.ImplLayout(rText, nIndex, nLength, aStartPoint, 0, rDXArray, pKashidaAry,
+ SalLayoutFlags::NONE, nullptr, pGlyphs);
+}
+
+void TextLayouterDevice::createEmphasisMarks(
+ const SalLayout& rSalLayout, TextEmphasisMark aTextEmphasisMark, bool bAbove,
+ const std::function<void(const basegfx::B2DPoint&, const basegfx::B2DPolyPolygon&, bool,
+ const tools::Rectangle&, const tools::Rectangle&)>& rCallback) const
+{
+ FontEmphasisMark nEmphasisMark(FontEmphasisMark::NONE);
+ double fEmphasisHeight(getTextHeight() * (250.0 / 1000.0));
+
+ switch (aTextEmphasisMark)
+ {
+ case TEXT_FONT_EMPHASIS_MARK_DOT:
+ nEmphasisMark = FontEmphasisMark::Dot;
+ break;
+ case TEXT_FONT_EMPHASIS_MARK_CIRCLE:
+ nEmphasisMark = FontEmphasisMark::Circle;
+ break;
+ case TEXT_FONT_EMPHASIS_MARK_DISC:
+ nEmphasisMark = FontEmphasisMark::Disc;
+ break;
+ case TEXT_FONT_EMPHASIS_MARK_ACCENT:
+ nEmphasisMark = FontEmphasisMark::Accent;
+ break;
+ default:
+ break;
+ }
+
+ if (bAbove)
+ nEmphasisMark |= FontEmphasisMark::PosAbove;
+ else
+ nEmphasisMark |= FontEmphasisMark::PosBelow;
+
+ mrDevice.createEmphasisMarks(nEmphasisMark, static_cast<tools::Long>(fEmphasisHeight),
+ rSalLayout, rCallback);
+}
// helper methods for vcl font handling
- vcl::Font getVclFontFromFontAttribute(
- const attribute::FontAttribute& rFontAttribute,
- double fFontScaleX,
- double fFontScaleY,
- double fFontRotation,
- const css::lang::Locale& rLocale)
- {
- // detect FontScaling
- const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
- const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
- const bool bFontIsScaled(nHeight != nWidth);
+vcl::Font getVclFontFromFontAttribute(const attribute::FontAttribute& rFontAttribute,
+ double fFontScaleX, double fFontScaleY, double fFontRotation,
+ const css::lang::Locale& rLocale)
+{
+ // detect FontScaling
+ const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
+ const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
+ const bool bFontIsScaled(nHeight != nWidth);
#ifdef _WIN32
- // for WIN32 systems, start with creating an unscaled font. If FontScaling
- // is wanted, that width needs to be adapted using FontMetric again to get a
- // width of the unscaled font
- vcl::Font aRetval(
- rFontAttribute.getFamilyName(),
- rFontAttribute.getStyleName(),
- Size(0, nHeight));
+ // for WIN32 systems, start with creating an unscaled font. If FontScaling
+ // is wanted, that width needs to be adapted using FontMetric again to get a
+ // width of the unscaled font
+ vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(),
+ Size(0, nHeight));
#else
- // for non-WIN32 systems things are easier since these accept a Font creation
- // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
- // FontWidth when no scaling is used to explicitly have that zero when e.g. the
- // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
- // set FontWidth; import that in a WIN32 system, and trouble is there)
- vcl::Font aRetval(
- rFontAttribute.getFamilyName(),
- rFontAttribute.getStyleName(),
- Size(bFontIsScaled ? std::max<sal_uInt32>(nWidth, 1) : 0, nHeight));
+ // for non-WIN32 systems things are easier since these accept a Font creation
+ // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
+ // FontWidth when no scaling is used to explicitly have that zero when e.g. the
+ // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
+ // set FontWidth; import that in a WIN32 system, and trouble is there)
+ vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(),
+ Size(bFontIsScaled ? std::max<sal_uInt32>(nWidth, 1) : 0, nHeight));
#endif
- // define various other FontAttribute
- aRetval.SetAlignment(ALIGN_BASELINE);
- aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE);
- aRetval.SetVertical(rFontAttribute.getVertical());
- aRetval.SetWeight(static_cast<FontWeight>(rFontAttribute.getWeight()));
- aRetval.SetItalic(rFontAttribute.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
- aRetval.SetOutline(rFontAttribute.getOutline());
- aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE);
- aRetval.SetLanguage(LanguageTag::convertToLanguageType( rLocale, false));
+ // define various other FontAttribute
+ aRetval.SetAlignment(ALIGN_BASELINE);
+ aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL
+ : RTL_TEXTENCODING_UNICODE);
+ aRetval.SetVertical(rFontAttribute.getVertical());
+ aRetval.SetWeight(static_cast<FontWeight>(rFontAttribute.getWeight()));
+ aRetval.SetItalic(rFontAttribute.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
+ aRetval.SetOutline(rFontAttribute.getOutline());
+ aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE);
+ aRetval.SetLanguage(LanguageTag::convertToLanguageType(rLocale, false));
#ifdef _WIN32
- // for WIN32 systems, correct the FontWidth if FontScaling is used
- if(bFontIsScaled && nHeight > 0)
- {
- const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval));
-
- if(aUnscaledFontMetric.GetAverageFontWidth() > 0)
- {
- const double fScaleFactor(static_cast<double>(nWidth) / static_cast<double>(nHeight));
- const sal_uInt32 nScaledWidth(basegfx::fround(static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor));
- aRetval.SetAverageFontWidth(nScaledWidth);
- }
- }
-#endif
- // handle FontRotation (if defined)
- if(!basegfx::fTools::equalZero(fFontRotation))
- {
- sal_Int16 aRotate10th(static_cast<sal_Int16>(fFontRotation * (-1800.0/F_PI)));
- aRetval.SetOrientation(aRotate10th % 3600);
- }
-
- return aRetval;
- }
+ // for WIN32 systems, correct the FontWidth if FontScaling is used
+ if (bFontIsScaled && nHeight > 0)
+ {
+ const FontMetric aUnscaledFontMetric(
+ Application::GetDefaultDevice()->GetFontMetric(aRetval));
- attribute::FontAttribute getFontAttributeFromVclFont(
- basegfx::B2DVector& o_rSize,
- const vcl::Font& rFont,
- bool bRTL,
- bool bBiDiStrong)
+ if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
{
- const attribute::FontAttribute aRetval(
- rFont.GetFamilyName(),
- rFont.GetStyleName(),
- static_cast<sal_uInt16>(rFont.GetWeight()),
- RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(),
- rFont.IsVertical(),
- ITALIC_NONE != rFont.GetItalic(),
- PITCH_FIXED == rFont.GetPitch(),
- rFont.IsOutline(),
- bRTL,
- bBiDiStrong);
- // TODO: eKerning
-
- // set FontHeight and init to no FontScaling
- o_rSize.setY(std::max<long>(rFont.GetFontSize().getHeight(), 0));
- o_rSize.setX(o_rSize.getY());
+ const double fScaleFactor(static_cast<double>(nWidth) / static_cast<double>(nHeight));
+ const sal_uInt32 nScaledWidth(basegfx::fround(
+ static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor));
+ aRetval.SetAverageFontWidth(nScaledWidth);
+ }
+ }
+#endif
+ // handle FontRotation (if defined)
+ if (!basegfx::fTools::equalZero(fFontRotation))
+ {
+ int aRotate10th(-basegfx::rad2deg<10>(fFontRotation));
+ aRetval.SetOrientation(Degree10(aRotate10th % 3600));
+ }
+
+ return aRetval;
+}
+
+attribute::FontAttribute getFontAttributeFromVclFont(basegfx::B2DVector& o_rSize,
+ const vcl::Font& rFont, bool bRTL,
+ bool bBiDiStrong)
+{
+ const attribute::FontAttribute aRetval(
+ rFont.GetFamilyName(), rFont.GetStyleName(), static_cast<sal_uInt16>(rFont.GetWeight()),
+ RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), rFont.IsVertical(),
+ ITALIC_NONE != rFont.GetItalic(), PITCH_FIXED == rFont.GetPitch(), rFont.IsOutline(), bRTL,
+ bBiDiStrong);
+ // TODO: eKerning
+
+ // set FontHeight and init to no FontScaling
+ o_rSize.setY(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
+ o_rSize.setX(o_rSize.getY());
#ifdef _WIN32
- // for WIN32 systems, the FontScaling at the Font is detected by
- // checking that FontWidth != 0. When FontScaling is used, WIN32
- // needs to do extra stuff to detect the correct width (since it's
- // zero and not equal the font height) and its relationship to
- // the height
- if(rFont.GetFontSize().getWidth() > 0)
- {
- vcl::Font aUnscaledFont(rFont);
- aUnscaledFont.SetAverageFontWidth(0);
- const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
-
- if(aUnscaledFontMetric.GetAverageFontWidth() > 0)
- {
- const double fScaleFactor(static_cast<double>(rFont.GetFontSize().getWidth()) / static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()));
- o_rSize.setX(fScaleFactor * o_rSize.getY());
- }
- }
+ // for WIN32 systems, the FontScaling at the Font is detected by
+ // checking that FontWidth != 0. When FontScaling is used, WIN32
+ // needs to do extra stuff to detect the correct width (since it's
+ // zero and not equal the font height) and its relationship to
+ // the height
+ if (rFont.GetFontSize().getWidth() > 0)
+ {
+ vcl::Font aUnscaledFont(rFont);
+ aUnscaledFont.SetAverageFontWidth(0);
+ const FontMetric aUnscaledFontMetric(
+ Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
+
+ if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
+ {
+ const double fScaleFactor(
+ static_cast<double>(rFont.GetFontSize().getWidth())
+ / static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()));
+ o_rSize.setX(fScaleFactor * o_rSize.getY());
+ }
+ }
#else
- // For non-WIN32 systems the detection is the same, but the value
- // is easier achieved since width == height is interpreted as no
- // scaling. Ergo, Width == 0 means width == height, and width != 0
- // means the scaling is in the direct relation of width to height
- if(rFont.GetFontSize().getWidth() > 0)
- {
- o_rSize.setX(static_cast<double>(rFont.GetFontSize().getWidth()));
- }
+ // For non-WIN32 systems the detection is the same, but the value
+ // is easier achieved since width == height is interpreted as no
+ // scaling. Ergo, Width == 0 means width == height, and width != 0
+ // means the scaling is in the direct relation of width to height
+ if (rFont.GetFontSize().getWidth() > 0)
+ {
+ o_rSize.setX(static_cast<double>(rFont.GetFontSize().getWidth()));
+ }
#endif
- return aRetval;
- }
+ return aRetval;
+}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textlineprimitive2d.cxx b/drawinglayer/source/primitive2d/textlineprimitive2d.cxx
index 2238fc383d5c..362c2e9778fb 100644
--- a/drawinglayer/source/primitive2d/textlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textlineprimitive2d.cxx
@@ -22,16 +22,17 @@
#include <drawinglayer/attribute/strokeattribute.hxx>
#include <drawinglayer/attribute/lineattribute.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
+#include <utility>
namespace drawinglayer::primitive2d
{
- void TextLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference TextLinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if(TEXT_LINE_NONE == getTextLine())
- return;
+ return nullptr;
bool bDoubleLine(false);
bool bWaveLine(false);
@@ -89,10 +90,6 @@ namespace drawinglayer::primitive2d
break;
}
case TEXT_LINE_SMALLWAVE:
- {
- bWaveLine = true;
- break;
- }
case TEXT_LINE_WAVE:
{
bWaveLine = true;
@@ -177,7 +174,7 @@ namespace drawinglayer::primitive2d
aDoubleArray.push_back(static_cast<double>(*p) * fHeight);
}
- aStrokeAttribute = attribute::StrokeAttribute(aDoubleArray);
+ aStrokeAttribute = attribute::StrokeAttribute(std::move(aDoubleArray));
}
// create base polygon and new primitive
@@ -207,18 +204,19 @@ namespace drawinglayer::primitive2d
fWaveWidth *= 2.0;
}
- aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5));
+ aNewPrimitive = new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5);
}
else
{
- aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aLine, aLineAttribute, aStrokeAttribute));
+ aNewPrimitive = new PolygonStrokePrimitive2D(std::move(aLine), aLineAttribute, std::move(aStrokeAttribute));
}
- // add primitive
- rContainer.push_back(aNewPrimitive);
-
if(!bDoubleLine)
- return;
+ return aNewPrimitive;
+
+ // add primitive
+ Primitive2DContainer aContainer;
+ aContainer.push_back(aNewPrimitive);
// double line, create 2nd primitive with offset using TransformPrimitive based on
// already created NewPrimitive
@@ -242,19 +240,19 @@ namespace drawinglayer::primitive2d
aTransform.translate(aTranslate.getX(), aTranslate.getY());
// add transform primitive
- const Primitive2DContainer aContent { aNewPrimitive };
- rContainer.push_back( new TransformPrimitive2D(aTransform, aContent) );
+ Primitive2DContainer aContent { aNewPrimitive };
+ aContainer.push_back(new TransformPrimitive2D(aTransform, std::move(aContent)));
+ return new GroupPrimitive2D(std::move(aContainer));
}
TextLinePrimitive2D::TextLinePrimitive2D(
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
double fWidth,
double fOffset,
double fHeight,
TextLine eTextLine,
const basegfx::BColor& rLineColor)
- : BufferedDecompositionPrimitive2D(),
- maObjectTransformation(rObjectTransformation),
+ : maObjectTransformation(std::move(aObjectTransformation)),
mfWidth(fWidth),
mfOffset(fOffset),
mfHeight(fHeight),
@@ -281,7 +279,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextLinePrimitive2D, PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D)
+ sal_uInt32 TextLinePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx
index e85d61009632..fae5866c6517 100644
--- a/drawinglayer/source/primitive2d/textprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx
@@ -22,307 +22,352 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <primitive2d/texteffectprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
-
+#include <vcl/vcllayout.hxx>
+#include <vcl/rendercontext/State.hxx>
+#include <vcl/kernarray.hxx>
+#include <utility>
+#include <osl/diagnose.h>
using namespace com::sun::star;
-
+namespace drawinglayer::primitive2d
+{
namespace
{
- // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted
- // scale from a text transformation. A copy is modified so that it contains only positive
- // scalings and XY-equal scalings to allow to get a non-X-scaled Vcl-Font for TextLayouter.
- // rScale is adapted accordingly to contain the corrected scale which would need to be
- // applied to e.g. outlines received from TextLayouter under usage of fontScale. This
- // includes Y-Scale, X-Scale-correction and mirrorings.
- basegfx::B2DVector getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale)
+// adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted
+// scale from a text transformation. A copy is modified so that it contains only positive
+// scalings and XY-equal scalings to allow to get a non-X-scaled Vcl-Font for TextLayouter.
+// rScale is adapted accordingly to contain the corrected scale which would need to be
+// applied to e.g. outlines received from TextLayouter under usage of fontScale. This
+// includes Y-Scale, X-Scale-correction and mirrorings.
+basegfx::B2DVector getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale)
+{
+ // copy input value
+ basegfx::B2DVector aFontScale(rScale);
+
+ // correct FontHeight settings
+ if (basegfx::fTools::equalZero(aFontScale.getY()))
+ {
+ // no font height; choose one and adapt scale to get back to original scaling
+ static const double fDefaultFontScale(100.0);
+ rScale.setY(1.0 / fDefaultFontScale);
+ aFontScale.setY(fDefaultFontScale);
+ }
+ else if (aFontScale.getY() < 0.0)
+ {
+ // negative font height; invert and adapt scale to get back to original scaling
+ aFontScale.setY(-aFontScale.getY());
+ rScale.setY(-1.0);
+ }
+ else
{
- // copy input value
- basegfx::B2DVector aFontScale(rScale);
+ // positive font height; adapt scale; scaling will be part of the polygons
+ rScale.setY(1.0);
+ }
- // correct FontHeight settings
- if(basegfx::fTools::equalZero(aFontScale.getY()))
- {
- // no font height; choose one and adapt scale to get back to original scaling
- static const double fDefaultFontScale(100.0);
- rScale.setY(1.0 / fDefaultFontScale);
- aFontScale.setY(fDefaultFontScale);
- }
- else if(basegfx::fTools::less(aFontScale.getY(), 0.0))
- {
- // negative font height; invert and adapt scale to get back to original scaling
- aFontScale.setY(-aFontScale.getY());
- rScale.setY(-1.0);
- }
- else
- {
- // positive font height; adapt scale; scaling will be part of the polygons
- rScale.setY(1.0);
- }
+ // correct FontWidth settings
+ if (basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY()))
+ {
+ // no FontScale, adapt scale
+ rScale.setX(1.0);
+ }
+ else
+ {
+ // If FontScale is used, force to no FontScale to get a non-scaled VCL font.
+ // Adapt scaling in X accordingly.
+ rScale.setX(aFontScale.getX() / aFontScale.getY());
+ aFontScale.setX(aFontScale.getY());
+ }
- // correct FontWidth settings
- if(basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY()))
- {
- // no FontScale, adapt scale
- rScale.setX(1.0);
- }
- else
+ return aFontScale;
+}
+} // end of anonymous namespace
+
+void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(
+ basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const
+{
+ if (!getTextLength())
+ return;
+
+ // decompose object transformation to single values
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+
+ // if decomposition returns false, create no geometry since e.g. scaling may
+ // be zero
+ if (!(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)
+ && aScale.getX() != 0.0))
+ return;
+
+ // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
+ // be expressed as rotation by PI
+ if (aScale.getX() < 0.0 && aScale.getY() < 0.0)
+ {
+ aScale = basegfx::absolute(aScale);
+ fRotate += M_PI;
+ }
+
+ // for the TextLayouterDevice, it is necessary to have a scaling representing
+ // the font size. Since we want to extract polygons here, it is okay to
+ // work just with scaling and to ignore shear, rotation and translation,
+ // all that can be applied to the polygons later
+ const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
+
+ // prepare textlayoutdevice
+ TextLayouterDevice aTextLayouter;
+ aTextLayouter.setFontAttribute(getFontAttribute(), aFontScale.getX(), aFontScale.getY(),
+ getLocale());
+
+ // When getting outlines from stretched text (aScale.getX() != 1.0) it
+ // is necessary to inverse-scale the DXArray (if used) to not get the
+ // outlines already aligned to given, but wrong DXArray
+ if (!getDXArray().empty() && !basegfx::fTools::equal(aScale.getX(), 1.0))
+ {
+ std::vector<double> aScaledDXArray = getDXArray();
+ const double fDXArrayScale(1.0 / aScale.getX());
+
+ for (double& a : aScaledDXArray)
{
- // If FontScale is used, force to no FontScale to get a non-scaled VCL font.
- // Adapt scaling in X accordingly.
- rScale.setX(aFontScale.getX() / aFontScale.getY());
- aFontScale.setX(aFontScale.getY());
+ a *= fDXArrayScale;
}
- return aFontScale;
+ // get the text outlines
+ aTextLayouter.getTextOutlines(rTarget, getText(), getTextPosition(), getTextLength(),
+ aScaledDXArray, getKashidaArray());
+ }
+ else
+ {
+ // get the text outlines
+ aTextLayouter.getTextOutlines(rTarget, getText(), getTextPosition(), getTextLength(),
+ getDXArray(), getKashidaArray());
}
-} // end of anonymous namespace
+ // create primitives for the outlines
+ const sal_uInt32 nCount(rTarget.size());
-namespace drawinglayer::primitive2d
+ if (nCount)
+ {
+ // prepare object transformation for polygons
+ rTransformation = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+ aScale, fShearX, fRotate, aTranslate);
+ }
+}
+
+Primitive2DReference TextSimplePortionPrimitive2D::create2DDecomposition(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
{
- void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const
- {
- if(!getTextLength())
- return;
+ if (!getTextLength())
+ return nullptr;
- // decompose object transformation to single values
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
+ basegfx::B2DPolyPolygonVector aB2DPolyPolyVector;
+ basegfx::B2DHomMatrix aPolygonTransform;
- // if decomposition returns false, create no geometry since e.g. scaling may
- // be zero
- if (!(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX) && aScale.getX() != 0.0))
- return;
+ // get text outlines and their object transformation
+ getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform);
- // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
- // be expressed as rotation by PI
- if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
- {
- aScale = basegfx::absolute(aScale);
- fRotate += F_PI;
- }
+ // create primitives for the outlines
+ const sal_uInt32 nCount(aB2DPolyPolyVector.size());
- // for the TextLayouterDevice, it is necessary to have a scaling representing
- // the font size. Since we want to extract polygons here, it is okay to
- // work just with scaling and to ignore shear, rotation and translation,
- // all that can be applied to the polygons later
- const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
+ if (!nCount)
+ return nullptr;
- // prepare textlayoutdevice
- TextLayouterDevice aTextLayouter;
- aTextLayouter.setFontAttribute(
- getFontAttribute(),
- aFontScale.getX(),
- aFontScale.getY(),
- getLocale());
-
- // When getting outlines from stretched text (aScale.getX() != 1.0) it
- // is necessary to inverse-scale the DXArray (if used) to not get the
- // outlines already aligned to given, but wrong DXArray
- if(!getDXArray().empty() && !basegfx::fTools::equal(aScale.getX(), 1.0))
- {
- std::vector< double > aScaledDXArray = getDXArray();
- const double fDXArrayScale(1.0 / aScale.getX());
-
- for(double & a : aScaledDXArray)
- {
- a *= fDXArrayScale;
- }
-
- // get the text outlines
- aTextLayouter.getTextOutlines(
- rTarget,
- getText(),
- getTextPosition(),
- getTextLength(),
- aScaledDXArray);
- }
- else
- {
- // get the text outlines
- aTextLayouter.getTextOutlines(
- rTarget,
- getText(),
- getTextPosition(),
- getTextLength(),
- getDXArray());
- }
+ // alloc space for the primitives
+ Primitive2DContainer aRetval;
+ aRetval.resize(nCount);
- // create primitives for the outlines
- const sal_uInt32 nCount(rTarget.size());
+ // color-filled polypolygons
+ for (sal_uInt32 a(0); a < nCount; a++)
+ {
+ // prepare polypolygon
+ basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a];
+ rPolyPolygon.transform(aPolygonTransform);
+ aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor());
+ }
- if(nCount)
- {
- // prepare object transformation for polygons
- rTransformation = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale, fShearX, fRotate, aTranslate);
- }
- }
+ if (getFontAttribute().getOutline())
+ {
+ // decompose polygon transformation to single values
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aPolygonTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // create outline text effect with current content and replace
+ return new TextEffectPrimitive2D(std::move(aRetval), aTranslate, fRotate,
+ TextEffectStyle2D::Outline);
+ }
- void TextSimplePortionPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
- if(!getTextLength())
- return;
+ return new GroupPrimitive2D(std::move(aRetval));
+}
+
+TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D(
+ basegfx::B2DHomMatrix rNewTransform, OUString rText, sal_Int32 nTextPosition,
+ sal_Int32 nTextLength, std::vector<double>&& rDXArray, std::vector<sal_Bool>&& rKashidaArray,
+ attribute::FontAttribute aFontAttribute, css::lang::Locale aLocale,
+ const basegfx::BColor& rFontColor, const Color& rTextFillColor)
+ : maTextTransform(std::move(rNewTransform))
+ , maText(std::move(rText))
+ , mnTextPosition(nTextPosition)
+ , mnTextLength(nTextLength)
+ , maDXArray(std::move(rDXArray))
+ , maKashidaArray(std::move(rKashidaArray))
+ , maFontAttribute(std::move(aFontAttribute))
+ , maLocale(std::move(aLocale))
+ , maFontColor(rFontColor)
+ , maTextFillColor(rTextFillColor)
+{
+#if OSL_DEBUG_LEVEL > 0
+ const sal_Int32 aStringLength(getText().getLength());
+ OSL_ENSURE(aStringLength >= getTextPosition()
+ && aStringLength >= getTextPosition() + getTextLength(),
+ "TextSimplePortionPrimitive2D with text out of range (!)");
+#endif
+}
- Primitive2DContainer aRetval;
- basegfx::B2DPolyPolygonVector aB2DPolyPolyVector;
- basegfx::B2DHomMatrix aPolygonTransform;
+bool LocalesAreEqual(const css::lang::Locale& rA, const css::lang::Locale& rB)
+{
+ return (rA.Language == rB.Language && rA.Country == rB.Country && rA.Variant == rB.Variant);
+}
- // get text outlines and their object transformation
- getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform);
+bool TextSimplePortionPrimitive2D::hasTextRelief() const
+{
+ // not possible for TextSimplePortionPrimitive2D
+ return false;
+}
- // create primitives for the outlines
- const sal_uInt32 nCount(aB2DPolyPolyVector.size());
+bool TextSimplePortionPrimitive2D::hasShadow() const
+{
+ // not possible for TextSimplePortionPrimitive2D
+ return false;
+}
- if(!nCount)
- return;
+bool TextSimplePortionPrimitive2D::hasTextDecoration() const
+{
+ // not possible for TextSimplePortionPrimitive2D
+ return false;
+}
- // alloc space for the primitives
- aRetval.resize(nCount);
+bool TextSimplePortionPrimitive2D::hasOutline() const
+{
+ // not allowed with TextRelief, else defined in FontAttributes
+ return !hasTextRelief() && getFontAttribute().getOutline();
+}
- // color-filled polypolygons
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- // prepare polypolygon
- basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a];
- rPolyPolygon.transform(aPolygonTransform);
- aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor());
- }
+bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const TextSimplePortionPrimitive2D& rCompare
+ = static_cast<const TextSimplePortionPrimitive2D&>(rPrimitive);
+
+ return (getTextTransform() == rCompare.getTextTransform() && getText() == rCompare.getText()
+ && getTextPosition() == rCompare.getTextPosition()
+ && getTextLength() == rCompare.getTextLength()
+ && getDXArray() == rCompare.getDXArray()
+ && getKashidaArray() == rCompare.getKashidaArray()
+ && getFontAttribute() == rCompare.getFontAttribute()
+ && LocalesAreEqual(getLocale(), rCompare.getLocale())
+ && getFontColor() == rCompare.getFontColor()
+ && maTextFillColor == rCompare.maTextFillColor);
+ }
- if(getFontAttribute().getOutline())
- {
- // decompose polygon transformation to single values
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- aPolygonTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- // create outline text effect with current content and replace
- Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
- aRetval,
- aTranslate,
- fRotate,
- TextEffectStyle2D::Outline));
-
- aRetval = Primitive2DContainer { aNewTextEffect };
- }
+ return false;
+}
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
- }
+basegfx::B2DRange TextSimplePortionPrimitive2D::getB2DRange(
+ const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ if (maB2DRange.isEmpty() && getTextLength())
+ {
+ // get TextBoundRect as base size
+ // decompose object transformation to single values
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
- TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D(
- const basegfx::B2DHomMatrix& rNewTransform,
- const OUString& rText,
- sal_Int32 nTextPosition,
- sal_Int32 nTextLength,
- const std::vector< double >& rDXArray,
- const attribute::FontAttribute& rFontAttribute,
- const css::lang::Locale& rLocale,
- const basegfx::BColor& rFontColor,
- bool bFilled,
- long nWidthToFill,
- const Color& rTextFillColor)
- : BufferedDecompositionPrimitive2D(),
- maTextTransform(rNewTransform),
- maText(rText),
- mnTextPosition(nTextPosition),
- mnTextLength(nTextLength),
- maDXArray(rDXArray),
- maFontAttribute(rFontAttribute),
- maLocale(rLocale),
- maFontColor(rFontColor),
- mbFilled(bFilled),
- mnWidthToFill(nWidthToFill),
- maTextFillColor(rTextFillColor),
- maB2DRange()
+ if (getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX))
{
-#if OSL_DEBUG_LEVEL > 0
- const sal_Int32 aStringLength(getText().getLength());
- OSL_ENSURE(aStringLength >= getTextPosition() && aStringLength >= getTextPosition() + getTextLength(),
- "TextSimplePortionPrimitive2D with text out of range (!)");
-#endif
- }
+ // for the TextLayouterDevice, it is necessary to have a scaling representing
+ // the font size. Since we want to extract polygons here, it is okay to
+ // work just with scaling and to ignore shear, rotation and translation,
+ // all that can be applied to the polygons later
+ const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
- bool LocalesAreEqual(const css::lang::Locale& rA, const css::lang::Locale& rB)
- {
- return (rA.Language == rB.Language
- && rA.Country == rB.Country
- && rA.Variant == rB.Variant);
- }
+ // prepare textlayoutdevice
+ TextLayouterDevice aTextLayouter;
+ aTextLayouter.setFontAttribute(getFontAttribute(), aFontScale.getX(), aFontScale.getY(),
+ getLocale());
- bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ // get basic text range
+ basegfx::B2DRange aNewRange(
+ aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()));
+
+ // #i104432#, #i102556# take empty results into account
+ if (!aNewRange.isEmpty())
{
- const TextSimplePortionPrimitive2D& rCompare = static_cast<const TextSimplePortionPrimitive2D&>(rPrimitive);
-
- return (getTextTransform() == rCompare.getTextTransform()
- && getText() == rCompare.getText()
- && getTextPosition() == rCompare.getTextPosition()
- && getTextLength() == rCompare.getTextLength()
- && getDXArray() == rCompare.getDXArray()
- && getFontAttribute() == rCompare.getFontAttribute()
- && LocalesAreEqual(getLocale(), rCompare.getLocale())
- && getFontColor() == rCompare.getFontColor()
- && mbFilled == rCompare.mbFilled
- && mnWidthToFill == rCompare.mnWidthToFill
- && maTextFillColor == rCompare.maTextFillColor);
- }
+ // prepare object transformation for range
+ const basegfx::B2DHomMatrix aRangeTransformation(
+ basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+ aScale, fShearX, fRotate, aTranslate));
- return false;
- }
+ // apply range transformation to it
+ aNewRange.transform(aRangeTransformation);
- basegfx::B2DRange TextSimplePortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
- if(maB2DRange.isEmpty() && getTextLength())
- {
- // get TextBoundRect as base size
- // decompose object transformation to single values
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
-
- if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX))
- {
- // for the TextLayouterDevice, it is necessary to have a scaling representing
- // the font size. Since we want to extract polygons here, it is okay to
- // work just with scaling and to ignore shear, rotation and translation,
- // all that can be applied to the polygons later
- const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
-
- // prepare textlayoutdevice
- TextLayouterDevice aTextLayouter;
- aTextLayouter.setFontAttribute(
- getFontAttribute(),
- aFontScale.getX(),
- aFontScale.getY(),
- getLocale());
-
- // get basic text range
- basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()));
-
- // #i104432#, #i102556# take empty results into account
- if(!aNewRange.isEmpty())
- {
- // prepare object transformation for range
- const basegfx::B2DHomMatrix aRangeTransformation(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale, fShearX, fRotate, aTranslate));
-
- // apply range transformation to it
- aNewRange.transform(aRangeTransformation);
-
- // assign to buffered value
- const_cast< TextSimplePortionPrimitive2D* >(this)->maB2DRange = aNewRange;
- }
- }
+ // assign to buffered value
+ const_cast<TextSimplePortionPrimitive2D*>(this)->maB2DRange = aNewRange;
}
-
- return maB2DRange;
}
+ }
- // provide unique ID
- ImplPrimitive2DIDBlock(TextSimplePortionPrimitive2D, PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D)
+ return maB2DRange;
+}
+
+void TextSimplePortionPrimitive2D::createTextLayouter(TextLayouterDevice& rTextLayouter) const
+{
+ // decompose primitive-local matrix to get local font scaling
+ const basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(getTextTransform());
+
+ // create a TextLayouter to access encapsulated VCL Text/Font related tooling
+ rTextLayouter.setFontAttribute(getFontAttribute(), aDecTrans.getScale().getX(),
+ aDecTrans.getScale().getY(), getLocale());
+
+ if (getFontAttribute().getRTL())
+ {
+ vcl::text::ComplexTextLayoutFlags nRTLLayoutMode(
+ rTextLayouter.getLayoutMode() & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+ nRTLLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl
+ | vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
+ rTextLayouter.setLayoutMode(nRTLLayoutMode);
+ }
+ else
+ {
+ // tdf#101686: This is LTR text, but the output device may have RTL state.
+ vcl::text::ComplexTextLayoutFlags nLTRLayoutMode(rTextLayouter.getLayoutMode());
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiRtl;
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong;
+ rTextLayouter.setLayoutMode(nLTRLayoutMode);
+ }
+}
+
+std::unique_ptr<SalLayout>
+TextSimplePortionPrimitive2D::createSalLayout(const TextLayouterDevice& rTextLayouter) const
+{
+ // As mentioned above we can act in the
+ // Text's local coordinate system without transformation at all
+ const ::std::vector<double>& rDXArray(getDXArray());
+
+ // create SalLayout. No need for a position, as mentioned text can work
+ // without transformations, so start point is always 0,0
+ return rTextLayouter.getSalLayout(getText(), getTextPosition(), getTextLength(),
+ basegfx::B2DPoint(0.0, 0.0), rDXArray, getKashidaArray());
+}
+
+// provide unique ID
+sal_uInt32 TextSimplePortionPrimitive2D::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D;
+}
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx b/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
index 23b0c5ffe40c..497f8c2dbe40 100644
--- a/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
@@ -24,19 +24,20 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/attribute/lineattribute.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <osl/diagnose.h>
#include <rtl/ustrbuf.hxx>
+#include <utility>
namespace drawinglayer::primitive2d
{
BaseTextStrikeoutPrimitive2D::BaseTextStrikeoutPrimitive2D(
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
double fWidth,
const basegfx::BColor& rFontColor)
- : BufferedDecompositionPrimitive2D(),
- maObjectTransformation(rObjectTransformation),
+ : maObjectTransformation(std::move(aObjectTransformation)),
mfWidth(fWidth),
maFontColor(rFontColor)
{
@@ -57,7 +58,7 @@ namespace drawinglayer::primitive2d
}
- void TextCharacterStrikeoutPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference TextCharacterStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
// strikeout with character
const OUString aSingleCharString(getStrikeoutChar());
@@ -89,16 +90,17 @@ namespace drawinglayer::primitive2d
}
auto len = aStrikeoutString.getLength();
- rContainer.push_back(
+ return
new TextSimplePortionPrimitive2D(
getObjectTransformation(),
aStrikeoutString.makeStringAndClear(),
0,
len,
- aDXArray,
+ std::move(aDXArray),
+ {},
getFontAttribute(),
getLocale(),
- getFontColor()));
+ getFontColor());
}
TextCharacterStrikeoutPrimitive2D::TextCharacterStrikeoutPrimitive2D(
@@ -106,12 +108,12 @@ namespace drawinglayer::primitive2d
double fWidth,
const basegfx::BColor& rFontColor,
sal_Unicode aStrikeoutChar,
- const attribute::FontAttribute& rFontAttribute,
- const css::lang::Locale& rLocale)
+ attribute::FontAttribute aFontAttribute,
+ css::lang::Locale aLocale)
: BaseTextStrikeoutPrimitive2D(rObjectTransformation, fWidth, rFontColor),
maStrikeoutChar(aStrikeoutChar),
- maFontAttribute(rFontAttribute),
- maLocale(rLocale)
+ maFontAttribute(std::move(aFontAttribute)),
+ maLocale(std::move(aLocale))
{
}
@@ -130,11 +132,12 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextCharacterStrikeoutPrimitive2D, PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D)
-
-
+ sal_uInt32 TextCharacterStrikeoutPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D;
+ }
- void TextGeometryStrikeoutPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference TextGeometryStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
OSL_ENSURE(TEXT_STRIKEOUT_SLASH != getTextStrikeout() && TEXT_STRIKEOUT_X != getTextStrikeout(),
"Wrong TEXT_STRIKEOUT type; a TextCharacterStrikeoutPrimitive2D should be used (!)");
@@ -188,8 +191,7 @@ namespace drawinglayer::primitive2d
// add primitive
const attribute::LineAttribute aLineAttribute(getFontColor(), fStrikeoutHeight, basegfx::B2DLineJoin::NONE);
- Primitive2DContainer xRetval(1);
- xRetval[0] = new PolygonStrokePrimitive2D(aStrikeoutLine, aLineAttribute);
+ Primitive2DReference xRetval = new PolygonStrokePrimitive2D(std::move(aStrikeoutLine), aLineAttribute);
if(bDoubleLine)
{
@@ -209,14 +211,14 @@ namespace drawinglayer::primitive2d
aTransform.rotate(fRotate);
aTransform.translate(aTranslate.getX(), aTranslate.getY());
- // add transform primitive
- xRetval.push_back(
- new TransformPrimitive2D(
- aTransform,
- xRetval));
+ // add original and transform primitive to a GroupPrimitive2D
+ xRetval = new GroupPrimitive2D({
+ xRetval, new TransformPrimitive2D(
+ aTransform,
+ Primitive2DContainer{xRetval}) });
}
- rContainer.insert(rContainer.end(), xRetval.begin(), xRetval.end());
+ return xRetval;
}
TextGeometryStrikeoutPrimitive2D::TextGeometryStrikeoutPrimitive2D(
@@ -248,7 +250,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TextGeometryStrikeoutPrimitive2D, PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D)
+ sal_uInt32 TextGeometryStrikeoutPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/transformprimitive2d.cxx b/drawinglayer/source/primitive2d/transformprimitive2d.cxx
index 4ac2ada55027..8c36fa9a73b9 100644
--- a/drawinglayer/source/primitive2d/transformprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/transformprimitive2d.cxx
@@ -19,6 +19,8 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/Tools.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -27,20 +29,29 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
TransformPrimitive2D::TransformPrimitive2D(
- const basegfx::B2DHomMatrix& rTransformation,
- const Primitive2DContainer& rChildren)
- : GroupPrimitive2D(rChildren),
- maTransformation(rTransformation)
+ basegfx::B2DHomMatrix aTransformation,
+ Primitive2DContainer&& aChildren)
+ : maTransformation(std::move(aTransformation)),
+ mxChildren(new GroupPrimitive2D(std::move(aChildren)))
+ {
+ }
+
+ TransformPrimitive2D::TransformPrimitive2D(
+ basegfx::B2DHomMatrix aTransformation,
+ GroupPrimitive2D& rChildren)
+ : maTransformation(std::move(aTransformation)),
+ mxChildren(&rChildren)
{
}
bool TransformPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(GroupPrimitive2D::operator==(rPrimitive))
+ if(BasePrimitive2D::operator==(rPrimitive))
{
const TransformPrimitive2D& rCompare = static_cast< const TransformPrimitive2D& >(rPrimitive);
- return (getTransformation() == rCompare.getTransformation());
+ return maTransformation == rCompare.maTransformation
+ && arePrimitive2DReferencesEqual(mxChildren, rCompare.mxChildren);
}
return false;
@@ -54,7 +65,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TransformPrimitive2D, PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D)
+ sal_uInt32 TransformPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/transparenceprimitive2d.cxx b/drawinglayer/source/primitive2d/transparenceprimitive2d.cxx
index da157d353209..8a86b1b295f4 100644
--- a/drawinglayer/source/primitive2d/transparenceprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/transparenceprimitive2d.cxx
@@ -27,10 +27,10 @@ using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
TransparencePrimitive2D::TransparencePrimitive2D(
- const Primitive2DContainer& rChildren,
- const Primitive2DContainer& rTransparence)
- : GroupPrimitive2D(rChildren),
- maTransparence(rTransparence)
+ Primitive2DContainer&& aChildren,
+ Primitive2DContainer&& aTransparence)
+ : GroupPrimitive2D(std::move(aChildren)),
+ maTransparence(std::move(aTransparence))
{
}
@@ -47,7 +47,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(TransparencePrimitive2D, PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D)
+ sal_uInt32 TransparencePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d.cxx b/drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d.cxx
index 70cfe675046e..5ecd367b1c95 100644
--- a/drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/unifiedtransparenceprimitive2d.cxx
@@ -21,21 +21,18 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/color/bcolor.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
-
-
-using namespace com::sun::star;
namespace drawinglayer::primitive2d
{
UnifiedTransparencePrimitive2D::UnifiedTransparencePrimitive2D(
- const Primitive2DContainer& rChildren,
+ Primitive2DContainer&& aChildren,
double fTransparence)
- : GroupPrimitive2D(rChildren),
+ : GroupPrimitive2D(std::move(aChildren)),
mfTransparence(fTransparence)
{
}
@@ -85,15 +82,15 @@ namespace drawinglayer::primitive2d
// I will take the last one here. The small overhead of two primitives will only be
// used when UnifiedTransparencePrimitive2D is not handled directly.
const basegfx::B2DRange aPolygonRange(getChildren().getB2DRange(rViewInformation));
- const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(aPolygonRange));
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(aPolygonRange));
const basegfx::BColor aGray(getTransparence(), getTransparence(), getTransparence());
Primitive2DContainer aTransparenceContent(2);
- aTransparenceContent[0] = Primitive2DReference(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), aGray));
- aTransparenceContent[1] = Primitive2DReference(new PolygonHairlinePrimitive2D(aPolygon, aGray));
+ aTransparenceContent[0] = new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), aGray);
+ aTransparenceContent[1] = new PolygonHairlinePrimitive2D(std::move(aPolygon), aGray);
// create sub-transparence group with a gray-colored rectangular fill polygon
- rVisitor.append(new TransparencePrimitive2D(getChildren(), aTransparenceContent));
+ rVisitor.visit(new TransparencePrimitive2D(Primitive2DContainer(getChildren()), std::move(aTransparenceContent)));
}
else
{
@@ -102,7 +99,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(UnifiedTransparencePrimitive2D, PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D)
+ sal_uInt32 UnifiedTransparencePrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/wallpaperprimitive2d.cxx b/drawinglayer/source/primitive2d/wallpaperprimitive2d.cxx
index d8926824f65a..ba4f06341f4a 100644
--- a/drawinglayer/source/primitive2d/wallpaperprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/wallpaperprimitive2d.cxx
@@ -31,199 +31,194 @@
namespace drawinglayer::primitive2d
{
- void WallpaperBitmapPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference WallpaperBitmapPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
+
+ if(getLocalObjectRange().isEmpty() || getBitmap().IsEmpty())
+ return nullptr;
+
Primitive2DReference aRetval;
- if(!getLocalObjectRange().isEmpty() && !getBitmapEx().IsEmpty())
- {
- // get bitmap PIXEL size
- const Size& rPixelSize = getBitmapEx().GetSizePixel();
+ // get bitmap PIXEL size
+ const Size aPixelSize = getBitmap().GetSizePixel();
- if(rPixelSize.Width() > 0 && rPixelSize.Height() > 0)
+ if(aPixelSize.Width() <= 0 || aPixelSize.Height() <= 0)
+ return nullptr;
+
+ if(WallpaperStyle::Scale == getWallpaperStyle())
+ {
+ // shortcut for scale; use simple BitmapPrimitive2D
+ basegfx::B2DHomMatrix aObjectTransform;
+
+ aObjectTransform.set(0, 0, getLocalObjectRange().getWidth());
+ aObjectTransform.set(1, 1, getLocalObjectRange().getHeight());
+ aObjectTransform.set(0, 2, getLocalObjectRange().getMinX());
+ aObjectTransform.set(1, 2, getLocalObjectRange().getMinY());
+
+ aRetval.set(
+ new BitmapPrimitive2D(
+ getBitmap(),
+ aObjectTransform));
+ }
+ else
+ {
+ // transform to logic size
+ basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation());
+ aInverseViewTransformation.invert();
+ basegfx::B2DVector aLogicSize(aPixelSize.Width(), aPixelSize.Height());
+ aLogicSize = aInverseViewTransformation * aLogicSize;
+
+ // apply layout
+ basegfx::B2DPoint aTargetTopLeft(getLocalObjectRange().getMinimum());
+ bool bUseTargetTopLeft(true);
+ bool bNeedsClipping(false);
+
+ switch(getWallpaperStyle())
{
- if(WallpaperStyle::Scale == getWallpaperStyle())
+ default: //case WallpaperStyle::Tile :, also WallpaperStyle::NONE and WallpaperStyle::ApplicationGradient
+ {
+ bUseTargetTopLeft = false;
+ break;
+ }
+ case WallpaperStyle::Scale :
+ {
+ // handled by shortcut above
+ break;
+ }
+ case WallpaperStyle::TopLeft :
+ {
+ // nothing to do
+ break;
+ }
+ case WallpaperStyle::Top :
+ {
+ const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
+ aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
+ break;
+ }
+ case WallpaperStyle::TopRight :
+ {
+ aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
+ break;
+ }
+ case WallpaperStyle::Left :
+ {
+ const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
+ aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
+ break;
+ }
+ case WallpaperStyle::Center :
+ {
+ const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
+ aTargetTopLeft = aCenter - (aLogicSize * 0.5);
+ break;
+ }
+ case WallpaperStyle::Right :
{
- // shortcut for scale; use simple BitmapPrimitive2D
- basegfx::B2DHomMatrix aObjectTransform;
+ const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
+ aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
+ aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
+ break;
+ }
+ case WallpaperStyle::BottomLeft :
+ {
+ aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
+ break;
+ }
+ case WallpaperStyle::Bottom :
+ {
+ const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
+ aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
+ aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
+ break;
+ }
+ case WallpaperStyle::BottomRight :
+ {
+ aTargetTopLeft = getLocalObjectRange().getMaximum() - aLogicSize;
+ break;
+ }
+ }
- aObjectTransform.set(0, 0, getLocalObjectRange().getWidth());
- aObjectTransform.set(1, 1, getLocalObjectRange().getHeight());
- aObjectTransform.set(0, 2, getLocalObjectRange().getMinX());
- aObjectTransform.set(1, 2, getLocalObjectRange().getMinY());
+ if(bUseTargetTopLeft)
+ {
+ // fill target range
+ const basegfx::B2DRange aTargetRange(aTargetTopLeft, aTargetTopLeft + aLogicSize);
- Primitive2DReference xReference(
- new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()),
- aObjectTransform));
+ // create aligned, single BitmapPrimitive2D
+ basegfx::B2DHomMatrix aObjectTransform;
- aRetval = xReference;
- }
- else
+ aObjectTransform.set(0, 0, aTargetRange.getWidth());
+ aObjectTransform.set(1, 1, aTargetRange.getHeight());
+ aObjectTransform.set(0, 2, aTargetRange.getMinX());
+ aObjectTransform.set(1, 2, aTargetRange.getMinY());
+
+ aRetval.set(
+ new BitmapPrimitive2D(
+ getBitmap(),
+ aObjectTransform));
+
+ // clip when not completely inside object range
+ bNeedsClipping = !getLocalObjectRange().isInside(aTargetRange);
+ }
+ else
+ {
+ // WallpaperStyle::Tile, WallpaperStyle::NONE, WallpaperStyle::ApplicationGradient
+ // convert to relative positions
+ const basegfx::B2DVector aRelativeSize(
+ aLogicSize.getX() / (getLocalObjectRange().getWidth() ? getLocalObjectRange().getWidth() : 1.0),
+ aLogicSize.getY() / (getLocalObjectRange().getHeight() ? getLocalObjectRange().getHeight() : 1.0));
+ basegfx::B2DPoint aRelativeTopLeft(0.0, 0.0);
+
+ if(WallpaperStyle::Tile != getWallpaperStyle())
{
- // transform to logic size
- basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation());
- aInverseViewTransformation.invert();
- basegfx::B2DVector aLogicSize(rPixelSize.Width(), rPixelSize.Height());
- aLogicSize = aInverseViewTransformation * aLogicSize;
-
- // apply layout
- basegfx::B2DPoint aTargetTopLeft(getLocalObjectRange().getMinimum());
- bool bUseTargetTopLeft(true);
- bool bNeedsClipping(false);
-
- switch(getWallpaperStyle())
- {
- default: //case WallpaperStyle::Tile :, also WallpaperStyle::NONE and WallpaperStyle::ApplicationGradient
- {
- bUseTargetTopLeft = false;
- break;
- }
- case WallpaperStyle::Scale :
- {
- // handled by shortcut above
- break;
- }
- case WallpaperStyle::TopLeft :
- {
- // nothing to do
- break;
- }
- case WallpaperStyle::Top :
- {
- const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
- aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
- break;
- }
- case WallpaperStyle::TopRight :
- {
- aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
- break;
- }
- case WallpaperStyle::Left :
- {
- const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
- aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
- break;
- }
- case WallpaperStyle::Center :
- {
- const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
- aTargetTopLeft = aCenter - (aLogicSize * 0.5);
- break;
- }
- case WallpaperStyle::Right :
- {
- const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
- aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
- aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
- break;
- }
- case WallpaperStyle::BottomLeft :
- {
- aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
- break;
- }
- case WallpaperStyle::Bottom :
- {
- const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
- aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
- aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
- break;
- }
- case WallpaperStyle::BottomRight :
- {
- aTargetTopLeft = getLocalObjectRange().getMaximum() - aLogicSize;
- break;
- }
- }
-
- if(bUseTargetTopLeft)
- {
- // fill target range
- const basegfx::B2DRange aTargetRange(aTargetTopLeft, aTargetTopLeft + aLogicSize);
-
- // create aligned, single BitmapPrimitive2D
- basegfx::B2DHomMatrix aObjectTransform;
-
- aObjectTransform.set(0, 0, aTargetRange.getWidth());
- aObjectTransform.set(1, 1, aTargetRange.getHeight());
- aObjectTransform.set(0, 2, aTargetRange.getMinX());
- aObjectTransform.set(1, 2, aTargetRange.getMinY());
-
- Primitive2DReference xReference(
- new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()),
- aObjectTransform));
- aRetval = xReference;
-
- // clip when not completely inside object range
- bNeedsClipping = !getLocalObjectRange().isInside(aTargetRange);
- }
- else
- {
- // WallpaperStyle::Tile, WallpaperStyle::NONE, WallpaperStyle::ApplicationGradient
- // convert to relative positions
- const basegfx::B2DVector aRelativeSize(
- aLogicSize.getX() / (getLocalObjectRange().getWidth() ? getLocalObjectRange().getWidth() : 1.0),
- aLogicSize.getY() / (getLocalObjectRange().getHeight() ? getLocalObjectRange().getHeight() : 1.0));
- basegfx::B2DPoint aRelativeTopLeft(0.0, 0.0);
-
- if(WallpaperStyle::Tile != getWallpaperStyle())
- {
- aRelativeTopLeft.setX(0.5 - aRelativeSize.getX());
- aRelativeTopLeft.setY(0.5 - aRelativeSize.getY());
- }
-
- // prepare FillGraphicAttribute
- const attribute::FillGraphicAttribute aFillGraphicAttribute(
- Graphic(getBitmapEx()),
- basegfx::B2DRange(aRelativeTopLeft, aRelativeTopLeft+ aRelativeSize),
- true);
-
- // create ObjectTransform
- const basegfx::B2DHomMatrix aObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- getLocalObjectRange().getRange(),
- getLocalObjectRange().getMinimum()));
-
- // create FillBitmapPrimitive
- const drawinglayer::primitive2d::Primitive2DReference xFillBitmap(
- new drawinglayer::primitive2d::FillGraphicPrimitive2D(
- aObjectTransform,
- aFillGraphicAttribute));
- aRetval = xFillBitmap;
-
- // always embed tiled fill to clipping
- bNeedsClipping = true;
- }
-
- if(bNeedsClipping)
- {
- // embed to clipping; this is necessary for tiled fills
- const basegfx::B2DPolyPolygon aPolyPolygon(
- basegfx::utils::createPolygonFromRect(getLocalObjectRange()));
- const drawinglayer::primitive2d::Primitive2DReference xClippedFill(
- new drawinglayer::primitive2d::MaskPrimitive2D(
- aPolyPolygon,
- { aRetval }));
- aRetval = xClippedFill;
- }
+ aRelativeTopLeft.setX(0.5 - aRelativeSize.getX());
+ aRelativeTopLeft.setY(0.5 - aRelativeSize.getY());
}
+
+ // prepare FillGraphicAttribute
+ const attribute::FillGraphicAttribute aFillGraphicAttribute(
+ Graphic(getBitmap()),
+ basegfx::B2DRange(aRelativeTopLeft, aRelativeTopLeft+ aRelativeSize),
+ true);
+
+ // create ObjectTransform
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ getLocalObjectRange().getRange(),
+ getLocalObjectRange().getMinimum()));
+
+ // create FillBitmapPrimitive
+ aRetval.set(
+ new drawinglayer::primitive2d::FillGraphicPrimitive2D(
+ aObjectTransform,
+ aFillGraphicAttribute));
+
+ // always embed tiled fill to clipping
+ bNeedsClipping = true;
+ }
+
+ if(bNeedsClipping)
+ {
+ // embed to clipping; this is necessary for tiled fills
+ basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::utils::createPolygonFromRect(getLocalObjectRange()));
+ const drawinglayer::primitive2d::Primitive2DReference xClippedFill(
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ std::move(aPolyPolygon),
+ { aRetval }));
+ aRetval = xClippedFill;
}
}
- if (aRetval.is())
- rContainer.push_back(aRetval);
+ return aRetval;
}
WallpaperBitmapPrimitive2D::WallpaperBitmapPrimitive2D(
const basegfx::B2DRange& rObjectRange,
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
WallpaperStyle eWallpaperStyle)
- : ViewTransformationDependentPrimitive2D(),
- maObjectRange(rObjectRange),
- maBitmapEx(rBitmapEx),
+ : maObjectRange(rObjectRange),
+ maBitmap(rBitmap),
meWallpaperStyle(eWallpaperStyle)
{
}
@@ -235,7 +230,7 @@ namespace drawinglayer::primitive2d
const WallpaperBitmapPrimitive2D& rCompare = static_cast<const WallpaperBitmapPrimitive2D&>(rPrimitive);
return (getLocalObjectRange() == rCompare.getLocalObjectRange()
- && getBitmapEx() == rCompare.getBitmapEx()
+ && getBitmap() == rCompare.getBitmap()
&& getWallpaperStyle() == rCompare.getWallpaperStyle());
}
@@ -248,7 +243,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(WallpaperBitmapPrimitive2D, PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D)
+ sal_uInt32 WallpaperBitmapPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
index f0eb918339bd..1efc7442ba73 100644
--- a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
@@ -19,61 +19,115 @@
#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <utility>
namespace drawinglayer::primitive2d
{
- void WrongSpellPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference WrongSpellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
- // ATM this decompose is view-independent, what the original VCL-Display is not. To mimic
- // the old behaviour here if wanted it is necessary to add get2DDecomposition and implement
- // it similar to the usage in e.g. HelplinePrimitive2D. Remembering the ViewTransformation
- // should be enough then.
- // The view-independent wavelines work well (if You ask me). Maybe the old VCL-Behaviour is only
- // in place because it was not possible/too expensive at that time to scale the wavelines with the
- // view...
- // With the VCL-PixelRenderer this will not even be used since it implements WrongSpellPrimitive2D
- // directly and mimics the old VCL-Display there. If You implemented a new renderer without
- // direct WrongSpellPrimitive2D support, You may want to do the described change here.
+ // This *was* a view-independent primitive before (see before this commit),
+ // but was never really used, but handled in various processors anyways.
+ // Since the current VCL primitive renderer and it's functions used in
+ // VCL do render this always in one discrete pixel size I decided to
+ // adapt this primitive to do that, too, but - due to being a primitive -
+ // with the correct invalidate/hit-ranges etc.
+ // I use here DiscreteMetricDependentPrimitive2D which already implements
+ // buffering and providing the discrete size using 'getDiscreteUnit()' plus
+ // the needed updates to buffering, what makes the rest simple.
+ // NOTE: If one day the (in my opinion) also good looking view-independent
+ // version should be needed again, just revert this change
+ if (basegfx::fTools::lessOrEqual(getStop(), getStart()))
+ {
+ // stop smaller or equal to start, done
+ return nullptr;
+ }
// get the font height (part of scale), so decompose the matrix
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
getTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
+ constexpr double constMinimumFontHeight(5.0);
+ if (aScale.getY() / getDiscreteUnit() < constMinimumFontHeight)
+ {
+ // font height smaller constMinimumFontHeight pixels -> decompose to empty
+ return nullptr;
+ }
+
// calculate distances based on a static default (to allow testing in debugger)
static const double fDefaultDistance(0.03);
const double fFontHeight(aScale.getY());
const double fUnderlineDistance(fFontHeight * fDefaultDistance);
- const double fWaveWidth(2.0 * fUnderlineDistance);
// the Y-distance needs to be relative to FontHeight since the points get
// transformed with the transformation containing that scale already.
const double fRelativeUnderlineDistance(basegfx::fTools::equalZero(aScale.getY()) ? 0.0 : fUnderlineDistance / aScale.getY());
- basegfx::B2DPoint aStart(getStart(), fRelativeUnderlineDistance);
- basegfx::B2DPoint aStop(getStop(), fRelativeUnderlineDistance);
- basegfx::B2DPolygon aPolygon;
- aPolygon.append(getTransformation() * aStart);
- aPolygon.append(getTransformation() * aStop);
+ // get start/stop positions and WaveLength, base all calculations for discrete
+ // waveline on these initial values
+ basegfx::B2DPoint aStart(getTransformation() * basegfx::B2DPoint(getStart(), fRelativeUnderlineDistance));
+ const basegfx::B2DPoint aStop(getTransformation() * basegfx::B2DPoint(getStop(), fRelativeUnderlineDistance));
+ const double fWaveLength(getDiscreteUnit() * 8);
+
+ // get pre-calculated vector and controlPoint for one wave segment
+ basegfx::B2DVector aVector(aStop - aStart);
+ double fLength(aVector.getLength());
+ aVector.normalize();
+ basegfx::B2DVector aControl(basegfx::getPerpendicular(aVector));
+ aVector *= fWaveLength;
+ aControl = aControl * (fWaveLength * 0.5) + aVector * 0.5;
+
+ // create geometry
+ basegfx::B2DPolygon aWave;
+ aWave.append(aStart);
+
+ while (fLength > fWaveLength)
+ {
+ // one WaveSegment per WaveLength
+ basegfx::B2DPoint aNew(aStart + aVector);
+ aWave.appendBezierSegment(
+ aStart + aControl,
+ aNew - aControl,
+ aNew);
+ aStart = aNew;
+ fLength -= fWaveLength;
+ }
- // prepare line attribute
- const attribute::LineAttribute aLineAttribute(getColor());
+ if (fLength > fWaveLength * 0.2)
+ {
+ // if rest is more than 20% of WaveLength, create
+ // remaining snippet and add it
+ basegfx::B2DPoint aNew(aStart + aVector);
+ basegfx::B2DCubicBezier aRest(
+ aStart,
+ aStart + aControl,
+ aNew - aControl,
+ aNew);
+ aRest = aRest.snippet(0.0, fLength/fWaveLength);
+ aWave.appendBezierSegment(
+ aRest.getControlPointA(),
+ aRest.getControlPointB(),
+ aRest.getEndPoint());
+ }
- // create the waveline primitive
- rContainer.push_back(new PolygonWavePrimitive2D(aPolygon, aLineAttribute, fWaveWidth, 0.5 * fWaveWidth));
+ // create & return primitive
+ return new PolygonHairlinePrimitive2D(
+ std::move(aWave),
+ getColor());
}
WrongSpellPrimitive2D::WrongSpellPrimitive2D(
- const basegfx::B2DHomMatrix& rTransformation,
+ basegfx::B2DHomMatrix aTransformation,
double fStart,
double fStop,
const basegfx::BColor& rColor)
- : BufferedDecompositionPrimitive2D(),
- maTransformation(rTransformation),
+ : DiscreteMetricDependentPrimitive2D(),
+ maTransformation(std::move(aTransformation)),
mfStart(fStart),
mfStop(fStop),
maColor(rColor)
@@ -82,7 +136,7 @@ namespace drawinglayer::primitive2d
bool WrongSpellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
{
const WrongSpellPrimitive2D& rCompare = static_cast<const WrongSpellPrimitive2D&>(rPrimitive);
@@ -96,7 +150,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(WrongSpellPrimitive2D, PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D)
+ sal_uInt32 WrongSpellPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D;
+ }
} // end of namespace
diff --git a/drawinglayer/source/primitive3d/Tools.cxx b/drawinglayer/source/primitive3d/Tools.cxx
new file mode 100644
index 000000000000..23ecc0851f40
--- /dev/null
+++ b/drawinglayer/source/primitive3d/Tools.cxx
@@ -0,0 +1,67 @@
+/* -*- 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/.
+ *
+ */
+
+#include <drawinglayer/primitive3d/Tools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+using namespace css;
+
+namespace drawinglayer::primitive3d
+{
+OUString idToString(sal_uInt32 nId)
+{
+ switch (nId)
+ {
+ case PRIMITIVE3D_ID_GROUPPRIMITIVE3D:
+ return u"GROUPPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D:
+ return u"HATCHTEXTUREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D:
+ return u"MODIFIEDCOLORPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D:
+ return u"POLYGONHAIRLINEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_POLYGONSTROKEPRIMITIVE3D:
+ return u"POLYGONSTROKEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_POLYGONTUBEPRIMITIVE3D:
+ return u"POLYGONTUBEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D:
+ return u"POLYPOLYGONMATERIALPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SDRCUBEPRIMITIVE3D:
+ return u"SDRCUBEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D:
+ return u"SDREXTRUDEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D:
+ return u"SDRLATHEPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SDRPOLYPOLYGONPRIMITIVE3D:
+ return u"SDRPOLYPOLYGONPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SDRSPHEREPRIMITIVE3D:
+ return u"SDRSPHEREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_SHADOWPRIMITIVE3D:
+ return u"SHADOWPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D:
+ return u"UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D:
+ return u"GRADIENTTEXTUREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D:
+ return u"BITMAPTEXTUREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_TRANSPARENCETEXTUREPRIMITIVE3D:
+ return u"TRANSPARENCETEXTUREPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D:
+ return u"TRANSFORMPRIMITIVE3D"_ustr;
+ case PRIMITIVE3D_ID_HIDDENGEOMETRYPRIMITIVE3D:
+ return u"HIDDENGEOMETRYPRIMITIVE3D"_ustr;
+ default:
+ return OUString::number((nId >> 16) & 0xFF) + "|" + OUString::number(nId & 0xFF);
+ }
+}
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive3d/baseprimitive3d.cxx b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
index 4a69c7cc0a73..c2c8cc9f7e0f 100644
--- a/drawinglayer/source/primitive3d/baseprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
@@ -29,7 +29,6 @@ using namespace com::sun::star;
namespace drawinglayer::primitive3d
{
BasePrimitive3D::BasePrimitive3D()
- : BasePrimitive3DImplBase(m_aMutex)
{
}
@@ -71,14 +70,12 @@ namespace drawinglayer::primitive3d
}
BufferedDecompositionPrimitive3D::BufferedDecompositionPrimitive3D()
- : BasePrimitive3D(),
- maBuffered3DDecomposition()
{
}
Primitive3DContainer BufferedDecompositionPrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
if(getBuffered3DDecomposition().empty())
{
@@ -98,20 +95,8 @@ namespace drawinglayer::primitive3d
if(rCandidate.is())
{
- // try to get C++ implementation base
- const BasePrimitive3D* pCandidate(dynamic_cast< BasePrimitive3D* >(rCandidate.get()));
-
- if(pCandidate)
- {
- // use it if possible
- aRetval.expand(pCandidate->getB3DRange(aViewInformation));
- }
- else
- {
- // use UNO API call instead
- const uno::Sequence< beans::PropertyValue >& rViewParameters(aViewInformation.getViewInformationSequence());
- aRetval.expand(basegfx::unotools::b3DRectangleFromRealRectangle3D(rCandidate->getRange(rViewParameters)));
- }
+ const BasePrimitive3D* pCandidate(static_cast< BasePrimitive3D* >(rCandidate.get()));
+ aRetval.expand(pCandidate->getB3DRange(aViewInformation));
}
return aRetval;
@@ -149,13 +134,8 @@ namespace drawinglayer::primitive3d
return true;
}
- const BasePrimitive3D* pA(dynamic_cast< const BasePrimitive3D* >(rxA.get()));
- const BasePrimitive3D* pB(dynamic_cast< const BasePrimitive3D* >(rxB.get()));
-
- if(!pA || !pB)
- {
- return false;
- }
+ const BasePrimitive3D* pA(static_cast< const BasePrimitive3D* >(rxA.get()));
+ const BasePrimitive3D* pB(static_cast< const BasePrimitive3D* >(rxB.get()));
return pA->operator==(*pB);
}
diff --git a/drawinglayer/source/primitive3d/groupprimitive3d.cxx b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
index 7a6254b00e72..c50e29f04d8c 100644
--- a/drawinglayer/source/primitive3d/groupprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
@@ -19,20 +19,17 @@
#include <drawinglayer/primitive3d/groupprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
{
- GroupPrimitive3D::GroupPrimitive3D( const Primitive3DContainer& rChildren )
- : BasePrimitive3D(),
- maChildren(rChildren)
+ GroupPrimitive3D::GroupPrimitive3D( Primitive3DContainer aChildren )
+ : maChildren(std::move(aChildren))
{
}
- /** The compare opertator uses the Sequence::==operator, so only checking if
+ /** The compare operator uses the Sequence::==operator, so only checking if
the references are equal. All non-equal references are interpreted as
non-equal.
*/
diff --git a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
index 2ea280b68be1..42e2f9e75b71 100644
--- a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
@@ -29,6 +29,7 @@
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -49,215 +50,206 @@ namespace drawinglayer::primitive3d
for(size_t a(0); a < nSourceCount; a++)
{
// get reference
- const Primitive3DReference xReference(aSource[a]);
+ const Primitive3DReference& xReference(aSource[a]);
if(xReference.is())
{
- // try to cast to BasePrimitive2D implementation
- const BasePrimitive3D* pBasePrimitive = dynamic_cast< const BasePrimitive3D* >(xReference.get());
+ const BasePrimitive3D* pBasePrimitive = static_cast< const BasePrimitive3D* >(xReference.get());
- if(pBasePrimitive)
+ // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
+ // not all content is needed, remove transparencies and ModifiedColorPrimitives
+ switch(pBasePrimitive->getPrimitive3DID())
{
- // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
- // not all content is needed, remove transparencies and ModifiedColorPrimitives
- switch(pBasePrimitive->getPrimitive3DID())
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
{
- case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ // polyPolygonMaterialPrimitive3D, check texturing and hatching
+ const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive);
+ const basegfx::B3DPolyPolygon& aFillPolyPolygon(rPrimitive.getB3DPolyPolygon());
+
+ if(maHatch.isFillBackground())
{
- // polyPolygonMaterialPrimitive3D, check texturing and hatching
- const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive);
- const basegfx::B3DPolyPolygon& aFillPolyPolygon(rPrimitive.getB3DPolyPolygon());
+ // add original primitive for background
+ aDestination.push_back(xReference);
+ }
- if(maHatch.isFillBackground())
+ if(aFillPolyPolygon.areTextureCoordinatesUsed())
+ {
+ const sal_uInt32 nPolyCount(aFillPolyPolygon.count());
+ basegfx::B2DPolyPolygon aTexPolyPolygon;
+ basegfx::B2DPoint a2N;
+ basegfx::B2DVector a2X, a2Y;
+ basegfx::B3DPoint a3N;
+ basegfx::B3DVector a3X, a3Y;
+ bool b2N(false), b2X(false), b2Y(false);
+
+ for(sal_uInt32 b(0); b < nPolyCount; b++)
{
- // add original primitive for background
- aDestination.push_back(xReference);
- }
+ const basegfx::B3DPolygon& aPartPoly(aFillPolyPolygon.getB3DPolygon(b));
+ const sal_uInt32 nPointCount(aPartPoly.count());
+ basegfx::B2DPolygon aTexPolygon;
- if(aFillPolyPolygon.areTextureCoordinatesUsed())
- {
- const sal_uInt32 nPolyCount(aFillPolyPolygon.count());
- basegfx::B2DPolyPolygon aTexPolyPolygon;
- basegfx::B2DPoint a2N;
- basegfx::B2DVector a2X, a2Y;
- basegfx::B3DPoint a3N;
- basegfx::B3DVector a3X, a3Y;
- bool b2N(false), b2X(false), b2Y(false);
-
- for(sal_uInt32 b(0); b < nPolyCount; b++)
+ for(sal_uInt32 c(0); c < nPointCount; c++)
{
- const basegfx::B3DPolygon& aPartPoly(aFillPolyPolygon.getB3DPolygon(b));
- const sal_uInt32 nPointCount(aPartPoly.count());
- basegfx::B2DPolygon aTexPolygon;
+ const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c));
- for(sal_uInt32 c(0); c < nPointCount; c++)
+ if(!b2N)
{
- const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c));
-
- if(!b2N)
- {
- a2N = a2Candidate;
- a3N = aPartPoly.getB3DPoint(c);
- b2N = true;
- }
- else if(!b2X && !a2N.equal(a2Candidate))
- {
- a2X = a2Candidate - a2N;
- a3X = aPartPoly.getB3DPoint(c) - a3N;
- b2X = true;
- }
- else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate))
- {
- a2Y = a2Candidate - a2N;
+ a2N = a2Candidate;
+ a3N = aPartPoly.getB3DPoint(c);
+ b2N = true;
+ }
+ else if(!b2X && !a2N.equal(a2Candidate))
+ {
+ a2X = a2Candidate - a2N;
+ a3X = aPartPoly.getB3DPoint(c) - a3N;
+ b2X = true;
+ }
+ else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate))
+ {
+ a2Y = a2Candidate - a2N;
- const double fCross(a2X.cross(a2Y));
+ const double fCross(a2X.cross(a2Y));
- if(!basegfx::fTools::equalZero(fCross))
- {
- a3Y = aPartPoly.getB3DPoint(c) - a3N;
- b2Y = true;
- }
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ a3Y = aPartPoly.getB3DPoint(c) - a3N;
+ b2Y = true;
}
-
- aTexPolygon.append(a2Candidate);
}
- aTexPolygon.setClosed(true);
- aTexPolyPolygon.append(aTexPolygon);
+ aTexPolygon.append(a2Candidate);
}
- if(b2N && b2X && b2Y)
+ aTexPolygon.setClosed(true);
+ aTexPolyPolygon.append(aTexPolygon);
+ }
+
+ if(b2N && b2X && b2Y)
+ {
+ // found two linearly independent 2D vectors
+ // get 2d range of texture coordinates
+ const basegfx::B2DRange aOutlineRange(basegfx::utils::getRange(aTexPolyPolygon));
+ const basegfx::BColor aHatchColor(getHatch().getColor());
+ const double fAngle(getHatch().getAngle());
+ std::vector< basegfx::B2DHomMatrix > aMatrices;
+
+ // get hatch transformations
+ switch(getHatch().getStyle())
{
- // found two linearly independent 2D vectors
- // get 2d range of texture coordinates
- const basegfx::B2DRange aOutlineRange(basegfx::utils::getRange(aTexPolyPolygon));
- const basegfx::BColor aHatchColor(getHatch().getColor());
- const double fAngle(getHatch().getAngle());
- std::vector< basegfx::B2DHomMatrix > aMatrices;
-
- // get hatch transformations
- switch(getHatch().getStyle())
+ case attribute::HatchStyle::Triple:
{
- case attribute::HatchStyle::Triple:
- {
- // rotated 45 degrees
- texture::GeoTexSvxHatch aHatch(
- aOutlineRange,
- aOutlineRange,
- getHatch().getDistance(),
- fAngle - F_PI4);
-
- aHatch.appendTransformations(aMatrices);
-
- [[fallthrough]];
- }
- case attribute::HatchStyle::Double:
- {
- // rotated 90 degrees
- texture::GeoTexSvxHatch aHatch(
- aOutlineRange,
- aOutlineRange,
- getHatch().getDistance(),
- fAngle - F_PI2);
+ // rotated 45 degrees
+ texture::GeoTexSvxHatch aHatch(
+ aOutlineRange,
+ aOutlineRange,
+ getHatch().getDistance(),
+ fAngle - M_PI_4);
- aHatch.appendTransformations(aMatrices);
+ aHatch.appendTransformations(aMatrices);
- [[fallthrough]];
- }
- case attribute::HatchStyle::Single:
- {
- // angle as given
- texture::GeoTexSvxHatch aHatch(
- aOutlineRange,
- aOutlineRange,
- getHatch().getDistance(),
- fAngle);
-
- aHatch.appendTransformations(aMatrices);
- }
+ [[fallthrough]];
}
+ case attribute::HatchStyle::Double:
+ {
+ // rotated 90 degrees
+ texture::GeoTexSvxHatch aHatch(
+ aOutlineRange,
+ aOutlineRange,
+ getHatch().getDistance(),
+ fAngle - M_PI_2);
- // create geometry from unit line
- basegfx::B2DPolyPolygon a2DHatchLines;
- basegfx::B2DPolygon a2DUnitLine;
- a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0));
- a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0));
+ aHatch.appendTransformations(aMatrices);
- for(const basegfx::B2DHomMatrix & rMatrix : aMatrices)
- {
- basegfx::B2DPolygon aNewLine(a2DUnitLine);
- aNewLine.transform(rMatrix);
- a2DHatchLines.append(aNewLine);
+ [[fallthrough]];
}
-
- if(a2DHatchLines.count())
+ case attribute::HatchStyle::Single:
{
- // clip against texture polygon
- a2DHatchLines = basegfx::utils::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true);
+ // angle as given
+ texture::GeoTexSvxHatch aHatch(
+ aOutlineRange,
+ aOutlineRange,
+ getHatch().getDistance(),
+ fAngle);
+
+ aHatch.appendTransformations(aMatrices);
}
+ }
+
+ // create geometry from unit line
+ basegfx::B2DPolyPolygon a2DHatchLines;
+ basegfx::B2DPolygon a2DUnitLine;
+ a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0));
+ a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0));
+
+ for(const basegfx::B2DHomMatrix & rMatrix : aMatrices)
+ {
+ basegfx::B2DPolygon aNewLine(a2DUnitLine);
+ aNewLine.transform(rMatrix);
+ a2DHatchLines.append(aNewLine);
+ }
+
+ if(a2DHatchLines.count())
+ {
+ // clip against texture polygon
+ a2DHatchLines = basegfx::utils::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true);
+ }
- if(a2DHatchLines.count())
+ if(a2DHatchLines.count())
+ {
+ // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the new coordinate system
+ basegfx::B2DHomMatrix a2D;
+ a2D.set(0, 0, a2X.getX());
+ a2D.set(1, 0, a2X.getY());
+ a2D.set(0, 1, a2Y.getX());
+ a2D.set(1, 1, a2Y.getY());
+ a2D.set(0, 2, a2N.getX());
+ a2D.set(1, 2, a2N.getY());
+
+ // invert that transformation, so we have a back-transformation from texture coordinates
+ // to unit coordinates
+ a2D.invert();
+ a2DHatchLines.transform(a2D);
+
+ // expand back-transformed geometry to 3D
+ basegfx::B3DPolyPolygon a3DHatchLines(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0));
+
+ // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the object's 3d coordinate system
+ basegfx::B3DHomMatrix a3D;
+ a3D.set(0, 0, a3X.getX());
+ a3D.set(1, 0, a3X.getY());
+ a3D.set(2, 0, a3X.getZ());
+ a3D.set(0, 1, a3Y.getX());
+ a3D.set(1, 1, a3Y.getY());
+ a3D.set(2, 1, a3Y.getZ());
+ a3D.set(0, 3, a3N.getX());
+ a3D.set(1, 3, a3N.getY());
+ a3D.set(2, 3, a3N.getZ());
+
+ // transform hatch lines to 3D object coordinates
+ a3DHatchLines.transform(a3D);
+
+ // build primitives from this geometry
+ const sal_uInt32 nHatchLines(a3DHatchLines.count());
+
+ for(sal_uInt32 d(0); d < nHatchLines; d++)
{
- // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents
- // a coordinate system transformation from unit coordinates to the new coordinate system
- basegfx::B2DHomMatrix a2D;
- a2D.set(0, 0, a2X.getX());
- a2D.set(1, 0, a2X.getY());
- a2D.set(0, 1, a2Y.getX());
- a2D.set(1, 1, a2Y.getY());
- a2D.set(0, 2, a2N.getX());
- a2D.set(1, 2, a2N.getY());
-
- // invert that transformation, so we have a back-transformation from texture coordinates
- // to unit coordinates
- a2D.invert();
- a2DHatchLines.transform(a2D);
-
- // expand back-transformed geometry to 3D
- basegfx::B3DPolyPolygon a3DHatchLines(basegfx::utils::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0));
-
- // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents
- // a coordinate system transformation from unit coordinates to the object's 3d coordinate system
- basegfx::B3DHomMatrix a3D;
- a3D.set(0, 0, a3X.getX());
- a3D.set(1, 0, a3X.getY());
- a3D.set(2, 0, a3X.getZ());
- a3D.set(0, 1, a3Y.getX());
- a3D.set(1, 1, a3Y.getY());
- a3D.set(2, 1, a3Y.getZ());
- a3D.set(0, 3, a3N.getX());
- a3D.set(1, 3, a3N.getY());
- a3D.set(2, 3, a3N.getZ());
-
- // transform hatch lines to 3D object coordinates
- a3DHatchLines.transform(a3D);
-
- // build primitives from this geometry
- const sal_uInt32 nHatchLines(a3DHatchLines.count());
-
- for(sal_uInt32 d(0); d < nHatchLines; d++)
- {
- const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor));
- aDestination.push_back(xRef);
- }
+ const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor));
+ aDestination.push_back(xRef);
}
}
}
-
- break;
- }
- default :
- {
- // add reference to result
- aDestination.push_back(xReference);
- break;
}
+
+ break;
+ }
+ default :
+ {
+ // add reference to result
+ aDestination.push_back(xReference);
+ break;
}
- }
- else
- {
- // unknown implementation, add to result
- aDestination.push_back(xReference);
}
}
}
@@ -276,14 +268,13 @@ namespace drawinglayer::primitive3d
}
HatchTexturePrimitive3D::HatchTexturePrimitive3D(
- const attribute::FillHatchAttribute& rHatch,
+ attribute::FillHatchAttribute aHatch,
const Primitive3DContainer& rChildren,
const basegfx::B2DVector& rTextureSize,
bool bModulate,
bool bFilter)
: TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
- maHatch(rHatch),
- maBuffered3DDecomposition()
+ maHatch(std::move(aHatch))
{
}
@@ -301,12 +292,11 @@ namespace drawinglayer::primitive3d
Primitive3DContainer HatchTexturePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
if(getBuffered3DDecomposition().empty())
{
- const Primitive3DContainer aNewSequence(impCreate3DDecomposition());
- const_cast< HatchTexturePrimitive3D* >(this)->maBuffered3DDecomposition = aNewSequence;
+ const_cast<HatchTexturePrimitive3D*>(this)->maBuffered3DDecomposition = impCreate3DDecomposition();
}
return getBuffered3DDecomposition();
diff --git a/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx b/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx
index 1a367e501d29..8d69d8741097 100644
--- a/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx
@@ -21,9 +21,6 @@
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-using namespace com::sun::star;
-
-
namespace drawinglayer::primitive3d
{
HiddenGeometryPrimitive3D::HiddenGeometryPrimitive3D(
diff --git a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
index 255f0235c911..64ae9b949ca1 100644
--- a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
@@ -19,18 +19,16 @@
#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
{
ModifiedColorPrimitive3D::ModifiedColorPrimitive3D(
const Primitive3DContainer& rChildren,
- const basegfx::BColorModifierSharedPtr& rColorModifier)
+ basegfx::BColorModifierSharedPtr xColorModifier)
: GroupPrimitive3D(rChildren),
- maColorModifier(rColorModifier)
+ maColorModifier(std::move(xColorModifier))
{
}
diff --git a/drawinglayer/source/primitive3d/polygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
index ac820546b9fa..6127ac77666b 100644
--- a/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
@@ -22,6 +22,7 @@
#include <basegfx/polygon/b3dpolypolygon.hxx>
#include <primitive3d/polygontubeprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -30,10 +31,9 @@ using namespace com::sun::star;
namespace drawinglayer::primitive3d
{
PolygonHairlinePrimitive3D::PolygonHairlinePrimitive3D(
- const basegfx::B3DPolygon& rPolygon,
+ basegfx::B3DPolygon aPolygon,
const basegfx::BColor& rBColor)
- : BasePrimitive3D(),
- maPolygon(rPolygon),
+ : maPolygon(std::move(aPolygon)),
maBColor(rBColor)
{
}
@@ -118,13 +118,12 @@ namespace drawinglayer::primitive3d
}
PolygonStrokePrimitive3D::PolygonStrokePrimitive3D(
- const basegfx::B3DPolygon& rPolygon,
+ basegfx::B3DPolygon aPolygon,
const attribute::LineAttribute& rLineAttribute,
- const attribute::StrokeAttribute& rStrokeAttribute)
- : BufferedDecompositionPrimitive3D(),
- maPolygon(rPolygon),
+ attribute::StrokeAttribute aStrokeAttribute)
+ : maPolygon(std::move(aPolygon)),
maLineAttribute(rLineAttribute),
- maStrokeAttribute(rStrokeAttribute)
+ maStrokeAttribute(std::move(aStrokeAttribute))
{
}
diff --git a/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
index 177d829ef4fc..473d836dc462 100644
--- a/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
@@ -25,8 +25,7 @@
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-#include <rtl/instance.hxx>
-
+#include <mutex>
namespace drawinglayer::primitive3d
{
@@ -39,7 +38,7 @@ namespace drawinglayer::primitive3d
Primitive3DContainer m_aLineTubeList;
sal_uInt32 m_nLineTubeSegments;
attribute::MaterialAttribute3D m_aLineMaterial;
- ::osl::Mutex m_aMutex;
+ std::mutex m_aMutex;
public:
TubeBuffer()
: m_nLineTubeSegments(0)
@@ -54,7 +53,7 @@ namespace drawinglayer::primitive3d
const attribute::MaterialAttribute3D& rMaterial)
{
// may exclusively change cached data, use mutex
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
if (nSegments != m_nLineTubeSegments || !(rMaterial == m_aLineMaterial))
{
@@ -70,7 +69,7 @@ namespace drawinglayer::primitive3d
basegfx::B3DPoint aLastLeft(0.0, 1.0, 0.0);
basegfx::B3DPoint aLastRight(1.0, 1.0, 0.0);
basegfx::B3DHomMatrix aRot;
- aRot.rotate(F_2PI / static_cast<double>(m_nLineTubeSegments), 0.0, 0.0);
+ aRot.rotate(2 * M_PI / static_cast<double>(m_nLineTubeSegments), 0.0, 0.0);
m_aLineTubeList.resize(m_nLineTubeSegments);
for(sal_uInt32 a = 0; a < m_nLineTubeSegments; ++a)
@@ -93,9 +92,8 @@ namespace drawinglayer::primitive3d
aNewPolygon.setClosed(true);
- const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
- const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, m_aLineMaterial, false));
- m_aLineTubeList[a] = xRef;
+ basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ m_aLineTubeList[a] = new PolyPolygonMaterialPrimitive3D(std::move(aNewPolyPolygon), m_aLineMaterial, false);
aLastLeft = aNextLeft;
aLastRight = aNextRight;
@@ -105,16 +103,13 @@ namespace drawinglayer::primitive3d
}
};
- struct theTubeBuffer :
- public rtl::Static< TubeBuffer, theTubeBuffer > {};
-
Primitive3DContainer getLineTubeSegments(
sal_uInt32 nSegments,
const attribute::MaterialAttribute3D& rMaterial)
{
// static data for buffered tube primitives
- TubeBuffer &rTheBuffer = theTubeBuffer::get();
- return rTheBuffer.getLineTubeSegments(nSegments, rMaterial);
+ static TubeBuffer theTubeBuffer;
+ return theTubeBuffer.getLineTubeSegments(nSegments, rMaterial);
}
class CapBuffer
@@ -124,7 +119,7 @@ namespace drawinglayer::primitive3d
Primitive3DContainer m_aLineCapList;
sal_uInt32 m_nLineCapSegments;
attribute::MaterialAttribute3D m_aLineMaterial;
- ::osl::Mutex m_aMutex;
+ std::mutex m_aMutex;
public:
CapBuffer()
: m_nLineCapSegments(0)
@@ -138,7 +133,7 @@ namespace drawinglayer::primitive3d
const attribute::MaterialAttribute3D& rMaterial)
{
// may exclusively change cached data, use mutex
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
if (nSegments != m_nLineCapSegments || !(rMaterial == m_aLineMaterial))
{
@@ -152,7 +147,7 @@ namespace drawinglayer::primitive3d
const basegfx::B3DPoint aNull(0.0, 0.0, 0.0);
basegfx::B3DPoint aLast(0.0, 1.0, 0.0);
basegfx::B3DHomMatrix aRot;
- aRot.rotate(F_2PI / static_cast<double>(m_nLineCapSegments), 0.0, 0.0);
+ aRot.rotate(2 * M_PI / static_cast<double>(m_nLineCapSegments), 0.0, 0.0);
m_aLineCapList.resize(m_nLineCapSegments);
for(sal_uInt32 a = 0; a < m_nLineCapSegments; ++a)
@@ -171,9 +166,8 @@ namespace drawinglayer::primitive3d
aNewPolygon.setClosed(true);
- const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
- const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, m_aLineMaterial, false));
- m_aLineCapList[a] = xRef;
+ basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ m_aLineCapList[a] = new PolyPolygonMaterialPrimitive3D(std::move(aNewPolyPolygon), m_aLineMaterial, false);
aLast = aNext;
}
@@ -183,16 +177,13 @@ namespace drawinglayer::primitive3d
}
};
- struct theCapBuffer :
- public rtl::Static< CapBuffer, theCapBuffer > {};
-
Primitive3DContainer getLineCapSegments(
sal_uInt32 nSegments,
const attribute::MaterialAttribute3D& rMaterial)
{
// static data for buffered cap primitives
- CapBuffer &rTheBuffer = theCapBuffer::get();
- return rTheBuffer.getLineCapSegments(nSegments, rMaterial);
+ static CapBuffer theCapBuffer;
+ return theCapBuffer.getLineCapSegments(nSegments, rMaterial);
}
class CapRoundBuffer
@@ -202,7 +193,7 @@ namespace drawinglayer::primitive3d
Primitive3DContainer m_aLineCapRoundList;
sal_uInt32 m_nLineCapRoundSegments;
attribute::MaterialAttribute3D m_aLineMaterial;
- ::osl::Mutex m_aMutex;
+ std::mutex m_aMutex;
public:
CapRoundBuffer()
: m_nLineCapRoundSegments(0)
@@ -216,7 +207,7 @@ namespace drawinglayer::primitive3d
const attribute::MaterialAttribute3D& rMaterial)
{
// may exclusively change cached data, use mutex
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
if (nSegments != m_nLineCapRoundSegments || !(rMaterial == m_aLineMaterial))
{
@@ -241,8 +232,8 @@ namespace drawinglayer::primitive3d
nSegments,
nVerSeg,
true,
- F_PI2, 0.0,
- 0.0, F_2PI));
+ M_PI_2, 0.0,
+ 0.0, 2 * M_PI));
const sal_uInt32 nCount(aSphere.count());
if (nCount)
@@ -251,7 +242,7 @@ namespace drawinglayer::primitive3d
// forget to transform normals, too
basegfx::B3DHomMatrix aSphereTrans;
- aSphereTrans.rotate(0.0, 0.0, F_PI2);
+ aSphereTrans.rotate(0.0, 0.0, M_PI_2);
aSphere.transform(aSphereTrans);
aSphere.transformNormals(aSphereTrans);
@@ -261,12 +252,12 @@ namespace drawinglayer::primitive3d
for (sal_uInt32 a = 0; a < nCount; ++a)
{
const basegfx::B3DPolygon& aPartPolygon(aSphere.getB3DPolygon(a));
- const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
+ basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
// need to create one primitive per Polygon since the primitive
// is for planar PolyPolygons which is definitely not the case here
m_aLineCapRoundList[a] = new PolyPolygonMaterialPrimitive3D(
- aPartPolyPolygon,
+ std::move(aPartPolyPolygon),
rMaterial,
false);
}
@@ -278,17 +269,13 @@ namespace drawinglayer::primitive3d
};
- struct theCapRoundBuffer :
- public rtl::Static< CapRoundBuffer, theCapRoundBuffer > {};
-
-
Primitive3DContainer getLineCapRoundSegments(
sal_uInt32 nSegments,
const attribute::MaterialAttribute3D& rMaterial)
{
// static data for buffered cap primitives
- CapRoundBuffer &rTheBuffer = theCapRoundBuffer::get();
- return rTheBuffer.getLineCapRoundSegments(nSegments, rMaterial);
+ static CapRoundBuffer theCapRoundBuffer;
+ return theCapRoundBuffer.getLineCapRoundSegments(nSegments, rMaterial);
}
Primitive3DContainer getLineJoinSegments(
@@ -307,19 +294,18 @@ namespace drawinglayer::primitive3d
if(basegfx::B2DLineJoin::Round == aLineJoin)
{
// calculate new horizontal segments
- const sal_uInt32 nHorSeg(basegfx::fround((fAngle / F_2PI) * static_cast<double>(nSegments)));
+ const sal_uInt32 nHorSeg(basegfx::fround((fAngle / (2 * M_PI)) * static_cast<double>(nSegments)));
if(nHorSeg)
{
// create half-sphere
- const basegfx::B3DPolyPolygon aSphere(basegfx::utils::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle));
+ const basegfx::B3DPolyPolygon aSphere(basegfx::utils::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, M_PI_2, -M_PI_2, 0.0, fAngle));
for(sal_uInt32 a(0); a < aSphere.count(); a++)
{
const basegfx::B3DPolygon& aPartPolygon(aSphere.getB3DPolygon(a));
- const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
- BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aPartPolyPolygon, rMaterial, false);
- aResultVector.push_back(pNew);
+ basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
+ aResultVector.push_back(new PolyPolygonMaterialPrimitive3D(std::move(aPartPolyPolygon), rMaterial, false));
}
}
else
@@ -343,13 +329,13 @@ namespace drawinglayer::primitive3d
}
}
- const double fInc(F_PI / static_cast<double>(nVerSeg));
+ const double fInc(M_PI / static_cast<double>(nVerSeg));
const double fSin(sin(-fAngle));
const double fCos(cos(-fAngle));
const bool bMiter(basegfx::B2DLineJoin::Miter == aLineJoin);
const double fMiterSin(bMiter ? sin(-(fAngle/2.0)) : 0.0);
const double fMiterCos(bMiter ? cos(-(fAngle/2.0)) : 0.0);
- double fPos(-F_PI2);
+ double fPos(-M_PI_2);
basegfx::B3DPoint aPointOnXY, aPointRotY, aNextPointOnXY, aNextPointRotY;
basegfx::B3DPoint aCurrMiter, aNextMiter;
basegfx::B3DPolygon aNewPolygon, aMiterPolygon;
@@ -465,9 +451,8 @@ namespace drawinglayer::primitive3d
// create primitive
if(aNewPolygon.count())
{
- const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
- BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, rMaterial, false);
- aResultVector.push_back(pNew);
+ basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ aResultVector.push_back(new PolyPolygonMaterialPrimitive3D(std::move(aNewPolyPolygon), rMaterial, false));
}
if(bMiter && aMiterPolygon.count())
@@ -479,9 +464,8 @@ namespace drawinglayer::primitive3d
}
// create primitive
- const basegfx::B3DPolyPolygon aMiterPolyPolygon(aMiterPolygon);
- BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aMiterPolyPolygon, rMaterial, false);
- aResultVector.push_back(pNew);
+ basegfx::B3DPolyPolygon aMiterPolyPolygon(aMiterPolygon);
+ aResultVector.push_back(new PolyPolygonMaterialPrimitive3D(std::move(aMiterPolyPolygon), rMaterial, false));
}
// prepare next step
@@ -501,10 +485,7 @@ namespace drawinglayer::primitive3d
Primitive3DContainer aRetval(aResultVector.size());
- for(size_t a(0); a < aResultVector.size(); a++)
- {
- aRetval[a] = Primitive3DReference(aResultVector[a]);
- }
+ std::transform(aResultVector.cbegin(), aResultVector.cend(), aRetval.begin(), [](auto &rResult){return Primitive3DReference(rResult);});
return aRetval;
}
@@ -536,7 +517,7 @@ using namespace com::sun::star;
if(nPointCount)
{
- if(basegfx::fTools::more(getRadius(), 0.0))
+ if(getRadius() > 0.0)
{
const attribute::MaterialAttribute3D aMaterial(getBColor());
static const sal_uInt32 nSegments(8); // default for 3d line segments, for more quality just raise this value (in even steps)
@@ -553,7 +534,7 @@ using namespace com::sun::star;
const basegfx::B3DVector aForw(aNext - aCurr);
const double fForwLen(aForw.getLength());
- if(basegfx::fTools::more(fForwLen, 0.0))
+ if(fForwLen > 0.0)
{
// find out if linecap is active
const bool bFirst(!a);
@@ -615,8 +596,7 @@ using namespace com::sun::star;
aSequence = getLineCapSegments(nSegments, aMaterial);
}
- TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aCapTrans, aSequence);
- aResultVector.push_back(pNewTransformedA);
+ aResultVector.push_back(new TransformPrimitive3D(std::move(aCapTrans), aSequence));
}
else
{
@@ -626,7 +606,7 @@ using namespace com::sun::star;
if(!basegfx::fTools::equalZero(fCross))
{
// line connect non-parallel, aBack, aForw, use getLineJoin()
- const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2
+ const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. M_PI_2
Primitive3DContainer aNewList(
getLineJoinSegments(
nSegments,
@@ -644,8 +624,8 @@ using namespace com::sun::star;
// create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X.
// Also apply usual scaling and translation
basegfx::B3DHomMatrix aSphereTrans;
- aSphereTrans.rotate(0.0, F_PI2, 0.0);
- aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0);
+ aSphereTrans.rotate(0.0, M_PI_2, 0.0);
+ aSphereTrans.rotate(M_PI - fRotInYZ, 0.0, 0.0);
aSphereTrans *= aRotVector;
aSphereTrans.scale(getRadius(), getRadius(), getRadius());
aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
@@ -653,7 +633,7 @@ using namespace com::sun::star;
// line start edge, build transformed primitiveVector3D
aResultVector.push_back(
new TransformPrimitive3D(
- aSphereTrans,
+ std::move(aSphereTrans),
aNewList));
}
}
@@ -661,7 +641,7 @@ using namespace com::sun::star;
// create line segments, build transformed primitiveVector3D
aResultVector.push_back(
new TransformPrimitive3D(
- aTubeTrans,
+ std::move(aTubeTrans),
getLineTubeSegments(nSegments, aMaterial)));
if(bNoLineJoin || (!bClosed && bLast))
@@ -670,7 +650,7 @@ using namespace com::sun::star;
basegfx::B3DHomMatrix aBackCapTrans;
// Mirror (line end) and radius scale
- aBackCapTrans.rotate(0.0, F_PI, 0.0);
+ aBackCapTrans.rotate(0.0, M_PI, 0.0);
aBackCapTrans.scale(getRadius(), getRadius(), getRadius());
if(bLineCapSquare && bLast)
@@ -704,7 +684,7 @@ using namespace com::sun::star;
aResultVector.push_back(
new TransformPrimitive3D(
- aBackCapTrans,
+ std::move(aBackCapTrans),
aSequence));
}
}
@@ -717,18 +697,14 @@ using namespace com::sun::star;
else
{
// create hairline
- PolygonHairlinePrimitive3D* pNew = new PolygonHairlinePrimitive3D(getB3DPolygon(), getBColor());
- aResultVector.push_back(pNew);
+ aResultVector.push_back(new PolygonHairlinePrimitive3D(getB3DPolygon(), getBColor()));
}
}
// prepare return value
Primitive3DContainer aRetval(aResultVector.size());
- for(size_t a(0); a < aResultVector.size(); a++)
- {
- aRetval[a] = Primitive3DReference(aResultVector[a]);
- }
+ std::transform(aResultVector.cbegin(), aResultVector.cend(), aRetval.begin(), [](auto &rResult){return Primitive3DReference(rResult);});
return aRetval;
}
@@ -741,7 +717,6 @@ using namespace com::sun::star;
double fDegreeStepWidth,
double fMiterMinimumAngle)
: PolygonHairlinePrimitive3D(rPolygon, rBColor),
- maLast3DDecomposition(),
mfRadius(fRadius),
mfDegreeStepWidth(fDegreeStepWidth),
mfMiterMinimumAngle(fMiterMinimumAngle),
@@ -768,12 +743,12 @@ using namespace com::sun::star;
Primitive3DContainer PolygonTubePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
if(getLast3DDecomposition().empty())
{
- const Primitive3DContainer aNewSequence(impCreate3DDecomposition(rViewInformation));
- const_cast< PolygonTubePrimitive3D* >(this)->maLast3DDecomposition = aNewSequence;
+ Primitive3DContainer aNewSequence(impCreate3DDecomposition(rViewInformation));
+ const_cast< PolygonTubePrimitive3D* >(this)->maLast3DDecomposition = std::move(aNewSequence);
}
return getLast3DDecomposition();
diff --git a/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
index db137b47eb28..5a03a89841e0 100644
--- a/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
@@ -20,19 +20,16 @@
#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
{
PolyPolygonMaterialPrimitive3D::PolyPolygonMaterialPrimitive3D(
- const basegfx::B3DPolyPolygon& rPolyPolygon,
+ basegfx::B3DPolyPolygon aPolyPolygon,
const attribute::MaterialAttribute3D& rMaterial,
bool bDoubleSided)
- : BasePrimitive3D(),
- maPolyPolygon(rPolyPolygon),
+ : maPolyPolygon(std::move(aPolyPolygon)),
maMaterial(rMaterial),
mbDoubleSided(bDoubleSided)
{
diff --git a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
index 826583b1404c..d69bb87b865c 100644
--- a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
@@ -36,6 +36,7 @@
#include <drawinglayer/attribute/sdrfillattribute.hxx>
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
#include <primitive3d/hiddengeometryprimitive3d.hxx>
+#include <rtl/ref.hxx>
namespace drawinglayer::primitive3d
@@ -136,15 +137,14 @@ namespace drawinglayer::primitive3d
// create line and stroke attribute
const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin(), rLine.getCap());
- const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen());
+ const attribute::StrokeAttribute aStrokeAttribute(std::vector(rLine.getDotDashArray()), rLine.getFullDotDashLen());
// create primitives
Primitive3DContainer aRetval(aScaledPolyPolygon.count());
for(sal_uInt32 a(0); a < aScaledPolyPolygon.count(); a++)
{
- const Primitive3DReference xRef(new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute));
- aRetval[a] = xRef;
+ aRetval[a] = new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute);
}
if(0.0 != rLine.getTransparence())
@@ -184,7 +184,7 @@ namespace drawinglayer::primitive3d
}
const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(
- aScaledPolyPolygon,
+ std::move(aScaledPolyPolygon),
aSdr3DObjectAttribute.getMaterial(),
aSdr3DObjectAttribute.getDoubleSided()));
aRetval[a] = xRef;
@@ -197,7 +197,7 @@ namespace drawinglayer::primitive3d
{
bool bModulate(css::drawing::TextureMode_MODULATE == aSdr3DObjectAttribute.getTextureMode());
bool bFilter(aSdr3DObjectAttribute.getTextureFilter());
- BasePrimitive3D* pNewTexturePrimitive3D = nullptr;
+ rtl::Reference<BasePrimitive3D> pNewTexturePrimitive3D;
if(!rFill.getGradient().isDefault())
{
@@ -233,18 +233,17 @@ namespace drawinglayer::primitive3d
}
// exchange aRetval content with texture group
- const Primitive3DReference xRef(pNewTexturePrimitive3D);
- aRetval = { xRef };
+ aRetval = { Primitive3DReference(pNewTexturePrimitive3D) };
if(css::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind())
{
// use modified color primitive to force textures to gray
- const basegfx::BColorModifierSharedPtr aBColorModifier =
+ basegfx::BColorModifierSharedPtr aBColorModifier =
std::make_shared<basegfx::BColorModifier_gray>();
- const Primitive3DReference xRef2(
+ Primitive3DReference xRef2(
new ModifiedColorPrimitive3D(
aRetval,
- aBColorModifier));
+ std::move(aBColorModifier)));
aRetval = { xRef2 };
}
diff --git a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
index afe030ac77b9..2e1071c1f9a6 100644
--- a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
@@ -71,7 +71,7 @@ namespace
{
rOuterPolyPolygon = rPolygon;
- if(!basegfx::fTools::more(fOffset, 0.0))
+ if (fOffset <= 0.0 || basegfx::fTools::equalZero(fOffset))
return;
if(bCharacterMode)
@@ -129,10 +129,22 @@ namespace
if(bCreateTextureCoordinates)
{
const double fPolygonLengthA(basegfx::utils::getLength(aSubA));
- fTexHorMultiplicatorA = basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA;
+ if (basegfx::fTools::equalZero(fPolygonLengthA))
+ fTexHorMultiplicatorA = 1.0;
+ else
+ {
+ assert(fPolygonLengthA != 0 && "help coverity see it's not zero");
+ fTexHorMultiplicatorA = 1.0 / fPolygonLengthA;
+ }
const double fPolygonLengthB(basegfx::utils::getLength(aSubB));
- fTexHorMultiplicatorB = basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB;
+ if (basegfx::fTools::equalZero(fPolygonLengthB))
+ fTexHorMultiplicatorB = 1.0;
+ else
+ {
+ assert(fPolygonLengthB != 0 && "help coverity see it's not zero");
+ fTexHorMultiplicatorB = 1.0 / fPolygonLengthB;
+ }
}
for(sal_uInt32 b(0); b < nEdgeCount; b++)
@@ -312,26 +324,26 @@ namespace
// polygon is closed, one of the points is a member
const sal_uInt32 nPointCount(rPoly.count());
- if(nPointCount)
- {
- basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
- const basegfx::B2DVector aVector(rEnd - rStart);
+ if(!nPointCount)
+ return false;
- for(sal_uInt32 a(0); a < nPointCount; a++)
- {
- const sal_uInt32 nNextIndex((a + 1) % nPointCount);
- const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
- const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
+ basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
+ const basegfx::B2DVector aVector(rEnd - rStart);
- if(basegfx::utils::findCut(
- rStart, aVector,
- aCurrent, aEdgeVector) != CutFlagValue::NONE)
- {
- return true;
- }
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
+ const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
- aCurrent = aNext;
+ if(basegfx::utils::findCut(
+ rStart, aVector,
+ aCurrent, aEdgeVector) != CutFlagValue::NONE)
+ {
+ return true;
}
+
+ aCurrent = aNext;
}
return false;
@@ -360,7 +372,7 @@ namespace drawinglayer::primitive3d
else
{
const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
- const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, F_2PI));
+ const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, 2 * M_PI));
basegfx::B2DPolyPolygon aFront(rSource);
basegfx::B2DPolyPolygon aBack(rSource);
basegfx::B3DHomMatrix aTransformBack;
@@ -619,6 +631,7 @@ namespace drawinglayer::primitive3d
if(!basegfx::fTools::equalZero(fTexHeight))
{
+ assert(fTexHeight != 0 && "help coverity see it's not zero");
fInvTexHeight = 1.0 / fTexHeight;
}
}
diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
index b7d1c8abdd9b..ed0e8d41c4ab 100644
--- a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
@@ -30,6 +30,7 @@
#include <drawinglayer/attribute/sdrfillattribute.hxx>
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -234,7 +235,7 @@ namespace drawinglayer::primitive3d
// take each angle which deviates more than 10% from going straight as
// special edge. This will detect the two outer edges of pie segments,
// but not always the center one (think about a near 180 degree pie)
- if(F_PI - fabs(fAngle) > F_PI * 0.1)
+ if(M_PI - fabs(fAngle) > M_PI * 0.1)
{
if(nPointCount == nIndexA)
{
@@ -375,7 +376,7 @@ namespace drawinglayer::primitive3d
// again when no longer geometry is needed for non-visible 3D objects as it is now for chart
if(getPolyPolygon().count() && maSlices.empty())
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices();
}
@@ -388,7 +389,7 @@ namespace drawinglayer::primitive3d
const basegfx::B2DVector& rTextureSize,
const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
- const basegfx::B2DPolyPolygon& rPolyPolygon,
+ basegfx::B2DPolyPolygon aPolyPolygon,
double fDepth,
double fDiagonal,
double fBackScale,
@@ -398,9 +399,7 @@ namespace drawinglayer::primitive3d
bool bCloseFront,
bool bCloseBack)
: SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
- maCorrectedPolyPolygon(),
- maSlices(),
- maPolyPolygon(rPolyPolygon),
+ maPolyPolygon(std::move(aPolyPolygon)),
mfDepth(fDepth),
mfDiagonal(fDiagonal),
mfBackScale(fBackScale),
@@ -411,13 +410,13 @@ namespace drawinglayer::primitive3d
mbCloseBack(bCloseBack)
{
// make sure depth is positive
- if(basegfx::fTools::lessOrEqual(getDepth(), 0.0))
+ if(getDepth() <= 0.0)
{
mfDepth = 0.0;
}
// make sure the percentage value getDiagonal() is between 0.0 and 1.0
- if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ if(getDiagonal() <= 0.0)
{
mfDiagonal = 0.0;
}
@@ -482,13 +481,13 @@ namespace drawinglayer::primitive3d
(!getBuffered3DDecomposition().empty()
&& *mpLastRLGViewInformation != rViewInformation))
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
// conditions of last local decomposition with reduced lines have changed. Remember
// new one and clear current decompositiopn
SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this);
pThat->setBuffered3DDecomposition(Primitive3DContainer());
- pThat->mpLastRLGViewInformation.reset( new geometry::ViewInformation3D(rViewInformation) );
+ pThat->mpLastRLGViewInformation = rViewInformation;
}
}
diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
index 1d5b918a27bf..682ea0c54042 100644
--- a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
@@ -26,6 +26,7 @@
#include <drawinglayer/attribute/sdrfillattribute.hxx>
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -43,7 +44,7 @@ namespace drawinglayer::primitive3d
if(!rSliceVector.empty())
{
const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
- const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI));
+ const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), 2 * M_PI));
sal_uInt32 a;
// decide what to create
@@ -227,7 +228,7 @@ namespace drawinglayer::primitive3d
// again when no longer geometry is needed for non-visible 3D objects as it is now for chart
if(getPolyPolygon().count() && maSlices.empty())
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
}
@@ -240,7 +241,7 @@ namespace drawinglayer::primitive3d
const basegfx::B2DVector& rTextureSize,
const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
- const basegfx::B2DPolyPolygon& rPolyPolygon,
+ basegfx::B2DPolyPolygon aPolyPolygon,
sal_uInt32 nHorizontalSegments,
sal_uInt32 nVerticalSegments,
double fDiagonal,
@@ -252,9 +253,7 @@ namespace drawinglayer::primitive3d
bool bCloseFront,
bool bCloseBack)
: SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
- maCorrectedPolyPolygon(),
- maSlices(),
- maPolyPolygon(rPolyPolygon),
+ maPolyPolygon(std::move(aPolyPolygon)),
mnHorizontalSegments(nHorizontalSegments),
mnVerticalSegments(nVerticalSegments),
mfDiagonal(fDiagonal),
@@ -267,13 +266,13 @@ namespace drawinglayer::primitive3d
mbCloseBack(bCloseBack)
{
// make sure Rotation is positive
- if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
+ if(getRotation() <= 0.0)
{
mfRotation = 0.0;
}
// make sure the percentage value getDiagonal() is between 0.0 and 1.0
- if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ if(getDiagonal() <= 0.0)
{
mfDiagonal = 0.0;
}
@@ -340,13 +339,13 @@ namespace drawinglayer::primitive3d
(!getBuffered3DDecomposition().empty()
&& *mpLastRLGViewInformation != rViewInformation))
{
- ::osl::MutexGuard aGuard( m_aMutex );
+ std::unique_lock aGuard( m_aMutex );
// conditions of last local decomposition with reduced lines have changed. Remember
// new one and clear current decompositiopn
SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
pThat->setBuffered3DDecomposition(Primitive3DContainer());
- pThat->mpLastRLGViewInformation.reset( new geometry::ViewInformation3D(rViewInformation) );
+ pThat->mpLastRLGViewInformation = rViewInformation;
}
}
diff --git a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
index 4887802e17a4..9219cc970c86 100644
--- a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
@@ -24,6 +24,7 @@
#include <drawinglayer/attribute/sdrfillattribute.hxx>
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -37,8 +38,7 @@ namespace drawinglayer::primitive3d
if(getPolyPolygon3D().count())
{
- std::vector< basegfx::B3DPolyPolygon > aFill;
- aFill.push_back(getPolyPolygon3D());
+ std::vector< basegfx::B3DPolyPolygon > aFill { getPolyPolygon3D() };
// get full range
const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
@@ -118,13 +118,13 @@ namespace drawinglayer::primitive3d
}
SdrPolyPolygonPrimitive3D::SdrPolyPolygonPrimitive3D(
- const basegfx::B3DPolyPolygon& rPolyPolygon3D,
+ basegfx::B3DPolyPolygon aPolyPolygon3D,
const basegfx::B3DHomMatrix& rTransform,
const basegfx::B2DVector& rTextureSize,
const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
: SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
- maPolyPolygon3D(rPolyPolygon3D)
+ maPolyPolygon3D(std::move(aPolyPolygon3D))
{
}
diff --git a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
index ad8b9daca186..7a6feb946ebc 100644
--- a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
@@ -20,9 +20,7 @@
#include <drawinglayer/primitive3d/sdrprimitive3d.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <drawinglayer/attribute/sdrlineattribute.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
@@ -75,14 +73,13 @@ namespace drawinglayer::primitive3d
}
SdrPrimitive3D::SdrPrimitive3D(
- const basegfx::B3DHomMatrix& rTransform,
+ basegfx::B3DHomMatrix aTransform,
const basegfx::B2DVector& rTextureSize,
- const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ attribute::SdrLineFillShadowAttribute3D aSdrLFSAttribute,
const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
- : BufferedDecompositionPrimitive3D(),
- maTransform(rTransform),
+ : maTransform(std::move(aTransform)),
maTextureSize(rTextureSize),
- maSdrLFSAttribute(rSdrLFSAttribute),
+ maSdrLFSAttribute(std::move(aSdrLFSAttribute)),
maSdr3DObjectAttribute(rSdr3DObjectAttribute)
{
}
diff --git a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
index 1e0dd7454124..c3127261f502 100644
--- a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
@@ -83,7 +83,7 @@ namespace drawinglayer::primitive3d
// different from forced to sphere texture coordinates,
// create a old version from it by rotating to old state before applying
// the texture coordinates to emulate old behaviour
- fRelativeAngle = F_2PI * (static_cast<double>((getHorizontalSegments() >> 1) - 1) / static_cast<double>(getHorizontalSegments()));
+ fRelativeAngle = 2 * M_PI * (static_cast<double>((getHorizontalSegments() >> 1) - 1) / static_cast<double>(getHorizontalSegments()));
basegfx::B3DHomMatrix aRot;
aRot.rotate(0.0, fRelativeAngle, 0.0);
aFill.transform(aRot);
diff --git a/drawinglayer/source/primitive3d/shadowprimitive3d.cxx b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
index cca2e3c6f07f..c32d17dbc69e 100644
--- a/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
@@ -19,21 +19,19 @@
#include <primitive3d/shadowprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
{
ShadowPrimitive3D::ShadowPrimitive3D(
- const basegfx::B2DHomMatrix& rShadowTransform,
+ basegfx::B2DHomMatrix aShadowTransform,
const basegfx::BColor& rShadowColor,
double fShadowTransparence,
bool bShadow3D,
const Primitive3DContainer& rChildren)
: GroupPrimitive3D(rChildren),
- maShadowTransform(rShadowTransform),
+ maShadowTransform(std::move(aShadowTransform)),
maShadowColor(rShadowColor),
mfShadowTransparence(fShadowTransparence),
mbShadow3D(bShadow3D)
diff --git a/drawinglayer/source/primitive3d/textureprimitive3d.cxx b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
index a053a7c214d0..ceeca0489487 100644
--- a/drawinglayer/source/primitive3d/textureprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
@@ -20,6 +20,8 @@
#include <primitive3d/textureprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
#include <basegfx/color/bcolor.hxx>
+#include <basegfx/utils/gradienttools.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -91,7 +93,13 @@ namespace drawinglayer::primitive3d
{
// create TransparenceTexturePrimitive3D with fixed transparence as replacement
const basegfx::BColor aGray(getTransparence(), getTransparence(), getTransparence());
- const attribute::FillGradientAttribute aFillGradient(attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, 0.0, aGray, aGray, 1);
+
+ // create ColorStops with StartColor == EndColor == aGray
+ const basegfx::BColorStops aColorStops {
+ basegfx::BColorStop(0.0, aGray),
+ basegfx::BColorStop(1.0, aGray) };
+
+ const attribute::FillGradientAttribute aFillGradient(css::awt::GradientStyle_LINEAR, 0.0, 0.0, 0.0, 0.0, aColorStops);
const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(aFillGradient, getChildren(), getTextureSize()));
return { xRef };
}
@@ -108,13 +116,13 @@ namespace drawinglayer::primitive3d
GradientTexturePrimitive3D::GradientTexturePrimitive3D(
- const attribute::FillGradientAttribute& rGradient,
+ attribute::FillGradientAttribute aGradient,
const Primitive3DContainer& rChildren,
const basegfx::B2DVector& rTextureSize,
bool bModulate,
bool bFilter)
: TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
- maGradient(rGradient)
+ maGradient(std::move(aGradient))
{
}
diff --git a/drawinglayer/source/primitive3d/transformprimitive3d.cxx b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
index 1ddb919bf2e1..135cba2c55ab 100644
--- a/drawinglayer/source/primitive3d/transformprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
@@ -19,18 +19,16 @@
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::primitive3d
{
TransformPrimitive3D::TransformPrimitive3D(
- const basegfx::B3DHomMatrix& rTransformation,
+ basegfx::B3DHomMatrix aTransformation,
const Primitive3DContainer& rChildren)
: GroupPrimitive3D(rChildren),
- maTransformation(rTransformation)
+ maTransformation(std::move(aTransformation))
{
}
diff --git a/drawinglayer/source/processor2d/SDPRProcessor2dTools.cxx b/drawinglayer/source/processor2d/SDPRProcessor2dTools.cxx
new file mode 100644
index 000000000000..58f961e2060b
--- /dev/null
+++ b/drawinglayer/source/processor2d/SDPRProcessor2dTools.cxx
@@ -0,0 +1,302 @@
+/* -*- 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 <drawinglayer/processor2d/SDPRProcessor2dTools.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/graph.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
+#include <tools/stream.hxx>
+#include <vcl/filter/PngImageWriter.hxx>
+#endif
+
+namespace drawinglayer::processor2d
+{
+void setOffsetXYCreatedBitmap(
+ drawinglayer::primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D,
+ const Bitmap& rBitmap)
+{
+ rFillGraphicPrimitive2D.impSetOffsetXYCreatedBitmap(rBitmap);
+}
+
+void takeCareOfOffsetXY(
+ const drawinglayer::primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D,
+ Bitmap& rTarget, basegfx::B2DRange& rFillUnitRange)
+{
+ const attribute::FillGraphicAttribute& rFillGraphicAttribute(
+ rFillGraphicPrimitive2D.getFillGraphic());
+ const bool bOffsetXIsUsed(rFillGraphicAttribute.getOffsetX() > 0.0
+ && rFillGraphicAttribute.getOffsetX() < 1.0);
+ const bool bOffsetYIsUsed(rFillGraphicAttribute.getOffsetY() > 0.0
+ && rFillGraphicAttribute.getOffsetY() < 1.0);
+
+ if (bOffsetXIsUsed)
+ {
+ if (rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap().IsEmpty())
+ {
+ const Size aSize(rTarget.GetSizePixel());
+ const tools::Long w(aSize.Width());
+ const tools::Long a(
+ basegfx::fround<tools::Long>(w * (1.0 - rFillGraphicAttribute.getOffsetX())));
+
+ if (0 != a && w != a)
+ {
+ const tools::Long h(aSize.Height());
+ const tools::Long b(w - a);
+ Bitmap aTarget(Size(w, h * 2), rTarget.getPixelFormat());
+
+ aTarget.SetPrefSize(
+ Size(rTarget.GetPrefSize().Width(), rTarget.GetPrefSize().Height() * 2));
+ const tools::Rectangle aSrcDst(Point(), aSize);
+ aTarget.CopyPixel(aSrcDst, // Dst
+ aSrcDst, // Src
+ rTarget);
+ const Size aSizeA(b, h);
+ aTarget.CopyPixel(tools::Rectangle(Point(0, h), aSizeA), // Dst
+ tools::Rectangle(Point(a, 0), aSizeA), // Src
+ rTarget);
+ const Size aSizeB(a, h);
+ aTarget.CopyPixel(tools::Rectangle(Point(b, h), aSizeB), // Dst
+ tools::Rectangle(Point(), aSizeB), // Src
+ rTarget);
+
+ setOffsetXYCreatedBitmap(
+ const_cast<drawinglayer::primitive2d::FillGraphicPrimitive2D&>(
+ rFillGraphicPrimitive2D),
+ aTarget);
+ }
+ }
+
+ if (!rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap().IsEmpty())
+ {
+ rTarget = rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap();
+ rFillUnitRange.expand(basegfx::B2DPoint(
+ rFillUnitRange.getMinX(), rFillUnitRange.getMaxY() + rFillUnitRange.getHeight()));
+ }
+ }
+ else if (bOffsetYIsUsed)
+ {
+ if (rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap().IsEmpty())
+ {
+ const Size aSize(rTarget.GetSizePixel());
+ const tools::Long h(aSize.Height());
+ const tools::Long a(
+ basegfx::fround<tools::Long>(h * (1.0 - rFillGraphicAttribute.getOffsetY())));
+
+ if (0 != a && h != a)
+ {
+ const tools::Long w(aSize.Width());
+ const tools::Long b(h - a);
+ Bitmap aTarget(Size(w * 2, h), rTarget.getPixelFormat());
+
+ aTarget.SetPrefSize(
+ Size(rTarget.GetPrefSize().Width() * 2, rTarget.GetPrefSize().Height()));
+ const tools::Rectangle aSrcDst(Point(), aSize);
+ aTarget.CopyPixel(aSrcDst, // Dst
+ aSrcDst, // Src
+ rTarget);
+ const Size aSizeA(w, b);
+ aTarget.CopyPixel(tools::Rectangle(Point(w, 0), aSizeA), // Dst
+ tools::Rectangle(Point(0, a), aSizeA), // Src
+ rTarget);
+ const Size aSizeB(w, a);
+ aTarget.CopyPixel(tools::Rectangle(Point(w, b), aSizeB), // Dst
+ tools::Rectangle(Point(), aSizeB), // Src
+ rTarget);
+
+ setOffsetXYCreatedBitmap(
+ const_cast<drawinglayer::primitive2d::FillGraphicPrimitive2D&>(
+ rFillGraphicPrimitive2D),
+ aTarget);
+ }
+ }
+
+ if (!rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap().IsEmpty())
+ {
+ rTarget = rFillGraphicPrimitive2D.getOffsetXYCreatedBitmap();
+ rFillUnitRange.expand(basegfx::B2DPoint(
+ rFillUnitRange.getMaxX() + rFillUnitRange.getWidth(), rFillUnitRange.getMinY()));
+ }
+ }
+}
+
+bool prepareBitmapForDirectRender(
+ const drawinglayer::primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D, Bitmap& rTarget,
+ basegfx::B2DRange& rFillUnitRange, double fBigDiscreteArea)
+{
+ const attribute::FillGraphicAttribute& rFillGraphicAttribute(
+ rFillGraphicPrimitive2D.getFillGraphic());
+ const Graphic& rGraphic(rFillGraphicAttribute.getGraphic());
+
+ if (rFillGraphicAttribute.isDefault() || rGraphic.IsNone())
+ {
+ // default attributes or GraphicType::NONE, so no fill .-> done
+ return false;
+ }
+
+ if (!rFillGraphicAttribute.getTiling())
+ {
+ // If no tiling used, the Graphic will need to be painted just once. This
+ // is perfectly done using the decomposition, so use it.
+ // What we want to do here is to optimize tiled paint, for two reasons:
+ // (a) speed: draw one tile, repeat -> obvious
+ // (b) correctness: not so obvious, but since in AAed paint the same edge
+ // of touching polygons both AAed do *not* sum up, but get blended by
+ // multiplication (0.5 * 0.5 -> 0.25) the connection will stay visible,
+ // not only with filled polygons, but also with bitmaps
+ // Signal that paint is needed
+ return true;
+ }
+
+ if (rFillUnitRange.isEmpty())
+ {
+ // no fill range definition, no fill, done
+ return false;
+ }
+
+ const basegfx::B2DHomMatrix aLocalTransform(rViewInformation2D.getObjectToViewTransformation()
+ * rFillGraphicPrimitive2D.getTransformation());
+ const basegfx::B2DRange& rDiscreteViewPort(rViewInformation2D.getDiscreteViewport());
+
+ if (!rDiscreteViewPort.isEmpty())
+ {
+ // calculate discrete covered pixel area
+ basegfx::B2DRange aDiscreteRange(basegfx::B2DRange::getUnitB2DRange());
+ aDiscreteRange.transform(aLocalTransform);
+
+ if (!aDiscreteRange.overlaps(rDiscreteViewPort))
+ {
+ // we have a Viewport and visible range of geometry is outside -> not visible, done
+ return false;
+ }
+ }
+
+ if (GraphicType::Bitmap == rGraphic.GetType() && rGraphic.IsAnimated())
+ {
+ // Need to prepare specialized AnimatedGraphicPrimitive2D,
+ // cannot handle here. Signal that paint is needed
+ return true;
+ }
+
+ if (GraphicType::Bitmap == rGraphic.GetType() && !rGraphic.getVectorGraphicData())
+ {
+ // bitmap graphic, always handle locally, so get bitmap data independent
+ // if it'sie or it's discrete display size
+ rTarget = rGraphic.GetBitmap();
+ }
+ else
+ {
+ // Vector Graphic Data fill, including metafile:
+ // We can know about discrete pixel size here, calculate and use it.
+ // To do so, using Vectors is sufficient to get the lengths. It is
+ // not necessary to transform the whole target coordinate system.
+ const basegfx::B2DVector aDiscreteXAxis(
+ aLocalTransform
+ * basegfx::B2DVector(rFillUnitRange.getMaxX() - rFillUnitRange.getMinX(), 0.0));
+ const basegfx::B2DVector aDiscreteYAxis(
+ aLocalTransform
+ * basegfx::B2DVector(0.0, rFillUnitRange.getMaxY() - rFillUnitRange.getMinY()));
+
+ // get and ensure minimal size
+ const double fDiscreteWidth(std::max(1.0, aDiscreteXAxis.getLength()));
+ const double fDiscreteHeight(std::max(1.0, aDiscreteYAxis.getLength()));
+
+ // compare with a big visualization size in discrete pixels
+ const double fTargetDiscreteArea(fDiscreteWidth * fDiscreteHeight);
+
+ if (fTargetDiscreteArea > fBigDiscreteArea)
+ {
+ // When the vector data is visualized big it is better to not handle here
+ // but use decomposition fallback which then will visualize the vector data
+ // directly -> better quality, acceptable number of tile repeat(s)
+ // signal that paint is needed
+ return true;
+ }
+ else
+ {
+ // If visualized small, the amount of repeated fills gets expensive, so
+ // in that case use a Bitmap and the Brush technique below.
+ // The Bitmap may be created here exactly for the needed target size
+ // (using local D2DBitmapPixelProcessor2D and the vector data),
+ // but since we have a HW renderer and re-use of system-dependent data
+ // at Bitmap is possible, just get the default fallback Bitmap from the
+ // vector data to continue. Trust the existing converters for now to
+ // do something with good quality.
+ rTarget = rGraphic.GetBitmap();
+ }
+ }
+
+ if (rTarget.IsEmpty() || rTarget.GetSizePixel().IsEmpty())
+ {
+ // no pixel data, done
+ return false;
+ }
+
+ // react if OffsetX/OffsetY of the FillGraphicAttribute is used
+ takeCareOfOffsetXY(rFillGraphicPrimitive2D, rTarget, rFillUnitRange);
+
+#ifdef DBG_UTIL
+ // allow to check bitmap data, e.g. control OffsetX/OffsetY stuff
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ if (bDoSaveForVisualControl)
+ {
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
+ {
+ SvFileStream aNew(sDumpPath + "test_getreplacement.png",
+ StreamMode::WRITE | StreamMode::TRUNC);
+ vcl::PngImageWriter aPNGWriter(aNew);
+ aPNGWriter.write(rTarget);
+ }
+ }
+#endif
+
+ // signal to render it
+ return true;
+}
+
+void calculateDiscreteVisibleRange(
+ basegfx::B2DRange& rDiscreteVisibleRange, const basegfx::B2DRange& rContentRange,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
+{
+ if (rContentRange.isEmpty())
+ {
+ // no content, done
+ rDiscreteVisibleRange.reset();
+ return;
+ }
+
+ basegfx::B2DRange aDiscreteRange(rContentRange);
+ aDiscreteRange.transform(rViewInformation2D.getObjectToViewTransformation());
+ const basegfx::B2DRange& rDiscreteViewPort(rViewInformation2D.getDiscreteViewport());
+ rDiscreteVisibleRange = aDiscreteRange;
+
+ if (!rDiscreteViewPort.isEmpty())
+ {
+ rDiscreteVisibleRange.intersect(rDiscreteViewPort);
+ }
+}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/baseprocessor2d.cxx b/drawinglayer/source/processor2d/baseprocessor2d.cxx
index 9d1671dcf959..5d71ab4fd7f7 100644
--- a/drawinglayer/source/processor2d/baseprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/baseprocessor2d.cxx
@@ -17,11 +17,9 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
-#include <comphelper/sequence.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::processor2d
@@ -30,8 +28,8 @@ namespace drawinglayer::processor2d
{
}
- BaseProcessor2D::BaseProcessor2D(const geometry::ViewInformation2D& rViewInformation)
- : maViewInformation2D(rViewInformation)
+ BaseProcessor2D::BaseProcessor2D(geometry::ViewInformation2D aViewInformation)
+ : maViewInformation2D(std::move(aViewInformation))
{
}
@@ -41,43 +39,46 @@ namespace drawinglayer::processor2d
void BaseProcessor2D::process(const primitive2d::BasePrimitive2D& rCandidate)
{
- primitive2d::Primitive2DContainer aContainer;
- rCandidate.get2DDecomposition(aContainer, getViewInformation2D());
- process(aContainer);
+ // use the visitor API to avoid the cost of constructing Primitive2DContainers
+ rCandidate.get2DDecomposition(*this, getViewInformation2D());
}
- void BaseProcessor2D::process(const primitive2d::Primitive2DContainer& rSource)
+ // Primitive2DDecompositionVisitor
+ void BaseProcessor2D::visit(const primitive2d::Primitive2DReference& rCandidate)
{
- if(rSource.empty())
- return;
-
- const sal_Int32 nCount(rSource.size());
+ if (rCandidate)
+ processBasePrimitive2D(*rCandidate);
+ }
+ void BaseProcessor2D::visit(const primitive2d::Primitive2DContainer& rContainer)
+ {
+ process(rContainer);
+ }
+ void BaseProcessor2D::visit(primitive2d::Primitive2DContainer&& rCandidate)
+ {
+ process(rCandidate);
+ }
- for(sal_Int32 a(0); a < nCount; a++)
+ void BaseProcessor2D::process(const primitive2d::Primitive2DContainer& rSource)
+ {
+ for (const primitive2d::Primitive2DReference& rCandidate : rSource)
{
- // get reference
- const primitive2d::Primitive2DReference xReference(rSource[a]);
+ // Skip, if not visible
+ if (rCandidate && rCandidate->getVisible())
+ processBasePrimitive2D(*rCandidate);
+ }
+ }
- if(xReference.is())
- {
- // try to cast to BasePrimitive2D implementation
- const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
+ void BaseProcessor2D::setViewInformation2D(const geometry::ViewInformation2D& rNew)
+ {
+ if (rNew != maViewInformation2D)
+ {
+ // set if changed
+ maViewInformation2D = rNew;
- if(pBasePrimitive)
- {
- // it is a BasePrimitive2D implementation, use local processor
- processBasePrimitive2D(*pBasePrimitive);
- }
- else
- {
- // unknown implementation, use UNO API call instead and process recursively
- const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation2D().getViewInformationSequence());
- process(comphelper::sequenceToContainer<primitive2d::Primitive2DContainer>(xReference->getDecomposition(rViewParameters)));
- }
- }
+ // allow reaction on change
+ onViewInformation2DChanged();
}
}
-
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
new file mode 100644
index 000000000000..c54a223c1e5c
--- /dev/null
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -0,0 +1,4584 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#include <sal/config.h>
+
+#include <drawinglayer/processor2d/cairopixelprocessor2d.hxx>
+#include <drawinglayer/processor2d/SDPRProcessor2dTools.hxx>
+#include <sal/log.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <vcl/BitmapWriteAccess.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/cairo.hxx>
+#include <vcl/CairoFormats.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/lok.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/Tools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/invertprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <drawinglayer/converters.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/utils/systemdependentdata.hxx>
+#include <basegfx/utils/bgradient.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/vcllayout.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <com/sun/star/awt/XView.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <unordered_map>
+#include <dlfcn.h>
+
+using namespace com::sun::star;
+
+namespace
+{
+void impl_cairo_set_hairline(cairo_t* pRT,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation,
+ bool bCairoCoordinateLimitWorkaroundActive)
+{
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0)
+ void* addr(dlsym(nullptr, "cairo_set_hairline"));
+ if (nullptr != addr)
+ {
+ cairo_set_hairline(pRT, true);
+ return;
+ }
+#endif
+ if (bCairoCoordinateLimitWorkaroundActive)
+ {
+ // we have to render in view coordinates, set line width to 1.0
+ cairo_set_line_width(pRT, 1.0);
+ }
+ else
+ {
+ // avoid cairo_device_to_user_distance, see note on that below
+ const double fPx(
+ (rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0))
+ .getLength());
+ cairo_set_line_width(pRT, fPx);
+ }
+}
+
+void addB2DPolygonToPathGeometry(cairo_t* pRT, const basegfx::B2DPolygon& rPolygon)
+{
+ const sal_uInt32 nPointCount(rPolygon.count());
+
+ if (0 == nPointCount)
+ // no points, done
+ return;
+
+ // get basic infos
+ const bool bClosed(rPolygon.isClosed());
+ const sal_uInt32 nEdgeCount(bClosed ? nPointCount : nPointCount - 1);
+
+ // get 1st point and move to it
+ basegfx::B2DPoint aCurrent(rPolygon.getB2DPoint(0));
+ cairo_move_to(pRT, aCurrent.getX(), aCurrent.getY());
+
+ for (sal_uInt32 nIndex(0); nIndex < nEdgeCount; nIndex++)
+ {
+ // get index for and next point
+ const sal_uInt32 nNextIndex((nIndex + 1) % nPointCount);
+ const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
+
+ // get and check curve stuff
+ basegfx::B2DPoint aCP1(rPolygon.getNextControlPoint(nIndex));
+ basegfx::B2DPoint aCP2(rPolygon.getPrevControlPoint(nNextIndex));
+ const bool bCP1Equal(aCP1.equal(aCurrent));
+ const bool bCP2Equal(aCP2.equal(aNext));
+
+ if (!bCP1Equal || !bCP2Equal)
+ {
+ // tdf#99165, see other similar changes for more info
+ if (bCP1Equal)
+ aCP1 = aCurrent + ((aCP2 - aCurrent) * 0.0005);
+
+ if (bCP2Equal)
+ aCP2 = aNext + ((aCP1 - aNext) * 0.0005);
+
+ cairo_curve_to(pRT, aCP1.getX(), aCP1.getY(), aCP2.getX(), aCP2.getY(), aNext.getX(),
+ aNext.getY());
+ }
+ else
+ {
+ cairo_line_to(pRT, aNext.getX(), aNext.getY());
+ }
+
+ // prepare next step
+ aCurrent = aNext;
+ }
+
+ if (bClosed)
+ cairo_close_path(pRT);
+}
+
+// needed as helper, see below. It guarantees clean
+// construction/cleanup using destructor
+// NOTE: maybe mpSurface can be constructed even simpler,
+// not sure about that. It is only used to construct
+// and hold path data
+struct CairoContextHolder
+{
+ cairo_surface_t* mpSurface;
+ cairo_t* mpRenderContext;
+
+ CairoContextHolder()
+ : mpSurface(cairo_image_surface_create(CAIRO_FORMAT_A1, 1, 1))
+ , mpRenderContext(cairo_create(mpSurface))
+ {
+ }
+
+ ~CairoContextHolder()
+ {
+ cairo_destroy(mpRenderContext);
+ cairo_surface_destroy(mpSurface);
+ }
+
+ cairo_t* getContext() const { return mpRenderContext; }
+};
+
+// global static helper instance
+CairoContextHolder globalStaticCairoContext;
+
+// it shows that re-using and buffering path geometry data using
+// cairo is more complicated than initially thought: when adding
+// a path to a cairo_t render context it already *uses* the set
+// transformation, also usually consumes the path when painting.
+// The (only available) method cairo_copy_path to preserve that
+// data *also* transforms the path - if not already created in
+// transformed form - using the current transformation set at the
+// cairo context.
+// This is not what we want to have a re-usable path that is
+// buffered at the Poly(poly)gon: we explicitly want *exactly*
+// the coordinates in the polygon preserved *at* the polygon to
+// be able to re-use that data independent from any set
+// transformation at any cairo context.
+// Thus, create paths using a helper (CairoPathHelper) using a
+// helper cairo context (CairoContextHolder) that never gets
+// transformed. This removes the need to feed it the cairo context,
+// but also does not immediately add the path data to the target
+// context, that needs to be done using cairo_append_path at the
+// target cairo context. That works since all geometry is designed
+// to use exactly that coordinate system the polygon is already
+// designed for anyways, and it transforms as needed inside the
+// target cairo context as needed (if transform is set)
+class CairoPathHelper
+{
+ // the created CairoPath
+ cairo_path_t* mpCairoPath;
+
+public:
+ CairoPathHelper(const basegfx::B2DPolygon& rPolygon)
+ : mpCairoPath(nullptr)
+ {
+ cairo_new_path(globalStaticCairoContext.getContext());
+ addB2DPolygonToPathGeometry(globalStaticCairoContext.getContext(), rPolygon);
+ mpCairoPath = cairo_copy_path(globalStaticCairoContext.getContext());
+ }
+
+ CairoPathHelper(const basegfx::B2DPolyPolygon& rPolyPolygon)
+ : mpCairoPath(nullptr)
+ {
+ cairo_new_path(globalStaticCairoContext.getContext());
+ for (const auto& rPolygon : rPolyPolygon)
+ addB2DPolygonToPathGeometry(globalStaticCairoContext.getContext(), rPolygon);
+ mpCairoPath = cairo_copy_path(globalStaticCairoContext.getContext());
+ }
+
+ ~CairoPathHelper()
+ {
+ // need to cleanup instance
+ cairo_path_destroy(mpCairoPath);
+ }
+
+ // read access
+ cairo_path_t* getCairoPath() const { return mpCairoPath; }
+
+ sal_Int64 getEstimatedSize() const
+ {
+ if (nullptr == mpCairoPath)
+ return 0;
+
+ // per node:
+ // - num_data incarnations of
+ // - sizeof(cairo_path_data_t) which is a union of defines and point data
+ // thus may 2 x sizeof(double)
+ return mpCairoPath->num_data * sizeof(cairo_path_data_t);
+ }
+};
+
+class SystemDependentData_CairoPathGeometry : public basegfx::SystemDependentData
+{
+ // the CairoPath holder
+ std::shared_ptr<CairoPathHelper> mpCairoPathHelper;
+
+public:
+ SystemDependentData_CairoPathGeometry(const std::shared_ptr<CairoPathHelper>& pCairoPathHelper)
+ : basegfx::SystemDependentData(Application::GetSystemDependentDataManager(),
+ basegfx::SDD_Type::SDDType_CairoPathGeometry)
+ , mpCairoPathHelper(pCairoPathHelper)
+ {
+ }
+
+ // read access
+ const std::shared_ptr<CairoPathHelper>& getCairoPathHelper() const { return mpCairoPathHelper; }
+
+ virtual sal_Int64 estimateUsageInBytes() const override
+ {
+ return (nullptr != mpCairoPathHelper) ? mpCairoPathHelper->getEstimatedSize() : 0;
+ }
+};
+
+constexpr unsigned long nMinimalPointsPath(4);
+constexpr unsigned long nMinimalPointsFill(12);
+
+void checkAndDoPixelSnap(cairo_t* pRT,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation)
+{
+ const bool bPixelSnap(rViewInformation.getPixelSnapHairline()
+ && rViewInformation.getUseAntiAliasing());
+
+ if (!bPixelSnap)
+ // no pixel snap, done
+ return;
+
+ // with the comments above at CairoPathHelper we cannot do PixelSnap
+ // at path construction time, so it needs to be done *after* the path
+ // data is added to the cairo context. Advantage is that all general
+ // path data can be buffered, though, but needs view-dependent manipulation
+ // here after being added.
+ // For now, just snap all points - no real need to identify hor/ver lines
+ // when you think about it
+
+ // get helper path
+ cairo_path_t* path(cairo_copy_path(pRT));
+
+ if (0 == path->num_data)
+ {
+ // path is empty, done
+ cairo_path_destroy(path);
+ return;
+ }
+
+ auto doPixelSnap([&pRT](double& rX, double& rY) {
+ // transform to discrete pixels
+ cairo_user_to_device(pRT, &rX, &rY);
+
+ // round them, also add 0.5 which will be as transform in
+ // the paint method to move to 'inside' pixels when AA used.
+ // remember: this is only done when AA is active (see bPixelSnap
+ // above) and moves the hairline to full-pixel position
+ rX = trunc(rX) + 0.5;
+ rY = trunc(rY) + 0.5;
+
+ // transform back to former transformed state
+ cairo_device_to_user(pRT, &rX, &rY);
+ });
+
+ for (int a(0); a < path->num_data; a += path->data[a].header.length)
+ {
+ cairo_path_data_t* data(&path->data[a]);
+
+ switch (data->header.type)
+ {
+ case CAIRO_PATH_CURVE_TO:
+ {
+ // curve: snap all three point positions,
+ // thus use fallthrough below
+ doPixelSnap(data[2].point.x, data[2].point.y);
+ doPixelSnap(data[3].point.x, data[3].point.y);
+ [[fallthrough]]; // break;
+ }
+ case CAIRO_PATH_MOVE_TO:
+ case CAIRO_PATH_LINE_TO:
+ {
+ // path/move: snap first point position
+ doPixelSnap(data[1].point.x, data[1].point.y);
+ break;
+ }
+ case CAIRO_PATH_CLOSE_PATH:
+ {
+ break;
+ }
+ }
+ }
+
+ // set changed path back at cairo context
+ cairo_new_path(pRT);
+ cairo_append_path(pRT, path);
+
+ // destroy helper path
+ cairo_path_destroy(path);
+}
+
+void getOrCreatePathGeometry(cairo_t* pRT, const basegfx::B2DPolygon& rPolygon,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation,
+ bool bPixelSnap)
+{
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_CairoPathGeometry> pSystemDependentData_CairoPathGeometry(
+ rPolygon.getSystemDependentData<SystemDependentData_CairoPathGeometry>(
+ basegfx::SDD_Type::SDDType_CairoPathGeometry));
+
+ if (pSystemDependentData_CairoPathGeometry)
+ {
+ // re-use data and do evtl. needed pixel snap after adding on cairo path data
+ cairo_append_path(
+ pRT, pSystemDependentData_CairoPathGeometry->getCairoPathHelper()->getCairoPath());
+ if (bPixelSnap)
+ checkAndDoPixelSnap(pRT, rViewInformation);
+ return;
+ }
+
+ // create new data and add path data to pRT and do evtl. needed pixel snap after adding on cairo path data
+ std::shared_ptr<CairoPathHelper> pCairoPathHelper(std::make_shared<CairoPathHelper>(rPolygon));
+ cairo_append_path(pRT, pCairoPathHelper->getCairoPath());
+ if (bPixelSnap)
+ checkAndDoPixelSnap(pRT, rViewInformation);
+
+ // add to buffering mechanism if not trivial
+ if (rPolygon.count() > nMinimalPointsPath)
+ rPolygon.addOrReplaceSystemDependentData<SystemDependentData_CairoPathGeometry>(
+ pCairoPathHelper);
+}
+
+void getOrCreateFillGeometry(cairo_t* pRT, const basegfx::B2DPolyPolygon& rPolyPolygon)
+{
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_CairoPathGeometry> pSystemDependentData_CairoPathGeometry(
+ rPolyPolygon.getSystemDependentData<SystemDependentData_CairoPathGeometry>(
+ basegfx::SDD_Type::SDDType_CairoPathGeometry));
+
+ if (pSystemDependentData_CairoPathGeometry)
+ {
+ // re-use data
+ cairo_append_path(
+ pRT, pSystemDependentData_CairoPathGeometry->getCairoPathHelper()->getCairoPath());
+ return;
+ }
+
+ // create new data and add path data to pRT
+ std::shared_ptr<CairoPathHelper> pCairoPathHelper(
+ std::make_shared<CairoPathHelper>(rPolyPolygon));
+ cairo_append_path(pRT, pCairoPathHelper->getCairoPath());
+
+ // get all PointCount to detect non-trivial
+ sal_uInt32 nAllPointCount(0);
+ for (const auto& rPolygon : rPolyPolygon)
+ nAllPointCount += rPolygon.count();
+
+ // add to buffering mechanism when no PixelSnapHairline (see above) and not trivial
+ if (nAllPointCount > nMinimalPointsFill)
+ rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_CairoPathGeometry>(
+ pCairoPathHelper);
+}
+
+// check for env var that decides for using downscale pattern
+const char* pDisableDownScale(getenv("SAL_DISABLE_CAIRO_DOWNSCALE"));
+const bool bDisableDownScale(nullptr != pDisableDownScale);
+constexpr unsigned long nMinimalDiscreteSize(15);
+constexpr unsigned long nHalfMDSize((nMinimalDiscreteSize + 1) / 2);
+constexpr unsigned long
+nMinimalDiscreteSquareSizeToBuffer(nMinimalDiscreteSize* nMinimalDiscreteSize);
+
+class CairoSurfaceHelper
+{
+ // the buffered CairoSurface (bitmap data)
+ cairo_surface_t* mpCairoSurface;
+
+ // evtl. MipMapped data (pre-scale to reduce data processing load)
+ mutable std::unordered_map<sal_uInt64, cairo_surface_t*> maDownscaled;
+
+ // create 32bit RGBA data for given Bitmap
+ void createRGBA(const Bitmap& rBitmap)
+ {
+ BitmapScopedReadAccess pReadAccess(rBitmap);
+ const tools::Long nHeight(pReadAccess->Height());
+ const tools::Long nWidth(pReadAccess->Width());
+ mpCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
+ if (cairo_surface_status(mpCairoSurface) != CAIRO_STATUS_SUCCESS)
+ {
+ SAL_WARN("drawinglayer",
+ "cairo_image_surface_create failed for: " << nWidth << " x " << nHeight);
+ return;
+ }
+ const sal_uInt32 nStride(cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nWidth));
+ unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface));
+
+ for (tools::Long y(0); y < nHeight; ++y)
+ {
+ unsigned char* pPixelData(surfaceData + (nStride * y));
+
+ for (tools::Long x(0); x < nWidth; ++x)
+ {
+ const BitmapColor aColor(pReadAccess->GetColor(y, x));
+ const sal_uInt16 nAlpha(aColor.GetAlpha());
+
+ pPixelData[SVP_CAIRO_RED] = vcl::bitmap::premultiply(aColor.GetRed(), nAlpha);
+ pPixelData[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(aColor.GetGreen(), nAlpha);
+ pPixelData[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(aColor.GetBlue(), nAlpha);
+ pPixelData[SVP_CAIRO_ALPHA] = nAlpha;
+ pPixelData += 4;
+ }
+ }
+
+ cairo_surface_mark_dirty(mpCairoSurface);
+ }
+
+ // create 32bit RGB data for given Bitmap
+ void createRGB(const Bitmap& rBitmap)
+ {
+ BitmapScopedReadAccess pReadAccess(rBitmap);
+ const tools::Long nHeight(pReadAccess->Height());
+ const tools::Long nWidth(pReadAccess->Width());
+ mpCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, nWidth, nHeight);
+ if (cairo_surface_status(mpCairoSurface) != CAIRO_STATUS_SUCCESS)
+ {
+ SAL_WARN("drawinglayer",
+ "cairo_image_surface_create failed for: " << nWidth << " x " << nHeight);
+ return;
+ }
+ sal_uInt32 nStride(cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, nWidth));
+ unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface));
+
+ for (tools::Long y(0); y < nHeight; ++y)
+ {
+ unsigned char* pPixelData(surfaceData + (nStride * y));
+
+ for (tools::Long x(0); x < nWidth; ++x)
+ {
+ const BitmapColor aColor(pReadAccess->GetColor(y, x));
+
+ pPixelData[SVP_CAIRO_RED] = aColor.GetRed();
+ pPixelData[SVP_CAIRO_GREEN] = aColor.GetGreen();
+ pPixelData[SVP_CAIRO_BLUE] = aColor.GetBlue();
+ pPixelData[SVP_CAIRO_ALPHA] = 255; // not really needed
+ pPixelData += 4;
+ }
+ }
+
+ cairo_surface_mark_dirty(mpCairoSurface);
+ }
+
+// #define TEST_RGB16
+#ifdef TEST_RGB16
+ // experimental: create 16bit RGB data for given Bitmap
+ void createRGB16(const Bitmap& rBitmap)
+ {
+ BitmapScopedReadAccess pReadAccess(rBitmap);
+ const tools::Long nHeight(pReadAccess->Height());
+ const tools::Long nWidth(pReadAccess->Width());
+ mpCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB16_565, nWidth, nHeight);
+ if (cairo_surface_status(mpCairoSurface) != CAIRO_STATUS_SUCCESS)
+ {
+ SAL_WARN("drawinglayer",
+ "cairo_image_surface_create failed for: " << nWidth << " x " << nHeight);
+ return;
+ }
+ sal_uInt32 nStride(cairo_format_stride_for_width(CAIRO_FORMAT_RGB16_565, nWidth));
+ unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface));
+
+ for (tools::Long y(0); y < nHeight; ++y)
+ {
+ unsigned char* pPixelData(surfaceData + (nStride * y));
+
+ for (tools::Long x(0); x < nWidth; ++x)
+ {
+ const BitmapColor aColor(pReadAccess->GetColor(y, x));
+ const sal_uInt8 aLeft((aColor.GetBlue() >> 3) | ((aColor.GetGreen() << 3) & 0xe0));
+ const sal_uInt8 aRight((aColor.GetRed() & 0xf8) | (aColor.GetGreen() >> 5));
+#ifdef OSL_BIGENDIAN
+ pPixelData[1] = aRight;
+ pPixelData[0] = aLeft;
+#else
+ pPixelData[0] = aLeft;
+ pPixelData[1] = aRight;
+#endif
+ pPixelData += 2;
+ }
+ }
+
+ cairo_surface_mark_dirty(mpCairoSurface);
+ }
+#endif
+
+public:
+ CairoSurfaceHelper(const Bitmap& rBitmap)
+ : mpCairoSurface(nullptr)
+ , maDownscaled()
+ {
+ if (rBitmap.HasAlpha())
+ createRGBA(rBitmap);
+ else
+#ifdef TEST_RGB16
+ createRGB16(rBitmap);
+#else
+ createRGB(rBitmap);
+#endif
+ }
+
+ ~CairoSurfaceHelper()
+ {
+ // cleanup surface
+ cairo_surface_destroy(mpCairoSurface);
+
+ // cleanup MipMap surfaces
+ for (auto& candidate : maDownscaled)
+ cairo_surface_destroy(candidate.second);
+ }
+
+ cairo_surface_t* getCairoSurface(sal_uInt32 nTargetWidth = 0,
+ sal_uInt32 nTargetHeight = 0) const
+ {
+ // in simple cases just return the single created surface
+ if (bDisableDownScale || nullptr == mpCairoSurface || 0 == nTargetWidth
+ || 0 == nTargetHeight)
+ return mpCairoSurface;
+
+ // get width/height of original surface
+ const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface));
+ const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface));
+
+ // zoomed in, need to stretch at paint, no pre-scale useful
+ if (nTargetWidth >= nSourceWidth || nTargetHeight >= nSourceHeight)
+ return mpCairoSurface;
+
+ // calculate downscale factor. Only use ONE factor to get the diagonal
+ // MipMap, NOT the full MipMap field in X/Y for uneven factors in both dimensions
+ sal_uInt32 nFactor(1);
+ sal_uInt32 nW((nSourceWidth + 1) / 2);
+ sal_uInt32 nH((nSourceHeight + 1) / 2);
+
+ while (nW > nTargetWidth && nW > nHalfMDSize && nH > nTargetHeight && nH > nHalfMDSize)
+ {
+ nW = (nW + 1) / 2;
+ nH = (nH + 1) / 2;
+ nFactor *= 2;
+ }
+
+ if (1 == nFactor)
+ {
+ // original size *is* best binary size, use it
+ return mpCairoSurface;
+ }
+
+ // go up one scale again
+ nW *= 2;
+ nH *= 2;
+
+ // bail out if the multiplication for the key would overflow
+ if (nW >= SAL_MAX_UINT32 || nH >= SAL_MAX_UINT32)
+ return mpCairoSurface;
+
+ // check if we have a downscaled version of required size
+ const sal_uInt64 key((nW * static_cast<sal_uInt64>(SAL_MAX_UINT32)) + nH);
+ auto isHit(maDownscaled.find(key));
+
+ // found -> return it
+ if (isHit != maDownscaled.end())
+ return isHit->second;
+
+ // create new surface in the targeted size
+ cairo_surface_t* pSurfaceTarget(cairo_surface_create_similar(
+ mpCairoSurface, cairo_surface_get_content(mpCairoSurface), nW, nH));
+
+ // made a version to scale self first with direct memory access.
+ // That worked well, but would've been hard to support
+ // CAIRO_FORMAT_A1 and similar (including bit shifting), so
+ // I decided to go with cairo itself - use CAIRO_FILTER_FAST or
+ // CAIRO_FILTER_GOOD though. Please modify as needed for
+ // performance/quality
+ cairo_t* cr = cairo_create(pSurfaceTarget);
+ const double fScaleX(static_cast<double>(nW) / static_cast<double>(nSourceWidth));
+ const double fScaleY(static_cast<double>(nH) / static_cast<double>(nSourceHeight));
+
+ cairo_scale(cr, fScaleX, fScaleY);
+ cairo_set_source_surface(cr, mpCairoSurface, 0.0, 0.0);
+ cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+
+ // NOTE: Took out, until now not really needed
+ // need to set device_scale for downscale surfaces to get
+ // them handled correctly
+ // cairo_surface_set_device_scale(pSurfaceTarget, fScaleX, fScaleY);
+
+ // add entry to cached entries
+ maDownscaled[key] = pSurfaceTarget;
+
+ return pSurfaceTarget;
+ }
+
+ bool isTrivial() const
+ {
+ if (nullptr == mpCairoSurface)
+ return true;
+
+ const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface));
+ const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface));
+
+ return nSourceWidth * nSourceHeight < nMinimalDiscreteSquareSizeToBuffer;
+ }
+};
+
+class SystemDependentData_CairoSurface : public basegfx::SystemDependentData
+{
+ // the CairoSurface holder
+ std::shared_ptr<CairoSurfaceHelper> mpCairoSurfaceHelper;
+
+public:
+ SystemDependentData_CairoSurface(const Bitmap& rBitmap)
+ : basegfx::SystemDependentData(Application::GetSystemDependentDataManager(),
+ basegfx::SDD_Type::SDDType_CairoSurface)
+ , mpCairoSurfaceHelper(std::make_shared<CairoSurfaceHelper>(rBitmap))
+ {
+ }
+
+ // read access
+ const std::shared_ptr<CairoSurfaceHelper>& getCairoSurfaceHelper() const
+ {
+ return mpCairoSurfaceHelper;
+ }
+
+ virtual sal_Int64 estimateUsageInBytes() const override;
+};
+
+sal_Int64 SystemDependentData_CairoSurface::estimateUsageInBytes() const
+{
+ sal_Int64 nRetval(0);
+
+ if (mpCairoSurfaceHelper)
+ {
+ cairo_surface_t* pSurface(mpCairoSurfaceHelper->getCairoSurface());
+ const tools::Long nStride(cairo_image_surface_get_stride(pSurface));
+ const tools::Long nHeight(cairo_image_surface_get_height(pSurface));
+
+ nRetval = nStride * nHeight;
+
+ // if we do downscale, size will grow by 1/4 + 1/16 + 1/32 + ...,
+ // rough estimation just multiplies by 1.25 .. 1.33, should be good enough
+ // for estimation of buffer survival time
+ if (!bDisableDownScale)
+ {
+ nRetval = (nRetval * 5) / 4;
+ }
+ }
+
+ return nRetval;
+}
+
+std::shared_ptr<CairoSurfaceHelper> getOrCreateCairoSurfaceHelper(const Bitmap& rBitmap)
+{
+ const basegfx::SystemDependentDataHolder* pHolder(rBitmap.accessSystemDependentDataHolder());
+ std::shared_ptr<SystemDependentData_CairoSurface> pSystemDependentData_CairoSurface;
+
+ if (nullptr != pHolder)
+ {
+ // try to access SystemDependentDataHolder and buffered data
+ pSystemDependentData_CairoSurface
+ = std::static_pointer_cast<SystemDependentData_CairoSurface>(
+ pHolder->getSystemDependentData(basegfx::SDD_Type::SDDType_CairoSurface));
+ }
+
+ if (!pSystemDependentData_CairoSurface)
+ {
+ // create new SystemDependentData_CairoSurface
+ pSystemDependentData_CairoSurface
+ = std::make_shared<SystemDependentData_CairoSurface>(rBitmap);
+
+ // only add if feasible
+ if (nullptr != pHolder
+ && !pSystemDependentData_CairoSurface->getCairoSurfaceHelper()->isTrivial()
+ && pSystemDependentData_CairoSurface->calculateCombinedHoldCyclesInSeconds() > 0)
+ {
+ basegfx::SystemDependentData_SharedPtr r2(pSystemDependentData_CairoSurface);
+ const_cast<basegfx::SystemDependentDataHolder*>(pHolder)
+ ->addOrReplaceSystemDependentData(r2);
+ }
+ }
+
+ return pSystemDependentData_CairoSurface->getCairoSurfaceHelper();
+}
+
+// This bit-tweaking looping is unpleasant and unfortunate
+void LuminanceToAlpha(cairo_surface_t* pMask)
+{
+ cairo_surface_flush(pMask);
+
+ const sal_uInt32 nWidth(cairo_image_surface_get_width(pMask));
+ const sal_uInt32 nHeight(cairo_image_surface_get_height(pMask));
+ const sal_uInt32 nStride(cairo_image_surface_get_stride(pMask));
+
+ if (0 == nWidth || 0 == nHeight)
+ return;
+
+ unsigned char* mask_surface_data(cairo_image_surface_get_data(pMask));
+
+ // change to unsigned 16bit and shifting. This is not much
+ // faster on modern processors due to nowadays good double/
+ // float HW, but may also be used on smaller HW (ARM, ...).
+ // Since source is sal_uInt8 integer using double (see version
+ // before) is not required numerically either.
+ // scaling values are now put to a 256 entry lookup for R, G and B
+ // thus 768 bytes, so no multiplications have to happen. The values
+ // used to create these are (54+183+18 == 255):
+ // sal_uInt16 nR(0.2125 * 256.0); // -> 54.4
+ // sal_uInt16 nG(0.7154 * 256.0); // -> 183.1424
+ // sal_uInt16 nB(0.0721 * 256.0); // -> 18.4576
+ // and the short loop (for nR, nG and nB resp.) like:
+ // for(unsigned short a(0); a < 256; a++)
+ // std::cout << ((a * nR) / 255) << ", ";
+ static constexpr std::array<sal_uInt8, 256> nRArray
+ = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+ 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9,
+ 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18,
+ 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 23,
+ 23, 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 26, 27, 27, 27, 27,
+ 27, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32,
+ 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37,
+ 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41,
+ 41, 42, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 46, 46,
+ 46, 46, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 51,
+ 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 54 };
+ static constexpr std::array<sal_uInt8, 256> nGArray
+ = { 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10,
+ 11, 12, 12, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22,
+ 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 33,
+ 34, 35, 35, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45,
+ 45, 46, 47, 48, 48, 49, 50, 50, 51, 52, 53, 53, 54, 55, 55, 56,
+ 57, 58, 58, 59, 60, 61, 61, 62, 63, 63, 64, 65, 66, 66, 67, 68,
+ 68, 69, 70, 71, 71, 72, 73, 73, 74, 75, 76, 76, 77, 78, 78, 79,
+ 80, 81, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 88, 89, 90, 91,
+ 91, 92, 93, 94, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 101, 102,
+ 103, 104, 104, 105, 106, 106, 107, 108, 109, 109, 110, 111, 111, 112, 113, 114,
+ 114, 115, 116, 116, 117, 118, 119, 119, 120, 121, 122, 122, 123, 124, 124, 125,
+ 126, 127, 127, 128, 129, 129, 130, 131, 132, 132, 133, 134, 134, 135, 136, 137,
+ 137, 138, 139, 139, 140, 141, 142, 142, 143, 144, 144, 145, 146, 147, 147, 148,
+ 149, 149, 150, 151, 152, 152, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160,
+ 160, 161, 162, 162, 163, 164, 165, 165, 166, 167, 167, 168, 169, 170, 170, 171,
+ 172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 180, 180, 181, 182, 183 };
+ static constexpr std::array<sal_uInt8, 256> nBArray
+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18 };
+
+ for (sal_uInt32 y(0); y < nHeight; ++y)
+ {
+ unsigned char* pMaskPixelData = mask_surface_data + (nStride * y);
+
+ for (sal_uInt32 x(0); x < nWidth; ++x)
+ {
+ // do not forget that we have pre-multiplied alpha
+ sal_uInt8 nAlpha(pMaskPixelData[SVP_CAIRO_ALPHA]);
+
+ if (0 != nAlpha)
+ {
+ // get Luminance in range [0..255]
+ const sal_uInt8 nLum(nRArray[pMaskPixelData[SVP_CAIRO_RED]]
+ + nGArray[pMaskPixelData[SVP_CAIRO_GREEN]]
+ + nBArray[pMaskPixelData[SVP_CAIRO_BLUE]]);
+
+ if (255 != nAlpha)
+ // remove pre-multiplied alpha (use existing VCL tooling)
+ nAlpha = vcl::bitmap::unpremultiply(nLum, nAlpha);
+ else
+ // already what we need
+ nAlpha = nLum;
+
+ pMaskPixelData[SVP_CAIRO_ALPHA] = 255 - nAlpha;
+ }
+
+ pMaskPixelData += 4;
+ }
+ }
+
+ cairo_surface_mark_dirty(pMask);
+}
+
+basegfx::B2DRange getDiscreteViewRange(cairo_t* pRT)
+{
+ double clip_x1, clip_x2, clip_y1, clip_y2;
+ cairo_save(pRT);
+ cairo_identity_matrix(pRT);
+ cairo_clip_extents(pRT, &clip_x1, &clip_y1, &clip_x2, &clip_y2);
+ cairo_restore(pRT);
+
+ return basegfx::B2DRange(basegfx::B2DPoint(clip_x1, clip_y1),
+ basegfx::B2DPoint(clip_x2, clip_y2));
+}
+
+bool checkCoordinateLimitWorkaroundNeededForUsedCairo()
+{
+ // setup surface and render context
+ cairo_surface_t* pSurface(cairo_image_surface_create(CAIRO_FORMAT_RGB24, 8, 8));
+ if (!pSurface)
+ {
+ SAL_INFO(
+ "drawinglayer",
+ "checkCoordinateLimitWorkaroundNeededForUsedCairo: got no surface -> be pessimistic");
+ return true;
+ }
+
+ cairo_t* pRender(cairo_create(pSurface));
+ if (!pRender)
+ {
+ SAL_INFO(
+ "drawinglayer",
+ "checkCoordinateLimitWorkaroundNeededForUsedCairo: got no render -> be pessimistic");
+ cairo_surface_destroy(pSurface);
+ return true;
+ }
+
+ // set basic values
+ cairo_set_antialias(pRender, CAIRO_ANTIALIAS_NONE);
+ cairo_set_fill_rule(pRender, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_operator(pRender, CAIRO_OPERATOR_OVER);
+ cairo_set_source_rgb(pRender, 1.0, 0.0, 0.0);
+
+ // create a to-be rendered area centered at the fNumCairoMax
+ // spot and 8x8 discrete units in size
+ constexpr double fNumCairoMax(1 << 23);
+ const basegfx::B2DPoint aCenter(fNumCairoMax, fNumCairoMax);
+ const basegfx::B2DPoint aOffset(4, 4);
+ const basegfx::B2DRange aObject(aCenter - aOffset, aCenter + aOffset);
+
+ // create transformation to render that to an area with
+ // range(0, 0, 8, 8) and set as transformation
+ const basegfx::B2DHomMatrix aObjectToView(basegfx::utils::createSourceRangeTargetRangeTransform(
+ aObject, basegfx::B2DRange(0, 0, 8, 8)));
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aObjectToView.a(), aObjectToView.b(), aObjectToView.c(),
+ aObjectToView.d(), aObjectToView.e(), aObjectToView.f());
+ cairo_set_matrix(pRender, &aMatrix);
+
+ // get/create the path for an object exactly filling that area
+ cairo_new_path(pRender);
+ basegfx::B2DPolyPolygon aObjectPolygon(basegfx::utils::createPolygonFromRect(aObject));
+ CairoPathHelper aPathHelper(aObjectPolygon);
+ cairo_append_path(pRender, aPathHelper.getCairoPath());
+
+ // render it and flush since we want to immediately inspect result
+ cairo_fill(pRender);
+ cairo_surface_flush(pSurface);
+
+ // get access to pixel data
+ const sal_uInt32 nStride(cairo_image_surface_get_stride(pSurface));
+ sal_uInt8* pStartPixelData(cairo_image_surface_get_data(pSurface));
+
+ // extract red value for pixels at (1,1) and (7,7)
+ sal_uInt8 aRedAt_1_1((pStartPixelData + (nStride * 1) + 1)[SVP_CAIRO_RED]);
+ sal_uInt8 aRedAt_6_6((pStartPixelData + (nStride * 6) + 6)[SVP_CAIRO_RED]);
+
+ // cleanup
+ cairo_destroy(pRender);
+ cairo_surface_destroy(pSurface);
+
+ // if cairo works or has no 24.8 internal format all pixels
+ // have to be red (255), thus workaround is needed if !=
+ auto const needed = aRedAt_1_1 != aRedAt_6_6;
+ SAL_INFO("drawinglayer", "checkCoordinateLimitWorkaroundNeededForUsedCairo: " << needed);
+ return needed;
+}
+}
+
+namespace drawinglayer::processor2d
+{
+void CairoPixelProcessor2D::onViewInformation2DChanged()
+{
+ // apply AntiAlias information to target device
+ cairo_set_antialias(mpRT, getViewInformation2D().getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT
+ : CAIRO_ANTIALIAS_NONE);
+}
+
+CairoPixelProcessor2D::CairoPixelProcessor2D(
+ const basegfx::BColorModifierStack& rBColorModifierStack,
+ const geometry::ViewInformation2D& rViewInformation, cairo_surface_t* pTarget)
+ : BaseProcessor2D(rViewInformation)
+ , mpTargetOutputDevice(nullptr)
+ , maBColorModifierStack(rBColorModifierStack)
+ , mpOwnedSurface(nullptr)
+ , mpRT(nullptr)
+ , mbRenderSimpleTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get())
+ , mbRenderDecoratedTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
+ , mnClipRecursionCount(0)
+ , mbCairoCoordinateLimitWorkaroundActive(false)
+{
+ // no target, nothing to initialize
+ if (nullptr == pTarget)
+ return;
+
+ // create RenderTarget for full target
+ mpRT = cairo_create(pTarget);
+
+ if (nullptr == mpRT)
+ // error, invalid
+ return;
+
+ // initialize some basic used values/settings
+ cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT
+ : CAIRO_ANTIALIAS_NONE);
+ cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER);
+
+ // evaluate if CairoCoordinateLimitWorkaround is needed
+ evaluateCairoCoordinateLimitWorkaround();
+}
+
+CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation,
+ tools::Long nWidthPixel, tools::Long nHeightPixel,
+ bool bUseRGBA)
+ : BaseProcessor2D(rViewInformation)
+ , mpTargetOutputDevice(nullptr)
+ , maBColorModifierStack()
+ , mpOwnedSurface(nullptr)
+ , mpRT(nullptr)
+ , mbRenderSimpleTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get())
+ , mbRenderDecoratedTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
+ , mnClipRecursionCount(0)
+ , mbCairoCoordinateLimitWorkaroundActive(false)
+{
+ if (nWidthPixel <= 0 || nHeightPixel <= 0)
+ // no size, invalid
+ return;
+
+ mpOwnedSurface = cairo_image_surface_create(bUseRGBA ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
+ nWidthPixel, nHeightPixel);
+
+ if (nullptr == mpOwnedSurface)
+ // error, invalid
+ return;
+
+ // create RenderTarget for full target
+ mpRT = cairo_create(mpOwnedSurface);
+
+ if (nullptr == mpRT)
+ // error, invalid
+ return;
+
+ // initialize some basic used values/settings
+ cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT
+ : CAIRO_ANTIALIAS_NONE);
+ cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER);
+
+ // evaluate if CairoCoordinateLimitWorkaround is needed
+ evaluateCairoCoordinateLimitWorkaround();
+}
+
+CairoPixelProcessor2D::CairoPixelProcessor2D(OutputDevice& rOutputDevice,
+ const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation)
+ , mpTargetOutputDevice(&rOutputDevice)
+ , maBColorModifierStack()
+ , mpOwnedSurface(nullptr)
+ , mpRT(nullptr)
+ , mbRenderSimpleTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get())
+ , mbRenderDecoratedTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
+ , mnClipRecursionCount(0)
+ , mbCairoCoordinateLimitWorkaroundActive(false)
+{
+ SystemGraphicsData aData(mpTargetOutputDevice->GetSystemGfxData());
+ cairo_surface_t* pTarget(static_cast<cairo_surface_t*>(aData.pSurface));
+
+ // no target, nothing to initialize
+ if (nullptr == pTarget)
+ {
+ mpTargetOutputDevice = nullptr;
+ return;
+ }
+
+ // get evtl. offsets if OutputDevice is e.g. a OUTDEV_WINDOW
+ // to evaluate if initial clip is needed
+ const tools::Long nOffsetPixelX(mpTargetOutputDevice->GetOutOffXPixel());
+ const tools::Long nOffsetPixelY(mpTargetOutputDevice->GetOutOffYPixel());
+ const tools::Long nWidthPixel(mpTargetOutputDevice->GetOutputWidthPixel());
+ const tools::Long nHeightPixel(mpTargetOutputDevice->GetOutputHeightPixel());
+ bool bClipNeeded(false);
+
+ if (0 != nOffsetPixelX || 0 != nOffsetPixelY || 0 != nWidthPixel || 0 != nHeightPixel)
+ {
+ if (0 != nOffsetPixelX || 0 != nOffsetPixelY)
+ {
+ // if offset is used we need initial clip
+ bClipNeeded = true;
+ }
+ else
+ {
+ // no offset used, compare to real pixel size
+ const tools::Long nRealPixelWidth(cairo_image_surface_get_width(pTarget));
+ const tools::Long nRealPixelHeight(cairo_image_surface_get_height(pTarget));
+
+ if (nRealPixelWidth != nWidthPixel || nRealPixelHeight != nHeightPixel)
+ {
+ // if size differs we need initial clip
+ bClipNeeded = true;
+ }
+ }
+ }
+
+ if (bClipNeeded)
+ {
+ // Make use of the possibility to add an initial clip relative
+ // to the 'real' pixel dimensions of the target surface. This is e.g.
+ // needed here due to the existence of 'virtual' target surfaces that
+ // internally use an offset and limited pixel size, mainly used for
+ // UI elements.
+ // let the CairoPixelProcessor2D do this, it has internal,
+ // system-specific possibilities to do that in an elegant and
+ // efficient way (using cairo_surface_create_for_rectangle).
+ mpOwnedSurface = cairo_surface_create_for_rectangle(pTarget, nOffsetPixelX, nOffsetPixelY,
+ nWidthPixel, nHeightPixel);
+
+ if (nullptr == mpOwnedSurface)
+ {
+ // error, invalid
+ mpTargetOutputDevice = nullptr;
+ return;
+ }
+
+ mpRT = cairo_create(mpOwnedSurface);
+ }
+ else
+ {
+ // create RenderTarget for full target
+ mpRT = cairo_create(pTarget);
+ }
+
+ if (nullptr == mpRT)
+ {
+ // error, invalid
+ mpTargetOutputDevice = nullptr;
+ return;
+ }
+
+ // initialize some basic used values/settings
+ cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT
+ : CAIRO_ANTIALIAS_NONE);
+ cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER);
+
+ // prepare output directly to pixels
+ mpTargetOutputDevice->Push(vcl::PushFlags::MAPMODE);
+ mpTargetOutputDevice->SetMapMode();
+
+ // evaluate if CairoCoordinateLimitWorkaround is needed
+ evaluateCairoCoordinateLimitWorkaround();
+}
+
+CairoPixelProcessor2D::~CairoPixelProcessor2D()
+{
+ if (nullptr != mpTargetOutputDevice) // restore MapMode
+ mpTargetOutputDevice->Pop();
+ if (nullptr != mpRT)
+ cairo_destroy(mpRT);
+ if (nullptr != mpOwnedSurface)
+ cairo_surface_destroy(mpOwnedSurface);
+}
+
+Bitmap CairoPixelProcessor2D::extractBitmap() const
+{
+ // default is empty Bitmap
+ Bitmap aRetval;
+
+ if (nullptr == mpRT)
+ // no RenderContext, not valid
+ return aRetval;
+
+ cairo_surface_t* pSource(cairo_get_target(mpRT));
+ if (nullptr == pSource)
+ // no surface, not valid
+ return aRetval;
+
+ // check pixel sizes
+ const sal_uInt32 nWidth(cairo_image_surface_get_width(pSource));
+ const sal_uInt32 nHeight(cairo_image_surface_get_height(pSource));
+ if (0 == nWidth || 0 == nHeight)
+ // no content, not valid
+ return aRetval;
+
+ // check format
+ const cairo_format_t aFormat(cairo_image_surface_get_format(pSource));
+ if (CAIRO_FORMAT_ARGB32 != aFormat && CAIRO_FORMAT_RGB24 != aFormat)
+ // we for now only support ARGB32 and RGB24, format not supported, not valid
+ return aRetval;
+
+ // ensure surface read access, wer need CAIRO_SURFACE_TYPE_IMAGE
+ cairo_surface_t* pReadSource(pSource);
+
+ if (CAIRO_SURFACE_TYPE_IMAGE != cairo_surface_get_type(pReadSource))
+ {
+ // create mapping for read access to source
+ pReadSource = cairo_surface_map_to_image(pReadSource, nullptr);
+ }
+
+ // prepare VCL/Bitmap stuff
+ const Size aBitmapSize(nWidth, nHeight);
+ const bool bHasAlpha(CAIRO_FORMAT_ARGB32 == aFormat);
+ Bitmap aBitmap(aBitmapSize, bHasAlpha ? vcl::PixelFormat::N32_BPP : vcl::PixelFormat::N24_BPP);
+ BitmapWriteAccess aAccess(aBitmap);
+ if (!aAccess)
+ {
+ SAL_WARN("drawinglayer", "Could not create image, likely too large, size= " << aBitmapSize);
+ return aRetval;
+ }
+
+ // prepare cairo stuff
+ const sal_uInt32 nStride(cairo_image_surface_get_stride(pReadSource));
+ unsigned char* pStartPixelData(cairo_image_surface_get_data(pReadSource));
+
+ // separate loops for bHasAlpha so that we have *no* branch in the
+ // loops itself
+ if (bHasAlpha)
+ {
+ for (sal_uInt32 y(0); y < nHeight; ++y)
+ {
+ // prepare scanline
+ unsigned char* pPixelData(pStartPixelData + (nStride * y));
+ Scanline pWriteRGBA = aAccess.GetScanline(y);
+
+ for (sal_uInt32 x(0); x < nWidth; ++x)
+ {
+ // RGBA: Do not forget: it's pre-multiplied
+ sal_uInt8 nAlpha(pPixelData[SVP_CAIRO_ALPHA]);
+ aAccess.SetPixelOnData(
+ pWriteRGBA, x,
+ BitmapColor(
+ ColorAlpha, vcl::bitmap::unpremultiply(pPixelData[SVP_CAIRO_RED], nAlpha),
+ vcl::bitmap::unpremultiply(pPixelData[SVP_CAIRO_GREEN], nAlpha),
+ vcl::bitmap::unpremultiply(pPixelData[SVP_CAIRO_BLUE], nAlpha), nAlpha));
+ pPixelData += 4;
+ }
+ }
+ }
+ else
+ {
+ for (sal_uInt32 y(0); y < nHeight; ++y)
+ {
+ // prepare scanline
+ unsigned char* pPixelData(pStartPixelData + (nStride * y));
+ Scanline pWriteRGB = aAccess.GetScanline(y);
+
+ for (sal_uInt32 x(0); x < nWidth; ++x)
+ {
+ aAccess.SetPixelOnData(pWriteRGB, x,
+ BitmapColor(pPixelData[SVP_CAIRO_RED],
+ pPixelData[SVP_CAIRO_GREEN],
+ pPixelData[SVP_CAIRO_BLUE]));
+ pPixelData += 4;
+ }
+ }
+ }
+
+ // construct and return Bitmap
+ aRetval = std::move(aBitmap);
+
+ if (pReadSource != pSource)
+ {
+ // cleanup mapping for read/write access to source
+ cairo_surface_unmap_image(pSource, pReadSource);
+ }
+
+ return aRetval;
+}
+
+void CairoPixelProcessor2D::processBitmapPrimitive2D(
+ const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+{
+ constexpr DrawModeFlags BITMAP(DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap
+ | DrawModeFlags::GrayBitmap);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+ const bool bDrawModeFlagsUsed(aDrawModeFlags & BITMAP);
+
+ if (bDrawModeFlagsUsed)
+ {
+ // if DrawModeFlags for Bitmap are used, encapsulate with
+ // corresponding BColorModifier
+ if (aDrawModeFlags & DrawModeFlags::BlackBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0, 0, 0)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else if (aDrawModeFlags & DrawModeFlags::WhiteBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(1, 1, 1)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else // DrawModeFlags::GrayBitmap
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ }
+
+ paintBitmapAlpha(rBitmapCandidate.getBitmap(), rBitmapCandidate.getTransform());
+
+ if (bDrawModeFlagsUsed)
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::paintBitmapAlpha(const Bitmap& rBitmap,
+ const basegfx::B2DHomMatrix& rTransform,
+ double fTransparency)
+{
+ // transparency invalid or completely transparent, done
+ if (fTransparency < 0.0 || fTransparency >= 1.0)
+ {
+ return;
+ }
+
+ // check if graphic content is inside discrete local ViewPort
+ const basegfx::B2DRange& rDiscreteViewPort(getViewInformation2D().getDiscreteViewport());
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation() * rTransform);
+
+ if (!rDiscreteViewPort.isEmpty())
+ {
+ basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+
+ aUnitRange.transform(aLocalTransform);
+
+ if (!aUnitRange.overlaps(rDiscreteViewPort))
+ {
+ // content is outside discrete local ViewPort
+ return;
+ }
+ }
+
+ Bitmap aBitmap(rBitmap);
+
+ if (aBitmap.IsEmpty() || aBitmap.GetSizePixel().IsEmpty())
+ {
+ // no pixel data, done
+ return;
+ }
+
+ // work with dimensions in discrete target pixels to use evtl. MipMap pre-scale
+ const tools::Long nDestWidth((aLocalTransform * basegfx::B2DVector(1.0, 0.0)).getLength());
+ const tools::Long nDestHeight((aLocalTransform * basegfx::B2DVector(0.0, 1.0)).getLength());
+
+ // tdf#167831 check for output size, may have zero discrete dimension in X and/or Y
+ if (0 == nDestWidth || 0 == nDestHeight)
+ {
+ // it has and is thus invisible
+ return;
+ }
+
+ if (maBColorModifierStack.count())
+ {
+ // need to apply ColorModifier to Bitmap data
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
+
+ if (aBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aModifiedColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+
+ // use unit geometry as fallback object geometry. Do *not*
+ // transform, the below used method will use the already
+ // correctly initialized local ViewInformation
+ const basegfx::B2DPolygon& aPolygon(basegfx::utils::createUnitPolygon());
+
+ // draw directly, done
+ paintPolyPolygonRGBA(basegfx::B2DPolyPolygon(aPolygon), aModifiedColor, fTransparency);
+
+ return;
+ }
+ }
+
+ // access or create cairo bitmap data
+ std::shared_ptr<CairoSurfaceHelper> aCairoSurfaceHelper(getOrCreateCairoSurfaceHelper(aBitmap));
+ if (!aCairoSurfaceHelper)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No SurfaceHelper from Bitmap (!)");
+ return;
+ }
+
+ cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight));
+ if (nullptr == pTarget)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)");
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // set linear transformation - no fAAOffset for bitmap data
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(),
+ aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ static bool bRenderTransformationBounds(false);
+ if (bRenderTransformationBounds)
+ {
+ cairo_set_source_rgba(mpRT, 1, 0, 0, 0.8);
+ impl_cairo_set_hairline(mpRT, getViewInformation2D(),
+ isCairoCoordinateLimitWorkaroundActive());
+ cairo_rectangle(mpRT, 0, 0, 1, 1);
+ cairo_stroke(mpRT);
+ }
+
+ cairo_set_source_surface(mpRT, pTarget, 0, 0);
+
+ // get the pattern created by cairo_set_source_surface and
+ // it's transformation
+ cairo_pattern_t* sourcepattern = cairo_get_source(mpRT);
+ cairo_pattern_get_matrix(sourcepattern, &aMatrix);
+
+ // RGBA sources overlap the unit geometry range, slightly,
+ // to see that activate bRenderTransformationBounds and
+ // insert a ARGB image, zoom to the borders. Seems to be half
+ // a pixel. Very good to demonstrate: 8x1 pixel, some
+ // transparent.
+ // Also errors with images 1 pixel wide/high, e.g. insert
+ // RGBA 8x1, 1x8 to see (and deactivate fix below). It also
+ // depends on the used filter, see comment below at
+ // cairo_pattern_set_filter. Found also errors with more
+ // than one pixel, so cannot use as criteria.
+ // This effect is also visible in the left/right/bottom/top
+ // page shadows, these DO use 8x1/1x8 images which led me to
+ // that problem. I double-checked that these *are* correctly
+ // defined, that is not the problem.
+ // Decided now to use clipping always. That again is
+ // simple (we are in unit coordinates)
+ cairo_rectangle(mpRT, 0, 0, 1, 1);
+ cairo_clip(mpRT);
+ cairo_matrix_scale(&aMatrix, cairo_image_surface_get_width(pTarget),
+ cairo_image_surface_get_height(pTarget));
+
+ // The alternative wpuld be: resize/scale it SLIGHTLY to force
+ // that half pixel overlap to be inside the unit range.
+ // That makes the error disappear, so no clip needed, but
+ // SLIGHTLY smaller. Keeping this code if someone might have
+ // to finetune this later for reference.
+ //
+ // cairo_matrix_init_scale(&aMatrix, nWidth + 1, nHeight + 1);
+ // cairo_matrix_translate(&aMatrix, -0.5 / (nWidth + 1), -0.5 / (nHeight + 1));
+
+ // The error/effect described above also is connected to the
+ // filter used, so I checked the filter modes available
+ // in Cairo:
+ //
+ // CAIRO_FILTER_FAST: okay, small errors, sometimes stretching some pixels
+ // CAIRO_FILTER_GOOD: stretching error
+ // CAIRO_FILTER_BEST: okay, small errors
+ // CAIRO_FILTER_NEAREST: similar to CAIRO_FILTER_FAST
+ // CAIRO_FILTER_BILINEAR: similar to CAIRO_FILTER_GOOD
+ // CAIRO_FILTER_GAUSSIAN: same as CAIRO_FILTER_GOOD/CAIRO_FILTER_BILINEAR, should
+ // not be used anyways (see docs)
+ //
+ // CAIRO_FILTER_GOOD seems to be the default anyways, but set it
+ // to be on the safe side
+ cairo_pattern_set_filter(sourcepattern, CAIRO_FILTER_GOOD);
+
+ // also set extend to CAIRO_EXTEND_PAD, else the outside of the
+ // bitmap is guessed as COL_BLACK and the filtering would blend
+ // against COL_BLACK what might give strange gray lines at borders
+ // of white-on-white bitmaps (used e.g. when painting controls).
+ // NOTE: CAIRO_EXTEND_REPEAT also works with clipping and might be
+ // broader supported by Cairo implementations
+ cairo_pattern_set_extend(sourcepattern, CAIRO_EXTEND_PAD);
+
+ cairo_pattern_set_matrix(sourcepattern, &aMatrix);
+
+ // paint bitmap data, evtl. with additional alpha channel
+ if (!basegfx::fTools::equalZero(fTransparency))
+ cairo_paint_with_alpha(mpRT, 1.0 - fTransparency);
+ else
+ cairo_paint(mpRT);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processPointArrayPrimitive2D(
+ const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate)
+{
+ const std::vector<basegfx::B2DPoint>& rPositions(rPointArrayCandidate.getPositions());
+
+ if (rPositions.empty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // determine & set color
+ basegfx::BColor aPointColor(getLineColor(rPointArrayCandidate.getRGBColor()));
+ aPointColor = maBColorModifierStack.getModifiedColor(aPointColor);
+ cairo_set_source_rgb(mpRT, aPointColor.getRed(), aPointColor.getGreen(), aPointColor.getBlue());
+
+ // To really paint a single pixel I found nothing better than
+ // switch off AA and draw a pixel-aligned rectangle
+ const cairo_antialias_t eOldAAMode(cairo_get_antialias(mpRT));
+ cairo_set_antialias(mpRT, CAIRO_ANTIALIAS_NONE);
+
+ for (auto const& pos : rPositions)
+ {
+ const basegfx::B2DPoint aDiscretePos(getViewInformation2D().getObjectToViewTransformation()
+ * pos);
+ const double fX(ceil(aDiscretePos.getX()));
+ const double fY(ceil(aDiscretePos.getY()));
+
+ cairo_rectangle(mpRT, fX, fY, 1, 1);
+ cairo_fill(mpRT);
+ }
+
+ cairo_set_antialias(mpRT, eOldAAMode);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processPolygonHairlinePrimitive2D(
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D)
+{
+ const basegfx::B2DPolygon& rPolygon(rPolygonHairlinePrimitive2D.getB2DPolygon());
+
+ if (!rPolygon.count())
+ {
+ // no geometry, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // determine & set color
+ basegfx::BColor aHairlineColor(getLineColor(rPolygonHairlinePrimitive2D.getBColor()));
+ aHairlineColor = maBColorModifierStack.getModifiedColor(aHairlineColor);
+ cairo_set_source_rgb(mpRT, aHairlineColor.getRed(), aHairlineColor.getGreen(),
+ aHairlineColor.getBlue());
+
+ // set LineWidth, use Cairo's special cairo_set_hairline
+ impl_cairo_set_hairline(mpRT, getViewInformation2D(), isCairoCoordinateLimitWorkaroundActive());
+
+ if (isCairoCoordinateLimitWorkaroundActive())
+ {
+ // need to fallback to paint in view coordinates, unfortunately
+ // need to transform self (cairo will do it wrong in this coordinate
+ // space), so no need to try to buffer
+ cairo_new_path(mpRT);
+ basegfx::B2DPolygon aAdaptedPolygon(rPolygon);
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ aAdaptedPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(fAAOffset, fAAOffset)
+ * getViewInformation2D().getObjectToViewTransformation());
+ cairo_identity_matrix(mpRT);
+ addB2DPolygonToPathGeometry(mpRT, aAdaptedPolygon);
+ cairo_stroke(mpRT);
+ }
+ else
+ {
+ // set linear transformation. use own, prepared, re-usable
+ // ObjectToViewTransformation and PolyPolygon data and let
+ // cairo do the transformations
+ cairo_matrix_t aMatrix;
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e() + fAAOffset,
+ rObjectToView.f() + fAAOffset);
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // get PathGeometry & paint it
+ cairo_new_path(mpRT);
+ getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(),
+ getViewInformation2D().getUseAntiAliasing());
+ cairo_stroke(mpRT);
+ }
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D(
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D)
+{
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::NoFill)
+ // NoFill wanted, done
+ return;
+
+ const basegfx::BColor aFillColor(getFillColor(rPolyPolygonColorPrimitive2D.getBColor()));
+ paintPolyPolygonRGBA(rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(), aFillColor);
+}
+
+void CairoPixelProcessor2D::paintPolyPolygonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const basegfx::BColor& rColor,
+ double fTransparency)
+{
+ // transparency invalid or completely transparent, done
+ if (fTransparency < 0.0 || fTransparency >= 1.0)
+ {
+ return;
+ }
+
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if (!nCount)
+ {
+ // no geometry, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // determine & set color
+ const basegfx::BColor aFillColor(maBColorModifierStack.getModifiedColor(rColor));
+
+ if (!basegfx::fTools::equalZero(fTransparency))
+ cairo_set_source_rgba(mpRT, aFillColor.getRed(), aFillColor.getGreen(),
+ aFillColor.getBlue(), 1.0 - fTransparency);
+ else
+ cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(),
+ aFillColor.getBlue());
+
+ if (isCairoCoordinateLimitWorkaroundActive())
+ {
+ // need to fallback to paint in view coordinates, unfortunately
+ // need to transform self (cairo will do it wrong in this coordinate
+ // space), so no need to try to buffer
+ cairo_new_path(mpRT);
+ basegfx::B2DPolyPolygon aAdaptedPolyPolygon(rPolyPolygon);
+ aAdaptedPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+ cairo_identity_matrix(mpRT);
+ for (const auto& rPolygon : aAdaptedPolyPolygon)
+ addB2DPolygonToPathGeometry(mpRT, rPolygon);
+ cairo_fill(mpRT);
+ }
+ else
+ {
+ // set linear transformation. use own, prepared, re-usable
+ // ObjectToViewTransformation and PolyPolygon data and let
+ // cairo do the transformations
+ cairo_matrix_t aMatrix;
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e(), rObjectToView.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // get PathGeometry & paint it
+ cairo_new_path(mpRT);
+ getOrCreateFillGeometry(mpRT, rPolyPolygon);
+ cairo_fill(mpRT);
+ }
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processTransparencePrimitive2D(
+ const primitive2d::TransparencePrimitive2D& rTransCandidate)
+{
+ if (rTransCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ if (rTransCandidate.getTransparence().empty())
+ {
+ // no mask (so nothing visible), done
+ return;
+ }
+
+ // calculate visible range, create only for that range
+ basegfx::B2DRange aDiscreteRange(
+ rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
+ aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ basegfx::B2DRange aVisibleRange(aDiscreteRange);
+ aVisibleRange.intersect(getDiscreteViewRange(mpRT));
+
+ if (aVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // tdf#166734 need to expand to full pixels due to pre-rendering
+ // will use discrete pixels/top-left position
+ aVisibleRange.expand(
+ basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY())));
+ aVisibleRange.expand(
+ basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY())));
+
+ // create embedding transformation for sub-surface
+ const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix(
+ -aVisibleRange.getMinX(), -aVisibleRange.getMinY()));
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setViewTransformation(aEmbedTransform
+ * getViewInformation2D().getViewTransformation());
+
+ // draw mask to temporary surface
+ cairo_surface_t* pTarget(cairo_get_target(mpRT));
+ const double fContainedWidth(aVisibleRange.getWidth());
+ const double fContainedHeight(aVisibleRange.getHeight());
+ cairo_surface_t* pMask(cairo_surface_create_similar_image(pTarget, CAIRO_FORMAT_ARGB32,
+ fContainedWidth, fContainedHeight));
+ CairoPixelProcessor2D aMaskRenderer(getBColorModifierStack(), aViewInformation2D, pMask);
+ aMaskRenderer.process(rTransCandidate.getTransparence());
+
+ // convert mask to something cairo can use
+ LuminanceToAlpha(pMask);
+
+ // draw content to temporary surface
+ cairo_surface_t* pContent(cairo_surface_create_similar(
+ pTarget, cairo_surface_get_content(pTarget), fContainedWidth, fContainedHeight));
+ CairoPixelProcessor2D aContent(getBColorModifierStack(), aViewInformation2D, pContent);
+ aContent.process(rTransCandidate.getChildren());
+
+ // munge the temporary surfaces to our target surface
+ cairo_set_source_surface(mpRT, pContent, aVisibleRange.getMinX(), aVisibleRange.getMinY());
+ cairo_mask_surface(mpRT, pMask, aVisibleRange.getMinX(), aVisibleRange.getMinY());
+
+ // cleanup temporary surfaces
+ cairo_surface_destroy(pContent);
+ cairo_surface_destroy(pMask);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processInvertPrimitive2D(
+ const primitive2d::InvertPrimitive2D& rInvertCandidate)
+{
+ if (rInvertCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ // calculate visible range, create only for that range
+ basegfx::B2DRange aDiscreteRange(
+ rInvertCandidate.getChildren().getB2DRange(getViewInformation2D()));
+ aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ basegfx::B2DRange aVisibleRange(aDiscreteRange);
+ aVisibleRange.intersect(getDiscreteViewRange(mpRT));
+
+ if (aVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // tdf#166734 need to expand to full pixels due to pre-rendering
+ // will use discrete pixels/top-left position
+ aVisibleRange.expand(
+ basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY())));
+ aVisibleRange.expand(
+ basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY())));
+
+ // create embedding transformation for sub-surface
+ const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix(
+ -aVisibleRange.getMinX(), -aVisibleRange.getMinY()));
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setViewTransformation(aEmbedTransform
+ * getViewInformation2D().getViewTransformation());
+
+ // draw sub-content to temporary surface
+ cairo_surface_t* pTarget(cairo_get_target(mpRT));
+ const double fContainedWidth(aVisibleRange.getWidth());
+ const double fContainedHeight(aVisibleRange.getHeight());
+ cairo_surface_t* pContent(cairo_surface_create_similar_image(
+ pTarget, CAIRO_FORMAT_ARGB32, fContainedWidth, fContainedHeight));
+ CairoPixelProcessor2D aContent(getBColorModifierStack(), aViewInformation2D, pContent);
+ aContent.process(rInvertCandidate.getChildren());
+ cairo_surface_flush(pContent);
+
+ // decide if to use builtin or create XOR yourself
+ // NOTE: not using and doing self is closer to what the
+ // current default does, so keep it
+ static bool bUseBuiltinXOR(false);
+
+ if (bUseBuiltinXOR)
+ {
+ // draw XOR to target using Cairo Operator CAIRO_OPERATOR_XOR
+ cairo_set_source_surface(mpRT, pContent, aVisibleRange.getMinX(), aVisibleRange.getMinY());
+ cairo_rectangle(mpRT, aVisibleRange.getMinX(), aVisibleRange.getMinY(),
+ aVisibleRange.getWidth(), aVisibleRange.getHeight());
+ cairo_set_operator(mpRT, CAIRO_OPERATOR_XOR);
+ cairo_fill(mpRT);
+ }
+ else
+ {
+ // get read/write access to target - XOR unfortunately needs that
+ cairo_surface_t* pRenderTarget(pTarget);
+
+ if (CAIRO_SURFACE_TYPE_IMAGE != cairo_surface_get_type(pRenderTarget))
+ {
+ // create mapping for read/write access to pRenderTarget
+ pRenderTarget = cairo_surface_map_to_image(pRenderTarget, nullptr);
+ }
+
+ // iterate over pre-rendered pContent (call it Front)
+ const sal_uInt32 nFrontWidth(cairo_image_surface_get_width(pContent));
+ const sal_uInt32 nFrontHeight(cairo_image_surface_get_height(pContent));
+ const sal_uInt32 nFrontStride(cairo_image_surface_get_stride(pContent));
+ unsigned char* pFrontDataRoot(cairo_image_surface_get_data(pContent));
+
+ // in parallel, iterate over original data (call it Back)
+ const sal_uInt32 nBackOffX(aVisibleRange.getMinX());
+ const sal_uInt32 nBackOffY(aVisibleRange.getMinY());
+ const sal_uInt32 nBackStride(cairo_image_surface_get_stride(pRenderTarget));
+ unsigned char* pBackDataRoot(cairo_image_surface_get_data(pRenderTarget));
+ const bool bBackPreMultiply(CAIRO_FORMAT_ARGB32
+ == cairo_image_surface_get_format(pRenderTarget));
+
+ if (nullptr != pFrontDataRoot && nullptr != pBackDataRoot)
+ {
+ for (sal_uInt32 y(0); y < nFrontHeight; ++y)
+ {
+ // get mem locations
+ unsigned char* pFrontData(pFrontDataRoot + (nFrontStride * y));
+ unsigned char* pBackData(pBackDataRoot + (nBackStride * (y + nBackOffY))
+ + (nBackOffX * 4));
+
+ // added advance mem to for-expression to be able to continue calls inside
+ for (sal_uInt32 x(0); x < nFrontWidth; ++x, pBackData += 4, pFrontData += 4)
+ {
+ // do not forget pre-multiply. Use 255 for non-premultiplied to
+ // not have to do if not needed
+ const sal_uInt8 nBackAlpha(bBackPreMultiply ? pBackData[SVP_CAIRO_ALPHA] : 255);
+
+ // change will only be visible in back/target when not fully transparent
+ if (0 == nBackAlpha)
+ continue;
+
+ // do not forget pre-multiply -> need to get both alphas. Use 255
+ // for non-premultiplied to not have to do if not needed
+ const sal_uInt8 nFrontAlpha(pFrontData[SVP_CAIRO_ALPHA]);
+
+ // only something to do if source is not fully transparent
+ if (0 == nFrontAlpha)
+ continue;
+
+ sal_uInt8 nFrontB(pFrontData[SVP_CAIRO_BLUE]);
+ sal_uInt8 nFrontG(pFrontData[SVP_CAIRO_GREEN]);
+ sal_uInt8 nFrontR(pFrontData[SVP_CAIRO_RED]);
+
+ if (255 != nFrontAlpha)
+ {
+ // get front color (Front is always CAIRO_FORMAT_ARGB32 and
+ // thus pre-multiplied)
+ nFrontB = vcl::bitmap::unpremultiply(nFrontB, nFrontAlpha);
+ nFrontG = vcl::bitmap::unpremultiply(nFrontG, nFrontAlpha);
+ nFrontR = vcl::bitmap::unpremultiply(nFrontR, nFrontAlpha);
+ }
+
+ sal_uInt8 nBackB(pBackData[SVP_CAIRO_BLUE]);
+ sal_uInt8 nBackG(pBackData[SVP_CAIRO_GREEN]);
+ sal_uInt8 nBackR(pBackData[SVP_CAIRO_RED]);
+
+ if (255 != nBackAlpha)
+ {
+ // get back color if bBackPreMultiply (aka 255)
+ nBackB = vcl::bitmap::unpremultiply(nBackB, nBackAlpha);
+ nBackG = vcl::bitmap::unpremultiply(nBackG, nBackAlpha);
+ nBackR = vcl::bitmap::unpremultiply(nBackR, nBackAlpha);
+ }
+
+ // create XOR r,g,b
+ const sal_uInt8 b(nFrontB ^ nBackB);
+ const sal_uInt8 g(nFrontG ^ nBackG);
+ const sal_uInt8 r(nFrontR ^ nBackR);
+
+ // write back directly to pBackData/target
+ if (255 == nBackAlpha)
+ {
+ pBackData[SVP_CAIRO_BLUE] = b;
+ pBackData[SVP_CAIRO_GREEN] = g;
+ pBackData[SVP_CAIRO_RED] = r;
+ }
+ else
+ {
+ // additionally premultiply if bBackPreMultiply (aka 255)
+ pBackData[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(b, nBackAlpha);
+ pBackData[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(g, nBackAlpha);
+ pBackData[SVP_CAIRO_RED] = vcl::bitmap::premultiply(r, nBackAlpha);
+ }
+ }
+ }
+
+ cairo_surface_mark_dirty(pRenderTarget);
+ }
+
+ if (pRenderTarget != pTarget)
+ {
+ // cleanup mapping for read/write access to target
+ cairo_surface_unmap_image(pTarget, pRenderTarget);
+ }
+ }
+
+ // cleanup temporary surface
+ cairo_surface_destroy(pContent);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processMaskPrimitive2D(
+ const primitive2d::MaskPrimitive2D& rMaskCandidate)
+{
+ if (rMaskCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ const basegfx::B2DPolyPolygon& rMask(rMaskCandidate.getMask());
+
+ if (!rMask.count())
+ {
+ // no mask (so nothing inside), done
+ return;
+ }
+
+ // calculate visible range
+ basegfx::B2DRange aMaskRange(rMask.getB2DRange());
+ aMaskRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ if (!getDiscreteViewRange(mpRT).overlaps(aMaskRange))
+ {
+ // not visible, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ if (isCairoCoordinateLimitWorkaroundActive())
+ {
+ // need to fallback to paint in view coordinates, unfortunately
+ // need to transform self (cairo will do it wrong in this coordinate
+ // space), so no need to try to buffer
+ cairo_new_path(mpRT);
+ basegfx::B2DPolyPolygon aAdaptedPolyPolygon(rMask);
+ aAdaptedPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+ for (const auto& rPolygon : aAdaptedPolyPolygon)
+ addB2DPolygonToPathGeometry(mpRT, rPolygon);
+
+ // clip to this mask
+ cairo_clip(mpRT);
+ }
+ else
+ {
+ // set linear transformation for applying mask. use no fAAOffset for mask
+ cairo_matrix_t aMatrix;
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e(), rObjectToView.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // create path geometry and put mask as path
+ cairo_new_path(mpRT);
+ getOrCreateFillGeometry(mpRT, rMask);
+
+ // clip to this mask
+ cairo_clip(mpRT);
+
+ // reset transformation to not have it set when processing
+ // child content below (was only used to set clip path)
+ cairo_identity_matrix(mpRT);
+ }
+
+ // process sub-content (that shall be masked)
+ mnClipRecursionCount++;
+ process(rMaskCandidate.getChildren());
+ mnClipRecursionCount--;
+
+ cairo_restore(mpRT);
+
+ if (0 == mnClipRecursionCount)
+ {
+ // for *some* reason Cairo seems to have problems using cairo_clip
+ // recursively, in combination with cairo_save/cairo_restore. I think
+ // it *should* work as used here, see
+ // https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-clip
+ // where this combination is explicitly mentioned/explained. It may
+ // just be a error in cairo, too (?).
+ // The error is that without that for some reason the last clip is not
+ // restored but *stays*, so e.g. when having a shape filled with
+ // 'tux.svg' and an ellipse overlapping in front, suddenly (but not
+ // always?) the ellipse gets 'clipped' against the shape filled with
+ // the tux graphic.
+ // What helps is to count the clip recursion for each incarnation of
+ // CairoPixelProcessor2D/cairo_t used and call/use cairo_reset_clip
+ // when last clip is left.
+ cairo_reset_clip(mpRT);
+ }
+}
+
+void CairoPixelProcessor2D::processModifiedColorPrimitive2D(
+ const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate)
+{
+ // standard implementation
+ if (!rModifiedCandidate.getChildren().empty())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+}
+
+void CairoPixelProcessor2D::processTransformPrimitive2D(
+ const primitive2d::TransformPrimitive2D& rTransformCandidate)
+{
+ // standard implementation
+ // remember current transformation and ViewInformation
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for local ViewInformation2D
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation()
+ * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
+
+ // process content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ setViewInformation2D(aLastViewInformation2D);
+}
+
+void CairoPixelProcessor2D::processUnifiedTransparencePrimitive2D(
+ const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate)
+{
+ if (rTransCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ if (0.0 == rTransCandidate.getTransparence())
+ {
+ // not transparent at all, use content
+ process(rTransCandidate.getChildren());
+ return;
+ }
+
+ if (rTransCandidate.getTransparence() < 0.0 || rTransCandidate.getTransparence() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ // calculate visible range, create only for that range
+ basegfx::B2DRange aDiscreteRange(
+ rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
+ aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ basegfx::B2DRange aVisibleRange(aDiscreteRange);
+ aVisibleRange.intersect(getDiscreteViewRange(mpRT));
+
+ if (aVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // tdf#166734 need to expand to full pixels due to pre-rendering
+ // will use discrete pixels/top-left position
+ aVisibleRange.expand(
+ basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY())));
+ aVisibleRange.expand(
+ basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY())));
+
+ // create embedding transformation for sub-surface
+ const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix(
+ -aVisibleRange.getMinX(), -aVisibleRange.getMinY()));
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setViewTransformation(aEmbedTransform
+ * getViewInformation2D().getViewTransformation());
+
+ // draw content to temporary surface
+ cairo_surface_t* pTarget(cairo_get_target(mpRT));
+ const double fContainedWidth(aVisibleRange.getWidth());
+ const double fContainedHeight(aVisibleRange.getHeight());
+ cairo_surface_t* pContent(cairo_surface_create_similar(
+ pTarget, cairo_surface_get_content(pTarget), fContainedWidth, fContainedHeight));
+ CairoPixelProcessor2D aContent(getBColorModifierStack(), aViewInformation2D, pContent);
+ aContent.process(rTransCandidate.getChildren());
+
+ // paint temporary surface to target with fixed transparence
+ cairo_set_source_surface(mpRT, pContent, aVisibleRange.getMinX(), aVisibleRange.getMinY());
+ cairo_paint_with_alpha(mpRT, 1.0 - rTransCandidate.getTransparence());
+
+ // cleanup temporary surface
+ cairo_surface_destroy(pContent);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processMarkerArrayPrimitive2D(
+ const primitive2d::MarkerArrayPrimitive2D& rMarkerArrayCandidate)
+{
+ const std::vector<basegfx::B2DPoint>& rPositions(rMarkerArrayCandidate.getPositions());
+
+ if (rPositions.empty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ const Bitmap& rMarker(rMarkerArrayCandidate.getMarker());
+
+ if (rMarker.IsEmpty())
+ {
+ // no marker defined, done
+ return;
+ }
+
+ // prepare Marker's Bitmap
+ Bitmap aBitmap(rMarkerArrayCandidate.getMarker());
+
+ constexpr DrawModeFlags BITMAP(DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap
+ | DrawModeFlags::GrayBitmap);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+ if (aDrawModeFlags & BITMAP)
+ {
+ if (aDrawModeFlags & DrawModeFlags::BlackBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0, 0, 0)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else if (aDrawModeFlags & DrawModeFlags::WhiteBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(1, 1, 1)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else // DrawModeFlags::GrayBitmap
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+
+ // need to apply ColorModifier to Bitmap data
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
+
+ if (aBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aReplacementColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ Bitmap aBitmap2(rMarker.GetSizePixel(), vcl::PixelFormat::N24_BPP);
+ aBitmap2.Erase(Color(aReplacementColor));
+
+ if (rMarker.HasAlpha())
+ aBitmap = Bitmap(aBitmap2, rMarker.CreateAlphaMask());
+ else
+ aBitmap = std::move(aBitmap2);
+ }
+
+ maBColorModifierStack.pop();
+ }
+
+ // access or create cairo bitmap data
+ std::shared_ptr<CairoSurfaceHelper> aCairoSurfaceHelper(getOrCreateCairoSurfaceHelper(aBitmap));
+ if (!aCairoSurfaceHelper)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No SurfaceHelper from Bitmap (!)");
+ return;
+ }
+
+ // do not use dimensions, these are usually small instances
+ cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface());
+ if (nullptr == pTarget)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)");
+ return;
+ }
+
+ const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget));
+ const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget));
+ const tools::Long nMiX((nWidth / 2) + 1);
+ const tools::Long nMiY((nHeight / 2) + 1);
+
+ cairo_save(mpRT);
+ cairo_identity_matrix(mpRT);
+ const cairo_antialias_t eOldAAMode(cairo_get_antialias(mpRT));
+ cairo_set_antialias(mpRT, CAIRO_ANTIALIAS_NONE);
+
+ for (auto const& pos : rPositions)
+ {
+ const basegfx::B2DPoint aDiscretePos(getViewInformation2D().getObjectToViewTransformation()
+ * pos);
+ const double fX(ceil(aDiscretePos.getX()));
+ const double fY(ceil(aDiscretePos.getY()));
+
+ cairo_set_source_surface(mpRT, pTarget, fX - nMiX, fY - nMiY);
+ cairo_paint(mpRT);
+ }
+
+ cairo_set_antialias(mpRT, eOldAAMode);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processBackgroundColorPrimitive2D(
+ const primitive2d::BackgroundColorPrimitive2D& rBackgroundColorCandidate)
+{
+ // check for allowed range [0.0 .. 1.0[
+ if (rBackgroundColorCandidate.getTransparency() < 0.0
+ || rBackgroundColorCandidate.getTransparency() >= 1.0)
+ return;
+
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::NoFill)
+ // NoFill wanted, done
+ return;
+
+ if (!getViewInformation2D().getViewport().isEmpty())
+ {
+ // we have a Viewport set with limitations, render as needed/defined
+ // by BackgroundColorPrimitive2D::create2DDecomposition. Alternatively,
+ // just use recursion/decompose in this case
+ process(rBackgroundColorCandidate);
+ return;
+ }
+
+ // no Viewport set, render surface completely
+ cairo_save(mpRT);
+ basegfx::BColor aFillColor(getFillColor(rBackgroundColorCandidate.getBColor()));
+ aFillColor = maBColorModifierStack.getModifiedColor(aFillColor);
+ cairo_set_source_rgba(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue(),
+ 1.0 - rBackgroundColorCandidate.getTransparency());
+ // to also copy alpha part of color, see cairo docu. Will be reset by restore below
+ cairo_set_operator(mpRT, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(mpRT);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processPolygonStrokePrimitive2D(
+ const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate)
+{
+ const basegfx::B2DPolygon& rPolygon(rPolygonStrokeCandidate.getB2DPolygon());
+ const attribute::LineAttribute& rLineAttribute(rPolygonStrokeCandidate.getLineAttribute());
+
+ if (!rPolygon.count() || rLineAttribute.getWidth() < 0.0)
+ {
+ // no geometry, done
+ return;
+ }
+
+ // get some values early that might be used for decisions
+ const bool bHairline(0.0 == rLineAttribute.getWidth());
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ const double fDiscreteLineWidth(
+ bHairline
+ ? 1.0
+ : (rObjectToView * basegfx::B2DVector(rLineAttribute.getWidth(), 0.0)).getLength());
+
+ // Here for every combination which the system-specific implementation is not
+ // capable of visualizing, use the (for decomposable Primitives always possible)
+ // fallback to the decomposition.
+ if (basegfx::B2DLineJoin::NONE == rLineAttribute.getLineJoin() && fDiscreteLineWidth > 1.5)
+ {
+ // basegfx::B2DLineJoin::NONE is special for our office, no other GraphicSystem
+ // knows that (so far), so fallback to decomposition. This is only needed if
+ // LineJoin will be used, so also check for discrete LineWidth before falling back
+ process(rPolygonStrokeCandidate);
+ return;
+ }
+
+ // This is a method every system-specific implementation of a decomposable Primitive
+ // can use to allow simple optical control of paint implementation:
+ // Create a copy, e.g. change color to 'red' as here and paint before the system
+ // paints it using the decomposition. That way you can - if active - directly
+ // optically compare if the system-specific solution is geometrically identical to
+ // the decomposition (which defines our interpretation that we need to visualize).
+ // Look below in the impl for bRenderDecomposeForCompareInRed to see that in that case
+ // we create a half-transparent paint to better support visual control
+ static bool bRenderDecomposeForCompareInRed(false);
+
+ if (bRenderDecomposeForCompareInRed)
+ {
+ const attribute::LineAttribute aRed(
+ basegfx::BColor(1.0, 0.0, 0.0), rLineAttribute.getWidth(), rLineAttribute.getLineJoin(),
+ rLineAttribute.getLineCap(), rLineAttribute.getMiterMinimumAngle());
+ rtl::Reference<primitive2d::PolygonStrokePrimitive2D> xCopy(
+ new primitive2d::PolygonStrokePrimitive2D(
+ rPolygonStrokeCandidate.getB2DPolygon(), aRed,
+ rPolygonStrokeCandidate.getStrokeAttribute()));
+ process(*xCopy);
+ }
+
+ cairo_save(mpRT);
+
+ // setup line attributes
+ cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER;
+ switch (rLineAttribute.getLineJoin())
+ {
+ case basegfx::B2DLineJoin::Bevel:
+ eCairoLineJoin = CAIRO_LINE_JOIN_BEVEL;
+ break;
+ case basegfx::B2DLineJoin::Round:
+ eCairoLineJoin = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case basegfx::B2DLineJoin::NONE:
+ case basegfx::B2DLineJoin::Miter:
+ eCairoLineJoin = CAIRO_LINE_JOIN_MITER;
+ break;
+ }
+ cairo_set_line_join(mpRT, eCairoLineJoin);
+
+ // convert miter minimum angle to miter limit
+ double fMiterLimit
+ = 1.0 / sin(std::max(rLineAttribute.getMiterMinimumAngle(), 0.01 * M_PI) / 2.0);
+ cairo_set_miter_limit(mpRT, fMiterLimit);
+
+ // setup cap attribute
+ cairo_line_cap_t eCairoLineCap(CAIRO_LINE_CAP_BUTT);
+ switch (rLineAttribute.getLineCap())
+ {
+ default: // css::drawing::LineCap_BUTT:
+ {
+ eCairoLineCap = CAIRO_LINE_CAP_BUTT;
+ break;
+ }
+ case css::drawing::LineCap_ROUND:
+ {
+ eCairoLineCap = CAIRO_LINE_CAP_ROUND;
+ break;
+ }
+ case css::drawing::LineCap_SQUARE:
+ {
+ eCairoLineCap = CAIRO_LINE_CAP_SQUARE;
+ break;
+ }
+ }
+ cairo_set_line_cap(mpRT, eCairoLineCap);
+
+ // determine & set color
+ basegfx::BColor aLineColor(getLineColor(rLineAttribute.getColor()));
+ aLineColor = maBColorModifierStack.getModifiedColor(aLineColor);
+ if (bRenderDecomposeForCompareInRed)
+ aLineColor.setRed(0.5);
+ cairo_set_source_rgb(mpRT, aLineColor.getRed(), aLineColor.getGreen(), aLineColor.getBlue());
+
+ // check stroke
+ const attribute::StrokeAttribute& rStrokeAttribute(
+ rPolygonStrokeCandidate.getStrokeAttribute());
+ const bool bDashUsed(!rStrokeAttribute.isDefault()
+ && !rStrokeAttribute.getDotDashArray().empty()
+ && 0.0 < rStrokeAttribute.getFullDotDashLen());
+ if (isCairoCoordinateLimitWorkaroundActive())
+ {
+ // need to fallback to paint in view coordinates, unfortunately
+ // need to transform self (cairo will do it wrong in this coordinate
+ // space), so no need to try to buffer
+ cairo_new_path(mpRT);
+ basegfx::B2DPolygon aAdaptedPolygon(rPolygon);
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ aAdaptedPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(fAAOffset, fAAOffset)
+ * getViewInformation2D().getObjectToViewTransformation());
+ cairo_identity_matrix(mpRT);
+ addB2DPolygonToPathGeometry(mpRT, aAdaptedPolygon);
+
+ // process/set LineWidth
+ const double fObjectLineWidth(bHairline
+ ? 1.0
+ : (getViewInformation2D().getObjectToViewTransformation()
+ * basegfx::B2DVector(rLineAttribute.getWidth(), 0.0))
+ .getLength());
+ cairo_set_line_width(mpRT, fObjectLineWidth);
+
+ if (bDashUsed)
+ {
+ std::vector<double> aStroke(rStrokeAttribute.getDotDashArray());
+ for (auto& rCandidate : aStroke)
+ rCandidate = (getViewInformation2D().getObjectToViewTransformation()
+ * basegfx::B2DVector(rCandidate, 0.0))
+ .getLength();
+ cairo_set_dash(mpRT, aStroke.data(), aStroke.size(), 0.0);
+ }
+
+ cairo_stroke(mpRT);
+ }
+ else
+ {
+ // set linear transformation
+ cairo_matrix_t aMatrix;
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e() + fAAOffset,
+ rObjectToView.f() + fAAOffset);
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // create path geometry and put mask as path
+ cairo_new_path(mpRT);
+ getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(),
+ bHairline && getViewInformation2D().getUseAntiAliasing());
+
+ // process/set LineWidth
+ const double fObjectLineWidth(
+ bHairline ? (getViewInformation2D().getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(1.0, 0.0))
+ .getLength()
+ : rLineAttribute.getWidth());
+ cairo_set_line_width(mpRT, fObjectLineWidth);
+
+ if (bDashUsed)
+ {
+ const std::vector<double>& rStroke = rStrokeAttribute.getDotDashArray();
+ cairo_set_dash(mpRT, rStroke.data(), rStroke.size(), 0.0);
+ }
+
+ // render
+ cairo_stroke(mpRT);
+ }
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processLineRectanglePrimitive2D(
+ const primitive2d::LineRectanglePrimitive2D& rLineRectanglePrimitive2D)
+{
+ if (rLineRectanglePrimitive2D.getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // work in view coordinates
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ basegfx::B2DRange aRange(rLineRectanglePrimitive2D.getB2DRange());
+ aRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ cairo_identity_matrix(mpRT);
+
+ basegfx::BColor aHairlineColor(getLineColor(rLineRectanglePrimitive2D.getBColor()));
+ aHairlineColor = maBColorModifierStack.getModifiedColor(aHairlineColor);
+ cairo_set_source_rgb(mpRT, aHairlineColor.getRed(), aHairlineColor.getGreen(),
+ aHairlineColor.getBlue());
+
+ const double fDiscreteLineWidth((getViewInformation2D().getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(1.0, 0.0))
+ .getLength());
+ cairo_set_line_width(mpRT, fDiscreteLineWidth);
+
+ cairo_rectangle(mpRT, aRange.getMinX() + fAAOffset, aRange.getMinY() + fAAOffset,
+ aRange.getWidth(), aRange.getHeight());
+ cairo_stroke(mpRT);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFilledRectanglePrimitive2D(
+ const primitive2d::FilledRectanglePrimitive2D& rFilledRectanglePrimitive2D)
+{
+ if (rFilledRectanglePrimitive2D.getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::NoFill)
+ // NoFill wanted, done
+ return;
+
+ cairo_save(mpRT);
+
+ // work in view coordinates
+ basegfx::B2DRange aRange(rFilledRectanglePrimitive2D.getB2DRange());
+ aRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ cairo_identity_matrix(mpRT);
+
+ basegfx::BColor aFillColor(getFillColor(rFilledRectanglePrimitive2D.getBColor()));
+ aFillColor = maBColorModifierStack.getModifiedColor(aFillColor);
+ cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue());
+
+ cairo_rectangle(mpRT, aRange.getMinX(), aRange.getMinY(), aRange.getWidth(),
+ aRange.getHeight());
+ cairo_fill(mpRT);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processSingleLinePrimitive2D(
+ const primitive2d::SingleLinePrimitive2D& rSingleLinePrimitive2D)
+{
+ cairo_save(mpRT);
+
+ basegfx::BColor aLineColor(getLineColor(rSingleLinePrimitive2D.getBColor()));
+ aLineColor = maBColorModifierStack.getModifiedColor(aLineColor);
+ cairo_set_source_rgb(mpRT, aLineColor.getRed(), aLineColor.getGreen(), aLineColor.getBlue());
+
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ const basegfx::B2DPoint aStart(rObjectToView * rSingleLinePrimitive2D.getStart());
+ const basegfx::B2DPoint aEnd(rObjectToView * rSingleLinePrimitive2D.getEnd());
+ cairo_identity_matrix(mpRT);
+
+ cairo_set_line_width(mpRT, 1.0f);
+
+ cairo_move_to(mpRT, aStart.getX() + fAAOffset, aStart.getY() + fAAOffset);
+ cairo_line_to(mpRT, aEnd.getX() + fAAOffset, aEnd.getY() + fAAOffset);
+ cairo_stroke(mpRT);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGraphicPrimitive2D(
+ const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D)
+{
+ if (rFillGraphicPrimitive2D.getTransparency() < 0.0
+ || rFillGraphicPrimitive2D.getTransparency() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ Bitmap aPreparedBitmap;
+ basegfx::B2DRange aFillUnitRange(rFillGraphicPrimitive2D.getFillGraphic().getGraphicRange());
+ constexpr double fBigDiscreteArea(300.0 * 300.0);
+
+ // use tooling to do various checks and prepare tiled rendering, see
+ // description of method, parameters and return value there
+ if (!prepareBitmapForDirectRender(rFillGraphicPrimitive2D, getViewInformation2D(),
+ aPreparedBitmap, aFillUnitRange, fBigDiscreteArea))
+ {
+ // no output needed, done
+ return;
+ }
+
+ if (aPreparedBitmap.IsEmpty())
+ {
+ // output needed and Bitmap data empty, so no bitmap data based
+ // tiled rendering is suggested. Use fallback for paint
+ // and decomposition
+ process(rFillGraphicPrimitive2D);
+ return;
+ }
+
+ // work with dimensions in discrete target pixels to use evtl. MipMap pre-scale
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation()
+ * rFillGraphicPrimitive2D.getTransformation());
+ const tools::Long nDestWidth(
+ (aLocalTransform * basegfx::B2DVector(aFillUnitRange.getWidth(), 0.0)).getLength());
+ const tools::Long nDestHeight(
+ (aLocalTransform * basegfx::B2DVector(0.0, aFillUnitRange.getHeight())).getLength());
+
+ // tdf#167831 check for output size, may have zero discrete dimension in X and/or Y
+ if (0 == nDestWidth || 0 == nDestHeight)
+ {
+ // it has and is thus invisible
+ return;
+ }
+
+ constexpr DrawModeFlags BITMAP(DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap
+ | DrawModeFlags::GrayBitmap);
+ basegfx::BColor aReplacementColor(0, 0, 0);
+ bool bTemporaryGrayColorModifier(false);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+ if (aDrawModeFlags & BITMAP)
+ {
+ if (aDrawModeFlags & DrawModeFlags::BlackBitmap)
+ {
+ // aReplacementColor already set
+ aPreparedBitmap.SetEmpty();
+ }
+ else if (aDrawModeFlags & DrawModeFlags::WhiteBitmap)
+ {
+ aReplacementColor = basegfx::BColor(1, 1, 1);
+ aPreparedBitmap.SetEmpty();
+ }
+ else // DrawModeFlags::GrayBitmap
+ {
+ bTemporaryGrayColorModifier = true;
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ }
+
+ if (!aPreparedBitmap.IsEmpty() && maBColorModifierStack.count())
+ {
+ // apply ColorModifier to Bitmap data
+ aPreparedBitmap = aPreparedBitmap.Modify(maBColorModifierStack);
+
+ if (aPreparedBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ aReplacementColor = maBColorModifierStack.getModifiedColor(basegfx::BColor());
+ }
+
+ if (bTemporaryGrayColorModifier)
+ // cleanup temporary BColorModifier
+ maBColorModifierStack.pop();
+ }
+
+ // if PreparedBitmap is empty, draw geometry in single color using
+ // prepared ReplacementColor
+ if (aPreparedBitmap.IsEmpty())
+ {
+ // use unit geometry as fallback object geometry. Do *not*
+ // transform, the below used method will use the already
+ // correctly initialized local ViewInformation
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
+
+ // what we still need to apply is the object transform from the
+ // local primitive, that is not part of DisplayInfo yet
+ aPolygon.transform(rFillGraphicPrimitive2D.getTransformation());
+
+ // draw directly, done
+ paintPolyPolygonRGBA(basegfx::B2DPolyPolygon(aPolygon), aReplacementColor,
+ rFillGraphicPrimitive2D.getTransparency());
+ return;
+ }
+
+ // access or create cairo bitmap data
+ std::shared_ptr<CairoSurfaceHelper> aCairoSurfaceHelper(
+ getOrCreateCairoSurfaceHelper(aPreparedBitmap));
+ if (!aCairoSurfaceHelper)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No SurfaceHelper from Bitmap (!)");
+ return;
+ }
+
+ cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight));
+ if (nullptr == pTarget)
+ {
+ SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)");
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ // set linear transformation - no fAAOffset for bitmap data
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(),
+ aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget));
+ const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget));
+
+ cairo_set_source_surface(mpRT, pTarget, 0, 0);
+
+ // get the pattern created by cairo_set_source_surface and
+ // it's transformation
+ cairo_pattern_t* sourcepattern = cairo_get_source(mpRT);
+ cairo_pattern_get_matrix(sourcepattern, &aMatrix);
+
+ // clip for RGBA (see other places)
+ if (CAIRO_FORMAT_ARGB32 == cairo_image_surface_get_format(pTarget))
+ {
+ cairo_rectangle(mpRT, 0, 0, 1, 1);
+ cairo_clip(mpRT);
+ }
+
+ // create transformation for source pattern (inverse, see
+ // cairo docu: uses user space to pattern space transformation)
+ cairo_matrix_init_scale(&aMatrix, nWidth / aFillUnitRange.getWidth(),
+ nHeight / aFillUnitRange.getHeight());
+ cairo_matrix_translate(&aMatrix, -aFillUnitRange.getMinX(), -aFillUnitRange.getMinY());
+
+ // set source pattern transform & activate pattern repeat
+ cairo_pattern_set_matrix(sourcepattern, &aMatrix);
+ cairo_pattern_set_extend(sourcepattern, CAIRO_EXTEND_REPEAT);
+
+ // CAIRO_FILTER_GOOD seems to be the default anyways, but set it
+ // to be on the safe side
+ cairo_pattern_set_filter(sourcepattern, CAIRO_FILTER_GOOD);
+
+ // paint
+ if (rFillGraphicPrimitive2D.hasTransparency())
+ cairo_paint_with_alpha(mpRT, 1.0 - rFillGraphicPrimitive2D.getTransparency());
+ else
+ cairo_paint(mpRT);
+
+ static bool bRenderTransformationBounds(false);
+ if (bRenderTransformationBounds)
+ {
+ cairo_set_source_rgba(mpRT, 0, 1, 0, 0.8);
+ impl_cairo_set_hairline(mpRT, getViewInformation2D(),
+ isCairoCoordinateLimitWorkaroundActive());
+ // full object
+ cairo_rectangle(mpRT, 0, 0, 1, 1);
+ // outline of pattern root image
+ cairo_rectangle(mpRT, aFillUnitRange.getMinX(), aFillUnitRange.getMinY(),
+ aFillUnitRange.getWidth(), aFillUnitRange.getHeight());
+ cairo_stroke(mpRT);
+ }
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D_drawOutputRange(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ // prepare outer color
+ basegfx::BColor aOuterColor(getGradientColor(rFillGradientPrimitive2D.getOuterColor()));
+ aOuterColor = maBColorModifierStack.getModifiedColor(aOuterColor);
+
+ cairo_save(mpRT);
+
+ // fill simple rect with outer color
+ if (rFillGradientPrimitive2D.hasAlphaGradient())
+ {
+ const attribute::FillGradientAttribute& rAlphaGradient(
+ rFillGradientPrimitive2D.getAlphaGradient());
+ double fLuminance(0.0);
+
+ if (!rAlphaGradient.getColorStops().empty())
+ {
+ if (css::awt::GradientStyle_AXIAL == rAlphaGradient.getStyle())
+ fLuminance = rAlphaGradient.getColorStops().back().getStopColor().luminance();
+ else
+ fLuminance = rAlphaGradient.getColorStops().front().getStopColor().luminance();
+ }
+
+ cairo_set_source_rgba(mpRT, aOuterColor.getRed(), aOuterColor.getGreen(),
+ aOuterColor.getBlue(), 1.0 - fLuminance);
+ }
+ else
+ {
+ cairo_set_source_rgb(mpRT, aOuterColor.getRed(), aOuterColor.getGreen(),
+ aOuterColor.getBlue());
+ }
+
+ const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation());
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(),
+ aTrans.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ const basegfx::B2DRange& rRange(rFillGradientPrimitive2D.getOutputRange());
+ cairo_rectangle(mpRT, rRange.getMinX(), rRange.getMinY(), rRange.getWidth(),
+ rRange.getHeight());
+ cairo_fill(mpRT);
+
+ cairo_restore(mpRT);
+}
+
+bool CairoPixelProcessor2D::processFillGradientPrimitive2D_isCompletelyBordered(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ const attribute::FillGradientAttribute& rFillGradient(
+ rFillGradientPrimitive2D.getFillGradient());
+ const double fBorder(rFillGradient.getBorder());
+
+ // check if completely 'bordered out'. This can be the case for all
+ // types of gradients
+ if (basegfx::fTools::less(fBorder, 1.0) && fBorder >= 0.0)
+ {
+ // no, we have visible content besides border
+ return false;
+ }
+
+ // draw all-covering polygon using getOuterColor and getOutputRange
+ processFillGradientPrimitive2D_drawOutputRange(rFillGradientPrimitive2D);
+ return true;
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D_linear_axial(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ const attribute::FillGradientAttribute& rFillGradient(
+ rFillGradientPrimitive2D.getFillGradient());
+ assert(!rFillGradientPrimitive2D.hasAlphaGradient()
+ || rFillGradient.sameDefinitionThanAlpha(rFillGradientPrimitive2D.getAlphaGradient()));
+ assert(
+ (css::awt::GradientStyle_LINEAR == rFillGradientPrimitive2D.getFillGradient().getStyle()
+ || css::awt::GradientStyle_AXIAL == rFillGradientPrimitive2D.getFillGradient().getStyle())
+ && "SDPRCairo: Helper allows only SPECIFIED types (!)");
+ cairo_save(mpRT);
+
+ // need to do 'antique' stuff adaptions for rotate/transitionStart in object coordinates
+ // (DefinitionRange) to have the right 'bending' on rotation
+ basegfx::B2DRange aAdaptedRange(rFillGradientPrimitive2D.getDefinitionRange());
+ const double fAngle(basegfx::normalizeToRange((2 * M_PI) - rFillGradient.getAngle(), 2 * M_PI));
+ const bool bAngle(!basegfx::fTools::equalZero(fAngle));
+ const basegfx::B2DPoint aCenter(aAdaptedRange.getCenter());
+
+ // pack rotation and offset into a transformation covering that part
+ basegfx::B2DHomMatrix aRotation(basegfx::utils::createRotateAroundPoint(aCenter, fAngle));
+
+ // create local transform to work in object coordinates based on OutputRange,
+ // combine with rotation - that way we can then just draw into AdaptedRange
+ basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation()
+ * aRotation);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(),
+ aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ if (bAngle)
+ {
+ // expand Range by rotating
+ aAdaptedRange.transform(aRotation);
+ }
+
+ // create linear pattern in unit coordinates in y-direction
+ cairo_pattern_t* pPattern(
+ cairo_pattern_create_linear(aAdaptedRange.getCenterX(), aAdaptedRange.getMinY(),
+ aAdaptedRange.getCenterX(), aAdaptedRange.getMaxY()));
+
+ // get color stops (make copy, might have to be changed)
+ basegfx::BColorStops aBColorStops(rFillGradient.getColorStops());
+ basegfx::BColorStops aBColorStopsAlpha;
+ const bool bHasAlpha(rFillGradientPrimitive2D.hasAlphaGradient());
+ if (bHasAlpha)
+ aBColorStopsAlpha = rFillGradientPrimitive2D.getAlphaGradient().getColorStops();
+ const bool bAxial(css::awt::GradientStyle_AXIAL == rFillGradient.getStyle());
+
+ // get and apply border - create soace at start in gradient
+ const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0));
+ if (!basegfx::fTools::equalZero(fBorder))
+ {
+ if (bAxial)
+ {
+ aBColorStops.reverseColorStops();
+ if (bHasAlpha)
+ aBColorStopsAlpha.reverseColorStops();
+ }
+
+ aBColorStops.createSpaceAtStart(fBorder);
+ if (bHasAlpha)
+ aBColorStopsAlpha.createSpaceAtStart(fBorder);
+
+ if (bAxial)
+ {
+ aBColorStops.reverseColorStops();
+ if (bHasAlpha)
+ aBColorStopsAlpha.reverseColorStops();
+ }
+ }
+
+ if (bAxial)
+ {
+ // expand with mirrored ColorStops to create axial
+ aBColorStops.doApplyAxial();
+ if (bHasAlpha)
+ aBColorStopsAlpha.doApplyAxial();
+ }
+
+ // Apply steps if used to 'emulate' LO's 'discrete step' feature
+ if (rFillGradient.getSteps())
+ {
+ aBColorStops.doApplySteps(rFillGradient.getSteps());
+ if (bHasAlpha)
+ aBColorStopsAlpha.doApplySteps(rFillGradient.getSteps());
+ }
+
+ // add color stops
+ for (size_t a(0); a < aBColorStops.size(); a++)
+ {
+ const basegfx::BColorStop& rStop(aBColorStops[a]);
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rStop.getStopColor()));
+
+ if (bHasAlpha)
+ {
+ const basegfx::BColor aAlpha(aBColorStopsAlpha[a].getStopColor());
+ cairo_pattern_add_color_stop_rgba(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(),
+ 1.0 - aAlpha.luminance());
+ }
+ else
+ {
+ if (rFillGradientPrimitive2D.hasTransparency())
+ {
+ cairo_pattern_add_color_stop_rgba(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(),
+ 1.0 - rFillGradientPrimitive2D.getTransparency());
+ }
+ else
+ {
+ cairo_pattern_add_color_stop_rgb(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue());
+ }
+ }
+ }
+
+ // draw OutRange
+ basegfx::B2DRange aOutRange(rFillGradientPrimitive2D.getOutputRange());
+ if (bAngle)
+ {
+ // expand backwards to cover all area needed for OutputRange
+ aRotation.invert();
+ aOutRange.transform(aRotation);
+ }
+ cairo_rectangle(mpRT, aOutRange.getMinX(), aOutRange.getMinY(), aOutRange.getWidth(),
+ aOutRange.getHeight());
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+
+ // cleanup
+ cairo_pattern_destroy(pPattern);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D_square_rect(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ if (rFillGradientPrimitive2D.hasAlphaGradient() || rFillGradientPrimitive2D.hasTransparency())
+ {
+ // Do not use direct alpha for this: It paints using four trapez that
+ // do not add up at edges due to being painted AntiAliased; that means
+ // common pixels do not add up, but blend by transparency, so leaving
+ // visual traces -> process recursively
+ process(rFillGradientPrimitive2D);
+ return;
+ }
+
+ assert(
+ (css::awt::GradientStyle_SQUARE == rFillGradientPrimitive2D.getFillGradient().getStyle()
+ || css::awt::GradientStyle_RECT == rFillGradientPrimitive2D.getFillGradient().getStyle())
+ && "SDPRCairo: Helper allows only SPECIFIED types (!)");
+ cairo_save(mpRT);
+
+ // draw all-covering polygon using getOuterColor and getOutputRange,
+ // the partial paints below will not fill areas outside automatically
+ // as happens in the other gradient paints
+ processFillGradientPrimitive2D_drawOutputRange(rFillGradientPrimitive2D);
+
+ // get DefinitionRange and adapt if needed
+ basegfx::B2DRange aAdaptedRange(rFillGradientPrimitive2D.getDefinitionRange());
+ const bool bSquare(css::awt::GradientStyle_SQUARE
+ == rFillGradientPrimitive2D.getFillGradient().getStyle());
+ const basegfx::B2DPoint aCenter(aAdaptedRange.getCenter());
+ bool bLandscape(false);
+ double fSmallRadius(1.0);
+
+ // get rotation and offset values
+ const attribute::FillGradientAttribute& rFillGradient(
+ rFillGradientPrimitive2D.getFillGradient());
+ const double fAngle(basegfx::normalizeToRange((2 * M_PI) - rFillGradient.getAngle(), 2 * M_PI));
+ const bool bAngle(!basegfx::fTools::equalZero(fAngle));
+ const double fOffxsetX(std::max(std::min(rFillGradient.getOffsetX(), 1.0), 0.0));
+ const double fOffxsetY(std::max(std::min(rFillGradient.getOffsetY(), 1.0), 0.0));
+
+ if (bSquare)
+ {
+ // expand to make width == height
+ const basegfx::B2DRange& rDefRange(rFillGradientPrimitive2D.getDefinitionRange());
+
+ if (rDefRange.getWidth() > rDefRange.getHeight())
+ {
+ // landscape -> square
+ const double fRadius(0.5 * rDefRange.getWidth());
+ aAdaptedRange.expand(basegfx::B2DPoint(rDefRange.getMinX(), aCenter.getY() - fRadius));
+ aAdaptedRange.expand(basegfx::B2DPoint(rDefRange.getMaxX(), aCenter.getY() + fRadius));
+ }
+ else
+ {
+ // portrait -> square
+ const double fRadius(0.5 * rDefRange.getHeight());
+ aAdaptedRange.expand(basegfx::B2DPoint(aCenter.getX() - fRadius, rDefRange.getMinY()));
+ aAdaptedRange.expand(basegfx::B2DPoint(aCenter.getX() + fRadius, rDefRange.getMaxY()));
+ }
+
+ bLandscape = true;
+ fSmallRadius = 0.5 * aAdaptedRange.getWidth();
+ }
+ else
+ {
+ if (bAngle)
+ {
+ // expand range using applied rotation
+ aAdaptedRange.transform(basegfx::utils::createRotateAroundPoint(aCenter, fAngle));
+ }
+
+ // set local params as needed for non-square
+ bLandscape = aAdaptedRange.getWidth() > aAdaptedRange.getHeight();
+ fSmallRadius = 0.5 * (bLandscape ? aAdaptedRange.getHeight() : aAdaptedRange.getWidth());
+ }
+
+ // pack rotation and offset into a combined transformation that covers that parts
+ basegfx::B2DHomMatrix aRotAndTranslate;
+ aRotAndTranslate.translate(-aCenter.getX(), -aCenter.getY());
+ if (bAngle)
+ aRotAndTranslate.rotate(fAngle);
+ aRotAndTranslate.translate(aAdaptedRange.getMinX() + (fOffxsetX * aAdaptedRange.getWidth()),
+ aAdaptedRange.getMinY() + (fOffxsetY * aAdaptedRange.getHeight()));
+
+ // create local transform to work in object coordinates based on OutputRange,
+ // combine with rotation and offset - that way we can then just draw into
+ // AdaptedRange
+ basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation()
+ * aRotAndTranslate);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(),
+ aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // get color stops (make copy, might have to be changed)
+ basegfx::BColorStops aBColorStops(rFillGradient.getColorStops());
+
+ // apply BColorModifierStack early - the BColorStops are used multiple
+ // times below, so do this only once
+ if (0 != maBColorModifierStack.count())
+ {
+ aBColorStops.tryToApplyBColorModifierStack(maBColorModifierStack);
+ }
+
+ // get and apply border - create soace at start in gradient
+ const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0));
+ if (!basegfx::fTools::equalZero(fBorder))
+ {
+ aBColorStops.createSpaceAtStart(fBorder);
+ }
+
+ // Apply steps if used to 'emulate' LO's 'discrete step' feature
+ if (rFillGradient.getSteps())
+ {
+ aBColorStops.doApplySteps(rFillGradient.getSteps());
+ }
+
+ // get half single pixel size to fill touching 'gaps'
+ // NOTE: I formally used cairo_device_to_user_distance, but that
+ // can indeed create negative sizes if the transformation e.g.
+ // contains rotation(s). could use fabs(), but just rely on
+ // linear algebra and use the (always positive) length of a vector
+ const double fHalfPx((getViewInformation2D().getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(1.0, 0.0))
+ .getLength());
+
+ // draw top part trapez/triangle
+ {
+ cairo_move_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMinY());
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMinY());
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMinY() + fHalfPx);
+ if (!bSquare && bLandscape)
+ {
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX() - fSmallRadius, aCenter.getY() + fHalfPx);
+ cairo_line_to(mpRT, aAdaptedRange.getMinX() + fSmallRadius, aCenter.getY() + fHalfPx);
+ }
+ else
+ {
+ cairo_line_to(mpRT, aCenter.getX(), aAdaptedRange.getMinY() + fSmallRadius + fHalfPx);
+ }
+ cairo_line_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMinY() + fHalfPx);
+ cairo_close_path(mpRT);
+
+ // create linear pattern in needed coordinates directly
+ // NOTE: I *tried* to create in unit coordinates and adapt modifying and re-using
+ // cairo_pattern_set_matrix - that *seems* to work but sometimes runs into
+ // numerical problems -> probably cairo implementation. So stay safe and do
+ // it the easy way, for the cost of re-creating gradient definitions (still cheap)
+ cairo_pattern_t* pPattern(cairo_pattern_create_linear(
+ aCenter.getX(), aAdaptedRange.getMinY(), aCenter.getX(),
+ aAdaptedRange.getMinY()
+ + (bLandscape ? aAdaptedRange.getHeight() * 0.5 : fSmallRadius)));
+ for (const auto& aStop : aBColorStops)
+ {
+ const basegfx::BColor& rColor(aStop.getStopColor());
+ cairo_pattern_add_color_stop_rgb(pPattern, aStop.getStopOffset(), rColor.getRed(),
+ rColor.getGreen(), rColor.getBlue());
+ }
+
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+ cairo_pattern_destroy(pPattern);
+ }
+
+ {
+ // draw right part trapez/triangle
+ cairo_move_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMinY());
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMaxY());
+ if (bSquare || bLandscape)
+ {
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX() - fSmallRadius - fHalfPx, aCenter.getY());
+ }
+ else
+ {
+ cairo_line_to(mpRT, aCenter.getX() - fHalfPx, aAdaptedRange.getMaxY() - fSmallRadius);
+ cairo_line_to(mpRT, aCenter.getX() - fHalfPx, aAdaptedRange.getMinY() + fSmallRadius);
+ }
+ cairo_close_path(mpRT);
+
+ // create linear pattern in needed coordinates directly
+ cairo_pattern_t* pPattern(cairo_pattern_create_linear(
+ aAdaptedRange.getMaxX(), aCenter.getY(),
+ aAdaptedRange.getMaxX() - (bLandscape ? fSmallRadius : aAdaptedRange.getWidth() * 0.5),
+ aCenter.getY()));
+ for (const auto& aStop : aBColorStops)
+ {
+ const basegfx::BColor& rColor(aStop.getStopColor());
+ cairo_pattern_add_color_stop_rgb(pPattern, aStop.getStopOffset(), rColor.getRed(),
+ rColor.getGreen(), rColor.getBlue());
+ }
+
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+ cairo_pattern_destroy(pPattern);
+ }
+
+ {
+ // draw bottom part trapez/triangle
+ cairo_move_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMaxY());
+ cairo_line_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMaxY());
+ cairo_line_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMaxY() - fHalfPx);
+ if (!bSquare && bLandscape)
+ {
+ cairo_line_to(mpRT, aAdaptedRange.getMinX() + fSmallRadius, aCenter.getY() - fHalfPx);
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX() - fSmallRadius, aCenter.getY() - fHalfPx);
+ }
+ else
+ {
+ cairo_line_to(mpRT, aCenter.getX(), aAdaptedRange.getMaxY() - fSmallRadius - fHalfPx);
+ }
+ cairo_line_to(mpRT, aAdaptedRange.getMaxX(), aAdaptedRange.getMaxY() - fHalfPx);
+ cairo_close_path(mpRT);
+
+ // create linear pattern in needed coordinates directly
+ cairo_pattern_t* pPattern(cairo_pattern_create_linear(
+ aCenter.getX(), aAdaptedRange.getMaxY(), aCenter.getX(),
+ aAdaptedRange.getMaxY()
+ - (bLandscape ? aAdaptedRange.getHeight() * 0.5 : fSmallRadius)));
+ for (const auto& aStop : aBColorStops)
+ {
+ const basegfx::BColor& rColor(aStop.getStopColor());
+ cairo_pattern_add_color_stop_rgb(pPattern, aStop.getStopOffset(), rColor.getRed(),
+ rColor.getGreen(), rColor.getBlue());
+ }
+
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+ cairo_pattern_destroy(pPattern);
+ }
+
+ {
+ // draw left part trapez/triangle
+ cairo_move_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMaxY());
+ cairo_line_to(mpRT, aAdaptedRange.getMinX(), aAdaptedRange.getMinY());
+ if (bSquare || bLandscape)
+ {
+ cairo_line_to(mpRT, aAdaptedRange.getMinX() + fSmallRadius + fHalfPx, aCenter.getY());
+ }
+ else
+ {
+ cairo_line_to(mpRT, aCenter.getX() + fHalfPx, aAdaptedRange.getMinY() + fSmallRadius);
+ cairo_line_to(mpRT, aCenter.getX() + fHalfPx, aAdaptedRange.getMaxY() - fSmallRadius);
+ }
+ cairo_close_path(mpRT);
+
+ // create linear pattern in needed coordinates directly
+ cairo_pattern_t* pPattern(cairo_pattern_create_linear(
+ aAdaptedRange.getMinX(), aCenter.getY(),
+ aAdaptedRange.getMinX() + (bLandscape ? fSmallRadius : aAdaptedRange.getWidth() * 0.5),
+ aCenter.getY()));
+ for (const auto& aStop : aBColorStops)
+ {
+ const basegfx::BColor& rColor(aStop.getStopColor());
+ cairo_pattern_add_color_stop_rgb(pPattern, aStop.getStopOffset(), rColor.getRed(),
+ rColor.getGreen(), rColor.getBlue());
+ }
+
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+ cairo_pattern_destroy(pPattern);
+ }
+
+ // cleanup
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D_radial_elliptical(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ const attribute::FillGradientAttribute& rFillGradient(
+ rFillGradientPrimitive2D.getFillGradient());
+ assert(!rFillGradientPrimitive2D.hasAlphaGradient()
+ || rFillGradient.sameDefinitionThanAlpha(rFillGradientPrimitive2D.getAlphaGradient()));
+ assert((css::awt::GradientStyle_RADIAL == rFillGradientPrimitive2D.getFillGradient().getStyle()
+ || css::awt::GradientStyle_ELLIPTICAL
+ == rFillGradientPrimitive2D.getFillGradient().getStyle())
+ && "SDPRCairo: Helper allows only SPECIFIED types (!)");
+ cairo_save(mpRT);
+
+ // need to do 'antique' stuff adaptions for rotate/transitionStart in object coordinates
+ // (DefinitionRange) to have the right 'bending' on rotation
+ const basegfx::B2DRange rDefRange(rFillGradientPrimitive2D.getDefinitionRange());
+ const basegfx::B2DPoint aCenter(rDefRange.getCenter());
+ double fRadius(1.0);
+ double fRatioElliptical(1.0);
+ const bool bRadial(css::awt::GradientStyle_RADIAL == rFillGradient.getStyle());
+
+ // use what is done in initEllipticalGradientInfo method to get as close as
+ // possible to former stuff, expand AdaptedRange as needed
+ if (bRadial)
+ {
+ const double fHalfOriginalDiag(std::hypot(rDefRange.getWidth(), rDefRange.getHeight())
+ * 0.5);
+ fRadius = fHalfOriginalDiag;
+ }
+ else
+ {
+ double fTargetSizeX(M_SQRT2 * rDefRange.getWidth());
+ double fTargetSizeY(M_SQRT2 * rDefRange.getHeight());
+ fRatioElliptical = fTargetSizeX / fTargetSizeY;
+ fRadius = std::max(fTargetSizeX, fTargetSizeY) * 0.5;
+ }
+
+ // get rotation and offset values
+ const double fAngle(basegfx::normalizeToRange((2 * M_PI) - rFillGradient.getAngle(), 2 * M_PI));
+ const bool bAngle(!basegfx::fTools::equalZero(fAngle));
+ const double fOffxsetX(std::max(std::min(rFillGradient.getOffsetX(), 1.0), 0.0));
+ const double fOffxsetY(std::max(std::min(rFillGradient.getOffsetY(), 1.0), 0.0));
+
+ // pack rotation and offset into a combined transformation covering that parts
+ basegfx::B2DHomMatrix aRotAndTranslate;
+ aRotAndTranslate.translate(-aCenter.getX(), -aCenter.getY());
+ if (bAngle)
+ aRotAndTranslate.rotate(fAngle);
+ aRotAndTranslate.translate(rDefRange.getMinX() + (fOffxsetX * rDefRange.getWidth()),
+ rDefRange.getMinY() + (fOffxsetY * rDefRange.getHeight()));
+
+ // create local transform to work in object coordinates based on OutputRange,
+ // combine with rotation and offset - that way we can then just draw into
+ // AdaptedRange
+ basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation()
+ * aRotAndTranslate);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(),
+ aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // create linear pattern in unit coordinates in y-direction
+ cairo_pattern_t* pPattern(cairo_pattern_create_radial(aCenter.getX(), aCenter.getY(), fRadius,
+ aCenter.getX(), aCenter.getY(), 0.0));
+
+ // get color stops (make copy, might have to be changed)
+ basegfx::BColorStops aBColorStops(rFillGradient.getColorStops());
+ basegfx::BColorStops aBColorStopsAlpha;
+ const bool bHasAlpha(rFillGradientPrimitive2D.hasAlphaGradient());
+ if (bHasAlpha)
+ aBColorStopsAlpha = rFillGradientPrimitive2D.getAlphaGradient().getColorStops();
+
+ // get and apply border - create soace at start in gradient
+ const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0));
+ if (!basegfx::fTools::equalZero(fBorder))
+ {
+ aBColorStops.createSpaceAtStart(fBorder);
+ if (bHasAlpha)
+ aBColorStopsAlpha.createSpaceAtStart(fBorder);
+ }
+
+ // Apply steps if used to 'emulate' LO's 'discrete step' feature
+ if (rFillGradient.getSteps())
+ {
+ aBColorStops.doApplySteps(rFillGradient.getSteps());
+ if (bHasAlpha)
+ aBColorStopsAlpha.doApplySteps(rFillGradient.getSteps());
+ }
+
+ // add color stops
+ for (size_t a(0); a < aBColorStops.size(); a++)
+ {
+ const basegfx::BColorStop& rStop(aBColorStops[a]);
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rStop.getStopColor()));
+
+ if (bHasAlpha)
+ {
+ const basegfx::BColor aAlpha(aBColorStopsAlpha[a].getStopColor());
+ cairo_pattern_add_color_stop_rgba(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(),
+ 1.0 - aAlpha.luminance());
+ }
+ else
+ {
+ if (rFillGradientPrimitive2D.hasTransparency())
+ {
+ cairo_pattern_add_color_stop_rgba(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(),
+ 1.0 - rFillGradientPrimitive2D.getTransparency());
+ }
+ else
+ {
+ cairo_pattern_add_color_stop_rgb(pPattern, rStop.getStopOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue());
+ }
+ }
+ }
+
+ cairo_set_source(mpRT, pPattern);
+
+ if (!bRadial) // css::awt::GradientStyle_ELLIPTICAL
+ {
+ // set cairo matrix at cairo_pattern_t to get needed ratio scale done.
+ // this is necessary since cairo_pattern_create_radial does *not*
+ // support ellipse resp. radial gradient with non-equidistant
+ // ratio directly
+ // this uses the transformation 'from user space to pattern space' as
+ // cairo docu states. That is the inverse of the intuitive thought
+ // model: describe from coordinates in texture, so use B2DHomMatrix
+ // and invert at the end to have better control about what has to happen
+ basegfx::B2DHomMatrix aTrans;
+
+ // move center to origin to prepare scale/rotate
+ aTrans.translate(-aCenter.getX(), -aCenter.getY());
+
+ // get scale factor and apply as needed
+ if (fRatioElliptical > 1.0)
+ aTrans.scale(1.0, 1.0 / fRatioElliptical);
+ else
+ aTrans.scale(fRatioElliptical, 1.0);
+
+ // move transformed stuff back to center
+ aTrans.translate(aCenter.getX(), aCenter.getY());
+
+ // invert and set at cairo_pattern_t
+ aTrans.invert();
+ cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(),
+ aTrans.f());
+ cairo_pattern_set_matrix(pPattern, &aMatrix);
+ }
+
+ // draw OutRange. Due to rot and translate being part of the
+ // set transform in cairo we need to back-transform (and expand
+ // as needed) the OutputRange to paint at the right place and
+ // get all OutputRange covered
+ basegfx::B2DRange aOutRange(rFillGradientPrimitive2D.getOutputRange());
+ aRotAndTranslate.invert();
+ aOutRange.transform(aRotAndTranslate);
+ cairo_rectangle(mpRT, aOutRange.getMinX(), aOutRange.getMinY(), aOutRange.getWidth(),
+ aOutRange.getHeight());
+ cairo_fill(mpRT);
+
+ // cleanup
+ cairo_pattern_destroy(pPattern);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D_fallback_decompose(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ if (rFillGradientPrimitive2D.hasAlphaGradient())
+ {
+ // process recursively to eliminate alpha, cannot be used in decompose fallback
+ process(rFillGradientPrimitive2D);
+ return;
+ }
+
+ // this helper draws the given gradient using the decompose fallback,
+ // maybe needed in some cases an can/will be handy
+ cairo_save(mpRT);
+
+ // draw all-covering initial BG polygon 1st using getOuterColor and getOutputRange
+ processFillGradientPrimitive2D_drawOutputRange(rFillGradientPrimitive2D);
+
+ // bet basic form in unit coordinates
+ CairoPathHelper aForm(rFillGradientPrimitive2D.getUnitPolygon());
+
+ // paint solid fill steps by providing callback as lambda
+ auto aCallback([this, &aForm](const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::BColor& rColor) {
+ const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation()
+ * rMatrix);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(),
+ aTrans.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rColor));
+ cairo_set_source_rgb(mpRT, aColor.getRed(), aColor.getGreen(), aColor.getBlue());
+
+ cairo_append_path(mpRT, aForm.getCairoPath());
+
+ cairo_fill(mpRT);
+ });
+
+ // call value generator to trigger callbacks
+ rFillGradientPrimitive2D.generateMatricesAndColors(aCallback);
+
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::processFillGradientPrimitive2D(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ if (rFillGradientPrimitive2D.getDefinitionRange().isEmpty())
+ {
+ // no definition area, done
+ return;
+ }
+
+ if (rFillGradientPrimitive2D.getOutputRange().isEmpty())
+ {
+ // no output area, done
+ return;
+ }
+
+ const attribute::FillGradientAttribute& rFillGradient(
+ rFillGradientPrimitive2D.getFillGradient());
+
+ if (rFillGradient.isDefault())
+ {
+ // no gradient definition, done
+ return;
+ }
+
+ // check if completely 'bordered out'
+ if (processFillGradientPrimitive2D_isCompletelyBordered(rFillGradientPrimitive2D))
+ {
+ // yes, done, was processed as single filled rectangle (using getOuterColor())
+ return;
+ }
+
+ constexpr DrawModeFlags SIMPLE_GRADIENT(DrawModeFlags::BlackGradient
+ | DrawModeFlags::WhiteGradient
+ | DrawModeFlags::SettingsGradient);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+ if (aDrawModeFlags & SIMPLE_GRADIENT)
+ {
+ // use simple, single-color OutputRange draw
+ processFillGradientPrimitive2D_drawOutputRange(rFillGradientPrimitive2D);
+ return;
+ }
+
+ const bool bTemporaryGrayColorModifier(aDrawModeFlags & DrawModeFlags::GrayGradient);
+ if (bTemporaryGrayColorModifier)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+
+ // evtl. prefer fallback: cairo does *not* render hard color transitions
+ // in gradients anti-aliased which is most visible in 'step'ed gradients,
+ // but may also happen in normal ones -> may need to be checked in
+ // basegfx::BColorStops (as tooling, like isSymmetrical() or similar).
+ // due to the nature of 'step'ing this also means a low number of
+ // filled polygons to be drawn (no 'smooth' parts to be replicated),
+ // so this is no runtime burner by definition.
+ // Making this configurable using static bool, may be moved to settings
+ // somewhere later. Do not forget to deactivate when working on 'step'ping
+ // stuff in the other helpers (!)
+ static bool bPreferAntiAliasedHardColorTransitions(true);
+
+ if (bPreferAntiAliasedHardColorTransitions && rFillGradient.getSteps())
+ {
+ processFillGradientPrimitive2D_fallback_decompose(rFillGradientPrimitive2D);
+ }
+ else
+ {
+ switch (rFillGradient.getStyle())
+ {
+ case css::awt::GradientStyle_LINEAR:
+ case css::awt::GradientStyle_AXIAL:
+ {
+ // use specialized renderer for this cases - linear, axial
+ processFillGradientPrimitive2D_linear_axial(rFillGradientPrimitive2D);
+ break;
+ }
+ case css::awt::GradientStyle_RADIAL:
+ case css::awt::GradientStyle_ELLIPTICAL:
+ {
+ // use specialized renderer for this cases - radial, elliptical
+
+ // NOTE for css::awt::GradientStyle_ELLIPTICAL:
+ // The first time ever I will accept slight deviations for the
+ // elliptical case here due to it's old chaotic move-two-pixels inside
+ // rendering method that cannot be patched into a lineartransformation
+ // and is hard/difficult to support in more modern systems. Differences
+ // are small and mostly would be visible *if* in steps-mode what is
+ // also rare. IF that should make problems reactivation of that case
+ // for the default case below is possible. main reason is that speed
+ // for direct rendering in cairo is much better.
+ processFillGradientPrimitive2D_radial_elliptical(rFillGradientPrimitive2D);
+ break;
+ }
+ case css::awt::GradientStyle_SQUARE:
+ case css::awt::GradientStyle_RECT:
+ {
+ // use specialized renderer for this cases - square, rect
+ // NOTE: *NO* support for FillGradientAlpha here. it is anyways
+ // hard to map these to direct rendering, but to do so the four
+ // trapezoids/sides are 'stitched' together, so painting RGBA
+ // directly will make the overlaps look bad and like errors.
+ // Anyways, these gradient types are only our internal heritage
+ // and rendering them directly is already much faster, will be okay.
+ processFillGradientPrimitive2D_square_rect(rFillGradientPrimitive2D);
+ break;
+ }
+ default:
+ {
+ // NOTE: All cases are covered above, but keep this as fallback,
+ // so it is possible anytime to exclude one of the cases above again
+ // and go back to decomposed version - just in case...
+ processFillGradientPrimitive2D_fallback_decompose(rFillGradientPrimitive2D);
+ break;
+ }
+ }
+ }
+
+ if (bTemporaryGrayColorModifier)
+ // cleanup temporary BColorModifier
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::processPolyPolygonRGBAPrimitive2D(
+ const primitive2d::PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D)
+{
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::NoFill)
+ // NoFill wanted, done
+ return;
+
+ const basegfx::BColor aFillColor(getFillColor(rPolyPolygonRGBAPrimitive2D.getBColor()));
+
+ if (!rPolyPolygonRGBAPrimitive2D.hasTransparency())
+ {
+ // do what CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D does
+ paintPolyPolygonRGBA(rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon(), aFillColor);
+ return;
+ }
+
+ // draw with alpha directly
+ paintPolyPolygonRGBA(rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon(), aFillColor,
+ rPolyPolygonRGBAPrimitive2D.getTransparency());
+}
+
+void CairoPixelProcessor2D::processPolyPolygonAlphaGradientPrimitive2D(
+ const primitive2d::PolyPolygonAlphaGradientPrimitive2D& rPolyPolygonAlphaGradientPrimitive2D)
+{
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::NoFill)
+ // NoFill wanted, done
+ return;
+
+ const basegfx::B2DPolyPolygon& rPolyPolygon(
+ rPolyPolygonAlphaGradientPrimitive2D.getB2DPolyPolygon());
+ if (0 == rPolyPolygon.count())
+ {
+ // no geometry, done
+ return;
+ }
+
+ basegfx::BColor aFillColor(getFillColor(rPolyPolygonAlphaGradientPrimitive2D.getBColor()));
+ aFillColor = maBColorModifierStack.getModifiedColor(aFillColor);
+
+ const attribute::FillGradientAttribute& rAlphaGradient(
+ rPolyPolygonAlphaGradientPrimitive2D.getAlphaGradient());
+ if (rAlphaGradient.isDefault())
+ {
+ // default is a single ColorStop at 0.0 with black (0, 0, 0). The
+ // luminance is then 0.0, too -> not transparent at all
+ paintPolyPolygonRGBA(rPolyPolygon, aFillColor);
+ return;
+ }
+
+ basegfx::BColor aSingleColor;
+ const basegfx::BColorStops& rAlphaStops(rAlphaGradient.getColorStops());
+ if (rAlphaStops.isSingleColor(aSingleColor))
+ {
+ // draw with alpha directly
+ paintPolyPolygonRGBA(rPolyPolygon, aFillColor, aSingleColor.luminance());
+ return;
+ }
+
+ const css::awt::GradientStyle aStyle(rAlphaGradient.getStyle());
+ if (css::awt::GradientStyle_SQUARE == aStyle || css::awt::GradientStyle_RECT == aStyle)
+ {
+ // direct paint cannot be used for these styles since they get 'stitched'
+ // by multiple parts, so *need* single alpha for multiple pieces, go
+ // with decompose/recursion
+ process(rPolyPolygonAlphaGradientPrimitive2D);
+ return;
+ }
+
+ // render as FillGradientPrimitive2D. The idea is to create BColorStops
+ // with the same number of entries, but all the same color, using the
+ // polygon's target fill color, so we can directly paint gradients as
+ // RGBA in Cairo
+ basegfx::BColorStops aColorStops;
+
+ // create ColorStops at same stops but single color
+ aColorStops.reserve(rAlphaStops.size());
+ for (const auto& entry : rAlphaStops)
+ aColorStops.emplace_back(entry.getStopOffset(), aFillColor);
+
+ // create FillGradient using that single-color ColorStops
+ const attribute::FillGradientAttribute aFillGradient(
+ rAlphaGradient.getStyle(), rAlphaGradient.getBorder(), rAlphaGradient.getOffsetX(),
+ rAlphaGradient.getOffsetY(), rAlphaGradient.getAngle(), aColorStops,
+ rAlphaGradient.getSteps());
+
+ // create temporary FillGradientPrimitive2D, but do not forget
+ // to embed to MaskPrimitive2D to get the PolyPolygon form
+ const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolyPolygon));
+ const primitive2d::Primitive2DContainer aContainerMaskedFillGradient{
+ rtl::Reference<primitive2d::MaskPrimitive2D>(new primitive2d::MaskPrimitive2D(
+ rPolyPolygon,
+ primitive2d::Primitive2DContainer{ rtl::Reference<primitive2d::FillGradientPrimitive2D>(
+ new primitive2d::FillGradientPrimitive2D(aRange, // OutputRange
+ aRange, // DefinitionRange
+ aFillGradient, &rAlphaGradient)) }))
+ };
+
+ // render this. Use container to not trigger decompose for temporary content
+ process(aContainerMaskedFillGradient);
+}
+
+void CairoPixelProcessor2D::processBitmapAlphaPrimitive2D(
+ const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaPrimitive2D)
+{
+ constexpr DrawModeFlags BITMAP(DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap
+ | DrawModeFlags::GrayBitmap);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+ const bool bDrawModeFlagsUsed(aDrawModeFlags & BITMAP);
+
+ if (bDrawModeFlagsUsed)
+ {
+ if (aDrawModeFlags & DrawModeFlags::BlackBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0, 0, 0)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else if (aDrawModeFlags & DrawModeFlags::WhiteBitmap)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(1, 1, 1)));
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ else // DrawModeFlags::GrayBitmap
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+ }
+
+ if (!rBitmapAlphaPrimitive2D.hasTransparency())
+ {
+ // do what CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D does
+ paintBitmapAlpha(rBitmapAlphaPrimitive2D.getBitmap(),
+ rBitmapAlphaPrimitive2D.getTransform());
+ }
+ else
+ {
+ // draw with alpha directly
+ paintBitmapAlpha(rBitmapAlphaPrimitive2D.getBitmap(),
+ rBitmapAlphaPrimitive2D.getTransform(),
+ rBitmapAlphaPrimitive2D.getTransparency());
+ }
+
+ if (bDrawModeFlagsUsed)
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::processTextSimplePortionPrimitive2D(
+ const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+{
+ if (SAL_LIKELY(mbRenderSimpleTextDirect))
+ {
+ renderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate, nullptr);
+ }
+ else
+ {
+ process(rCandidate);
+ }
+}
+
+void CairoPixelProcessor2D::processTextDecoratedPortionPrimitive2D(
+ const primitive2d::TextDecoratedPortionPrimitive2D& rCandidate)
+{
+ if (SAL_LIKELY(mbRenderDecoratedTextDirect))
+ {
+ if (!rCandidate.getOrCreateBrokenUpText().empty())
+ {
+ // if BrokenUpText/WordLineMode is used, go into recursion
+ // with single snippets
+ process(rCandidate.getOrCreateBrokenUpText());
+ return;
+ }
+
+ renderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate, &rCandidate);
+ }
+ else
+ {
+ process(rCandidate);
+ }
+}
+
+void CairoPixelProcessor2D::renderTextBackground(
+ const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate, double fAscent,
+ double fDescent, const basegfx::B2DHomMatrix& rTransform, double fTextWidth)
+{
+ cairo_save(mpRT);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, rTransform.a(), rTransform.b(), rTransform.c(), rTransform.d(),
+ rTransform.e(), rTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+ basegfx::BColor aFillColor(getFillColor(rTextCandidate.getTextFillColor().getBColor()));
+ aFillColor = maBColorModifierStack.getModifiedColor(aFillColor);
+ cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue());
+ cairo_rectangle(mpRT, 0.0, -fAscent, fTextWidth, fAscent + fDescent);
+ cairo_fill(mpRT);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::renderSalLayout(const std::unique_ptr<SalLayout>& rSalLayout,
+ const basegfx::BColor& rTextColor,
+ const basegfx::B2DHomMatrix& rTransform,
+ bool bAntiAliase) const
+{
+ cairo_save(mpRT);
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, rTransform.a(), rTransform.b(), rTransform.c(), rTransform.d(),
+ rTransform.e(), rTransform.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+ rSalLayout->drawSalLayout(mpRT, rTextColor, bAntiAliase);
+ cairo_restore(mpRT);
+}
+
+void CairoPixelProcessor2D::renderTextDecorationWithOptionalTransformAndColor(
+ const primitive2d::TextDecoratedPortionPrimitive2D& rDecoratedCandidate,
+ const basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose& rDecTrans,
+ const basegfx::B2DHomMatrix* pOptionalObjectTransform, const basegfx::BColor* pReplacementColor)
+{
+ // get decorations from Primitive (using original TextTransform),
+ // guaranteed the same visualization as a decomposition would create
+ const primitive2d::Primitive2DContainer& rDecorationGeometryContent(
+ rDecoratedCandidate.getOrCreateDecorationGeometryContent(
+ rDecTrans, rDecoratedCandidate.getText(), rDecoratedCandidate.getTextPosition(),
+ rDecoratedCandidate.getTextLength(), rDecoratedCandidate.getDXArray()));
+
+ if (rDecorationGeometryContent.empty())
+ {
+ // no decoration, done
+ return;
+ }
+
+ // modify ColorStack as needed - if needed
+ if (nullptr != pReplacementColor)
+ maBColorModifierStack.push(
+ std::make_shared<basegfx::BColorModifier_replace>(*pReplacementColor));
+
+ // modify transformation as needed - if needed
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+ if (nullptr != pOptionalObjectTransform)
+ {
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(*pOptionalObjectTransform);
+ setViewInformation2D(aViewInformation2D);
+ }
+
+ // render primitives
+ process(rDecorationGeometryContent);
+
+ // restore mods
+ if (nullptr != pOptionalObjectTransform)
+ setViewInformation2D(aLastViewInformation2D);
+ if (nullptr != pReplacementColor)
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::renderTextSimpleOrDecoratedPortionPrimitive2D(
+ const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate,
+ const primitive2d::TextDecoratedPortionPrimitive2D* pDecoratedCandidate)
+{
+ primitive2d::TextLayouterDevice aTextLayouter;
+ rTextCandidate.createTextLayouter(aTextLayouter);
+ std::unique_ptr<SalLayout> pSalLayout(rTextCandidate.createSalLayout(aTextLayouter));
+
+ if (!pSalLayout)
+ {
+ // got no layout, error. use decompose as fallback
+ process(rTextCandidate);
+ return;
+ }
+
+ // prepare local transformations
+ basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(
+ rTextCandidate.getTextTransform());
+ const basegfx::B2DHomMatrix aObjTransformWithoutScale(
+ basegfx::utils::createShearXRotateTranslateB2DHomMatrix(
+ aDecTrans.getShearX(), aDecTrans.getRotate(), aDecTrans.getTranslate()));
+ const basegfx::B2DHomMatrix aFullTextTransform(
+ getViewInformation2D().getObjectToViewTransformation() * aObjTransformWithoutScale);
+
+ if (!rTextCandidate.getTextFillColor().IsTransparent())
+ {
+ // render TextBackground first -> casts no shadow itself, so do independent of
+ // text shadow being activated
+ double fAscent(aTextLayouter.getFontAscent());
+ double fDescent(aTextLayouter.getFontDescent());
+
+ if (nullptr != pDecoratedCandidate
+ && primitive2d::TEXT_FONT_EMPHASIS_MARK_NONE
+ != pDecoratedCandidate->getTextEmphasisMark())
+ {
+ if (pDecoratedCandidate->getEmphasisMarkAbove())
+ fAscent += aTextLayouter.getTextHeight() * (250.0 / 1000.0);
+ if (pDecoratedCandidate->getEmphasisMarkBelow())
+ fDescent += aTextLayouter.getTextHeight() * (250.0 / 1000.0);
+ }
+
+ renderTextBackground(rTextCandidate, fAscent, fDescent, aFullTextTransform,
+ pSalLayout->GetTextWidth());
+ }
+
+ // get TextColor early, may have to be modified
+ basegfx::BColor aTextColor(getTextColor(rTextCandidate.getFontColor()));
+
+ if (rTextCandidate.hasShadow())
+ {
+ // Text shadow is constant, relative to font size, *not* rotated with
+ // text (always from top-left!)
+ static const double fFactor(1.0 / 24.0);
+ const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor);
+
+ // see ::ImplDrawSpecialText -> no longer simple fixed color
+ const basegfx::BColor aBlack(0.0, 0.0, 0.0);
+ basegfx::BColor aShadowColor(aBlack);
+ if (aBlack == aTextColor || aTextColor.luminance() < (8.0 / 255.0))
+ aShadowColor = COL_LIGHTGRAY.getBColor();
+ aShadowColor = maBColorModifierStack.getModifiedColor(aShadowColor);
+
+ // create shadow offset
+ const basegfx::B2DHomMatrix aShadowTransform(
+ basegfx::utils::createTranslateB2DHomMatrix(fTextShadowOffset, fTextShadowOffset));
+ const basegfx::B2DHomMatrix aShadowFullTextTransform(
+ // right to left: 1st the ObjTrans, then the shadow offset, last ObjToView. That way
+ // the shadow is always from top-left, independent of text rotation. Independent from
+ // thinking about if that is wanted (shadow direction *could* rotate with the text)
+ // this is what the office currently does -> do *not* change visualization (!)
+ getViewInformation2D().getObjectToViewTransformation() * aShadowTransform
+ * aObjTransformWithoutScale);
+
+ // render text as shadow
+ renderSalLayout(pSalLayout, aShadowColor, aShadowFullTextTransform,
+ getViewInformation2D().getUseAntiAliasing());
+
+ if (rTextCandidate.hasTextDecoration())
+ {
+ const basegfx::B2DHomMatrix aTransform(getViewInformation2D().getObjectTransformation()
+ * aShadowTransform);
+ renderTextDecorationWithOptionalTransformAndColor(*pDecoratedCandidate, aDecTrans,
+ &aTransform, &aShadowColor);
+ }
+ }
+ if (rTextCandidate.hasOutline())
+ {
+ // render as outline
+ aTextColor = maBColorModifierStack.getModifiedColor(aTextColor);
+ basegfx::B2DHomMatrix aInvViewTransform;
+
+ // discrete offsets defined here to easily allow to change them,
+ // e.g. if more 'fat' outline is wanted, it may be increased to 1.5
+ constexpr double fZero(0.0);
+ constexpr double fPlus(1.0);
+ constexpr double fMinus(-1.0);
+
+ static constexpr std::array<std::pair<double, double>, 8> offsets{
+ std::pair<double, double>{ fMinus, fMinus }, std::pair<double, double>{ fZero, fMinus },
+ std::pair<double, double>{ fPlus, fMinus }, std::pair<double, double>{ fMinus, fZero },
+ std::pair<double, double>{ fPlus, fZero }, std::pair<double, double>{ fMinus, fPlus },
+ std::pair<double, double>{ fZero, fPlus }, std::pair<double, double>{ fPlus, fPlus }
+ };
+
+ if (rTextCandidate.hasTextDecoration())
+ {
+ // to use discrete offset (pixels) we will need the back-transform from
+ // discrete view coordinates to 'world' coordinates (logic view coordinates),
+ // this is the inverse ViewTransformation.
+ // NOTE: Alternatively we could calculate the lengths for fPlus/fMinus in
+ // logic view coordinates, but would need to create another B2DHomMatrix and
+ // to do it correct would need to handle two vectors holding the directions,
+ // else - if ever someone will rotate/shear that transformation - it would
+ // break
+ aInvViewTransform = getViewInformation2D().getViewTransformation();
+ aInvViewTransform.invert();
+ }
+
+ for (const auto& offset : offsets)
+ {
+ const basegfx::B2DHomMatrix aDiscreteOffset(
+ basegfx::utils::createTranslateB2DHomMatrix(offset.first, offset.second));
+ renderSalLayout(pSalLayout, aTextColor, aDiscreteOffset * aFullTextTransform,
+ getViewInformation2D().getUseAntiAliasing());
+ if (rTextCandidate.hasTextDecoration())
+ {
+ basegfx::B2DHomMatrix aTransform(
+ aInvViewTransform * aDiscreteOffset
+ * getViewInformation2D().getObjectToViewTransformation());
+ renderTextDecorationWithOptionalTransformAndColor(*pDecoratedCandidate, aDecTrans,
+ &aTransform);
+ }
+ }
+
+ // at (center, center) paint in COL_WHITE
+ aTextColor = maBColorModifierStack.getModifiedColor(COL_WHITE.getBColor());
+ renderSalLayout(pSalLayout, aTextColor, aFullTextTransform,
+ getViewInformation2D().getUseAntiAliasing());
+ if (rTextCandidate.hasTextDecoration())
+ {
+ renderTextDecorationWithOptionalTransformAndColor(*pDecoratedCandidate, aDecTrans,
+ nullptr, &aTextColor);
+ }
+
+ // paint is complete, Outline and TextRelief cannot be combined, return
+ return;
+ }
+
+ if (rTextCandidate.hasTextRelief())
+ {
+ // manipulate TextColor for final text paint below (see ::ImplDrawSpecialText)
+ if (aTextColor == COL_BLACK.getBColor())
+ aTextColor = COL_WHITE.getBColor();
+
+ // relief offset defined here to easily allow to change them
+ // see ::ImplDrawSpecialText and the comment @ 'nOff += mnDPIX/300'
+ const bool bEmboss(primitive2d::TEXT_RELIEF_EMBOSSED
+ == pDecoratedCandidate->getTextRelief());
+ constexpr double fReliefOffset(1.1);
+ const double fOffset(bEmboss ? fReliefOffset : -fReliefOffset);
+ const basegfx::B2DHomMatrix aDiscreteOffset(
+ basegfx::utils::createTranslateB2DHomMatrix(fOffset, fOffset));
+
+ // see aReliefColor in ::ImplDrawSpecialText
+ basegfx::BColor aReliefColor(COL_LIGHTGRAY.getBColor());
+ if (COL_WHITE.getBColor() == aTextColor)
+ aReliefColor = COL_BLACK.getBColor();
+ aReliefColor = maBColorModifierStack.getModifiedColor(aReliefColor);
+
+ // render relief text with offset
+ renderSalLayout(pSalLayout, aReliefColor, aDiscreteOffset * aFullTextTransform,
+ getViewInformation2D().getUseAntiAliasing());
+
+ if (rTextCandidate.hasTextDecoration())
+ {
+ basegfx::B2DHomMatrix aInvViewTransform(getViewInformation2D().getViewTransformation());
+ aInvViewTransform.invert();
+ const basegfx::B2DHomMatrix aTransform(
+ aInvViewTransform * aDiscreteOffset
+ * getViewInformation2D().getObjectToViewTransformation());
+ renderTextDecorationWithOptionalTransformAndColor(*pDecoratedCandidate, aDecTrans,
+ &aTransform, &aReliefColor);
+ }
+ }
+
+ // render text
+ aTextColor = maBColorModifierStack.getModifiedColor(aTextColor);
+ renderSalLayout(pSalLayout, aTextColor, aFullTextTransform,
+ getViewInformation2D().getUseAntiAliasing());
+
+ if (rTextCandidate.hasTextDecoration())
+ {
+ // render using same geometry/primitives that a decompose would
+ // create -> safe to get the same visualization for both
+ renderTextDecorationWithOptionalTransformAndColor(*pDecoratedCandidate, aDecTrans);
+ }
+}
+
+bool CairoPixelProcessor2D::handleSvgGradientHelper(
+ const primitive2d::SvgGradientHelper& rCandidate)
+{
+ // check PolyPolygon to be filled
+ const basegfx::B2DPolyPolygon& rPolyPolygon(rCandidate.getPolyPolygon());
+
+ if (!rPolyPolygon.count())
+ {
+ // no PolyPolygon, done
+ return true;
+ }
+
+ // calculate visible range
+ basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange());
+ aPolyPolygonRange.transform(getViewInformation2D().getObjectToViewTransformation());
+ if (!getDiscreteViewRange(mpRT).overlaps(aPolyPolygonRange))
+ {
+ // not visible, done
+ return true;
+ }
+
+ if (!rCandidate.getCreatesContent())
+ {
+ // creates no content, done
+ return true;
+ }
+
+ basegfx::BColor aSimpleColor;
+ bool bDrawSimple(false);
+ primitive2d::SvgGradientEntryVector::const_reference aEntry(
+ rCandidate.getGradientEntries().back());
+
+ constexpr DrawModeFlags SIMPLE_GRADIENT(DrawModeFlags::BlackGradient
+ | DrawModeFlags::WhiteGradient
+ | DrawModeFlags::SettingsGradient);
+ if (getViewInformation2D().getDrawModeFlags() & SIMPLE_GRADIENT)
+ {
+ aSimpleColor = getGradientColor(aSimpleColor);
+ bDrawSimple = true;
+ }
+
+ if (!bDrawSimple && rCandidate.getSingleEntry())
+ {
+ // only one color entry, fill with last existing color, done
+ aSimpleColor = aEntry.getColor();
+ bDrawSimple = true;
+ }
+
+ if (bDrawSimple)
+ {
+ paintPolyPolygonRGBA(rCandidate.getPolyPolygon(), aSimpleColor, 1.0 - aEntry.getOpacity());
+ return true;
+ }
+
+ return false;
+}
+
+void CairoPixelProcessor2D::processSvgLinearGradientPrimitive2D(
+ const primitive2d::SvgLinearGradientPrimitive2D& rCandidate)
+{
+ // check for simple cases, returns if all necessary is already done
+ if (handleSvgGradientHelper(rCandidate))
+ {
+ // simple case, handled, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ const bool bTemporaryGrayColorModifier(getViewInformation2D().getDrawModeFlags()
+ & DrawModeFlags::GrayGradient);
+ if (bTemporaryGrayColorModifier)
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+
+ // set ObjectToView as regular transformation at CairoContext
+ const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation());
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(),
+ aTrans.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // create pattern using unit coordinates. Unit coordinates here means that
+ // the transformation provided by the primitive maps the linear gradient
+ // to (0,0) -> (1,0) at the unified object coordinates, along the unified
+ // X-Axis
+ cairo_pattern_t* pPattern(cairo_pattern_create_linear(0, 0, 1, 0));
+
+ // get pre-defined UnitGradientToObject transformation from primitive
+ // and invert to get ObjectToUnitGradient transform
+ basegfx::B2DHomMatrix aObjectToUnitGradient(
+ rCandidate.createUnitGradientToObjectTransformation());
+ aObjectToUnitGradient.invert();
+
+ // set ObjectToUnitGradient as transformation at gradient - patterns
+ // need the inverted transformation, see cairo documentation
+ cairo_matrix_init(&aMatrix, aObjectToUnitGradient.a(), aObjectToUnitGradient.b(),
+ aObjectToUnitGradient.c(), aObjectToUnitGradient.d(),
+ aObjectToUnitGradient.e(), aObjectToUnitGradient.f());
+ cairo_pattern_set_matrix(pPattern, &aMatrix);
+
+ // add color stops
+ const primitive2d::SvgGradientEntryVector& rGradientEntries(rCandidate.getGradientEntries());
+
+ for (const auto& entry : rGradientEntries)
+ {
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(entry.getColor()));
+ cairo_pattern_add_color_stop_rgba(pPattern, entry.getOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(), entry.getOpacity());
+ }
+
+ // set SpreadMethod. Note that we have no SpreadMethod::None because the
+ // source is SVG and SVG does also not have that (checked that)
+ switch (rCandidate.getSpreadMethod())
+ {
+ case primitive2d::SpreadMethod::Pad:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_PAD);
+ break;
+ case primitive2d::SpreadMethod::Reflect:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REFLECT);
+ break;
+ case primitive2d::SpreadMethod::Repeat:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REPEAT);
+ break;
+ }
+
+ // get PathGeometry & paint it filed with gradient
+ cairo_new_path(mpRT);
+ getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon());
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+
+ // cleanup
+ cairo_pattern_destroy(pPattern);
+ cairo_restore(mpRT);
+
+ if (bTemporaryGrayColorModifier)
+ // cleanup temporary BColorModifier
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::processSvgRadialGradientPrimitive2D(
+ const primitive2d::SvgRadialGradientPrimitive2D& rCandidate)
+{
+ // check for simple cases, returns if all necessary is already done
+ if (handleSvgGradientHelper(rCandidate))
+ {
+ // simple case, handled, done
+ return;
+ }
+
+ cairo_save(mpRT);
+
+ bool bTemporaryGrayColorModifier(false);
+ if (getViewInformation2D().getDrawModeFlags() & DrawModeFlags::GrayGradient)
+ {
+ bTemporaryGrayColorModifier = true;
+ const basegfx::BColorModifierSharedPtr aBColorModifier(
+ std::make_shared<basegfx::BColorModifier_gray>());
+ maBColorModifierStack.push(aBColorModifier);
+ }
+
+ // set ObjectToView as regular transformation at CairoContext
+ const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation());
+ cairo_matrix_t aMatrix;
+ cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(),
+ aTrans.f());
+ cairo_set_matrix(mpRT, &aMatrix);
+
+ // get pre-defined UnitGradientToObject transformation from primitive
+ // and invert to get ObjectToUnitGradient transform
+ basegfx::B2DHomMatrix aObjectToUnitGradient(
+ rCandidate.createUnitGradientToObjectTransformation());
+ aObjectToUnitGradient.invert();
+
+ // prepare empty FocalVector
+ basegfx::B2DVector aFocalVector(0.0, 0.0);
+
+ if (rCandidate.isFocalSet())
+ {
+ // FocalPoint is used, create ObjectTransform based on polygon range
+ const basegfx::B2DRange aPolyRange(rCandidate.getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight, aPolyRange.getMinX(), aPolyRange.getMinY()));
+
+ // get vector, then transform to object coordinates, then to
+ // UnitGradient coordinates to be in the needed coordinate system
+ aFocalVector = basegfx::B2DVector(rCandidate.getStart() - rCandidate.getFocal());
+ aFocalVector *= aObjectTransform;
+ aFocalVector *= aObjectToUnitGradient;
+ }
+
+ // create pattern using unit coordinates. Unit coordinates here means that
+ // the transformation provided by the primitive maps the radial gradient
+ // to (0,0) as center, 1.0 as radius - which is the unit circle. The
+ // FocalPoint (if used) has to be relative to that, so - since unified
+ // center is at (0, 0), handling as vector is sufficient
+ cairo_pattern_t* pPattern(
+ cairo_pattern_create_radial(0, 0, 0, aFocalVector.getX(), aFocalVector.getY(), 1));
+
+ // set ObjectToUnitGradient as transformation at gradient - patterns
+ // need the inverted transformation, see cairo documentation
+ cairo_matrix_init(&aMatrix, aObjectToUnitGradient.a(), aObjectToUnitGradient.b(),
+ aObjectToUnitGradient.c(), aObjectToUnitGradient.d(),
+ aObjectToUnitGradient.e(), aObjectToUnitGradient.f());
+ cairo_pattern_set_matrix(pPattern, &aMatrix);
+
+ // add color stops
+ const primitive2d::SvgGradientEntryVector& rGradientEntries(rCandidate.getGradientEntries());
+
+ for (const auto& entry : rGradientEntries)
+ {
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(entry.getColor()));
+ cairo_pattern_add_color_stop_rgba(pPattern, entry.getOffset(), aColor.getRed(),
+ aColor.getGreen(), aColor.getBlue(), entry.getOpacity());
+ }
+
+ // set SpreadMethod
+ switch (rCandidate.getSpreadMethod())
+ {
+ case primitive2d::SpreadMethod::Pad:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_PAD);
+ break;
+ case primitive2d::SpreadMethod::Reflect:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REFLECT);
+ break;
+ case primitive2d::SpreadMethod::Repeat:
+ cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REPEAT);
+ break;
+ }
+
+ // get PathGeometry & paint it filed with gradient
+ cairo_new_path(mpRT);
+ getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon());
+ cairo_set_source(mpRT, pPattern);
+ cairo_fill(mpRT);
+
+ // cleanup
+ cairo_pattern_destroy(pPattern);
+ cairo_restore(mpRT);
+
+ if (bTemporaryGrayColorModifier)
+ // cleanup temporary BColorModifier
+ maBColorModifierStack.pop();
+}
+
+void CairoPixelProcessor2D::processControlPrimitive2D(
+ const primitive2d::ControlPrimitive2D& rControlPrimitive)
+{
+ // find out if the control is already visualized as a VCL-ChildWindow
+ bool bControlIsVisibleAsChildWindow(rControlPrimitive.isVisibleAsChildWindow());
+
+ // tdf#131281 FormControl rendering for Tiled Rendering
+ if (bControlIsVisibleAsChildWindow && comphelper::LibreOfficeKit::isActive())
+ {
+ // Do force paint when we are in Tiled Renderer and FormControl is 'visible'
+ bControlIsVisibleAsChildWindow = false;
+ }
+
+ if (bControlIsVisibleAsChildWindow)
+ {
+ // f the control is already visualized as a VCL-ChildWindow it
+ // does not need to be painted at all
+ return;
+ }
+
+ bool bDone(false);
+
+ try
+ {
+ if (nullptr != mpTargetOutputDevice)
+ {
+ const uno::Reference<awt::XGraphics> xTargetGraphics(
+ mpTargetOutputDevice->CreateUnoGraphics());
+
+ if (xTargetGraphics.is())
+ {
+ // Needs to be drawn. Link new graphics and view
+ const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
+ uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics());
+ xControlView->setGraphics(xTargetGraphics);
+
+ // get position
+ const basegfx::B2DHomMatrix aObjectToPixel(
+ getViewInformation2D().getObjectToViewTransformation()
+ * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0));
+
+ xControlView->draw(basegfx::fround(aTopLeftPixel.getX()),
+ basegfx::fround(aTopLeftPixel.getY()));
+
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
+ bDone = true;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // #i116763# removing since there is a good alternative when the xControlView
+ // is not found and it is allowed to happen
+ // DBG_UNHANDLED_EXCEPTION();
+ }
+
+ if (!bDone)
+ {
+ // process recursively and use the decomposition as Bitmap
+ process(rControlPrimitive);
+ }
+}
+
+void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround()
+{
+ static bool bAlreadyCheckedIfNeeded(false);
+ static bool bIsNeeded(false);
+
+ if (!bAlreadyCheckedIfNeeded)
+ {
+ // check once for office runtime: is workaround needed?
+ bAlreadyCheckedIfNeeded = true;
+ bIsNeeded = checkCoordinateLimitWorkaroundNeededForUsedCairo();
+ }
+
+ if (!bIsNeeded)
+ {
+ // we have a working cairo, so workaround is not needed
+ // and mbCairoCoordinateLimitWorkaroundActive can stay false
+ return;
+ }
+
+ // get discrete size (pixels)
+ basegfx::B2DRange aLogicViewRange(getDiscreteViewRange(mpRT));
+
+ // transform to world coordinates -> logic view range
+ basegfx::B2DHomMatrix aInvViewTrans(getViewInformation2D().getViewTransformation());
+ aInvViewTrans.invert();
+ aLogicViewRange.transform(aInvViewTrans);
+
+ // create 1<<23 CairoCoordinate limit from 24.8 internal format
+ // and a range fitting to it (just once, this is static)
+ constexpr double fNumCairoMax(1 << 23);
+ static const basegfx::B2DRange aNumericalCairoLimit(-fNumCairoMax, -fNumCairoMax,
+ fNumCairoMax - 1.0, fNumCairoMax - 1.0);
+
+ if (!aLogicViewRange.isEmpty() && !aNumericalCairoLimit.isInside(aLogicViewRange))
+ {
+ // aLogicViewRange is not completely inside region covered by
+ // 24.8 cairo format, thus workaround is needed, set flag
+ mbCairoCoordinateLimitWorkaroundActive = true;
+ }
+}
+
+basegfx::BColor CairoPixelProcessor2D::getLineColor(const basegfx::BColor& rColor) const
+{
+ constexpr DrawModeFlags LINE(DrawModeFlags::BlackLine | DrawModeFlags::WhiteLine
+ | DrawModeFlags::GrayLine | DrawModeFlags::SettingsLine);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+
+ if (!(aDrawModeFlags & LINE))
+ return rColor;
+
+ if (aDrawModeFlags & DrawModeFlags::BlackLine)
+ return basegfx::BColor(0, 0, 0);
+
+ if (aDrawModeFlags & DrawModeFlags::WhiteLine)
+ return basegfx::BColor(1, 1, 1);
+
+ if (aDrawModeFlags & DrawModeFlags::GrayLine)
+ {
+ const double fLuminance(rColor.luminance());
+ return basegfx::BColor(fLuminance, fLuminance, fLuminance);
+ }
+
+ // DrawModeFlags::SettingsLine
+ if (aDrawModeFlags & DrawModeFlags::SettingsForSelection)
+ return Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
+
+ return Application::GetSettings().GetStyleSettings().GetWindowTextColor().getBColor();
+}
+
+basegfx::BColor CairoPixelProcessor2D::getFillColor(const basegfx::BColor& rColor) const
+{
+ constexpr DrawModeFlags FILL(DrawModeFlags::BlackFill | DrawModeFlags::WhiteFill
+ | DrawModeFlags::GrayFill | DrawModeFlags::SettingsFill);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+
+ if (!(aDrawModeFlags & FILL))
+ return rColor;
+
+ if (aDrawModeFlags & DrawModeFlags::BlackFill)
+ return basegfx::BColor(0, 0, 0);
+
+ if (aDrawModeFlags & DrawModeFlags::WhiteFill)
+ return basegfx::BColor(1, 1, 1);
+
+ if (aDrawModeFlags & DrawModeFlags::GrayFill)
+ {
+ const double fLuminance(rColor.luminance());
+ return basegfx::BColor(fLuminance, fLuminance, fLuminance);
+ }
+
+ // DrawModeFlags::SettingsFill
+ if (aDrawModeFlags & DrawModeFlags::SettingsForSelection)
+ return Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
+
+ return Application::GetSettings().GetStyleSettings().GetWindowColor().getBColor();
+}
+
+basegfx::BColor CairoPixelProcessor2D::getTextColor(const basegfx::BColor& rColor) const
+{
+ constexpr DrawModeFlags TEXT(DrawModeFlags::BlackText | DrawModeFlags::WhiteText
+ | DrawModeFlags::GrayText | DrawModeFlags::SettingsText);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+
+ if (!(aDrawModeFlags & TEXT))
+ return rColor;
+
+ if (aDrawModeFlags & DrawModeFlags::BlackText)
+ return basegfx::BColor(0, 0, 0);
+
+ if (aDrawModeFlags & DrawModeFlags::WhiteText)
+ return basegfx::BColor(1, 1, 1);
+
+ if (aDrawModeFlags & DrawModeFlags::GrayText)
+ {
+ const double fLuminance(rColor.luminance());
+ return basegfx::BColor(fLuminance, fLuminance, fLuminance);
+ }
+
+ // DrawModeFlags::SettingsText
+ if (aDrawModeFlags & DrawModeFlags::SettingsForSelection)
+ return Application::GetSettings().GetStyleSettings().GetHighlightTextColor().getBColor();
+
+ return Application::GetSettings().GetStyleSettings().GetWindowTextColor().getBColor();
+}
+
+basegfx::BColor CairoPixelProcessor2D::getGradientColor(const basegfx::BColor& rColor) const
+{
+ constexpr DrawModeFlags GRADIENT(DrawModeFlags::BlackGradient | DrawModeFlags::GrayGradient
+ | DrawModeFlags::WhiteGradient
+ | DrawModeFlags::SettingsGradient);
+ const DrawModeFlags aDrawModeFlags(getViewInformation2D().getDrawModeFlags());
+
+ if (!(aDrawModeFlags & GRADIENT))
+ return rColor;
+
+ if (aDrawModeFlags & DrawModeFlags::BlackGradient)
+ return basegfx::BColor(0, 0, 0);
+
+ if (aDrawModeFlags & DrawModeFlags::WhiteGradient)
+ return basegfx::BColor(1, 1, 1);
+
+ if (aDrawModeFlags & DrawModeFlags::GrayGradient)
+ {
+ const double fLuminance(rColor.luminance());
+ return basegfx::BColor(fLuminance, fLuminance, fLuminance);
+ }
+
+ // DrawModeFlags::SettingsGradient
+ if (aDrawModeFlags & DrawModeFlags::SettingsForSelection)
+ return Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
+
+ return Application::GetSettings().GetStyleSettings().GetWindowColor().getBColor();
+}
+
+void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ const cairo_status_t aStart(cairo_status(mpRT));
+
+ switch (rCandidate.getPrimitive2DID())
+ {
+ // geometry that *has* to be processed
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
+ {
+ processBitmapPrimitive2D(
+ static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ {
+ processPointArrayPrimitive2D(
+ static_cast<const primitive2d::PointArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
+ {
+ processPolygonHairlinePrimitive2D(
+ static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
+ {
+ processPolyPolygonColorPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ // embedding/groups that *have* to be processed
+ case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D:
+ {
+ processTransparencePrimitive2D(
+ static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_INVERTPRIMITIVE2D:
+ {
+ processInvertPrimitive2D(
+ static_cast<const primitive2d::InvertPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
+ {
+ processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
+ {
+ processModifiedColorPrimitive2D(
+ static_cast<const primitive2d::ModifiedColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
+ {
+ processTransformPrimitive2D(
+ static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
+ break;
+ }
+
+ // geometry that *may* be processed due to being able to do it better
+ // then using the decomposition
+ case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
+ {
+ processUnifiedTransparencePrimitive2D(
+ static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
+ {
+ processMarkerArrayPrimitive2D(
+ static_cast<const primitive2d::MarkerArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D:
+ {
+ processBackgroundColorPrimitive2D(
+ static_cast<const primitive2d::BackgroundColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ processPolygonStrokePrimitive2D(
+ static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_LINERECTANGLEPRIMITIVE2D:
+ {
+ processLineRectanglePrimitive2D(
+ static_cast<const primitive2d::LineRectanglePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLEDRECTANGLEPRIMITIVE2D:
+ {
+ processFilledRectanglePrimitive2D(
+ static_cast<const primitive2d::FilledRectanglePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SINGLELINEPRIMITIVE2D:
+ {
+ processSingleLinePrimitive2D(
+ static_cast<const primitive2d::SingleLinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
+ {
+ processFillGraphicPrimitive2D(
+ static_cast<const primitive2d::FillGraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D:
+ {
+ processFillGradientPrimitive2D(
+ static_cast<const primitive2d::FillGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D:
+ {
+ processPolyPolygonRGBAPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonRGBAPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D:
+ {
+ processBitmapAlphaPrimitive2D(
+ static_cast<const primitive2d::BitmapAlphaPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+ {
+ processPolyPolygonAlphaGradientPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonAlphaGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
+ {
+ processTextSimplePortionPrimitive2D(
+ static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
+ {
+ processTextDecoratedPortionPrimitive2D(
+ static_cast<const primitive2d::TextDecoratedPortionPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D:
+ {
+ processSvgLinearGradientPrimitive2D(
+ static_cast<const primitive2d::SvgLinearGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D:
+ {
+ processSvgRadialGradientPrimitive2D(
+ static_cast<const primitive2d::SvgRadialGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D:
+ {
+ processControlPrimitive2D(
+ static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
+ break;
+ }
+
+ // continue with decompose
+ default:
+ {
+ SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(
+ rCandidate.getPrimitive2DID()));
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+
+ const cairo_status_t aEnd(cairo_status(mpRT));
+
+ if (aStart != aEnd)
+ {
+ SAL_WARN("drawinglayer", "CairoSDPR: Cairo status problem (!)");
+ }
+}
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/drawinglayer/source/processor2d/contourextractor2d.cxx b/drawinglayer/source/processor2d/contourextractor2d.cxx
index 8abec2f50f9d..94d6b109ecfb 100644
--- a/drawinglayer/source/processor2d/contourextractor2d.cxx
+++ b/drawinglayer/source/processor2d/contourextractor2d.cxx
@@ -19,7 +19,7 @@
#include <drawinglayer/processor2d/contourextractor2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
@@ -30,16 +30,12 @@
#include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
-using namespace com::sun::star;
-
-
namespace drawinglayer::processor2d
{
ContourExtractor2D::ContourExtractor2D(
const geometry::ViewInformation2D& rViewInformation,
bool bExtractFillOnly)
: BaseProcessor2D(rViewInformation),
- maExtractedContour(),
mbExtractFillOnly(bExtractFillOnly)
{
}
@@ -124,20 +120,15 @@ namespace drawinglayer::processor2d
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process content
process(rTransformCandidate.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
break;
}
diff --git a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
new file mode 100644
index 000000000000..82f51fdc4356
--- /dev/null
+++ b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
@@ -0,0 +1,2177 @@
+/* -*- 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>
+
+// win-specific
+#include <prewin.h>
+#include <d2d1.h>
+#include <d2d1_1.h>
+#include <postwin.h>
+
+#include <drawinglayer/processor2d/d2dpixelprocessor2d.hxx>
+#include <drawinglayer/processor2d/SDPRProcessor2dTools.hxx>
+#include <sal/log.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/outdev.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/Tools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/invertprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/converters.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/utils/systemdependentdata.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+class ID2D1GlobalFactoryProvider
+{
+ sal::systools::COMReference<ID2D1Factory> mpD2DFactory;
+
+public:
+ ID2D1GlobalFactoryProvider()
+ : mpD2DFactory(nullptr)
+ {
+ const HRESULT hr(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ __uuidof(ID2D1Factory), nullptr,
+ reinterpret_cast<void**>(&mpD2DFactory)));
+
+ if (!SUCCEEDED(hr))
+ mpD2DFactory.clear();
+ }
+
+ sal::systools::COMReference<ID2D1Factory>& getID2D1Factory() { return mpD2DFactory; }
+};
+
+ID2D1GlobalFactoryProvider aID2D1GlobalFactoryProvider;
+
+class ID2D1GlobalRenderTargetProvider
+{
+ sal::systools::COMReference<ID2D1DCRenderTarget> mpID2D1DCRenderTarget;
+
+public:
+ ID2D1GlobalRenderTargetProvider()
+ : mpID2D1DCRenderTarget()
+ {
+ }
+
+ sal::systools::COMReference<ID2D1DCRenderTarget>& getID2D1DCRenderTarget()
+ {
+ if (!mpID2D1DCRenderTarget && aID2D1GlobalFactoryProvider.getID2D1Factory())
+ {
+ const D2D1_RENDER_TARGET_PROPERTIES aRTProps(D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE), //D2D1_ALPHA_MODE_PREMULTIPLIED),
+ 0, 0, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT));
+
+ const HRESULT hr(aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateDCRenderTarget(
+ &aRTProps, &mpID2D1DCRenderTarget));
+
+ // interestingly this ID2D1DCRenderTarget already works and can hold
+ // created ID2D1Bitmap(s) in RenderTarget-specific form, *without*
+ // any call to "BindDC", thus *without* the need of a real HDC - nice :-)
+ // When that would be needed, Application::GetDefaultDevice() would need
+ // to have a HDC that is valid during LO's lifetime.
+
+ if (!SUCCEEDED(hr))
+ mpID2D1DCRenderTarget.clear();
+ }
+
+ return mpID2D1DCRenderTarget;
+ }
+};
+
+ID2D1GlobalRenderTargetProvider aID2D1GlobalRenderTargetProvider;
+
+class SystemDependentData_ID2D1PathGeometry : public basegfx::SystemDependentData
+{
+private:
+ sal::systools::COMReference<ID2D1PathGeometry> mpID2D1PathGeometry;
+
+public:
+ SystemDependentData_ID2D1PathGeometry(
+ sal::systools::COMReference<ID2D1PathGeometry>& rID2D1PathGeometry)
+ : basegfx::SystemDependentData(Application::GetSystemDependentDataManager(),
+ basegfx::SDD_Type::SDDType_ID2D1PathGeometry)
+ , mpID2D1PathGeometry(rID2D1PathGeometry)
+ {
+ }
+
+ const sal::systools::COMReference<ID2D1PathGeometry>& getID2D1PathGeometry() const
+ {
+ return mpID2D1PathGeometry;
+ }
+ virtual sal_Int64 estimateUsageInBytes() const override;
+};
+
+sal_Int64 SystemDependentData_ID2D1PathGeometry::estimateUsageInBytes() const
+{
+ sal_Int64 aRetval(0);
+
+ if (getID2D1PathGeometry())
+ {
+ UINT32 nCount(0);
+ const HRESULT hr(getID2D1PathGeometry()->GetSegmentCount(&nCount));
+
+ if (SUCCEEDED(hr))
+ {
+ // without completely receiving and tracing the GeometrySink
+ // do a rough estimation - each segment is 2D, so has two doubles.
+ // Some are beziers, so add some guessed buffer for two additional
+ // control points
+ aRetval = static_cast<sal_Int64>(nCount) * (6 * sizeof(double));
+ }
+ }
+
+ return aRetval;
+}
+
+basegfx::B2DPoint impPixelSnap(const basegfx::B2DPolygon& rPolygon,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation,
+ sal_uInt32 nIndex)
+{
+ const sal_uInt32 nCount(rPolygon.count());
+
+ // get the data
+ const basegfx::B2ITuple aPrevTuple(
+ basegfx::fround(rViewInformation.getObjectToViewTransformation()
+ * rPolygon.getB2DPoint((nIndex + nCount - 1) % nCount)));
+ const basegfx::B2DPoint aCurrPoint(rViewInformation.getObjectToViewTransformation()
+ * rPolygon.getB2DPoint(nIndex));
+ const basegfx::B2ITuple aCurrTuple(basegfx::fround(aCurrPoint));
+ const basegfx::B2ITuple aNextTuple(
+ basegfx::fround(rViewInformation.getObjectToViewTransformation()
+ * rPolygon.getB2DPoint((nIndex + 1) % nCount)));
+
+ // get the states
+ const bool bPrevVertical(aPrevTuple.getX() == aCurrTuple.getX());
+ const bool bNextVertical(aNextTuple.getX() == aCurrTuple.getX());
+ const bool bPrevHorizontal(aPrevTuple.getY() == aCurrTuple.getY());
+ const bool bNextHorizontal(aNextTuple.getY() == aCurrTuple.getY());
+ const bool bSnapX(bPrevVertical || bNextVertical);
+ const bool bSnapY(bPrevHorizontal || bNextHorizontal);
+
+ if (bSnapX || bSnapY)
+ {
+ basegfx::B2DPoint aSnappedPoint(bSnapX ? aCurrTuple.getX() : aCurrPoint.getX(),
+ bSnapY ? aCurrTuple.getY() : aCurrPoint.getY());
+
+ aSnappedPoint *= rViewInformation.getInverseObjectToViewTransformation();
+
+ return aSnappedPoint;
+ }
+
+ return rPolygon.getB2DPoint(nIndex);
+}
+
+void addB2DPolygonToPathGeometry(sal::systools::COMReference<ID2D1GeometrySink>& rSink,
+ const basegfx::B2DPolygon& rPolygon,
+ const drawinglayer::geometry::ViewInformation2D* pViewInformation)
+{
+ const sal_uInt32 nPointCount(rPolygon.count());
+ const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nPointCount : nPointCount - 1);
+ basegfx::B2DCubicBezier aEdge;
+
+ for (sal_uInt32 a(0); a < nEdgeCount; a++)
+ {
+ rPolygon.getBezierSegment(a, aEdge);
+
+ const basegfx::B2DPoint aEndPoint(
+ nullptr == pViewInformation
+ ? aEdge.getEndPoint()
+ : impPixelSnap(rPolygon, *pViewInformation, (a + 1) % nPointCount));
+
+ if (aEdge.isBezier())
+ {
+ rSink->AddBezier(
+ D2D1::BezierSegment(D2D1::Point2F(aEdge.getControlPointA().getX(),
+ aEdge.getControlPointA().getY()), //C1
+ D2D1::Point2F(aEdge.getControlPointB().getX(),
+ aEdge.getControlPointB().getY()), //c2
+ D2D1::Point2F(aEndPoint.getX(), aEndPoint.getY()))); //end
+ }
+ else
+ {
+ rSink->AddLine(D2D1::Point2F(aEndPoint.getX(), aEndPoint.getY()));
+ }
+ }
+}
+
+std::shared_ptr<SystemDependentData_ID2D1PathGeometry>
+getOrCreatePathGeometry(const basegfx::B2DPolygon& rPolygon,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation)
+{
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1PathGeometry(
+ rPolygon.getSystemDependentData<SystemDependentData_ID2D1PathGeometry>(
+ basegfx::SDD_Type::SDDType_ID2D1PathGeometry));
+
+ if (pSystemDependentData_ID2D1PathGeometry)
+ {
+ if (rViewInformation.getPixelSnapHairline())
+ {
+ // do not buffer when PixelSnap is active
+ pSystemDependentData_ID2D1PathGeometry.reset();
+ }
+ else
+ {
+ // use and return buffered data
+ return pSystemDependentData_ID2D1PathGeometry;
+ }
+ }
+
+ sal::systools::COMReference<ID2D1PathGeometry> pID2D1PathGeometry;
+ HRESULT hr(
+ aID2D1GlobalFactoryProvider.getID2D1Factory()->CreatePathGeometry(&pID2D1PathGeometry));
+ const sal_uInt32 nPointCount(rPolygon.count());
+
+ if (SUCCEEDED(hr) && nPointCount)
+ {
+ sal::systools::COMReference<ID2D1GeometrySink> pSink;
+ hr = pID2D1PathGeometry->Open(&pSink);
+
+ if (SUCCEEDED(hr) && pSink)
+ {
+ const basegfx::B2DPoint aStart(rViewInformation.getPixelSnapHairline()
+ ? rPolygon.getB2DPoint(0)
+ : impPixelSnap(rPolygon, rViewInformation, 0));
+
+ pSink->BeginFigure(D2D1::Point2F(aStart.getX(), aStart.getY()),
+ D2D1_FIGURE_BEGIN_HOLLOW);
+ addB2DPolygonToPathGeometry(pSink, rPolygon, &rViewInformation);
+ pSink->EndFigure(rPolygon.isClosed() ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
+ pSink->Close();
+ }
+ }
+
+ // add to buffering mechanism
+ if (pID2D1PathGeometry)
+ {
+ if (rViewInformation.getPixelSnapHairline() || nPointCount <= 4)
+ {
+ // do not buffer when PixelSnap is active or small polygon
+ return std::make_shared<SystemDependentData_ID2D1PathGeometry>(pID2D1PathGeometry);
+ }
+ else
+ {
+ return rPolygon.addOrReplaceSystemDependentData<SystemDependentData_ID2D1PathGeometry>(
+ pID2D1PathGeometry);
+ }
+ }
+
+ return std::shared_ptr<SystemDependentData_ID2D1PathGeometry>();
+}
+
+std::shared_ptr<SystemDependentData_ID2D1PathGeometry>
+getOrCreateFillGeometry(const basegfx::B2DPolyPolygon& rPolyPolygon)
+{
+ // try to access buffered data
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1PathGeometry(
+ rPolyPolygon.getSystemDependentData<SystemDependentData_ID2D1PathGeometry>(
+ basegfx::SDD_Type::SDDType_ID2D1PathGeometry));
+
+ if (pSystemDependentData_ID2D1PathGeometry)
+ {
+ // use and return buffered data
+ return pSystemDependentData_ID2D1PathGeometry;
+ }
+
+ sal::systools::COMReference<ID2D1PathGeometry> pID2D1PathGeometry;
+ HRESULT hr(
+ aID2D1GlobalFactoryProvider.getID2D1Factory()->CreatePathGeometry(&pID2D1PathGeometry));
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if (SUCCEEDED(hr) && nCount)
+ {
+ sal::systools::COMReference<ID2D1GeometrySink> pSink;
+ hr = pID2D1PathGeometry->Open(&pSink);
+
+ if (SUCCEEDED(hr) && pSink)
+ {
+ for (sal_uInt32 a(0); a < nCount; a++)
+ {
+ const basegfx::B2DPolygon& rPolygon(rPolyPolygon.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(rPolygon.count());
+
+ if (nPointCount)
+ {
+ const basegfx::B2DPoint aStart(rPolygon.getB2DPoint(0));
+
+ pSink->BeginFigure(D2D1::Point2F(aStart.getX(), aStart.getY()),
+ D2D1_FIGURE_BEGIN_FILLED);
+ addB2DPolygonToPathGeometry(pSink, rPolygon, nullptr);
+ pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
+ }
+ }
+
+ pSink->Close();
+ }
+ }
+
+ // add to buffering mechanism
+ if (pID2D1PathGeometry)
+ {
+ return rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_ID2D1PathGeometry>(
+ pID2D1PathGeometry);
+ }
+
+ return std::shared_ptr<SystemDependentData_ID2D1PathGeometry>();
+}
+
+class SystemDependentData_ID2D1Bitmap : public basegfx::SystemDependentData
+{
+private:
+ sal::systools::COMReference<ID2D1Bitmap> mpD2DBitmap;
+
+public:
+ SystemDependentData_ID2D1Bitmap(sal::systools::COMReference<ID2D1Bitmap>& rD2DBitmap)
+ : basegfx::SystemDependentData(Application::GetSystemDependentDataManager(),
+ basegfx::SDD_Type::SDDType_ID2D1Bitmap)
+ , mpD2DBitmap(rD2DBitmap)
+ {
+ }
+
+ const sal::systools::COMReference<ID2D1Bitmap>& getID2D1Bitmap() const { return mpD2DBitmap; }
+
+ virtual sal_Int64 estimateUsageInBytes() const override;
+};
+
+sal_Int64 SystemDependentData_ID2D1Bitmap::estimateUsageInBytes() const
+{
+ sal_Int64 aRetval(0);
+
+ if (getID2D1Bitmap())
+ {
+ // use factor 4 for RGBA_8 as estimation
+ const D2D1_SIZE_U aSizePixel(getID2D1Bitmap()->GetPixelSize());
+ aRetval = static_cast<sal_Int64>(aSizePixel.width)
+ * static_cast<sal_Int64>(aSizePixel.height) * 4;
+ }
+
+ return aRetval;
+}
+
+sal::systools::COMReference<ID2D1Bitmap> createB2DBitmap(const Bitmap& rBitmap)
+{
+ const Size& rSizePixel(rBitmap.GetSizePixel());
+ const bool bAlpha(rBitmap.HasAlpha());
+ const sal_uInt32 nPixelCount(rSizePixel.Width() * rSizePixel.Height());
+ std::unique_ptr<sal_uInt32[]> aData(new sal_uInt32[nPixelCount]);
+ sal_uInt32* pTarget = aData.get();
+
+ {
+ BitmapScopedReadAccess pReadAccess(rBitmap);
+ const tools::Long nHeight(pReadAccess->Height());
+ const tools::Long nWidth(pReadAccess->Width());
+
+ for (tools::Long y = 0; y < nHeight; ++y)
+ {
+ for (tools::Long x = 0; x < nWidth; ++x)
+ {
+ const BitmapColor aColor(pReadAccess->GetColor(y, x));
+ *pTarget++ = sal_uInt32(aColor);
+ }
+ }
+ }
+
+ // use GlobalRenderTarget to allow usage combined with
+ // the Direct2D CreateSharedBitmap-mechanism. This is needed
+ // since ID2D1Bitmap is a ID2D1RenderTarget-dependent resource
+ // and thus - in principle - would have to be re-created for
+ // *each* new ID2D1RenderTarget, that means for *each* new
+ // target HDC, resp. OutputDevice
+ sal::systools::COMReference<ID2D1Bitmap> pID2D1Bitmap;
+
+ if (aID2D1GlobalRenderTargetProvider.getID2D1DCRenderTarget())
+ {
+ const HRESULT hr(aID2D1GlobalRenderTargetProvider.getID2D1DCRenderTarget()->CreateBitmap(
+ D2D1::SizeU(rSizePixel.Width(), rSizePixel.Height()), &aData[0],
+ rSizePixel.Width() * sizeof(sal_uInt32),
+ D2D1::BitmapProperties(
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, // DXGI_FORMAT
+ bAlpha ? D2D1_ALPHA_MODE_PREMULTIPLIED
+ : D2D1_ALPHA_MODE_IGNORE)), // D2D1_ALPHA_MODE
+ &pID2D1Bitmap));
+
+ if (!SUCCEEDED(hr))
+ pID2D1Bitmap.clear();
+ }
+
+ return pID2D1Bitmap;
+}
+
+sal::systools::COMReference<ID2D1Bitmap>
+getOrCreateB2DBitmap(sal::systools::COMReference<ID2D1RenderTarget>& rRT, const Bitmap& rBitmap)
+{
+ const basegfx::SystemDependentDataHolder* pHolder(rBitmap.accessSystemDependentDataHolder());
+ std::shared_ptr<SystemDependentData_ID2D1Bitmap> pSystemDependentData_ID2D1Bitmap;
+
+ if (nullptr != pHolder)
+ {
+ // try to access SystemDependentDataHolder and buffered data
+ pSystemDependentData_ID2D1Bitmap
+ = std::static_pointer_cast<SystemDependentData_ID2D1Bitmap>(
+ pHolder->getSystemDependentData(basegfx::SDD_Type::SDDType_ID2D1Bitmap));
+ }
+
+ if (!pSystemDependentData_ID2D1Bitmap)
+ {
+ // have to create newly
+ sal::systools::COMReference<ID2D1Bitmap> pID2D1Bitmap(createB2DBitmap(rBitmap));
+
+ if (pID2D1Bitmap)
+ {
+ // creation worked, create SystemDependentData_ID2D1Bitmap
+ pSystemDependentData_ID2D1Bitmap
+ = std::make_shared<SystemDependentData_ID2D1Bitmap>(pID2D1Bitmap);
+
+ // only add if feasible
+ if (nullptr != pHolder
+ && pSystemDependentData_ID2D1Bitmap->calculateCombinedHoldCyclesInSeconds() > 0)
+ {
+ basegfx::SystemDependentData_SharedPtr r2(pSystemDependentData_ID2D1Bitmap);
+ const_cast<basegfx::SystemDependentDataHolder*>(pHolder)
+ ->addOrReplaceSystemDependentData(r2);
+ }
+ }
+ }
+
+ sal::systools::COMReference<ID2D1Bitmap> pWrappedD2DBitmap;
+
+ if (pSystemDependentData_ID2D1Bitmap)
+ {
+ // embed to CreateSharedBitmap, that makes it usable on
+ // the specified RenderTarget
+ const HRESULT hr(rRT->CreateSharedBitmap(
+ __uuidof(ID2D1Bitmap),
+ static_cast<void*>(pSystemDependentData_ID2D1Bitmap->getID2D1Bitmap()), nullptr,
+ &pWrappedD2DBitmap));
+
+ if (!SUCCEEDED(hr))
+ pWrappedD2DBitmap.clear();
+ }
+
+ return pWrappedD2DBitmap;
+}
+
+// This is a simple local derivation of D2DPixelProcessor2D to be used
+// when sub-content needs to be rendered to pixels. Hand over the adapted
+// ViewInformation2D, a pixel size and the parent RenderTarget. It will
+// locally create and use a ID2D1BitmapRenderTarget to render the stuff
+// (you need to call process() with the primitives to be painted of
+// course). Then use the local helper getID2D1Bitmap() to access the
+// ID2D1Bitmap which was the target of that operation.
+class D2DBitmapPixelProcessor2D final : public drawinglayer::processor2d::D2DPixelProcessor2D
+{
+ // the local ID2D1BitmapRenderTarget
+ sal::systools::COMReference<ID2D1BitmapRenderTarget> mpBitmapRenderTarget;
+
+public:
+ // helper class to create another instance of D2DPixelProcessor2D for
+ // creating helper-ID2D1Bitmap's for a given ID2D1RenderTarget
+ D2DBitmapPixelProcessor2D(const drawinglayer::geometry::ViewInformation2D& rViewInformation,
+ sal_uInt32 nWidth, sal_uInt32 nHeight,
+ const sal::systools::COMReference<ID2D1RenderTarget>& rParent)
+ : drawinglayer::processor2d::D2DPixelProcessor2D(rViewInformation)
+ , mpBitmapRenderTarget()
+ {
+ if (0 == nWidth || 0 == nHeight)
+ {
+ // no width/height, done
+ increaseError();
+ }
+
+ if (!hasError())
+ {
+ // Allocate compatible RGBA render target
+ const D2D1_SIZE_U aRenderTargetSizePixel(D2D1::SizeU(nWidth, nHeight));
+ const HRESULT hr(rParent->CreateCompatibleRenderTarget(
+ nullptr, &aRenderTargetSizePixel, nullptr,
+ D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &mpBitmapRenderTarget));
+
+ if (!SUCCEEDED(hr) || nullptr == mpBitmapRenderTarget)
+ {
+ // did not work, done
+ increaseError();
+ }
+ else
+ {
+ sal::systools::COMReference<ID2D1RenderTarget> pRT;
+ mpBitmapRenderTarget->QueryInterface(__uuidof(ID2D1RenderTarget),
+ reinterpret_cast<void**>(&pRT));
+ setRenderTarget(pRT);
+ }
+ }
+
+ if (hasRenderTarget())
+ {
+ // set Viewort if none was given. We have a fixed pixel target, s we know the
+ // exact Viewport to work on
+ if (getViewInformation2D().getViewport().isEmpty())
+ {
+ drawinglayer::geometry::ViewInformation2D aViewInformation(getViewInformation2D());
+ basegfx::B2DRange aViewport(0.0, 0.0, nWidth, nHeight);
+ basegfx::B2DHomMatrix aInvViewTransform(aViewInformation.getViewTransformation());
+
+ aInvViewTransform.invert();
+ aViewport.transform(aInvViewTransform);
+ aViewInformation.setViewport(aViewport);
+ setViewInformation2D(aViewInformation);
+ }
+
+ // clear as render preparation
+ getRenderTarget()->BeginDraw();
+ getRenderTarget()->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));
+ getRenderTarget()->EndDraw();
+ }
+ }
+
+ sal::systools::COMReference<ID2D1Bitmap> getID2D1Bitmap() const
+ {
+ sal::systools::COMReference<ID2D1Bitmap> pResult;
+
+ // access the resulting bitmap if exists
+ if (mpBitmapRenderTarget)
+ {
+ mpBitmapRenderTarget->GetBitmap(&pResult);
+ }
+
+ return pResult;
+ }
+};
+
+bool createBitmapSubContent(sal::systools::COMReference<ID2D1Bitmap>& rResult,
+ basegfx::B2DRange& rDiscreteVisibleRange,
+ const drawinglayer::primitive2d::Primitive2DContainer& rContent,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D,
+ const sal::systools::COMReference<ID2D1RenderTarget>& rRenderTarget)
+{
+ if (rContent.empty() || !rRenderTarget)
+ {
+ // no content or no render target, done
+ return false;
+ }
+
+ drawinglayer::processor2d::calculateDiscreteVisibleRange(
+ rDiscreteVisibleRange, rContent.getB2DRange(rViewInformation2D), rViewInformation2D);
+
+ if (rDiscreteVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return false;
+ }
+
+ // Use a temporary second instance of a D2DBitmapPixelProcessor2D with adapted
+ // ViewInformation2D, it will create the needed ID2D1BitmapRenderTarget
+ // locally and Clear() it.
+ drawinglayer::geometry::ViewInformation2D aAdaptedViewInformation2D(rViewInformation2D);
+ const double fTargetWidth(ceil(rDiscreteVisibleRange.getWidth()));
+ const double fTargetHeight(ceil(rDiscreteVisibleRange.getHeight()));
+
+ {
+ // create adapted ViewTransform, needs to be offset in discrete coordinates,
+ // so multiply from left
+ basegfx::B2DHomMatrix aAdapted(
+ basegfx::utils::createTranslateB2DHomMatrix(-rDiscreteVisibleRange.getMinX(),
+ -rDiscreteVisibleRange.getMinY())
+ * rViewInformation2D.getViewTransformation());
+ aAdaptedViewInformation2D.setViewTransformation(aAdapted);
+
+ // reset Viewport (world coordinates), so the helper renderer will create it's
+ // own based on it's given internal discrete size
+ aAdaptedViewInformation2D.setViewport(basegfx::B2DRange());
+ }
+
+ D2DBitmapPixelProcessor2D aSubContentRenderer(aAdaptedViewInformation2D, fTargetWidth,
+ fTargetHeight, rRenderTarget);
+
+ if (!aSubContentRenderer.valid())
+ {
+ // did not work, done
+ return false;
+ }
+
+ // render sub-content recursively
+ aSubContentRenderer.process(rContent);
+
+ // grab Bitmap & prepare results from RGBA content rendering
+ rResult = aSubContentRenderer.getID2D1Bitmap();
+ return true;
+}
+}
+
+namespace drawinglayer::processor2d
+{
+D2DPixelProcessor2D::D2DPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation)
+ , maBColorModifierStack()
+ , mpRT()
+ , mnRecursionCounter(0)
+ , mnErrorCounter(0)
+{
+}
+
+D2DPixelProcessor2D::D2DPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation,
+ HDC aHdc)
+ : BaseProcessor2D(rViewInformation)
+ , maBColorModifierStack()
+ , mpRT()
+ , mnRecursionCounter(0)
+ , mnErrorCounter(0)
+{
+ sal::systools::COMReference<ID2D1DCRenderTarget> pDCRT;
+ tools::Long aOutWidth(0), aOutHeight(0);
+
+ if (aHdc)
+ {
+ aOutWidth = GetDeviceCaps(aHdc, HORZRES);
+ aOutHeight = GetDeviceCaps(aHdc, VERTRES);
+ }
+
+ if (aOutWidth > 0 && aOutHeight > 0 && aID2D1GlobalFactoryProvider.getID2D1Factory())
+ {
+ const D2D1_RENDER_TARGET_PROPERTIES aRTProps(D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE), //D2D1_ALPHA_MODE_PREMULTIPLIED),
+ 0, 0, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT));
+
+ const HRESULT hr(
+ aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateDCRenderTarget(&aRTProps, &pDCRT));
+
+ if (!SUCCEEDED(hr))
+ pDCRT.clear();
+ }
+
+ if (pDCRT)
+ {
+ const RECT rc(
+ { 0, 0, o3tl::narrowing<LONG>(aOutWidth), o3tl::narrowing<LONG>(aOutHeight) });
+ const HRESULT hr(pDCRT->BindDC(aHdc, &rc));
+
+ if (!SUCCEEDED(hr))
+ pDCRT.clear();
+ }
+
+ if (pDCRT)
+ {
+ if (rViewInformation.getUseAntiAliasing())
+ {
+ D2D1_ANTIALIAS_MODE eAAMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
+ pDCRT->SetAntialiasMode(eAAMode);
+ }
+ else
+ {
+ D2D1_ANTIALIAS_MODE eAAMode = D2D1_ANTIALIAS_MODE_ALIASED;
+ pDCRT->SetAntialiasMode(eAAMode);
+ }
+
+ // since ID2D1DCRenderTarget depends on the transformation
+ // set at hdc, be careful and reset it to identity
+ XFORM aXForm;
+ aXForm.eM11 = 1.0;
+ aXForm.eM12 = 0.0;
+ aXForm.eM21 = 0.0;
+ aXForm.eM22 = 1.0;
+ aXForm.eDx = 0.0;
+ aXForm.eDy = 0.0;
+ SetWorldTransform(aHdc, &aXForm);
+ }
+
+ if (pDCRT)
+ {
+ sal::systools::COMReference<ID2D1RenderTarget> pRT;
+ pDCRT->QueryInterface(__uuidof(ID2D1RenderTarget), reinterpret_cast<void**>(&pRT));
+ setRenderTarget(pRT);
+ }
+ else
+ {
+ increaseError();
+ }
+}
+
+void D2DPixelProcessor2D::processPolygonHairlinePrimitive2D(
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D)
+{
+ const basegfx::B2DPolygon& rPolygon(rPolygonHairlinePrimitive2D.getB2DPolygon());
+
+ if (!rPolygon.count())
+ {
+ // no geometry, done
+ return;
+ }
+
+ bool bDone(false);
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1PathGeometry(
+ getOrCreatePathGeometry(rPolygon, getViewInformation2D()));
+
+ if (pSystemDependentData_ID2D1PathGeometry)
+ {
+ sal::systools::COMReference<ID2D1TransformedGeometry> pTransformedGeometry;
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ HRESULT hr(aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateTransformedGeometry(
+ pSystemDependentData_ID2D1PathGeometry->getID2D1PathGeometry(),
+ D2D1::Matrix3x2F(rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e() + fAAOffset,
+ rObjectToView.f() + fAAOffset),
+ &pTransformedGeometry));
+
+ if (SUCCEEDED(hr) && pTransformedGeometry)
+ {
+ const basegfx::BColor aHairlineColor(
+ maBColorModifierStack.getModifiedColor(rPolygonHairlinePrimitive2D.getBColor()));
+ const D2D1::ColorF aD2DColor(aHairlineColor.getRed(), aHairlineColor.getGreen(),
+ aHairlineColor.getBlue());
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ hr = getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ // TODO: Unfortunately Direct2D paint of one pixel wide lines does not
+ // correctly and completely blend 100% over the background. Experimenting
+ // shows that a value around/slightly below 2.0 is needed which hints that
+ // alpha blending the half-shifted lines (see fAAOffset above) is involved.
+ // To get correct blending I try to use just wider hairlines for now. This
+ // may need to be improved - or balanced (trying sqrt(2) now...)
+ getRenderTarget()->DrawGeometry(pTransformedGeometry, pColorBrush, 1.44f);
+ bDone = true;
+ }
+ }
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+bool D2DPixelProcessor2D::drawPolyPolygonColorTransformed(
+ const basegfx::B2DHomMatrix& rTansformation, const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const basegfx::BColor& rColor)
+{
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1PathGeometry(
+ getOrCreateFillGeometry(rPolyPolygon));
+
+ if (pSystemDependentData_ID2D1PathGeometry)
+ {
+ sal::systools::COMReference<ID2D1TransformedGeometry> pTransformedGeometry;
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ basegfx::B2DHomMatrix aTansformation(getViewInformation2D().getObjectToViewTransformation()
+ * rTansformation);
+ HRESULT hr(aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateTransformedGeometry(
+ pSystemDependentData_ID2D1PathGeometry->getID2D1PathGeometry(),
+ D2D1::Matrix3x2F(aTansformation.a(), aTansformation.b(), aTansformation.c(),
+ aTansformation.d(), aTansformation.e() + fAAOffset,
+ aTansformation.f() + fAAOffset),
+ &pTransformedGeometry));
+
+ if (SUCCEEDED(hr) && pTransformedGeometry)
+ {
+ const basegfx::BColor aFillColor(maBColorModifierStack.getModifiedColor(rColor));
+ const D2D1::ColorF aD2DColor(aFillColor.getRed(), aFillColor.getGreen(),
+ aFillColor.getBlue());
+
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ hr = getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ getRenderTarget()->FillGeometry(pTransformedGeometry, pColorBrush);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void D2DPixelProcessor2D::processPolyPolygonColorPrimitive2D(
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D)
+{
+ const basegfx::B2DPolyPolygon& rPolyPolygon(rPolyPolygonColorPrimitive2D.getB2DPolyPolygon());
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if (!nCount)
+ {
+ // no geometry, done
+ return;
+ }
+
+ const bool bDone(drawPolyPolygonColorTransformed(basegfx::B2DHomMatrix(), rPolyPolygon,
+ rPolyPolygonColorPrimitive2D.getBColor()));
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processBitmapPrimitive2D(
+ const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+{
+ // check if graphic content is inside discrete local ViewPort
+ if (!getViewInformation2D().getDiscreteViewport().isEmpty())
+ {
+ // calculate logic object range, remember: the helper below will
+ // transform using getObjectToViewTransformation, so the bitmap-local
+ // transform would be missing
+ basegfx::B2DRange aDiscreteVisibleRange(basegfx::B2DRange::getUnitB2DRange());
+ aDiscreteVisibleRange.transform(rBitmapCandidate.getTransform());
+
+ // calculate visible range
+ calculateDiscreteVisibleRange(aDiscreteVisibleRange, aDiscreteVisibleRange,
+ getViewInformation2D());
+
+ if (aDiscreteVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+ }
+
+ Bitmap aBitmap(rBitmapCandidate.getBitmap());
+
+ if (aBitmap.IsEmpty() || aBitmap.GetSizePixel().IsEmpty())
+ {
+ // no pixel data, done
+ return;
+ }
+
+ if (maBColorModifierStack.count())
+ {
+ // need to apply ColorModifier to Bitmap data
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
+
+ if (aBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it (any input works)
+ const basegfx::BColor aModifiedColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+
+ // use unit geometry as fallback object geometry. Do *not*
+ // transform, the below used method will use the already
+ // correctly initialized local ViewInformation
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
+
+ rtl::Reference<primitive2d::PolyPolygonColorPrimitive2D> aTemp(
+ new primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon),
+ aModifiedColor));
+
+ // draw as Polygon, done
+ processPolyPolygonColorPrimitive2D(*aTemp);
+ return;
+ }
+ }
+
+ bool bDone(false);
+ sal::systools::COMReference<ID2D1Bitmap> pD2DBitmap(
+ getOrCreateB2DBitmap(getRenderTarget(), aBitmap));
+
+ if (pD2DBitmap)
+ {
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation()
+ * rBitmapCandidate.getTransform());
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F(
+ aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(), aLocalTransform.d(),
+ aLocalTransform.e() + fAAOffset, aLocalTransform.f() + fAAOffset));
+
+ // destinationRectangle is part of transformation above, so use UnitRange
+ getRenderTarget()->DrawBitmap(pD2DBitmap, D2D1::RectF(0.0, 0.0, 1.0, 1.0));
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+sal::systools::COMReference<ID2D1Bitmap> D2DPixelProcessor2D::implCreateAlpha_Direct(
+ const primitive2d::TransparencePrimitive2D& rTransCandidate)
+{
+ // Try if we can use ID2D1DeviceContext/d2d1_1 by querying for interface.
+ // Only then can we use ID2D1Effect/CLSID_D2D1LuminanceToAlpha and it makes
+ // sense to try to do it this way in this implementation
+ sal::systools::COMReference<ID2D1DeviceContext> pID2D1DeviceContext;
+ getRenderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext),
+ reinterpret_cast<void**>(&pID2D1DeviceContext));
+ sal::systools::COMReference<ID2D1Bitmap> pRetval;
+
+ if (!pID2D1DeviceContext)
+ {
+ // no, done - tell caller to use fallback by returning empty - we have
+ // not the preconditions for this
+ return pRetval;
+ }
+
+ // Release early
+ pID2D1DeviceContext.clear();
+ basegfx::B2DRange aDiscreteVisibleRange;
+
+ if (!createBitmapSubContent(pRetval, aDiscreteVisibleRange, rTransCandidate.getTransparence(),
+ getViewInformation2D(), getRenderTarget())
+ || !pRetval)
+ {
+ // return of false means no display needed, return
+ return pRetval;
+ }
+
+ // Now we need a target to render this to, using the ID2D1Effect tooling.
+ // We can directly apply the effect to an alpha-only 8bit target here,
+ // so create one (no RGBA needed for this).
+ // We need another render target: I tried to render pInBetweenResult
+ // to pContent again, but that does not work due to the bitmap
+ // fetched being probably only an internal reference to the
+ // ID2D1BitmapRenderTarget, thus it would draw onto itself -> chaos
+ sal::systools::COMReference<ID2D1BitmapRenderTarget> pContent;
+ const D2D1_PIXEL_FORMAT aAlphaFormat(
+ D2D1::PixelFormat(DXGI_FORMAT_A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT));
+ const D2D1_SIZE_U aRenderTargetSizePixel(D2D1::SizeU(ceil(aDiscreteVisibleRange.getWidth()),
+ ceil(aDiscreteVisibleRange.getHeight())));
+ const HRESULT hr(getRenderTarget()->CreateCompatibleRenderTarget(
+ nullptr, &aRenderTargetSizePixel, &aAlphaFormat, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE,
+ &pContent));
+
+ if (SUCCEEDED(hr) && pContent)
+ {
+ // try to access ID2D1DeviceContext of that target, we need that *now*
+ pContent->QueryInterface(__uuidof(ID2D1DeviceContext),
+ reinterpret_cast<void**>(&pID2D1DeviceContext));
+
+ if (pID2D1DeviceContext)
+ {
+ // create the effect
+ sal::systools::COMReference<ID2D1Effect> pLuminanceToAlpha;
+ pID2D1DeviceContext->CreateEffect(CLSID_D2D1LuminanceToAlpha, &pLuminanceToAlpha);
+
+ if (pLuminanceToAlpha)
+ {
+ // chain effect stuff together & paint it
+ pLuminanceToAlpha->SetInput(0, pRetval);
+
+ pID2D1DeviceContext->BeginDraw();
+ pID2D1DeviceContext->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));
+ pID2D1DeviceContext->DrawImage(pLuminanceToAlpha);
+ pID2D1DeviceContext->EndDraw();
+
+ // grab result
+ pContent->GetBitmap(&pRetval);
+ }
+ }
+ }
+
+ return pRetval;
+}
+
+sal::systools::COMReference<ID2D1Bitmap> D2DPixelProcessor2D::implCreateAlpha_B2DBitmap(
+ const primitive2d::TransparencePrimitive2D& rTransCandidate,
+ const basegfx::B2DRange& rVisibleRange, D2D1_MATRIX_3X2_F& rMaskScale)
+{
+ // Use this fallback that will also use a pixel processor indirectly,
+ // but allows to get the AlphaMask as vcl Bitmap using existing tooling
+ const sal_uInt32 nDiscreteClippedWidth(ceil(rVisibleRange.getWidth()));
+ const sal_uInt32 nDiscreteClippedHeight(ceil(rVisibleRange.getHeight()));
+ const sal_uInt32 nMaximumQuadraticPixels(250000);
+
+ // Embed content graphics to TransformPrimitive2D
+ const basegfx::B2DHomMatrix aAlphaEmbedding(
+ basegfx::utils::createTranslateB2DHomMatrix(-rVisibleRange.getMinX(),
+ -rVisibleRange.getMinY())
+ * getViewInformation2D().getObjectToViewTransformation());
+ const primitive2d::Primitive2DReference xAlphaEmbedRef(new primitive2d::TransformPrimitive2D(
+ aAlphaEmbedding,
+ drawinglayer::primitive2d::Primitive2DContainer(rTransCandidate.getTransparence())));
+ drawinglayer::primitive2d::Primitive2DContainer xEmbedSeq{ xAlphaEmbedRef };
+
+ // use empty ViewInformation to have neutral transformation
+ const geometry::ViewInformation2D aEmptyViewInformation2D;
+
+ // use new mode to create AlphaChannel (not just AlphaMask) for transparency channel
+ const AlphaMask aAlpha(::drawinglayer::createAlphaMask(
+ std::move(xEmbedSeq), aEmptyViewInformation2D, nDiscreteClippedWidth,
+ nDiscreteClippedHeight, nMaximumQuadraticPixels, true));
+ sal::systools::COMReference<ID2D1Bitmap> pRetval;
+
+ if (aAlpha.IsEmpty())
+ {
+ // if we have no content we are done
+ return pRetval;
+ }
+
+ // use alpha data to create the ID2D1Bitmap
+ const Size& rSizePixel(aAlpha.GetSizePixel());
+ const sal_uInt32 nPixelCount(rSizePixel.Width() * rSizePixel.Height());
+ std::unique_ptr<sal_uInt8[]> aData(new sal_uInt8[nPixelCount]);
+ sal_uInt8* pTarget = aData.get();
+ Bitmap aSrcAlpha(aAlpha.GetBitmap());
+ BitmapScopedReadAccess pReadAccess(aSrcAlpha);
+ const tools::Long nHeight(pReadAccess->Height());
+ const tools::Long nWidth(pReadAccess->Width());
+
+ for (tools::Long y = 0; y < nHeight; ++y)
+ {
+ for (tools::Long x = 0; x < nWidth; ++x)
+ {
+ const BitmapColor aColor(pReadAccess->GetColor(y, x));
+ *pTarget++ = aColor.GetLuminance();
+ }
+ }
+
+ const D2D1_BITMAP_PROPERTIES aBmProps(D2D1::BitmapProperties(
+ D2D1::PixelFormat(DXGI_FORMAT_A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)));
+ const HRESULT hr(getRenderTarget()->CreateBitmap(
+ D2D1::SizeU(rSizePixel.Width(), rSizePixel.Height()), &aData[0],
+ rSizePixel.Width() * sizeof(sal_uInt8), &aBmProps, &pRetval));
+
+ if (!SUCCEEDED(hr) || !pRetval)
+ {
+ // did not work, done
+ return pRetval;
+ }
+
+ // create needed adapted transformation for alpha brush.
+ // We may have to take a corrective scaling into account when the
+ // MaximumQuadraticPixel limit was used/triggered
+ const Size& rBitmapSizePixel(aAlpha.GetSizePixel());
+
+ if (static_cast<sal_uInt32>(rBitmapSizePixel.Width()) != nDiscreteClippedWidth
+ || static_cast<sal_uInt32>(rBitmapSizePixel.Height()) != nDiscreteClippedHeight)
+ {
+ // scale in X and Y should be the same (see fReduceFactor in createAlphaMask),
+ // so adapt numerically to a single scale value, they are integer rounded values
+ const double fScaleX(static_cast<double>(rBitmapSizePixel.Width())
+ / static_cast<double>(nDiscreteClippedWidth));
+ const double fScaleY(static_cast<double>(rBitmapSizePixel.Height())
+ / static_cast<double>(nDiscreteClippedHeight));
+
+ const double fScale(1.0 / ((fScaleX + fScaleY) * 0.5));
+ rMaskScale = D2D1::Matrix3x2F::Scale(fScale, fScale);
+ }
+
+ return pRetval;
+}
+
+void D2DPixelProcessor2D::processTransparencePrimitive2D(
+ const primitive2d::TransparencePrimitive2D& rTransCandidate)
+{
+ if (rTransCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ if (rTransCandidate.getTransparence().empty())
+ {
+ // no mask (so nothing visible), done
+ return;
+ }
+
+ // calculate visible range, create only for that range
+ basegfx::B2DRange aDiscreteVisibleRange;
+ calculateDiscreteVisibleRange(aDiscreteVisibleRange,
+ rTransCandidate.getChildren().getB2DRange(getViewInformation2D()),
+ getViewInformation2D());
+
+ if (aDiscreteVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ // try to create directly, this needs the current mpRT to be a ID2D1DeviceContext/d2d1_1
+ // what is not guaranteed but usually works for more modern windows (after 7)
+ sal::systools::COMReference<ID2D1Bitmap> pAlphaBitmap(implCreateAlpha_Direct(rTransCandidate));
+ D2D1_MATRIX_3X2_F aMaskScale(D2D1::Matrix3x2F::Identity());
+
+ if (!pAlphaBitmap)
+ {
+ // did not work, use more expensive fallback to existing tooling
+ pAlphaBitmap
+ = implCreateAlpha_B2DBitmap(rTransCandidate, aDiscreteVisibleRange, aMaskScale);
+ }
+
+ if (!pAlphaBitmap)
+ {
+ // could not create alpha channel, error
+ increaseError();
+ return;
+ }
+
+ sal::systools::COMReference<ID2D1Layer> pLayer;
+ HRESULT hr(getRenderTarget()->CreateLayer(nullptr, &pLayer));
+ bool bDone(false);
+
+ if (SUCCEEDED(hr) && pLayer)
+ {
+ sal::systools::COMReference<ID2D1BitmapBrush> pBitmapBrush;
+ hr = getRenderTarget()->CreateBitmapBrush(pAlphaBitmap, &pBitmapBrush);
+
+ if (SUCCEEDED(hr) && pBitmapBrush)
+ {
+ // apply MaskScale to Brush, maybe used if implCreateAlpha_B2DBitmap was needed
+ pBitmapBrush->SetTransform(aMaskScale);
+
+ // need to set transform offset for Layer initialization, we work
+ // in discrete device coordinates
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Translation(
+ floor(aDiscreteVisibleRange.getMinX()), floor(aDiscreteVisibleRange.getMinY())));
+
+ getRenderTarget()->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), nullptr,
+ D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
+ D2D1::Matrix3x2F::Identity(), 1.0,
+ pBitmapBrush),
+ pLayer);
+
+ // ... but need to reset to paint content unchanged
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+
+ // draw content recursively
+ process(rTransCandidate.getChildren());
+
+ getRenderTarget()->PopLayer();
+ bDone = true;
+ }
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processUnifiedTransparencePrimitive2D(
+ const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate)
+{
+ if (rTransCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ if (0.0 == rTransCandidate.getTransparence())
+ {
+ // not transparent at all, use content
+ process(rTransCandidate.getChildren());
+ return;
+ }
+
+ if (rTransCandidate.getTransparence() < 0.0 || rTransCandidate.getTransparence() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ // calculate visible range
+ basegfx::B2DRange aDiscreteVisibleRange;
+ calculateDiscreteVisibleRange(aDiscreteVisibleRange,
+ rTransCandidate.getChildren().getB2DRange(getViewInformation2D()),
+ getViewInformation2D());
+
+ if (aDiscreteVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ bool bDone(false);
+ sal::systools::COMReference<ID2D1Layer> pLayer;
+ const HRESULT hr(getRenderTarget()->CreateLayer(nullptr, &pLayer));
+
+ if (SUCCEEDED(hr) && pLayer)
+ {
+ // need to set correct transform for Layer initialization, we work
+ // in discrete device coordinates
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ getRenderTarget()->PushLayer(
+ D2D1::LayerParameters(D2D1::InfiniteRect(), nullptr, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
+ D2D1::IdentityMatrix(),
+ 1.0 - rTransCandidate.getTransparence()), // opacity
+ pLayer);
+ process(rTransCandidate.getChildren());
+ getRenderTarget()->PopLayer();
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
+{
+ if (rMaskCandidate.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+ if (!aMask.count())
+ {
+ // no mask (so nothing inside), done
+ return;
+ }
+
+ // calculate visible range
+ basegfx::B2DRange aDiscreteVisibleRange;
+ calculateDiscreteVisibleRange(aDiscreteVisibleRange, aMask.getB2DRange(),
+ getViewInformation2D());
+
+ if (aDiscreteVisibleRange.isEmpty())
+ {
+ // not visible, done
+ return;
+ }
+
+ bool bDone(false);
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1MaskGeometry(
+ getOrCreateFillGeometry(rMaskCandidate.getMask()));
+
+ if (pSystemDependentData_ID2D1MaskGeometry)
+ {
+ sal::systools::COMReference<ID2D1TransformedGeometry> pTransformedMaskGeometry;
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ HRESULT hr(aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateTransformedGeometry(
+ pSystemDependentData_ID2D1MaskGeometry->getID2D1PathGeometry(),
+ D2D1::Matrix3x2F(rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e(), rObjectToView.f()),
+ &pTransformedMaskGeometry));
+
+ if (SUCCEEDED(hr) && pTransformedMaskGeometry)
+ {
+ sal::systools::COMReference<ID2D1Layer> pLayer;
+ hr = getRenderTarget()->CreateLayer(nullptr, &pLayer);
+
+ if (SUCCEEDED(hr) && pLayer)
+ {
+ // need to set correct transform for Layer initialization, we work
+ // in discrete device coordinates
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ getRenderTarget()->PushLayer(
+ D2D1::LayerParameters(D2D1::InfiniteRect(), pTransformedMaskGeometry), pLayer);
+ process(rMaskCandidate.getChildren());
+ getRenderTarget()->PopLayer();
+ bDone = true;
+ }
+ }
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processPointArrayPrimitive2D(
+ const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate)
+{
+ const std::vector<basegfx::B2DPoint>& rPositions(rPointArrayCandidate.getPositions());
+
+ if (rPositions.empty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ const basegfx::BColor aPointColor(
+ maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ D2D1::ColorF aD2DColor(aPointColor.getRed(), aPointColor.getGreen(), aPointColor.getBlue());
+ const HRESULT hr(getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush));
+ bool bDone(false);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+
+ // To really paint a single pixel I found nothing better than
+ // switch off AA and draw a pixel-aligned rectangle
+ const D2D1_ANTIALIAS_MODE aOldAAMode(getRenderTarget()->GetAntialiasMode());
+ getRenderTarget()->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+
+ for (auto const& pos : rPositions)
+ {
+ const basegfx::B2DPoint aDiscretePos(
+ getViewInformation2D().getObjectToViewTransformation() * pos);
+ const double fX(ceil(aDiscretePos.getX()));
+ const double fY(ceil(aDiscretePos.getY()));
+ const D2D1_RECT_F rect = { FLOAT(fX), FLOAT(fY), FLOAT(fX), FLOAT(fY) };
+
+ getRenderTarget()->DrawRectangle(&rect, pColorBrush);
+ }
+
+ getRenderTarget()->SetAntialiasMode(aOldAAMode);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processMarkerArrayPrimitive2D(
+ const primitive2d::MarkerArrayPrimitive2D& rMarkerArrayCandidate)
+{
+ const std::vector<basegfx::B2DPoint>& rPositions(rMarkerArrayCandidate.getPositions());
+
+ if (rPositions.empty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ Bitmap rMarker(rMarkerArrayCandidate.getMarker());
+
+ if (rMarker.IsEmpty())
+ {
+ // no marker defined, done
+ return;
+ }
+
+ sal::systools::COMReference<ID2D1Bitmap> pD2DBitmap(
+ getOrCreateB2DBitmap(getRenderTarget(), rMarker));
+ bool bDone(false);
+
+ if (pD2DBitmap)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ const Size& rSizePixel(rMarker.GetSizePixel());
+ const tools::Long nMiX((rSizePixel.Width() / 2) + 1);
+ const tools::Long nMiY((rSizePixel.Height() / 2) + 1);
+ const tools::Long nPlX(rSizePixel.Width() - nMiX);
+ const tools::Long nPlY(rSizePixel.Height() - nMiY);
+
+ // draw with non-AA to show unhampered, clear, non-scaled marker
+ const D2D1_ANTIALIAS_MODE aOldAAMode(getRenderTarget()->GetAntialiasMode());
+ getRenderTarget()->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+
+ for (auto const& pos : rPositions)
+ {
+ const basegfx::B2DPoint aDiscretePos(
+ getViewInformation2D().getObjectToViewTransformation() * pos);
+ const double fX(ceil(aDiscretePos.getX()));
+ const double fY(ceil(aDiscretePos.getY()));
+ const D2D1_RECT_F rect
+ = { FLOAT(fX - nMiX), FLOAT(fY - nMiY), FLOAT(fX + nPlX), FLOAT(fY + nPlY) };
+
+ getRenderTarget()->DrawBitmap(pD2DBitmap, &rect);
+ }
+
+ getRenderTarget()->SetAntialiasMode(aOldAAMode);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processBackgroundColorPrimitive2D(
+ const primitive2d::BackgroundColorPrimitive2D& rBackgroundColorCandidate)
+{
+ // check for allowed range [0.0 .. 1.0[
+ if (rBackgroundColorCandidate.getTransparency() < 0.0
+ || rBackgroundColorCandidate.getTransparency() >= 1.0)
+ return;
+
+ const D2D1::ColorF aD2DColor(rBackgroundColorCandidate.getBColor().getRed(),
+ rBackgroundColorCandidate.getBColor().getGreen(),
+ rBackgroundColorCandidate.getBColor().getBlue(),
+ 1.0 - rBackgroundColorCandidate.getTransparency());
+
+ getRenderTarget()->Clear(aD2DColor);
+}
+
+void D2DPixelProcessor2D::processModifiedColorPrimitive2D(
+ const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate)
+{
+ if (!rModifiedCandidate.getChildren().empty())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+}
+
+void D2DPixelProcessor2D::processTransformPrimitive2D(
+ const primitive2d::TransformPrimitive2D& rTransformCandidate)
+{
+ // remember current transformation and ViewInformation
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for local ViewInformation2D
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation()
+ * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
+
+ // process content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ setViewInformation2D(aLastViewInformation2D);
+}
+
+void D2DPixelProcessor2D::processPolygonStrokePrimitive2D(
+ const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate)
+{
+ const basegfx::B2DPolygon& rPolygon(rPolygonStrokeCandidate.getB2DPolygon());
+ const attribute::LineAttribute& rLineAttribute(rPolygonStrokeCandidate.getLineAttribute());
+
+ if (!rPolygon.count() || rLineAttribute.getWidth() < 0.0)
+ {
+ // no geometry, done
+ return;
+ }
+
+ // get some values early that might be used for decisions
+ const bool bHairline(0.0 == rLineAttribute.getWidth());
+ const basegfx::B2DHomMatrix& rObjectToView(
+ getViewInformation2D().getObjectToViewTransformation());
+ const double fDiscreteLineWidth(
+ bHairline
+ ? 1.0
+ : (rObjectToView * basegfx::B2DVector(rLineAttribute.getWidth(), 0.0)).getLength());
+
+ // Here for every combination which the system-specific implementation is not
+ // capable of visualizing, use the (for decomposable Primitives always possible)
+ // fallback to the decomposition.
+ if (basegfx::B2DLineJoin::NONE == rLineAttribute.getLineJoin() && fDiscreteLineWidth > 1.5)
+ {
+ // basegfx::B2DLineJoin::NONE is special for our office, no other GraphicSystem
+ // knows that (so far), so fallback to decomposition. This is only needed if
+ // LineJoin will be used, so also check for discrete LineWidth before falling back
+ process(rPolygonStrokeCandidate);
+ return;
+ }
+
+ // This is a method every system-specific implementation of a decomposable Primitive
+ // can use to allow simple optical control of paint implementation:
+ // Create a copy, e.g. change color to 'red' as here and paint before the system
+ // paints it using the decomposition. That way you can - if active - directly
+ // optically compare if the system-specific solution is geometrically identical to
+ // the decomposition (which defines our interpretation that we need to visualize).
+ // Look below in the impl for bRenderDecomposeForCompareInRed to see that in that case
+ // we create a half-transparent paint to better support visual control
+ static bool bRenderDecomposeForCompareInRed(false);
+
+ if (bRenderDecomposeForCompareInRed)
+ {
+ const attribute::LineAttribute aRed(
+ basegfx::BColor(1.0, 0.0, 0.0), rLineAttribute.getWidth(), rLineAttribute.getLineJoin(),
+ rLineAttribute.getLineCap(), rLineAttribute.getMiterMinimumAngle());
+ rtl::Reference<primitive2d::PolygonStrokePrimitive2D> aCopy(
+ new primitive2d::PolygonStrokePrimitive2D(
+ rPolygonStrokeCandidate.getB2DPolygon(), aRed,
+ rPolygonStrokeCandidate.getStrokeAttribute()));
+ process(*aCopy);
+ }
+
+ bool bDone(false);
+ std::shared_ptr<SystemDependentData_ID2D1PathGeometry> pSystemDependentData_ID2D1PathGeometry(
+ getOrCreatePathGeometry(rPolygon, getViewInformation2D()));
+
+ if (pSystemDependentData_ID2D1PathGeometry)
+ {
+ sal::systools::COMReference<ID2D1TransformedGeometry> pTransformedGeometry;
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ HRESULT hr(aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateTransformedGeometry(
+ pSystemDependentData_ID2D1PathGeometry->getID2D1PathGeometry(),
+ D2D1::Matrix3x2F(rObjectToView.a(), rObjectToView.b(), rObjectToView.c(),
+ rObjectToView.d(), rObjectToView.e() + fAAOffset,
+ rObjectToView.f() + fAAOffset),
+ &pTransformedGeometry));
+
+ if (SUCCEEDED(hr) && pTransformedGeometry)
+ {
+ const basegfx::BColor aLineColor(
+ maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
+ D2D1::ColorF aD2DColor(aLineColor.getRed(), aLineColor.getGreen(),
+ aLineColor.getBlue());
+
+ if (bRenderDecomposeForCompareInRed)
+ {
+ aD2DColor.a = 0.5;
+ }
+
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ hr = getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ sal::systools::COMReference<ID2D1StrokeStyle> pStrokeStyle;
+ D2D1_CAP_STYLE aCapStyle(D2D1_CAP_STYLE_FLAT);
+ D2D1_LINE_JOIN aLineJoin(D2D1_LINE_JOIN_MITER);
+ const attribute::StrokeAttribute& rStrokeAttribute(
+ rPolygonStrokeCandidate.getStrokeAttribute());
+ const bool bDashUsed(!rStrokeAttribute.isDefault()
+ && !rStrokeAttribute.getDotDashArray().empty()
+ && 0.0 < rStrokeAttribute.getFullDotDashLen());
+ D2D1_DASH_STYLE aDashStyle(bDashUsed ? D2D1_DASH_STYLE_CUSTOM
+ : D2D1_DASH_STYLE_SOLID);
+ std::vector<float> dashes;
+ float miterLimit(1.0);
+
+ switch (rLineAttribute.getLineCap())
+ {
+ case css::drawing::LineCap_ROUND:
+ aCapStyle = D2D1_CAP_STYLE_ROUND;
+ break;
+ case css::drawing::LineCap_SQUARE:
+ aCapStyle = D2D1_CAP_STYLE_SQUARE;
+ break;
+ default:
+ break;
+ }
+
+ switch (rLineAttribute.getLineJoin())
+ {
+ case basegfx::B2DLineJoin::NONE:
+ break;
+ case basegfx::B2DLineJoin::Bevel:
+ aLineJoin = D2D1_LINE_JOIN_BEVEL;
+ break;
+ case basegfx::B2DLineJoin::Miter:
+ {
+ // for basegfx::B2DLineJoin::Miter there are two problems:
+ // (1) MS uses D2D1_LINE_JOIN_MITER which handles the cut-off when MiterLimit is hit not by
+ // fallback to Bevel, but by cutting miter geometry at the defined distance. That is
+ // nice, but not what we need or is the standard for other graphic systems. Luckily there
+ // is also D2D1_LINE_JOIN_MITER_OR_BEVEL and (after some search) the page
+ // https://learn.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_line_join
+ // which gives some explanation, so that is what we need to use here.
+ // (2) Instead of using an angle in radians (15 deg default) MS uses
+ // "miterLimit is relative to 1/2 LineWidth", so a length. After some experimenting
+ // it shows that the (better understandable) angle has to be converted to the length
+ // that a miter prolongation would have at that angle, so use some trigonometry.
+ // Unfortunately there is also some'precision' problem (probably), so I had to
+ // experimentally come to a correction value around 0.9925. Since that seems to
+ // be no obvious numerical value involved somehow (and as long as I find no other
+ // explanation) I will have to use that.
+ // NOTE: To find that correction value I usd that handy bRenderDecomposeForCompareInRed
+ // and changes in debugger - as work tipp
+ // With both done I can use Direct2D for Miter completely - what is good for speed.
+ aLineJoin = D2D1_LINE_JOIN_MITER_OR_BEVEL;
+
+ // snap absolute value of angle in radians to [0.0 .. PI]
+ double fVal(::basegfx::snapToZeroRange(
+ fabs(rLineAttribute.getMiterMinimumAngle()), M_PI));
+
+ // cut at 0.0 and PI since sin would be zero ('endless' miter)
+ const double fSmallValue(M_PI * 0.0000001);
+ fVal = std::max(fSmallValue, fVal);
+ fVal = std::min(M_PI - fSmallValue, fVal);
+
+ // get relative length
+ fVal = 1.0 / sin(fVal);
+
+ // use for miterLimit, we need factor 2.0 (relative to double LineWidth)
+ // and the correction mentioned in (2) above
+ const double fCorrector(2.0 * 0.9925);
+
+ miterLimit = fVal * fCorrector;
+ break;
+ }
+ case basegfx::B2DLineJoin::Round:
+ aLineJoin = D2D1_LINE_JOIN_ROUND;
+ break;
+ default:
+ break;
+ }
+
+ if (bDashUsed)
+ {
+ // dashes need to be discrete and relative to LineWidth
+ for (auto& value : rStrokeAttribute.getDotDashArray())
+ {
+ dashes.push_back(
+ (rObjectToView * basegfx::B2DVector(value, 0.0)).getLength()
+ / fDiscreteLineWidth);
+ }
+ }
+
+ hr = aID2D1GlobalFactoryProvider.getID2D1Factory()->CreateStrokeStyle(
+ D2D1::StrokeStyleProperties(aCapStyle, // startCap
+ aCapStyle, // endCap
+ aCapStyle, // dashCap
+ aLineJoin, // lineJoin
+ miterLimit, // miterLimit
+ aDashStyle, // dashStyle
+ 0.0f), // dashOffset
+ bDashUsed ? dashes.data() : nullptr, bDashUsed ? dashes.size() : 0,
+ &pStrokeStyle);
+
+ if (SUCCEEDED(hr) && pStrokeStyle)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ getRenderTarget()->DrawGeometry(
+ pTransformedGeometry, pColorBrush,
+ // TODO: Hairline LineWidth, see comment at processPolygonHairlinePrimitive2D
+ bHairline ? 1.44 : fDiscreteLineWidth, pStrokeStyle);
+ bDone = true;
+ }
+ }
+ }
+ }
+
+ if (!bDone)
+ {
+ // fallback to decomposition
+ process(rPolygonStrokeCandidate);
+ }
+}
+
+void D2DPixelProcessor2D::processLineRectanglePrimitive2D(
+ const primitive2d::LineRectanglePrimitive2D& rLineRectanglePrimitive2D)
+{
+ if (rLineRectanglePrimitive2D.getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ const basegfx::BColor aHairlineColor(
+ maBColorModifierStack.getModifiedColor(rLineRectanglePrimitive2D.getBColor()));
+ const D2D1::ColorF aD2DColor(aHairlineColor.getRed(), aHairlineColor.getGreen(),
+ aHairlineColor.getBlue());
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ const HRESULT hr(getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush));
+ bool bDone(false);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation());
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F(
+ aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(), aLocalTransform.d(),
+ aLocalTransform.e() + fAAOffset, aLocalTransform.f() + fAAOffset));
+ const basegfx::B2DRange& rRange(rLineRectanglePrimitive2D.getB2DRange());
+ const D2D1_RECT_F rect = { FLOAT(rRange.getMinX()), FLOAT(rRange.getMinY()),
+ FLOAT(rRange.getMaxX()), FLOAT(rRange.getMaxY()) };
+ const double fDiscreteLineWidth(
+ (getViewInformation2D().getInverseObjectToViewTransformation()
+ * basegfx::B2DVector(1.44, 0.0))
+ .getLength());
+
+ getRenderTarget()->DrawRectangle(&rect, pColorBrush, fDiscreteLineWidth);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processFilledRectanglePrimitive2D(
+ const primitive2d::FilledRectanglePrimitive2D& rFilledRectanglePrimitive2D)
+{
+ if (rFilledRectanglePrimitive2D.getB2DRange().isEmpty())
+ {
+ // no geometry, done
+ return;
+ }
+
+ const basegfx::BColor aFillColor(
+ maBColorModifierStack.getModifiedColor(rFilledRectanglePrimitive2D.getBColor()));
+ const D2D1::ColorF aD2DColor(aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue());
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ const HRESULT hr(getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush));
+ bool bDone(false);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation());
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F(
+ aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(), aLocalTransform.d(),
+ aLocalTransform.e() + fAAOffset, aLocalTransform.f() + fAAOffset));
+ const basegfx::B2DRange& rRange(rFilledRectanglePrimitive2D.getB2DRange());
+ const D2D1_RECT_F rect = { FLOAT(rRange.getMinX()), FLOAT(rRange.getMinY()),
+ FLOAT(rRange.getMaxX()), FLOAT(rRange.getMaxY()) };
+
+ getRenderTarget()->FillRectangle(&rect, pColorBrush);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processSingleLinePrimitive2D(
+ const primitive2d::SingleLinePrimitive2D& rSingleLinePrimitive2D)
+{
+ const basegfx::BColor aLineColor(
+ maBColorModifierStack.getModifiedColor(rSingleLinePrimitive2D.getBColor()));
+ const D2D1::ColorF aD2DColor(aLineColor.getRed(), aLineColor.getGreen(), aLineColor.getBlue());
+ sal::systools::COMReference<ID2D1SolidColorBrush> pColorBrush;
+ const HRESULT hr(getRenderTarget()->CreateSolidColorBrush(aD2DColor, &pColorBrush));
+ bool bDone(false);
+
+ if (SUCCEEDED(hr) && pColorBrush)
+ {
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation());
+ const basegfx::B2DPoint aStart(aLocalTransform * rSingleLinePrimitive2D.getStart());
+ const basegfx::B2DPoint aEnd(aLocalTransform * rSingleLinePrimitive2D.getEnd());
+
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ const D2D1_POINT_2F aD2D1Start
+ = { FLOAT(aStart.getX() + fAAOffset), FLOAT(aStart.getY() + fAAOffset) };
+ const D2D1_POINT_2F aD2D1End
+ = { FLOAT(aEnd.getX() + fAAOffset), FLOAT(aEnd.getY() + fAAOffset) };
+
+ getRenderTarget()->DrawLine(aD2D1Start, aD2D1End, pColorBrush, 1.44f);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processFillGraphicPrimitive2D(
+ const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D)
+{
+ if (rFillGraphicPrimitive2D.getTransparency() < 0.0
+ || rFillGraphicPrimitive2D.getTransparency() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ if (rFillGraphicPrimitive2D.hasTransparency())
+ {
+ // cannot handle yet, use decomposition
+ process(rFillGraphicPrimitive2D);
+ return;
+ }
+
+ Bitmap aPreparedBitmap;
+ basegfx::B2DRange aFillUnitRange(rFillGraphicPrimitive2D.getFillGraphic().getGraphicRange());
+ constexpr double fBigDiscreteArea(300.0 * 300.0);
+
+ // use tooling to do various checks and prepare tiled rendering, see
+ // description of method, parameters and return value there
+ if (!prepareBitmapForDirectRender(rFillGraphicPrimitive2D, getViewInformation2D(),
+ aPreparedBitmap, aFillUnitRange, fBigDiscreteArea))
+ {
+ // no output needed, done
+ return;
+ }
+
+ if (aPreparedBitmap.IsEmpty())
+ {
+ // output needed and Bitmap data empty, so no bitmap data based
+ // tiled rendering is suggested. Use fallback for paint (decomposition)
+ process(rFillGraphicPrimitive2D);
+ return;
+ }
+
+ // render tiled using the prepared Bitmap data
+ if (maBColorModifierStack.count())
+ {
+ // need to apply ColorModifier to Bitmap data
+ aPreparedBitmap = aPreparedBitmap.Modify(maBColorModifierStack);
+
+ if (aPreparedBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it (any input works)
+ const basegfx::BColor aModifiedColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+
+ // use unit geometry as fallback object geometry. Do *not*
+ // transform, the below used method will use the already
+ // correctly initialized local ViewInformation
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
+
+ // what we still need to apply is the object transform from the
+ // local primitive, that is not part of DisplayInfo yet
+ aPolygon.transform(rFillGraphicPrimitive2D.getTransformation());
+
+ rtl::Reference<primitive2d::PolyPolygonColorPrimitive2D> aTemp(
+ new primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon),
+ aModifiedColor));
+
+ // draw as colored Polygon, done
+ processPolyPolygonColorPrimitive2D(*aTemp);
+ return;
+ }
+ }
+
+ bool bDone(false);
+ sal::systools::COMReference<ID2D1Bitmap> pD2DBitmap(
+ getOrCreateB2DBitmap(getRenderTarget(), aPreparedBitmap));
+
+ if (pD2DBitmap)
+ {
+ sal::systools::COMReference<ID2D1BitmapBrush> pBitmapBrush;
+ const HRESULT hr(getRenderTarget()->CreateBitmapBrush(pD2DBitmap, &pBitmapBrush));
+
+ if (SUCCEEDED(hr) && pBitmapBrush)
+ {
+ // set extended to repeat/wrap AKA tiling
+ pBitmapBrush->SetExtendModeX(D2D1_EXTEND_MODE_WRAP);
+ pBitmapBrush->SetExtendModeY(D2D1_EXTEND_MODE_WRAP);
+
+ // set interpolation mode
+ // NOTE: This uses D2D1_BITMAP_INTERPOLATION_MODE, but there seem to be
+ // advanced modes when using D2D1_INTERPOLATION_MODE, but that needs
+ // D2D1_BITMAP_BRUSH_PROPERTIES1 and ID2D1BitmapBrush1
+ sal::systools::COMReference<ID2D1BitmapBrush1> pBrush1;
+ pBitmapBrush->QueryInterface(__uuidof(ID2D1BitmapBrush1),
+ reinterpret_cast<void**>(&pBrush1));
+
+ if (pBrush1)
+ {
+ pBrush1->SetInterpolationMode1(D2D1_INTERPOLATION_MODE_MULTI_SAMPLE_LINEAR);
+ }
+ else
+ {
+ pBitmapBrush->SetInterpolationMode(D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
+ }
+
+ // set BitmapBrush transformation relative to it's PixelSize and
+ // the used FillUnitRange. Since we use unit coordinates here this
+ // is pretty simple
+ const D2D1_SIZE_U aBMSPixel(pD2DBitmap->GetPixelSize());
+ const double fScaleX((aFillUnitRange.getMaxX() - aFillUnitRange.getMinX())
+ / aBMSPixel.width);
+ const double fScaleY((aFillUnitRange.getMaxY() - aFillUnitRange.getMinY())
+ / aBMSPixel.height);
+ const D2D1_MATRIX_3X2_F aBTrans(D2D1::Matrix3x2F(
+ fScaleX, 0.0, 0.0, fScaleY, aFillUnitRange.getMinX(), aFillUnitRange.getMinY()));
+ pBitmapBrush->SetTransform(&aBTrans);
+
+ // set transform to ObjectToWorld to be able to paint in unit coordinates, so
+ // evtl. shear/rotate in that transform is used and does not influence the
+ // orthogonal and unit-oriented brush handling
+ const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0);
+ const basegfx::B2DHomMatrix aLocalTransform(
+ getViewInformation2D().getObjectToViewTransformation()
+ * rFillGraphicPrimitive2D.getTransformation());
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F(
+ aLocalTransform.a(), aLocalTransform.b(), aLocalTransform.c(), aLocalTransform.d(),
+ aLocalTransform.e() + fAAOffset, aLocalTransform.f() + fAAOffset));
+
+ // use unit rectangle, transformation is already set to include ObjectToWorld
+ const D2D1_RECT_F rect = { FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(1.0) };
+
+ // draw as unit rectangle as brush filled rectangle
+ getRenderTarget()->FillRectangle(&rect, pBitmapBrush);
+ bDone = true;
+ }
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processFillGradientPrimitive2D(
+ const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D)
+{
+ if (rFillGradientPrimitive2D.hasAlphaGradient() || rFillGradientPrimitive2D.hasTransparency())
+ {
+ // SDPR: As long as direct alpha is not supported by this
+ // renderer we need to work on the decomposition, so call it
+ process(rFillGradientPrimitive2D);
+ return;
+ }
+
+ // draw all-covering initial BG polygon 1st
+ bool bDone(drawPolyPolygonColorTransformed(
+ basegfx::B2DHomMatrix(),
+ basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect(rFillGradientPrimitive2D.getOutputRange())),
+ rFillGradientPrimitive2D.getOuterColor()));
+
+ if (bDone)
+ {
+ const basegfx::B2DPolyPolygon aForm(rFillGradientPrimitive2D.getUnitPolygon());
+
+ // paint solid fill steps by providing callback as lambda
+ auto aCallback([&aForm, &bDone, this](const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::BColor& rColor) {
+ if (bDone)
+ {
+ bDone = drawPolyPolygonColorTransformed(rMatrix, aForm, rColor);
+ }
+ });
+
+ // call value generator to trigger callbacks
+ rFillGradientPrimitive2D.generateMatricesAndColors(aCallback);
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processInvertPrimitive2D(
+ const primitive2d::InvertPrimitive2D& rInvertPrimitive2D)
+{
+ if (rInvertPrimitive2D.getChildren().empty())
+ {
+ // no content, done
+ return;
+ }
+
+ // Try if we can use ID2D1DeviceContext/d2d1_1 by querying for interface.
+ // Only with ID2D1DeviceContext we can use ::DrawImage which supports
+ // D2D1_COMPOSITE_MODE_XOR
+ sal::systools::COMReference<ID2D1DeviceContext> pID2D1DeviceContext;
+ getRenderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext),
+ reinterpret_cast<void**>(&pID2D1DeviceContext));
+
+ if (!pID2D1DeviceContext)
+ {
+ // TODO: We have *no* ID2D1DeviceContext and cannot use D2D1_COMPOSITE_MODE_XOR,
+ // so there is currently no (simple?) way to solve this, there is no 'Invert' method.
+ // It may be possible to convert to a WICBitmap (gets read access) and do the invert
+ // there, but that needs experimenting and is probably not performant - but doable.
+ increaseError();
+ return;
+ }
+
+ sal::systools::COMReference<ID2D1Bitmap> pInBetweenResult;
+ basegfx::B2DRange aDiscreteVisibleRange;
+
+ // create in-between result in discrete coordinates, clipped against visible
+ // part of ViewInformation (if available)
+ if (!createBitmapSubContent(pInBetweenResult, aDiscreteVisibleRange,
+ rInvertPrimitive2D.getChildren(), getViewInformation2D(),
+ getRenderTarget()))
+ {
+ // return of false means no display needed, return
+ return;
+ }
+
+ bool bDone(false);
+
+ if (pInBetweenResult)
+ {
+ getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
+ const D2D1_POINT_2F aTopLeft = { FLOAT(floor(aDiscreteVisibleRange.getMinX())),
+ FLOAT(floor(aDiscreteVisibleRange.getMinY())) };
+
+ pID2D1DeviceContext->DrawImage(pInBetweenResult, aTopLeft, D2D1_INTERPOLATION_MODE_LINEAR,
+ D2D1_COMPOSITE_MODE_XOR);
+ bDone = true;
+ }
+
+ if (!bDone)
+ increaseError();
+}
+
+void D2DPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ if (0 == mnRecursionCounter)
+ getRenderTarget()->BeginDraw();
+ mnRecursionCounter++;
+
+ switch (rCandidate.getPrimitive2DID())
+ {
+ // Geometry that *has* to be processed
+ //
+ // These Primitives have *no* decompose implementation, so these are the basic ones
+ // Just four to go to make a processor work completely (but not optimized)
+ // NOTE: This *could* theoretically be reduced to one and all could implement
+ // a decompose to pixel data, but that seemed not to make sense to me when
+ // I designed this. Thus these four are the lowest-level best representation
+ // from my POV
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
+ {
+ processBitmapPrimitive2D(
+ static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ {
+ processPointArrayPrimitive2D(
+ static_cast<const primitive2d::PointArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
+ {
+ processPolygonHairlinePrimitive2D(
+ static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
+ {
+ processPolyPolygonColorPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
+ break;
+ }
+
+ // Embedding/groups that *have* to be processed
+ //
+ // These represent qualifiers for freely defined content, e.g. making
+ // any combination of primitives freely transformed or transparent
+ // NOTE: PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D and
+ // PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D are pretty much default-
+ // implementations that can and are re-used in all processors.
+ // So - with these and PRIMITIVE2D_ID_INVERTPRIMITIVE2D marked to
+ // be removed in the future - just three really to be implemented
+ // locally specifically
+ case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D:
+ {
+ processTransparencePrimitive2D(
+ static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_INVERTPRIMITIVE2D:
+ {
+ // We urgently should get rid of XOR paint, modern graphic systems
+ // allow no read access to the pixel targets, but that's naturally
+ // a precondition for XOR. While we can do that for the office's
+ // visualization, we can in principle *not* fully avoid getting
+ // stuff that needs/defines XOR paint, e.g. EMF/WMF imports, so
+ // we *have* to support it (for now - sigh)...
+ processInvertPrimitive2D(
+ static_cast<const primitive2d::InvertPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
+ {
+ processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
+ {
+ processModifiedColorPrimitive2D(
+ static_cast<const primitive2d::ModifiedColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
+ {
+ processTransformPrimitive2D(
+ static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
+ break;
+ }
+
+ // Geometry that *may* be processed due to being able to do it better
+ // then using the decomposition.
+ // NOTE: In these implementations you could always call what the default
+ // case below does - call process(rCandidate) to use the decomposition.
+ // So these impls should only do something if they can do it better/
+ // faster that the decomposition. So some of them check if they could
+ // - and if not - use exactly that.
+ case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
+ {
+ // transparence with a fixed alpha for all content, can be done
+ // significally faster
+ processUnifiedTransparencePrimitive2D(
+ static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
+ {
+ // can be done simpler and without AA better locally
+ processMarkerArrayPrimitive2D(
+ static_cast<const primitive2d::MarkerArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D:
+ {
+ // reset to a color, can be done more effectively locally, would
+ // else decompose to a polygon fill
+ processBackgroundColorPrimitive2D(
+ static_cast<const primitive2d::BackgroundColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ // fat and stroked lines - much better doable locally, would decompose
+ // to the full line geometry creation (tessellation)
+ processPolygonStrokePrimitive2D(
+ static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_LINERECTANGLEPRIMITIVE2D:
+ {
+ // simple primitive to support future fast callbacks from OutputDevice
+ // (see 'Example POC' in Gerrit), decomposes to polygon primitive
+ processLineRectanglePrimitive2D(
+ static_cast<const primitive2d::LineRectanglePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLEDRECTANGLEPRIMITIVE2D:
+ {
+ // simple primitive to support future fast callbacks from OutputDevice
+ // (see 'Example POC' in Gerrit), decomposes to filled polygon primitive
+ processFilledRectanglePrimitive2D(
+ static_cast<const primitive2d::FilledRectanglePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SINGLELINEPRIMITIVE2D:
+ {
+ // simple primitive to support future fast callbacks from OutputDevice
+ // (see 'Example POC' in Gerrit), decomposes to polygon primitive
+ processSingleLinePrimitive2D(
+ static_cast<const primitive2d::SingleLinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
+ {
+ processFillGraphicPrimitive2D(
+ static_cast<const primitive2d::FillGraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D:
+ {
+ processFillGradientPrimitive2D(
+ static_cast<const primitive2d::FillGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+
+ // continue with decompose as fallback
+ default:
+ {
+ SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(
+ rCandidate.getPrimitive2DID()));
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+
+ mnRecursionCounter--;
+ if (0 == mnRecursionCounter)
+ getRenderTarget()->EndDraw();
+}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/getdigitlanguage.cxx b/drawinglayer/source/processor2d/getdigitlanguage.cxx
index 858284b23e91..464fbf642af4 100644
--- a/drawinglayer/source/processor2d/getdigitlanguage.cxx
+++ b/drawinglayer/source/processor2d/getdigitlanguage.cxx
@@ -18,7 +18,7 @@
#include "getdigitlanguage.hxx"
LanguageType drawinglayer::detail::getDigitLanguage() {
- switch (SvtCTLOptions().GetCTLTextNumerals()) {
+ switch (SvtCTLOptions::GetCTLTextNumerals()) {
case SvtCTLOptions::NUMERALS_ARABIC:
return LANGUAGE_ENGLISH;
case SvtCTLOptions::NUMERALS_HINDI:
diff --git a/drawinglayer/source/processor2d/getdigitlanguage.hxx b/drawinglayer/source/processor2d/getdigitlanguage.hxx
index c634321b36f9..c22076fa7cd0 100644
--- a/drawinglayer/source/processor2d/getdigitlanguage.hxx
+++ b/drawinglayer/source/processor2d/getdigitlanguage.hxx
@@ -7,20 +7,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_PROCESSOR2D_GETDIGITLANGUAGE_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_PROCESSOR2D_GETDIGITLANGUAGE_HXX
+#pragma once
#include <sal/config.h>
#include <i18nlangtag/lang.h>
-namespace drawinglayer::detail {
-
+namespace drawinglayer::detail
+{
/// Get digit language derived from SvtCTLOptions
LanguageType getDigitLanguage();
-
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
deleted file mode 100644
index 9f838a7e1b61..000000000000
--- a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- 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 "helperwrongspellrenderer.hxx"
-#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
-#include <tools/gen.hxx>
-#include <vcl/outdev.hxx>
-#include <basegfx/color/bcolormodifier.hxx>
-#include <vcl/outdev/ScopedStates.hxx>
-
-using namespace css;
-
-namespace drawinglayer
-{
-namespace
-{
-constexpr sal_uInt32 constMinimumFontHeight = 5; // #define WRONG_SHOW_MIN 5
-}
-
-bool renderWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate,
- OutputDevice& rOutputDevice,
- const basegfx::B2DHomMatrix& rObjectToViewTransformation,
- const basegfx::BColorModifierStack& rBColorModifierStack)
-{
- const basegfx::B2DHomMatrix aLocalTransform(rObjectToViewTransformation
- * rWrongSpellCandidate.getTransformation());
- const basegfx::B2DVector aFontVectorPixel(aLocalTransform * basegfx::B2DVector(0.0, 1.0));
- const sal_uInt32 nFontPixelHeight(basegfx::fround(aFontVectorPixel.getLength()));
-
- if (nFontPixelHeight <= constMinimumFontHeight)
- return true;
-
- const basegfx::B2DPoint aStart(aLocalTransform
- * basegfx::B2DPoint(rWrongSpellCandidate.getStart(), 0.0));
- const basegfx::B2DPoint aStop(aLocalTransform
- * basegfx::B2DPoint(rWrongSpellCandidate.getStop(), 0.0));
- const Point aVclStart(basegfx::fround(aStart.getX()), basegfx::fround(aStart.getY()));
- const Point aVclStop(basegfx::fround(aStop.getX()), basegfx::fround(aStop.getY()));
-
- // #i101075# draw it. Do not forget to use the evtl. offsetted origin of the target device,
- // e.g. when used with mask/transparence buffer device
- const Point aOrigin(rOutputDevice.GetMapMode().GetOrigin());
-
- const basegfx::BColor aProcessedColor(
- rBColorModifierStack.getModifiedColor(rWrongSpellCandidate.getColor()));
- const bool bMapModeEnabledState(rOutputDevice.IsMapModeEnabled());
-
- vcl::ScopedAntialiasing a(rOutputDevice, true);
- rOutputDevice.EnableMapMode(false);
- rOutputDevice.SetLineColor(Color(aProcessedColor));
- rOutputDevice.SetFillColor();
- rOutputDevice.DrawWaveLine(aOrigin + aVclStart, aOrigin + aVclStop);
- rOutputDevice.EnableMapMode(bMapModeEnabledState);
-
- // cannot really go wrong
- return true;
-}
-} // end of namespace drawinglayer
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
index 65a03548cb1c..7f9391298ecb 100644
--- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -20,8 +20,11 @@
#include <drawinglayer/processor2d/hittestprocessor2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
@@ -39,29 +42,25 @@ namespace drawinglayer::processor2d
{
HitTestProcessor2D::HitTestProcessor2D(const geometry::ViewInformation2D& rViewInformation,
const basegfx::B2DPoint& rLogicHitPosition,
- double fLogicHitTolerance,
+ const basegfx::B2DVector& rLogicHitTolerancePerAxis,
bool bHitTextOnly)
: BaseProcessor2D(rViewInformation),
- maDiscreteHitPosition(),
- mfDiscreteHitTolerance(0.0),
- maHitStack(),
+ maDiscreteHitTolerancePerAxis(rLogicHitTolerancePerAxis),
mbCollectHitStack(false),
mbHit(false),
mbHitTextOnly(bHitTextOnly)
{
- // init hit tolerance
- mfDiscreteHitTolerance = fLogicHitTolerance;
+ // ensure input parameters for hit tolerance is >= 0.0
+ if (maDiscreteHitTolerancePerAxis.getX() < 0.0)
+ maDiscreteHitTolerancePerAxis.setX(0.0);
+ if (maDiscreteHitTolerancePerAxis.getY() < 0.0)
+ maDiscreteHitTolerancePerAxis.setY(0.0);
- if(basegfx::fTools::less(mfDiscreteHitTolerance, 0.0))
- {
- // ensure input parameter for hit tolerance is >= 0.0
- mfDiscreteHitTolerance = 0.0;
- }
- else if(basegfx::fTools::more(mfDiscreteHitTolerance, 0.0))
+ if (!maDiscreteHitTolerancePerAxis.equalZero())
{
// generate discrete hit tolerance
- mfDiscreteHitTolerance = (getViewInformation2D().getObjectToViewTransformation()
- * basegfx::B2DVector(mfDiscreteHitTolerance, 0.0)).getLength();
+ maDiscreteHitTolerancePerAxis
+ = getViewInformation2D().getObjectToViewTransformation() * rLogicHitTolerancePerAxis;
}
// generate discrete hit position
@@ -74,7 +73,7 @@ namespace drawinglayer::processor2d
bool HitTestProcessor2D::checkHairlineHitWithTolerance(
const basegfx::B2DPolygon& rPolygon,
- double fDiscreteHitTolerance) const
+ const basegfx::B2DVector& rDiscreteHitTolerancePerAxis) const
{
basegfx::B2DPolygon aLocalPolygon(rPolygon);
aLocalPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
@@ -82,9 +81,9 @@ namespace drawinglayer::processor2d
// get discrete range
basegfx::B2DRange aPolygonRange(aLocalPolygon.getB2DRange());
- if(basegfx::fTools::more(fDiscreteHitTolerance, 0.0))
+ if(rDiscreteHitTolerancePerAxis.getX() > 0 || rDiscreteHitTolerancePerAxis.getY() > 0)
{
- aPolygonRange.grow(fDiscreteHitTolerance);
+ aPolygonRange.grow(rDiscreteHitTolerancePerAxis);
}
// do rough range test first
@@ -94,7 +93,7 @@ namespace drawinglayer::processor2d
return basegfx::utils::isInEpsilonRange(
aLocalPolygon,
getDiscreteHitPosition(),
- fDiscreteHitTolerance);
+ std::max(rDiscreteHitTolerancePerAxis.getX(), rDiscreteHitTolerancePerAxis.getY()));
}
return false;
@@ -102,7 +101,7 @@ namespace drawinglayer::processor2d
bool HitTestProcessor2D::checkFillHitWithTolerance(
const basegfx::B2DPolyPolygon& rPolyPolygon,
- double fDiscreteHitTolerance) const
+ const basegfx::B2DVector& rDiscreteHitTolerancePerAxis) const
{
bool bRetval(false);
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
@@ -110,11 +109,13 @@ namespace drawinglayer::processor2d
// get discrete range
basegfx::B2DRange aPolygonRange(aLocalPolyPolygon.getB2DRange());
- const bool bDiscreteHitToleranceUsed(basegfx::fTools::more(fDiscreteHitTolerance, 0.0));
- if(bDiscreteHitToleranceUsed)
+ const bool bDiscreteHitToleranceUsed(rDiscreteHitTolerancePerAxis.getX() > 0
+ || rDiscreteHitTolerancePerAxis.getY() > 0);
+
+ if (bDiscreteHitToleranceUsed)
{
- aPolygonRange.grow(fDiscreteHitTolerance);
+ aPolygonRange.grow(rDiscreteHitTolerancePerAxis);
}
// do rough range test first
@@ -125,7 +126,7 @@ namespace drawinglayer::processor2d
basegfx::utils::isInEpsilonRange(
aLocalPolyPolygon,
getDiscreteHitPosition(),
- fDiscreteHitTolerance))
+ std::max(rDiscreteHitTolerancePerAxis.getX(), rDiscreteHitTolerancePerAxis.getY())))
{
bRetval = true;
}
@@ -143,6 +144,54 @@ namespace drawinglayer::processor2d
return bRetval;
}
+ void HitTestProcessor2D::checkBitmapHit(basegfx::B2DRange aRange, const Bitmap& rBitmap, const basegfx::B2DHomMatrix& rTransform)
+ {
+ if(!getHitTextOnly())
+ {
+ // The recently added Bitmap::GetTransparency() makes it easy to extend
+ // the BitmapPrimitive2D HitTest to take the contained Bitmap and it's
+ // transparency into account
+ if(!aRange.isEmpty())
+ {
+ const Size aSizePixel(rBitmap.GetSizePixel());
+
+ // When tiled rendering, don't bother with the pixel size of the candidate.
+ if(aSizePixel.Width() && aSizePixel.Height() && !comphelper::LibreOfficeKit::isActive())
+ {
+ basegfx::B2DHomMatrix aBackTransform(
+ getViewInformation2D().getObjectToViewTransformation() *
+ rTransform);
+ aBackTransform.invert();
+
+ const basegfx::B2DPoint aRelativePoint(aBackTransform * getDiscreteHitPosition());
+ const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+
+ if(aUnitRange.isInside(aRelativePoint))
+ {
+ // aRelativePoint.getX() == 0.0 -> 0
+ // aRelativePoint.getX() == 0.999... -> aSizePixel.Width() - 1
+ // Since isInside includes upper bound (1.0), force also this:
+ // aRelativePoint.getX() == 1.0 -> aSizePixel.Width() - 1
+ sal_Int32 nX(aRelativePoint.getX() * aSizePixel.Width());
+ if (nX == aSizePixel.Width())
+ --nX;
+ sal_Int32 nY(aRelativePoint.getY() * aSizePixel.Height());
+ if (nY == aSizePixel.Height())
+ --nY;
+
+ mbHit = (0 != rBitmap.GetPixelColor(nX, nY).GetAlpha());
+ }
+ }
+ else
+ {
+ // fallback to standard HitTest
+ const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aRange));
+ mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance());
+ }
+ }
+ }
+ }
+
void HitTestProcessor2D::check3DHit(const primitive2d::ScenePrimitive2D& rCandidate)
{
// calculate relative point in unified 2D scene
@@ -233,20 +282,15 @@ namespace drawinglayer::processor2d
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D containing transformation
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process child content recursively
process(rTransformCandidate.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
break;
}
@@ -284,7 +328,7 @@ namespace drawinglayer::processor2d
const primitive2d::PolygonStrokePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
const attribute::LineAttribute& rLineAttribute = rPolygonCandidate.getLineAttribute();
- if(basegfx::fTools::more(rLineAttribute.getWidth(), 0.0))
+ if(rLineAttribute.getWidth() > 0.0)
{
if(basegfx::B2DLineJoin::Miter == rLineAttribute.getLineJoin())
{
@@ -296,10 +340,10 @@ namespace drawinglayer::processor2d
{
// for all other B2DLINEJOIN_* do a hairline HitTest with expanded tolerance
const basegfx::B2DVector aDiscreteHalfLineVector(getViewInformation2D().getObjectToViewTransformation()
- * basegfx::B2DVector(rLineAttribute.getWidth() * 0.5, 0.0));
+ * basegfx::B2DVector(rLineAttribute.getWidth() * 0.5, rLineAttribute.getWidth() * 0.5));
mbHit = checkHairlineHitWithTolerance(
rPolygonCandidate.getB2DPolygon(),
- getDiscreteHitTolerance() + aDiscreteHalfLineVector.getLength());
+ getDiscreteHitTolerance() + aDiscreteHalfLineVector);
}
}
else
@@ -321,23 +365,23 @@ namespace drawinglayer::processor2d
double fLogicHitTolerance(0.0);
// if WaveHeight, grow by it
- if(basegfx::fTools::more(rPolygonCandidate.getWaveHeight(), 0.0))
+ if(rPolygonCandidate.getWaveHeight() > 0.0)
{
fLogicHitTolerance += rPolygonCandidate.getWaveHeight();
}
// if line width, grow by it
- if(basegfx::fTools::more(rPolygonCandidate.getLineAttribute().getWidth(), 0.0))
+ if(rPolygonCandidate.getLineAttribute().getWidth() > 0.0)
{
fLogicHitTolerance += rPolygonCandidate.getLineAttribute().getWidth() * 0.5;
}
const basegfx::B2DVector aDiscreteHalfLineVector(getViewInformation2D().getObjectToViewTransformation()
- * basegfx::B2DVector(fLogicHitTolerance, 0.0));
+ * basegfx::B2DVector(fLogicHitTolerance, fLogicHitTolerance));
mbHit = checkHairlineHitWithTolerance(
rPolygonCandidate.getB2DPolygon(),
- getDiscreteHitTolerance() + aDiscreteHalfLineVector.getLength());
+ getDiscreteHitTolerance() + aDiscreteHalfLineVector);
}
break;
@@ -421,49 +465,28 @@ namespace drawinglayer::processor2d
break;
}
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D :
{
- if(!getHitTextOnly())
- {
- // The recently added BitmapEx::GetTransparency() makes it easy to extend
- // the BitmapPrimitive2D HitTest to take the contained BitmapEx and it's
- // transparency into account
- const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
-
- if(!aRange.isEmpty())
- {
- const primitive2d::BitmapPrimitive2D& rBitmapCandidate(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
- const BitmapEx aBitmapEx(VCLUnoHelper::GetBitmap(rBitmapCandidate.getXBitmap()));
- const Size& rSizePixel(aBitmapEx.GetSizePixel());
+ // avoid decompose of this primitive by handling directly
+ const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaCandidate(static_cast< const primitive2d::BitmapAlphaPrimitive2D& >(rCandidate));
- // When tiled rendering, don't bother with the pixel size of the candidate.
- if(rSizePixel.Width() && rSizePixel.Height() && !comphelper::LibreOfficeKit::isActive())
- {
- basegfx::B2DHomMatrix aBackTransform(
- getViewInformation2D().getObjectToViewTransformation() *
- rBitmapCandidate.getTransform());
- aBackTransform.invert();
-
- const basegfx::B2DPoint aRelativePoint(aBackTransform * getDiscreteHitPosition());
- const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
-
- if(aUnitRange.isInside(aRelativePoint))
- {
- const sal_Int32 nX(basegfx::fround(aRelativePoint.getX() * rSizePixel.Width()));
- const sal_Int32 nY(basegfx::fround(aRelativePoint.getY() * rSizePixel.Height()));
-
- mbHit = (0xff != aBitmapEx.GetTransparency(nX, nY));
- }
- }
- else
- {
- // fallback to standard HitTest
- const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aRange));
- mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance());
- }
- }
+ if (!basegfx::fTools::equal(rBitmapAlphaCandidate.getTransparency(), 1.0))
+ {
+ checkBitmapHit(
+ rCandidate.getB2DRange(getViewInformation2D()),
+ rBitmapAlphaCandidate.getBitmap(),
+ rBitmapAlphaCandidate.getTransform());
}
-
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // use common tooling
+ const primitive2d::BitmapPrimitive2D& rBitmapCandidate(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+ checkBitmapHit(
+ rCandidate.getB2DRange(getViewInformation2D()),
+ rBitmapCandidate.getBitmap(),
+ rBitmapCandidate.getTransform());
break;
}
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
@@ -473,6 +496,8 @@ namespace drawinglayer::processor2d
case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D :
case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
case PRIMITIVE2D_ID_MEDIAPRIMITIVE2D:
+ case PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D:
+ case PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D:
{
if(!getHitTextOnly())
{
@@ -521,7 +546,8 @@ namespace drawinglayer::processor2d
const basegfx::B2DPoint aPosition(getViewInformation2D().getObjectToViewTransformation() * rPositions[a]);
const basegfx::B2DVector aDistance(aPosition - getDiscreteHitPosition());
- if(aDistance.getLength() <= getDiscreteHitTolerance())
+ if (aDistance.getLength() <= std::max(getDiscreteHitTolerance().getX(),
+ getDiscreteHitTolerance().getY()))
{
mbHit = true;
}
@@ -543,7 +569,7 @@ namespace drawinglayer::processor2d
{
/// push candidate to HitStack to create it. This only happens when a hit is found and
/// creating the HitStack was requested (see collectHitStack)
- maHitStack.append(primitive2d::Primitive2DReference(const_cast< primitive2d::BasePrimitive2D* >(&rCandidate)));
+ maHitStack.append(const_cast< primitive2d::BasePrimitive2D* >(&rCandidate));
}
}
diff --git a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
index 9262e23e4509..8c07c8a17c0a 100644
--- a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
+++ b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
@@ -19,20 +19,15 @@
#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-using namespace com::sun::star;
-
-
namespace drawinglayer::processor2d
{
LineGeometryExtractor2D::LineGeometryExtractor2D(const geometry::ViewInformation2D& rViewInformation)
: BaseProcessor2D(rViewInformation),
- maExtractedHairlines(),
- maExtractedLineFills(),
mbInLineGeometry(false)
{
}
@@ -86,20 +81,15 @@ namespace drawinglayer::processor2d
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new transformations for CurrentTransformation and for local ViewInformation2D
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process content
process(rTransformCandidate.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
break;
}
diff --git a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
index 552406d53f68..d1162f6c2af3 100644
--- a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
+++ b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
@@ -21,8 +21,6 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
-using namespace com::sun::star;
-
namespace drawinglayer::processor2d
{
void ObjectInfoPrimitiveExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx
index 7bc0f5fa0536..366e2ed469f7 100644
--- a/drawinglayer/source/processor2d/processor2dtools.cxx
+++ b/drawinglayer/source/processor2d/processor2dtools.cxx
@@ -20,43 +20,165 @@
#include <vcl/gdimtf.hxx>
#include "vclpixelprocessor2d.hxx"
#include "vclmetafileprocessor2d.hxx"
+#include <config_vclplug.h>
+#if defined(_WIN32)
+#include <drawinglayer/processor2d/d2dpixelprocessor2d.hxx>
+#include <vcl/sysdata.hxx>
+#elif USE_HEADLESS_CODE
+#include <drawinglayer/processor2d/cairopixelprocessor2d.hxx>
+#include <officecfg/Office/Common.hxx>
+#endif
using namespace com::sun::star;
-
namespace drawinglayer::processor2d
{
- std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice(
- OutputDevice& rTargetOutDev,
- const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
+std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromScratch(
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D,
+ sal_uInt32 nPixelWidth,
+ sal_uInt32 nPixelHeight,
+ bool bUseRGBA)
+{
+ if (0 == nPixelWidth || 0 == nPixelHeight)
+ // error: no size given
+ return nullptr;
+
+#if USE_HEADLESS_CODE
+ // Linux/Cairo: now globally activated in master. Leave a
+ // possibility to deactivate for easy test/request testing
+ static bool bUsePrimitiveRenderer(nullptr == std::getenv("DISABLE_SYSTEM_DEPENDENT_PRIMITIVE_RENDERER"));
+
+ if (bUsePrimitiveRenderer)
+ {
+ // create CairoPixelProcessor2D with given size
+ std::unique_ptr<CairoPixelProcessor2D> aRetval(
+ std::make_unique<CairoPixelProcessor2D>(
+ rViewInformation2D,
+ nPixelWidth,
+ nPixelHeight,
+ bUseRGBA));
+
+ if (aRetval->valid())
+ return aRetval;
+ }
+#endif
+
+ // avoid unused parameter errors
+ (void)rViewInformation2D;
+ (void)nPixelWidth;
+ (void)nPixelHeight;
+ (void)bUseRGBA;
+
+ // error: no result when no SDPR supported
+ return nullptr;
+}
+
+std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice(
+ OutputDevice& rTargetOutDev,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
+{
+#if defined(_WIN32)
+ // Windows: make dependent on TEST_SYSTEM_PRIMITIVE_RENDERER
+ static bool bUsePrimitiveRenderer(nullptr != std::getenv("TEST_SYSTEM_PRIMITIVE_RENDERER"));
+
+ if (bUsePrimitiveRenderer)
+ {
+ drawinglayer::geometry::ViewInformation2D aViewInformation2D(rViewInformation2D);
+
+ // if mnOutOffX/mnOutOffY is set (a 'hack' to get a cheap additional offset), apply it additionally
+ // NOTE: This will also need to take extended size of target device into
+ // consideration, using D2DPixelProcessor2D *will* have to clip
+ // against that. Thus for now this is *not* sufficient (see tdf#163125)
+ if(0 != rTargetOutDev.GetOutOffXPixel() || 0 != rTargetOutDev.GetOutOffYPixel())
{
- // create Pixel Vcl-Processor
- return std::make_unique<VclPixelProcessor2D>(rViewInformation2D, rTargetOutDev);
+ basegfx::B2DHomMatrix aTransform(aViewInformation2D.getViewTransformation());
+ aTransform.translate(rTargetOutDev.GetOutOffXPixel(), rTargetOutDev.GetOutOffYPixel());
+ aViewInformation2D.setViewTransformation(aTransform);
}
- std::unique_ptr<BaseProcessor2D> createProcessor2DFromOutputDevice(
- OutputDevice& rTargetOutDev,
- const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
+ SystemGraphicsData aData(rTargetOutDev.GetSystemGfxData());
+ std::unique_ptr<D2DPixelProcessor2D> aRetval(
+ std::make_unique<D2DPixelProcessor2D>(aViewInformation2D, aData.hDC));
+ if (aRetval->valid())
+ return aRetval;
+ }
+#elif USE_HEADLESS_CODE
+ // Linux/Cairo: now globally activated in master. Leave a
+ // possibility to deactivate for easy test/request testing
+ static bool bUsePrimitiveRenderer(nullptr == std::getenv("DISABLE_SYSTEM_DEPENDENT_PRIMITIVE_RENDERER"));
+
+ if (bUsePrimitiveRenderer)
+ {
+ // tdf#165061 do not use SDPR when RTL is enabled, SDPR is designed
+ // for rendering EditViews and does not support RTL (yet?)
+ // tdf#165437 also need to check for HasMirroredGraphics to
+ // get *all* mirrorings covered
+ const bool bMirrored(rTargetOutDev.IsRTLEnabled() || rTargetOutDev.HasMirroredGraphics());
+
+ if (!bMirrored)
{
- const GDIMetaFile* pMetaFile = rTargetOutDev.GetConnectMetaFile();
- const bool bOutputToRecordingMetaFile(pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
+ // create CairoPixelProcessor2D associated with the given
+ // OutputDevice
+ std::unique_ptr<CairoPixelProcessor2D> aRetval(
+ std::make_unique<CairoPixelProcessor2D>(
+ rTargetOutDev,
+ rViewInformation2D));
- if(bOutputToRecordingMetaFile)
+ if (aRetval->valid())
{
- // create MetaFile Vcl-Processor and process
- return std::make_unique<VclMetafileProcessor2D>(rViewInformation2D, rTargetOutDev);
- }
- else
- {
- // create Pixel Vcl-Processor
- return createPixelProcessor2DFromOutputDevice(
- rTargetOutDev,
- rViewInformation2D);
+ return aRetval;
}
}
+ }
+#endif
-} // end of namespace
+ // default: create VclPixelProcessor2D
+ // NOTE: Since this uses VCL OutputDevice in the VclPixelProcessor2D
+ // taking care of virtual devices is not needed, OutputDevice
+ // and VclPixelProcessor2D will traditionally take care of it
+ return std::make_unique<VclPixelProcessor2D>(rViewInformation2D, rTargetOutDev);
+}
+
+std::unique_ptr<BaseProcessor2D> createProcessor2DFromOutputDevice(
+ OutputDevice& rTargetOutDev,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
+{
+ const GDIMetaFile* pMetaFile = rTargetOutDev.GetConnectMetaFile();
+ const bool bOutputToRecordingMetaFile(pMetaFile && pMetaFile->IsRecord()
+ && !pMetaFile->IsPause());
+
+ if (bOutputToRecordingMetaFile)
+ {
+ // create MetaFile Vcl-Processor and process
+ return std::make_unique<VclMetafileProcessor2D>(rViewInformation2D, rTargetOutDev);
+ }
+ else
+ {
+ // create Pixel Vcl-Processor
+ return createPixelProcessor2DFromOutputDevice(rTargetOutDev, rViewInformation2D);
+ }
+}
+Bitmap extractBitmapFromBaseProcessor2D(const std::unique_ptr<BaseProcessor2D>& rProcessor)
+{
+ Bitmap aRetval;
+
+#if USE_HEADLESS_CODE
+ // currently only defined for cairo
+ CairoPixelProcessor2D* pSource(dynamic_cast<CairoPixelProcessor2D*>(rProcessor.get()));
+
+ if (nullptr != pSource)
+ aRetval = pSource->extractBitmap();
+#endif
+
+ // avoid unused parameter errors
+ (void)rProcessor;
+
+ // default: return empty Bitmap
+ return aRetval;
+}
+
+} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/processorfromoutputdevice.cxx b/drawinglayer/source/processor2d/processorfromoutputdevice.cxx
deleted file mode 100644
index c8433753aeff..000000000000
--- a/drawinglayer/source/processor2d/processorfromoutputdevice.cxx
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <vcl/outdev.hxx>
-#include <vcl/gdimtf.hxx>
-#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
-#include "vclmetafileprocessor2d.hxx"
-#include "vclpixelprocessor2d.hxx"
-
-using namespace com::sun::star;
-
-namespace drawinglayer::processor2d
-{
- std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> createBaseProcessor2DFromOutputDevice(
- OutputDevice& rTargetOutDev,
- const drawinglayer::geometry::ViewInformation2D& rViewInformation2D)
- {
- const GDIMetaFile* pMetaFile = rTargetOutDev.GetConnectMetaFile();
- const bool bOutputToRecordingMetaFile(pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
-
- if(bOutputToRecordingMetaFile)
- {
- // create MetaFile Vcl-Processor and process
- return std::make_unique<drawinglayer::processor2d::VclMetafileProcessor2D>(rViewInformation2D, rTargetOutDev);
- }
- else
- {
- // create Pixel Vcl-Processor
- return std::make_unique<drawinglayer::processor2d::VclPixelProcessor2D>(rViewInformation2D, rTargetOutDev);
- }
- }
-} // end of namespace
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
index e3a584f86172..4315f6696f75 100644
--- a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
+++ b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
@@ -19,65 +19,56 @@
#include <drawinglayer/processor2d/textaspolygonextractor2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
namespace drawinglayer::processor2d
{
+ void TextAsPolygonExtractor2D::processTextPrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ // PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D
+ // TextDecoratedPortionPrimitive2D can produce the following primitives
+ // when being decomposed:
+ //
+ // - TextSimplePortionPrimitive2D
+ // - PolygonWavePrimitive2D
+ // - PolygonStrokePrimitive2D
+ // - PolygonStrokePrimitive2D
+ // - PolyPolygonColorPrimitive2D
+ // - PolyPolygonHairlinePrimitive2D
+ // - PolygonHairlinePrimitive2D
+ // - ShadowPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - TextEffectPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - GroupPrimitive2D
+
+ // PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D
+ // TextSimplePortionPrimitive2D can produce the following primitives
+ // when being decomposed:
+ //
+ // - PolyPolygonColorPrimitive2D
+ // - TextEffectPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - GroupPrimitive2D
+
+ // encapsulate with flag and use decomposition
+ mnInText++;
+ process(rCandidate);
+ mnInText--;
+ }
+
void TextAsPolygonExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
{
- switch(rCandidate.getPrimitive2DID())
+ switch (rCandidate.getPrimitive2DID())
{
- case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
- {
- // TextDecoratedPortionPrimitive2D can produce the following primitives
- // when being decomposed:
- //
- // - TextSimplePortionPrimitive2D
- // - PolygonWavePrimitive2D
- // - PolygonStrokePrimitive2D
- // - PolygonStrokePrimitive2D
- // - PolyPolygonColorPrimitive2D
- // - PolyPolygonHairlinePrimitive2D
- // - PolygonHairlinePrimitive2D
- // - ShadowPrimitive2D
- // - ModifiedColorPrimitive2D
- // - TransformPrimitive2D
- // - TextEffectPrimitive2D
- // - ModifiedColorPrimitive2D
- // - TransformPrimitive2D
- // - GroupPrimitive2D
-
- // encapsulate with flag and use decomposition
- mnInText++;
- process(rCandidate);
- mnInText--;
-
- break;
- }
- case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
- {
- // TextSimplePortionPrimitive2D can produce the following primitives
- // when being decomposed:
- //
- // - PolyPolygonColorPrimitive2D
- // - TextEffectPrimitive2D
- // - ModifiedColorPrimitive2D
- // - TransformPrimitive2D
- // - GroupPrimitive2D
-
- // encapsulate with flag and use decomposition
- mnInText++;
- process(rCandidate);
- mnInText--;
-
- break;
- }
-
// as can be seen from the TextSimplePortionPrimitive2D and the
// TextDecoratedPortionPrimitive2D, inside of the mnInText marks
// the following primitives can occur containing geometry data
@@ -177,48 +168,27 @@ namespace drawinglayer::processor2d
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new transformations for CurrentTransformation and for local ViewInformation2D
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process content
process(rTransformCandidate.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
break;
}
- // ignorable primitives
- case PRIMITIVE2D_ID_SCENEPRIMITIVE2D :
- case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
- case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
- case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
- case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
- {
+ default:
+ TextExtractor2D::processBasePrimitive2D(rCandidate);
break;
- }
-
- default :
- {
- // process recursively
- process(rCandidate);
- break;
- }
}
}
TextAsPolygonExtractor2D::TextAsPolygonExtractor2D(const geometry::ViewInformation2D& rViewInformation)
- : BaseProcessor2D(rViewInformation),
- maTarget(),
+ : TextExtractor2D(rViewInformation),
maBColorModifierStack(),
mnInText(0)
{
diff --git a/drawinglayer/source/processor2d/textextractor2d.cxx b/drawinglayer/source/processor2d/textextractor2d.cxx
new file mode 100644
index 000000000000..835cb0cc24bc
--- /dev/null
+++ b/drawinglayer/source/processor2d/textextractor2d.cxx
@@ -0,0 +1,88 @@
+/* -*- 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 <drawinglayer/processor2d/textextractor2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+
+namespace drawinglayer::processor2d
+{
+void TextExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ switch (rCandidate.getPrimitive2DID())
+ {
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
+ {
+ processTextPrimitive2D(rCandidate);
+ break;
+ }
+
+ // usage of transformation stack is needed
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
+ {
+ // remember current transformation and ViewInformation
+ const primitive2d::TransformPrimitive2D& rTransformCandidate(
+ static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for CurrentTransformation and for local ViewInformation2D
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(
+ getViewInformation2D().getObjectTransformation()
+ * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
+
+ // process content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ setViewInformation2D(aLastViewInformation2D);
+
+ break;
+ }
+
+ // ignorable primitives
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D:
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D:
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D:
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
+ break;
+
+ default:
+ {
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+}
+
+TextExtractor2D::TextExtractor2D(const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation)
+{
+}
+
+TextExtractor2D::~TextExtractor2D() {}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index 647825959108..d62606ac803b 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -19,7 +19,6 @@
#include <sal/config.h>
#include <sal/log.hxx>
-#include <osl/diagnose.h>
#include <algorithm>
#include <map>
@@ -27,32 +26,43 @@
#include "vclhelperbufferdevice.hxx"
#include <basegfx/range/b2drange.hxx>
-#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmap.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <tools/stream.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <vcl/timer.hxx>
-#include <cppuhelper/basemutex.hxx>
-#include <vcl/lazydelete.hxx>
+#include <tools/lazydelete.hxx>
#include <vcl/dibtools.hxx>
+#include <vcl/skia/SkiaHelper.hxx>
+#include <mutex>
-// buffered VDev usage
+#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
+#include <tools/stream.hxx>
+#endif
+// #define SPEED_COMPARE
+#ifdef SPEED_COMPARE
+#include <tools/time.hxx>
+#endif
+
+// buffered VDev usage
namespace
{
-class VDevBuffer : public Timer, protected cppu::BaseMutex
+class VDevBuffer : public Timer
{
private:
struct Entry
{
VclPtr<VirtualDevice> buf;
- bool isTransparent = false;
- Entry(const VclPtr<VirtualDevice>& vdev, bool bTransparent)
+ Entry(const VclPtr<VirtualDevice>& vdev)
: buf(vdev)
- , isTransparent(bTransparent)
{
}
};
+ std::mutex m_aMutex;
+
// available buffers
std::vector<Entry> maFreeBuffers;
@@ -64,12 +74,13 @@ private:
// virtualdevice because that isn't safe to do at least for Gtk2
std::map<VclPtr<VirtualDevice>, VclPtr<OutputDevice>> maDeviceTemplates;
+ static bool isSizeSuitable(const VclPtr<VirtualDevice>& device, const Size& size);
+
public:
VDevBuffer();
virtual ~VDevBuffer() override;
- VclPtr<VirtualDevice> alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear,
- bool bMonoChrome, bool bTransparent);
+ VclPtr<VirtualDevice> alloc(OutputDevice& rOutDev, const Size& rSizePixel);
void free(VirtualDevice& rDevice);
// Timer virtuals
@@ -77,17 +88,14 @@ public:
};
VDevBuffer::VDevBuffer()
- : Timer("VDevBuffer timer")
- , maFreeBuffers()
- , maUsedBuffers()
+ : Timer("drawinglayer::VDevBuffer via Invoke()")
{
SetTimeout(10L * 1000L); // ten seconds
- SetDebugName("drawinglayer::VDevBuffer via Invoke()");
}
VDevBuffer::~VDevBuffer()
{
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
Stop();
while (!maFreeBuffers.empty())
@@ -103,13 +111,40 @@ VDevBuffer::~VDevBuffer()
}
}
-VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear,
- bool bMonoChrome, bool bTransparent)
+bool VDevBuffer::isSizeSuitable(const VclPtr<VirtualDevice>& device, const Size& rSizePixel)
+{
+ if (device->GetOutputWidthPixel() >= rSizePixel.getWidth()
+ && device->GetOutputHeightPixel() >= rSizePixel.getHeight())
+ {
+ bool requireSmall = false;
+#if defined(UNX)
+ // HACK: See the small size handling in SvpSalVirtualDevice::CreateSurface().
+ // Make sure to not reuse a larger device when a small one should be preferred.
+ if (device->GetRenderBackendName() == "svp")
+ requireSmall = true;
+#endif
+ // The same for Skia, see renderMethodToUseForSize().
+ if (SkiaHelper::isVCLSkiaEnabled())
+ requireSmall = true;
+ if (requireSmall)
+ {
+ if (rSizePixel.getWidth() <= 32 && rSizePixel.getHeight() <= 32
+ && (device->GetOutputWidthPixel() > 32 || device->GetOutputHeightPixel() > 32))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel)
{
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
VclPtr<VirtualDevice> pRetval;
- sal_Int32 nBits = bMonoChrome ? 1 : rOutDev.GetBitCount();
+ sal_Int32 nBits = rOutDev.GetBitCount();
bool bOkay(false);
if (!maFreeBuffers.empty())
@@ -120,7 +155,7 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
{
assert(a->buf && "Empty pointer in VDevBuffer (!)");
- if (nBits == a->buf->GetBitCount() && bTransparent == a->isTransparent)
+ if (nBits == a->buf->GetBitCount())
{
// candidate is valid due to bit depth
if (aFound != maFreeBuffers.end())
@@ -129,9 +164,7 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
if (bOkay)
{
// found is valid
- const bool bCandidateOkay(
- a->buf->GetOutputWidthPixel() >= rSizePixel.getWidth()
- && a->buf->GetOutputHeightPixel() >= rSizePixel.getHeight());
+ const bool bCandidateOkay = isSizeSuitable(a->buf, rSizePixel);
if (bCandidateOkay)
{
@@ -156,16 +189,14 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
{
// found is invalid, use candidate
aFound = a;
- bOkay = aFound->buf->GetOutputWidthPixel() >= rSizePixel.getWidth()
- && aFound->buf->GetOutputHeightPixel() >= rSizePixel.getHeight();
+ bOkay = isSizeSuitable(aFound->buf, rSizePixel);
}
}
else
{
// none yet, use candidate
aFound = a;
- bOkay = aFound->buf->GetOutputWidthPixel() >= rSizePixel.getWidth()
- && aFound->buf->GetOutputHeightPixel() >= rSizePixel.getHeight();
+ bOkay = isSizeSuitable(aFound->buf, rSizePixel);
}
}
}
@@ -192,15 +223,12 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
{
if (bOkay)
{
- if (bClear)
- {
- pRetval->Erase(
- ::tools::Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight()));
- }
+ pRetval->Erase(pRetval->PixelToLogic(
+ tools::Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight())));
}
else
{
- pRetval->SetOutputSizePixel(rSizePixel, bClear);
+ pRetval->SetOutputSizePixel(rSizePixel, true);
}
}
}
@@ -208,11 +236,9 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
// no success yet, create new buffer
if (!pRetval)
{
- pRetval = VclPtr<VirtualDevice>::Create(
- rOutDev, bMonoChrome ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT,
- bTransparent ? DeviceFormat::DEFAULT : DeviceFormat::NONE);
+ pRetval = VclPtr<VirtualDevice>::Create(rOutDev, DeviceFormat::WITHOUT_ALPHA);
maDeviceTemplates[pRetval] = &rOutDev;
- pRetval->SetOutputSizePixel(rSizePixel, bClear);
+ pRetval->SetOutputSizePixel(rSizePixel, true);
}
else
{
@@ -222,14 +248,14 @@ VclPtr<VirtualDevice> VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSize
}
// remember allocated buffer
- maUsedBuffers.emplace_back(pRetval, bTransparent);
+ maUsedBuffers.emplace_back(pRetval);
return pRetval;
}
void VDevBuffer::free(VirtualDevice& rDevice)
{
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
const auto aUsedFound
= std::find_if(maUsedBuffers.begin(), maUsedBuffers.end(),
[&rDevice](const Entry& el) { return el.buf == &rDevice; });
@@ -247,7 +273,7 @@ void VDevBuffer::free(VirtualDevice& rDevice)
void VDevBuffer::Invoke()
{
- ::osl::MutexGuard aGuard(m_aMutex);
+ std::unique_lock aGuard(m_aMutex);
while (!maFreeBuffers.empty())
{
@@ -257,63 +283,138 @@ void VDevBuffer::Invoke()
maFreeBuffers.pop_back();
}
}
-}
-// support for rendering Bitmap and BitmapEx contents
+#ifdef SPEED_COMPARE
+void doSpeedCompare(double fTrans, const Bitmap& rContent, const tools::Rectangle& rDestPixel,
+ OutputDevice& rOutDev)
+{
+ const int nAvInd(500);
+ static double fFactors[nAvInd];
+ static int nIndex(nAvInd + 1);
+ static int nRepeat(5);
+ static int nWorseTotal(0);
+ static int nBetterTotal(0);
+ int a(0);
+
+ const Size aSizePixel(rDestPixel.GetSize());
+
+ // init statics
+ if (nIndex > nAvInd)
+ {
+ for (a = 0; a < nAvInd; a++)
+ fFactors[a] = 1.0;
+ nIndex = 0;
+ }
+
+ // get start time
+ const sal_uInt64 nTimeA(tools::Time::GetSystemTicks());
+
+ // loop nRepeat times to get somewhat better timings, else
+ // numbers are pretty small
+ for (a = 0; a < nRepeat; a++)
+ {
+ // "Former" method using a temporary AlphaMask & DrawBitmapEx
+ sal_uInt8 nMaskValue(static_cast<sal_uInt8>(basegfx::fround(fTrans * 255.0)));
+ const AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
+ rOutDev.DrawBitmapEx(rDestPixel.TopLeft(), Bitmap(rContent, aAlphaMask));
+ }
+
+ // get intermediate time
+ const sal_uInt64 nTimeB(tools::Time::GetSystemTicks());
+
+ // loop nRepeat times
+ for (a = 0; a < nRepeat; a++)
+ {
+ // New method using DrawTransformedBitmapEx & fTrans directly
+ rOutDev.DrawTransformedBitmapEx(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aSizePixel.Width(), aSizePixel.Height(),
+ rDestPixel.TopLeft().X(), rDestPixel.TopLeft().Y()),
+ rContent, 1 - fTrans);
+ }
+
+ // get end time
+ const sal_uInt64 nTimeC(tools::Time::GetSystemTicks());
+ // calculate deltas
+ const sal_uInt64 nTimeFormer(nTimeB - nTimeA);
+ const sal_uInt64 nTimeNew(nTimeC - nTimeB);
+
+ // compare & note down
+ if (nTimeFormer != nTimeNew && 0 != nTimeFormer && 0 != nTimeNew)
+ {
+ if ((nTimeFormer < 10 || nTimeNew < 10) && nRepeat < 500)
+ {
+ nRepeat += 1;
+ SAL_INFO("drawinglayer.processor2d", "Increment nRepeat to " << nRepeat);
+ return;
+ }
+
+ const double fNewFactor((double)nTimeFormer / nTimeNew);
+ fFactors[nIndex % nAvInd] = fNewFactor;
+ nIndex++;
+ double fAverage(0.0);
+ {
+ for (a = 0; a < nAvInd; a++)
+ fAverage += fFactors[a];
+ fAverage /= nAvInd;
+ }
+ if (fNewFactor < 1.0)
+ nWorseTotal++;
+ else
+ nBetterTotal++;
+
+ char buf[300];
+ sprintf(buf,
+ "Former: %ld New: %ld It got %s (factor %f) (av. last %d Former/New is %f, "
+ "WorseTotal: %d, BetterTotal: %d)",
+ nTimeFormer, nTimeNew, fNewFactor < 1.0 ? "WORSE" : "BETTER",
+ fNewFactor < 1.0 ? 1.0 / fNewFactor : fNewFactor, nAvInd, fAverage, nWorseTotal,
+ nBetterTotal);
+ SAL_INFO("drawinglayer.processor2d", buf);
+ }
+}
+#endif
+}
+
+// support for rendering Bitmap contents
namespace drawinglayer
{
-// static global VDev buffer for the VclProcessor2D's (VclMetafileProcessor2D and VclPixelProcessor2D)
+// static global VDev buffer for VclProcessor2D/VclPixelProcessor2D
VDevBuffer& getVDevBuffer()
{
// secure global instance with Vcl's safe destroyer of external (seen by
// library base) stuff, the remembered VDevs need to be deleted before
// Vcl's deinit
- static vcl::DeleteOnDeinit<VDevBuffer> aVDevBuffer(new VDevBuffer());
+ static tools::DeleteOnDeinit<VDevBuffer> aVDevBuffer{};
return *aVDevBuffer.get();
}
-impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange,
- bool bContentTransparent)
+impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange)
: mrOutDev(rOutDev)
, mpContent(nullptr)
- , mpMask(nullptr)
, mpAlpha(nullptr)
- , mbContentTransparent(bContentTransparent)
{
basegfx::B2DRange aRangePixel(rRange);
aRangePixel.transform(mrOutDev.GetViewTransformation());
- const ::tools::Rectangle aRectPixel(static_cast<sal_Int32>(floor(aRangePixel.getMinX())),
- static_cast<sal_Int32>(floor(aRangePixel.getMinY())),
- static_cast<sal_Int32>(ceil(aRangePixel.getMaxX())),
- static_cast<sal_Int32>(ceil(aRangePixel.getMaxY())));
- const Point aEmptyPoint;
- maDestPixel = ::tools::Rectangle(aEmptyPoint, mrOutDev.GetOutputSizePixel());
- maDestPixel.Intersection(aRectPixel);
+ maDestPixel = tools::Rectangle(floor(aRangePixel.getMinX()), floor(aRangePixel.getMinY()),
+ ceil(aRangePixel.getMaxX()), ceil(aRangePixel.getMaxY()));
+ maDestPixel.Intersection(tools::Rectangle{ Point{}, mrOutDev.GetOutputSizePixel() });
if (!isVisible())
return;
-#ifdef IOS
- // Exact mechanism unknown, but for some reason SmartArt
- // rendering, especially shadows, is broken on iOS unless
- // we pass 'true' here. Are virtual devices always de
- // facto cleared when created on other platforms?
- mpContent
- = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false, bContentTransparent);
-#else
- mpContent
- = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false, bContentTransparent);
-#endif
+ mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize());
// #i93485# assert when copying from window to VDev is used
SAL_WARN_IF(
mrOutDev.GetOutDevType() == OUTDEV_WINDOW, "drawinglayer",
"impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)");
+ // initialize buffer by blitting content of source to prepare for
+ // transparence/ copying back
const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled());
mrOutDev.EnableMapMode(false);
- mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(),
+ mpContent->DrawOutDev(Point(), maDestPixel.GetSize(), maDestPixel.TopLeft(),
maDestPixel.GetSize(), mrOutDev);
mrOutDev.EnableMapMode(bWasEnabledSrc);
@@ -338,11 +439,6 @@ impBufferDevice::~impBufferDevice()
getVDevBuffer().free(*mpContent);
}
- if (mpMask)
- {
- getVDevBuffer().free(*mpMask);
- }
-
if (mpAlpha)
{
getVDevBuffer().free(*mpAlpha);
@@ -357,23 +453,18 @@ void impBufferDevice::paint(double fTrans)
const Point aEmptyPoint;
const Size aSizePixel(maDestPixel.GetSize());
const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled());
-#ifdef DBG_UTIL
- static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
-#endif
mrOutDev.EnableMapMode(false);
mpContent->EnableMapMode(false);
#ifdef DBG_UTIL
- if (bDoSaveForVisualControl)
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+
+ if (!sDumpPath.isEmpty() && bDoSaveForVisualControl)
{
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\content.bmp",
-#else
- "~/content.bmp",
-#endif
- StreamMode::WRITE | StreamMode::TRUNC);
+ SvFileStream aNew(sDumpPath + "content.bmp", StreamMode::WRITE | StreamMode::TRUNC);
Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
WriteDIB(aContent, aNew, false, true);
}
@@ -387,67 +478,87 @@ void impBufferDevice::paint(double fTrans)
{
mpAlpha->EnableMapMode(false);
AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
+ aAlphaMask.Invert(); // convert transparency to alpha
#ifdef DBG_UTIL
- if (bDoSaveForVisualControl)
+ if (!sDumpPath.isEmpty() && bDoSaveForVisualControl)
{
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\transparence.bmp",
-#else
- "~/transparence.bmp",
-#endif
- StreamMode::WRITE | StreamMode::TRUNC);
+ SvFileStream aNew(sDumpPath + "transparence.bmp",
+ StreamMode::WRITE | StreamMode::TRUNC);
WriteDIB(aAlphaMask.GetBitmap(), aNew, false, true);
}
#endif
- BitmapEx aContent(mpContent->GetBitmapEx(aEmptyPoint, aSizePixel));
- if (mbContentTransparent)
- aAlphaMask.BlendWith(aContent.GetAlpha());
- mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent.GetBitmap(), aAlphaMask));
+ Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
+ mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), Bitmap(aContent, aAlphaMask));
}
- else if (mpMask)
+ else if (0.0 != fTrans)
{
- mpMask->EnableMapMode(false);
- const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel));
+ const Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
-#ifdef DBG_UTIL
- if (bDoSaveForVisualControl)
- {
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\mask.bmp",
-#else
- "~/mask.bmp",
-#endif
- StreamMode::WRITE | StreamMode::TRUNC);
- WriteDIB(aMask, aNew, false, true);
- }
-#endif
+#ifdef SPEED_COMPARE
+ static bool bCompareFormerAndNewTimings(true);
- if (mbContentTransparent)
+ if (bCompareFormerAndNewTimings)
{
- BitmapEx aContent(mpContent->GetBitmapEx(aEmptyPoint, aSizePixel));
- AlphaMask aAlpha(aContent.GetAlpha());
- aAlpha.BlendWith(aMask);
- mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent.GetBitmap(), aAlpha));
+ doSpeedCompare(fTrans, aContent, maDestPixel, mrOutDev);
}
else
+#endif
+ // Note: this extra scope is needed due to 'clang plugin indentation'. It complains
+ // that lines 494 and (now) 539 are 'statement mis-aligned compared to neighbours'.
+ // That is true if SPEED_COMPARE is not defined. Not nice, but have to fix this.
{
- Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
- mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask));
+ // For the case we have a unified transparency value there is a former
+ // and new method to paint that which can be used. To decide on measurements,
+ // I added 'doSpeedCompare' above which can be activated by defining
+ // SPEED_COMPARE at the top of this file.
+ // I added the used Testdoc: blurplay3.odg as
+ // https://bugs.documentfoundation.org/attachment.cgi?id=182463
+ // I did measure on
+ //
+ // Linux Dbg:
+ // Former: 21 New: 32 It got WORSE (factor 1.523810) (av. last 500 Former/New is 0.968533, WorseTotal: 515, BetterTotal: 934)
+ //
+ // Linux Pro:
+ // Former: 27 New: 44 It got WORSE (factor 1.629630) (av. last 500 Former/New is 0.923256, WorseTotal: 433, BetterTotal: 337)
+ //
+ // Win Dbg:
+ // Former: 21 New: 78 It got WORSE (factor 3.714286) (av. last 500 Former/New is 1.007176, WorseTotal: 85, BetterTotal: 1428)
+ //
+ // Win Pro:
+ // Former: 3 New: 4 It got WORSE (factor 1.333333) (av. last 500 Former/New is 1.054167, WorseTotal: 143, BetterTotal: 3909)
+ //
+ // Note: I am aware that the Dbg are of limited usefulness, but include them here
+ // for reference.
+ //
+ // The important part is "av. last 500 Former/New is %ld" which describes the averaged factor from Former/New
+ // over the last 500 measurements. When < 1.0 Former is better (Linux), > 1.0 (Win) New is better. Since the
+ // factor on Win is still close to 1.0 what means we lose nearly nothing and Linux Former is better, I will
+ // use Former for now.
+ //
+ // To easily allow to change this (maybe system-dependent) I add a static switch here,
+ // also for eventually experimenting (hint: can be changed in the debugger).
+ static bool bUseNew(false);
+
+ if (bUseNew)
+ {
+ // New method using DrawTransformedBitmapEx & fTrans directly
+ mrOutDev.DrawTransformedBitmapEx(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aSizePixel.Width(), aSizePixel.Height(),
+ maDestPixel.TopLeft().X(),
+ maDestPixel.TopLeft().Y()),
+ aContent, 1 - fTrans);
+ }
+ else
+ {
+ // "Former" method using a temporary AlphaMask & DrawBitmapEx
+ sal_uInt8 nMaskValue(static_cast<sal_uInt8>(basegfx::fround(fTrans * 255.0)));
+ const AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
+ mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), Bitmap(aContent, aAlphaMask));
+ }
}
}
- else if (0.0 != fTrans)
- {
- sal_uInt8 nMaskValue(static_cast<sal_uInt8>(basegfx::fround(fTrans * 255.0)));
- AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
- BitmapEx aContent(mpContent->GetBitmapEx(aEmptyPoint, aSizePixel));
- if (mbContentTransparent)
- aAlphaMask.BlendWith(aContent.GetAlpha());
- mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent.GetBitmap(), aAlphaMask));
- }
else
{
mrOutDev.DrawOutDev(maDestPixel.TopLeft(), aSizePixel, aEmptyPoint, aSizePixel, *mpContent);
@@ -464,28 +575,13 @@ VirtualDevice& impBufferDevice::getContent()
return *mpContent;
}
-VirtualDevice& impBufferDevice::getMask()
-{
- SAL_WARN_IF(!mpContent, "drawinglayer",
- "impBufferDevice: No content, check isVisible() before accessing (!)");
- if (!mpMask)
- {
- mpMask = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, true, false);
- mpMask->SetMapMode(mpContent->GetMapMode());
-
- // do NOT copy AA flag for mask!
- }
-
- return *mpMask;
-}
-
VirtualDevice& impBufferDevice::getTransparence()
{
SAL_WARN_IF(!mpContent, "drawinglayer",
"impBufferDevice: No content, check isVisible() before accessing (!)");
if (!mpAlpha)
{
- mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false, false);
+ mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize());
mpAlpha->SetMapMode(mpContent->GetMapMode());
// copy AA flag for new target; masking needs to be smooth
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
index c85e3c4a6048..618fb38209a5 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
@@ -21,12 +21,73 @@
#include <vcl/virdev.hxx>
-namespace basegfx
-{
-class B2DRange;
-}
-
-// support methods for vcl direct gradient rendering
+// Helper class *exclusively* for VclProcessor2D. It should only
+// be used internally, see current four usages. It is used to
+// render something with mask or transparence (see MaskPrimitive2D,
+// UnifiedTransparencePrimitive2D and TransparencePrimitive2D) or
+// as tooling for preparing pixelized output in the renderer
+// (see PatternFillPrimitive2D) if that is faster.
+//
+// To do so, initializing this instance takes over a lot of work
+// from you:
+// - It initializes a 'Content' VDev which is buffered (since it had
+// shown that re-allocating all the time is slower). It checks
+// visibility and all usages initializing this should check for
+// isVisible() after construction.
+// - It pre-initializes the 'Content' VDev with blitting the content
+// of the target VDev.
+// - It offers to get a 'Transparence' VDev (also from the buffer) if
+// needed.
+//
+// If 'Transparence' is/was used, it combines as needed to paint
+// all buffered stuff to target VDev when calling paint().
+// Caution: It is designed to use *either* a fixed transparence in
+// the paint()-call *or* a fill TransparenceChannel using a
+// 'Transparence' VDev. It is *not* designed to use/combine
+// both - it's simply not needed for it's intended purpose/usage.
+//
+// Painting transparent works based on a simple principle: It first
+// blits the original content of the target VDev. Then the content
+// is painted on top of that, plus a Transparence/Mask prepared.
+// The combination always works since unchanged pixels will not
+// change, independent of the transparence value [0..255] it gets
+// mixed with. Or the other way around: Only pixels changed on the
+// Content *can* be changed by transparence values.
+//
+// This is 2.5 times faster than first painting to a
+// 'combined' VDev that supports transparency, as is used by the
+// presentation engine.
+// For the mentioned factor refer to:
+// Patch to demonstrate former and now repaint differences
+// https://gerrit.libreoffice.org/c/core/+/129301
+// git fetch https://git.libreoffice.org/core refs/changes/01/129301/3 && git cherry-pick FETCH_HEAD
+//
+// Note: This principle only works when the target is RGB, so
+// useful for EditViews like for PrimitiveRenderers where this is
+// the case. For usage with GBA targets the starting conditions
+// would have to be modified to not blend against the initial color
+// of 'Content' (usually COL_WHITE).
+//
+// After having finished the rework of ShadowPrimitive2D,
+// SoftEdgePrimitive2D and GlowPrimitive2D (see commits:)
+// e735ad1c57cddaf17d6ffc0cf15b5e14fa63c4ad
+// 707b0c328a282d993fa33b618083d20b6c521de6
+// c2d1458723c66c2fd717a112f89f773226adc841
+// which used the impBufferDevice in such a mode combined with
+// mentioned 'combined' transparence VDev it is now possible
+// to return to this former, much faster method.
+//
+// Please do *not* hack/use this helper class, better create
+// a new one fitting your/the intended purpose. I do not want
+// to see losing performance by this getting modified again.
+//
+// Note: Using that 'combined' transparence VDev is not really
+// recommended, it may vanish anytime. That it works with
+// PrimitiveRenderers *at all* is neither designed nor tested
+// or recommended - it's pure coincidence.
+//
+// I hope that for the future all this will vanish by getting to
+// fully RGBA-capable devices - what is planned and makes sense.
namespace drawinglayer
{
@@ -34,20 +95,16 @@ class impBufferDevice
{
OutputDevice& mrOutDev;
VclPtr<VirtualDevice> mpContent;
- VclPtr<VirtualDevice> mpMask;
VclPtr<VirtualDevice> mpAlpha;
tools::Rectangle maDestPixel;
- bool mbContentTransparent;
public:
- impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange,
- bool bContentTransparent = false);
+ impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange);
~impBufferDevice();
void paint(double fTrans = 0.0);
bool isVisible() const { return !maDestPixel.IsEmpty(); }
VirtualDevice& getContent();
- VirtualDevice& getMask();
VirtualDevice& getTransparence();
};
} // end of namespace drawinglayer
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 4c4a9fe3a329..6c8160f09a70 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -17,38 +17,37 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <cmath>
#include <memory>
#include "vclmetafileprocessor2d.hxx"
#include "vclpixelprocessor2d.hxx"
#include <rtl/ustring.hxx>
-#include <rtl/math.hxx>
#include <tools/gen.hxx>
#include <tools/stream.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/flagguard.hxx>
#include <comphelper/processfactory.hxx>
+#include <config_global.h>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <vcl/virdev.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/gradient.hxx>
#include <vcl/graphictools.hxx>
#include <vcl/metaact.hxx>
#include <vcl/graph.hxx> // for PDFExtOutDevData Graphic support
-#include <toolkit/helper/formpdfexport.hxx> // for PDFExtOutDevData Graphic support
+#include <vcl/formpdfexport.hxx> // for PDFExtOutDevData Graphic support
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/glowprimitive2d.hxx>
-#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokeArrowPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
@@ -65,6 +64,10 @@
#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> // for Title/Description metadata
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/converters.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <tools/vcompat.hxx>
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/i18n/BreakIterator.hpp>
@@ -180,7 +183,7 @@ void fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
if (aSplitted.count() != nPolyCount)
{
- rPolyPolygon = aSplitted;
+ rPolyPolygon = std::move(aSplitted);
}
}
@@ -224,8 +227,10 @@ VclMetafileProcessor2D::impDumpToMetaFile(const primitive2d::Primitive2DContaine
aPrimitiveRange.transform(maCurrentTransformation);
const tools::Rectangle aPrimitiveRectangle(
- basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
- basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
+ basegfx::fround<tools::Long>(aPrimitiveRange.getMinX()),
+ basegfx::fround<tools::Long>(aPrimitiveRange.getMinY()),
+ basegfx::fround<tools::Long>(aPrimitiveRange.getMaxX()),
+ basegfx::fround<tools::Long>(aPrimitiveRange.getMaxY()));
ScopedVclPtrInstance<VirtualDevice> aContentVDev;
MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
@@ -260,22 +265,24 @@ void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
Gradient& o_rVCLGradient, const attribute::FillGradientAttribute& rFiGrAtt,
bool bIsTransparenceGradient) const
{
+ const basegfx::BColor aStartColor(rFiGrAtt.getColorStops().front().getStopColor());
+ const basegfx::BColor aEndColor(rFiGrAtt.getColorStops().back().getStopColor());
+
if (bIsTransparenceGradient)
{
// it's about transparence channel intensities (black/white), do not use color modifier
- o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
- o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
+ o_rVCLGradient.SetStartColor(Color(aStartColor));
+ o_rVCLGradient.SetEndColor(Color(aEndColor));
}
else
{
// use color modifier to influence start/end color of gradient
- o_rVCLGradient.SetStartColor(
- Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
- o_rVCLGradient.SetEndColor(
- Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
+ o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(aStartColor)));
+ o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(aEndColor)));
}
- o_rVCLGradient.SetAngle(static_cast<sal_uInt16>(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
+ o_rVCLGradient.SetAngle(
+ Degree10(static_cast<sal_uInt32>(basegfx::rad2deg<10>(rFiGrAtt.getAngle()))));
o_rVCLGradient.SetBorder(static_cast<sal_uInt16>(rFiGrAtt.getBorder() * 100.0));
o_rVCLGradient.SetOfsX(static_cast<sal_uInt16>(rFiGrAtt.getOffsetX() * 100.0));
o_rVCLGradient.SetOfsY(static_cast<sal_uInt16>(rFiGrAtt.getOffsetY() * 100.0));
@@ -284,40 +291,7 @@ void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
// defaults for intensity; those were computed into the start/end colors already
o_rVCLGradient.SetStartIntensity(100);
o_rVCLGradient.SetEndIntensity(100);
-
- switch (rFiGrAtt.getStyle())
- {
- default: // attribute::GradientStyle::Linear :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Linear);
- break;
- }
- case attribute::GradientStyle::Axial:
- {
- o_rVCLGradient.SetStyle(GradientStyle::Axial);
- break;
- }
- case attribute::GradientStyle::Radial:
- {
- o_rVCLGradient.SetStyle(GradientStyle::Radial);
- break;
- }
- case attribute::GradientStyle::Elliptical:
- {
- o_rVCLGradient.SetStyle(GradientStyle::Elliptical);
- break;
- }
- case attribute::GradientStyle::Square:
- {
- o_rVCLGradient.SetStyle(GradientStyle::Square);
- break;
- }
- case attribute::GradientStyle::Rect:
- {
- o_rVCLGradient.SetStyle(GradientStyle::Rect);
- break;
- }
- }
+ o_rVCLGradient.SetStyle(rFiGrAtt.getStyle());
}
void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill const* pSvtGraphicFill)
@@ -328,7 +302,7 @@ void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill const* pSvtGr
WriteSvtGraphicFill(aMemStm, *pSvtGraphicFill);
mpMetaFile->AddAction(new MetaCommentAction(
- "XPATHFILL_SEQ_BEGIN", 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ "XPATHFILL_SEQ_BEGIN"_ostr, 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
aMemStm.TellEnd()));
mnSvtGraphicFillCount++;
}
@@ -339,7 +313,7 @@ void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill const* pSvtGrap
if (pSvtGraphicFill && mnSvtGraphicFillCount)
{
mnSvtGraphicFillCount--;
- mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"_ostr));
}
}
@@ -386,36 +360,34 @@ std::unique_ptr<SvtGraphicStroke> VclMetafileProcessor2D::impTryToCreateSvtGraph
if (!aLocalPolygon.isClosed())
{
- double fPolyLength(0.0);
- double fStart(0.0);
- double fEnd(0.0);
-
- if (pStart && pStart->isActive())
+ const bool bCalcStart = pStart && pStart->isActive();
+ const bool bCalcEnd = pEnd && pEnd->isActive();
+ if (bCalcStart || bCalcEnd)
{
- fPolyLength = basegfx::utils::getLength(aLocalPolygon);
+ double fPolyLength = basegfx::utils::getLength(aLocalPolygon);
+ double fStart(0.0);
+ double fEnd(0.0);
- aStartArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
- fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart);
- }
-
- if (pEnd && pEnd->isActive())
- {
- if (basegfx::fTools::equalZero(fPolyLength))
+ if (bCalcStart)
{
- fPolyLength = basegfx::utils::getLength(aLocalPolygon);
+ aStartArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
+ fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart);
}
- aEndArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), fPolyLength,
- pEnd->isCentered() ? 0.5 : 0.0, &fEnd);
- }
+ if (bCalcEnd)
+ {
+ aEndArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
+ fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, &fEnd);
+ }
- if (0.0 != fStart || 0.0 != fEnd)
- {
- // build new poly, consume something from old poly
- aLocalPolygon = basegfx::utils::getSnippetAbsolute(aLocalPolygon, fStart,
- fPolyLength - fEnd, fPolyLength);
+ if (0.0 != fStart || 0.0 != fEnd)
+ {
+ // build new poly, consume something from old poly
+ aLocalPolygon = basegfx::utils::getSnippetAbsolute(
+ aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength);
+ }
}
}
@@ -446,7 +418,8 @@ std::unique_ptr<SvtGraphicStroke> VclMetafileProcessor2D::impTryToCreateSvtGraph
{
eJoin = SvtGraphicStroke::joinMiter;
// ATM 15 degrees is assumed
- fMiterLength /= rtl::math::sin(basegfx::deg2rad(15.0));
+ // TODO wait for P1383R0 and C++20's std::numbers::pi
+ fMiterLength /= std::sin(M_PI / 12);
break;
}
case basegfx::B2DLineJoin::Round:
@@ -497,7 +470,7 @@ std::unique_ptr<SvtGraphicStroke> VclMetafileProcessor2D::impTryToCreateSvtGraph
pRetval.reset(
new SvtGraphicStroke(tools::Polygon(aLocalPolygon), tools::PolyPolygon(aStartArrow),
tools::PolyPolygon(aEndArrow), mfCurrentUnifiedTransparence,
- fLineWidth, eCap, eJoin, fMiterLength, aDashArray));
+ fLineWidth, eCap, eJoin, fMiterLength, std::move(aDashArray)));
}
return pRetval;
@@ -511,7 +484,7 @@ void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke const* pS
WriteSvtGraphicStroke(aMemStm, *pSvtGraphicStroke);
mpMetaFile->AddAction(new MetaCommentAction(
- "XPATHSTROKE_SEQ_BEGIN", 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ "XPATHSTROKE_SEQ_BEGIN"_ostr, 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
aMemStm.TellEnd()));
mnSvtGraphicStrokeCount++;
}
@@ -522,11 +495,11 @@ void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke const* pSvt
if (pSvtGraphicStroke && mnSvtGraphicStrokeCount)
{
mnSvtGraphicStrokeCount--;
- mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"_ostr));
}
}
-void VclMetafileProcessor2D::popStructureElement(vcl::PDFWriter::StructElement eElem)
+void VclMetafileProcessor2D::popStructureElement(vcl::pdf::StructElement eElem)
{
if (!maListElements.empty() && maListElements.top() == eElem)
{
@@ -537,19 +510,16 @@ void VclMetafileProcessor2D::popStructureElement(vcl::PDFWriter::StructElement e
void VclMetafileProcessor2D::popListItem()
{
- popStructureElement(vcl::PDFWriter::LIBody);
- popStructureElement(vcl::PDFWriter::ListItem);
+ popStructureElement(vcl::pdf::StructElement::LIBody);
+ popStructureElement(vcl::pdf::StructElement::ListItem);
}
void VclMetafileProcessor2D::popList()
{
popListItem();
- popStructureElement(vcl::PDFWriter::List);
+ popStructureElement(vcl::pdf::StructElement::List);
}
-// init static break iterator
-uno::Reference<css::i18n::XBreakIterator> VclMetafileProcessor2D::mxBreakIterator;
-
VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation,
OutputDevice& rOutDev)
: VclProcessor2D(rViewInformation, rOutDev)
@@ -680,7 +650,7 @@ VclMetafileProcessor2D::~VclMetafileProcessor2D()
Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
used to export the original again (if exists).
- Not necessary to support with MetaFuleRenderer.
+ Not necessary to support with MetaFileRenderer.
XTEXT_SCROLLRECT, XTEXT_PAINTRECT
Currently used to get extra MetaFile infos using GraphicExporter which again uses
@@ -720,17 +690,7 @@ VclMetafileProcessor2D::~VclMetafileProcessor2D()
- UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
- This may be added in primitive MetaFile renderer.
- Adding support...
- OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
- svxform. Have to talk to FS if this has to be like that. Especially since
- vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
- Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
- that stuff to somewhere else, maybe tools or svtools ?!? We will see...
- Moved to toolkit, so I have to link against it. I tried VCL first, but it did
- not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other than the name
- may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
- the lowest movement plane is toolkit.
+ This was added in primitive MetaFile renderer.
Checked form control export, it works well. Done.
- In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
@@ -829,7 +789,7 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
{
- // direct draw of transformed BitmapEx primitive; use default processing, but without
+ // direct draw of transformed Bitmap primitive; use default processing, but without
// former testing if graphic content is inside discrete local viewport; this is not
// setup for metafile targets (metafile renderer tries to render in logic coordinates,
// the mapping is kept to the OutputDevice for better Metafile recording)
@@ -838,8 +798,17 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D:
{
- processPolyPolygonGraphicPrimitive2D(
- static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D&>(rCandidate));
+ if (maBColorModifierStack.count())
+ {
+ // tdf#151104 unfortunately processPolyPolygonGraphicPrimitive2D below
+ // does not support an active BColorModifierStack, so use the default
+ process(rCandidate);
+ }
+ else
+ {
+ processPolyPolygonGraphicPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D&>(rCandidate));
+ }
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D:
@@ -867,7 +836,7 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
{
- // modified color group. Force output to unified color. Use default pocessing.
+ // modified color group. Force output to unified color. Use default processing.
RenderModifiedColorPrimitive2D(
static_cast<const primitive2d::ModifiedColorPrimitive2D&>(rCandidate));
break;
@@ -886,7 +855,7 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
{
- // use default transform group pocessing
+ // use default transform group processing
RenderTransformPrimitive2D(
static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
break;
@@ -900,14 +869,14 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
{
- // use default marker array pocessing
+ // use default marker array processing
RenderMarkerArrayPrimitive2D(
static_cast<const primitive2d::MarkerArrayPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
{
- // use default point array pocessing
+ // use default point array processing
RenderPointArrayPrimitive2D(
static_cast<const primitive2d::PointArrayPrimitive2D&>(rCandidate));
break;
@@ -925,14 +894,21 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D:
{
- RenderObjectInfoPrimitive2D(
+ processObjectInfoPrimitive2D(
static_cast<const primitive2d::ObjectInfoPrimitive2D&>(rCandidate));
break;
}
- case PRIMITIVE2D_ID_GLOWPRIMITIVE2D:
- case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D:
+ case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
{
- processPrimitive2DOnPixelProcessor(rCandidate);
+ processFillGraphicPrimitive2D(
+ static_cast<const primitive2d::FillGraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYEMPHASISMARKPRIMITIVE2D:
+ {
+ // EmphasisMarks are traditionally not added to Metafiles, see
+ // OutputDevice::ImplDrawEmphasisMarks which resets GDIMetaFile*
+ // while painting these, so just ignore these
break;
}
default:
@@ -944,6 +920,165 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi
}
}
+void VclMetafileProcessor2D::processObjectInfoPrimitive2D(
+ primitive2d::ObjectInfoPrimitive2D const& rObjectInfoPrimitive2D)
+{
+ // tdf#154982 process content first, so this object overrides any nested one
+ process(rObjectInfoPrimitive2D.getChildren());
+
+ // currently StructureTagPrimitive2D is only used for SdrObjects - have to
+ // avoid adding Alt text if the SdrObject is not actually tagged, as it
+ // would then end up on an unrelated structure element.
+ if (mpCurrentStructureTag && mpCurrentStructureTag->isTaggedSdrObject())
+ {
+ // Create image alternative description from ObjectInfoPrimitive2D info
+ // for PDF export, for the currently active SdrObject's structure element
+ if (mpPDFExtOutDevData->GetIsExportTaggedPDF())
+ {
+ OUString aAlternateDescription;
+
+ if (!rObjectInfoPrimitive2D.getTitle().isEmpty())
+ {
+ aAlternateDescription += rObjectInfoPrimitive2D.getTitle();
+ }
+
+ if (!rObjectInfoPrimitive2D.getDesc().isEmpty())
+ {
+ if (!aAlternateDescription.isEmpty())
+ {
+ aAlternateDescription += " - ";
+ }
+
+ aAlternateDescription += rObjectInfoPrimitive2D.getDesc();
+ }
+
+ // Use SetAlternateText to set it. This will work as long as some
+ // structure is used (see PDFWriterImpl::setAlternateText and
+ // m_nCurrentStructElement - tagged PDF export works with this in
+ // Draw/Impress/Writer, but not in Calc due to too less structure...)
+ //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..?
+ if (!aAlternateDescription.isEmpty())
+ {
+ mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
+ }
+ }
+ }
+}
+
+void VclMetafileProcessor2D::processFillGraphicPrimitive2D(
+ primitive2d::FillGraphicPrimitive2D const& rFillGraphicPrimitive2D)
+{
+ // tdf#166709 check if we have to make an exception handling this
+ // FillGraphicPrimitive2D. If it
+ // - has transparency
+ // - is tiled
+ // - is a Bitmap
+ // - is not animated
+ // - is no embedded SVG
+ // we have to, see below
+ if (!basegfx::fTools::equalZero(rFillGraphicPrimitive2D.getTransparency(), 0.0))
+ {
+ // we have transparency
+ const attribute::FillGraphicAttribute& rAttribute(rFillGraphicPrimitive2D.getFillGraphic());
+
+ if (rAttribute.getTiling())
+ {
+ // we have tiling
+ const Graphic& rGraphic(rAttribute.getGraphic());
+
+ if (GraphicType::Bitmap == rGraphic.GetType() && !rGraphic.IsAnimated()
+ && !rGraphic.getVectorGraphicData())
+ {
+ // tdf#166709 it is a Bitmap, not animated & not
+ // embedded SVG.
+
+ // conditions are met. Unfortunately for metafile
+ // and for PDF export we *need* all tiles which are
+ // potentially created by the decomposition of the
+ // FillGraphicPrimitive2D to be embedded to a single
+ // UnifiedTransparencePrimitive2D that holds that
+ // transparency - as it was before adding more
+ // possibilities for direct unified transparency.
+
+ // Despite the decomposition being correct and creating
+ // now BitmapAlphaPrimitive2D with every one holding the
+ // correct alpha, the 'old' way with encapsulating to
+ // a UnifiedTransparencePrimitive2D is needed here
+ // to create a single bitmap representation that then
+ // gets used. When not doing this a potentially high
+ // number of BitmapAlphaPrimitive2D will be exported,
+ // which is not an error but needs too much resources,
+ // prevents loading of the created PDF for some viewers
+ // and bloats the PDF file.
+
+ // NOTE: I thought if only doing this for the PDF export
+ // case would make sense, but all exports still based
+ // on metafile potentially have this problem, so better
+ // do it in general at metafile creation already.
+
+ // NOTE: This shows how urgent it would be to create a
+ // PDF export using a PrimitiveRenderer instead of
+ // Metafile - that could do the right thing and use
+ // a representation in the PDF that is capable of
+ // tiling. No chance to do that with the existing
+ // metafile stuff we have.
+
+ // NOTE: The creation of the possible MetafileAction
+ // for this is done here locally in method
+ // processUnifiedTransparencePrimitive2D. Use that
+ // directly if necessary.
+
+ // So: create a FillGraphicPrimitive2D without transparency
+ // embedded to a UnifiedTransparencePrimitive2D representing
+ // the transparency and process it directly
+ rtl::Reference<primitive2d::BasePrimitive2D> aPrimitive(
+ new primitive2d::UnifiedTransparencePrimitive2D(
+ primitive2d::Primitive2DContainer{
+ rtl::Reference<primitive2d::FillGraphicPrimitive2D>(
+ new primitive2d::FillGraphicPrimitive2D(
+ rFillGraphicPrimitive2D.getTransformation(),
+ attribute::FillGraphicAttribute(
+ rGraphic, rAttribute.getGraphicRange(),
+ rAttribute.getTiling(), rAttribute.getOffsetX(),
+ rAttribute.getOffsetY()))) },
+ rFillGraphicPrimitive2D.getTransparency()));
+
+ // tdf#166709 see comments 21-23, we have two possibilities here:
+ // (a) use UnifiedTransparencePrimitive2D: test PDF is 47.5kb
+ // (b) use TransparencePrimitive2D: test PDF is 30.8 kb
+ // differences are described in the task. Due to (b) being smaller
+ // and is better re-loadable I opt for that. To be able to change
+ // this easily I let both versions stand here
+ static bool bTransparencePrimitive2DUse(true);
+
+ if (bTransparencePrimitive2DUse)
+ {
+ // process recursively. Since this first gets the decomposition
+ // (else a primitive processor would loop recursively) this will
+ // use TransparencePrimitive2D, created by
+ // UnifiedTransparencePrimitive2D::get2DDecomposition. This could
+ // also be done here, but that decompose already has needed stuff
+ // and we keep it in one place
+ process(*aPrimitive);
+ }
+ else
+ {
+ // process UnifiedTransparencePrimitive2D primitive directly
+ processUnifiedTransparencePrimitive2D(
+ static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(
+ *aPrimitive));
+ }
+
+ // we are done, return
+ return;
+ }
+ }
+ }
+
+ // all other cases: process recursively with original primitive
+ process(rFillGraphicPrimitive2D);
+}
+
void VclMetafileProcessor2D::processGraphicPrimitive2D(
const primitive2d::GraphicPrimitive2D& rGraphicPrimitive)
{
@@ -1035,43 +1170,11 @@ void VclMetafileProcessor2D::processGraphicPrimitive2D(
sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
}
- // Create image alternative description from ObjectInfoPrimitive2D info
- // for PDF export
- if (mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != getObjectInfoPrimitive2D())
- {
- OUString aAlternateDescription;
-
- if (!getObjectInfoPrimitive2D()->getTitle().isEmpty())
- {
- aAlternateDescription += getObjectInfoPrimitive2D()->getTitle();
- }
-
- if (!getObjectInfoPrimitive2D()->getDesc().isEmpty())
- {
- if (!aAlternateDescription.isEmpty())
- {
- aAlternateDescription += " - ";
- }
-
- aAlternateDescription += getObjectInfoPrimitive2D()->getDesc();
- }
-
- // Use SetAlternateText to set it. This will work as long as some
- // structure is used (see PDFWriterImpl::setAlternateText and
- // m_nCurrentStructElement - tagged PDF export works with this in
- // Draw/Impress/Writer, but not in Calc due to too less structure...)
- //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..?
- if (!aAlternateDescription.isEmpty())
- {
- mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
- }
- }
-
// #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
// object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
// uncropped region. Thus, correct order is aCropRect, aCurrentRect
mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
- rAttr.GetTransparency(), aCropRect, aCurrentRect);
+ 255 - rAttr.GetAlpha(), aCropRect, aCurrentRect);
}
void VclMetafileProcessor2D::processControlPrimitive2D(
@@ -1090,7 +1193,7 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
uno::Reference<beans::XPropertySetInfo> xPropertyInfo(
xModelProperties.is() ? xModelProperties->getPropertySetInfo()
: uno::Reference<beans::XPropertySetInfo>());
- const OUString sPrintablePropertyName("Printable");
+ static constexpr OUString sPrintablePropertyName(u"Printable"_ustr);
if (xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
{
@@ -1109,14 +1212,25 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
if (!bIsPrintableControl)
return;
+ ::std::optional<sal_Int32> oAnchorParent;
+ if (mpPDFExtOutDevData)
+ {
+ if (rControlPrimitive.GetAnchorStructureElementKey())
+ {
+ sal_Int32 const id = mpPDFExtOutDevData->EnsureStructureElement(
+ rControlPrimitive.GetAnchorStructureElementKey());
+ oAnchorParent.emplace(mpPDFExtOutDevData->GetCurrentStructureElement());
+ mpPDFExtOutDevData->SetCurrentStructureElement(id);
+ }
+ }
+
const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
bool bDoProcessRecursively(true);
+ bool bDecorative = (mpCurrentStructureTag && mpCurrentStructureTag->isDecorative());
- if (bPDFExport)
+ if (bPDFExport && !bDecorative)
{
// PDF export. Emulate data handling from UnoControlPDFExportContact
- // I have now moved describePDFControl to toolkit, thus i can implement the PDF
- // form control support now as follows
std::unique_ptr<vcl::PDFWriter::AnyWidget> pPDFControl(
::toolkitform::describePDFControl(rXControl, *mpPDFExtOutDevData));
@@ -1136,9 +1250,37 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
mpOutputDevice->GetMapMode());
pPDFControl->TextFont.SetFontSize(aFontSize);
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Form);
+ vcl::PDFWriter::StructAttributeValue role;
+ switch (pPDFControl->Type)
+ {
+ case vcl::PDFWriter::PushButton:
+ role = vcl::PDFWriter::Pb;
+ break;
+ case vcl::PDFWriter::RadioButton:
+ role = vcl::PDFWriter::Rb;
+ break;
+ case vcl::PDFWriter::CheckBox:
+ role = vcl::PDFWriter::Cb;
+ break;
+ default: // there is a paucity of roles, tv is the catch-all one
+ role = vcl::PDFWriter::Tv;
+ break;
+ }
+ // ISO 14289-1:2014, Clause: 7.18.4
+ mpPDFExtOutDevData->SetStructureAttribute(vcl::PDFWriter::Role, role);
+ // ISO 14289-1:2014, Clause: 7.18.1
+ OUString const& rAltText(rControlPrimitive.GetAltText());
+ if (!rAltText.isEmpty())
+ {
+ mpPDFExtOutDevData->SetAlternateText(rAltText);
+ }
mpPDFExtOutDevData->CreateControl(*pPDFControl);
mpPDFExtOutDevData->EndStructureElement();
+ if (oAnchorParent)
+ {
+ mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
+ }
// no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
// do not process recursively
@@ -1152,6 +1294,32 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
}
}
+ if (!bDoProcessRecursively)
+ {
+ return;
+ }
+
+ if (mpPDFExtOutDevData)
+ { // no corresponding PDF Form, use Figure instead
+ if (!bDecorative)
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Figure);
+ else
+ mpPDFExtOutDevData->WrapBeginStructureElement(
+ vcl::pdf::StructElement::NonStructElement);
+ mpPDFExtOutDevData->SetStructureAttribute(vcl::PDFWriter::Placement, vcl::PDFWriter::Block);
+ auto const range(rControlPrimitive.getB2DRange(getViewInformation2D()));
+ tools::Rectangle const aLogicRect(basegfx::fround<tools::Long>(range.getMinX()),
+ basegfx::fround<tools::Long>(range.getMinY()),
+ basegfx::fround<tools::Long>(range.getMaxX()),
+ basegfx::fround<tools::Long>(range.getMaxY()));
+ mpPDFExtOutDevData->SetStructureBoundingBox(aLogicRect);
+ OUString const& rAltText(rControlPrimitive.GetAltText());
+ if (!rAltText.isEmpty() && !bDecorative)
+ {
+ mpPDFExtOutDevData->SetAlternateText(rAltText);
+ }
+ }
+
// #i93169# used flag the wrong way; true means that nothing was done yet
if (bDoProcessRecursively)
{
@@ -1196,6 +1364,15 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
{
process(rControlPrimitive);
}
+
+ if (mpPDFExtOutDevData)
+ {
+ mpPDFExtOutDevData->EndStructureElement();
+ if (oAnchorParent)
+ {
+ mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
+ }
+ }
}
void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
@@ -1203,10 +1380,9 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
{
// support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
// thus do the MetafileAction embedding stuff but just handle recursively.
- const OString aCommentStringCommon("FIELD_SEQ_BEGIN");
- const OString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
- const OString aCommentStringEnd("FIELD_SEQ_END");
+ static constexpr OString aCommentStringCommon("FIELD_SEQ_BEGIN"_ostr);
OUString aURL;
+ const bool bIsExportTaggedPDF(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF());
switch (rFieldPrimitive.getType())
{
@@ -1217,18 +1393,22 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
}
case drawinglayer::primitive2d::FIELD_TYPE_PAGE:
{
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
+ mpMetaFile->AddAction(new MetaCommentAction("FIELD_SEQ_BEGIN;PageField"_ostr));
break;
}
case drawinglayer::primitive2d::FIELD_TYPE_URL:
{
- aURL = rFieldPrimitive.getValue("URL");
+ aURL = rFieldPrimitive.getValue(u"URL"_ustr);
if (!aURL.isEmpty())
{
mpMetaFile->AddAction(new MetaCommentAction(
aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()),
2 * aURL.getLength()));
+
+ if (bIsExportTaggedPDF)
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Link,
+ u"Link"_ustr);
}
break;
@@ -1241,7 +1421,7 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
process(rContent);
// for the end comment the type is not relevant yet, they are all the same. Just add.
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
+ mpMetaFile->AddAction(new MetaCommentAction("FIELD_SEQ_END"_ostr));
if (!(mpPDFExtOutDevData
&& drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType()))
@@ -1254,43 +1434,47 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
static_cast<sal_Int32>(ceil(aViewRange.getMaxX())),
static_cast<sal_Int32>(ceil(aViewRange.getMaxY())));
vcl::PDFExtOutDevBookmarkEntry aBookmark;
- aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
+ OUString const altText(rFieldPrimitive.getValue(u"AltText"_ustr));
+ aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic, altText);
aBookmark.aBookmark = aURL;
std::vector<vcl::PDFExtOutDevBookmarkEntry>& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
rBookmarks.push_back(aBookmark);
+
+ if (bIsExportTaggedPDF)
+ {
+ mpPDFExtOutDevData->SetStructureAttributeNumerical(vcl::PDFWriter::LinkAnnotation,
+ aBookmark.nLinkId);
+ mpPDFExtOutDevData->EndStructureElement();
+ }
}
void VclMetafileProcessor2D::processTextHierarchyLinePrimitive2D(
const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive)
{
- const OString aCommentString("XTEXT_EOL");
-
// process recursively and add MetaFile comment
process(rLinePrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ mpMetaFile->AddAction(new MetaCommentAction("XTEXT_EOL"_ostr));
}
void VclMetafileProcessor2D::processTextHierarchyBulletPrimitive2D(
const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive)
{
- // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
- // "XTEXT_EOC" is used, use here, too.
- const OString aCommentString("XTEXT_EOC");
-
// this is a part of list item, start LILabel ( = bullet)
if (mbInListItem)
{
- maListElements.push(vcl::PDFWriter::LILabel);
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::LILabel);
+ maListElements.push(vcl::pdf::StructElement::LILabel);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::LILabel);
}
// process recursively and add MetaFile comment
process(rBulletPrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ // in Outliner::StripBullet(), a MetafileComment for bullets is added, too. The
+ // "XTEXT_EOC" is used, use here, too.
+ mpMetaFile->AddAction(new MetaCommentAction("XTEXT_EOC"_ostr));
if (mbInListItem)
{
- if (maListElements.top() == vcl::PDFWriter::LILabel)
+ if (maListElements.top() == vcl::pdf::StructElement::LILabel)
{
maListElements.pop();
mpPDFExtOutDevData->EndStructureElement(); // end LILabel
@@ -1302,7 +1486,7 @@ void VclMetafileProcessor2D::processTextHierarchyBulletPrimitive2D(
void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(
const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive)
{
- const OString aCommentString("XTEXT_EOP");
+ static constexpr OString aCommentString("XTEXT_EOP"_ostr);
static bool bSuppressPDFExtOutDevDataSupport(false); // loplugin:constvars:ignore
if (nullptr == mpPDFExtOutDevData || bSuppressPDFExtOutDevDataSupport)
@@ -1318,7 +1502,7 @@ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(
{
// No Tagged PDF -> Dump as Paragraph
// Emulate data handling from old ImpEditEngine::Paint
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Paragraph);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Paragraph);
// Process recursively and add MetaFile comment
process(rParagraphPrimitive);
@@ -1343,8 +1527,8 @@ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(
// increase List level
for (sal_Int16 a(mnCurrentOutlineLevel); a != nNewOutlineLevel; ++a)
{
- maListElements.push(vcl::PDFWriter::List);
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::List);
+ maListElements.push(vcl::pdf::StructElement::List);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::List);
}
}
else // if(nNewOutlineLevel < mnCurrentOutlineLevel)
@@ -1374,14 +1558,14 @@ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(
if (bDumpAsListItem)
{
// Dump as ListItem
- maListElements.push(vcl::PDFWriter::ListItem);
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::ListItem);
+ maListElements.push(vcl::pdf::StructElement::ListItem);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::ListItem);
mbInListItem = true;
}
else
{
// Dump as Paragraph
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Paragraph);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Paragraph);
}
// Process recursively and add MetaFile comment
@@ -1397,11 +1581,8 @@ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(
void VclMetafileProcessor2D::processTextHierarchyBlockPrimitive2D(
const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive)
{
- const OString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
- const OString aCommentStringB("XTEXT_PAINTSHAPE_END");
-
// add MetaFile comment, process recursively and add MetaFile comment
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
+ mpMetaFile->AddAction(new MetaCommentAction("XTEXT_PAINTSHAPE_BEGIN"_ostr));
process(rBlockPrimitive);
if (mnCurrentOutlineLevel >= 0)
@@ -1413,7 +1594,7 @@ void VclMetafileProcessor2D::processTextHierarchyBlockPrimitive2D(
}
}
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
+ mpMetaFile->AddAction(new MetaCommentAction("XTEXT_PAINTSHAPE_END"_ostr));
}
void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(
@@ -1427,8 +1608,8 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(
// bullet has been already processed, start LIBody
if (mbInListItem && mbBulletPresent)
{
- maListElements.push(vcl::PDFWriter::LIBody);
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::LIBody);
+ maListElements.push(vcl::pdf::StructElement::LIBody);
+ mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::LIBody);
}
// directdraw of text simple portion; use default processing
@@ -1442,13 +1623,22 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(
// #i101169# if(pTextDecoratedCandidate)
{
+ /* break iterator support
+ made static so it only needs to be fetched once, even with many single
+ constructed VclMetafileProcessor2D. It's still incarnated on demand,
+ but exists for OOo runtime now by purpose.
+ */
+ static tools::DeleteOnDeinit<css::uno::Reference<css::i18n::XBreakIterator>>
+ gxBreakIterator;
+
// support for TEXT_ MetaFile actions only for decorated texts
- if (!mxBreakIterator.is())
+ if (!gxBreakIterator.get() || !gxBreakIterator.get()->get())
{
- uno::Reference<uno::XComponentContext> xContext(
+ const uno::Reference<uno::XComponentContext>& xContext(
::comphelper::getProcessComponentContext());
- mxBreakIterator = i18n::BreakIterator::create(xContext);
+ gxBreakIterator.set(i18n::BreakIterator::create(xContext));
}
+ auto& rBreakIterator = *gxBreakIterator.get()->get();
const OUString& rTxt = rTextCandidate.getText();
const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
@@ -1459,16 +1649,16 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(
const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
sal_Int32 nDone;
- sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(
+ sal_Int32 nNextCellBreak(rBreakIterator.nextCharacters(
rTxt, nTextPosition, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 0,
nDone));
- css::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(
+ css::i18n::Boundary nNextWordBoundary(rBreakIterator.getWordBoundary(
rTxt, nTextPosition, rLocale, css::i18n::WordType::ANY_WORD, true));
sal_Int32 nNextSentenceBreak(
- mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
- const OString aCommentStringA("XTEXT_EOC");
- const OString aCommentStringB("XTEXT_EOW");
- const OString aCommentStringC("XTEXT_EOS");
+ rBreakIterator.endOfSentence(rTxt, nTextPosition, rLocale));
+ static constexpr OStringLiteral aCommentStringA("XTEXT_EOC");
+ static constexpr OStringLiteral aCommentStringB("XTEXT_EOW");
+ static constexpr OStringLiteral aCommentStringC("XTEXT_EOS");
for (sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
{
@@ -1477,21 +1667,21 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(
{
mpMetaFile->AddAction(
new MetaCommentAction(aCommentStringA, i - nTextPosition));
- nNextCellBreak = mxBreakIterator->nextCharacters(
+ nNextCellBreak = rBreakIterator.nextCharacters(
rTxt, i, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
}
if (i == nNextWordBoundary.endPos)
{
mpMetaFile->AddAction(
new MetaCommentAction(aCommentStringB, i - nTextPosition));
- nNextWordBoundary = mxBreakIterator->getWordBoundary(
+ nNextWordBoundary = rBreakIterator.getWordBoundary(
rTxt, i + 1, rLocale, css::i18n::WordType::ANY_WORD, true);
}
if (i == nNextSentenceBreak)
{
mpMetaFile->AddAction(
new MetaCommentAction(aCommentStringC, i - nTextPosition));
- nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
+ nNextSentenceBreak = rBreakIterator.endOfSentence(rTxt, i + 1, rLocale);
}
}
}
@@ -1510,9 +1700,11 @@ void VclMetafileProcessor2D::processPolygonHairlinePrimitive2D(
basegfx::B2DPolygon aLeft, aRight;
splitLinePolygon(rBasePolygon, aLeft, aRight);
rtl::Reference<primitive2d::PolygonHairlinePrimitive2D> xPLeft(
- new primitive2d::PolygonHairlinePrimitive2D(aLeft, rHairlinePrimitive.getBColor()));
+ new primitive2d::PolygonHairlinePrimitive2D(std::move(aLeft),
+ rHairlinePrimitive.getBColor()));
rtl::Reference<primitive2d::PolygonHairlinePrimitive2D> xPRight(
- new primitive2d::PolygonHairlinePrimitive2D(aRight, rHairlinePrimitive.getBColor()));
+ new primitive2d::PolygonHairlinePrimitive2D(std::move(aRight),
+ rHairlinePrimitive.getBColor()));
processBasePrimitive2D(*xPLeft);
processBasePrimitive2D(*xPRight);
@@ -1560,10 +1752,12 @@ void VclMetafileProcessor2D::processPolygonStrokePrimitive2D(
basegfx::B2DPolygon aLeft, aRight;
splitLinePolygon(rBasePolygon, aLeft, aRight);
rtl::Reference<primitive2d::PolygonStrokePrimitive2D> xPLeft(
- new primitive2d::PolygonStrokePrimitive2D(aLeft, rStrokePrimitive.getLineAttribute(),
+ new primitive2d::PolygonStrokePrimitive2D(std::move(aLeft),
+ rStrokePrimitive.getLineAttribute(),
rStrokePrimitive.getStrokeAttribute()));
rtl::Reference<primitive2d::PolygonStrokePrimitive2D> xPRight(
- new primitive2d::PolygonStrokePrimitive2D(aRight, rStrokePrimitive.getLineAttribute(),
+ new primitive2d::PolygonStrokePrimitive2D(std::move(aRight),
+ rStrokePrimitive.getLineAttribute(),
rStrokePrimitive.getStrokeAttribute()));
processBasePrimitive2D(*xPLeft);
@@ -1571,7 +1765,8 @@ void VclMetafileProcessor2D::processPolygonStrokePrimitive2D(
}
else
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
+ auto popIt
+ = mpOutputDevice->ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
// support SvtGraphicStroke MetaCommentAction
std::unique_ptr<SvtGraphicStroke> pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
@@ -1582,34 +1777,90 @@ void VclMetafileProcessor2D::processPolygonStrokePrimitive2D(
const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
// create MetaPolyLineActions, but without LineStyle::Dash
- if (basegfx::fTools::more(rLine.getWidth(), 0.0))
+ if (rLine.getWidth() > 0.0)
{
const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
- basegfx::B2DPolyPolygon aHairLinePolyPolygon;
-
- if (0.0 == rStroke.getFullDotDashLen())
- {
- aHairLinePolyPolygon.append(rBasePolygon);
- }
- else
- {
- basegfx::utils::applyLineDashing(rBasePolygon, rStroke.getDotDashArray(),
- &aHairLinePolyPolygon, nullptr,
- rStroke.getFullDotDashLen());
- }
const basegfx::BColor aHairlineColor(
maBColorModifierStack.getModifiedColor(rLine.getColor()));
mpOutputDevice->SetLineColor(Color(aHairlineColor));
mpOutputDevice->SetFillColor();
- aHairLinePolyPolygon.transform(maCurrentTransformation);
// use the transformed line width
LineInfo aLineInfo(LineStyle::Solid,
- basegfx::fround(getTransformedLineWidth(rLine.getWidth())));
+ std::round(getTransformedLineWidth(rLine.getWidth())));
aLineInfo.SetLineJoin(rLine.getLineJoin());
aLineInfo.SetLineCap(rLine.getLineCap());
+ basegfx::B2DPolyPolygon aHairLinePolyPolygon;
+ if (0.0 == rStroke.getFullDotDashLen())
+ {
+ aHairLinePolyPolygon.append(rBasePolygon);
+ }
+ else
+ {
+ bool done = false;
+ const std::vector<double>& array = rStroke.getDotDashArray();
+ // The dotdash array should generally have the form
+ // (<dashLen> <distance>)+ (<dotLen> <distance>)*
+ // (where (,),+ and * have their regex meaning).
+ // Find out what the lengths and their counts are.
+ if (!array.empty() && array.size() % 2 == 0)
+ {
+ double dashLen = array[0];
+ double distance = array[1];
+ int dashCount = 1;
+ double dotLen = 0;
+ int dotCount = 0;
+ size_t pos = 2;
+ while (pos + 2 <= array.size())
+ {
+ if (array[pos] != dashLen || array[pos + 1] != distance)
+ break;
+ ++dashCount;
+ pos += 2;
+ }
+ if (pos + 2 <= array.size() && array[pos + 1] == distance)
+ {
+ dotLen = array[pos];
+ ++dotCount;
+ pos += 2;
+ while (pos + 2 <= array.size())
+ {
+ if (array[pos] != dotLen || array[pos + 1] != distance)
+ break;
+ ++dotCount;
+ pos += 2;
+ }
+ }
+ if (array.size() == pos)
+ {
+ aHairLinePolyPolygon.append(rBasePolygon);
+ // This will be used by setupStrokeAttributes() in cppcanvas.
+ aLineInfo.SetStyle(LineStyle::Dash);
+ aLineInfo.SetDashCount(dashCount);
+ aLineInfo.SetDashLen(getTransformedLineWidth(dashLen));
+ aLineInfo.SetDistance(getTransformedLineWidth(distance));
+ if (dotCount != 0)
+ {
+ aLineInfo.SetDotCount(dotCount);
+ aLineInfo.SetDotLen(getTransformedLineWidth(dotLen));
+ }
+ done = true;
+ }
+ }
+ if (!done)
+ {
+ // LineInfo can hold only limited info about dashing, apply dashing manually
+ // if LineInfo cannot describe it. That should not happen though.
+ SAL_WARN("drawinglayer", "dotdash array cannot be converted to LineInfo");
+ basegfx::utils::applyLineDashing(rBasePolygon, rStroke.getDotDashArray(),
+ &aHairLinePolyPolygon, nullptr,
+ rStroke.getFullDotDashLen());
+ }
+ }
+ aHairLinePolyPolygon.transform(maCurrentTransformation);
+
for (sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
{
const basegfx::B2DPolygon& aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
@@ -1628,8 +1879,6 @@ void VclMetafileProcessor2D::processPolygonStrokePrimitive2D(
}
impEndSvtGraphicStroke(pSvtGraphicStroke.get());
-
- mpOutputDevice->Pop();
}
}
@@ -1707,6 +1956,16 @@ void VclMetafileProcessor2D::processPolyPolygonGraphicPrimitive2D(
// need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
+ if (!rBitmapCandidate.getDefinitionRange().isEmpty()
+ && aLocalPolyPolygon.getB2DRange() != rBitmapCandidate.getDefinitionRange())
+ {
+ // The range which defines the bitmap fill is defined and different from the
+ // range of the defining geometry (e.g. used for FillStyle UseSlideBackground).
+ // This cannot be done calling vcl, thus use decomposition here directly
+ process(rBitmapCandidate);
+ return;
+ }
+
fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
std::unique_ptr<SvtGraphicFill> pSvtGraphicFill;
@@ -1750,10 +2009,11 @@ void VclMetafileProcessor2D::processPolyPolygonGraphicPrimitive2D(
aTransform.matrix[5] = aTransformPosition.getY();
pSvtGraphicFill.reset(new SvtGraphicFill(
- getFillPolyPolygon(aLocalPolyPolygon), Color(), 0.0, SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillTexture, aTransform, rFillGraphicAttribute.getTiling(),
- SvtGraphicFill::hatchSingle, Color(), SvtGraphicFill::GradientType::Linear, Color(),
- Color(), 0, rFillGraphicAttribute.getGraphic()));
+ getFillPolyPolygon(aLocalPolyPolygon), Color(), rBitmapCandidate.getTransparency(),
+ SvtGraphicFill::fillEvenOdd, SvtGraphicFill::fillTexture, aTransform,
+ rFillGraphicAttribute.getTiling(), SvtGraphicFill::hatchSingle, Color(),
+ SvtGraphicFill::GradientType::Linear, Color(), Color(), 0,
+ rFillGraphicAttribute.getGraphic()));
}
// Do use decomposition; encapsulate with SvtGraphicFill
@@ -1857,8 +2117,8 @@ void VclMetafileProcessor2D::processPolyPolygonHatchPrimitive2D(
aToolsPolyPolygon,
Hatch(aHatchStyle,
Color(maBColorModifierStack.getModifiedColor(rFillHatchAttribute.getColor())),
- basegfx::fround(rFillHatchAttribute.getDistance()),
- basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
+ basegfx::fround<tools::Long>(rFillHatchAttribute.getDistance()),
+ Degree10(basegfx::fround(basegfx::rad2deg<10>(rFillHatchAttribute.getAngle())))));
impEndSvtGraphicFill(pSvtGraphicFill.get());
}
@@ -1866,42 +2126,164 @@ void VclMetafileProcessor2D::processPolyPolygonHatchPrimitive2D(
void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D(
const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate)
{
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
-
- maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
-
- if (!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
- {
- // #i121185# When rotation or shear is used, a VCL Gradient cannot be used directly.
- // This is because VCL Gradient mechanism does *not* support to rotate the gradient
- // with objects and this case is not expressible in a Metafile (and cannot be added
- // since the FileFormats used, e.g. *.wmf, do not support it either).
- // Such cases happen when a graphic object uses a Metafile as graphic information or
- // a fill style definition uses a Metafile. In this cases the graphic content is
- // rotated with the graphic or filled object; this is not supported by the target
- // format of this conversion renderer - Metafiles.
- // To solve this, not a Gradient is written, but the decomposition of this object
- // is written to the Metafile. This is the PolyPolygons building the gradient fill.
- // These will need more space and time, but the result will be as if the Gradient
- // was rotated with the object.
- // This mechanism is used by all exporters still not using Primitives (e.g. Print,
- // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
- // transfers. One more reason to *change* these to primitives.
- // BTW: One more example how useful the principles of primitives are; the decomposition
- // is by definition a simpler, maybe more expensive representation of the same content.
- process(rGradientCandidate);
+ // SDPR: Caution: metafile export cannot handle added TransparencyGradient
+ if (rGradientCandidate.hasAlphaGradient() || rGradientCandidate.hasTransparency())
+ {
+ // if it has alpha added directly we need to use the decomposition.
+ // unfortunately VclMetafileProcessor2D does *not* support the
+ // primitive created in the decomposition, the FillGradientPrimitive2D.
+ // at the same time extra stuff like adding gradient info to the
+ // metafile (BGRAD_SEQ_BEGIN) only is done HERE. To solve that and to
+ // not add PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D now, create a temporary
+ // decomposition to again get a PolyPolygonGradientPrimitive2D, but
+ // *without* directly added alpha
+ primitive2d::Primitive2DReference aRetval(new primitive2d::PolyPolygonGradientPrimitive2D(
+ rGradientCandidate.getB2DPolyPolygon(), rGradientCandidate.getDefinitionRange(),
+ rGradientCandidate.getFillGradient()));
+
+ if (rGradientCandidate.hasAlphaGradient())
+ {
+ const basegfx::B2DRange aPolyPolygonRange(
+ rGradientCandidate.getB2DPolyPolygon().getB2DRange());
+ primitive2d::Primitive2DContainer aAlpha{ new primitive2d::FillGradientPrimitive2D(
+ aPolyPolygonRange, rGradientCandidate.getDefinitionRange(),
+ rGradientCandidate.getAlphaGradient()) };
+
+ aRetval = new primitive2d::TransparencePrimitive2D(
+ primitive2d::Primitive2DContainer{ aRetval }, std::move(aAlpha));
+ }
+
+ if (rGradientCandidate.hasTransparency())
+ {
+ aRetval = new primitive2d::UnifiedTransparencePrimitive2D(
+ primitive2d::Primitive2DContainer{ aRetval }, rGradientCandidate.getTransparency());
+ }
+
+ process(primitive2d::Primitive2DContainer{ aRetval });
return;
}
+ bool useDecompose(false);
+
+ if (!useDecompose)
+ {
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+
+ maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // detect if transformation is rotated, sheared or mirrored in X and/or Y
+ if (!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX)
+ || aScale.getX() < 0.0 || aScale.getY() < 0.0)
+ {
+ // #i121185# When rotation or shear is used, a VCL Gradient cannot be used directly.
+ // This is because VCL Gradient mechanism does *not* support to rotate the gradient
+ // with objects and this case is not expressible in a Metafile (and cannot be added
+ // since the FileFormats used, e.g. *.wmf, do not support it either).
+ // Such cases happen when a graphic object uses a Metafile as graphic information or
+ // a fill style definition uses a Metafile. In this cases the graphic content is
+ // rotated with the graphic or filled object; this is not supported by the target
+ // format of this conversion renderer - Metafiles.
+ // To solve this, not a Gradient is written, but the decomposition of this object
+ // is written to the Metafile. This is the PolyPolygons building the gradient fill.
+ // These will need more space and time, but the result will be as if the Gradient
+ // was rotated with the object.
+ // This mechanism is used by all exporters still not using Primitives (e.g. Print,
+ // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
+ // transfers. One more reason to *change* these to primitives.
+ // BTW: One more example how useful the principles of primitives are; the decomposition
+ // is by definition a simpler, maybe more expensive representation of the same content.
+ useDecompose = true;
+ }
+ }
+
+ // tdf#150551 for PDF export, use the decomposition for better gradient visualization
+ if (!useDecompose && nullptr != mpPDFExtOutDevData)
+ {
+ useDecompose = true;
+ }
+
basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
- if (aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
+ if (!useDecompose && aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
{
// the range which defines the gradient is different from the range of the
// geometry (used for writer frames). This cannot be done calling vcl, thus use
// decomposition here
+ useDecompose = true;
+ }
+
+ const attribute::FillGradientAttribute& rFillGradient(rGradientCandidate.getFillGradient());
+
+ if (!useDecompose && rFillGradient.cannotBeHandledByVCL())
+ {
+ // MCGR: if we have ColorStops, do not try to fallback to old VCL-Gradient,
+ // that will *not* be capable of representing this properly. Use the
+ // correct decomposition instead
+ useDecompose = true;
+ }
+
+ if (useDecompose)
+ {
+ GDIMetaFile* pMetaFile(mpOutputDevice->GetConnectMetaFile());
+
+ // tdf#155479 only add 'BGRAD_SEQ_BEGIN' if SVG export
+ // SDPR: Caution: metafile export cannot handle added TransparencyGradient
+ if (nullptr != pMetaFile && pMetaFile->getSVG() && !rGradientCandidate.hasAlphaGradient())
+ {
+ // write the color stops to a memory stream
+ SvMemoryStream aMemStm;
+ VersionCompatWrite aCompat(aMemStm, 1);
+
+ const basegfx::BColorStops& rColorStops(rFillGradient.getColorStops());
+ sal_uInt16 nTmp(sal::static_int_cast<sal_uInt16>(rColorStops.size()));
+ aMemStm.WriteUInt16(nTmp);
+
+ for (auto const& rCand : rColorStops)
+ {
+ aMemStm.WriteDouble(rCand.getStopOffset());
+ const basegfx::BColor& rColor(rCand.getStopColor());
+ aMemStm.WriteDouble(rColor.getRed());
+ aMemStm.WriteDouble(rColor.getGreen());
+ aMemStm.WriteDouble(rColor.getBlue());
+ }
+
+ // Add a new MetaCommentAction section of type 'BGRAD_SEQ_BEGIN/BGRAD_SEQ_END'
+ // that is capable of holding the new color step information, plus the
+ // already used MetaActionType::GRADIENTEX.
+ // With that combination only places that know about that new BGRAD_SEQ_* will
+ // use it while all others will work on the created decomposition of the
+ // gradient for compatibility - which are single-color filled polygons
+ pMetaFile->AddAction(new MetaCommentAction(
+ "BGRAD_SEQ_BEGIN"_ostr, 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ aMemStm.TellEnd()));
+
+ // create MetaActionType::GRADIENTEX
+ // NOTE: with the new BGRAD_SEQ_* we could use basegfx::B2DPolygon and
+ // basegfx::BGradient here directly, but may have to add streaming OPs
+ // for these, so for now just go with what we use all the time. The real
+ // work for improvement should not go to this 'compromise' but to a real
+ // re-work of the SVG export (or/and others) to no longer work on metafiles
+ // but on UNO API or primitives (whatever fits best to the specific export)
+ fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
+ Gradient aVCLGradient;
+ impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rFillGradient, false);
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ const tools::PolyPolygon aToolsPolyPolygon(
+ getFillPolyPolygon(basegfx::utils::adaptiveSubdivideByAngle(aLocalPolyPolygon)));
+ mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
+ }
+
+ // use decompose to draw, will create PolyPolygon ColorFill actions
process(rGradientCandidate);
+
+ // tdf#155479 only add 'BGRAD_SEQ_END' if SVG export
+ if (nullptr != pMetaFile && pMetaFile->getSVG())
+ {
+ // close the BGRAD_SEQ_* actions range
+ pMetaFile->AddAction(new MetaCommentAction("BGRAD_SEQ_END"_ostr));
+ }
+
return;
}
@@ -1913,8 +2295,7 @@ void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D(
// it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
// re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
Gradient aVCLGradient;
- impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(),
- false);
+ impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rFillGradient, false);
aLocalPolyPolygon.transform(maCurrentTransformation);
// #i82145# ATM VCL printing of gradients using curved shapes does not work,
@@ -1935,16 +2316,16 @@ void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D(
switch (aVCLGradient.GetStyle())
{
- default: // GradientStyle::Linear:
- case GradientStyle::Axial:
+ default: // css::awt::GradientStyle_LINEAR:
+ case css::awt::GradientStyle_AXIAL:
eGrad = SvtGraphicFill::GradientType::Linear;
break;
- case GradientStyle::Radial:
- case GradientStyle::Elliptical:
+ case css::awt::GradientStyle_RADIAL:
+ case css::awt::GradientStyle_ELLIPTICAL:
eGrad = SvtGraphicFill::GradientType::Radial;
break;
- case GradientStyle::Square:
- case GradientStyle::Rect:
+ case css::awt::GradientStyle_SQUARE:
+ case css::awt::GradientStyle_RECT:
eGrad = SvtGraphicFill::GradientType::Rectangular;
break;
}
@@ -1965,7 +2346,7 @@ void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D(
void VclMetafileProcessor2D::processPolyPolygonColorPrimitive2D(
const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate)
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
// #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
@@ -1981,8 +2362,6 @@ void VclMetafileProcessor2D::processPolyPolygonColorPrimitive2D(
mpOutputDevice->SetLineColor();
mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
-
- mpOutputDevice->Pop();
}
void VclMetafileProcessor2D::processMaskPrimitive2D(
@@ -1996,6 +2375,12 @@ void VclMetafileProcessor2D::processMaskPrimitive2D(
if (aMask.count())
{
+ // A clipping path is a set of closed vector path that may consist of an arbitrary number
+ // of straight and curved segments. The region(s) enclosed by the path define(s) the visible area,
+ // i.e. after applying a clipping path, only those portions of the subsequently drawn graphics that
+ // fall inside the enclosed area are visible, everything else is cut away.
+ if (!aMask.isClosed())
+ aMask.setClosed(true);
// prepare new mask polygon and rescue current one
aMask.transform(maCurrentTransformation);
const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
@@ -2012,7 +2397,7 @@ void VclMetafileProcessor2D::processMaskPrimitive2D(
else
{
// use mask directly
- maClipPolyPolygon = aMask;
+ maClipPolyPolygon = std::move(aMask);
}
if (maClipPolyPolygon.count())
@@ -2020,16 +2405,13 @@ void VclMetafileProcessor2D::processMaskPrimitive2D(
// set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
// Removed subdivision and fixed in vcl::Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
// the ClipRegion is built from the Polygon. An AdaptiveSubdivide on the source polygon was missing there
- mpOutputDevice->Push(PushFlags::CLIPREGION);
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::CLIPREGION);
mpOutputDevice->SetClipRegion(vcl::Region(maClipPolyPolygon));
// recursively paint content
// #i121267# Only need to process sub-content when clip polygon is *not* empty.
// If it is empty, the clip is empty and there can be nothing inside.
process(rMaskCandidate.getChildren());
-
- // restore VCL clip region
- mpOutputDevice->Pop();
}
// restore to rescued clip polygon
@@ -2045,7 +2427,7 @@ void VclMetafileProcessor2D::processMaskPrimitive2D(
void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(
const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
// for metafile: Need to examine what the pure vcl version is doing here actually
// - uses DrawTransparent with metafile for content and a gradient
// - uses DrawTransparent for single PolyPolygons directly. Can be detected by
@@ -2069,7 +2451,7 @@ void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(
if (!bForceToMetafile && 1 == rContent.size())
{
- const primitive2d::Primitive2DReference xReference(rContent[0]);
+ const primitive2d::Primitive2DReference& xReference(rContent.front());
pPoPoColor = dynamic_cast<const primitive2d::PolyPolygonColorPrimitive2D*>(
xReference.get());
}
@@ -2113,6 +2495,11 @@ void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(
// various content, create content-metafile
GDIMetaFile aContentMetafile;
+
+ // tdf#155479 always forward propagate SVG flag for sub-content,
+ // it may contain cannotBeHandledByVCL gradients or transparencyGradients
+ aContentMetafile.setSVG(mpOutputDevice->GetConnectMetaFile()->getSVG());
+
const tools::Rectangle aPrimitiveRectangle(
impDumpToMetaFile(rContent, aContentMetafile));
@@ -2126,10 +2513,10 @@ void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(
basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0)));
const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
- aVCLGradient.SetStyle(GradientStyle::Linear);
+ aVCLGradient.SetStyle(css::awt::GradientStyle_LINEAR);
aVCLGradient.SetStartColor(aTransColor);
aVCLGradient.SetEndColor(aTransColor);
- aVCLGradient.SetAngle(0);
+ aVCLGradient.SetAngle(0_deg10);
aVCLGradient.SetBorder(0);
aVCLGradient.SetOfsX(0);
aVCLGradient.SetOfsY(0);
@@ -2143,8 +2530,6 @@ void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(
}
}
}
-
- mpOutputDevice->Pop();
}
void VclMetafileProcessor2D::processTransparencePrimitive2D(
@@ -2156,29 +2541,82 @@ void VclMetafileProcessor2D::processTransparencePrimitive2D(
// FillGradientPrimitive2D and reconstruct the gradient.
// If that detection goes wrong, I have to create a transparence-blended bitmap. Eventually
// do that in stripes, else RenderTransparencePrimitive2D may just be used
- const primitive2d::Primitive2DContainer& rContent = rTransparenceCandidate.getChildren();
- const primitive2d::Primitive2DContainer& rTransparence
- = rTransparenceCandidate.getTransparence();
+ const primitive2d::Primitive2DContainer& rContent(rTransparenceCandidate.getChildren());
+ const primitive2d::Primitive2DContainer& rTransparence(
+ rTransparenceCandidate.getTransparence());
if (rContent.empty() || rTransparence.empty())
return;
// try to identify a single FillGradientPrimitive2D in the
- // transparence part of the primitive
- const primitive2d::FillGradientPrimitive2D* pFiGradient = nullptr;
+ // transparence part of the primitive. The hope is to handle
+ // the more specific case in a better way than the general
+ // TransparencePrimitive2D which has strongly separated
+ // definitions for transparency and content, both completely
+ // free definable by primitives
+ const primitive2d::FillGradientPrimitive2D* pFiGradient(nullptr);
static bool bForceToBigTransparentVDev(false); // loplugin:constvars:ignore
+ // check for single FillGradientPrimitive2D
if (!bForceToBigTransparentVDev && 1 == rTransparence.size())
{
- const primitive2d::Primitive2DReference xReference(rTransparence[0]);
- pFiGradient = dynamic_cast<const primitive2d::FillGradientPrimitive2D*>(xReference.get());
+ pFiGradient = dynamic_cast<const primitive2d::FillGradientPrimitive2D*>(
+ rTransparence.front().get());
+
+ // check also for correct ID to exclude derived implementations
+ if (pFiGradient
+ && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D != pFiGradient->getPrimitive2DID())
+ pFiGradient = nullptr;
}
- // Check also for correct ID to exclude derived implementations
- if (pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
+ // tdf#155479 preps for holding extra-MCGR infos
+ bool bSVGTransparencyColorStops(false);
+ basegfx::BColorStops aSVGTransparencyColorStops;
+
+ // MCGR: tdf#155437 If we have identified a transparency gradient,
+ // check if VCL is able to handle it at all
+ if (nullptr != pFiGradient && pFiGradient->getFillGradient().cannotBeHandledByVCL())
{
- // various content, create content-metafile
+ // If not, reset the pointer and do not make use of this special case.
+ // Adding a gradient in incomplete state that can not be handled by vcl
+ // makes no sense and will knowingly lead to errors, especially with
+ // MCGR extended possibilities. I checked what happens with the
+ // MetaFloatTransparentAction added by OutputDevice::DrawTransparent, but
+ // in most cases it gets converted to bitmap or even ignored, see e.g.
+ // - vcl/source/gdi/pdfwriter_impl2.cxx for PDF export
+ // - vcl/source/filter/wmf/wmfwr.cxx -> does ignore TransparenceGradient completely
+ // - vcl/source/filter/wmf/emfwr.cxx -> same
+ // - vcl/source/filter/eps/eps.cxx -> same
+ // NOTE: Theoretically it would be possible to make the new extended Gradient data
+ // available in metafiles, with the known limitations (not backward comp, all
+ // places using it would need adaption, ...), but combined with knowing that nearly
+ // all usages ignore or render it locally anyways makes that a non-option.
+
+ // tdf#155479 Yepp, as already mentioned above we need to add
+ // some MCGR infos in case of SVG export, prepare that here
+ if (mpOutputDevice->GetConnectMetaFile()->getSVG())
+ {
+ // for SVG, do not use decompose & prep extra data
+ bSVGTransparencyColorStops = true;
+ aSVGTransparencyColorStops = pFiGradient->getFillGradient().getColorStops();
+ }
+ else
+ {
+ // use decomposition
+ pFiGradient = nullptr;
+ }
+ }
+
+ if (nullptr != pFiGradient)
+ {
+ // this combination of Gradient can be expressed/handled by
+ // vcl/metafile, so add it directly. various content, create content-metafile
GDIMetaFile aContentMetafile;
+
+ // tdf#155479 always forward propagate SVG flag for sub-content,
+ // it may contain cannotBeHandledByVCL gradients or transparencyGradients
+ aContentMetafile.setSVG(mpOutputDevice->GetConnectMetaFile()->getSVG());
+
const tools::Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
// re-create a VCL-gradient from FillGradientPrimitive2D
@@ -2186,127 +2624,193 @@ void VclMetafileProcessor2D::processTransparencePrimitive2D(
impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(),
true);
- // render it to VCL
- mpOutputDevice->DrawTransparent(aContentMetafile, aPrimitiveRectangle.TopLeft(),
- aPrimitiveRectangle.GetSize(), aVCLGradient);
- }
- else
- {
- // sub-transparence group. Draw to VDev first.
- // this may get refined to tiling when resolution is too big here
-
- // need to avoid switching off MapMode stuff here; maybe need another
- // tooling class, cannot just do the same as with the pixel renderer.
- // Need to experiment...
-
- // Okay, basic implementation finished and tested. The DPI stuff was hard
- // and not easy to find out that it's needed.
- // Since this will not yet happen normally (as long as no one constructs
- // transparence primitives with non-trivial transparence content) i will for now not
- // refine to tiling here.
-
- basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D()));
- aViewRange.transform(maCurrentTransformation);
- const tools::Rectangle aRectLogic(static_cast<sal_Int32>(floor(aViewRange.getMinX())),
- static_cast<sal_Int32>(floor(aViewRange.getMinY())),
- static_cast<sal_Int32>(ceil(aViewRange.getMaxX())),
- static_cast<sal_Int32>(ceil(aViewRange.getMaxY())));
- const tools::Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
- Size aSizePixel(aRectPixel.GetSize());
- const Point aEmptyPoint;
- ScopedVclPtrInstance<VirtualDevice> aBufferDevice;
- const sal_uInt32 nMaxQuadratPixels(500000);
- const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight());
- double fReduceFactor(1.0);
-
- if (nViewVisibleArea > nMaxQuadratPixels)
- {
- // reduce render size
- fReduceFactor = sqrt(double(nMaxQuadratPixels) / static_cast<double>(nViewVisibleArea));
- aSizePixel = Size(
- basegfx::fround(static_cast<double>(aSizePixel.getWidth()) * fReduceFactor),
- basegfx::fround(static_cast<double>(aSizePixel.getHeight()) * fReduceFactor));
- }
-
- if (aBufferDevice->SetOutputSizePixel(aSizePixel))
- {
- // create and set MapModes for target devices
- MapMode aNewMapMode(mpOutputDevice->GetMapMode());
- aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
- aBufferDevice->SetMapMode(aNewMapMode);
-
- // prepare view transformation for target renderers
- // ATTENTION! Need to apply another scaling because of the potential DPI differences
- // between Printer and VDev (mpOutputDevice and aBufferDevice here).
- // To get the DPI, LogicToPixel from (1,1) from MapUnit::MapInch needs to be used.
- basegfx::B2DHomMatrix aViewTransform(aBufferDevice->GetViewTransformation());
- const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const Size aDPINew(aBufferDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const double fDPIXChange(static_cast<double>(aDPIOld.getWidth())
- / static_cast<double>(aDPINew.getWidth()));
- const double fDPIYChange(static_cast<double>(aDPIOld.getHeight())
- / static_cast<double>(aDPINew.getHeight()));
-
- if (!basegfx::fTools::equal(fDPIXChange, 1.0)
- || !basegfx::fTools::equal(fDPIYChange, 1.0))
- {
- aViewTransform.scale(fDPIXChange, fDPIYChange);
- }
-
- // also take scaling from Size reduction into account
- if (!basegfx::fTools::equal(fReduceFactor, 1.0))
- {
- aViewTransform.scale(fReduceFactor, fReduceFactor);
- }
-
- // create view information and pixel renderer. Reuse known ViewInformation
- // except new transformation and range
- const geometry::ViewInformation2D aViewInfo(
- getViewInformation2D().getObjectTransformation(), aViewTransform, aViewRange,
- getViewInformation2D().getVisualizedPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
-
- VclPixelProcessor2D aBufferProcessor(aViewInfo, *aBufferDevice);
-
- // draw content using pixel renderer
- aBufferProcessor.process(rContent);
- const Bitmap aBmContent(aBufferDevice->GetBitmap(aEmptyPoint, aSizePixel));
-
- // draw transparence using pixel renderer
- aBufferDevice->Erase();
- aBufferProcessor.process(rTransparence);
- const AlphaMask aBmAlpha(aBufferDevice->GetBitmap(aEmptyPoint, aSizePixel));
+ if (bSVGTransparencyColorStops)
+ {
+ // tdf#155479 create action directly & add extra
+ // MCGR infos to the metafile, do that by adding - ONLY in
+ // case of SVG export - to the MetaFileAction. For that
+ // reason, do what OutputDevice::DrawTransparent will do,
+ // but locally.
+ // NOTE: That would be good for this whole
+ // VclMetafileProcessor2D anyways to allow to get it
+ // completely independent from OutputDevice in the long run
+ GDIMetaFile* pMetaFile(mpOutputDevice->GetConnectMetaFile());
+ rtl::Reference<::MetaFloatTransparentAction> pAction(new MetaFloatTransparentAction(
+ aContentMetafile, aPrimitiveRectangle.TopLeft(), aPrimitiveRectangle.GetSize(),
+ std::move(aVCLGradient), std::move(aSVGTransparencyColorStops)));
- // paint
- mpOutputDevice->DrawBitmapEx(aRectLogic.TopLeft(), aRectLogic.GetSize(),
- BitmapEx(aBmContent, aBmAlpha));
+ pMetaFile->AddAction(pAction);
}
+ else
+ {
+ // render it to VCL (creates MetaFloatTransparentAction)
+ mpOutputDevice->DrawTransparent(aContentMetafile, aPrimitiveRectangle.TopLeft(),
+ aPrimitiveRectangle.GetSize(), aVCLGradient);
+ }
+ return;
}
+
+ // Here we need to create a correct replacement visualization for the
+ // TransparencePrimitive2D for the target metafile.
+ // I replaced the n'th iteration to convert-to-bitmap which was
+ // used here by using the existing tooling. The orig here was also producing
+ // transparency errors with test-file from tdf#155437 on the right part of the
+ // image.
+ // Just rely on existing tooling doing the right thing in one place, so also
+ // corrections/optimizations can be in one single place
+
+ // Start by getting logic range of content, transform object-to-world, then world-to-view
+ // to get to discrete values ('pixels'). Matrix multiplication is right-to-left (and not
+ // commutative)
+ basegfx::B2DRange aLogicRange(rTransparenceCandidate.getB2DRange(getViewInformation2D()));
+ aLogicRange.transform(mpOutputDevice->GetViewTransformation() * maCurrentTransformation);
+
+ // expand in discrete coordinates to next-bigger 'pixel' boundaries and remember
+ // created discrete range
+ aLogicRange.expand(
+ basegfx::B2DPoint(floor(aLogicRange.getMinX()), floor(aLogicRange.getMinY())));
+ aLogicRange.expand(basegfx::B2DPoint(ceil(aLogicRange.getMaxX()), ceil(aLogicRange.getMaxY())));
+ const basegfx::B2DRange aDiscreteRange(aLogicRange);
+
+ // transform back from discrete to world coordinates: this creates the
+ // pixel-boundaries extended logic range we need to cover all content
+ // reliably
+ aLogicRange.transform(mpOutputDevice->GetInverseViewTransformation());
+
+ // create transform embedding for renderer. Goal is to translate what we
+ // want to paint to top/left 0/0 and the calculated discrete size
+ basegfx::B2DHomMatrix aEmbedding(basegfx::utils::createTranslateB2DHomMatrix(
+ -aLogicRange.getMinX(), -aLogicRange.getMinY()));
+ const double fLogicWidth(
+ basegfx::fTools::equalZero(aLogicRange.getWidth()) ? 1.0 : aLogicRange.getWidth());
+ const double fLogicHeight(
+ basegfx::fTools::equalZero(aLogicRange.getHeight()) ? 1.0 : aLogicRange.getHeight());
+ aEmbedding.scale(aDiscreteRange.getWidth() / fLogicWidth,
+ aDiscreteRange.getHeight() / fLogicHeight);
+
+ // use the whole TransparencePrimitive2D as input (no need to create a new
+ // one with the sub-contents, these are ref-counted) and add to embedding
+ // primitive2d::TransparencePrimitive2D& rTrCand();
+ primitive2d::Primitive2DContainer xEmbedSeq{ &const_cast<primitive2d::TransparencePrimitive2D&>(
+ rTransparenceCandidate) };
+
+ // tdf#158743 when embedding, do not forget to 1st apply the evtl. used
+ // CurrentTransformation (right-to-left, apply that 1st)
+ xEmbedSeq = primitive2d::Primitive2DContainer{ new primitive2d::TransformPrimitive2D(
+ aEmbedding * maCurrentTransformation, std::move(xEmbedSeq)) };
+
+ // use empty ViewInformation & a useful MaximumQuadraticPixels
+ // limitation to paint the content
+ const auto aViewInformation2D(geometry::createViewInformation2D({}));
+ const sal_uInt32 nMaximumQuadraticPixels(500000);
+ const Bitmap aBitmap(convertToBitmap(
+ std::move(xEmbedSeq), aViewInformation2D, basegfx::fround(aDiscreteRange.getWidth()),
+ basegfx::fround(aDiscreteRange.getHeight()), nMaximumQuadraticPixels));
+
+ // add to target metafile (will create MetaFloatTransparentAction)
+ mpOutputDevice->DrawBitmapEx(Point(basegfx::fround<tools::Long>(aLogicRange.getMinX()),
+ basegfx::fround<tools::Long>(aLogicRange.getMinY())),
+ Size(basegfx::fround<tools::Long>(aLogicRange.getWidth()),
+ basegfx::fround<tools::Long>(aLogicRange.getHeight())),
+ aBitmap);
}
void VclMetafileProcessor2D::processStructureTagPrimitive2D(
const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate)
{
+ ::comphelper::ValueRestorationGuard const g(mpCurrentStructureTag, &rStructureTagCandidate);
+
// structured tag primitive
- const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
- bool bTagUsed((vcl::PDFWriter::NonStructElement != rTagElement));
+ const vcl::pdf::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
+ bool bTagUsed((vcl::pdf::StructElement::NonStructElement != rTagElement));
+ ::std::optional<sal_Int32> oAnchorParent;
+
+ if (!rStructureTagCandidate.isTaggedSdrObject())
+ {
+ bTagUsed = false;
+ }
if (mpPDFExtOutDevData && bTagUsed)
{
// foreground object: tag as regular structure element
if (!rStructureTagCandidate.isBackground())
{
- mpPDFExtOutDevData->BeginStructureElement(rTagElement);
+ if (rStructureTagCandidate.GetAnchorStructureElementKey() != nullptr)
+ {
+ sal_Int32 const id = mpPDFExtOutDevData->EnsureStructureElement(
+ rStructureTagCandidate.GetAnchorStructureElementKey());
+ oAnchorParent.emplace(mpPDFExtOutDevData->GetCurrentStructureElement());
+ mpPDFExtOutDevData->SetCurrentStructureElement(id);
+ }
+ mpPDFExtOutDevData->WrapBeginStructureElement(rTagElement);
+ switch (rTagElement)
+ {
+ case vcl::pdf::StructElement::H1:
+ case vcl::pdf::StructElement::H2:
+ case vcl::pdf::StructElement::H3:
+ case vcl::pdf::StructElement::H4:
+ case vcl::pdf::StructElement::H5:
+ case vcl::pdf::StructElement::H6:
+ case vcl::pdf::StructElement::Paragraph:
+ case vcl::pdf::StructElement::Heading:
+ case vcl::pdf::StructElement::Title:
+ case vcl::pdf::StructElement::Caption:
+ case vcl::pdf::StructElement::BlockQuote:
+ case vcl::pdf::StructElement::Table:
+ case vcl::pdf::StructElement::TableRow:
+ case vcl::pdf::StructElement::Formula:
+ case vcl::pdf::StructElement::Figure:
+ case vcl::pdf::StructElement::Annot:
+ mpPDFExtOutDevData->SetStructureAttribute(vcl::PDFWriter::Placement,
+ vcl::PDFWriter::Block);
+ break;
+ case vcl::pdf::StructElement::TableData:
+ case vcl::pdf::StructElement::TableHeader:
+ mpPDFExtOutDevData->SetStructureAttribute(vcl::PDFWriter::Placement,
+ vcl::PDFWriter::Inline);
+ break;
+ default:
+ break;
+ }
+ switch (rTagElement)
+ {
+ case vcl::pdf::StructElement::Table:
+ case vcl::pdf::StructElement::Formula:
+ case vcl::pdf::StructElement::Figure:
+ case vcl::pdf::StructElement::Annot:
+ {
+ auto const range(rStructureTagCandidate.getB2DRange(getViewInformation2D()));
+ tools::Rectangle const aLogicRect(
+ basegfx::fround<tools::Long>(range.getMinX()),
+ basegfx::fround<tools::Long>(range.getMinY()),
+ basegfx::fround<tools::Long>(range.getMaxX()),
+ basegfx::fround<tools::Long>(range.getMaxY()));
+ mpPDFExtOutDevData->SetStructureBoundingBox(aLogicRect);
+ break;
+ }
+ default:
+ break;
+ }
+ if (rTagElement == vcl::pdf::StructElement::Annot)
+ {
+ mpPDFExtOutDevData->SetStructureAnnotIds(rStructureTagCandidate.GetAnnotIds());
+ }
+ if (rTagElement == vcl::pdf::StructElement::TableHeader)
+ {
+ mpPDFExtOutDevData->SetStructureAttribute(vcl::PDFWriter::Scope,
+ vcl::PDFWriter::Column);
+ }
}
// background object
else
{
// background image: tag as artifact
if (rStructureTagCandidate.isImage())
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::NonStructElement);
+ mpPDFExtOutDevData->WrapBeginStructureElement(
+ vcl::pdf::StructElement::NonStructElement);
// any other background object: do not tag
else
- bTagUsed = false;
+ assert(false);
}
}
@@ -2317,97 +2821,10 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D(
{
// write end tag
mpPDFExtOutDevData->EndStructureElement();
- }
-}
-
-VclPtr<VirtualDevice>
-VclMetafileProcessor2D::CreateBufferDevice(const basegfx::B2DRange& rCandidateRange,
- geometry::ViewInformation2D& rViewInfo,
- tools::Rectangle& rRectLogic, Size& rSizePixel)
-{
- constexpr double fMaxQuadratPixels = 500000;
- basegfx::B2DRange aViewRange(rCandidateRange);
- aViewRange.transform(maCurrentTransformation);
- rRectLogic = tools::Rectangle(static_cast<long>(std::floor(aViewRange.getMinX())),
- static_cast<long>(std::floor(aViewRange.getMinY())),
- static_cast<long>(std::ceil(aViewRange.getMaxX())),
- static_cast<long>(std::ceil(aViewRange.getMaxY())));
- const tools::Rectangle aRectPixel(mpOutputDevice->LogicToPixel(rRectLogic));
- rSizePixel = aRectPixel.GetSize();
- const double fViewVisibleArea(rSizePixel.getWidth() * rSizePixel.getHeight());
- double fReduceFactor(1.0);
-
- if (fViewVisibleArea > fMaxQuadratPixels)
- {
- // reduce render size
- fReduceFactor = sqrt(fMaxQuadratPixels / fViewVisibleArea);
- rSizePixel = Size(basegfx::fround(rSizePixel.getWidth() * fReduceFactor),
- basegfx::fround(rSizePixel.getHeight() * fReduceFactor));
- }
-
- VclPtrInstance<VirtualDevice> pBufferDevice(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
- if (pBufferDevice->SetOutputSizePixel(rSizePixel))
- {
- // create and set MapModes for target devices
- MapMode aNewMapMode(mpOutputDevice->GetMapMode());
- aNewMapMode.SetOrigin(Point(-rRectLogic.Left(), -rRectLogic.Top()));
- pBufferDevice->SetMapMode(aNewMapMode);
-
- // prepare view transformation for target renderers
- // ATTENTION! Need to apply another scaling because of the potential DPI differences
- // between Printer and VDev (mpOutputDevice and pBufferDevice here).
- // To get the DPI, LogicToPixel from (1,1) from MapUnit::MapInch needs to be used.
- basegfx::B2DHomMatrix aViewTransform(pBufferDevice->GetViewTransformation());
- const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const Size aDPINew(pBufferDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const double fDPIXChange(static_cast<double>(aDPIOld.getWidth())
- / static_cast<double>(aDPINew.getWidth()));
- const double fDPIYChange(static_cast<double>(aDPIOld.getHeight())
- / static_cast<double>(aDPINew.getHeight()));
-
- if (!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
+ if (oAnchorParent)
{
- aViewTransform.scale(fDPIXChange, fDPIYChange);
+ mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
}
-
- // also take scaling from Size reduction into account
- if (!basegfx::fTools::equal(fReduceFactor, 1.0))
- {
- aViewTransform.scale(fReduceFactor, fReduceFactor);
- }
-
- // create view information and pixel renderer. Reuse known ViewInformation
- // except new transformation and range
- rViewInfo = geometry::ViewInformation2D(
- getViewInformation2D().getObjectTransformation(), aViewTransform, aViewRange,
- getViewInformation2D().getVisualizedPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- }
- else
- pBufferDevice.disposeAndClear();
-
- return std::move(pBufferDevice);
-}
-
-void VclMetafileProcessor2D::processPrimitive2DOnPixelProcessor(
- const primitive2d::BasePrimitive2D& rCandidate)
-{
- basegfx::B2DRange aViewRange(rCandidate.getB2DRange(getViewInformation2D()));
- geometry::ViewInformation2D aViewInfo;
- tools::Rectangle aRectLogic;
- Size aSizePixel;
- auto pBufferDevice(CreateBufferDevice(aViewRange, aViewInfo, aRectLogic, aSizePixel));
- if (pBufferDevice)
- {
- VclPixelProcessor2D aBufferProcessor(aViewInfo, *pBufferDevice, maBColorModifierStack);
-
- // draw content using pixel renderer
- primitive2d::Primitive2DReference aRef(
- &const_cast<primitive2d::BasePrimitive2D&>(rCandidate));
- aBufferProcessor.process({ aRef });
- const BitmapEx aBmContent(pBufferDevice->GetBitmapEx(Point(), aSizePixel));
- mpOutputDevice->DrawBitmapEx(aRectLogic.TopLeft(), aRectLogic.GetSize(), aBmContent);
- pBufferDevice.disposeAndClear();
}
}
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
index 67a79ca307cc..46d1cb2f1edf 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
@@ -25,6 +25,7 @@
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <vcl/pdfextoutdevdata.hxx> // vcl::PDFExtOutDevData support
+#include <tools/lazydelete.hxx>
class GDIMetaFile;
namespace tools
@@ -63,6 +64,8 @@ class PolyPolygonColorPrimitive2D;
class MaskPrimitive2D;
class UnifiedTransparencePrimitive2D;
class TransparencePrimitive2D;
+class ObjectInfoPrimitive2D;
+class FillGraphicPrimitive2D;
class StructureTagPrimitive2D;
}
@@ -105,7 +108,7 @@ private:
const attribute::LineStartEndAttribute* pEnd);
void impStartSvtGraphicStroke(SvtGraphicStroke const* pSvtGraphicStroke);
void impEndSvtGraphicStroke(SvtGraphicStroke const* pSvtGraphicStroke);
- void popStructureElement(vcl::PDFWriter::StructElement eElem);
+ void popStructureElement(vcl::pdf::StructElement eElem);
void popListItem();
void popList();
@@ -142,12 +145,12 @@ private:
const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate);
void processTransparencePrimitive2D(
const primitive2d::TransparencePrimitive2D& rTransparenceCandidate);
+ void
+ processObjectInfoPrimitive2D(const primitive2d::ObjectInfoPrimitive2D& rObjectInfoPrimitive2D);
+ void processFillGraphicPrimitive2D(
+ primitive2d::FillGraphicPrimitive2D const& rFillGraphicPrimitive2D);
void processStructureTagPrimitive2D(
const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate);
- void processPrimitive2DOnPixelProcessor(const primitive2d::BasePrimitive2D& rCandidate);
- VclPtr<VirtualDevice> CreateBufferDevice(const basegfx::B2DRange& rCandidateRange,
- geometry::ViewInformation2D& rViewInfo,
- tools::Rectangle& rRectLogic, Size& rSizePixel);
/// Convert the fWidth to the same space as its coordinates.
double getTransformedLineWidth(double fWidth) const;
@@ -171,13 +174,6 @@ private:
*/
double mfCurrentUnifiedTransparence;
- /* break iterator support
- made static so it only needs to be fetched once, even with many single
- constructed VclMetafileProcessor2D. It's still incarnated on demand,
- but exists for OOo runtime now by purpose.
- */
- static css::uno::Reference<css::i18n::XBreakIterator> mxBreakIterator;
-
/* vcl::PDFExtOutDevData support
For the first step, some extra actions at vcl::PDFExtOutDevData need to
be emulated with the VclMetafileProcessor2D. These are potentially temporarily
@@ -193,7 +189,9 @@ private:
bool mbInListItem;
bool mbBulletPresent;
- std::stack<vcl::PDFWriter::StructElement> maListElements;
+ std::stack<vcl::pdf::StructElement> maListElements;
+
+ primitive2d::StructureTagPrimitive2D const* mpCurrentStructureTag = nullptr;
protected:
/* the local processor for BasePrimitive2D-Implementation based primitives,
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index b91bf57c360d..90dd5c5fb420 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -19,29 +19,24 @@
#include "vclpixelprocessor2d.hxx"
#include "vclhelperbufferdevice.hxx"
-#include "helperwrongspellrenderer.hxx"
+#include <comphelper/lok.hxx>
#include <sal/log.hxx>
-#include <tools/stream.hxx>
-#include <vcl/BitmapBasicMorphologyFilter.hxx>
-#include <vcl/BitmapFilterStackBlur.hxx>
#include <vcl/outdev.hxx>
-#include <vcl/dibtools.hxx>
#include <vcl/hatch.hxx>
+#include <vcl/canvastools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/Tools.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
@@ -50,9 +45,9 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/glowprimitive2d.hxx>
-#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
@@ -60,49 +55,43 @@
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
-#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx>
#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
+#include <drawinglayer/primitive2d/patternfillprimitive2d.hxx>
#include <com/sun/star/awt/XWindow2.hpp>
#include <com/sun/star/awt/XControl.hpp>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/gradient.hxx>
+
using namespace com::sun::star;
namespace drawinglayer::processor2d
{
-struct VclPixelProcessor2D::Impl
-{
- AntialiasingFlags m_nOrigAntiAliasing;
-
- explicit Impl(OutputDevice const& rOutDev)
- : m_nOrigAntiAliasing(rOutDev.GetAntialiasing())
- {
- }
-};
-
VclPixelProcessor2D::VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation,
- OutputDevice& rOutDev,
- const basegfx::BColorModifierStack& rInitStack)
- : VclProcessor2D(rViewInformation, rOutDev, rInitStack)
- , m_pImpl(new Impl(rOutDev))
+ OutputDevice& rOutDev)
+ : VclProcessor2D(rViewInformation, rOutDev)
+ , m_nOrigAntiAliasing(rOutDev.GetAntialiasing())
+ , m_bRenderSimpleTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get())
+ , m_bRenderDecoratedTextDirect(
+ officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
{
// prepare maCurrentTransformation matrix with viewTransformation to target directly to pixels
maCurrentTransformation = rViewInformation.getObjectToViewTransformation();
// prepare output directly to pixels
- mpOutputDevice->Push(PushFlags::MAPMODE);
+ mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
mpOutputDevice->SetMapMode();
// react on AntiAliasing settings
- if (getOptionsDrawinglayer().IsAntiAliasing())
+ if (rViewInformation.getUseAntiAliasing())
{
- mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing
- | AntialiasingFlags::EnableB2dDraw);
+ mpOutputDevice->SetAntialiasing(m_nOrigAntiAliasing | AntialiasingFlags::Enable);
}
else
{
- mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing
- & ~AntialiasingFlags::EnableB2dDraw);
+ mpOutputDevice->SetAntialiasing(m_nOrigAntiAliasing & ~AntialiasingFlags::Enable);
}
}
@@ -112,7 +101,7 @@ VclPixelProcessor2D::~VclPixelProcessor2D()
mpOutputDevice->Pop();
// restore AntiAliasing
- mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing);
+ mpOutputDevice->SetAntialiasing(m_nOrigAntiAliasing);
}
void VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(
@@ -127,7 +116,11 @@ void VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(
const basegfx::BColor aPolygonColor(
maBColorModifierStack.getModifiedColor(rSource.getBColor()));
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ if (comphelper::LibreOfficeKit::isActive() && aPolygonColor.isAutomatic())
+ mpOutputDevice->SetFillColor(getViewInformation2D().getAutoColor());
+ else
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+
mpOutputDevice->SetLineColor();
mpOutputDevice->DrawTransparent(maCurrentTransformation, rSource.getB2DPolyPolygon(),
fTransparency);
@@ -194,20 +187,13 @@ bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(
rSource.getLineAttribute().getWidth(), fTransparency,
bStrokeAttributeNotUsed ? nullptr : &rSource.getStrokeAttribute().getDotDashArray(),
rSource.getLineAttribute().getLineJoin(), rSource.getLineAttribute().getLineCap(),
- rSource.getLineAttribute().getMiterMinimumAngle()
- /* false bBypassAACheck, default*/);
+ rSource.getLineAttribute().getMiterMinimumAngle());
}
void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
{
switch (rCandidate.getPrimitive2DID())
{
- case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D:
- {
- processWrongSpellPrimitive2D(
- static_cast<const primitive2d::WrongSpellPrimitive2D&>(rCandidate));
- break;
- }
case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
{
processTextSimplePortionPrimitive2D(
@@ -228,7 +214,7 @@ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv
}
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
{
- // direct draw of transformed BitmapEx primitive
+ // direct draw of transformed Bitmap primitive
processBitmapPrimitive2D(
static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
break;
@@ -343,17 +329,6 @@ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv
static_cast<const primitive2d::BackgroundColorPrimitive2D&>(rCandidate));
break;
}
- case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D:
- {
- // #i97628#
- // This primitive means that the content is derived from an active text edit,
- // not from model data itself. Some renderers need to suppress this content, e.g.
- // the pixel renderer used for displaying the edit view (like this one). It's
- // not to be suppressed by the MetaFile renderers, so that the edited text is
- // part of the MetaFile, e.g. needed for presentation previews.
- // Action: Ignore here, do nothing.
- break;
- }
case PRIMITIVE2D_ID_INVERTPRIMITIVE2D:
{
processInvertPrimitive2D(rCandidate);
@@ -382,22 +357,16 @@ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv
static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate));
break;
}
- case PRIMITIVE2D_ID_GLOWPRIMITIVE2D:
- {
- processGlowPrimitive2D(
- static_cast<const drawinglayer::primitive2d::GlowPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D:
+ case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D:
{
- processSoftEdgePrimitive2D(
- static_cast<const drawinglayer::primitive2d::SoftEdgePrimitive2D&>(rCandidate));
+ processFillGradientPrimitive2D(
+ static_cast<const drawinglayer::primitive2d::FillGradientPrimitive2D&>(rCandidate));
break;
}
- case PRIMITIVE2D_ID_SHADOWPRIMITIVE2D:
+ case PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D:
{
- processShadowPrimitive2D(
- static_cast<const drawinglayer::primitive2d::ShadowPrimitive2D&>(rCandidate));
+ processPatternFillPrimitive2D(
+ static_cast<const drawinglayer::primitive2d::PatternFillPrimitive2D&>(rCandidate));
break;
}
default:
@@ -411,17 +380,6 @@ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv
}
}
-void VclPixelProcessor2D::processWrongSpellPrimitive2D(
- const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive)
-{
- if (!renderWrongSpellPrimitive2D(rWrongSpellPrimitive, *mpOutputDevice, maCurrentTransformation,
- maBColorModifierStack))
- {
- // fallback to decomposition (MetaFile)
- process(rWrongSpellPrimitive);
- }
-}
-
void VclPixelProcessor2D::processTextSimplePortionPrimitive2D(
const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
{
@@ -429,7 +387,7 @@ void VclPixelProcessor2D::processTextSimplePortionPrimitive2D(
const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
adaptTextToFillDrawMode();
- if (getOptionsDrawinglayer().IsRenderSimpleTextDirect())
+ if (SAL_LIKELY(m_bRenderSimpleTextDirect))
{
RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
}
@@ -449,7 +407,7 @@ void VclPixelProcessor2D::processTextDecoratedPortionPrimitive2D(
const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
adaptTextToFillDrawMode();
- if (getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
+ if (SAL_LIKELY(m_bRenderDecoratedTextDirect))
{
RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
}
@@ -501,15 +459,31 @@ void VclPixelProcessor2D::processBitmapPrimitive2D(
void VclPixelProcessor2D::processPolyPolygonGradientPrimitive2D(
const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
{
- // direct draw of gradient
- const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
- basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
- basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ // no geometry, no need to render, done
if (!aLocalPolyPolygon.count())
return;
+ // *try* direct draw (AKA using old VCL stuff) to render gradient
+ const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
+
+ // MCGR: *many* - and not only GradientStops - cases cannot be handled by VCL
+ // so use decomposition
+ // NOTE: There may be even more reasons to detect, e.g. a ViewTransformation
+ // that uses shear/rotate/mirror (what VCL cannot handle at all), see
+ // other checks already in processFillGradientPrimitive2D
+ if (rGradient.cannotBeHandledByVCL())
+ {
+ process(rPolygonCandidate);
+ return;
+ }
+
+ basegfx::BColor aStartColor(
+ maBColorModifierStack.getModifiedColor(rGradient.getColorStops().front().getStopColor()));
+ basegfx::BColor aEndColor(
+ maBColorModifierStack.getModifiedColor(rGradient.getColorStops().back().getStopColor()));
+
if (aStartColor == aEndColor)
{
// no gradient at all, draw as polygon in AA and non-AA case
@@ -517,12 +491,11 @@ void VclPixelProcessor2D::processPolyPolygonGradientPrimitive2D(
mpOutputDevice->SetLineColor();
mpOutputDevice->SetFillColor(Color(aStartColor));
mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ return;
}
- else
- {
- // use the primitive decomposition of the metafile
- process(rPolygonCandidate);
- }
+
+ // use the primitive decomposition
+ process(rPolygonCandidate);
}
void VclPixelProcessor2D::processPolyPolygonColorPrimitive2D(
@@ -537,8 +510,8 @@ void VclPixelProcessor2D::processPolyPolygonColorPrimitive2D(
// when AA is on and this filled polygons are the result of stroked line geometry,
// draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
// Caution: This is needed in both cases (!)
- if (!(mnPolygonStrokePrimitive2D && getOptionsDrawinglayer().IsAntiAliasing()
- && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw)))
+ if (!(mnPolygonStrokePrimitive2D && getViewInformation2D().getUseAntiAliasing()
+ && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::Enable)))
return;
const basegfx::BColor aPolygonColor(
@@ -583,67 +556,60 @@ void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D(
if (1 == rContent.size())
{
- const primitive2d::Primitive2DReference xReference(rContent[0]);
- const primitive2d::BasePrimitive2D* pBasePrimitive
- = dynamic_cast<const primitive2d::BasePrimitive2D*>(xReference.get());
+ const primitive2d::BasePrimitive2D* pBasePrimitive = rContent.front().get();
- if (pBasePrimitive)
+ switch (pBasePrimitive->getPrimitive2DID())
{
- switch (pBasePrimitive->getPrimitive2DID())
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
{
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
- {
- // single transparent tools::PolyPolygon identified, use directly
- const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor
- = static_cast<const primitive2d::PolyPolygonColorPrimitive2D*>(
- pBasePrimitive);
- SAL_WARN_IF(!pPoPoColor, "drawinglayer",
- "OOps, PrimitiveID and PrimitiveType do not match (!)");
- bDrawTransparentUsed = true;
- tryDrawPolyPolygonColorPrimitive2DDirect(
- *pPoPoColor, rUniTransparenceCandidate.getTransparence());
- break;
- }
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
- {
- // single transparent PolygonHairlinePrimitive2D identified, use directly
- const primitive2d::PolygonHairlinePrimitive2D* pPoHair
- = static_cast<const primitive2d::PolygonHairlinePrimitive2D*>(
- pBasePrimitive);
- SAL_WARN_IF(!pPoHair, "drawinglayer",
- "OOps, PrimitiveID and PrimitiveType do not match (!)");
-
- // do no tallow by default - problem is that self-overlapping parts of this geometry will
- // not be in an all-same transparency but will already alpha-cover themselves with blending.
- // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
- // content to be uniformly transparent.
- // For hairline the effect is pretty minimal, but still not correct.
- bDrawTransparentUsed = false;
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
- {
- // single transparent PolygonStrokePrimitive2D identified, use directly
- const primitive2d::PolygonStrokePrimitive2D* pPoStroke
- = static_cast<const primitive2d::PolygonStrokePrimitive2D*>(
- pBasePrimitive);
- SAL_WARN_IF(!pPoStroke, "drawinglayer",
- "OOps, PrimitiveID and PrimitiveType do not match (!)");
-
- // do no tallow by default - problem is that self-overlapping parts of this geometry will
- // not be in an all-same transparency but will already alpha-cover themselves with blending.
- // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
- // content to be uniformly transparent.
- // To check, activate and draw a wide transparent self-crossing line/curve
- bDrawTransparentUsed = false;
- break;
- }
- default:
- SAL_INFO("drawinglayer",
- "default case for " << drawinglayer::primitive2d::idToString(
- rUniTransparenceCandidate.getPrimitive2DID()));
- break;
+ // single transparent tools::PolyPolygon identified, use directly
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor
+ = static_cast<const primitive2d::PolyPolygonColorPrimitive2D*>(
+ pBasePrimitive);
+ assert(pPoPoColor && "OOps, PrimitiveID and PrimitiveType do not match (!)");
+ bDrawTransparentUsed = true;
+ tryDrawPolyPolygonColorPrimitive2DDirect(
+ *pPoPoColor, rUniTransparenceCandidate.getTransparence());
+ break;
}
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
+ {
+ // single transparent PolygonHairlinePrimitive2D identified, use directly
+ const primitive2d::PolygonHairlinePrimitive2D* pPoHair
+ = static_cast<const primitive2d::PolygonHairlinePrimitive2D*>(
+ pBasePrimitive);
+ SAL_WARN_IF(!pPoHair, "drawinglayer",
+ "OOps, PrimitiveID and PrimitiveType do not match (!)");
+
+ // do no tallow by default - problem is that self-overlapping parts of this geometry will
+ // not be in an all-same transparency but will already alpha-cover themselves with blending.
+ // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
+ // content to be uniformly transparent.
+ // For hairline the effect is pretty minimal, but still not correct.
+ bDrawTransparentUsed = false;
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ // single transparent PolygonStrokePrimitive2D identified, use directly
+ const primitive2d::PolygonStrokePrimitive2D* pPoStroke
+ = static_cast<const primitive2d::PolygonStrokePrimitive2D*>(pBasePrimitive);
+ SAL_WARN_IF(!pPoStroke, "drawinglayer",
+ "OOps, PrimitiveID and PrimitiveType do not match (!)");
+
+ // do no tallow by default - problem is that self-overlapping parts of this geometry will
+ // not be in an all-same transparency but will already alpha-cover themselves with blending.
+ // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
+ // content to be uniformly transparent.
+ // To check, activate and draw a wide transparent self-crossing line/curve
+ bDrawTransparentUsed = false;
+ break;
+ }
+ default:
+ SAL_INFO("drawinglayer",
+ "default case for " << drawinglayer::primitive2d::idToString(
+ rUniTransparenceCandidate.getPrimitive2DID()));
+ break;
}
}
@@ -658,43 +624,63 @@ void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D(
void VclPixelProcessor2D::processControlPrimitive2D(
const primitive2d::ControlPrimitive2D& rControlPrimitive)
{
- // control primitive
- const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
+ // find out if the control is already visualized as a VCL-ChildWindow
+ bool bControlIsVisibleAsChildWindow(rControlPrimitive.isVisibleAsChildWindow());
+
+ // tdf#131281 The FormControls are not painted when using the Tiled Rendering for a simple
+ // reason: when e.g. bControlIsVisibleAsChildWindow is true. This is the case because the
+ // office is in non-layout mode (default for controls at startup). For the common office
+ // this means that there exists a real VCL-System-Window for the control, so it is *not*
+ // painted here due to being exactly obscured by that real Window (and creates danger of
+ // flickering, too).
+ // Tiled Rendering clients usually do *not* have real VCL-Windows for the controls, but
+ // exactly that would be needed on each client displaying the tiles (what would be hard
+ // to do but also would have advantages - the clients would have real controls in the
+ // shape of their target system which could be interacted with...). It is also what the
+ // office does.
+ // For now, fallback to just render these controls when Tiled Rendering is active to just
+ // have them displayed on all clients.
+ if (bControlIsVisibleAsChildWindow && comphelper::LibreOfficeKit::isActive())
+ {
+ // Do force paint when we are in Tiled Renderer and FormControl is 'visible'
+ bControlIsVisibleAsChildWindow = false;
+ }
+
+ if (bControlIsVisibleAsChildWindow)
+ {
+ // f the control is already visualized as a VCL-ChildWindow it
+ // does not need to be painted at all
+ return;
+ }
+
+ bool bDone(false);
try
{
- // remember old graphics and create new
- uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW);
- const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics());
- const uno::Reference<awt::XGraphics> xNewGraphics(mpOutputDevice->CreateUnoGraphics());
+ const uno::Reference<awt::XGraphics> xTargetGraphics(mpOutputDevice->CreateUnoGraphics());
- if (xNewGraphics.is())
+ if (xTargetGraphics.is())
{
- // link graphics and view
- xControlView->setGraphics(xNewGraphics);
+ // Needs to be drawn. Link new graphics and view
+ const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
+ uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics());
+ xControlView->setGraphics(xTargetGraphics);
// get position
const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation
* rControlPrimitive.getTransform());
const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0));
- // find out if the control is already visualized as a VCL-ChildWindow. If yes,
- // it does not need to be painted at all.
- uno::Reference<awt::XWindow2> xControlWindow(rXControl, uno::UNO_QUERY_THROW);
- const bool bControlIsVisibleAsChildWindow(rXControl->getPeer().is()
- && xControlWindow->isVisible());
-
- if (!bControlIsVisibleAsChildWindow)
- {
- // draw it. Do not forget to use the evtl. offsetted origin of the target device,
- // e.g. when used with mask/transparence buffer device
- const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
- xControlView->draw(aOrigin.X() + basegfx::fround(aTopLeftPixel.getX()),
- aOrigin.Y() + basegfx::fround(aTopLeftPixel.getY()));
- }
+ // Do not forget to use the evtl. offsetted origin of the target device,
+ // e.g. when used with mask/transparence buffer device
+ const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
+ xControlView->draw(aOrigin.X() + basegfx::fround(aTopLeftPixel.getX()),
+ aOrigin.Y() + basegfx::fround(aTopLeftPixel.getY()));
// restore original graphics
xControlView->setGraphics(xOriginalGraphics);
+ bDone = true;
}
}
catch (const uno::Exception&)
@@ -702,7 +688,10 @@ void VclPixelProcessor2D::processControlPrimitive2D(
// #i116763# removing since there is a good alternative when the xControlView
// is not found and it is allowed to happen
// DBG_UNHANDLED_EXCEPTION();
+ }
+ if (!bDone)
+ {
// process recursively and use the decomposition as Bitmap
process(rControlPrimitive);
}
@@ -739,7 +728,7 @@ void VclPixelProcessor2D::processPolygonStrokePrimitive2D(
void VclPixelProcessor2D::processFillHatchPrimitive2D(
const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive)
{
- if (getOptionsDrawinglayer().IsAntiAliasing())
+ if (getViewInformation2D().getUseAntiAliasing())
{
// if AA is used (or ignore smoothing is on), there is no need to smooth
// hatch painting, use decomposition
@@ -801,9 +790,10 @@ void VclPixelProcessor2D::processFillHatchPrimitive2D(
const basegfx::B2DVector aDiscreteDistance(
maCurrentTransformation * basegfx::B2DVector(rFillHatchAttributes.getDistance(), 0.0));
const sal_uInt32 nDistance(basegfx::fround(aDiscreteDistance.getLength()));
- const sal_uInt16 nAngle10(
- static_cast<sal_uInt16>(basegfx::fround(rFillHatchAttributes.getAngle() / F_PI1800)));
- ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance, nAngle10);
+ const sal_uInt32 nAngle10(
+ basegfx::fround(basegfx::rad2deg<10>(rFillHatchAttributes.getAngle())));
+ ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance,
+ Degree10(nAngle10));
// draw hatch using VCL
mpOutputDevice->DrawHatch(::tools::PolyPolygon(::tools::Polygon(aHatchPolygon)), aVCLHatch);
@@ -817,14 +807,13 @@ void VclPixelProcessor2D::processBackgroundColorPrimitive2D(
const AntialiasingFlags nOriginalAA(mpOutputDevice->GetAntialiasing());
// switch AA off in all cases
- mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
- & ~AntialiasingFlags::EnableB2dDraw);
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~AntialiasingFlags::Enable);
// create color for fill
const basegfx::BColor aPolygonColor(
maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
Color aFillColor(aPolygonColor);
- aFillColor.SetTransparency(sal_uInt8((rPrimitive.getTransparency() * 255.0) + 0.5));
+ aFillColor.SetAlpha(255 - sal_uInt8((rPrimitive.getTransparency() * 255.0) + 0.5));
mpOutputDevice->SetFillColor(aFillColor);
mpOutputDevice->SetLineColor();
@@ -875,7 +864,7 @@ void VclPixelProcessor2D::processBorderLinePrimitive2D(
&& rBorder.isHorizontalOrVertical(getViewInformation2D()))
{
AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing();
- mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
+ mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::Enable);
process(rBorder);
mpOutputDevice->SetAntialiasing(nAntiAliasing);
}
@@ -890,24 +879,22 @@ void VclPixelProcessor2D::processInvertPrimitive2D(const primitive2d::BasePrimit
// invert primitive (currently only used for HighContrast fallback for selection in SW and SC).
// (Not true, also used at least for the drawing of dragged column and row boundaries in SC.)
// Set OutDev to XOR and switch AA off (XOR does not work with AA)
- mpOutputDevice->Push();
+ auto popIt = mpOutputDevice->ScopedPush();
mpOutputDevice->SetRasterOp(RasterOp::Xor);
const AntialiasingFlags nAntiAliasing(mpOutputDevice->GetAntialiasing());
- mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
+ mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::Enable);
// process content recursively
process(rCandidate);
// restore OutDev
- mpOutputDevice->Pop();
mpOutputDevice->SetAntialiasing(nAntiAliasing);
}
void VclPixelProcessor2D::processMetaFilePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
{
// #i98289#
- const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing()
- && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+ const bool bForceLineSnap(getViewInformation2D().getPixelSnapHairline());
const AntialiasingFlags nOldAntiAliase(mpOutputDevice->GetAntialiasing());
if (bForceLineSnap)
@@ -923,202 +910,222 @@ void VclPixelProcessor2D::processMetaFilePrimitive2D(const primitive2d::BasePrim
}
}
-namespace
+void VclPixelProcessor2D::processFillGradientPrimitive2D(
+ const primitive2d::FillGradientPrimitive2D& rPrimitive)
{
-/* Returns 8-bit alpha mask created from passed mask.
-
- Negative fErodeDilateRadius values mean erode, positive - dilate.
- nTransparency defines minimal transparency level.
-*/
-AlphaMask ProcessAndBlurAlphaMask(const Bitmap& rMask, double fErodeDilateRadius,
- double fBlurRadius, sal_uInt8 nTransparency)
-{
- // Only completely white pixels on the initial mask must be considered for transparency. Any
- // other color must be treated as black. This creates 1-bit B&W bitmap.
- BitmapEx mask(rMask.CreateMask(COL_WHITE));
-
- // Scaling down increases performance without noticeable quality loss. Additionally,
- // current blur implementation can only handle blur radius between 2 and 254.
- Size aSize = mask.GetSizePixel();
- double fScale = 1.0;
- while (fBlurRadius > 254 || aSize.Height() > 1000 || aSize.Width() > 1000)
+ if (rPrimitive.hasAlphaGradient() || rPrimitive.hasTransparency())
{
- fScale /= 2;
- fBlurRadius /= 2;
- fErodeDilateRadius /= 2;
- aSize.setHeight(aSize.Height() / 2);
- aSize.setWidth(aSize.Width() / 2);
+ // SDPR: As long as direct alpha is not supported by this
+ // renderer we need to work on the decomposition, so call it
+ process(rPrimitive);
+ return;
}
- // BmpScaleFlag::Fast is important for following color replacement
- mask.Scale(fScale, fScale, BmpScaleFlag::Fast);
+ const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getFillGradient();
+ bool useDecompose(false);
- if (fErodeDilateRadius > 0)
- BitmapFilter::Filter(mask, BitmapDilateFilter(fErodeDilateRadius));
- else if (fErodeDilateRadius < 0)
- BitmapFilter::Filter(mask, BitmapErodeFilter(-fErodeDilateRadius, 0xFF));
-
- if (nTransparency)
+ // MCGR: *many* - and not only GradientStops - cases cannot be handled by VCL
+ // so use decomposition
+ if (rFillGradient.cannotBeHandledByVCL())
{
- const Color aTransparency(nTransparency, nTransparency, nTransparency);
- mask.Replace(COL_BLACK, aTransparency);
+ useDecompose = true;
}
- // We need 8-bit grey mask for blurring
- mask.Convert(BmpConversion::N8BitGreys);
-
- // calculate blurry effect
- BitmapFilter::Filter(mask, BitmapFilterStackBlur(fBlurRadius));
-
- mask.Scale(rMask.GetSizePixel());
-
- return AlphaMask(mask.GetBitmap());
-}
-}
-
-void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitive2D& rCandidate)
-{
- basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
- aRange.transform(maCurrentTransformation);
- basegfx::B2DVector aGlowRadiusVector(rCandidate.getGlowRadius(), 0);
- // Calculate the pixel size of glow radius in current transformation
- aGlowRadiusVector *= maCurrentTransformation;
- // Glow radius is the size of the halo from each side of the object. The halo is the
- // border of glow color that fades from glow transparency level to fully transparent
- // When blurring a sharp boundary (our case), it gets 50% of original intensity, and
- // fades to both sides by the blur radius; thus blur radius is half of glow radius.
- const double fBlurRadius = aGlowRadiusVector.getLength() / 2;
- // Consider glow transparency (initial transparency near the object edge)
- const sal_uInt8 nTransparency = rCandidate.getGlowColor().GetTransparency();
-
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
- if (aBufferDevice.isVisible())
+ // tdf#149754 VCL gradient draw is not capable to handle all primitive gradient definitions,
+ // what should be clear due to being developed to extend/replace them in
+ // capabilities & precision.
+ // It is e.g. not capable to correctly paint if the OutputRange is not completely
+ // inside the DefinitionRange, thus forcing to paint gradient parts *outside* the
+ // DefinitionRange.
+ // This happens for Writer with Frames anchored in Frames (and was broken due to
+ // falling back to VCL Gradient paint here), and for the new SlideBackgroundFill
+ // Fill mode for objects using it that reach outside the page (which is the
+ // DefinitionRange in that case).
+ // I see no real reason to fallback here to OutputDevice::DrawGradient and VCL
+ // gradient paint at all (system-dependent renderers wouldn't in the future), but
+ // will for convenience only add that needed additional correcting case
+ if (!useDecompose && !rPrimitive.getDefinitionRange().isInside(rPrimitive.getOutputRange()))
{
- // remember last OutDev and set to content
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- mpOutputDevice = &aBufferDevice.getContent();
- // We don't need antialiased mask here, which would only make effect thicker
- const auto aPrevAA = mpOutputDevice->GetAntialiasing();
- mpOutputDevice->SetAntialiasing(AntialiasingFlags::NONE);
- mpOutputDevice->Erase();
- process(rCandidate);
- const tools::Rectangle aRect(static_cast<long>(std::floor(aRange.getMinX())),
- static_cast<long>(std::floor(aRange.getMinY())),
- static_cast<long>(std::ceil(aRange.getMaxX())),
- static_cast<long>(std::ceil(aRange.getMaxY())));
- BitmapEx bmpEx = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize());
- mpOutputDevice->SetAntialiasing(aPrevAA);
-
- AlphaMask mask
- = ProcessAndBlurAlphaMask(bmpEx.GetAlpha(), fBlurRadius, fBlurRadius, nTransparency);
-
- // The end result is the bitmap filled with glow color and blurred 8-bit alpha mask
- const basegfx::BColor aGlowColor(
- maBColorModifierStack.getModifiedColor(rCandidate.getGlowColor().getBColor()));
- Bitmap bmp = bmpEx.GetBitmap();
- bmp.Erase(Color(aGlowColor));
- BitmapEx result(bmp, mask);
-
- // back to old OutDev
- mpOutputDevice = pLastOutputDevice;
- mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result);
+ useDecompose = true;
}
- else
- SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");
-}
-void VclPixelProcessor2D::processSoftEdgePrimitive2D(
- const primitive2d::SoftEdgePrimitive2D& rCandidate)
-{
- // TODO: don't limit the object at view range. This is needed to not blur objects at window
- // borders, where they don't end. Ideally, process the full object once at maximal reasonable
- // resolution, and store the resulting alpha mask in primitive's cache; then reuse it later,
- // applying the transform.
- basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
- aRange.transform(maCurrentTransformation);
- basegfx::B2DVector aRadiusVector(rCandidate.getRadius(), 0);
- // Calculate the pixel size of soft edge radius in current transformation
- aRadiusVector *= maCurrentTransformation;
- // Blur radius is equal to soft edge radius
- const double fBlurRadius = aRadiusVector.getLength();
-
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
- if (aBufferDevice.isVisible())
+ // tdf#151081 need to use regular primitive decomposition when the gradient
+ // is transformed in any other way then just translate & scale
+ if (!useDecompose)
{
- // remember last OutDev and set to content
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
- // Since the effect converts all children to bitmap, we can't disable antialiasing here,
- // because it would result in poor quality in areas not affected by the effect
- process(rCandidate);
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
- const tools::Rectangle aRect(static_cast<long>(std::floor(aRange.getMinX())),
- static_cast<long>(std::floor(aRange.getMinY())),
- static_cast<long>(std::ceil(aRange.getMaxX())),
- static_cast<long>(std::ceil(aRange.getMaxY())));
- BitmapEx bitmap = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize());
+ maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
- AlphaMask aMask = bitmap.GetAlpha();
- AlphaMask blurMask = ProcessAndBlurAlphaMask(aMask, -fBlurRadius, fBlurRadius, 0);
+ // detect if transformation is rotated, sheared or mirrored in X and/or Y
+ if (!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX)
+ || aScale.getX() < 0.0 || aScale.getY() < 0.0)
+ {
+ useDecompose = true;
+ }
+ }
- aMask.BlendWith(blurMask);
+ if (useDecompose)
+ {
+ // default is to use the direct render below. For security,
+ // keep the (simple) fallback to decompose in place here
+ static bool bTryDirectRender(true);
- // The end result is the original bitmap with blurred 8-bit alpha mask
- BitmapEx result(bitmap.GetBitmap(), aMask);
+ if (bTryDirectRender)
+ {
+ // MCGR: Avoid one level of primitive creation, use FillGradientPrimitive2D
+ // tooling to directly create needed geometry & color for getting better
+ // performance (partially compensate for potentially more expensive multi
+ // color gradients).
+ // To handle a primitive that needs paint, either use decompose, or - when you
+ // do not want that for any reason, e.g. extra primitives created - implement
+ // a direct handling in your primitive renderer. This is always possible
+ // since primitives by definition are self-contained what means they have all
+ // needed data locally available to do so.
+ // The question is the complexity to invest - the implemented decompose
+ // is always a good hint of what is needed to do this. In this case I decided
+ // to add some tooling methods to the primitive itself to support this. These
+ // are used in decompose and can be used - as here now - for direct handling,
+ // too. This is always a possibility in primitive handling - you can, but do not
+ // have to.
+ mpOutputDevice->SetFillColor(
+ Color(maBColorModifierStack.getModifiedColor(rPrimitive.getOuterColor())));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawTransparent(
+ maCurrentTransformation,
+ basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect(rPrimitive.getOutputRange())),
+ 0.0);
+
+ // paint solid fill steps by providing callback as lambda
+ auto aCallback([&rPrimitive, this](const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::BColor& rColor) {
+ // create part polygon
+ basegfx::B2DPolygon aNewPoly(rPrimitive.getUnitPolygon());
+ aNewPoly.transform(rMatrix);
+
+ // create solid fill
+ mpOutputDevice->SetFillColor(Color(maBColorModifierStack.getModifiedColor(rColor)));
+ mpOutputDevice->DrawTransparent(maCurrentTransformation,
+ basegfx::B2DPolyPolygon(aNewPoly), 0.0);
+ });
+
+ // call value generator to trigger callbacks
+ rPrimitive.generateMatricesAndColors(aCallback);
+ }
+ else
+ {
+ // use the decompose
+ process(rPrimitive);
+ }
- // back to old OutDev
- mpOutputDevice = pLastOutputDevice;
- mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result);
+ return;
}
- else
- SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");
+
+ // try to use vcl - since vcl uses the old gradient paint mechanisms this may
+ // create wrong geometries. If so, add another case above for useDecompose
+ Gradient aGradient(rFillGradient.getStyle(),
+ Color(rFillGradient.getColorStops().front().getStopColor()),
+ Color(rFillGradient.getColorStops().back().getStopColor()));
+
+ aGradient.SetAngle(Degree10(static_cast<int>(basegfx::rad2deg<10>(rFillGradient.getAngle()))));
+ aGradient.SetBorder(rFillGradient.getBorder() * 100);
+ aGradient.SetOfsX(rFillGradient.getOffsetX() * 100.0);
+ aGradient.SetOfsY(rFillGradient.getOffsetY() * 100.0);
+ aGradient.SetSteps(rFillGradient.getSteps());
+
+ basegfx::B2DRange aOutputRange(rPrimitive.getOutputRange());
+ aOutputRange.transform(maCurrentTransformation);
+ basegfx::B2DRange aFullRange(rPrimitive.getDefinitionRange());
+ aFullRange.transform(maCurrentTransformation);
+
+ const tools::Rectangle aOutputRectangle(
+ std::floor(aOutputRange.getMinX()), std::floor(aOutputRange.getMinY()),
+ std::ceil(aOutputRange.getMaxX()), std::ceil(aOutputRange.getMaxY()));
+ const tools::Rectangle aFullRectangle(
+ std::floor(aFullRange.getMinX()), std::floor(aFullRange.getMinY()),
+ std::ceil(aFullRange.getMaxX()), std::ceil(aFullRange.getMaxY()));
+
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::CLIPREGION);
+ mpOutputDevice->IntersectClipRegion(aOutputRectangle);
+ mpOutputDevice->DrawGradient(aFullRectangle, aGradient);
}
-void VclPixelProcessor2D::processShadowPrimitive2D(const primitive2d::ShadowPrimitive2D& rCandidate)
+void VclPixelProcessor2D::processPatternFillPrimitive2D(
+ const primitive2d::PatternFillPrimitive2D& rPrimitive)
{
- if (rCandidate.getShadowBlur() == 0)
- {
- process(rCandidate);
+ const basegfx::B2DRange& rReferenceRange = rPrimitive.getReferenceRange();
+ if (rReferenceRange.isEmpty() || rReferenceRange.getWidth() <= 0.0
+ || rReferenceRange.getHeight() <= 0.0)
return;
- }
- basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
- aRange.transform(maCurrentTransformation);
- basegfx::B2DVector aBlurRadiusVector(rCandidate.getShadowBlur(), 0);
- aBlurRadiusVector *= maCurrentTransformation;
- const double fBlurRadius = aBlurRadiusVector.getLength();
+ basegfx::B2DPolyPolygon aMask = rPrimitive.getMask();
+ aMask.transform(maCurrentTransformation);
+ const basegfx::B2DRange aMaskRange(aMask.getB2DRange());
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
- if (aBufferDevice.isVisible())
- {
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
-
- process(rCandidate);
+ if (aMaskRange.isEmpty() || aMaskRange.getWidth() <= 0.0 || aMaskRange.getHeight() <= 0.0)
+ return;
- const tools::Rectangle aRect(static_cast<long>(std::floor(aRange.getMinX())),
- static_cast<long>(std::floor(aRange.getMinY())),
- static_cast<long>(std::ceil(aRange.getMaxX())),
- static_cast<long>(std::ceil(aRange.getMaxY())));
+ sal_uInt32 nTileWidth, nTileHeight;
+ rPrimitive.getTileSize(nTileWidth, nTileHeight, getViewInformation2D());
+ if (nTileWidth == 0 || nTileHeight == 0)
+ return;
+ Bitmap aTileImage = rPrimitive.createTileImage(nTileWidth, nTileHeight);
+ tools::Rectangle aMaskRect = vcl::unotools::rectangleFromB2DRectangle(aMaskRange);
- BitmapEx bitmapEx = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize());
+ // Unless smooth edges are needed, simply use clipping.
+ if (basegfx::utils::isRectangle(aMask) || !getViewInformation2D().getUseAntiAliasing())
+ {
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::CLIPREGION);
+ mpOutputDevice->IntersectClipRegion(vcl::Region(aMask));
+ Wallpaper aWallpaper(aTileImage);
+ aWallpaper.SetColor(COL_TRANSPARENT);
+ Point aPaperPt(aMaskRect.getX() % nTileWidth, aMaskRect.getY() % nTileHeight);
+ tools::Rectangle aPaperRect(aPaperPt, aTileImage.GetSizePixel());
+ aWallpaper.SetRect(aPaperRect);
+ mpOutputDevice->DrawWallpaper(aMaskRect, aWallpaper);
+ return;
+ }
- AlphaMask mask = ProcessAndBlurAlphaMask(bitmapEx.GetAlpha(), 0, fBlurRadius, 0);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aMaskRange);
- const basegfx::BColor aShadowColor(
- maBColorModifierStack.getModifiedColor(rCandidate.getShadowColor()));
+ if (!aBufferDevice.isVisible())
+ return;
- Bitmap bitmap = bitmapEx.GetBitmap();
- bitmap.Erase(Color(aShadowColor));
- BitmapEx result(bitmap, mask);
+ // remember last OutDev and set to content
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice = pLastOutputDevice;
- mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result);
+ // if the tile is a single pixel big, just flood fill with that pixel color
+ if (nTileWidth == 1 && nTileHeight == 1)
+ {
+ Color col = aTileImage.GetPixelColor(0, 0);
+ mpOutputDevice->SetLineColor(col);
+ mpOutputDevice->SetFillColor(col);
+ mpOutputDevice->DrawRect(aMaskRect);
}
else
- SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");
+ {
+ Wallpaper aWallpaper(aTileImage);
+ aWallpaper.SetColor(COL_TRANSPARENT);
+ Point aPaperPt(aMaskRect.getX() % nTileWidth, aMaskRect.getY() % nTileHeight);
+ tools::Rectangle aPaperRect(aPaperPt, aTileImage.GetSizePixel());
+ aWallpaper.SetRect(aPaperRect);
+ mpOutputDevice->DrawWallpaper(aMaskRect, aWallpaper);
+ }
+
+ // back to old OutDev
+ mpOutputDevice = pLastOutputDevice;
+
+ // draw mask
+ VirtualDevice& rMask = aBufferDevice.getTransparence();
+ rMask.SetLineColor();
+ rMask.SetFillColor(COL_BLACK);
+ rMask.DrawPolyPolygon(aMask);
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
}
} // end of namespace
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
index c3bd19141669..2c582c3347bc 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx
@@ -29,19 +29,15 @@ namespace drawinglayer::primitive2d
class PolyPolygonColorPrimitive2D;
class PolygonHairlinePrimitive2D;
class PolygonStrokePrimitive2D;
-class WrongSpellPrimitive2D;
-class TextSimplePortionPrimitive;
class BitmapPrimitive2D;
class PolyPolygonGradientPrimitive2D;
class UnifiedTransparencePrimitive2D;
class ControlPrimitive2D;
-class PolygonStrokePrimitive2D;
class FillHatchPrimitive2D;
class BackgroundColorPrimitive2D;
class BorderLinePrimitive2D;
-class GlowPrimitive2D;
-class ShadowPrimitive2D;
-class SoftEdgePrimitive2D;
+class FillGradientPrimitive2D;
+class PatternFillPrimitive2D;
}
namespace drawinglayer::processor2d
@@ -54,8 +50,10 @@ namespace drawinglayer::processor2d
*/
class VclPixelProcessor2D final : public VclProcessor2D
{
- struct Impl;
- std::unique_ptr<Impl> m_pImpl;
+ AntialiasingFlags m_nOrigAntiAliasing;
+
+ bool m_bRenderSimpleTextDirect;
+ bool m_bRenderDecoratedTextDirect;
/* the local processor for BasePrimitive2D-Implementation based primitives,
called from the common process()-implementation
@@ -71,8 +69,6 @@ class VclPixelProcessor2D final : public VclProcessor2D
bool tryDrawPolygonStrokePrimitive2DDirect(const primitive2d::PolygonStrokePrimitive2D& rSource,
double fTransparency);
- void
- processWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive);
void processTextSimplePortionPrimitive2D(
const primitive2d::TextSimplePortionPrimitive2D& rCandidate);
void processTextDecoratedPortionPrimitive2D(
@@ -96,15 +92,12 @@ class VclPixelProcessor2D final : public VclProcessor2D
processBorderLinePrimitive2D(const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder);
void processInvertPrimitive2D(const primitive2d::BasePrimitive2D& rCandidate);
void processMetaFilePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate);
- void processGlowPrimitive2D(const primitive2d::GlowPrimitive2D& rCandidate);
- void processSoftEdgePrimitive2D(const primitive2d::SoftEdgePrimitive2D& rCandidate);
- void processShadowPrimitive2D(const primitive2d::ShadowPrimitive2D& rCandidate);
+ void processFillGradientPrimitive2D(const primitive2d::FillGradientPrimitive2D& rPrimitive);
+ void processPatternFillPrimitive2D(const primitive2d::PatternFillPrimitive2D& rPrimitive);
public:
/// constructor/destructor
- VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev,
- const basegfx::BColorModifierStack& rInitStack
- = basegfx::BColorModifierStack());
+ VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev);
virtual ~VclPixelProcessor2D() override;
};
} // end of namespace drawinglayer::processor2d
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 5a0a85f911ef..b3f319f51d8f 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -23,8 +23,14 @@
#include "vclhelperbufferdevice.hxx"
#include <cmath>
#include <comphelper/string.hxx>
+#include <comphelper/lok.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
#include <tools/debug.hxx>
+#include <tools/fract.hxx>
+#include <utility>
+#include <vcl/glyphitemcache.hxx>
#include <vcl/graph.hxx>
+#include <vcl/kernarray.hxx>
#include <vcl/outdev.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
@@ -34,19 +40,14 @@
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
@@ -94,6 +95,29 @@ sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA,
}
}
+namespace
+{
+/** helper to convert a MapMode to a transformation */
+basegfx::B2DHomMatrix getTransformFromMapMode(const MapMode& rMapMode)
+{
+ basegfx::B2DHomMatrix aMapping;
+ const Fraction aNoScale(1, 1);
+ const Point& rOrigin(rMapMode.GetOrigin());
+
+ if (0 != rOrigin.X() || 0 != rOrigin.Y())
+ {
+ aMapping.translate(rOrigin.X(), rOrigin.Y());
+ }
+
+ if (rMapMode.GetScaleX() != aNoScale || rMapMode.GetScaleY() != aNoScale)
+ {
+ aMapping.scale(double(rMapMode.GetScaleX()), double(rMapMode.GetScaleY()));
+ }
+
+ return aMapping;
+}
+}
+
namespace drawinglayer::processor2d
{
// rendering support
@@ -111,45 +135,64 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
basegfx::B2DVector aFontScaling, aTranslate;
double fRotate, fShearX;
aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
+
bool bPrimitiveAccepted(false);
// tdf#95581: Assume tiny shears are rounding artefacts or whatever and can be ignored,
// especially if the effect is less than a pixel.
if (std::abs(aFontScaling.getY() * fShearX) < 1)
{
- if (basegfx::fTools::less(aFontScaling.getX(), 0.0)
- && basegfx::fTools::less(aFontScaling.getY(), 0.0))
+ if (aFontScaling.getX() < 0.0 && aFontScaling.getY() < 0.0)
{
// handle special case: If scale is negative in (x,y) (3rd quadrant), it can
// be expressed as rotation by PI. Use this since the Font rendering will not
// apply the negative scales in any form
aFontScaling = basegfx::absolute(aFontScaling);
- fRotate += F_PI;
+ fRotate += M_PI;
}
- if (basegfx::fTools::more(aFontScaling.getX(), 0.0)
- && basegfx::fTools::more(aFontScaling.getY(), 0.0))
+ if (aFontScaling.getX() > 0.0 && aFontScaling.getY() > 0.0)
{
- // Get the VCL font (use FontHeight as FontWidth)
- vcl::Font aFont(primitive2d::getVclFontFromFontAttribute(
- rTextCandidate.getFontAttribute(), aFontScaling.getX(), aFontScaling.getY(),
- fRotate, rTextCandidate.getLocale()));
+ double fIgnoreRotate, fIgnoreShearX;
- // set FillColor Attribute
- const Color aFillColor(rTextCandidate.getTextFillColor());
- if (aFillColor != COL_TRANSPARENT)
+ basegfx::B2DVector aFontSize, aTextTranslate;
+ rTextCandidate.getTextTransform().decompose(aFontSize, aTextTranslate, fIgnoreRotate,
+ fIgnoreShearX);
+
+ // tdf#153092 Ideally we don't have to scale the font and dxarray, but we might have
+ // to nevertheless if dealing with non integer sizes
+ const bool bScaleFont(aFontSize.getY() != std::round(aFontSize.getY())
+ || comphelper::LibreOfficeKit::isActive());
+ vcl::Font aFont;
+
+ // Get the VCL font
+ if (!bScaleFont)
{
- aFont.SetFillColor(aFillColor);
- aFont.SetTransparent(false);
+ aFont = primitive2d::getVclFontFromFontAttribute(
+ rTextCandidate.getFontAttribute(), aFontSize.getX(), aFontSize.getY(), fRotate,
+ rTextCandidate.getLocale());
+ }
+ else
+ {
+ aFont = primitive2d::getVclFontFromFontAttribute(
+ rTextCandidate.getFontAttribute(), aFontScaling.getX(), aFontScaling.getY(),
+ fRotate, rTextCandidate.getLocale());
}
// Don't draw fonts without height
- if (aFont.GetFontHeight() <= 0)
+ Size aResultFontSize = aFont.GetFontSize();
+ if (aResultFontSize.Height() <= 0)
return;
+ // set FillColor Attribute
+ const Color aFillColor(rTextCandidate.getTextFillColor());
+ aFont.SetTransparent(aFillColor.IsTransparent());
+ aFont.SetFillColor(aFillColor);
+
// handle additional font attributes
- const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP
- = dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>(
+ const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = nullptr;
+ if (rTextCandidate.getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
+ pTCPP = static_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>(
&rTextCandidate);
if (pTCPP != nullptr)
@@ -251,83 +294,187 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
aFont.SetShadow(true);
}
- // create transformed integer DXArray in view coordinate system
- std::vector<long> aTransformedDXArray;
+ // create integer DXArray
+ KernArray aDXArray;
if (!rTextCandidate.getDXArray().empty())
{
- aTransformedDXArray.reserve(rTextCandidate.getDXArray().size());
- const basegfx::B2DVector aPixelVector(maCurrentTransformation
- * basegfx::B2DVector(1.0, 0.0));
- const double fPixelVectorFactor(aPixelVector.getLength());
-
- for (auto const& elem : rTextCandidate.getDXArray())
+ double fPixelVectorFactor(1.0);
+ if (bScaleFont)
{
- aTransformedDXArray.push_back(basegfx::fround(elem * fPixelVectorFactor));
+ const basegfx::B2DVector aPixelVector(maCurrentTransformation
+ * basegfx::B2DVector(1.0, 0.0));
+ fPixelVectorFactor = aPixelVector.getLength();
}
+
+ aDXArray.reserve(rTextCandidate.getDXArray().size());
+ for (auto const& elem : rTextCandidate.getDXArray())
+ aDXArray.push_back(elem * fPixelVectorFactor);
}
// set parameters and paint text snippet
const basegfx::BColor aRGBFontColor(
maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
- const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
- const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()));
- const ComplexTextLayoutFlags nOldLayoutMode(mpOutputDevice->GetLayoutMode());
+
+ // Store previous complex text layout state, to be restored after drawing
+ const vcl::text::ComplexTextLayoutFlags nOldLayoutMode(mpOutputDevice->GetLayoutMode());
if (rTextCandidate.getFontAttribute().getRTL())
{
- ComplexTextLayoutFlags nRTLLayoutMode(nOldLayoutMode
- & ~ComplexTextLayoutFlags::BiDiStrong);
- nRTLLayoutMode
- |= ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
+ vcl::text::ComplexTextLayoutFlags nRTLLayoutMode(
+ nOldLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+ nRTLLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl
+ | vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
mpOutputDevice->SetLayoutMode(nRTLLayoutMode);
}
+ else
+ {
+ // tdf#101686: This is LTR text, but the output device may have RTL state.
+ vcl::text::ComplexTextLayoutFlags nLTRLayoutMode(nOldLayoutMode);
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiRtl;
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong;
+ mpOutputDevice->SetLayoutMode(nLTRLayoutMode);
+ }
- mpOutputDevice->SetFont(aFont);
- mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+ Point aStartPoint;
+ bool bChangeMapMode(false);
+ if (!bScaleFont)
+ {
+ basegfx::B2DHomMatrix aCombinedTransform(
+ getTransformFromMapMode(mpOutputDevice->GetMapMode())
+ * maCurrentTransformation);
+
+ basegfx::B2DVector aCurrentScaling, aCurrentTranslate;
+ double fCurrentRotate;
+ aCombinedTransform.decompose(aCurrentScaling, aCurrentTranslate, fCurrentRotate,
+ fIgnoreShearX);
+
+ const Point aOrigin(
+ basegfx::fround<tools::Long>(aCurrentTranslate.getX() / aCurrentScaling.getX()),
+ basegfx::fround<tools::Long>(aCurrentTranslate.getY()
+ / aCurrentScaling.getY()));
+
+ Fraction aScaleX(aCurrentScaling.getX());
+ if (!aScaleX.IsValid())
+ {
+ SAL_WARN("drawinglayer", "invalid X Scale");
+ return;
+ }
+
+ Fraction aScaleY(aCurrentScaling.getY());
+ if (!aScaleY.IsValid())
+ {
+ SAL_WARN("drawinglayer", "invalid Y Scale");
+ return;
+ }
- OUString aText(rTextCandidate.getText());
- sal_Int32 nPos = rTextCandidate.getTextPosition();
- sal_Int32 nLen = rTextCandidate.getTextLength();
+ MapMode aMapMode(mpOutputDevice->GetMapMode().GetMapUnit(), aOrigin, aScaleX,
+ aScaleY);
- long* pDXArray = !aTransformedDXArray.empty() ? aTransformedDXArray.data() : nullptr;
+ if (fCurrentRotate)
+ aTextTranslate *= basegfx::utils::createRotateB2DHomMatrix(fCurrentRotate);
+ aStartPoint = Point(basegfx::fround<tools::Long>(aTextTranslate.getX()),
+ basegfx::fround<tools::Long>(aTextTranslate.getY()));
- if (rTextCandidate.isFilled())
+ bChangeMapMode = aMapMode != mpOutputDevice->GetMapMode();
+ if (bChangeMapMode)
+ {
+ mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
+ mpOutputDevice->SetRelativeMapMode(aMapMode);
+ }
+ }
+ else
{
- basegfx::B2DVector aOldFontScaling, aOldTranslate;
- double fOldRotate, fOldShearX;
- rTextCandidate.getTextTransform().decompose(aOldFontScaling, aOldTranslate,
- fOldRotate, fOldShearX);
-
- long nWidthToFill = static_cast<long>(
- rTextCandidate.getWidthToFill() * aFontScaling.getX() / aOldFontScaling.getX());
-
- long nWidth
- = mpOutputDevice->GetTextArray(rTextCandidate.getText(), pDXArray, 0, 1);
- long nChars = 2;
- if (nWidth)
- nChars = nWidthToFill / nWidth;
-
- OUStringBuffer aFilled;
- comphelper::string::padToLength(aFilled, nChars, aText[0]);
- aText = aFilled.makeStringAndClear();
- nPos = 0;
- nLen = nChars;
+ const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
+ double aPointX = aPoint.getX(), aPointY = aPoint.getY();
+
+ if (!comphelper::LibreOfficeKit::isActive())
+ {
+ // aFont has an integer size; we must scale a bit for precision
+ double nFontScalingFixY = aFontScaling.getY() / aResultFontSize.Height();
+ double nFontScalingFixX
+ = aFontScaling.getX()
+ / (aResultFontSize.Width() ? aResultFontSize.Width()
+ : aResultFontSize.Height());
+
+#ifdef _WIN32
+ if (aResultFontSize.Width()
+ && aResultFontSize.Width() != aResultFontSize.Height())
+ {
+ // See getVclFontFromFontAttribute in drawinglayer/source/primitive2d/textlayoutdevice.cxx
+ vcl::Font aUnscaledTest(aFont);
+ aUnscaledTest.SetFontSize({ 0, aResultFontSize.Height() });
+ const FontMetric aUnscaledFontMetric(
+ Application::GetDefaultDevice()->GetFontMetric(aUnscaledTest));
+ if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
+ {
+ double nExistingXScale = static_cast<double>(aResultFontSize.Width())
+ / aUnscaledFontMetric.GetAverageFontWidth();
+ nFontScalingFixX
+ = aFontScaling.getX() / aFontScaling.getY() / nExistingXScale;
+ }
+ }
+#endif
+
+ if (!rtl_math_approxEqual(nFontScalingFixY, 1.0)
+ || !rtl_math_approxEqual(nFontScalingFixX, 1.0))
+ {
+ MapMode aMapMode = mpOutputDevice->GetMapMode();
+ aMapMode.SetScaleX(aMapMode.GetScaleX() * nFontScalingFixX);
+ aMapMode.SetScaleY(aMapMode.GetScaleY() * nFontScalingFixY);
+
+ const bool bValidScaling
+ = aMapMode.GetScaleX().IsValid() && aMapMode.GetScaleY().IsValid();
+ if (!bValidScaling)
+ SAL_WARN("drawinglayer", "skipping invalid scaling");
+ else
+ {
+ assert(nFontScalingFixX != 0 && nFontScalingFixY != 0
+ && "or bValidScaling would be false");
+
+ Point origin = aMapMode.GetOrigin();
+
+ mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
+ mpOutputDevice->SetRelativeMapMode(aMapMode);
+ bChangeMapMode = true;
+
+ aPointX = (aPointX + origin.X()) / nFontScalingFixX - origin.X();
+ aPointY = (aPointY + origin.Y()) / nFontScalingFixY - origin.Y();
+ }
+ }
+ }
+
+ aStartPoint = Point(basegfx::fround<tools::Long>(aPointX),
+ basegfx::fround<tools::Long>(aPointY));
}
- if (!aTransformedDXArray.empty())
+ // tdf#152990 set the font after the MapMode is (potentially) set so canvas uses the desired
+ // font size
+ mpOutputDevice->SetFont(aFont);
+ mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+
+ if (!aDXArray.empty())
{
- mpOutputDevice->DrawTextArray(aStartPoint, aText, pDXArray, nPos, nLen);
+ const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+ mpOutputDevice, rTextCandidate.getText(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
+ mpOutputDevice->DrawTextArray(
+ aStartPoint, rTextCandidate.getText(), aDXArray,
+ rTextCandidate.getKashidaArray(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength(), SalLayoutFlags::NONE, pGlyphs);
}
else
{
- mpOutputDevice->DrawText(aStartPoint, aText, nPos, nLen);
+ mpOutputDevice->DrawText(aStartPoint, rTextCandidate.getText(),
+ rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
}
- if (rTextCandidate.getFontAttribute().getRTL())
- {
- mpOutputDevice->SetLayoutMode(nOldLayoutMode);
- }
+ // Restore previous layout mode
+ mpOutputDevice->SetLayoutMode(nOldLayoutMode);
+
+ if (bChangeMapMode)
+ mpOutputDevice->Pop();
bPrimitiveAccepted = true;
}
@@ -352,8 +499,7 @@ void VclProcessor2D::RenderPolygonHairlinePrimitive2D(
basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
aLocalPolygon.transform(maCurrentTransformation);
- if (bPixelBased && getOptionsDrawinglayer().IsAntiAliasing()
- && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete())
+ if (bPixelBased && getViewInformation2D().getPixelSnapHairline())
{
// #i98289#
// when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete
@@ -366,18 +512,18 @@ void VclProcessor2D::RenderPolygonHairlinePrimitive2D(
mpOutputDevice->DrawPolyLine(aLocalPolygon, 0.0);
}
-// direct draw of transformed BitmapEx primitive
+// direct draw of transformed Bitmap primitive
void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
{
- BitmapEx aBitmapEx(VCLUnoHelper::GetBitmap(rBitmapCandidate.getXBitmap()));
+ Bitmap aBitmap(rBitmapCandidate.getBitmap());
const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
* rBitmapCandidate.getTransform());
if (maBColorModifierStack.count())
{
- aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
- if (aBitmapEx.IsEmpty())
+ if (aBitmap.IsEmpty())
{
// color gets completely replaced, get it
const basegfx::BColor aModifiedColor(
@@ -397,249 +543,248 @@ void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2
// the own transformer is used (see OutputDevice::DrawTransformedBitmapEx).
// draw using OutputDevice'sDrawTransformedBitmapEx
- mpOutputDevice->DrawTransformedBitmapEx(aLocalTransform, aBitmapEx);
+ mpOutputDevice->DrawTransformedBitmapEx(aLocalTransform, aBitmap);
}
void VclProcessor2D::RenderFillGraphicPrimitive2D(
const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
{
+ if (rFillBitmapCandidate.getTransparency() < 0.0
+ || rFillBitmapCandidate.getTransparency() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ bool bPrimitiveAccepted = RenderFillGraphicPrimitive2DImpl(rFillBitmapCandidate);
+
+ if (!bPrimitiveAccepted)
+ {
+ // do not accept, use decomposition
+ process(rFillBitmapCandidate);
+ }
+}
+
+bool VclProcessor2D::RenderFillGraphicPrimitive2DImpl(
+ const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
+{
const attribute::FillGraphicAttribute& rFillGraphicAttribute(
rFillBitmapCandidate.getFillGraphic());
- bool bPrimitiveAccepted(false);
// #121194# when tiling is used and content is bitmap-based, do direct tiling in the
// renderer on pixel base to ensure tight fitting. Do not do this when
// the fill is rotated or sheared.
- if (rFillGraphicAttribute.getTiling())
- {
- // content is bitmap(ex)
- //
- // for Vector Graphic Data (SVG, EMF+) support, force decomposition when present. This will lead to use
- // the primitive representation of the vector data directly.
- //
- // when graphic is animated, force decomposition to use the correct graphic, else
- // fill style will not be animated
- if (GraphicType::Bitmap == rFillGraphicAttribute.getGraphic().GetType()
- && !rFillGraphicAttribute.getGraphic().getVectorGraphicData()
- && !rFillGraphicAttribute.getGraphic().IsAnimated())
- {
- // decompose matrix to check for shear, rotate and mirroring
- basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
- * rFillBitmapCandidate.getTransformation());
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- // when nopt rotated/sheared
- if (basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
- {
- // no shear or rotate, draw direct in pixel coordinates
- bPrimitiveAccepted = true;
+ if (!rFillGraphicAttribute.getTiling())
+ return false;
+
+ // content is bitmap(ex)
+ //
+ // for Vector Graphic Data (SVG, EMF+) support, force decomposition when present. This will lead to use
+ // the primitive representation of the vector data directly.
+ //
+ // when graphic is animated, force decomposition to use the correct graphic, else
+ // fill style will not be animated
+ if (GraphicType::Bitmap != rFillGraphicAttribute.getGraphic().GetType()
+ || rFillGraphicAttribute.getGraphic().getVectorGraphicData()
+ || rFillGraphicAttribute.getGraphic().IsAnimated())
+ return false;
+
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
+ * rFillBitmapCandidate.getTransformation());
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
- // transform object range to device coordinates (pixels). Use
- // the device transformation for better accuracy
- basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
- aObjectRange.transform(mpOutputDevice->GetViewTransformation());
+ // when nopt rotated/sheared
+ if (!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
+ return false;
- // extract discrete size of object
- const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
- const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
+ // no shear or rotate, draw direct in pixel coordinates
- // only do something when object has a size in discrete units
- if (nOWidth > 0 && nOHeight > 0)
- {
- // transform graphic range to device coordinates (pixels). Use
- // the device transformation for better accuracy
- basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
- aGraphicRange.transform(mpOutputDevice->GetViewTransformation()
- * aLocalTransform);
-
- // extract discrete size of graphic
- // caution: when getting to zero, nothing would be painted; thus, do not allow this
- const sal_Int32 nBWidth(
- std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getWidth())));
- const sal_Int32 nBHeight(
- std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getHeight())));
-
- // only do something when bitmap fill has a size in discrete units
- if (nBWidth > 0 && nBHeight > 0)
- {
- // nBWidth, nBHeight is the pixel size of the needed bitmap. To not need to scale it
- // in vcl many times, create a size-optimized version
- const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
- BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
- const bool bPreScaled(nBWidth * nBHeight < (250 * 250));
-
- // ... but only up to a maximum size, else it gets too expensive
- if (bPreScaled)
- {
- // if color depth is below 24bit, expand before scaling for better quality.
- // This is even needed for low colors, else the scale will produce
- // a bitmap in gray or Black/White (!)
- if (aBitmapEx.GetBitCount() < 24)
- {
- aBitmapEx.Convert(BmpConversion::N24Bit);
- }
+ // transform object range to device coordinates (pixels). Use
+ // the device transformation for better accuracy
+ basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
+ aObjectRange.transform(mpOutputDevice->GetViewTransformation());
- aBitmapEx.Scale(aNeededBitmapSizePixel, BmpScaleFlag::Interpolate);
- }
+ // extract discrete size of object
+ const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
+ const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
- bool bPainted(false);
+ // only do something when object has a size in discrete units
+ if (nOWidth <= 0 || nOHeight <= 0)
+ return true;
- if (maBColorModifierStack.count())
- {
- // when color modifier, apply to bitmap
- aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
+ // transform graphic range to device coordinates (pixels). Use
+ // the device transformation for better accuracy
+ basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
+ aGraphicRange.transform(mpOutputDevice->GetViewTransformation() * aLocalTransform);
- // impModifyBitmapEx uses empty bitmap as sign to return that
- // the content will be completely replaced to mono color, use shortcut
- if (aBitmapEx.IsEmpty())
- {
- // color gets completely replaced, get it
- const basegfx::BColor aModifiedColor(
- maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
- aPolygon.transform(aLocalTransform);
+ // extract discrete size of graphic
+ // caution: when getting to zero, nothing would be painted; thus, do not allow this
+ const sal_Int32 nBWidth(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getWidth())));
+ const sal_Int32 nBHeight(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getHeight())));
- mpOutputDevice->SetFillColor(Color(aModifiedColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawPolygon(aPolygon);
+ // nBWidth, nBHeight is the pixel size of the needed bitmap. To not need to scale it
+ // in vcl many times, create a size-optimized version
+ const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
+ Bitmap aBitmap(rFillGraphicAttribute.getGraphic().GetBitmap());
+ const bool bPreScaled(nBWidth * nBHeight < (250 * 250));
- bPainted = true;
- }
- }
+ // ... but only up to a maximum size, else it gets too expensive
+ if (bPreScaled)
+ {
+ // if color depth is below 24bit, expand before scaling for better quality.
+ // This is even needed for low colors, else the scale will produce
+ // a bitmap in gray or Black/White (!)
+ if (isPalettePixelFormat(aBitmap.getPixelFormat()))
+ {
+ aBitmap.Convert(BmpConversion::N24Bit);
+ }
- if (!bPainted)
- {
- sal_Int32 nBLeft(basegfx::fround(aGraphicRange.getMinX()));
- sal_Int32 nBTop(basegfx::fround(aGraphicRange.getMinY()));
- const sal_Int32 nOLeft(basegfx::fround(aObjectRange.getMinX()));
- const sal_Int32 nOTop(basegfx::fround(aObjectRange.getMinY()));
- sal_Int32 nPosX(0);
- sal_Int32 nPosY(0);
-
- if (nBLeft > nOLeft)
- {
- const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
+ aBitmap.Scale(aNeededBitmapSizePixel, BmpScaleFlag::Interpolate);
+ }
- nPosX -= nDiff;
- nBLeft -= nDiff * nBWidth;
- }
+ if (rFillBitmapCandidate.hasTransparency())
+ aBitmap.BlendAlpha(
+ static_cast<sal_uInt8>(255 - (rFillBitmapCandidate.getTransparency() * 255)));
- if (nBLeft + nBWidth <= nOLeft)
- {
- const sal_Int32 nDiff(-nBLeft / nBWidth);
+ if (maBColorModifierStack.count())
+ {
+ // when color modifier, apply to bitmap
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
- nPosX += nDiff;
- nBLeft += nDiff * nBWidth;
- }
+ // ModifyBitmapEx uses empty bitmap as sign to return that
+ // the content will be completely replaced to mono color, use shortcut
+ if (aBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aModifiedColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
+ aPolygon.transform(aLocalTransform);
- if (nBTop > nOTop)
- {
- const sal_Int32 nDiff((nBTop / nBHeight) + 1);
+ mpOutputDevice->SetFillColor(Color(aModifiedColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aPolygon);
- nPosY -= nDiff;
- nBTop -= nDiff * nBHeight;
- }
+ return true;
+ }
+ }
- if (nBTop + nBHeight <= nOTop)
- {
- const sal_Int32 nDiff(-nBTop / nBHeight);
+ sal_Int32 nBLeft(basegfx::fround(aGraphicRange.getMinX()));
+ sal_Int32 nBTop(basegfx::fround(aGraphicRange.getMinY()));
+ const sal_Int32 nOLeft(basegfx::fround(aObjectRange.getMinX()));
+ const sal_Int32 nOTop(basegfx::fround(aObjectRange.getMinY()));
+ sal_Int32 nPosX(0);
+ sal_Int32 nPosY(0);
- nPosY += nDiff;
- nBTop += nDiff * nBHeight;
- }
+ if (nBLeft > nOLeft)
+ {
+ const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
- // prepare OutDev
- const Point aEmptyPoint(0, 0);
- const ::tools::Rectangle aVisiblePixel(
- aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
- const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
- mpOutputDevice->EnableMapMode(false);
+ nPosX -= nDiff;
+ nBLeft -= nDiff * nBWidth;
+ }
- // check if offset is used
- const sal_Int32 nOffsetX(
- basegfx::fround(rFillGraphicAttribute.getOffsetX() * nBWidth));
+ if (nBLeft + nBWidth <= nOLeft)
+ {
+ const sal_Int32 nDiff(-nBLeft / nBWidth);
- if (nOffsetX)
- {
- // offset in X, so iterate over Y first and draw lines
- for (sal_Int32 nYPos(nBTop); nYPos < nOTop + nOHeight;
- nYPos += nBHeight, nPosY++)
- {
- for (sal_Int32 nXPos((nPosY % 2) ? nBLeft - nBWidth + nOffsetX
- : nBLeft);
- nXPos < nOLeft + nOWidth; nXPos += nBWidth)
- {
- const ::tools::Rectangle aOutRectPixel(
- Point(nXPos, nYPos), aNeededBitmapSizePixel);
-
- if (aOutRectPixel.IsOver(aVisiblePixel))
- {
- if (bPreScaled)
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aBitmapEx);
- }
- else
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aNeededBitmapSizePixel,
- aBitmapEx);
- }
- }
- }
- }
- }
- else
- {
- // check if offset is used
- const sal_Int32 nOffsetY(
- basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
+ nPosX += nDiff;
+ nBLeft += nDiff * nBWidth;
+ }
- // possible offset in Y, so iterate over X first and draw columns
- for (sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth;
- nXPos += nBWidth, nPosX++)
- {
- for (sal_Int32 nYPos((nPosX % 2) ? nBTop - nBHeight + nOffsetY
- : nBTop);
- nYPos < nOTop + nOHeight; nYPos += nBHeight)
- {
- const ::tools::Rectangle aOutRectPixel(
- Point(nXPos, nYPos), aNeededBitmapSizePixel);
-
- if (aOutRectPixel.IsOver(aVisiblePixel))
- {
- if (bPreScaled)
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aBitmapEx);
- }
- else
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aNeededBitmapSizePixel,
- aBitmapEx);
- }
- }
- }
- }
- }
+ if (nBTop > nOTop)
+ {
+ const sal_Int32 nDiff((nBTop / nBHeight) + 1);
- // restore OutDev
- mpOutputDevice->EnableMapMode(bWasEnabled);
- }
+ nPosY -= nDiff;
+ nBTop -= nDiff * nBHeight;
+ }
+
+ if (nBTop + nBHeight <= nOTop)
+ {
+ const sal_Int32 nDiff(-nBTop / nBHeight);
+
+ nPosY += nDiff;
+ nBTop += nDiff * nBHeight;
+ }
+
+ // prepare OutDev
+ const Point aEmptyPoint(0, 0);
+ // the visible rect, in pixels
+ const ::tools::Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
+ const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
+ mpOutputDevice->EnableMapMode(false);
+
+ // check if offset is used
+ const sal_Int32 nOffsetX(basegfx::fround(rFillGraphicAttribute.getOffsetX() * nBWidth));
+ const sal_Int32 nOffsetY(basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
+
+ // if the tile is a single pixel big, just flood fill with that pixel color
+ if (nOffsetX == 0 && nOffsetY == 0 && aNeededBitmapSizePixel.getWidth() == 1
+ && aNeededBitmapSizePixel.getHeight() == 1)
+ {
+ Color col = aBitmap.GetPixelColor(0, 0);
+ mpOutputDevice->SetLineColor(col);
+ mpOutputDevice->SetFillColor(col);
+ mpOutputDevice->DrawRect(aVisiblePixel);
+ }
+ else if (nOffsetX)
+ {
+ // offset in X, so iterate over Y first and draw lines
+ for (sal_Int32 nYPos(nBTop); nYPos < nOTop + nOHeight; nYPos += nBHeight, nPosY++)
+ {
+ for (sal_Int32 nXPos((nPosY % 2) ? nBLeft - nBWidth + nOffsetX : nBLeft);
+ nXPos < nOLeft + nOWidth; nXPos += nBWidth)
+ {
+ const ::tools::Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if (aOutRectPixel.Overlaps(aVisiblePixel))
+ {
+ if (bPreScaled)
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmap);
+ }
+ else
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(),
+ aNeededBitmapSizePixel, aBitmap);
}
}
}
}
}
-
- if (!bPrimitiveAccepted)
+ else // nOffsetY is used
{
- // do not accept, use decomposition
- process(rFillBitmapCandidate);
+ // possible offset in Y, so iterate over X first and draw columns
+ for (sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth; nXPos += nBWidth, nPosX++)
+ {
+ for (sal_Int32 nYPos((nPosX % 2) ? nBTop - nBHeight + nOffsetY : nBTop);
+ nYPos < nOTop + nOHeight; nYPos += nBHeight)
+ {
+ const ::tools::Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if (aOutRectPixel.Overlaps(aVisiblePixel))
+ {
+ if (bPreScaled)
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmap);
+ }
+ else
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(),
+ aNeededBitmapSizePixel, aBitmap);
+ }
+ }
+ }
+ }
}
+
+ // restore OutDev
+ mpOutputDevice->EnableMapMode(bWasEnabled);
+ return true;
}
// direct draw of Graphic
@@ -672,7 +817,8 @@ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(
case GraphicType::Bitmap:
{
if (!rFillGraphicAttribute.getGraphic().IsTransparent()
- && !rFillGraphicAttribute.getGraphic().IsAlpha())
+ && !rFillGraphicAttribute.getGraphic().IsAlpha()
+ && !rPolygonCandidate.hasTransparency())
{
// bitmap is not transparent and has no alpha
const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
@@ -757,7 +903,7 @@ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(
}
}
-// mask group. Force output to VDev and create mask from given mask
+// mask group
void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate)
{
if (rMaskCandidate.getChildren().empty())
@@ -769,6 +915,16 @@ void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive
return;
aMask.transform(maCurrentTransformation);
+
+ // Unless smooth edges are needed, simply use clipping.
+ if (basegfx::utils::isRectangle(aMask) || !getViewInformation2D().getUseAntiAliasing())
+ {
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::CLIPREGION);
+ mpOutputDevice->IntersectClipRegion(vcl::Region(aMask));
+ process(rMaskCandidate.getChildren());
+ return;
+ }
+
const basegfx::B2DRange aRange(basegfx::utils::getRange(aMask));
impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
@@ -785,28 +941,11 @@ void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive
// back to old OutDev
mpOutputDevice = pLastOutputDevice;
- // if the mask fills the whole area we can skip
- // creating a transparent vd and filling it.
- if (!basegfx::utils::isRectangle(aMask))
- {
- // draw mask
- if (getOptionsDrawinglayer().IsAntiAliasing())
- {
- // with AA, use 8bit AlphaMask to get nice borders
- VirtualDevice& rTransparence = aBufferDevice.getTransparence();
- rTransparence.SetLineColor();
- rTransparence.SetFillColor(COL_BLACK);
- rTransparence.DrawPolyPolygon(aMask);
- }
- else
- {
- // No AA, use 1bit mask
- VirtualDevice& rMask = aBufferDevice.getMask();
- rMask.SetLineColor();
- rMask.SetFillColor(COL_BLACK);
- rMask.DrawPolyPolygon(aMask);
- }
- }
+ // draw mask
+ VirtualDevice& rMask = aBufferDevice.getTransparence();
+ rMask.SetLineColor();
+ rMask.SetFillColor(COL_BLACK);
+ rMask.DrawPolyPolygon(aMask);
// dump buffer to outdev
aBufferDevice.paint();
@@ -841,14 +980,13 @@ void VclProcessor2D::RenderUnifiedTransparencePrimitive2D(
// transparence is in visible range
basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
aRange.transform(maCurrentTransformation);
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
if (aBufferDevice.isVisible())
{
// remember last OutDev and set to content
OutputDevice* pLastOutputDevice = mpOutputDevice;
mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
// paint content to it
process(rTransCandidate.getChildren());
@@ -871,7 +1009,7 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
aRange.transform(maCurrentTransformation);
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
if (!aBufferDevice.isVisible())
return;
@@ -879,7 +1017,6 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
// remember last OutDev and set to content
OutputDevice* pLastOutputDevice = mpOutputDevice;
mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
// paint content to it
process(rTransCandidate.getChildren());
@@ -891,13 +1028,11 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
maBColorModifierStack = basegfx::BColorModifierStack();
- mpOutputDevice->Erase();
-
// paint mask to it (always with transparence intensities, evtl. with AA)
process(rTransCandidate.getTransparence());
// back to old color stack
- maBColorModifierStack = aLastBColorModifierStack;
+ maBColorModifierStack = std::move(aLastBColorModifierStack);
// back to old OutDev
mpOutputDevice = pLastOutputDevice;
@@ -917,19 +1052,17 @@ void VclProcessor2D::RenderTransformPrimitive2D(
// create new transformations for CurrentTransformation
// and for local ViewInformation2D
maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(), getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation()
+ * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process content
process(rTransformCandidate.getChildren());
// restore transformations
maCurrentTransformation = aLastCurrentTransformation;
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
}
// new XDrawPage for ViewInformation2D
@@ -940,18 +1073,15 @@ void VclProcessor2D::RenderPagePreviewPrimitive2D(
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation(),
- getViewInformation2D().getViewTransformation(), getViewInformation2D().getViewport(),
- rPagePreviewCandidate.getXDrawPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setVisualizedPage(rPagePreviewCandidate.getXDrawPage());
+ setViewInformation2D(aViewInformation2D);
// process decomposed content
process(rPagePreviewCandidate);
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
}
// marker
@@ -962,11 +1092,11 @@ void VclProcessor2D::RenderMarkerArrayPrimitive2D(
const std::vector<basegfx::B2DPoint>& rPositions = rMarkArrayCandidate.getPositions();
const sal_uInt32 nCount(rPositions.size());
- if (!(nCount && !rMarkArrayCandidate.getMarker().IsEmpty()))
+ if (!nCount || rMarkArrayCandidate.getMarker().IsEmpty())
return;
// get pixel size
- const BitmapEx& rMarker(rMarkArrayCandidate.getMarker());
+ const Bitmap& rMarker(rMarkArrayCandidate.getMarker());
const Size aBitmapSize(rMarker.GetSizePixel());
if (!(aBitmapSize.Width() && aBitmapSize.Height()))
@@ -990,8 +1120,8 @@ void VclProcessor2D::RenderMarkerArrayPrimitive2D(
{
const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * pos)
- aDiscreteHalfSize);
- const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()),
- basegfx::fround(aDiscreteTopLeft.getY()));
+ const Point aDiscretePoint(basegfx::fround<tools::Long>(aDiscreteTopLeft.getX()),
+ basegfx::fround<tools::Long>(aDiscreteTopLeft.getY()));
mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker);
}
@@ -1011,8 +1141,8 @@ void VclProcessor2D::RenderPointArrayPrimitive2D(
for (auto const& pos : rPositions)
{
const basegfx::B2DPoint aViewPosition(maCurrentTransformation * pos);
- const Point aPos(basegfx::fround(aViewPosition.getX()),
- basegfx::fround(aViewPosition.getY()));
+ const Point aPos(basegfx::fround<tools::Long>(aViewPosition.getX()),
+ basegfx::fround<tools::Long>(aViewPosition.getY()));
mpOutputDevice->DrawPixel(aPos, aVCLColor);
}
@@ -1027,7 +1157,7 @@ void VclProcessor2D::RenderPolygonStrokePrimitive2D(
const double fLineWidth(rLineAttribute.getWidth());
bool bDone(false);
- if (basegfx::fTools::more(fLineWidth, 0.0))
+ if (fLineWidth > 0.0)
{
const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation
* basegfx::B2DVector(fLineWidth, 0.0));
@@ -1058,7 +1188,7 @@ void VclProcessor2D::RenderPolygonStrokePrimitive2D(
if (nCount)
{
- const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing());
+ const bool bAntiAliased(getViewInformation2D().getUseAntiAliasing());
aHairlinePolyPolygon.transform(maCurrentTransformation);
if (bAntiAliased)
@@ -1271,26 +1401,12 @@ void VclProcessor2D::RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEp
}
}
-void VclProcessor2D::RenderObjectInfoPrimitive2D(
- const primitive2d::ObjectInfoPrimitive2D& rObjectInfoPrimitive2D)
-{
- // remember current ObjectInfoPrimitive2D and set new current one (build a stack - push)
- const primitive2d::ObjectInfoPrimitive2D* pLast(getObjectInfoPrimitive2D());
- mpObjectInfoPrimitive2D = &rObjectInfoPrimitive2D;
-
- // process content
- process(rObjectInfoPrimitive2D.getChildren());
-
- // restore current ObjectInfoPrimitive2D (pop)
- mpObjectInfoPrimitive2D = pLast;
-}
-
void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(
const primitive2d::SvgLinearAtomPrimitive2D& rCandidate)
{
const double fDelta(rCandidate.getOffsetB() - rCandidate.getOffsetA());
- if (!basegfx::fTools::more(fDelta, 0.0))
+ if (fDelta <= 0.0)
return;
const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
@@ -1300,7 +1416,7 @@ void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(
const basegfx::B2DVector aDiscreteVector(
getViewInformation2D().getInverseObjectToViewTransformation()
* basegfx::B2DVector(1.0, 1.0));
- const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
+ const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / M_SQRT2));
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit));
@@ -1334,7 +1450,7 @@ void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(
{
const double fDeltaScale(rCandidate.getScaleB() - rCandidate.getScaleA());
- if (!basegfx::fTools::more(fDeltaScale, 0.0))
+ if (fDeltaScale <= 0.0)
return;
const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
@@ -1344,7 +1460,7 @@ void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(
const basegfx::B2DVector aDiscreteVector(
getViewInformation2D().getInverseObjectToViewTransformation()
* basegfx::B2DVector(1.0, 1.0));
- const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
+ const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / M_SQRT2));
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(
@@ -1482,25 +1598,40 @@ void VclProcessor2D::adaptTextToFillDrawMode() const
mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
}
-// process support
+void VclProcessor2D::onViewInformation2DChanged()
+{
+ // apply AntiAlias information to target device
+ if (getViewInformation2D().getUseAntiAliasing())
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
+ | AntialiasingFlags::Enable);
+ else
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
+ & ~AntialiasingFlags::Enable);
+
+ // apply DrawModeFlags to target device
+ if (getViewInformation2D().getDrawModeFlags() != mpOutputDevice->GetDrawMode())
+ mpOutputDevice->SetDrawMode(getViewInformation2D().getDrawModeFlags());
+}
+// process support
VclProcessor2D::VclProcessor2D(const geometry::ViewInformation2D& rViewInformation,
- OutputDevice& rOutDev,
- const basegfx::BColorModifierStack& rInitStack)
+ OutputDevice& rOutDev)
: BaseProcessor2D(rViewInformation)
, mpOutputDevice(&rOutDev)
- , maBColorModifierStack(rInitStack)
- , maCurrentTransformation()
- , maDrawinglayerOpt()
+ , maBColorModifierStack()
, mnPolygonStrokePrimitive2D(0)
- , mpObjectInfoPrimitive2D(nullptr)
+ , mnOriginalAA(rOutDev.GetAntialiasing())
{
// set digit language, derived from SvtCTLOptions to have the correct
// number display for arabic/hindi numerals
rOutDev.SetDigitLanguage(drawinglayer::detail::getDigitLanguage());
+
+ // NOTE: to save/restore original AntiAliasing mode we need
+ // to use mnOriginalAA here - OutputDevice::Push/Pop does not
+ // offer that
}
-VclProcessor2D::~VclProcessor2D() {}
+VclProcessor2D::~VclProcessor2D() { mpOutputDevice->SetAntialiasing(mnOriginalAA); }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.hxx b/drawinglayer/source/processor2d/vclprocessor2d.hxx
index dbca9ed4ba25..10beddf6bd10 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.hxx
@@ -22,7 +22,7 @@
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/color/bcolormodifier.hxx>
-#include <svtools/optionsdrawinglayer.hxx>
+#include <vcl/rendercontext/AntialiasingFlags.hxx>
#include <vcl/vclptr.hxx>
class OutputDevice;
@@ -33,9 +33,7 @@ class TextSimplePortionPrimitive2D;
class PolygonHairlinePrimitive2D;
class BitmapPrimitive2D;
class FillGraphicPrimitive2D;
-class PolyPolygonGradientPrimitive2D;
class PolyPolygonGraphicPrimitive2D;
-class MetafilePrimitive2D;
class MaskPrimitive2D;
class UnifiedTransparencePrimitive2D;
class TransparencePrimitive2D;
@@ -44,10 +42,8 @@ class MarkerArrayPrimitive2D;
class PointArrayPrimitive2D;
class ModifiedColorPrimitive2D;
class PolygonStrokePrimitive2D;
-class ControlPrimitive2D;
class PagePreviewPrimitive2D;
class EpsPrimitive2D;
-class ObjectInfoPrimitive2D;
class SvgLinearAtomPrimitive2D;
class SvgRadialAtomPrimitive2D;
}
@@ -73,15 +69,12 @@ protected:
// ViewInformation2D cannot directly be used, but needs to be kept up to date
basegfx::B2DHomMatrix maCurrentTransformation;
- // SvtOptionsDrawinglayer incarnation to react on diverse settings
- const SvtOptionsDrawinglayer maDrawinglayerOpt;
-
// stack value (increment and decrement) to count how deep we are in
// PolygonStrokePrimitive2D's decompositions (normally only one)
sal_uInt32 mnPolygonStrokePrimitive2D;
- // currently used ObjectInfoPrimitive2D
- const primitive2d::ObjectInfoPrimitive2D* mpObjectInfoPrimitive2D;
+ // AntialiasingFlags, saved at construction time
+ const AntialiasingFlags mnOriginalAA;
// common VCL rendering support
void RenderTextSimpleOrDecoratedPortionPrimitive2D(
@@ -109,8 +102,6 @@ protected:
void RenderPolygonStrokePrimitive2D(
const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate);
void RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEpsPrimitive2D);
- void
- RenderObjectInfoPrimitive2D(const primitive2d::ObjectInfoPrimitive2D& rObjectInfoPrimitive2D);
void RenderSvgLinearAtomPrimitive2D(const primitive2d::SvgLinearAtomPrimitive2D& rCandidate);
void RenderSvgRadialAtomPrimitive2D(const primitive2d::SvgRadialAtomPrimitive2D& rCandidate);
@@ -118,20 +109,17 @@ protected:
void adaptLineToFillDrawMode() const;
void adaptTextToFillDrawMode() const;
+ // allow to react on changes of ViewInformation2D
+ virtual void onViewInformation2DChanged() override;
+
public:
// constructor/destructor
- VclProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev,
- const basegfx::BColorModifierStack& rInitStack = basegfx::BColorModifierStack());
+ VclProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev);
virtual ~VclProcessor2D() override;
- // access to Drawinglayer configuration options
- const SvtOptionsDrawinglayer& getOptionsDrawinglayer() const { return maDrawinglayerOpt; }
-
- // access to currently used ObjectInfoPrimitive2D
- const primitive2d::ObjectInfoPrimitive2D* getObjectInfoPrimitive2D() const
- {
- return mpObjectInfoPrimitive2D;
- }
+private:
+ bool RenderFillGraphicPrimitive2DImpl(
+ const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate);
};
} // end of namespace drawinglayer::processor2d
diff --git a/drawinglayer/source/processor3d/baseprocessor3d.cxx b/drawinglayer/source/processor3d/baseprocessor3d.cxx
index 508ee553f31c..7fd2a80a9988 100644
--- a/drawinglayer/source/processor3d/baseprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/baseprocessor3d.cxx
@@ -18,7 +18,7 @@
*/
#include <drawinglayer/processor3d/baseprocessor3d.hxx>
-#include <comphelper/sequence.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -30,8 +30,8 @@ namespace drawinglayer::processor3d
{
}
- BaseProcessor3D::BaseProcessor3D(const geometry::ViewInformation3D& rViewInformation)
- : maViewInformation3D(rViewInformation)
+ BaseProcessor3D::BaseProcessor3D(geometry::ViewInformation3D aViewInformation)
+ : maViewInformation3D(std::move(aViewInformation))
{
}
@@ -49,27 +49,27 @@ namespace drawinglayer::processor3d
for(size_t a(0); a < nCount; a++)
{
// get reference
- const primitive3d::Primitive3DReference xReference(rSource[a]);
+ const primitive3d::Primitive3DReference& xReference(rSource[a]);
if(xReference.is())
{
- // try to cast to BasePrimitive3D implementation
- const primitive3d::BasePrimitive3D* pBasePrimitive = dynamic_cast< const primitive3d::BasePrimitive3D* >(xReference.get());
-
- if(pBasePrimitive)
- {
- processBasePrimitive3D(*pBasePrimitive);
- }
- else
- {
- // unknown implementation, use UNO API call instead and process recursively
- const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation3D().getViewInformationSequence());
- process(comphelper::sequenceToContainer<primitive3d::Primitive3DContainer>(xReference->getDecomposition(rViewParameters)));
- }
+ const primitive3d::BasePrimitive3D* pBasePrimitive = static_cast< const primitive3d::BasePrimitive3D* >(xReference.get());
+ processBasePrimitive3D(*pBasePrimitive);
}
}
}
+ void BaseProcessor3D::setViewInformation3D(const geometry::ViewInformation3D& rNew)
+ {
+ if (rNew != maViewInformation3D)
+ {
+ // set if changed
+ maViewInformation3D = rNew;
+
+ // allow reaction on change
+ onViewInformation3DChanged();
+ }
+ }
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor3d/cutfindprocessor3d.cxx b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx
index 432ef87d3a85..59228aeca0ed 100644
--- a/drawinglayer/source/processor3d/cutfindprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx
@@ -37,8 +37,6 @@ namespace drawinglayer::processor3d
: BaseProcessor3D(rViewInformation),
maFront(rFront),
maBack(rBack),
- maResult(),
- maCombinedTransform(),
mbAnyHit(bAnyHit)
{
}
@@ -76,7 +74,7 @@ namespace drawinglayer::processor3d
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
- updateViewInformation(aNewViewInformation3D);
+ setViewInformation3D(aNewViewInformation3D);
// #i102956# remember needed back-transform for found cuts (combine from right side)
const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform);
@@ -87,7 +85,7 @@ namespace drawinglayer::processor3d
// restore transformations and front, back
maCombinedTransform = aLastCombinedTransform;
- updateViewInformation(aLastViewInformation3D);
+ setViewInformation3D(aLastViewInformation3D);
maFront = aLastFront;
maBack = aLastBack;
break;
diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
index 51dfefb6ac5d..1e1212470a56 100644
--- a/drawinglayer/source/processor3d/defaultprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
@@ -31,7 +31,7 @@
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
-#include <vcl/bitmapex.hxx>
+#include <vcl/bitmap.hxx>
#include <drawinglayer/attribute/sdrsceneattribute3d.hxx>
#include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
#include <vcl/graph.hxx>
@@ -59,106 +59,82 @@ namespace drawinglayer::processor3d
// create texture
const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getGradient();
const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
- const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle());
- sal_uInt32 nSteps(rFillGradient.getSteps());
- const basegfx::BColor& aStart(rFillGradient.getStartColor());
- const basegfx::BColor& aEnd(rFillGradient.getEndColor());
- const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
+ const css::awt::GradientStyle aGradientStyle(rFillGradient.getStyle());
std::shared_ptr< texture::GeoTexSvx > pNewTex;
+ basegfx::BColor aSingleColor;
- if(nMaxSteps)
+ if (!rFillGradient.getColorStops().isSingleColor(aSingleColor))
{
- // there IS a color distance
- if(nSteps == 0)
- {
- nSteps = nMaxSteps;
- }
-
- if(nSteps < 2)
- {
- nSteps = 2;
- }
-
- if(nSteps > nMaxSteps)
- {
- nSteps = nMaxSteps;
- }
-
switch(aGradientStyle)
{
- case attribute::GradientStyle::Linear:
+ default: // GradientStyle_MAKE_FIXED_SIZE
+ case css::awt::GradientStyle_LINEAR:
{
pNewTex = std::make_shared<texture::GeoTexSvxGradientLinear>(
aOutlineRange,
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getAngle());
break;
}
- case attribute::GradientStyle::Axial:
+ case css::awt::GradientStyle_AXIAL:
{
pNewTex = std::make_shared<texture::GeoTexSvxGradientAxial>(
aOutlineRange,
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getAngle());
break;
}
- case attribute::GradientStyle::Radial:
+ case css::awt::GradientStyle_RADIAL:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientRadial>(
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY());
break;
}
- case attribute::GradientStyle::Elliptical:
+ case css::awt::GradientStyle_ELLIPTICAL:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientElliptical>(
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
rFillGradient.getAngle());
break;
}
- case attribute::GradientStyle::Square:
+ case css::awt::GradientStyle_SQUARE:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientSquare>(
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
rFillGradient.getAngle());
break;
}
- case attribute::GradientStyle::Rect:
+ case css::awt::GradientStyle_RECT:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientRect>(
aOutlineRange,
- aStart,
- aEnd,
- nSteps,
+ rFillGradient.getSteps(),
+ rFillGradient.getColorStops(),
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
@@ -171,20 +147,16 @@ namespace drawinglayer::processor3d
}
else
{
- // no color distance -> same color, use simple texture
- pNewTex = std::make_shared<texture::GeoTexSvxMono>(aStart, 1.0 - aStart.luminance());
+ // only one color, so no real gradient -> use simple texture
+ pNewTex = std::make_shared<texture::GeoTexSvxMono>(aSingleColor, 1.0 - aSingleColor.luminance());
mbSimpleTextureActive = true;
}
// set created texture
if(bTransparence)
- {
- mpTransparenceGeoTexSvx = pNewTex;
- }
+ mpTransparenceGeoTexSvx = std::move(pNewTex);
else
- {
- mpGeoTexSvx = pNewTex;
- }
+ mpGeoTexSvx = std::move(pNewTex);
// process sub-list
process(rSubSequence);
@@ -196,11 +168,11 @@ namespace drawinglayer::processor3d
if(bTransparence)
{
- mpTransparenceGeoTexSvx = pOldTex;
+ mpTransparenceGeoTexSvx = std::move(pOldTex);
}
else
{
- mpGeoTexSvx = pOldTex;
+ mpGeoTexSvx = std::move(pOldTex);
}
}
@@ -214,7 +186,7 @@ namespace drawinglayer::processor3d
// rescue values
const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
- std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx;
+ std::shared_ptr<texture::GeoTexSvx> xOldTex(mpGeoTexSvx);
// calculate logic pixel size in object coordinates. Create transformation view
// to object by inverting ObjectToView
@@ -242,7 +214,7 @@ namespace drawinglayer::processor3d
// restore values
mbModulate = bOldModulate;
mbFilter = bOldFilter;
- mpGeoTexSvx = pOldTex;
+ mpGeoTexSvx = std::move(xOldTex);
}
void DefaultProcessor3D::impRenderBitmapTexturePrimitive3D(const primitive3d::BitmapTexturePrimitive3D& rPrimitive)
@@ -261,7 +233,7 @@ namespace drawinglayer::processor3d
const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPrimitive.getFillGraphicAttribute();
// #121194# For 3D texture we will use the BitmapRex representation
- const BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
+ const Bitmap aBitmap(rFillGraphicAttribute.getGraphic().GetBitmap());
// create range scaled by texture size
basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
@@ -274,7 +246,7 @@ namespace drawinglayer::processor3d
{
mpGeoTexSvx =
std::make_shared<texture::GeoTexSvxBitmapExTiled>(
- aBitmapEx,
+ aBitmap,
aGraphicRange,
rFillGraphicAttribute.getOffsetX(),
rFillGraphicAttribute.getOffsetY());
@@ -283,7 +255,7 @@ namespace drawinglayer::processor3d
{
mpGeoTexSvx =
std::make_shared<texture::GeoTexSvxBitmapEx>(
- aBitmapEx,
+ aBitmap,
aGraphicRange);
}
@@ -293,7 +265,7 @@ namespace drawinglayer::processor3d
// restore values
mbModulate = bOldModulate;
mbFilter = bOldFilter;
- mpGeoTexSvx = pOldTex;
+ mpGeoTexSvx = std::move(pOldTex);
}
void DefaultProcessor3D::impRenderModifiedColorPrimitive3D(const primitive3d::ModifiedColorPrimitive3D& rModifiedCandidate)
@@ -489,13 +461,13 @@ namespace drawinglayer::processor3d
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
- updateViewInformation(aNewViewInformation3D);
+ setViewInformation3D(aNewViewInformation3D);
// let break down recursively
process(rTransformCandidate.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation3D);
+ setViewInformation3D(aLastViewInformation3D);
}
void DefaultProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rBasePrimitive)
@@ -577,11 +549,7 @@ namespace drawinglayer::processor3d
: BaseProcessor3D(rViewInformation),
mrSdrSceneAttribute(rSdrSceneAttribute),
mrSdrLightingAttribute(rSdrLightingAttribute),
- maRasterRange(),
maBColorModifierStack(),
- mpGeoTexSvx(),
- mpTransparenceGeoTexSvx(),
- maDrawinglayerOpt(),
mnTransparenceCounter(0),
mbModulate(false),
mbFilter(false),
diff --git a/drawinglayer/source/processor3d/geometry2dextractor.cxx b/drawinglayer/source/processor3d/geometry2dextractor.cxx
index c90eebe6819d..42144eae299e 100644
--- a/drawinglayer/source/processor3d/geometry2dextractor.cxx
+++ b/drawinglayer/source/processor3d/geometry2dextractor.cxx
@@ -23,14 +23,12 @@
#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <primitive3d/textureprimitive3d.hxx>
-
-
-using namespace com::sun::star;
+#include <utility>
namespace drawinglayer::processor3d
@@ -56,13 +54,13 @@ namespace drawinglayer::processor3d
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
- updateViewInformation(aNewViewInformation3D);
+ setViewInformation3D(aNewViewInformation3D);
// let break down recursively
process(rPrimitive.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation3D);
+ setViewInformation3D(aLastViewInformation3D);
break;
}
case PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D :
@@ -89,7 +87,7 @@ namespace drawinglayer::processor3d
{
a2DHairline.transform(getObjectTransformation());
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
- const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(a2DHairline, aModifiedColor));
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(std::move(a2DHairline), aModifiedColor));
maPrimitive2DSequence.push_back(xRef);
}
break;
@@ -104,7 +102,7 @@ namespace drawinglayer::processor3d
{
a2DFill.transform(getObjectTransformation());
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(rPrimitive.getMaterial().getColor()));
- const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(a2DFill, aModifiedColor));
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(std::move(a2DFill), aModifiedColor));
maPrimitive2DSequence.push_back(xRef);
}
break;
@@ -141,10 +139,9 @@ namespace drawinglayer::processor3d
Geometry2DExtractingProcessor::Geometry2DExtractingProcessor(
const geometry::ViewInformation3D& rViewInformation,
- const basegfx::B2DHomMatrix& rObjectTransformation)
+ basegfx::B2DHomMatrix aObjectTransformation)
: BaseProcessor3D(rViewInformation),
- maPrimitive2DSequence(),
- maObjectTransformation(rObjectTransformation),
+ maObjectTransformation(std::move(aObjectTransformation)),
maBColorModifierStack()
{
}
diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx
index 0b653236eb1b..7970b46cfabb 100644
--- a/drawinglayer/source/processor3d/shadow3dextractor.cxx
+++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx
@@ -24,11 +24,14 @@
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -71,20 +74,19 @@ namespace drawinglayer::processor3d
// create 2d shadow primitive with result. This also fetches all entries
// from aNewSubList, so there is no need to delete them
- primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D(
+ rtl::Reference<primitive2d::BasePrimitive2D> pNew = new primitive2d::ShadowPrimitive2D(
rPrimitive.getShadowTransform(),
rPrimitive.getShadowColor(),
0, // shadow3d doesn't have rPrimitive.getShadowBlur() yet.
- aNewSubList);
+ std::move(aNewSubList));
- if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0))
+ if(rPrimitive.getShadowTransparence() > 0.0)
{
// create simpleTransparencePrimitive, add created primitives
- const primitive2d::Primitive2DReference xRef(pNew);
- const primitive2d::Primitive2DContainer aNewTransPrimitiveVector { xRef };
+ primitive2d::Primitive2DContainer aNewTransPrimitiveVector { pNew };
pNew = new primitive2d::UnifiedTransparencePrimitive2D(
- aNewTransPrimitiveVector,
+ std::move(aNewTransPrimitiveVector),
rPrimitive.getShadowTransparence());
}
@@ -106,7 +108,7 @@ namespace drawinglayer::processor3d
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
- updateViewInformation(aNewViewInformation3D);
+ setViewInformation3D(aNewViewInformation3D);
if(mbShadowProjectionIsValid)
{
@@ -119,7 +121,7 @@ namespace drawinglayer::processor3d
process(rPrimitive.getChildren());
// restore transformations
- updateViewInformation(aLastViewInformation3D);
+ setViewInformation3D(aLastViewInformation3D);
if(mbShadowProjectionIsValid)
{
@@ -154,7 +156,7 @@ namespace drawinglayer::processor3d
a2DHairline.transform(getObjectTransformation());
mpPrimitive2DSequence->push_back(
new primitive2d::PolygonHairlinePrimitive2D(
- a2DHairline,
+ std::move(a2DHairline),
basegfx::BColor()));
}
}
@@ -185,7 +187,7 @@ namespace drawinglayer::processor3d
a2DFill.transform(getObjectTransformation());
mpPrimitive2DSequence->push_back(
new primitive2d::PolyPolygonColorPrimitive2D(
- a2DFill,
+ std::move(a2DFill),
basegfx::BColor()));
}
}
@@ -202,19 +204,14 @@ namespace drawinglayer::processor3d
Shadow3DExtractingProcessor::Shadow3DExtractingProcessor(
const geometry::ViewInformation3D& rViewInformation,
- const basegfx::B2DHomMatrix& rObjectTransformation,
+ basegfx::B2DHomMatrix aObjectTransformation,
const basegfx::B3DVector& rLightNormal,
double fShadowSlant,
const basegfx::B3DRange& rContained3DRange)
: BaseProcessor3D(rViewInformation),
- maPrimitive2DSequence(),
mpPrimitive2DSequence(&maPrimitive2DSequence),
- maObjectTransformation(rObjectTransformation),
- maWorldToEye(),
- maEyeToView(),
+ maObjectTransformation(std::move(aObjectTransformation)),
maLightNormal(rLightNormal),
- maShadowPlaneNormal(),
- maPlanePoint(),
mfLightPlaneScalar(0.0),
mbShadowProjectionIsValid(false),
mbConvert(false),
@@ -227,7 +224,7 @@ namespace drawinglayer::processor3d
mfLightPlaneScalar = maLightNormal.scalar(maShadowPlaneNormal);
// use only when scalar is > 0.0, so the light is in front of the object
- if(!basegfx::fTools::more(mfLightPlaneScalar, 0.0))
+ if(mfLightPlaneScalar <= 0.0 || basegfx::fTools::equalZero(mfLightPlaneScalar))
return;
// prepare buffered WorldToEye and EyeToView
diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
index 6cd65d60b416..22674b414cc6 100644
--- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
@@ -27,6 +27,9 @@
#include <basegfx/polygon/b3dpolygontools.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
+#include <o3tl/safeint.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <utility>
using namespace com::sun::star;
@@ -100,7 +103,7 @@ private:
double decideColorAndOpacity(basegfx::BColor& rColor) const
{
// init values with full opacity and material color
- OSL_ENSURE(nullptr != mpCurrentMaterial, "CurrentMaterial not set (!)");
+ assert(nullptr != mpCurrentMaterial && "CurrentMaterial not set (!)");
double fOpacity(1.0);
rColor = mpCurrentMaterial->getColor();
@@ -116,14 +119,14 @@ private:
mrProcessor.getGeoTexSvx()->modifyBColor(aTexCoor, rColor, fOpacity);
}
- if(basegfx::fTools::more(fOpacity, 0.0) && mrProcessor.getTransparenceGeoTexSvx())
+ if (fOpacity > 0.0 && !basegfx::fTools::equalZero(fOpacity) && mrProcessor.getTransparenceGeoTexSvx())
{
// calc opacity. Object has a 2nd texture, a transparence texture
mrProcessor.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor, fOpacity);
}
}
- if(basegfx::fTools::more(fOpacity, 0.0))
+ if (fOpacity > 0.0 && !basegfx::fTools::equalZero(fOpacity))
{
if(mrProcessor.getGeoTexSvx())
{
@@ -246,14 +249,8 @@ private:
public:
ZBufferRasterConverter3D(basegfx::BZPixelRaster& rBuffer, const drawinglayer::processor3d::ZBufferProcessor3D& rProcessor)
- : basegfx::RasterConverter3D(),
- mrProcessor(rProcessor),
+ : mrProcessor(rProcessor),
mrBuffer(rBuffer),
- maIntZ(),
- maIntColor(),
- maIntNormal(),
- maIntTexture(),
- maIntInvTexture(),
mpCurrentMaterial(nullptr),
mbModifyColor(false),
mbUseTex(false),
@@ -274,7 +271,7 @@ void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLi
if(nSpanCount & 0x0001)
return;
- if(nLine < 0 || nLine >= static_cast<sal_Int32>(mrBuffer.getHeight()))
+ if(nLine < 0 || o3tl::make_unsigned(nLine) >= mrBuffer.getHeight())
return;
sal_uInt32 nXA(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rA.getX().getVal())))));
@@ -298,7 +295,7 @@ void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLi
while(nXA < nXB)
{
// early-test Z values if we need to do anything at all
- const double fNewZ(std::max(0.0, std::min(double(0xffff), maIntZ.getVal())));
+ const double fNewZ(std::clamp(maIntZ.getVal(), 0.0, 65535.0));
const sal_uInt16 nNewZ(static_cast< sal_uInt16 >(fNewZ));
sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex));
@@ -322,20 +319,20 @@ void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLi
{
basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex);
- if(rDest.getOpacity())
+ if(rDest.getAlpha())
{
// mix new color by using
// color' = color * (1 - opacity) + newcolor * opacity
- const sal_uInt16 nTransparence(0x0100 - nOpacity);
+ const sal_uInt16 nTransparence(255 - nOpacity);
rDest.setRed(static_cast<sal_uInt8>(((rDest.getRed() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getRed()) * nOpacity)) >> 8));
rDest.setGreen(static_cast<sal_uInt8>(((rDest.getGreen() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getGreen()) * nOpacity)) >> 8));
rDest.setBlue(static_cast<sal_uInt8>(((rDest.getBlue() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getBlue()) * nOpacity)) >> 8));
- if(0xff != rDest.getOpacity())
+ if(255 != rDest.getAlpha())
{
// both are transparent, mix new opacity by using
// opacity = newopacity * (1 - oldopacity) + oldopacity
- rDest.setOpacity(static_cast<sal_uInt8>((nOpacity * (0x0100 - rDest.getOpacity())) >> 8) + rDest.getOpacity());
+ rDest.setAlpha(static_cast<sal_uInt8>((nOpacity * (255 - rDest.getAlpha())) >> 8) + rDest.getAlpha());
}
}
else
@@ -379,16 +376,16 @@ private:
public:
RasterPrimitive3D(
- const std::shared_ptr< drawinglayer::texture::GeoTexSvx >& pGeoTexSvx,
- const std::shared_ptr< drawinglayer::texture::GeoTexSvx >& pTransparenceGeoTexSvx,
+ std::shared_ptr< drawinglayer::texture::GeoTexSvx > pGeoTexSvx,
+ std::shared_ptr< drawinglayer::texture::GeoTexSvx > pTransparenceGeoTexSvx,
const drawinglayer::attribute::MaterialAttribute3D& rMaterial,
const basegfx::B3DPolyPolygon& rPolyPolygon,
bool bModulate,
bool bFilter,
bool bSimpleTextureActive,
bool bIsLine)
- : mpGeoTexSvx(pGeoTexSvx),
- mpTransparenceGeoTexSvx(pTransparenceGeoTexSvx),
+ : mpGeoTexSvx(std::move(pGeoTexSvx)),
+ mpTransparenceGeoTexSvx(std::move(pTransparenceGeoTexSvx)),
maMaterial(rMaterial),
maPolyPolygon(rPolyPolygon),
mfCenterZ(basegfx::utils::getRange(rPolyPolygon).getCenter().getZ()),
@@ -422,12 +419,8 @@ namespace drawinglayer::processor3d
{
// transparent output; record for later sorting and painting from
// back to front
- if(!mpRasterPrimitive3Ds)
- {
- const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds.reset( new std::vector< RasterPrimitive3D > );
- }
- mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
+ maRasterPrimitive3Ds.push_back(RasterPrimitive3D(
getGeoTexSvx(),
getTransparenceGeoTexSvx(),
rMaterial,
@@ -444,7 +437,7 @@ namespace drawinglayer::processor3d
if(mnAntiAlialize > 1)
{
- const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+ const bool bForceLineSnap(SvtOptionsDrawinglayer::IsAntiAliasing() && SvtOptionsDrawinglayer::IsSnapHorVerLinesToDiscrete());
if(bForceLineSnap)
{
@@ -486,12 +479,7 @@ namespace drawinglayer::processor3d
{
// transparent output; record for later sorting and painting from
// back to front
- if(!mpRasterPrimitive3Ds)
- {
- const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds.reset( new std::vector< RasterPrimitive3D > );
- }
-
- mpRasterPrimitive3Ds->push_back(RasterPrimitive3D(
+ maRasterPrimitive3Ds.push_back(RasterPrimitive3D(
getGeoTexSvx(),
getTransparenceGeoTexSvx(),
rMaterial,
@@ -520,7 +508,6 @@ namespace drawinglayer::processor3d
sal_uInt32 nStartLine,
sal_uInt32 nStopLine)
: DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
- maInvEyeToView(),
mnAntiAlialize(nAntiAlialize),
mnStartLine(nStartLine),
mnStopLine(nStopLine)
@@ -575,7 +562,7 @@ namespace drawinglayer::processor3d
aDeviceToView,
getViewInformation3D().getViewTime(),
getViewInformation3D().getExtendedInformationSequence());
- updateViewInformation(aNewViewInformation3D);
+ setViewInformation3D(aNewViewInformation3D);
// prepare inverse EyeToView transformation. This can be done in constructor
// since changes in object transformations when processing TransformPrimitive3Ds
@@ -596,32 +583,31 @@ namespace drawinglayer::processor3d
{
mpZBufferRasterConverter3D.reset();
- if(mpRasterPrimitive3Ds)
+ if(!maRasterPrimitive3Ds.empty())
{
OSL_FAIL("ZBufferProcessor3D: destructed, but there are unrendered transparent geometries. Use ZBufferProcessor3D::finish() to render these (!)");
}
- mpRasterPrimitive3Ds.reset();
}
void ZBufferProcessor3D::finish()
{
- if(!mpRasterPrimitive3Ds)
+ if(maRasterPrimitive3Ds.empty())
return;
// there are transparent rasterprimitives
- const sal_uInt32 nSize(mpRasterPrimitive3Ds->size());
+ const sal_uInt32 nSize(maRasterPrimitive3Ds.size());
if(nSize > 1)
{
// sort them from back to front
- std::sort(mpRasterPrimitive3Ds->begin(), mpRasterPrimitive3Ds->end());
+ std::sort(maRasterPrimitive3Ds.begin(), maRasterPrimitive3Ds.end());
}
for(sal_uInt32 a(0); a < nSize; a++)
{
// paint each one by setting the remembered data and calling
// the render method
- const RasterPrimitive3D& rCandidate = (*mpRasterPrimitive3Ds)[a];
+ const RasterPrimitive3D& rCandidate = maRasterPrimitive3Ds[a];
mpGeoTexSvx = rCandidate.getGeoTexSvx();
mpTransparenceGeoTexSvx = rCandidate.getTransparenceGeoTexSvx();
@@ -645,7 +631,7 @@ namespace drawinglayer::processor3d
// delete them to signal the destructor that all is done and
// to allow asserting there
- mpRasterPrimitive3Ds.reset();
+ maRasterPrimitive3Ds.clear();
}
} // end of namespace
diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx
index a7e9dca54c79..d0210dbc7b24 100644
--- a/drawinglayer/source/texture/texture.cxx
+++ b/drawinglayer/source/texture/texture.cxx
@@ -20,6 +20,7 @@
#include <sal/config.h>
#include <algorithm>
+#include <limits>
#include <texture/texture.hxx>
#include <basegfx/numeric/ftools.hxx>
@@ -71,15 +72,14 @@ namespace drawinglayer::texture
GeoTexSvxGradient::GeoTexSvxGradient(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder)
- : GeoTexSvx(),
- maGradientInfo(),
- maDefinitionRange(rDefinitionRange),
- maStart(rStart),
- maEnd(rEnd),
- mfBorder(fBorder)
+ : maDefinitionRange(rDefinitionRange)
+ , mnRequestedSteps(nRequestedSteps)
+ , mnColorStops(rColorStops)
+ , mfBorder(fBorder)
+ , maLastColorStopRange()
{
}
@@ -94,26 +94,26 @@ namespace drawinglayer::texture
return (pCompare
&& maGradientInfo == pCompare->maGradientInfo
&& maDefinitionRange == pCompare->maDefinitionRange
+ && mnRequestedSteps == pCompare->mnRequestedSteps
+ && mnColorStops == pCompare->mnColorStops
&& mfBorder == pCompare->mfBorder);
}
-
GeoTexSvxGradientLinear::GeoTexSvxGradientLinear(
const basegfx::B2DRange& rDefinitionRange,
const basegfx::B2DRange& rOutputRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fAngle)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder),
- mfUnitMinX(0.0),
- mfUnitWidth(1.0),
- mfUnitMaxY(1.0)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
+ , mfUnitMinX(0.0)
+ , mfUnitWidth(1.0)
+ , mfUnitMaxY(1.0)
{
maGradientInfo = basegfx::utils::createLinearODFGradientInfo(
rDefinitionRange,
- nSteps,
+ nRequestedSteps,
fBorder,
fAngle);
@@ -133,16 +133,30 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientLinear::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maStart;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- const double fStripeWidth(1.0 / maGradientInfo.getSteps());
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
+
+ if (bPenultimateUsed)
+ {
+ // Here we need to temporarily add a ColorStop entry with the
+ // same color as the last entry to correctly 'close' the
+ // created gradient geometry.
+ // The simplest way is to temporarily add an entry to the local
+ // ColorStops for this at 1.0 (using same color)
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
+ }
+
+ // prepare unit range transform
basegfx::B2DHomMatrix aPattern;
// bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
@@ -153,54 +167,106 @@ namespace drawinglayer::texture
aPattern.scale(mfUnitWidth, 1.0);
aPattern.translate(mfUnitMinX, 0.0);
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{
- const double fPos(fStripeWidth * a);
- basegfx::B2DHomMatrix aNew(aPattern);
-
- // scale and translate in Y
- double fHeight(1.0 - fPos);
-
- if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0)
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
+
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
+
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+ // calculate StripeWidth
+ // nSteps is >= 1, see getRequestedSteps, so no check needed here
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
+
+ // for the 1st color range we do not need to create the 1st step
+ // since it will be equal to StartColor and thus OuterColor, so
+ // will be painted by the 1st, always-created background polygon
+ // colored using OuterColor.
+ // We *need* to create this though for all 'inner' color ranges
+ // to get a correct start
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
{
- fHeight += mfUnitMaxY - 1.0;
+ // calculate pos in Y
+ const double fPos(fOffsetStart + (fStripeWidth * innerLoop));
+
+ // scale and translate in Y. For GradientLinear we always have
+ // the full height
+ double fHeight(1.0 - fPos);
+
+ if (mfUnitMaxY > 1.0)
+ {
+ // extend when difference between definition and OutputRange exists
+ fHeight += mfUnitMaxY - 1.0;
+ }
+
+ basegfx::B2DHomMatrix aNew(aPattern);
+ aNew.scale(1.0, fHeight);
+ aNew.translate(0.0, fPos);
+
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform() * aNew,
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
}
+ }
- aNew.scale(1.0, fHeight);
- aNew.translate(0.0, fPos);
-
- // set at target
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew;
-
- // interpolate and set color
- aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
-
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ if (bPenultimateUsed)
+ {
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
- const double fScaler(basegfx::utils::getLinearGradientAlpha(rUV, maGradientInfo));
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
+
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+ const double fScaler(basegfx::utils::getLinearGradientAlpha(rUV, maGradientInfo));
+ rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientAxial::GeoTexSvxGradientAxial(
const basegfx::B2DRange& rDefinitionRange,
const basegfx::B2DRange& rOutputRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fAngle)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder),
- mfUnitMinX(0.0),
- mfUnitWidth(1.0)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
+ , mfUnitMinX(0.0)
+ , mfUnitWidth(1.0)
{
+ // ARGH! GradientAxial uses the ColorStops in reverse order compared
+ // with the other gradients. Either stay 'thinking reverse' for the
+ // rest of time or adapt it here and go in same order as the other five,
+ // so unifications/tooling will be possible
+ mnColorStops.reverseColorStops();
+
maGradientInfo = basegfx::utils::createAxialODFGradientInfo(
rDefinitionRange,
- nSteps,
+ nRequestedSteps,
fBorder,
fAngle);
@@ -219,65 +285,118 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientAxial::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maEnd;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- const double fStripeWidth(1.0 / maGradientInfo.getSteps());
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
+
+ if (bPenultimateUsed)
+ {
+ // temporarily add a ColorStop entry
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
+ }
+
+ // prepare unit range transform
+ basegfx::B2DHomMatrix aPattern;
+
+ // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
+ aPattern.scale(0.5, 1.0);
+ aPattern.translate(0.5, 0.0);
+
+ // scale/translate in X
+ aPattern.scale(mfUnitWidth, 1.0);
+ aPattern.translate(mfUnitMinX, 0.0);
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{
- const double fPos(fStripeWidth * a);
- basegfx::B2DHomMatrix aNew;
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
- // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
- aNew.scale(0.5, 1.0);
- aNew.translate(0.5, 0.0);
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
- // scale/translate in X
- aNew.scale(mfUnitWidth, 1.0);
- aNew.translate(mfUnitMinX, 0.0);
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
- // already centered in Y on X-Axis, just scale in Y
- aNew.scale(1.0, 1.0 - fPos);
+ // calculate StripeWidth
+ // nSteps is >= 1, see getRequestedSteps, so no check needed here
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
- // set at target
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew;
+ // for the 1st color range we do not need to create the 1st step, see above
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
+ {
+ // calculate pos in Y
+ const double fPos(fOffsetStart + (fStripeWidth * innerLoop));
- // interpolate and set color
- aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1));
+ // already centered in Y on X-Axis, just scale in Y
+ basegfx::B2DHomMatrix aNew(aPattern);
+ aNew.scale(1.0, 1.0 - fPos);
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform() * aNew,
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
+ }
+ }
+
+ if (bPenultimateUsed)
+ {
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
+
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ // we use the reverse ColorSteps here, so use front value
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
+
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
const double fScaler(basegfx::utils::getAxialGradientAlpha(rUV, maGradientInfo));
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // we use the reverse ColorSteps here, so mirror scaler value
+ rBColor = mnColorStops.getInterpolatedBColor(1.0 - fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientRadial::GeoTexSvxGradientRadial(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
{
maGradientInfo = basegfx::utils::createRadialODFGradientInfo(
rDefinitionRange,
basegfx::B2DVector(fOffsetX,fOffsetY),
- nSteps,
+ nRequestedSteps,
fBorder);
}
@@ -286,49 +405,100 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientRadial::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maStart;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- const double fStepSize(1.0 / maGradientInfo.getSteps());
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
+
+ if (bPenultimateUsed)
+ {
+ // temporarily add a ColorStop entry
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
+ }
+
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
+ {
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
+
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
+
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+ // calculate StripeWidth
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
+
+ // get correct start for inner loop (see above)
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
+ {
+ // calculate size/radius
+ const double fSize(1.0 - (fOffsetStart + (fStripeWidth * innerLoop)));
+
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize),
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
+ }
+ }
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ if (bPenultimateUsed)
{
- const double fSize(1.0 - (fStepSize * a));
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize);
- aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
- const double fScaler(basegfx::utils::getRadialGradientAlpha(rUV, maGradientInfo));
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
+
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+ const double fScaler(basegfx::utils::getRadialGradientAlpha(rUV, maGradientInfo));
+ rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
double fAngle)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
{
maGradientInfo = basegfx::utils::createEllipticalODFGradientInfo(
rDefinitionRange,
basegfx::B2DVector(fOffsetX,fOffsetY),
- nSteps,
+ nRequestedSteps,
fBorder,
fAngle);
}
@@ -338,67 +508,107 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientElliptical::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maStart;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- double fWidth(1.0);
- double fHeight(1.0);
- double fIncrementX(0.0);
- double fIncrementY(0.0);
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
- if(maGradientInfo.getAspectRatio() > 1.0)
+ if (bPenultimateUsed)
{
- fIncrementY = fHeight / maGradientInfo.getSteps();
- fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
- }
- else
- {
- fIncrementX = fWidth / maGradientInfo.getSteps();
- fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
+ // temporarily add a ColorStop entry
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // prepare vars dependent on aspect ratio
+ const double fAR(maGradientInfo.getAspectRatio());
+ const bool bMTO(fAR > 1.0);
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{
- // next step
- fWidth -= fIncrementX;
- fHeight -= fIncrementY;
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
+
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight);
- aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+ // calculate StripeWidth
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
+
+ // get correct start for inner loop (see above)
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
+ {
+ // calculate offset position for entry
+ const double fSize(fOffsetStart + (fStripeWidth * innerLoop));
+
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform()
+ * basegfx::utils::createScaleB2DHomMatrix(
+ 1.0 - (bMTO ? fSize / fAR : fSize),
+ 1.0 - (bMTO ? fSize : fSize * fAR)),
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
+ }
+ }
+
+ if (bPenultimateUsed)
+ {
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
- const double fScaler(basegfx::utils::getEllipticalGradientAlpha(rUV, maGradientInfo));
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
+
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+ const double fScaler(basegfx::utils::getEllipticalGradientAlpha(rUV, maGradientInfo));
+ rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientSquare::GeoTexSvxGradientSquare(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
double fAngle)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
{
maGradientInfo = basegfx::utils::createSquareODFGradientInfo(
rDefinitionRange,
basegfx::B2DVector(fOffsetX,fOffsetY),
- nSteps,
+ nRequestedSteps,
fBorder,
fAngle);
}
@@ -408,49 +618,100 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientSquare::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maStart;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- const double fStepSize(1.0 / maGradientInfo.getSteps());
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ if (bPenultimateUsed)
{
- const double fSize(1.0 - (fStepSize * a));
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize);
- aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ // temporarily add a ColorStop entry
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
+ }
+
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
+ {
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
+
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
+
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+ // calculate StripeWidth
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
+
+ // get correct start for inner loop (see above)
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
+ {
+ // calculate size/radius
+ const double fSize(1.0 - (fOffsetStart + (fStripeWidth * innerLoop)));
+
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize),
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
+ }
+ }
+
+ if (bPenultimateUsed)
+ {
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
- const double fScaler(basegfx::utils::getSquareGradientAlpha(rUV, maGradientInfo));
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
+
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+ const double fScaler(basegfx::utils::getSquareGradientAlpha(rUV, maGradientInfo));
+ rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
GeoTexSvxGradientRect::GeoTexSvxGradientRect(
const basegfx::B2DRange& rDefinitionRange,
- const basegfx::BColor& rStart,
- const basegfx::BColor& rEnd,
- sal_uInt32 nSteps,
+ sal_uInt32 nRequestedSteps,
+ const basegfx::BColorStops& rColorStops,
double fBorder,
double fOffsetX,
double fOffsetY,
double fAngle)
- : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, fBorder)
+ : GeoTexSvxGradient(rDefinitionRange, nRequestedSteps, rColorStops, fBorder)
{
maGradientInfo = basegfx::utils::createRectangularODFGradientInfo(
rDefinitionRange,
basegfx::B2DVector(fOffsetX,fOffsetY),
- nSteps,
+ nRequestedSteps,
fBorder,
fAngle);
}
@@ -460,49 +721,90 @@ namespace drawinglayer::texture
}
void GeoTexSvxGradientRect::appendTransformationsAndColors(
- std::vector< B2DHomMatrixAndBColor >& rEntries,
- basegfx::BColor& rOuterColor)
+ const std::function<void(const basegfx::B2DHomMatrix& rMatrix, const basegfx::BColor& rColor)>& rCallback)
{
- rOuterColor = maStart;
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- if(!maGradientInfo.getSteps())
+ // only one color, done
+ if (mnColorStops.size() < 2)
return;
- double fWidth(1.0);
- double fHeight(1.0);
- double fIncrementX(0.0);
- double fIncrementY(0.0);
+ // check if we need last-ColorStop-correction
+ const bool bPenultimateUsed(mnColorStops.checkPenultimate());
- if(maGradientInfo.getAspectRatio() > 1.0)
- {
- fIncrementY = fHeight / maGradientInfo.getSteps();
- fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
- }
- else
+ if (bPenultimateUsed)
{
- fIncrementX = fWidth / maGradientInfo.getSteps();
- fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
+ // temporarily add a ColorStop entry
+ mnColorStops.emplace_back(1.0, mnColorStops.back().getStopColor());
}
- B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+ // prepare vars dependent on aspect ratio
+ const double fAR(maGradientInfo.getAspectRatio());
+ const bool bMTO(fAR > 1.0);
- for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
+ // outer loop over ColorStops, each is from cs_l to cs_r
+ for (auto cs_l(mnColorStops.begin()), cs_r(cs_l + 1); cs_r != mnColorStops.end(); cs_l++, cs_r++)
{
- // next step
- fWidth -= fIncrementX;
- fHeight -= fIncrementY;
+ // get offsets
+ const double fOffsetStart(cs_l->getStopOffset());
+ const double fOffsetEnd(cs_r->getStopOffset());
+
+ // same offset, empty BColorStopRange, continue with next step
+ if (basegfx::fTools::equal(fOffsetStart, fOffsetEnd))
+ continue;
+
+ // get colors & calculate steps
+ const basegfx::BColor aCStart(cs_l->getStopColor());
+ const basegfx::BColor aCEnd(cs_r->getStopColor());
+ const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+ maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+ // calculate StripeWidth
+ const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
- aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight);
- aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
- rEntries.push_back(aB2DHomMatrixAndBColor);
+ // get correct start for inner loop (see above)
+ const sal_uInt32 nStartInnerLoop(cs_l == mnColorStops.begin() ? 1 : 0);
+
+ for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
+ {
+ // calculate offset position for entry
+ const double fSize(fOffsetStart + (fStripeWidth * innerLoop));
+
+ // set and add at target
+ rCallback(
+ maGradientInfo.getTextureTransform()
+ * basegfx::utils::createScaleB2DHomMatrix(
+ 1.0 - (bMTO ? fSize / fAR : fSize),
+ 1.0 - (bMTO ? fSize : fSize * fAR)),
+ 1 == nSteps ? aCStart : basegfx::BColor(interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1))));
+ }
+ }
+
+ if (bPenultimateUsed)
+ {
+ // correct temporary change
+ mnColorStops.pop_back();
}
}
void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
{
- const double fScaler(basegfx::utils::getRectangularGradientAlpha(rUV, maGradientInfo));
+ // no color at all, done
+ if (mnColorStops.empty())
+ return;
- rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
+ // just single color, done
+ if (mnColorStops.size() < 2)
+ {
+ rBColor = mnColorStops.front().getStopColor();
+ return;
+ }
+
+ // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+ const double fScaler(basegfx::utils::getRectangularGradientAlpha(rUV, maGradientInfo));
+ rBColor = mnColorStops.getInterpolatedBColor(fScaler, mnRequestedSteps, maLastColorStopRange);
}
@@ -512,8 +814,6 @@ namespace drawinglayer::texture
double fDistance,
double fAngle)
: maOutputRange(rOutputRange),
- maTextureTransform(),
- maBackTextureTransform(),
mfDistance(0.1),
mfAngle(fAngle),
mnSteps(10),
@@ -631,8 +931,20 @@ namespace drawinglayer::texture
double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
{
- const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV);
- return fmod(aCoor.getY(), mfDistance);
+ // the below is an inlined and optimised version of
+ // const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV);
+ // return fmod(aCoor.getY(), mfDistance);
+
+ const basegfx::B2DHomMatrix& rMat = getBackTextureTransform();
+ double fX = rUV.getX();
+ double fY = rUV.getY();
+
+ double fTempY(
+ rMat.get(1, 0) * fX +
+ rMat.get(1, 1) * fY +
+ rMat.get(1, 2));
+
+ return fmod(fTempY, mfDistance);
}
const basegfx::B2DHomMatrix& GeoTexSvxHatch::getBackTextureTransform() const
@@ -712,7 +1024,7 @@ namespace drawinglayer::texture
sal_Int32 nPosX(0);
sal_Int32 nPosY(0);
- if(basegfx::fTools::more(fStartX, 0.0))
+ if(fStartX > 0.0)
{
const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1);
@@ -720,7 +1032,7 @@ namespace drawinglayer::texture
fStartX -= nDiff * fWidth;
}
- if(basegfx::fTools::less(fStartX + fWidth, 0.0))
+ if((fStartX + fWidth) < 0.0)
{
const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth)));
@@ -728,7 +1040,7 @@ namespace drawinglayer::texture
fStartX += nDiff * fWidth;
}
- if(basegfx::fTools::more(fStartY, 0.0))
+ if(fStartY > 0.0)
{
const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1);
@@ -736,7 +1048,7 @@ namespace drawinglayer::texture
fStartY -= nDiff * fHeight;
}
- if(basegfx::fTools::less(fStartY + fHeight, 0.0))
+ if((fStartY + fHeight) < 0.0)
{
const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight)));
diff --git a/drawinglayer/source/texture/texture3d.cxx b/drawinglayer/source/texture/texture3d.cxx
index 1ea09cb0fdd9..03af53afe09b 100644
--- a/drawinglayer/source/texture/texture3d.cxx
+++ b/drawinglayer/source/texture/texture3d.cxx
@@ -22,10 +22,11 @@
#include <algorithm>
#include <texture/texture3d.hxx>
-#include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapReadAccess.hxx>
#include <vcl/BitmapTools.hxx>
#include <primitive3d/hatchtextureprimitive3d.hxx>
#include <sal/log.hxx>
+#include <osl/diagnose.h>
namespace drawinglayer::texture
{
@@ -58,39 +59,16 @@ namespace drawinglayer::texture
GeoTexSvxBitmapEx::GeoTexSvxBitmapEx(
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
const basegfx::B2DRange& rRange)
- : maBitmapEx(rBitmapEx),
- maTransparence(),
+ : maBitmap(rBitmap),
maTopLeft(rRange.getMinimum()),
maSize(rRange.getRange()),
mfMulX(0.0),
- mfMulY(0.0),
- mbIsAlpha(false),
- mbIsTransparent(maBitmapEx.IsTransparent())
+ mfMulY(0.0)
{
- if(vcl::bitmap::convertBitmap32To24Plus8(maBitmapEx,maBitmapEx))
- mbIsTransparent = maBitmapEx.IsTransparent();
- // #121194# Todo: use alpha channel, too (for 3d)
- maBitmap = maBitmapEx.GetBitmap();
-
- if(mbIsTransparent)
- {
- if(maBitmapEx.IsAlpha())
- {
- mbIsAlpha = true;
- maTransparence = rBitmapEx.GetAlpha().GetBitmap();
- }
- else
- {
- maTransparence = rBitmapEx.GetMask();
- }
-
- mpReadTransparence = Bitmap::ScopedReadAccess(maTransparence);
- }
-
- if (!!maBitmap)
- mpReadBitmap = Bitmap::ScopedReadAccess(maBitmap);
+ if (!maBitmap.IsEmpty())
+ mpReadBitmap = maBitmap;
SAL_WARN_IF(!mpReadBitmap, "drawinglayer", "GeoTexSvxBitmapEx: Got no read access to Bitmap");
if (mpReadBitmap)
{
@@ -113,48 +91,6 @@ namespace drawinglayer::texture
{
}
- sal_uInt8 GeoTexSvxBitmapEx::impGetTransparence(sal_Int32 rX, sal_Int32 rY) const
- {
- switch(maBitmapEx.GetTransparentType())
- {
- case TransparentType::NONE:
- {
- break;
- }
- case TransparentType::Color:
- {
- const BitmapColor aBitmapColor(mpReadBitmap->GetColor(rY, rX));
-
- if(maBitmapEx.GetTransparentColor() == aBitmapColor)
- {
- return 255;
- }
-
- break;
- }
- case TransparentType::Bitmap:
- {
- OSL_ENSURE(mpReadTransparence, "OOps, transparence type Bitmap, but no read access created in the constructor (?)");
- const BitmapColor aBitmapColor(mpReadTransparence->GetPixel(rY, rX));
-
- if(mbIsAlpha)
- {
- return aBitmapColor.GetIndex();
- }
- else
- {
- if(0x00 != aBitmapColor.GetIndex())
- {
- return 255;
- }
- }
- break;
- }
- }
-
- return 0;
- }
-
bool GeoTexSvxBitmapEx::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const
{
if(mpReadBitmap)
@@ -187,12 +123,12 @@ namespace drawinglayer::texture
rBColor = aBSource;
- if(mbIsTransparent)
+ if (maBitmap.HasAlpha())
{
- // when we have a transparence, make use of it
- const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
+ // when we have alpha, make use of it
+ const sal_uInt8 aAlpha(aBMCol.GetAlpha());
- rfOpacity = (static_cast<double>(0xff - aLuminance) * (1.0 / 255.0));
+ rfOpacity = (static_cast<double>(aAlpha) * (1.0 / 255.0));
}
else
{
@@ -211,18 +147,18 @@ namespace drawinglayer::texture
if(impIsValid(rUV, nX, nY))
{
- if(mbIsTransparent)
+ const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
+ if (maBitmap.HasAlpha())
{
// this texture has an alpha part, use it
- const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
- const double fNewOpacity(static_cast<double>(0xff - aLuminance) * (1.0 / 255.0));
+ const sal_uInt8 aAlpha(aBMCol.GetAlpha());
+ const double fNewOpacity(static_cast<double>(aAlpha) * (1.0 / 255.0));
rfOpacity = 1.0 - ((1.0 - fNewOpacity) * (1.0 - rfOpacity));
}
else
{
// this texture is a color bitmap used as transparence map
- const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue());
rfOpacity = (static_cast<double>(0xff - aColor.GetLuminance()) * (1.0 / 255.0));
@@ -276,11 +212,11 @@ namespace drawinglayer::texture
}
GeoTexSvxBitmapExTiled::GeoTexSvxBitmapExTiled(
- const BitmapEx& rBitmapEx,
+ const Bitmap& rBitmap,
const basegfx::B2DRange& rRange,
double fOffsetX,
double fOffsetY)
- : GeoTexSvxBitmapEx(rBitmapEx, rRange),
+ : GeoTexSvxBitmapEx(rBitmap, rRange),
mfOffsetX(std::clamp(fOffsetX, 0.0, 1.0)),
mfOffsetY(std::clamp(fOffsetY, 0.0, 1.0)),
mbUseOffsetX(!basegfx::fTools::equalZero(mfOffsetX)),
@@ -327,7 +263,7 @@ namespace drawinglayer::texture
aOutlineRange,
aOutlineRange,
rHatch.getDistance(),
- fAngleA + F_PI2) );
+ fAngleA + M_PI_2) );
}
if(attribute::HatchStyle::Triple == rHatch.getStyle())
@@ -336,7 +272,7 @@ namespace drawinglayer::texture
aOutlineRange,
aOutlineRange,
rHatch.getDistance(),
- fAngleA + F_PI4) );
+ fAngleA + M_PI_4) );
}
}
diff --git a/drawinglayer/source/tools/converters.cxx b/drawinglayer/source/tools/converters.cxx
index ff9b79a688fa..fc6bef06fd21 100644
--- a/drawinglayer/source/tools/converters.cxx
+++ b/drawinglayer/source/tools/converters.cxx
@@ -23,153 +23,379 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+#include <comphelper/diagnose_ex.hxx>
-#include <converters.hxx>
+#include <drawinglayer/converters.hxx>
+#include <config_vclplug.h>
#ifdef DBG_UTIL
+#include <o3tl/environment.hxx>
#include <tools/stream.hxx>
-#include <vcl/pngwrite.hxx>
+#include <vcl/dibtools.hxx>
#endif
+namespace
+{
+bool implPrepareConversion(drawinglayer::primitive2d::Primitive2DContainer& rSequence,
+ sal_uInt32& rnDiscreteWidth, sal_uInt32& rnDiscreteHeight,
+ const sal_uInt32 nMaxSquarePixels)
+{
+ if (rSequence.empty())
+ return false;
+
+ if (rnDiscreteWidth <= 0 || rnDiscreteHeight <= 0)
+ return false;
+
+ const sal_uInt32 nViewVisibleArea(rnDiscreteWidth * rnDiscreteHeight);
+
+ if (nViewVisibleArea > nMaxSquarePixels)
+ {
+ // reduce render size
+ double fReduceFactor
+ = sqrt(static_cast<double>(nMaxSquarePixels) / static_cast<double>(nViewVisibleArea));
+ rnDiscreteWidth = basegfx::fround(static_cast<double>(rnDiscreteWidth) * fReduceFactor);
+ rnDiscreteHeight = basegfx::fround(static_cast<double>(rnDiscreteHeight) * fReduceFactor);
+
+ const drawinglayer::primitive2d::Primitive2DReference aEmbed(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ basegfx::utils::createScaleB2DHomMatrix(fReduceFactor, fReduceFactor),
+ std::move(rSequence)));
+
+ rSequence = drawinglayer::primitive2d::Primitive2DContainer{ aEmbed };
+ }
+
+ return true;
+}
+
+AlphaMask implcreateAlphaMask(drawinglayer::primitive2d::Primitive2DContainer& rSequence,
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D,
+ const Size& rSizePixel, bool bUseLuminance)
+{
+ ScopedVclPtrInstance<VirtualDevice> pContent;
+
+ // prepare vdev
+ if (!pContent->SetOutputSizePixel(rSizePixel, false))
+ {
+ SAL_WARN("vcl", "Cannot set VirtualDevice to size : " << rSizePixel.Width() << "x"
+ << rSizePixel.Height());
+ return AlphaMask();
+ }
+
+ // create pixel processor, also already takes care of AAing and
+ // checking the getOptionsDrawinglayer().IsAntiAliasing() switch. If
+ // not wanted, change after this call as needed
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pContentProcessor
+ = drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(*pContent,
+ rViewInformation2D);
+
+ // prepare for mask creation
+ pContent->SetMapMode(MapMode(MapUnit::MapPixel));
+
+ // set transparency to all white (fully transparent)
+ pContent->Erase();
+
+ basegfx::BColorModifierSharedPtr aBColorModifier;
+ if (bUseLuminance)
+ {
+ // new mode: bUseLuminance allows simple creation of alpha channels
+ // for any content (e.g. gradients)
+ aBColorModifier = std::make_shared<basegfx::BColorModifier_luminance_to_alpha>();
+ }
+ else
+ {
+ // Embed primitives to paint them black (fully opaque)
+ aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0.0, 0.0, 0.0));
+ }
+ const drawinglayer::primitive2d::Primitive2DReference xRef(
+ new drawinglayer::primitive2d::ModifiedColorPrimitive2D(std::move(rSequence),
+ std::move(aBColorModifier)));
+ const drawinglayer::primitive2d::Primitive2DContainer xSeq{ xRef };
+
+ // render
+ pContentProcessor->process(xSeq);
+ pContentProcessor.reset();
+
+ // get alpha channel from vdev
+ pContent->EnableMapMode(false);
+ const Point aEmptyPoint;
+
+ // Convert from transparency->alpha.
+ // FIXME in theory I should be able to directly construct alpha by using black as background
+ // and white as foreground, but that doesn't work for some reason.
+ Bitmap aContentBitmap = pContent->GetBitmap(aEmptyPoint, rSizePixel);
+ aContentBitmap.Invert();
+
+ return AlphaMask(aContentBitmap);
+}
+}
+
namespace drawinglayer
{
+AlphaMask createAlphaMask(drawinglayer::primitive2d::Primitive2DContainer&& rSeq,
+ const geometry::ViewInformation2D& rViewInformation2D,
+ sal_uInt32 nDiscreteWidth, sal_uInt32 nDiscreteHeight,
+ sal_uInt32 nMaxSquarePixels, bool bUseLuminance)
+{
+ drawinglayer::primitive2d::Primitive2DContainer aSequence(std::move(rSeq));
- BitmapEx convertToBitmapEx(
- const drawinglayer::primitive2d::Primitive2DContainer& rSeq,
- const geometry::ViewInformation2D& rViewInformation2D,
- sal_uInt32 nDiscreteWidth,
- sal_uInt32 nDiscreteHeight,
- sal_uInt32 nMaxQuadratPixels)
+ if (!implPrepareConversion(aSequence, nDiscreteWidth, nDiscreteHeight, nMaxSquarePixels))
{
- BitmapEx aRetval;
+ return AlphaMask();
+ }
- if(!rSeq.empty() && nDiscreteWidth && nDiscreteHeight)
- {
- // get destination size in pixels
- const MapMode aMapModePixel(MapUnit::MapPixel);
- const sal_uInt32 nViewVisibleArea(nDiscreteWidth * nDiscreteHeight);
- drawinglayer::primitive2d::Primitive2DContainer aSequence(rSeq);
-
- if(nViewVisibleArea > nMaxQuadratPixels)
- {
- // reduce render size
- double fReduceFactor = sqrt(static_cast<double>(nMaxQuadratPixels) / static_cast<double>(nViewVisibleArea));
- nDiscreteWidth = basegfx::fround(static_cast<double>(nDiscreteWidth) * fReduceFactor);
- nDiscreteHeight = basegfx::fround(static_cast<double>(nDiscreteHeight) * fReduceFactor);
-
- const drawinglayer::primitive2d::Primitive2DReference aEmbed(
- new drawinglayer::primitive2d::TransformPrimitive2D(
- basegfx::utils::createScaleB2DHomMatrix(fReduceFactor, fReduceFactor),
- rSeq));
-
- aSequence = drawinglayer::primitive2d::Primitive2DContainer { aEmbed };
- }
-
- const Point aEmptyPoint;
- const Size aSizePixel(nDiscreteWidth, nDiscreteHeight);
- ScopedVclPtrInstance< VirtualDevice > pContent;
-
- // prepare vdev
- pContent->SetOutputSizePixel(aSizePixel, false);
- pContent->SetMapMode(aMapModePixel);
-
- // set to all white
- pContent->SetBackground(Wallpaper(COL_WHITE));
- pContent->Erase();
-
- // create pixel processor, also already takes care of AAing and
- // checking the getOptionsDrawinglayer().IsAntiAliasing() switch. If
- // not wanted, change after this call as needed
- std::unique_ptr<processor2d::BaseProcessor2D> pContentProcessor = processor2d::createPixelProcessor2DFromOutputDevice(
- *pContent,
- rViewInformation2D);
-
- if(pContentProcessor)
- {
-#ifdef DBG_UTIL
- static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
-#endif
- // render content
- pContentProcessor->process(aSequence);
+ const Size aSizePixel(nDiscreteWidth, nDiscreteHeight);
- // get content
- pContent->EnableMapMode(false);
- const Bitmap aContent(pContent->GetBitmap(aEmptyPoint, aSizePixel));
+ return implcreateAlphaMask(aSequence, rViewInformation2D, aSizePixel, bUseLuminance);
+}
-#ifdef DBG_UTIL
- if(bDoSaveForVisualControl)
- {
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\test_content.png"
-#else
- "~/test_content.png"
-#endif
- , StreamMode::WRITE|StreamMode::TRUNC);
- BitmapEx aContentEx(aContent);
- vcl::PNGWriter aPNGWriter(aContentEx);
- aPNGWriter.Write(aNew);
- }
+Bitmap convertToBitmap(drawinglayer::primitive2d::Primitive2DContainer&& rSeq,
+ const geometry::ViewInformation2D& rViewInformation2D,
+ sal_uInt32 nDiscreteWidth, sal_uInt32 nDiscreteHeight,
+ sal_uInt32 nMaxSquarePixels, bool bForceAlphaMaskCreation)
+{
+ drawinglayer::primitive2d::Primitive2DContainer aSequence(std::move(rSeq));
+
+ if (!implPrepareConversion(aSequence, nDiscreteWidth, nDiscreteHeight, nMaxSquarePixels))
+ {
+ return Bitmap();
+ }
+
+#if USE_HEADLESS_CODE
+ // shortcut: try to directly create a PixelProcessor2D with
+ // RGBA support - that's what we need
+ // Currently only implemented for CairoSDPR, so add code only
+ // for USE_HEADLESS_CODE, but is designed as a general functionality
+ std::unique_ptr<processor2d::BaseProcessor2D> pRGBAProcessor
+ = processor2d::createPixelProcessor2DFromScratch(rViewInformation2D, nDiscreteWidth, nDiscreteHeight, true);
+ if (pRGBAProcessor)
+ {
+ // render content
+ pRGBAProcessor->process(aSequence);
+
+ // create final Bitmap result (content)
+ const Bitmap aRetval(processor2d::extractBitmapFromBaseProcessor2D(pRGBAProcessor));
+
+ // check if we have a result and return if so
+ if (!aRetval.IsEmpty())
+ return aRetval;
+ }
#endif
- // prepare for mask creation
- pContent->SetMapMode(aMapModePixel);
-
- // set alpha to all white (fully transparent)
- pContent->Erase();
-
- // embed primitives to paint them black
- const primitive2d::Primitive2DReference xRef(
- new primitive2d::ModifiedColorPrimitive2D(
- aSequence,
- std::make_shared<basegfx::BColorModifier_replace>(
- basegfx::BColor(0.0, 0.0, 0.0))));
- const primitive2d::Primitive2DContainer xSeq { xRef };
-
- // render
- pContentProcessor->process(xSeq);
- pContentProcessor.reset();
-
- // get alpha channel from vdev
- pContent->EnableMapMode(false);
- const Bitmap aAlpha(pContent->GetBitmap(aEmptyPoint, aSizePixel));
+
+ const Point aEmptyPoint;
+ const Size aSizePixel(nDiscreteWidth, nDiscreteHeight);
+
+ // Create target VirtualDevice. Go back to using a simple RGB
+ // target version (compared with former version, see history).
+ // Reasons are manyfold:
+ // - Avoid the RGBA mode for VirtualDevice (two VDevs)
+ // - It's not suggested to be used outside presentation engine
+ // - It only works *by chance* with VCLPrimitiveRenderer
+ // - Usage of two-VDev alpha-VDev avoided alpha blending against
+ // COL_WHITE in the 1st layer of targets (not in buffers below)
+ // but is kind of a 'hack' doing so
+ // - Other renderers (system-dependent PrimitiveRenderers, other
+ // than the VCL-based ones) will probably not support splitted
+ // VDevs for content/alpha, so require a method that works with
+ // RGB targeting (for now)
+ // - Less resource usage, better speed (no 2 VDevs, no merge of
+ // AlphaChannels)
+ // As long as not all our mechanisms are changed to RGBA completely,
+ // mixing these is just too dangerous and expensive and may to wrong
+ // or deliver bad quality results.
+ // Nonetheless we need a RGBA result here. Luckily we are able to
+ // create a complete and valid AlphaChannel using 'createAlphaMask'
+ // above.
+ // When we know the content (RGB result from renderer), alpha
+ // (result from createAlphaMask) and the start condition (content
+ // rendered against COL_WHITE), it is possible to calculate back
+ // the content, quasi 'remove' that initial blending against
+ // COL_WHITE.
+ // That is what the helper Bitmap::RemoveBlendedStartColor does.
+ // Luckily we only need it for this 'convertToBitmapEx', not in
+ // any other rendering. It could be further optimized, too.
+ // This gives good results, it is in principle comparable with
+ // the results using pre-multiplied alpha tooling, also reducing
+ // the range of values where high alpha values are used.
+ ScopedVclPtrInstance<VirtualDevice> pContent(*Application::GetDefaultDevice());
+
+ // prepare vdev
+ if (!pContent->SetOutputSizePixel(aSizePixel, false))
+ {
+ SAL_WARN("vcl", "Cannot set VirtualDevice to size : " << aSizePixel.Width() << "x"
+ << aSizePixel.Height());
+ return Bitmap();
+ }
+
+ // We map to pixel, use that MapMode. Init by erasing.
+ pContent->SetMapMode(MapMode(MapUnit::MapPixel));
+ pContent->Erase();
+
+ // create pixel processor, also already takes care of AAing and
+ // checking the getOptionsDrawinglayer().IsAntiAliasing() switch. If
+ // not wanted, change after this call as needed
+ std::unique_ptr<processor2d::BaseProcessor2D> pContentProcessor
+ = processor2d::createPixelProcessor2DFromOutputDevice(*pContent, rViewInformation2D);
+
+ // render content
+ pContentProcessor->process(aSequence);
+
+ // create final Bitmap result (content)
+ Bitmap aRetval(pContent->GetBitmap(aEmptyPoint, aSizePixel));
+
#ifdef DBG_UTIL
- if(bDoSaveForVisualControl)
- {
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\test_alpha.png"
-#else
- "~/test_alpha.png"
-#endif
- , StreamMode::WRITE|StreamMode::TRUNC);
- BitmapEx aAlphaEx(aAlpha);
- vcl::PNGWriter aPNGWriter(aAlphaEx);
- aPNGWriter.Write(aNew);
- }
+ static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
+ if (bDoSaveForVisualControl)
+ {
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
+ {
+ SvFileStream aNew(sDumpPath + "test_content.bmp",
+ StreamMode::WRITE | StreamMode::TRUNC);
+ WriteDIB(aRetval, aNew, false, true);
+ }
+ }
#endif
- // create BitmapEx result
- aRetval = BitmapEx(aContent, AlphaMask(aAlpha));
+ // Create the AlphaMask using a method that does this always correct (also used
+ // now in GlowPrimitive2D and ShadowPrimitive2D which both only need the
+ // AlphaMask to do their job, so speeding that up, too).
+ AlphaMask aAlpha(implcreateAlphaMask(aSequence, rViewInformation2D, aSizePixel, false));
+
#ifdef DBG_UTIL
- if(bDoSaveForVisualControl)
- {
- SvFileStream aNew(
-#ifdef _WIN32
- "c:\\test_combined.png"
-#else
- "~/test_combined.png"
-#endif
- , StreamMode::WRITE|StreamMode::TRUNC);
- vcl::PNGWriter aPNGWriter(aRetval);
- aPNGWriter.Write(aNew);
- }
-#endif
- }
+ if (bDoSaveForVisualControl)
+ {
+ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
+ static const OUString sDumpPath(o3tl::getEnvironment(u"VCL_DUMP_BMP_PATH"_ustr));
+ if (!sDumpPath.isEmpty())
+ {
+ SvFileStream aNew(sDumpPath + "test_alpha.bmp", StreamMode::WRITE | StreamMode::TRUNC);
+ WriteDIB(aAlpha.GetBitmap(), aNew, false, true);
}
+ }
+#endif
+ if (bForceAlphaMaskCreation || aAlpha.hasAlpha())
+ {
+ // Need to correct content using known alpha to get to background-free
+ // RGBA result, usable e.g. in PNG export(s) or convert-to-bitmap.
+ // Now that vcl supports bitmaps with an alpha channel, only apply
+ // this correction to bitmaps without an alpha channel.
+ if (pContent->GetBitCount() < 32)
+ {
+ aRetval.RemoveBlendedStartColor(COL_BLACK, aAlpha);
+ }
+ else
+ {
+ // tdf#157558 invert and remove blended white color
+ // Before commit 81994cb2b8b32453a92bcb011830fcb884f22ff3,
+ // RemoveBlendedStartColor(COL_BLACK, aAlpha) would darken
+ // the bitmap when running a slideshow, printing, or exporting
+ // to PDF. To get the same effect, the alpha mask must be
+ // inverted, RemoveBlendedStartColor(COL_WHITE, aAlpha)
+ // called, and the alpha mask uninverted.
+ aAlpha.Invert();
+ aRetval.RemoveBlendedStartColor(COL_WHITE, aAlpha);
+ aAlpha.Invert();
+ }
+ // return combined result
+ return Bitmap(aRetval, aAlpha);
+ }
+ else
return aRetval;
+}
+
+Bitmap convertPrimitive2DContainerToBitmap(primitive2d::Primitive2DContainer&& rSequence,
+ const basegfx::B2DRange& rTargetRange,
+ sal_uInt32 nMaximumQuadraticPixels,
+ const o3tl::Length eTargetUnit,
+ const std::optional<Size>& rTargetDPI)
+{
+ if (rSequence.empty())
+ return Bitmap();
+
+ try
+ {
+ css::geometry::RealRectangle2D aRealRect;
+ aRealRect.X1 = rTargetRange.getMinX();
+ aRealRect.Y1 = rTargetRange.getMinY();
+ aRealRect.X2 = rTargetRange.getMaxX();
+ aRealRect.Y2 = rTargetRange.getMaxY();
+
+ // get system DPI
+ Size aDPI(
+ Application::GetDefaultDevice()->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
+ if (rTargetDPI.has_value())
+ {
+ aDPI = *rTargetDPI;
+ }
+
+ ::sal_uInt32 DPI_X = aDPI.getWidth();
+ ::sal_uInt32 DPI_Y = aDPI.getHeight();
+ const basegfx::B2DRange aRange(aRealRect.X1, aRealRect.Y1, aRealRect.X2, aRealRect.Y2);
+ const double fWidth(aRange.getWidth());
+ const double fHeight(aRange.getHeight());
+
+ if (fWidth <= 0.0 || fHeight <= 0.0 || basegfx::fTools::equalZero(fWidth) || basegfx::fTools::equalZero(fHeight))
+ return Bitmap();
+
+ if (0 == DPI_X)
+ {
+ DPI_X = 75;
+ }
+
+ if (0 == DPI_Y)
+ {
+ DPI_Y = 75;
+ }
+
+ if (0 == nMaximumQuadraticPixels)
+ {
+ nMaximumQuadraticPixels = 500000;
+ }
+
+ const auto aViewInformation2D = geometry::createViewInformation2D({});
+ const sal_uInt32 nDiscreteWidth(
+ basegfx::fround(o3tl::convert(fWidth, eTargetUnit, o3tl::Length::in) * DPI_X));
+ const sal_uInt32 nDiscreteHeight(
+ basegfx::fround(o3tl::convert(fHeight, eTargetUnit, o3tl::Length::in) * DPI_Y));
+
+ basegfx::B2DHomMatrix aEmbedding(
+ basegfx::utils::createTranslateB2DHomMatrix(-aRange.getMinX(), -aRange.getMinY()));
+
+ aEmbedding.scale(nDiscreteWidth / fWidth, nDiscreteHeight / fHeight);
+
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(aEmbedding, std::move(rSequence)));
+ primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ Bitmap aBitmap(convertToBitmap(std::move(xEmbedSeq), aViewInformation2D,
+ nDiscreteWidth, nDiscreteHeight,
+ nMaximumQuadraticPixels));
+
+ if (aBitmap.IsEmpty())
+ return Bitmap();
+ aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ aBitmap.SetPrefSize(Size(basegfx::fround<tools::Long>(fWidth), basegfx::fround<tools::Long>(fHeight)));
+
+ return aBitmap;
+ }
+ catch (const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("vcl", "Got no graphic::XPrimitive2DRenderer!");
}
+ catch (const std::exception& e)
+ {
+ SAL_WARN("vcl", "Got no graphic::XPrimitive2DRenderer! : " << e.what());
+ }
+
+ return Bitmap();
+}
} // end of namespace drawinglayer
diff --git a/drawinglayer/source/tools/emfpbrush.cxx b/drawinglayer/source/tools/emfpbrush.cxx
index ca0c27b23ecf..786209bb641b 100644
--- a/drawinglayer/source/tools/emfpbrush.cxx
+++ b/drawinglayer/source/tools/emfpbrush.cxx
@@ -52,13 +52,13 @@ namespace emfplushelper
{
switch (type)
{
- case BrushTypeSolidColor: return "BrushTypeSolidColor";
- case BrushTypeHatchFill: return "BrushTypeHatchFill";
- case BrushTypeTextureFill: return "BrushTypeTextureFill";
- case BrushTypePathGradient: return "BrushTypePathGradient";
- case BrushTypeLinearGradient: return "BrushTypeLinearGradient";
+ case BrushTypeSolidColor: return u"BrushTypeSolidColor"_ustr;
+ case BrushTypeHatchFill: return u"BrushTypeHatchFill"_ustr;
+ case BrushTypeTextureFill: return u"BrushTypeTextureFill"_ustr;
+ case BrushTypePathGradient: return u"BrushTypePathGradient"_ustr;
+ case BrushTypeLinearGradient: return u"BrushTypeLinearGradient"_ustr;
}
- return "";
+ return u""_ustr;
}
void EMFPBrush::Read(SvStream& s, EmfPlusHelperData const & rR)
@@ -67,8 +67,8 @@ namespace emfplushelper
s.ReadUInt32(header).ReadUInt32(type);
- SAL_INFO("drawinglayer", "EMF+\t\t\tHeader: 0x" << std::hex << header);
- SAL_INFO("drawinglayer", "EMF+\t\t\tType: " << BrushTypeToString(type) << "(0x" << type << ")" << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\tHeader: 0x" << std::hex << header);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\tType: " << BrushTypeToString(type) << "(0x" << type << ")" << std::dec);
switch (type)
{
@@ -77,8 +77,8 @@ namespace emfplushelper
sal_uInt32 color;
s.ReadUInt32(color);
- solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tSolid color: 0x" << std::hex << color << std::dec);
+ solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tSolid color: 0x" << std::hex << color << std::dec);
break;
}
case BrushTypeHatchFill:
@@ -91,53 +91,48 @@ namespace emfplushelper
s.ReadUInt32(backgroundColor);
hatchStyle = static_cast<EmfPlusHatchStyle>(style);
- solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
- secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tHatch style: 0x" << std::hex << style);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tForeground color: 0x" << solidColor.AsRGBHexString());
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tBackground color: 0x" << secondColor.AsRGBHexString());
+ solidColor = ::Color(ColorAlpha, (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
+ secondColor = ::Color(ColorAlpha, (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tHatch style: 0x" << std::hex << style);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tForeground color: 0x" << solidColor.AsRGBHexString());
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tBackground color: 0x" << secondColor.AsRGBHexString());
break;
}
case BrushTypeTextureFill:
{
- SAL_WARN("drawinglayer", "EMF+\tTODO: implement BrushTypeTextureFill brush");
+ SAL_WARN("drawinglayer.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush");
break;
}
case BrushTypePathGradient:
{
s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec);
sal_uInt32 color;
s.ReadUInt32(color);
- solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec);
+ solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec);
s.ReadFloat(firstPointX).ReadFloat(firstPointY);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tCenter point: " << firstPointX << "," << firstPointY);
- s.ReadInt32(surroundColorsNumber);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber);
-
- if (surroundColorsNumber<0 || o3tl::make_unsigned(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
- {
- surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
- }
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter point: " << firstPointX << "," << firstPointY);
+ s.ReadUInt32(surroundColorsNumber);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber);
surroundColors.reset( new ::Color[surroundColorsNumber] );
- for (int i = 0; i < surroundColorsNumber; i++)
+ for (sal_uInt32 i = 0; i < surroundColorsNumber; i++)
{
s.ReadUInt32(color);
- surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ surroundColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
if (i == 0)
secondColor = surroundColors[0];
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tSurround color[" << i << "]: 0x" << std::hex << color << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tSurround color[" << i << "]: 0x" << std::hex << color << std::dec);
}
- if (additionalFlags & 0x01)
+ if (additionalFlags & 0x01) // BrushDataPath
{
sal_Int32 pathLength;
s.ReadInt32(pathLength);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPath length: " << pathLength);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath length: " << pathLength);
sal_uInt64 const pos = s.Tell();
@@ -145,10 +140,10 @@ namespace emfplushelper
sal_Int32 pathPoints, pathFlags;
s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPath (brush path gradient)");
- SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tHeader: 0x" << std::hex << pathHeader);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tPoints: " << std::dec << pathPoints);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tAdditional flags: 0x" << std::hex << pathFlags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath (brush path gradient)");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tHeader: 0x" << std::hex << pathHeader);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tPoints: " << std::dec << pathPoints);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tAdditional flags: 0x" << std::hex << pathFlags << std::dec);
path.reset( new EMFPPath(pathPoints) );
path->Read(s, pathFlags);
@@ -158,7 +153,7 @@ namespace emfplushelper
const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
aWidth = aBounds.getWidth();
aHeight = aBounds.getHeight();
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
<< aBounds.getWidth() << "x" << aBounds.getHeight());
}
else
@@ -167,7 +162,7 @@ namespace emfplushelper
s.ReadInt32(boundaryPointCount);
sal_uInt64 const pos = s.Tell();
- SAL_INFO("drawinglayer", "EMF+\t use boundary, points: " << boundaryPointCount);
+ SAL_INFO("drawinglayer.emf", "EMF+\t use boundary, points: " << boundaryPointCount);
path.reset( new EMFPPath(boundaryPointCount) );
path->Read(s, 0x0);
@@ -176,68 +171,61 @@ namespace emfplushelper
const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
aWidth = aBounds.getWidth();
aHeight = aBounds.getHeight();
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
<< aBounds.getWidth() << "x" << aBounds.getHeight());
}
- if (additionalFlags & 0x02)
+ if (additionalFlags & 0x02) // BrushDataTransform
{
EmfPlusHelperData::readXForm(s, brush_transformation);
hasTransformation = true;
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
}
- if (additionalFlags & 0x08)
+ // BrushDataPresetColors and BrushDataBlendFactorsH
+ if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
{
- s.ReadInt32(blendPoints);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tuse blend, points: " << blendPoints);
- if (blendPoints<0 || o3tl::make_unsigned(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
- blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+ SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
+ return;
+ }
+ if (additionalFlags & 0x08) // BrushDataBlendFactorsH
+ {
+ s.ReadUInt32(blendPoints);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tuse blend, points: " << blendPoints);
blendPositions.reset( new float[2 * blendPoints] );
blendFactors = blendPositions.get() + blendPoints;
- for (int i = 0; i < blendPoints; i++)
+ for (sal_uInt32 i = 0; i < blendPoints; i++)
{
s.ReadFloat(blendPositions[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tposition[" << i << "]: " << blendPositions[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tposition[" << i << "]: " << blendPositions[i]);
}
- for (int i = 0; i < blendPoints; i++)
+ for (sal_uInt32 i = 0; i < blendPoints; i++)
{
s.ReadFloat(blendFactors[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
}
}
- if (additionalFlags & 0x04)
+ if (additionalFlags & 0x04) // BrushDataPresetColors
{
- s.ReadInt32(colorblendPoints);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
-
- if (colorblendPoints<0 || o3tl::make_unsigned(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
- {
- colorblendPoints = SAL_MAX_INT32 / sizeof(float);
- }
-
- if (o3tl::make_unsigned(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color))
- {
- colorblendPoints = SAL_MAX_INT32 / sizeof(::Color);
- }
-
+ s.ReadUInt32(colorblendPoints);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
colorblendPositions.reset( new float[colorblendPoints] );
colorblendColors.reset( new ::Color[colorblendPoints] );
- for (int i = 0; i < colorblendPoints; i++)
+ for (sal_uInt32 i = 0; i < colorblendPoints; i++)
{
s.ReadFloat(colorblendPositions[i]);
- SAL_INFO("drawinglayer", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
}
- for (int i = 0; i < colorblendPoints; i++)
+ for (sal_uInt32 i = 0; i < colorblendPoints; i++)
{
s.ReadUInt32(color);
- colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
+ colorblendColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
}
}
@@ -246,80 +234,73 @@ namespace emfplushelper
case BrushTypeLinearGradient:
{
s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tLinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec << ", wrapMode: " << wrapMode);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tLinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec << ", wrapMode: " << wrapMode);
s.ReadFloat(firstPointX).ReadFloat(firstPointY).ReadFloat(aWidth).ReadFloat(aHeight);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY
<< ", size " << aWidth << "x" << aHeight);
sal_uInt32 color;
s.ReadUInt32(color);
- solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec);
+ solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec);
s.ReadUInt32(color);
- secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tsecond color: 0x" << std::hex << color << std::dec);
+ secondColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tsecond color: 0x" << std::hex << color << std::dec);
// repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
s.ReadUInt32(color);
s.ReadUInt32(color);
- if (additionalFlags & 0x02)
+ if (additionalFlags & 0x02) //BrushDataTransform
{
EmfPlusHelperData::readXForm(s, brush_transformation);
hasTransformation = true;
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
+ }
+ // BrushDataPresetColors and BrushDataBlendFactorsH
+ if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
+ {
+ SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
+ return;
}
- if (additionalFlags & 0x08)
+ if (additionalFlags & 0x08) // BrushDataBlendFactorsH
{
- s.ReadInt32(blendPoints);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse blend, points: " << blendPoints);
- if (blendPoints<0 || o3tl::make_unsigned(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
- blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+ s.ReadUInt32(blendPoints);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse blend, points: " << blendPoints);
blendPositions.reset( new float[2 * blendPoints] );
blendFactors = blendPositions.get() + blendPoints;
- for (int i = 0; i < blendPoints; i++)
+ for (sal_uInt32 i = 0; i < blendPoints; i++)
{
s.ReadFloat(blendPositions[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPosition[" << i << "]: " << blendPositions[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPosition[" << i << "]: " << blendPositions[i]);
}
- for (int i = 0; i < blendPoints; i++)
+ for (sal_uInt32 i = 0; i < blendPoints; i++)
{
s.ReadFloat(blendFactors[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
}
}
if (additionalFlags & 0x04)
{
- s.ReadInt32(colorblendPoints);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
-
- if (colorblendPoints<0 || o3tl::make_unsigned(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
- {
- colorblendPoints = SAL_MAX_INT32 / sizeof(float);
- }
-
- if (o3tl::make_unsigned(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color))
- {
- colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color);
- }
-
+ s.ReadUInt32(colorblendPoints);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
colorblendPositions.reset( new float[colorblendPoints] );
colorblendColors.reset( new ::Color[colorblendPoints] );
- for (int i = 0; i < colorblendPoints; i++)
+ for (sal_uInt32 i = 0; i < colorblendPoints; i++)
{
s.ReadFloat(colorblendPositions[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tPosition[" << i << "]: " << colorblendPositions[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPosition[" << i << "]: " << colorblendPositions[i]);
}
- for (int i = 0; i < colorblendPoints; i++)
+ for (sal_uInt32 i = 0; i < colorblendPoints; i++)
{
s.ReadUInt32(color);
- colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
+ colorblendColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
}
}
@@ -327,7 +308,7 @@ namespace emfplushelper
}
default:
{
- SAL_WARN("drawinglayer", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
+ SAL_WARN("drawinglayer.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
}
}
}
diff --git a/drawinglayer/source/tools/emfpbrush.hxx b/drawinglayer/source/tools/emfpbrush.hxx
index 49706c615898..aee3fe02f60e 100644
--- a/drawinglayer/source/tools/emfpbrush.hxx
+++ b/drawinglayer/source/tools/emfpbrush.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPBRUSH_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPBRUSH_HXX
+#pragma once
#include "emfphelperdata.hxx"
#include <tools/color.hxx>
@@ -91,7 +90,7 @@ namespace emfplushelper
BrushTypeLinearGradient = 0x00000004
};
- struct EMFPPath;
+ class EMFPPath;
struct EMFPBrush : public EMFPObject
{
@@ -105,13 +104,13 @@ namespace emfplushelper
::Color secondColor; // first color is stored in solidColor;
basegfx::B2DHomMatrix brush_transformation;
bool hasTransformation;
- sal_Int32 blendPoints;
+ sal_uInt32 blendPoints;
std::unique_ptr<float[]> blendPositions;
float* blendFactors;
- sal_Int32 colorblendPoints;
+ sal_uInt32 colorblendPoints;
std::unique_ptr<float[]> colorblendPositions;
std::unique_ptr<::Color[]> colorblendColors;
- sal_Int32 surroundColorsNumber;
+ sal_uInt32 surroundColorsNumber;
std::unique_ptr<::Color[]> surroundColors;
std::unique_ptr<EMFPPath> path;
EmfPlusHatchStyle hatchStyle;
@@ -126,6 +125,4 @@ namespace emfplushelper
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx
index 98af0f5241c7..e457a36cc2c4 100644
--- a/drawinglayer/source/tools/emfpcustomlinecap.cxx
+++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx
@@ -21,6 +21,7 @@
#include "emfpcustomlinecap.hxx"
#include "emfppath.hxx"
#include "emfppen.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace ::com::sun::star;
using namespace ::basegfx;
@@ -39,33 +40,27 @@ namespace emfplushelper
, strokeEndCap(0)
, strokeJoin(0)
, miterLimit(0.0)
+ , widthScale(0.0)
, mbIsFilled(false)
{
}
- void EMFPCustomLineCap::SetAttributes(rendering::StrokeAttributes& aAttributes)
- {
- aAttributes.StartCapType = EMFPPen::lcl_convertStrokeCap(strokeStartCap);
- aAttributes.EndCapType = EMFPPen::lcl_convertStrokeCap(strokeEndCap);
- aAttributes.JoinType = EMFPPen::lcl_convertLineJoinType(strokeJoin);
-
- aAttributes.MiterLimit = miterLimit;
- }
-
void EMFPCustomLineCap::ReadPath(SvStream& s, EmfPlusHelperData const & rR, bool bFill)
{
sal_Int32 pathLength;
s.ReadInt32(pathLength);
- SAL_INFO("drawinglayer", "EMF+\t\tpath length: " << pathLength);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tpath length: " << pathLength);
sal_uInt32 pathHeader;
sal_Int32 pathPoints, pathFlags;
s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
- SAL_INFO("drawinglayer", "EMF+\t\tpath (custom cap line path)");
- SAL_INFO("drawinglayer", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tpath (custom cap line path)");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
EMFPPath path(pathPoints);
path.Read(s, pathFlags);
polygon = path.GetPolygon(rR, false);
+ // rotate polygon by 180 degrees
+ polygon.transform(basegfx::utils::createRotateB2DHomMatrix(M_PI));
mbIsFilled = bFill;
}
@@ -73,14 +68,13 @@ namespace emfplushelper
{
sal_uInt32 header;
s.ReadUInt32(header).ReadUInt32(type);
- SAL_INFO("drawinglayer", "EMF+\t\tcustom cap");
- SAL_INFO("drawinglayer", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tcustom cap");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
if (type == EmfPlusCustomLineCapDataTypeDefault)
{
sal_uInt32 customLineCapDataFlags, baseCap;
float baseInset;
- float widthScale;
float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
s.ReadUInt32(customLineCapDataFlags).ReadUInt32(baseCap).ReadFloat(baseInset)
@@ -88,14 +82,9 @@ namespace emfplushelper
.ReadFloat(miterLimit).ReadFloat(widthScale)
.ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(strokeHotSpotX).ReadFloat(strokeHotSpotY);
- SAL_INFO("drawinglayer", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
- SAL_INFO("drawinglayer", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
- SAL_INFO("drawinglayer", "EMF+\t\tbaseInset: " << baseInset);
- SAL_INFO("drawinglayer", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
- SAL_INFO("drawinglayer", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
- SAL_INFO("drawinglayer", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
- SAL_INFO("drawinglayer", "EMF+\t\tmiterLimit: " << miterLimit);
- SAL_INFO("drawinglayer", "EMF+\t\twidthScale: " << widthScale);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tbaseInset: " << baseInset);
if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
{
@@ -112,16 +101,20 @@ namespace emfplushelper
// TODO only reads the data, does not use them [I've had
// no test document to be able to implement it]
- sal_Int32 width, height, middleInset, fillState, lineStartCap;
- sal_Int32 lineEndCap, lineJoin, widthScale;
- float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
+ sal_Int32 fillState;
+ float width, height, middleInset, unusedHotSpot;
- s.ReadInt32(width).ReadInt32(height).ReadInt32(middleInset).ReadInt32(fillState).ReadInt32(lineStartCap)
- .ReadInt32(lineEndCap).ReadInt32(lineJoin).ReadFloat(miterLimit).ReadInt32(widthScale)
- .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(lineHotSpotX).ReadFloat(lineHotSpotY);
+ s.ReadFloat(width).ReadFloat(height).ReadFloat(middleInset).ReadInt32(fillState).ReadUInt32(strokeStartCap)
+ .ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin).ReadFloat(miterLimit).ReadFloat(widthScale)
+ .ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot);
- SAL_INFO("drawinglayer", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
}
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tmiterLimit: " << miterLimit);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\twidthScale: " << widthScale);
}
}
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.hxx b/drawinglayer/source/tools/emfpcustomlinecap.hxx
index 3fd2d2fc64a8..22ed6be6dd4d 100644
--- a/drawinglayer/source/tools/emfpcustomlinecap.hxx
+++ b/drawinglayer/source/tools/emfpcustomlinecap.hxx
@@ -17,10 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPCUSTOMLINECAP_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPCUSTOMLINECAP_HXX
+#pragma once
-#include <com/sun/star/rendering/StrokeAttributes.hpp>
#include "emfphelperdata.hxx"
namespace emfplushelper
@@ -29,18 +27,15 @@ namespace emfplushelper
{
sal_uInt32 type;
sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
- float miterLimit;
+ float miterLimit, widthScale;
basegfx::B2DPolyPolygon polygon;
bool mbIsFilled;
EMFPCustomLineCap();
- void SetAttributes(com::sun::star::rendering::StrokeAttributes& aAttributes);
void ReadPath(SvStream& s, EmfPlusHelperData const & rR, bool bFill);
void Read(SvStream& s, EmfPlusHelperData const & rR);
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpfont.cxx b/drawinglayer/source/tools/emfpfont.cxx
index f641fdd4d21b..3fd6537e75a0 100644
--- a/drawinglayer/source/tools/emfpfont.cxx
+++ b/drawinglayer/source/tools/emfpfont.cxx
@@ -18,27 +18,28 @@
*/
#include <sal/log.hxx>
+#include <rtl/ustrbuf.hxx>
#include "emfpfont.hxx"
namespace emfplushelper
{
static OUString FontStyleToString(sal_uInt32 style)
{
- OUString sStyle;
+ OUStringBuffer sStyle;
if (style & FontStyleBold)
sStyle = "\n\t\t\tFontStyleBold";
if (style & FontStyleItalic)
- sStyle = sStyle.concat("\n\t\t\tFontStyleItalic");
+ sStyle.append("\n\t\t\tFontStyleItalic");
if (style & FontStyleUnderline)
- sStyle = sStyle.concat("\n\t\t\tFontStyleUnderline");
+ sStyle.append("\n\t\t\tFontStyleUnderline");
if (style & FontStyleStrikeout)
- sStyle = sStyle.concat("\n\t\t\tFontStyleStrikeout");
+ sStyle.append("\n\t\t\tFontStyleStrikeout");
- return sStyle;
+ return sStyle.makeStringAndClear();
}
void EMFPFont::Read(SvMemoryStream &s)
@@ -47,14 +48,14 @@ namespace emfplushelper
sal_uInt32 reserved;
sal_uInt32 length;
s.ReadUInt32(header).ReadFloat(emSize).ReadUInt32(sizeUnit).ReadInt32(fontFlags).ReadUInt32(reserved).ReadUInt32(length);
- SAL_WARN_IF((header >> 12) != 0xdbc01, "drawinglayer", "Invalid header - not 0xdbc01");
- SAL_INFO("drawinglayer", "EMF+\tHeader: 0x" << std::hex << (header >> 12));
- SAL_INFO("drawinglayer", "EMF+\tVersion: 0x" << (header & 0x1fff));
- SAL_INFO("drawinglayer", "EMF+\tSize: " << std::dec << emSize);
- SAL_INFO("drawinglayer", "EMF+\tUnit: " << UnitTypeToString(sizeUnit) << " (0x" << std::hex << sizeUnit << ")" << std::dec);
- SAL_INFO("drawinglayer", "EMF+\tFlags: " << FontStyleToString(fontFlags) << " (0x" << std::hex << fontFlags << ")");
- SAL_INFO("drawinglayer", "EMF+\tReserved: 0x" << reserved << std::dec);
- SAL_INFO("drawinglayer", "EMF+\tLength: " << length);
+ SAL_WARN_IF((header >> 12) != 0xdbc01, "drawinglayer.emf", "Invalid header - not 0xdbc01");
+ SAL_INFO("drawinglayer.emf", "EMF+\tHeader: 0x" << std::hex << (header >> 12));
+ SAL_INFO("drawinglayer.emf", "EMF+\tVersion: 0x" << (header & 0x1fff));
+ SAL_INFO("drawinglayer.emf", "EMF+\tSize: " << std::dec << emSize);
+ SAL_INFO("drawinglayer.emf", "EMF+\tUnit: " << UnitTypeToString(sizeUnit) << " (0x" << std::hex << sizeUnit << ")" << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\tFlags: " << FontStyleToString(fontFlags) << " (0x" << std::hex << fontFlags << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\tReserved: 0x" << reserved << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\tLength: " << length);
if (length <= 0 || length >= 0x4000)
return;
@@ -68,7 +69,7 @@ namespace emfplushelper
}
family = OUString(pStr, SAL_NO_ACQUIRE);
- SAL_INFO("drawinglayer", "EMF+\tFamily: " << family);
+ SAL_INFO("drawinglayer.emf", "EMF+\tFamily: " << family);
}
}
diff --git a/drawinglayer/source/tools/emfpfont.hxx b/drawinglayer/source/tools/emfpfont.hxx
index 0559cb949487..3f9e24166850 100644
--- a/drawinglayer/source/tools/emfpfont.hxx
+++ b/drawinglayer/source/tools/emfpfont.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPFONT_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPFONT_HXX
+#pragma once
#include "emfphelperdata.hxx"
@@ -46,6 +45,4 @@ namespace emfplushelper
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index cc0770c9a8fb..9f583702dcc2 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -29,16 +29,14 @@
#include "emfpstringformat.hxx"
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <wmfemfhelper.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokeArrowPrimitive2D.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
@@ -51,7 +49,6 @@
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
#include <sal/log.hxx>
-#include <vcl/outdev.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <i18nlangtag/languagetag.hxx>
@@ -84,6 +81,9 @@ namespace emfplushelper
case EmfPlusRecordTypeDrawRects: return "EmfPlusRecordTypeDrawRects";
case EmfPlusRecordTypeFillPolygon: return "EmfPlusRecordTypeFillPolygon";
case EmfPlusRecordTypeDrawLines: return "EmfPlusRecordTypeDrawLines";
+ case EmfPlusRecordTypeFillClosedCurve: return "EmfPlusRecordTypeFillClosedCurve";
+ case EmfPlusRecordTypeDrawClosedCurve: return "EmfPlusRecordTypeDrawClosedCurve";
+ case EmfPlusRecordTypeDrawCurve: return "EmfPlusRecordTypeDrawCurve";
case EmfPlusRecordTypeFillEllipse: return "EmfPlusRecordTypeFillEllipse";
case EmfPlusRecordTypeDrawEllipse: return "EmfPlusRecordTypeDrawEllipse";
case EmfPlusRecordTypeFillPie: return "EmfPlusRecordTypeFillPie";
@@ -128,89 +128,89 @@ namespace emfplushelper
{
switch (type)
{
- case EmfPlusObjectTypeBrush: return "EmfPlusObjectTypeBrush";
- case EmfPlusObjectTypePen: return "EmfPlusObjectTypePen";
- case EmfPlusObjectTypePath: return "EmfPlusObjectTypePath";
- case EmfPlusObjectTypeRegion: return "EmfPlusObjectTypeRegion";
- case EmfPlusObjectTypeImage: return "EmfPlusObjectTypeImage";
- case EmfPlusObjectTypeFont: return "EmfPlusObjectTypeFont";
- case EmfPlusObjectTypeStringFormat: return "EmfPlusObjectTypeStringFormat";
- case EmfPlusObjectTypeImageAttributes: return "EmfPlusObjectTypeImageAttributes";
- case EmfPlusObjectTypeCustomLineCap: return "EmfPlusObjectTypeCustomLineCap";
+ case EmfPlusObjectTypeBrush: return u"EmfPlusObjectTypeBrush"_ustr;
+ case EmfPlusObjectTypePen: return u"EmfPlusObjectTypePen"_ustr;
+ case EmfPlusObjectTypePath: return u"EmfPlusObjectTypePath"_ustr;
+ case EmfPlusObjectTypeRegion: return u"EmfPlusObjectTypeRegion"_ustr;
+ case EmfPlusObjectTypeImage: return u"EmfPlusObjectTypeImage"_ustr;
+ case EmfPlusObjectTypeFont: return u"EmfPlusObjectTypeFont"_ustr;
+ case EmfPlusObjectTypeStringFormat: return u"EmfPlusObjectTypeStringFormat"_ustr;
+ case EmfPlusObjectTypeImageAttributes: return u"EmfPlusObjectTypeImageAttributes"_ustr;
+ case EmfPlusObjectTypeCustomLineCap: return u"EmfPlusObjectTypeCustomLineCap"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString PixelOffsetModeToString(sal_uInt16 nPixelOffset)
{
switch (nPixelOffset)
{
- case PixelOffsetMode::PixelOffsetModeDefault: return "PixelOffsetModeDefault";
- case PixelOffsetMode::PixelOffsetModeHighSpeed: return "PixelOffsetModeHighSpeed";
- case PixelOffsetMode::PixelOffsetModeHighQuality: return "PixelOffsetModeHighQuality";
- case PixelOffsetMode::PixelOffsetModeNone: return "PixelOffsetModeNone";
- case PixelOffsetMode::PixelOffsetModeHalf: return "PixelOffsetModeHalf";
+ case PixelOffsetMode::PixelOffsetModeDefault: return u"PixelOffsetModeDefault"_ustr;
+ case PixelOffsetMode::PixelOffsetModeHighSpeed: return u"PixelOffsetModeHighSpeed"_ustr;
+ case PixelOffsetMode::PixelOffsetModeHighQuality: return u"PixelOffsetModeHighQuality"_ustr;
+ case PixelOffsetMode::PixelOffsetModeNone: return u"PixelOffsetModeNone"_ustr;
+ case PixelOffsetMode::PixelOffsetModeHalf: return u"PixelOffsetModeHalf"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString SmoothingModeToString(sal_uInt16 nSmoothMode)
{
switch (nSmoothMode)
{
- case SmoothingMode::SmoothingModeDefault: return "SmoothingModeDefault";
- case SmoothingMode::SmoothingModeHighSpeed: return "SmoothModeHighSpeed";
- case SmoothingMode::SmoothingModeHighQuality: return "SmoothingModeHighQuality";
- case SmoothingMode::SmoothingModeNone: return "SmoothingModeNone";
- case SmoothingMode::SmoothingModeAntiAlias8x4: return "SmoothingModeAntiAlias8x4";
- case SmoothingMode::SmoothingModeAntiAlias8x8: return "SmoothingModeAntiAlias8x8";
+ case SmoothingMode::SmoothingModeDefault: return u"SmoothingModeDefault"_ustr;
+ case SmoothingMode::SmoothingModeHighSpeed: return u"SmoothModeHighSpeed"_ustr;
+ case SmoothingMode::SmoothingModeHighQuality: return u"SmoothingModeHighQuality"_ustr;
+ case SmoothingMode::SmoothingModeNone: return u"SmoothingModeNone"_ustr;
+ case SmoothingMode::SmoothingModeAntiAlias8x4: return u"SmoothingModeAntiAlias8x4"_ustr;
+ case SmoothingMode::SmoothingModeAntiAlias8x8: return u"SmoothingModeAntiAlias8x8"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString TextRenderingHintToString(sal_uInt16 nHint)
{
switch (nHint)
{
- case TextRenderingHint::TextRenderingHintSystemDefault: return "TextRenderingHintSystemDefault";
- case TextRenderingHint::TextRenderingHintSingleBitPerPixelGridFit: return "TextRenderingHintSingleBitPerPixelGridFit";
- case TextRenderingHint::TextRenderingHintSingleBitPerPixel: return "TextRenderingHintSingleBitPerPixel";
- case TextRenderingHint::TextRenderingHintAntialiasGridFit: return "TextRenderingHintAntialiasGridFit";
- case TextRenderingHint::TextRenderingHintAntialias: return "TextRenderingHintAntialias";
- case TextRenderingHint::TextRenderingHintClearTypeGridFit: return "TextRenderingHintClearTypeGridFit";
+ case TextRenderingHint::TextRenderingHintSystemDefault: return u"TextRenderingHintSystemDefault"_ustr;
+ case TextRenderingHint::TextRenderingHintSingleBitPerPixelGridFit: return u"TextRenderingHintSingleBitPerPixelGridFit"_ustr;
+ case TextRenderingHint::TextRenderingHintSingleBitPerPixel: return u"TextRenderingHintSingleBitPerPixel"_ustr;
+ case TextRenderingHint::TextRenderingHintAntialiasGridFit: return u"TextRenderingHintAntialiasGridFit"_ustr;
+ case TextRenderingHint::TextRenderingHintAntialias: return u"TextRenderingHintAntialias"_ustr;
+ case TextRenderingHint::TextRenderingHintClearTypeGridFit: return u"TextRenderingHintClearTypeGridFit"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString InterpolationModeToString(sal_uInt16 nMode)
{
switch (nMode)
{
- case InterpolationMode::InterpolationModeDefault: return "InterpolationModeDefault";
- case InterpolationMode::InterpolationModeLowQuality: return "InterpolationModeLowQuality";
- case InterpolationMode::InterpolationModeHighQuality: return "InterpolationModeHighQuality";
- case InterpolationMode::InterpolationModeBilinear: return "InterpolationModeBilinear";
- case InterpolationMode::InterpolationModeBicubic: return "InterpolationModeBicubic";
- case InterpolationMode::InterpolationModeNearestNeighbor: return "InterpolationModeNearestNeighbor";
- case InterpolationMode::InterpolationModeHighQualityBilinear: return "InterpolationModeHighQualityBilinear";
- case InterpolationMode::InterpolationModeHighQualityBicubic: return "InterpolationModeHighQualityBicubic";
+ case InterpolationMode::InterpolationModeDefault: return u"InterpolationModeDefault"_ustr;
+ case InterpolationMode::InterpolationModeLowQuality: return u"InterpolationModeLowQuality"_ustr;
+ case InterpolationMode::InterpolationModeHighQuality: return u"InterpolationModeHighQuality"_ustr;
+ case InterpolationMode::InterpolationModeBilinear: return u"InterpolationModeBilinear"_ustr;
+ case InterpolationMode::InterpolationModeBicubic: return u"InterpolationModeBicubic"_ustr;
+ case InterpolationMode::InterpolationModeNearestNeighbor: return u"InterpolationModeNearestNeighbor"_ustr;
+ case InterpolationMode::InterpolationModeHighQualityBilinear: return u"InterpolationModeHighQualityBilinear"_ustr;
+ case InterpolationMode::InterpolationModeHighQualityBicubic: return u"InterpolationModeHighQualityBicubic"_ustr;
}
- return "";
+ return u""_ustr;
}
OUString UnitTypeToString(sal_uInt16 nType)
{
switch (nType)
{
- case UnitTypeWorld: return "UnitTypeWorld";
- case UnitTypeDisplay: return "UnitTypeDisplay";
- case UnitTypePixel: return "UnitTypePixel";
- case UnitTypePoint: return "UnitTypePoint";
- case UnitTypeInch: return "UnitTypeInch";
- case UnitTypeDocument: return "UnitTypeDocument";
- case UnitTypeMillimeter: return "UnitTypeMillimeter";
+ case UnitTypeWorld: return u"UnitTypeWorld"_ustr;
+ case UnitTypeDisplay: return u"UnitTypeDisplay"_ustr;
+ case UnitTypePixel: return u"UnitTypePixel"_ustr;
+ case UnitTypePoint: return u"UnitTypePoint"_ustr;
+ case UnitTypeInch: return u"UnitTypeInch"_ustr;
+ case UnitTypeDocument: return u"UnitTypeDocument"_ustr;
+ case UnitTypeMillimeter: return u"UnitTypeMillimeter"_ustr;
}
- return "";
+ return u""_ustr;
}
static bool IsBrush(sal_uInt16 flags)
@@ -220,47 +220,43 @@ namespace emfplushelper
static OUString BrushIDToString(sal_uInt16 flags, sal_uInt32 brushid)
{
- OUString sBrushId;
-
if (IsBrush(flags))
- sBrushId = sBrushId.concat("EmfPlusBrush ID: ").concat(OUString::number(brushid));
+ return "EmfPlusBrush ID: " + OUString::number(brushid);
else
- sBrushId = sBrushId.concat("ARGB: 0x").concat(OUString::number(brushid, 16));
-
- return sBrushId;
+ return "ARGB: 0x" + OUString::number(brushid, 16);
}
EMFPObject::~EMFPObject()
{
}
- float EmfPlusHelperData::getUnitToPixelMultiplier(const UnitType aUnitType, const sal_uInt32 aDPI)
+ double EmfPlusHelperData::unitToPixel(double n, sal_uInt32 aUnitType, Direction d)
{
- switch (aUnitType)
+ switch (static_cast<UnitType>(aUnitType))
{
case UnitTypePixel:
- return 1.0f;
+ return n;
case UnitTypePoint:
- return aDPI / 72.0;
+ return o3tl::convert(n, o3tl::Length::pt, o3tl::Length::in) * DPI(d);
case UnitTypeInch:
- return aDPI;
+ return n * DPI(d);
case UnitTypeMillimeter:
- return aDPI / 25.4;
+ return o3tl::convert(n, o3tl::Length::mm, o3tl::Length::in) * DPI(d);
case UnitTypeDocument:
- return aDPI / 300.0;
+ return n * DPI(d) / 300.0;
case UnitTypeWorld:
case UnitTypeDisplay:
- SAL_WARN("drawinglayer", "EMF+\t Converting to World/Display.");
- return 1.0f;
+ SAL_WARN("drawinglayer.emf", "EMF+\t Converting to World/Display.");
+ return n;
default:
- SAL_WARN("drawinglayer", "EMF+\tTODO Unimplemented support of Unit Type: 0x" << std::hex << aUnitType);
- return 1.0f;
+ SAL_WARN("drawinglayer.emf", "EMF+\tTODO Unimplemented support of Unit Type: 0x" << std::hex << aUnitType);
+ return n;
}
}
@@ -268,9 +264,9 @@ namespace emfplushelper
{
sal_uInt16 objecttype = flags & 0x7f00;
sal_uInt16 index = flags & 0xff;
- SAL_INFO("drawinglayer", "EMF+ Object: " << emfObjectToName(objecttype) << " (0x" << objecttype << ")");
- SAL_INFO("drawinglayer", "EMF+\tObject slot: " << index);
- SAL_INFO("drawinglayer", "EMF+\tFlags: " << (flags & 0xff00));
+ SAL_INFO("drawinglayer.emf", "EMF+ Object: " << emfObjectToName(objecttype) << " (0x" << objecttype << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\tObject slot: " << index);
+ SAL_INFO("drawinglayer.emf", "EMF+\tFlags: " << (flags & 0xff00));
switch (objecttype)
{
@@ -286,21 +282,20 @@ namespace emfplushelper
EMFPPen *pen = new EMFPPen();
maEMFPObjects[index].reset(pen);
pen->Read(rObjectStream, *this);
- pen->penWidth = pen->penWidth * getUnitToPixelMultiplier(static_cast<UnitType>(pen->penUnit), mnHDPI);
+ pen->penWidth = unitToPixel(pen->penWidth, pen->penUnit, Direction::horizontal);
break;
}
case EmfPlusObjectTypePath:
{
- sal_uInt32 header, pathFlags;
- sal_Int32 points;
-
- rObjectStream.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags);
- SAL_INFO("drawinglayer", "EMF+\t\tHeader: 0x" << std::hex << header);
- SAL_INFO("drawinglayer", "EMF+\t\tPoints: " << std::dec << points);
- SAL_INFO("drawinglayer", "EMF+\t\tAdditional flags: 0x" << std::hex << pathFlags << std::dec);
- EMFPPath *path = new EMFPPath(points);
+ sal_uInt32 aVersion, aPathPointCount, aPathPointFlags;
+
+ rObjectStream.ReadUInt32(aVersion).ReadUInt32(aPathPointCount).ReadUInt32(aPathPointFlags);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tVersion: 0x" << std::hex << aVersion);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tNumber of points: " << std::dec << aPathPointCount);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tPath point flags: 0x" << std::hex << aPathPointFlags << std::dec);
+ EMFPPath *path = new EMFPPath(aPathPointCount);
maEMFPObjects[index].reset(path);
- path->Read(rObjectStream, pathFlags);
+ path->Read(rObjectStream, aPathPointFlags);
break;
}
case EmfPlusObjectTypeRegion:
@@ -331,7 +326,7 @@ namespace emfplushelper
font->fontFlags = 0;
font->Read(rObjectStream);
// tdf#113624 Convert unit to Pixels
- font->emSize = font->emSize * getUnitToPixelMultiplier(static_cast<UnitType>(font->sizeUnit), mnHDPI);
+ font->emSize = unitToPixel(font->emSize, font->sizeUnit, Direction::horizontal);
break;
}
@@ -351,12 +346,12 @@ namespace emfplushelper
}
case EmfPlusObjectTypeCustomLineCap:
{
- SAL_WARN("drawinglayer", "EMF+\t TODO Object type 'custom line cap' not yet implemented");
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO Object type 'custom line cap' not yet implemented");
break;
}
default:
{
- SAL_WARN("drawinglayer", "EMF+\t TODO Object unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec);
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO Object unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec);
}
}
}
@@ -368,7 +363,7 @@ namespace emfplushelper
// specifies a location in the coordinate space that is relative to
// the location specified by the previous element in the array. In the case of the first element in
// PointData, a previous location at coordinates (0,0) is assumed.
- SAL_WARN("drawinglayer", "EMF+\t\t TODO Relative coordinates bit detected. Implement parse EMFPlusPointR");
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO Relative coordinates bit detected. Implement parse EMFPlusPointR");
}
if (flags & 0x4000)
@@ -435,7 +430,7 @@ namespace emfplushelper
{
if (mnPixX == 0 || mnPixY == 0)
{
- SAL_WARN("drawinglayer", "dimensions in pixels is 0");
+ SAL_WARN("drawinglayer.emf", "dimensions in pixels is 0");
return;
}
// Call when mnMmX/mnMmY/mnPixX/mnPixY/mnFrameLeft/mnFrameTop/maWorldTransform/ changes.
@@ -452,6 +447,10 @@ namespace emfplushelper
maMapTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(100.0 * mnMmX / mnPixX, 100.0 * mnMmY / mnPixY,
double(-mnFrameLeft), double(-mnFrameTop));
maMapTransform *= maBaseTransform;
+
+ // Used only for performance optimization, to do not calculate it every line draw
+ mdExtractedXScale = std::hypot(maMapTransform.a(), maMapTransform.b());
+ mdExtractedYScale = std::hypot(maMapTransform.c(), maMapTransform.d());
}
::basegfx::B2DPoint EmfPlusHelperData::Map(double ix, double iy) const
@@ -464,15 +463,17 @@ namespace emfplushelper
Color color;
if (flags & 0x8000) // we use a color
{
- color = Color(0xff - (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff,
+ color = Color(ColorAlpha, (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff,
(brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff);
}
- else // we use a pen
+ else // we use a brush
{
- const EMFPPen* pen = static_cast<EMFPPen*>(maEMFPObjects[brushIndexOrColor & 0xff].get());
- if (pen)
+ const EMFPBrush* brush = dynamic_cast<EMFPBrush*>(maEMFPObjects[brushIndexOrColor & 0xff].get());
+ if (brush)
{
- color = pen->GetColor();
+ color = brush->GetColor();
+ if (brush->type != BrushTypeSolidColor)
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO Brush other than solid color is not supported");
}
}
return color;
@@ -485,212 +486,184 @@ namespace emfplushelper
if ( iter != map.end() )
{
map.erase( iter );
- SAL_INFO("drawinglayer", "EMF+\t\tStack index: " << index << " found and erased");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tStack index: " << index << " found and erased");
}
wmfemfhelper::PropertyHolder state = mrPropertyHolders.Current();
// tdf#112500 We need to save world transform somehow, during graphic state push
state.setTransformation(maWorldTransform);
- map[ index ] = state;
+ map[ index ] = std::move(state);
}
- void EmfPlusHelperData::GraphicStatePop(GraphicStateMap& map, sal_Int32 index, wmfemfhelper::PropertyHolder& rState)
+ void EmfPlusHelperData::GraphicStatePop(GraphicStateMap& map, sal_Int32 index)
{
- GraphicStateMap::iterator iter = map.find( index );
+ GraphicStateMap::iterator iter = map.find(index);
- if ( iter != map.end() )
+ if (iter != map.end())
{
wmfemfhelper::PropertyHolder state = iter->second;
maWorldTransform = state.getTransformation();
- rState.setClipPolyPolygon( state.getClipPolyPolygon() );
+ if (state.getClipPolyPolygonActive())
+ {
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t Restore clipping region to saved in index: " << index);
+ wmfemfhelper::HandleNewClipRegion(state.getClipPolyPolygon(), mrTargetHolders,
+ mrPropertyHolders);
+ }
+ else
+ {
+ SAL_INFO("drawinglayer.emf", "EMF+\t Disable clipping");
+ wmfemfhelper::HandleNewClipRegion(::basegfx::B2DPolyPolygon(), mrTargetHolders,
+ mrPropertyHolders);
+ }
mappingChanged();
- SAL_INFO("drawinglayer", "EMF+\t\tStack index: " << index << " found, maWorldTransform: " << maWorldTransform);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t\tStack index: " << index
+ << " found, maWorldTransform: " << maWorldTransform);
}
}
- void EmfPlusHelperData::EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon, sal_uInt32 penIndex)
+ drawinglayer::attribute::LineStartEndAttribute
+ EmfPlusHelperData::CreateLineEnd(const sal_Int32 aCap, const float aPenWidth) const
{
- const EMFPPen* pen = dynamic_cast<EMFPPen*>(maEMFPObjects[penIndex & 0xff].get());
- SAL_WARN_IF(!pen, "drawinglayer", "emf+ missing pen");
-
- if (!(pen && polygon.count()))
- return;
-
- // we need a line join attribute
- basegfx::B2DLineJoin lineJoin = basegfx::B2DLineJoin::Round;
- if (pen->penDataFlags & EmfPlusPenDataJoin) // additional line join information
+ const double pw = mdExtractedYScale * aPenWidth;
+ if (aCap == LineCapTypeSquare)
{
- lineJoin = static_cast<basegfx::B2DLineJoin>(EMFPPen::lcl_convertLineJoinType(pen->lineJoin));
+ basegfx::B2DPolygon aCapPolygon(
+ { {-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
-
- // we need a line cap attribute
- css::drawing::LineCap lineCap = css::drawing::LineCap_BUTT;
- if (pen->penDataFlags & EmfPlusPenDataStartCap) // additional line cap information
+ else if (aCap == LineCapTypeRound)
{
- lineCap = static_cast<css::drawing::LineCap>(EMFPPen::lcl_convertStrokeCap(pen->startCap));
- SAL_WARN_IF(pen->startCap != pen->endCap, "drawinglayer", "emf+ pen uses different start and end cap");
+ basegfx::B2DPolygon aCapPolygon(
+ { {-1.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {0.9236, -0.3827},
+ {0.7071, -0.7071}, {0.3827, -0.9236}, {0.0, -1.0}, {-0.3827, -0.9236},
+ {-0.7071, -0.7071}, {-0.9236, -0.3827}, {-1.0, 0.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
-
- const double transformedPenWidth = maMapTransform.get(0, 0) * pen->penWidth;
- drawinglayer::attribute::LineAttribute lineAttribute(pen->GetColor().getBColor(),
- transformedPenWidth,
- lineJoin,
- lineCap);
-
- drawinglayer::attribute::StrokeAttribute aStrokeAttribute;
- if (pen->penDataFlags & EmfPlusPenDataLineStyle && pen->dashStyle != EmfPlusLineStyleCustom) // pen has a predefined line style
+ else if (aCap == LineCapTypeTriangle)
{
- // short writing
- const double pw = maMapTransform.get(1, 1) * pen->penWidth;
- // taken from the old cppcanvas implementation and multiplied with pen width
- const std::vector<double> dash = { 3*pw, 3*pw };
- const std::vector<double> dot = { pw, 3*pw };
- const std::vector<double> dashdot = { 3*pw, 3*pw, pw, 3*pw };
- const std::vector<double> dashdotdot = { 3*pw, 3*pw, pw, 3*pw, pw, 3*pw };
-
- switch (pen->dashStyle)
- {
- case EmfPlusLineStyleSolid: // do nothing special, use default stroke attribute
- break;
- case EmfPlusLineStyleDash:
- aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dash);
- break;
- case EmfPlusLineStyleDot:
- aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dot);
- break;
- case EmfPlusLineStyleDashDot:
- aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdot);
- break;
- case EmfPlusLineStyleDashDotDot:
- aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdotdot);
- break;
- }
+ basegfx::B2DPolygon aCapPolygon(
+ { {-1.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {0.0, -1.0}, {-1.0, 0.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
- else if (pen->penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line
+ else if (aCap == LineCapTypeSquareAnchor)
{
- // StrokeAttribute needs a double vector while the pen provides a float vector
- std::vector<double> aPattern(pen->dashPattern.size());
- for (size_t i=0; i<aPattern.size(); i++)
- {
- // convert from float to double and multiply with the adjusted pen width
- aPattern[i] = maMapTransform.get(1, 1) * pen->penWidth * pen->dashPattern[i];
- }
- aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(aPattern);
+ basegfx::B2DPolygon aCapPolygon(
+ { {-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ 1.5 * pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
-
- if (pen->GetColor().GetTransparency() == 0)
+ else if (aCap == LineCapTypeRoundAnchor)
{
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>(
- polygon,
- lineAttribute,
- aStrokeAttribute));
+ const basegfx::B2DPolygon aCapPolygon
+ = ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 1.0, 1.0);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ 2.0 * pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
- else
+ else if (aCap == LineCapTypeDiamondAnchor)
{
- const drawinglayer::primitive2d::Primitive2DReference aPrimitive(
- new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
- polygon,
- lineAttribute,
- aStrokeAttribute));
-
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>(
- drawinglayer::primitive2d::Primitive2DContainer { aPrimitive },
- pen->GetColor().GetTransparency() / 255.0));
+ basegfx::B2DPolygon aCapPolygon({ {0.0, -1.0}, {1.0, 0.0}, {0.5, 0.5},
+ {0.5, 1.0}, {-0.5, 1.0}, {-0.5, 0.5},
+ {-1.0, 0.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ 2.0 * pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
}
-
- if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) && (pen->customStartCap->polygon.begin()->count() > 1))
+ else if (aCap == LineCapTypeArrowAnchor)
{
- SAL_WARN("drawinglayer", "EMF+\tCustom Start Line Cap");
- ::basegfx::B2DPolyPolygon startCapPolygon(pen->customStartCap->polygon);
-
- // get the gradient of the first line in the polypolygon
- double x1 = polygon.begin()->getB2DPoint(0).getX();
- double y1 = polygon.begin()->getB2DPoint(0).getY();
- double x2 = polygon.begin()->getB2DPoint(1).getX();
- double y2 = polygon.begin()->getB2DPoint(1).getY();
-
- if ((x2 - x1) != 0)
- {
- double gradient = (y2 - y1) / (x2 - x1);
-
- // now we get the angle that we need to rotate the arrow by
- double angle = (M_PI / 2) - atan(gradient);
+ basegfx::B2DPolygon aCapPolygon({ {0.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0} });
+ aCapPolygon.setClosed(true);
+ return drawinglayer::attribute::LineStartEndAttribute(
+ 2.0 * pw, basegfx::B2DPolyPolygon(aCapPolygon), true);
+ }
+ return drawinglayer::attribute::LineStartEndAttribute();
+ }
- // rotate the arrow
- startCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle));
- }
+ void EmfPlusHelperData::EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon,
+ sal_uInt32 penIndex)
+ {
+ const EMFPPen* pen = dynamic_cast<EMFPPen*>(maEMFPObjects[penIndex & 0xff].get());
+ SAL_WARN_IF(!pen, "drawinglayer.emf", "emf+ missing pen");
- startCapPolygon.transform(maMapTransform);
+ if (!(pen && polygon.count()))
+ return;
- basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(0).getX(),
- 0.0, pen->penWidth, polygon.begin()->getB2DPoint(0).getY());
- startCapPolygon.transform(tran);
+ const double transformedPenWidth = mdExtractedYScale * pen->penWidth;
+ drawinglayer::attribute::LineAttribute lineAttribute(
+ pen->GetColor().getBColor(), transformedPenWidth, pen->maLineJoin,
+ css::drawing::LineCap_BUTT, //TODO implement PenDataDashedLineCap support here
+ pen->fMiterMinimumAngle);
- if (pen->customStartCap->mbIsFilled)
- {
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
- startCapPolygon,
- pen->GetColor().getBColor()));
- }
+ drawinglayer::attribute::LineStartEndAttribute aStart;
+ if (pen->penDataFlags & EmfPlusPenDataStartCap)
+ {
+ if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap)
+ && (pen->customStartCap->polygon.begin()->count() > 1))
+ aStart = drawinglayer::attribute::LineStartEndAttribute(
+ pen->customStartCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale
+ * pen->customStartCap->widthScale * pen->penWidth,
+ pen->customStartCap->polygon, false);
else
- {
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>(
- startCapPolygon,
- lineAttribute,
- aStrokeAttribute));
- }
+ aStart = EmfPlusHelperData::CreateLineEnd(pen->startCap, pen->penWidth);
}
- if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) && (pen->customEndCap->polygon.begin()->count() > 1))
+ drawinglayer::attribute::LineStartEndAttribute aEnd;
+ if (pen->penDataFlags & EmfPlusPenDataEndCap)
{
- SAL_WARN("drawinglayer", "EMF+\tCustom End Line Cap");
-
- ::basegfx::B2DPolyPolygon endCapPolygon(pen->customEndCap->polygon);
-
- // get the gradient of the first line in the polypolygon
- double x1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX();
- double y1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY();
- double x2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getX();
- double y2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getY();
+ if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap)
+ && (pen->customEndCap->polygon.begin()->count() > 1))
+ aEnd = drawinglayer::attribute::LineStartEndAttribute(
+ pen->customEndCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale
+ * pen->customEndCap->widthScale * pen->penWidth,
+ pen->customEndCap->polygon, false);
+ else
+ aEnd = EmfPlusHelperData::CreateLineEnd(pen->endCap, pen->penWidth);
+ }
- if ((x2 - x1) != 0)
+ if (pen->GetColor().IsTransparent())
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aContainer;
+ if (aStart.isDefault() && aEnd.isDefault())
+ aContainer.append(
+ new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+ polygon, lineAttribute, pen->GetStrokeAttribute(mdExtractedXScale)));
+ else
{
- double gradient = (y2 - y1) / (x2 - x1);
-
- // now we get the angle that we need to rotate the arrow by
- double angle = (M_PI / 2) - atan(gradient);
-
- // rotate the arrow
- endCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle));
+ aContainer.resize(polygon.count());
+ for (sal_uInt32 i = 0; i < polygon.count(); i++)
+ aContainer[i] =
+ new drawinglayer::primitive2d::PolygonStrokeArrowPrimitive2D(
+ polygon.getB2DPolygon(i), lineAttribute,
+ pen->GetStrokeAttribute(mdExtractedXScale), aStart, aEnd);
}
-
- endCapPolygon.transform(maMapTransform);
- basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(),
- 0.0, pen->penWidth, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY());
- endCapPolygon.transform(tran);
-
- if (pen->customEndCap->mbIsFilled)
- {
+ mrTargetHolders.Current().append(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aContainer), (255 - pen->GetColor().GetAlpha()) / 255.0));
+ }
+ else
+ {
+ if (aStart.isDefault() && aEnd.isDefault())
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
- endCapPolygon,
- pen->GetColor().getBColor()));
- }
+ new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+ polygon, lineAttribute, pen->GetStrokeAttribute(mdExtractedXScale)));
else
- {
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>(
- endCapPolygon,
- lineAttribute,
- aStrokeAttribute));
- }
+ for (sal_uInt32 i = 0; i < polygon.count(); i++)
+ {
+ mrTargetHolders.Current().append(
+ new drawinglayer::primitive2d::PolygonStrokeArrowPrimitive2D(
+ polygon.getB2DPolygon(i), lineAttribute,
+ pen->GetStrokeAttribute(mdExtractedXScale), aStart, aEnd));
+ }
}
-
mrPropertyHolders.Current().setLineColor(pen->GetColor().getBColor());
mrPropertyHolders.Current().setLineColorActive(true);
mrPropertyHolders.Current().setFillColorActive(false);
@@ -698,28 +671,25 @@ namespace emfplushelper
void EmfPlusHelperData::EMFPPlusFillPolygonSolidColor(const ::basegfx::B2DPolyPolygon& polygon, Color const& color)
{
- if (color.GetTransparency() >= 255)
+ if (color.GetAlpha() == 0)
return;
- if (color.GetTransparency() == 0)
+ if (!color.IsTransparent())
{
// not transparent
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
polygon,
color.getBColor()));
}
else
{
- const drawinglayer::primitive2d::Primitive2DReference aPrimitive(
- new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
- polygon,
- color.getBColor()));
-
+ // transparent
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>(
- drawinglayer::primitive2d::Primitive2DContainer { aPrimitive },
- color.GetTransparency() / 255.0));
+ new drawinglayer::primitive2d::PolyPolygonRGBAPrimitive2D(
+ polygon,
+ color.getBColor(),
+ (255 - color.GetAlpha()) / 255.0));
}
}
@@ -730,11 +700,11 @@ namespace emfplushelper
if (isColor) // use Color
{
- SAL_INFO("drawinglayer", "EMF+\t\t Fill polygon, ARGB color: 0x" << std::hex << brushIndexOrColor << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t Fill polygon, ARGB color: 0x" << std::hex << brushIndexOrColor << std::dec);
// EMF Alpha (1 byte): An 8-bit unsigned integer that specifies the transparency of the background,
// ranging from 0 for completely transparent to 0xFF for completely opaque.
- const Color color(0xff - (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff, (brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff);
+ const Color color(ColorAlpha, (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff, (brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff);
EMFPPlusFillPolygonSolidColor(polygon, color);
mrPropertyHolders.Current().setFillColor(color.getBColor());
@@ -743,8 +713,8 @@ namespace emfplushelper
}
else // use Brush
{
- EMFPBrush* brush = static_cast<EMFPBrush*>( maEMFPObjects[brushIndexOrColor & 0xff].get() );
- SAL_INFO("drawinglayer", "EMF+\t\t Fill polygon, brush slot: " << brushIndexOrColor << " (brush type: " << (brush ? brush->GetType() : -1) << ")");
+ EMFPBrush* brush = dynamic_cast<EMFPBrush*>(maEMFPObjects[brushIndexOrColor & 0xff].get());
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t Fill polygon, brush slot: " << brushIndexOrColor << " (brush type: " << (brush ? brush->GetType() : -1) << ")");
// give up in case something wrong happened
if( !brush )
@@ -797,20 +767,20 @@ namespace emfplushelper
// temporal solution: create a solid colored polygon
// TODO create a 'real' hatching primitive
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
polygon,
fillColor.getBColor()));
}
else if (brush->type == BrushTypeTextureFill)
{
- SAL_WARN("drawinglayer", "EMF+\tTODO: implement BrushTypeTextureFill brush");
+ SAL_WARN("drawinglayer.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush");
}
else if (brush->type == BrushTypePathGradient || brush->type == BrushTypeLinearGradient)
{
if (brush->type == BrushTypePathGradient && !(brush->additionalFlags & 0x1))
{
- SAL_WARN("drawinglayer", "EMF+\t TODO Implement displaying BrushTypePathGradient with Boundary: ");
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO Implement displaying BrushTypePathGradient with Boundary: ");
}
::basegfx::B2DHomMatrix aTextureTransformation;
@@ -831,63 +801,36 @@ namespace emfplushelper
if (brush->blendPositions)
{
- SAL_INFO("drawinglayer", "EMF+\t\tUse blend");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tUse blend");
// store the blendpoints in the vector
- for (int i = 0; i < brush->blendPoints; i++)
+ for (sal_uInt32 i = 0; i < brush->blendPoints; i++)
{
- double aBlendPoint;
+ const double aBlendPoint = brush->blendPositions[i];
basegfx::BColor aColor;
- if (brush->type == BrushTypeLinearGradient)
- {
- aBlendPoint = brush->blendPositions [i];
- }
- else
- {
- // seems like SvgRadialGradientPrimitive2D needs doubled, inverted radius
- aBlendPoint = 2. * ( 1. - brush->blendPositions [i] );
- }
- aColor.setGreen( aStartColor.getGreen() + brush->blendFactors[i] * ( aEndColor.getGreen() - aStartColor.getGreen() ) );
- aColor.setBlue ( aStartColor.getBlue() + brush->blendFactors[i] * ( aEndColor.getBlue() - aStartColor.getBlue() ) );
- aColor.setRed ( aStartColor.getRed() + brush->blendFactors[i] * ( aEndColor.getRed() - aStartColor.getRed() ) );
- const double aTransparency = brush->solidColor.GetTransparency() + brush->blendFactors[i] * ( brush->secondColor.GetTransparency() - brush->solidColor.GetTransparency() );
- aVector.emplace_back(aBlendPoint, aColor, (255.0 - aTransparency) / 255.0);
+ aColor.setGreen(aStartColor.getGreen() + brush->blendFactors[i] * (aEndColor.getGreen() - aStartColor.getGreen()));
+ aColor.setBlue (aStartColor.getBlue() + brush->blendFactors[i] * (aEndColor.getBlue() - aStartColor.getBlue()));
+ aColor.setRed (aStartColor.getRed() + brush->blendFactors[i] * (aEndColor.getRed() - aStartColor.getRed()));
+ const double aAlpha = brush->solidColor.GetAlpha() + brush->blendFactors[i] * (brush->secondColor.GetAlpha() - brush->solidColor.GetAlpha());
+ aVector.emplace_back(aBlendPoint, aColor, aAlpha / 255.0);
}
}
else if (brush->colorblendPositions)
{
- SAL_INFO("drawinglayer", "EMF+\t\tUse color blend");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tUse color blend");
// store the colorBlends in the vector
- for (int i = 0; i < brush->colorblendPoints; i++)
+ for (sal_uInt32 i = 0; i < brush->colorblendPoints; i++)
{
- double aBlendPoint;
- basegfx::BColor aColor;
- if (brush->type == BrushTypeLinearGradient)
- {
- aBlendPoint = brush->colorblendPositions [i];
- }
- else
- {
- // seems like SvgRadialGradientPrimitive2D needs doubled, inverted radius
- aBlendPoint = 2. * ( 1. - brush->colorblendPositions [i] );
- }
- aColor = brush->colorblendColors[i].getBColor();
- aVector.emplace_back(aBlendPoint, aColor, (255 - brush->colorblendColors[i].GetTransparency()) / 255.0 );
+ const double aBlendPoint = brush->colorblendPositions[i];
+ const basegfx::BColor aColor = brush->colorblendColors[i].getBColor();
+ aVector.emplace_back(aBlendPoint, aColor, brush->colorblendColors[i].GetAlpha() / 255.0);
}
}
else // ok, no extra points: just start and end
{
- if (brush->type == BrushTypeLinearGradient)
- {
- aVector.emplace_back(0.0, aStartColor, (255 - brush->solidColor.GetTransparency()) / 255.0);
- aVector.emplace_back(1.0, aEndColor, (255 - brush->secondColor.GetTransparency()) / 255.0);
- }
- else // again, here reverse
- {
- aVector.emplace_back(0.0, aEndColor, (255 - brush->secondColor.GetTransparency()) / 255.0);
- aVector.emplace_back(1.0, aStartColor, (255 - brush->solidColor.GetTransparency()) / 255.0);
- }
+ aVector.emplace_back(0.0, aStartColor, brush->solidColor.GetAlpha() / 255.0);
+ aVector.emplace_back(1.0, aEndColor, brush->secondColor.GetAlpha() / 255.0);
}
// get the polygon range to be able to map the start/end/center point correctly
@@ -928,30 +871,30 @@ namespace emfplushelper
// create the same one used for SVG
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::SvgLinearGradientPrimitive2D>(
+ new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D(
aTextureTransformation,
polygon,
- aVector,
+ std::move(aVector),
aStartPoint,
aEndPoint,
false, // do not use UnitCoordinates
aSpreadMethod));
}
else // BrushTypePathGradient
- {
+ { // TODO The PathGradient is not implemented, and Radial Gradient is used instead
basegfx::B2DPoint aCenterPoint = Map(brush->firstPointX, brush->firstPointY);
aCenterPoint = aPolygonTransformation * aCenterPoint;
// create the same one used for SVG
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::SvgRadialGradientPrimitive2D>(
+ new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D(
aTextureTransformation,
polygon,
- aVector,
+ std::move(aVector),
aCenterPoint,
- 0.5, // relative radius
- true, // use UnitCoordinates to stretch the gradient
- drawinglayer::primitive2d::SpreadMethod::Repeat,
+ 0.7, // relative radius little bigger to cover all elements
+ true, // use UnitCoordinates to stretch the gradient
+ drawinglayer::primitive2d::SpreadMethod::Pad,
nullptr));
}
}
@@ -962,11 +905,7 @@ namespace emfplushelper
SvMemoryStream& rMS,
wmfemfhelper::TargetHolders& rTargetHolders,
wmfemfhelper::PropertyHolders& rPropertyHolders)
- : maBaseTransform(),
- maWorldTransform(),
- maMapTransform(),
- maEMFPObjects(),
- mfPageScale(0.0),
+ : mfPageScale(0.0),
mnOriginX(0),
mnOriginY(0),
mnHDPI(0),
@@ -983,17 +922,18 @@ namespace emfplushelper
mnMmY(0),
mbMultipart(false),
mMFlags(0),
- mMStream(),
+ mdExtractedXScale(1.0),
+ mdExtractedYScale(1.0),
mrTargetHolders(rTargetHolders),
mrPropertyHolders(rPropertyHolders),
bIsGetDCProcessing(false)
{
rMS.ReadInt32(mnFrameLeft).ReadInt32(mnFrameTop).ReadInt32(mnFrameRight).ReadInt32(mnFrameBottom);
- SAL_INFO("drawinglayer", "EMF+ picture frame: " << mnFrameLeft << "," << mnFrameTop << " - " << mnFrameRight << "," << mnFrameBottom);
+ SAL_INFO("drawinglayer.emf", "EMF+ picture frame: " << mnFrameLeft << "," << mnFrameTop << " - " << mnFrameRight << "," << mnFrameBottom);
rMS.ReadInt32(mnPixX).ReadInt32(mnPixY).ReadInt32(mnMmX).ReadInt32(mnMmY);
- SAL_INFO("drawinglayer", "EMF+ ref device pixel size: " << mnPixX << "x" << mnPixY << " mm size: " << mnMmX << "x" << mnMmY);
+ SAL_INFO("drawinglayer.emf", "EMF+ ref device pixel size: " << mnPixX << "x" << mnPixY << " mm size: " << mnMmX << "x" << mnMmY);
readXForm(rMS, maBaseTransform);
- SAL_INFO("drawinglayer", "EMF+ base transform: " << maBaseTransform);
+ SAL_INFO("drawinglayer.emf", "EMF+ base transform: " << maBaseTransform);
mappingChanged();
}
@@ -1013,14 +953,8 @@ namespace emfplushelper
}
case EmfPlusCombineModeIntersect:
{
- if (leftPolygon.count())
- {
- aClippedPolyPolygon = basegfx::utils::clipPolyPolygonOnPolyPolygon(
- leftPolygon,
- rightPolygon,
- true,
- false);
- }
+ aClippedPolyPolygon = basegfx::utils::clipPolyPolygonOnPolyPolygon(
+ leftPolygon, rightPolygon, true, false);
break;
}
case EmfPlusCombineModeUnion:
@@ -1056,7 +990,7 @@ namespace emfplushelper
sal_uInt64 length = rMS.GetSize();
if (length < 12)
- SAL_WARN("drawinglayer", "length is less than required header size");
+ SAL_WARN("drawinglayer.emf", "length is less than required header size");
// 12 is minimal valid EMF+ record size; remaining bytes are padding
while (length >= 12)
@@ -1071,30 +1005,40 @@ namespace emfplushelper
if (size < 12)
{
- SAL_WARN("drawinglayer", "Size field is less than 12 bytes");
+ SAL_WARN("drawinglayer.emf", "Size field is less than 12 bytes");
break;
}
else if (size > length)
{
- SAL_WARN("drawinglayer", "Size field is greater than bytes left");
+ SAL_WARN("drawinglayer.emf", "Size field is greater than bytes left");
break;
}
if (dataSize > (size - 12))
{
- SAL_WARN("drawinglayer", "DataSize field is greater than Size-12");
+ SAL_WARN("drawinglayer.emf", "DataSize field is greater than Size-12");
break;
}
- SAL_INFO("drawinglayer", "EMF+ " << emfTypeToName(type) << " (0x" << std::hex << type << ")" << std::dec);
- SAL_INFO("drawinglayer", "EMF+\t record size: " << size);
- SAL_INFO("drawinglayer", "EMF+\t flags: 0x" << std::hex << flags << std::dec);
- SAL_INFO("drawinglayer", "EMF+\t data size: " << dataSize);
+ SAL_INFO("drawinglayer.emf", "EMF+ " << emfTypeToName(type) << " (0x" << std::hex << type << ")" << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t record size: " << size);
+ SAL_INFO("drawinglayer.emf", "EMF+\t flags: 0x" << std::hex << flags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t data size: " << dataSize);
if (bIsGetDCProcessing)
{
- SAL_INFO("drawinglayer", "EMF+\t reset the current clipping region for the world space to infinity.");
- wmfemfhelper::HandleNewClipRegion(::basegfx::B2DPolyPolygon(), mrTargetHolders, mrPropertyHolders);
+ if (aGetDCState.getClipPolyPolygonActive())
+ {
+ SAL_INFO("drawinglayer.emf", "EMF+\t Restore region to GetDC saved");
+ wmfemfhelper::HandleNewClipRegion(aGetDCState.getClipPolyPolygon(), mrTargetHolders,
+ mrPropertyHolders);
+ }
+ else
+ {
+ SAL_INFO("drawinglayer.emf", "EMF+\t Disable clipping");
+ wmfemfhelper::HandleNewClipRegion(::basegfx::B2DPolyPolygon(), mrTargetHolders,
+ mrPropertyHolders);
+ }
bIsGetDCProcessing = false;
}
if (type == EmfPlusRecordTypeObject && ((mbMultipart && (flags & 0x7fff) == (mMFlags & 0x7fff)) || (flags & 0x8000)))
@@ -1110,13 +1054,13 @@ namespace emfplushelper
// 1st 4 bytes are TotalObjectSize
mMStream.WriteBytes(static_cast<const char *>(rMS.GetData()) + rMS.Tell() + 4, dataSize - 4);
- SAL_INFO("drawinglayer", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
+ SAL_INFO("drawinglayer.emf", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
}
else
{
if (mbMultipart)
{
- SAL_INFO("drawinglayer", "EMF+ multipart record flags: " << mMFlags);
+ SAL_INFO("drawinglayer.emf", "EMF+ multipart record flags: " << mMFlags);
mMStream.Seek(0);
processObjectRecord(mMStream, mMFlags, 0, true);
}
@@ -1130,14 +1074,15 @@ namespace emfplushelper
{
case EmfPlusRecordTypeHeader:
{
- sal_uInt32 header, version;
-
- rMS.ReadUInt32(header).ReadUInt32(version).ReadUInt32(mnHDPI).ReadUInt32(mnVDPI);
- SAL_INFO("drawinglayer", "EMF+\tHeader: 0x" << std::hex << header);
- SAL_INFO("drawinglayer", "EMF+\tVersion: " << std::dec << version);
- SAL_INFO("drawinglayer", "EMF+\tHorizontal DPI: " << mnHDPI);
- SAL_INFO("drawinglayer", "EMF+\tVertical DPI: " << mnVDPI);
- SAL_INFO("drawinglayer", "EMF+\tDual: " << ((flags & 1) ? "true" : "false"));
+ sal_uInt32 version, emfPlusFlags;
+ SAL_INFO("drawinglayer.emf", "EMF+\tDual: " << ((flags & 1) ? "true" : "false"));
+
+ rMS.ReadUInt32(version).ReadUInt32(emfPlusFlags).ReadUInt32(mnHDPI).ReadUInt32(mnVDPI);
+ SAL_INFO("drawinglayer.emf", "EMF+\tVersion: 0x" << std::hex << version);
+ SAL_INFO("drawinglayer.emf", "EMF+\tEmf+ Flags: 0x" << emfPlusFlags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\tMetafile was recorded with a reference device context for " << ((emfPlusFlags & 1) ? "video display" : "printer"));
+ SAL_INFO("drawinglayer.emf", "EMF+\tHorizontal DPI: " << mnHDPI);
+ SAL_INFO("drawinglayer.emf", "EMF+\tVertical DPI: " << mnVDPI);
break;
}
case EmfPlusRecordTypeEndOfFile:
@@ -1150,7 +1095,7 @@ namespace emfplushelper
unsigned char data;
OUString hexdata;
- SAL_INFO("drawinglayer", "EMF+\tDatasize: 0x" << std::hex << dataSize << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\tDatasize: 0x" << std::hex << dataSize << std::dec);
for (sal_uInt32 i=0; i<dataSize; i++)
{
@@ -1166,14 +1111,15 @@ namespace emfplushelper
hexdata += "0x" + padding + OUString::number(data, 16) + " ";
}
- SAL_INFO("drawinglayer", "EMF+\t" << hexdata);
+ SAL_INFO("drawinglayer.emf", "EMF+\t" << hexdata);
#endif
break;
}
case EmfPlusRecordTypeGetDC:
{
bIsGetDCProcessing = true;
- SAL_INFO("drawinglayer", "EMF+\tAlready used in svtools wmf/emf filter parser");
+ aGetDCState = mrPropertyHolders.Current();
+ SAL_INFO("drawinglayer.emf", "EMF+\tAlready used in svtools wmf/emf filter parser");
break;
}
case EmfPlusRecordTypeObject:
@@ -1193,21 +1139,21 @@ namespace emfplushelper
if (type == EmfPlusRecordTypeFillPie)
{
rMS.ReadUInt32(brushIndexOrColor);
- SAL_INFO("drawinglayer", "EMF+\t FillPie colorOrIndex: " << brushIndexOrColor);
+ SAL_INFO("drawinglayer.emf", "EMF+\t FillPie colorOrIndex: " << brushIndexOrColor);
}
else if (type == EmfPlusRecordTypeDrawPie)
{
- SAL_INFO("drawinglayer", "EMF+\t DrawPie");
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawPie");
}
else
{
- SAL_INFO("drawinglayer", "EMF+\t DrawArc");
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawArc");
}
rMS.ReadFloat(startAngle).ReadFloat(sweepAngle);
float dx, dy, dw, dh;
ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000));
- SAL_INFO("drawinglayer", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
+ SAL_INFO("drawinglayer.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
startAngle = basegfx::deg2rad(startAngle);
sweepAngle = basegfx::deg2rad(sweepAngle);
float endAngle = startAngle + sweepAngle;
@@ -1228,7 +1174,7 @@ namespace emfplushelper
std::swap(endAngle, startAngle);
}
- SAL_INFO("drawinglayer", "EMF+\t Adjusted angles: start " <<
+ SAL_INFO("drawinglayer.emf", "EMF+\t Adjusted angles: start " <<
basegfx::rad2deg(startAngle) << ", end: " << basegfx::rad2deg(endAngle) <<
" startAngle: " << startAngle << " sweepAngle: " << sweepAngle);
const ::basegfx::B2DPoint centerPoint(dx + 0.5 * dw, dy + 0.5 * dh);
@@ -1254,13 +1200,13 @@ namespace emfplushelper
sal_uInt32 index = flags & 0xff;
sal_uInt32 brushIndexOrColor;
rMS.ReadUInt32(brushIndexOrColor);
- SAL_INFO("drawinglayer", "EMF+ FillPath slot: " << index);
+ SAL_INFO("drawinglayer.emf", "EMF+ FillPath slot: " << index);
EMFPPath* path = dynamic_cast<EMFPPath*>(maEMFPObjects[index].get());
if (path)
EMFPPlusFillPolygon(path->GetPolygon(*this), flags & 0x8000, brushIndexOrColor);
else
- SAL_WARN("drawinglayer", "EMF+\tEmfPlusRecordTypeFillPath missing path");
+ SAL_WARN("drawinglayer.emf", "EMF+\tEmfPlusRecordTypeFillPath missing path");
}
break;
case EmfPlusRecordTypeFillRegion:
@@ -1268,9 +1214,13 @@ namespace emfplushelper
sal_uInt32 index = flags & 0xff;
sal_uInt32 brushIndexOrColor;
rMS.ReadUInt32(brushIndexOrColor);
- SAL_INFO("drawinglayer", "EMF+\t FillRegion slot: " << index);
+ SAL_INFO("drawinglayer.emf", "EMF+\t FillRegion slot: " << index);
- EMFPPlusFillPolygon(static_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get())->regionPolyPolygon, flags & 0x8000, brushIndexOrColor);
+ EMFPRegion* region = dynamic_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get());
+ if (region)
+ EMFPPlusFillPolygon(region->regionPolyPolygon, flags & 0x8000, brushIndexOrColor);
+ else
+ SAL_WARN("drawinglayer.emf", "EMF+\tEmfPlusRecordTypeFillRegion missing region");
}
break;
case EmfPlusRecordTypeDrawEllipse:
@@ -1286,10 +1236,10 @@ namespace emfplushelper
rMS.ReadUInt32(brushIndexOrColor);
}
- SAL_INFO("drawinglayer", "EMF+\t " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff));
+ SAL_INFO("drawinglayer.emf", "EMF+\t " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff));
float dx, dy, dw, dh;
ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000));
- SAL_INFO("drawinglayer", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
+ SAL_INFO("drawinglayer.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
::basegfx::B2DPolyPolygon polyPolygon(
::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(dx + 0.5 * dw, dy + 0.5 * dh),
0.5 * dw, 0.5 * dh));
@@ -1305,26 +1255,26 @@ namespace emfplushelper
{
// Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used
sal_uInt32 brushIndexOrColor = 999;
- sal_Int32 rectangles;
+ ::basegfx::B2DPolyPolygon polyPolygon;
+ sal_uInt32 rectangles;
+ float x, y, width, height;
const bool isColor = (flags & 0x8000);
::basegfx::B2DPolygon polygon;
if (EmfPlusRecordTypeFillRects == type)
{
- SAL_INFO("drawinglayer", "EMF+\t FillRects");
+ SAL_INFO("drawinglayer.emf", "EMF+\t FillRects");
rMS.ReadUInt32(brushIndexOrColor);
- SAL_INFO("drawinglayer", "EMF+\t" << (isColor ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t" << (isColor ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
}
else
{
- SAL_INFO("drawinglayer", "EMF+\t DrawRects");
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawRects");
}
- rMS.ReadInt32(rectangles);
-
- for (int i = 0; i < rectangles; i++)
+ rMS.ReadUInt32(rectangles);
+ for (sal_uInt32 i = 0; i < rectangles; i++)
{
- float x, y, width, height;
ReadRectangle(rMS, x, y, width, height, bool(flags & 0x4000));
polygon.clear();
polygon.append(Map(x, y));
@@ -1333,39 +1283,35 @@ namespace emfplushelper
polygon.append(Map(x, y + height));
polygon.setClosed(true);
- SAL_INFO("drawinglayer", "EMF+\t\t rectangle: " << x << ", "<< y << " " << width << "x" << height);
-
- ::basegfx::B2DPolyPolygon polyPolygon(polygon);
- if (type == EmfPlusRecordTypeFillRects)
- EMFPPlusFillPolygon(polyPolygon, isColor, brushIndexOrColor);
- else
- EMFPPlusDrawPolygon(polyPolygon, flags & 0xff);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t rectangle: " << x << ", "<< y << " " << width << "x" << height);
+ polyPolygon.append(polygon);
}
+ if (type == EmfPlusRecordTypeFillRects)
+ EMFPPlusFillPolygon(polyPolygon, isColor, brushIndexOrColor);
+ else
+ EMFPPlusDrawPolygon(polyPolygon, flags & 0xff);
break;
}
case EmfPlusRecordTypeFillPolygon:
{
- const sal_uInt8 index = flags & 0xff;
- sal_uInt32 brushIndexOrColor;
- sal_Int32 points;
+ sal_uInt32 brushIndexOrColor, points;
rMS.ReadUInt32(brushIndexOrColor);
- rMS.ReadInt32(points);
- SAL_INFO("drawinglayer", "EMF+\t FillPolygon in slot: " << index << " points: " << points);
- SAL_INFO("drawinglayer", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << " : 0x" << std::hex << brushIndexOrColor << std::dec);
+ rMS.ReadUInt32(points);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Points: " << points);
+ SAL_INFO("drawinglayer.emf", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << " : 0x" << std::hex << brushIndexOrColor << std::dec);
EMFPPath path(points, true);
path.Read(rMS, flags);
EMFPPlusFillPolygon(path.GetPolygon(*this), flags & 0x8000, brushIndexOrColor);
-
break;
}
case EmfPlusRecordTypeDrawLines:
{
sal_uInt32 points;
rMS.ReadUInt32(points);
- SAL_INFO("drawinglayer", "EMF+\t DrawLines in slot: " << (flags & 0xff) << " points: " << points);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Points: " << points);
EMFPPath path(points, true);
path.Read(rMS, flags);
@@ -1379,13 +1325,13 @@ namespace emfplushelper
{
sal_uInt32 penIndex;
rMS.ReadUInt32(penIndex);
- SAL_INFO("drawinglayer", "EMF+\t Pen: " << penIndex);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Pen: " << penIndex);
EMFPPath* path = dynamic_cast<EMFPPath*>(maEMFPObjects[flags & 0xff].get());
if (path)
EMFPPlusDrawPolygon(path->GetPolygon(*this), penIndex);
else
- SAL_WARN("drawinglayer", "\t\tEmfPlusRecordTypeDrawPath missing path");
+ SAL_WARN("drawinglayer.emf", "\t\tEmfPlusRecordTypeDrawPath missing path");
break;
}
@@ -1393,46 +1339,98 @@ namespace emfplushelper
{
sal_uInt32 aCount;
float x1, y1, x2, y2, x3, y3, x4, y4;
- ::basegfx::B2DPoint aStartPoint, aControlPointA, aControlPointB, aEndPoint;
::basegfx::B2DPolygon aPolygon;
rMS.ReadUInt32(aCount);
- SAL_INFO("drawinglayer", "EMF+\t DrawBeziers slot: " << (flags & 0xff));
- SAL_INFO("drawinglayer", "EMF+\t Number of points: " << aCount);
- SAL_WARN_IF((aCount - 1) % 3 != 0, "drawinglayer", "EMF+\t Bezier Draw not support number of points other than 4, 7, 10, 13, 16...");
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawBeziers slot: " << (flags & 0xff));
+ SAL_INFO("drawinglayer.emf", "EMF+\t Number of points: " << aCount);
+ SAL_WARN_IF((aCount - 1) % 3 != 0, "drawinglayer.emf",
+ "EMF+\t Bezier Draw not support number of points other than 4, 7, "
+ "10, 13, 16...");
if (aCount < 4)
{
- SAL_WARN("drawinglayer", "EMF+\t Bezier Draw does not support less than 4 points. Number of points: " << aCount);
+ SAL_WARN("drawinglayer.emf", "EMF+\t Bezier Draw does not support less "
+ "than 4 points. Number of points: "
+ << aCount);
break;
}
ReadPoint(rMS, x1, y1, flags);
// We need to add first starting point
- aStartPoint = Map(x1, y1);
- aPolygon.append(aStartPoint);
-
+ aPolygon.append(Map(x1, y1));
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t Bezier starting point: " << x1 << "," << y1);
for (sal_uInt32 i = 4; i <= aCount; i += 3)
{
ReadPoint(rMS, x2, y2, flags);
ReadPoint(rMS, x3, y3, flags);
ReadPoint(rMS, x4, y4, flags);
- SAL_INFO("drawinglayer", "EMF+\t Bezier points: " << x1 << "," << y1 << " " << x2 << "," << y2 << " " << x3 << "," << y3 << " " << x4 << "," << y4);
-
- aStartPoint = Map(x1, y1);
- aControlPointA = Map(x2, y2);
- aControlPointB = Map(x3, y3);
- aEndPoint = Map(x4, y4);
-
- ::basegfx::B2DCubicBezier cubicBezier(aStartPoint, aControlPointA, aControlPointB, aEndPoint);
- cubicBezier.adaptiveSubdivideByDistance(aPolygon, 10.0);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t Bezier points: " << x2 << "," << y2 << " " << x3 << ","
+ << y3 << " " << x4 << "," << y4);
+ aPolygon.appendBezierSegment(Map(x2, y2), Map(x3, y3), Map(x4, y4));
+ }
+ EMFPPlusDrawPolygon(::basegfx::B2DPolyPolygon(aPolygon), flags & 0xff);
+ break;
+ }
+ case EmfPlusRecordTypeDrawCurve:
+ {
+ sal_uInt32 aOffset, aNumSegments, points;
+ float aTension;
+ rMS.ReadFloat(aTension);
+ rMS.ReadUInt32(aOffset);
+ rMS.ReadUInt32(aNumSegments);
+ rMS.ReadUInt32(points);
+ SAL_WARN("drawinglayer.emf",
+ "EMF+\t Tension: " << aTension << " Offset: " << aOffset
+ << " NumSegments: " << aNumSegments
+ << " Points: " << points);
- EMFPPlusDrawPolygon(::basegfx::B2DPolyPolygon(aPolygon), flags & 0xff);
+ EMFPPath path(points, true);
+ path.Read(rMS, flags);
- // The ending coordinate of one Bezier curve is the starting coordinate of the next.
- x1 = x4;
- y1 = y4;
+ if (points >= 2)
+ EMFPPlusDrawPolygon(
+ path.GetCardinalSpline(*this, aTension, aOffset, aNumSegments),
+ flags & 0xff);
+ else
+ SAL_WARN("drawinglayer.emf", "Not enough number of points");
+ break;
+ }
+ case EmfPlusRecordTypeDrawClosedCurve:
+ case EmfPlusRecordTypeFillClosedCurve:
+ {
+ // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used
+ sal_uInt32 brushIndexOrColor = 999, points;
+ float aTension;
+ if (type == EmfPlusRecordTypeFillClosedCurve)
+ {
+ rMS.ReadUInt32(brushIndexOrColor);
+ SAL_INFO(
+ "drawinglayer.emf",
+ "EMF+\t Fill Mode: " << (flags & 0x2000 ? "Winding" : "Alternate"));
}
+ rMS.ReadFloat(aTension);
+ rMS.ReadUInt32(points);
+ SAL_WARN("drawinglayer.emf",
+ "EMF+\t Tension: " << aTension << " Points: " << points);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t " << (flags & 0x8000 ? "Color" : "Brush index") << " : 0x"
+ << std::hex << brushIndexOrColor << std::dec);
+ if (points < 3)
+ {
+ SAL_WARN("drawinglayer.emf", "Not enough number of points");
+ break;
+ }
+ EMFPPath path(points, true);
+ path.Read(rMS, flags);
+ if (type == EmfPlusRecordTypeFillClosedCurve)
+ EMFPPlusFillPolygon(path.GetClosedCardinalSpline(*this, aTension),
+ flags & 0x8000, brushIndexOrColor);
+ else
+ EMFPPlusDrawPolygon(path.GetClosedCardinalSpline(*this, aTension),
+ flags & 0xff);
break;
}
case EmfPlusRecordTypeDrawImage:
@@ -1441,20 +1439,30 @@ namespace emfplushelper
sal_uInt32 imageAttributesId;
sal_Int32 sourceUnit;
rMS.ReadUInt32(imageAttributesId).ReadInt32(sourceUnit);
- SAL_INFO("drawinglayer", "EMF+\t " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << " image attributes Id: " << imageAttributesId << " source unit: " << sourceUnit);
- SAL_INFO("drawinglayer", "EMF+\t TODO: use image attributes");
-
- // For DrawImage and DrawImagePoints, source unit of measurement type must be 1 pixel
- if (sourceUnit == UnitTypePixel && maEMFPObjects[flags & 0xff])
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t " << (type == EmfPlusRecordTypeDrawImage ? "DrawImage"
+ : "DrawImagePoints")
+ << " image attributes Id: " << imageAttributesId
+ << " source unit: " << sourceUnit);
+ SAL_INFO("drawinglayer.emf", "EMF+\t TODO: use image attributes");
+
+ // Source unit of measurement type must be 1 pixel
+ if (EMFPImage* image = sourceUnit == UnitTypePixel ?
+ dynamic_cast<EMFPImage*>(maEMFPObjects[flags & 0xff].get()) :
+ nullptr)
{
- EMFPImage& image = *static_cast<EMFPImage *>(maEMFPObjects[flags & 0xff].get());
float sx, sy, sw, sh;
ReadRectangle(rMS, sx, sy, sw, sh);
- ::tools::Rectangle aSource(Point(sx, sy), Size(sw, sh));
- SAL_INFO("drawinglayer", "EMF+\t " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << " source rectangle: " << sx << "," << sy << " " << sw << "x" << sh);
- ::basegfx::B2DPoint aDstPoint;
- ::basegfx::B2DSize aDstSize;
+ ::tools::Rectangle aSource(Point(sx, sy), Size(sw + 1, sh + 1));
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t "
+ << (type == EmfPlusRecordTypeDrawImage ? "DrawImage"
+ : "DrawImagePoints")
+ << " source rectangle: " << sx << "," << sy << " " << sw << "x"
+ << sh);
+
+ float dx(0.), dy(0.), dw(0.), dh(0.);
double fShearX = 0.0;
double fShearY = 0.0;
if (type == EmfPlusRecordTypeDrawImagePoints)
@@ -1463,251 +1471,290 @@ namespace emfplushelper
rMS.ReadUInt32(aCount);
// Number of points used by DrawImagePoints. Exactly 3 points must be specified.
- if(aCount == 3)
+ if (aCount != 3)
{
- float x1, y1, x2, y2, x3, y3;
-
- ReadPoint(rMS, x1, y1, flags); // upper-left point
- ReadPoint(rMS, x2, y2, flags); // upper-right
- ReadPoint(rMS, x3, y3, flags); // lower-left
-
- SAL_INFO("drawinglayer", "EMF+\t destination points: P1:" << x1 << "," << y1 << " P2:" << x2 << "," << y2 << " P3:" << x3 << "," << y3);
-
- aDstPoint = ::basegfx::B2DPoint(x1, y1);
- aDstSize = ::basegfx::B2DSize(x2 - x1, y3 - y1);
- fShearX = x3 - x1;
- fShearY = y2 - y1;
- }
- else
- {
- SAL_WARN("drawinglayer", "EMF+\t DrawImagePoints Wrong EMF+ file. Expected 3 points, received: "<< aCount);
+ SAL_WARN("drawinglayer.emf", "EMF+\t Wrong EMF+ file. Expected "
+ "3 points, received: "
+ << aCount);
break;
}
+ float x1, y1, x2, y2, x3, y3;
+
+ ReadPoint(rMS, x1, y1, flags); // upper-left point
+ ReadPoint(rMS, x2, y2, flags); // upper-right
+ ReadPoint(rMS, x3, y3, flags); // lower-left
+
+ SAL_INFO("drawinglayer.emf", "EMF+\t destination points: "
+ << x1 << "," << y1 << " " << x2 << ","
+ << y2 << " " << x3 << "," << y3);
+ dx = x1;
+ dy = y2;
+ dw = x2 - x1;
+ dh = y3 - y1;
+ fShearX = x3 - x1;
+ fShearY = y2 - y1;
}
else if (type == EmfPlusRecordTypeDrawImage)
- {
- float dx, dy, dw, dh;
ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000));
- SAL_INFO("drawinglayer", "EMF+\t destination rectangle: " << dx << "," << dy << " " << dw << "x" << dh);
- aDstPoint = ::basegfx::B2DPoint(dx, dy);
- aDstSize = ::basegfx::B2DSize(dw, dh);
- }
- const basegfx::B2DHomMatrix aTransformMatrix = maMapTransform *
- basegfx::B2DHomMatrix(
- /* Row 0, Column 0 */ aDstSize.getX(),
- /* Row 0, Column 1 */ fShearX,
- /* Row 0, Column 2 */ aDstPoint.getX(),
- /* Row 1, Column 0 */ fShearY,
- /* Row 1, Column 1 */ aDstSize.getY(),
- /* Row 1, Column 2 */ aDstPoint.getY());
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t Rectangle: " << dx << "," << dy << " " << dw << "x" << dh);
+ Size aSize;
+ if (image->type == ImageDataTypeBitmap)
+ {
+ aSize = image->graphic.GetBitmap().GetSizePixel();
+ SAL_INFO("drawinglayer.emf", "EMF+\t Bitmap size: " << aSize.Width()
+ << "x"
+ << aSize.Height());
+ if (sx < 0)
+ {
+ // If src position is negative then we need shift image to right
+ dx = dx + ((-sx) / sw) * dw;
+ if (sx + sw <= aSize.Width())
+ dw = ((sw + sx) / sw) * dw;
+ else
+ dw = (aSize.Width() / sw) * dw;
+ }
+ else if (sx + sw > aSize.Width())
+ // If the src image is smaller that what we want to cut, then we need to scale down
+ dw = ((aSize.Width() - sx) / sw) * dw;
- if (image.type == ImageDataTypeBitmap)
+ if (sy < 0)
+ {
+ dy = dy + ((-sy) / sh) * dh;
+ if (sy + sh <= aSize.Height())
+ dh = ((sh + sy) / sh) * dh;
+ else
+ dh = (aSize.Height() / sh) * dh;
+ }
+ else if (sy + sh > aSize.Height())
+ dh = ((aSize.Height() - sy) / sh) * dh;
+ }
+ else
+ SAL_INFO(
+ "drawinglayer.emf",
+ "EMF+\t TODO: Add support for SrcRect to ImageDataTypeMetafile");
+ const ::basegfx::B2DPoint aDstPoint(dx, dy);
+ const ::basegfx::B2DSize aDstSize(dw, dh);
+
+ const basegfx::B2DHomMatrix aTransformMatrix
+ = maMapTransform
+ * basegfx::B2DHomMatrix(
+ /* Row 0, Column 0 */ aDstSize.getWidth(),
+ /* Row 0, Column 1 */ fShearX,
+ /* Row 0, Column 2 */ aDstPoint.getX(),
+ /* Row 1, Column 0 */ fShearY,
+ /* Row 1, Column 1 */ aDstSize.getHeight(),
+ /* Row 1, Column 2 */ aDstPoint.getY());
+
+ if (image->type == ImageDataTypeBitmap)
{
- BitmapEx aBmp(image.graphic.GetBitmapEx());
+ Bitmap aBmp(image->graphic.GetBitmap());
aBmp.Crop(aSource);
- Size aSize(aBmp.GetSizePixel());
- SAL_INFO("drawinglayer", "EMF+\t Bitmap size: " << aSize.Width() << "x" << aSize.Height());
+ aSize = aBmp.GetSizePixel();
if (aSize.Width() > 0 && aSize.Height() > 0)
{
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::BitmapPrimitive2D>(
- VCLUnoHelper::CreateVCLXBitmap(aBmp),
- aTransformMatrix));
+ new drawinglayer::primitive2d::BitmapPrimitive2D(
+ aBmp, aTransformMatrix));
}
else
- {
- SAL_WARN("drawinglayer", "EMF+\t warning: empty bitmap");
- break;
- }
+ SAL_WARN("drawinglayer.emf", "EMF+\t warning: empty bitmap");
}
- else if (image.type == ImageDataTypeMetafile)
+ else if (image->type == ImageDataTypeMetafile)
{
- GDIMetaFile aGDI(image.graphic.GetGDIMetaFile());
+ GDIMetaFile aGDI(image->graphic.GetGDIMetaFile());
aGDI.Clip(aSource);
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::MetafilePrimitive2D>(aTransformMatrix, aGDI));
+ new drawinglayer::primitive2d::MetafilePrimitive2D(aTransformMatrix,
+ aGDI));
}
}
else
{
- SAL_WARN("drawinglayer", "EMF+\tDrawImage(Points) Wrong EMF+ file. Only Unit Type Pixel is support by EMF+ specification for DrawImage(Points)");
+ SAL_WARN("drawinglayer.emf",
+ "EMF+\tDrawImage(Points) Wrong EMF+ file. Only Unit Type Pixel is "
+ "support by EMF+ specification for DrawImage(Points)");
}
break;
}
case EmfPlusRecordTypeDrawString:
{
- sal_uInt32 brushId;
- sal_uInt32 formatId;
- sal_uInt32 stringLength;
+ sal_uInt32 brushId, formatId, stringLength;
rMS.ReadUInt32(brushId).ReadUInt32(formatId).ReadUInt32(stringLength);
- SAL_INFO("drawinglayer", "EMF+\t FontId: " << OUString::number(flags & 0xFF));
- SAL_INFO("drawinglayer", "EMF+\t BrushId: " << BrushIDToString(flags, brushId));
- SAL_INFO("drawinglayer", "EMF+\t FormatId: " << formatId);
- SAL_INFO("drawinglayer", "EMF+\t Length: " << stringLength);
-
- if (flags & 0x8000)
+ SAL_INFO("drawinglayer.emf", "EMF+\t FontId: " << OUString::number(flags & 0xFF));
+ SAL_INFO("drawinglayer.emf", "EMF+\t BrushId: " << BrushIDToString(flags, brushId));
+ SAL_INFO("drawinglayer.emf", "EMF+\t FormatId: " << formatId);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Length: " << stringLength);
+
+ // read the layout rectangle
+ float lx, ly, lw, lh;
+ rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh);
+
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh);
+ // parse the string
+ const OUString text = read_uInt16s_ToOUString(rMS, stringLength);
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawString string: " << text);
+ // get the stringFormat from the Object table ( this is OPTIONAL and may be nullptr )
+ const EMFPStringFormat *stringFormat = dynamic_cast<EMFPStringFormat*>(maEMFPObjects[formatId & 0xff].get());
+ // get the font from the flags
+ const EMFPFont *font = dynamic_cast<EMFPFont*>(maEMFPObjects[flags & 0xff].get());
+ if (!font)
{
- // read the layout rectangle
- float lx, ly, lw, lh;
- rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh);
-
- SAL_INFO("drawinglayer", "EMF+\t DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh);
- // parse the string
- const OUString text = read_uInt16s_ToOUString(rMS, stringLength);
- SAL_INFO("drawinglayer", "EMF+\t DrawString string: " << text);
- // get the stringFormat from the Object table ( this is OPTIONAL and may be nullptr )
- const EMFPStringFormat *stringFormat = dynamic_cast<EMFPStringFormat*>(maEMFPObjects[formatId & 0xff].get());
- // get the font from the flags
- const EMFPFont *font = static_cast< EMFPFont* >( maEMFPObjects[flags & 0xff].get() );
- if (!font)
- {
- break;
- }
- mrPropertyHolders.Current().setFont(vcl::Font(font->family, Size(font->emSize, font->emSize)));
+ break;
+ }
+ mrPropertyHolders.Current().setFont(vcl::Font(font->family, Size(font->emSize, font->emSize)));
+
+ drawinglayer::attribute::FontAttribute fontAttribute(
+ font->family, // font family
+ u""_ustr, // (no) font style
+ font->Bold() ? 8u : 1u, // weight: 8 = bold
+ font->family == "SYMBOL", // symbol
+ stringFormat && stringFormat->DirectionVertical(), // vertical
+ font->Italic(), // italic
+ false, // monospaced
+ false, // outline = false, no such thing in MS-EMFPLUS
+ stringFormat && stringFormat->DirectionRightToLeft(), // right-to-left
+ false); // BiDiStrong
+
+ css::lang::Locale locale;
+ double stringAlignmentHorizontalOffset = 0.0;
+ double stringAlignmentVerticalOffset = font->emSize;
+ if (stringFormat)
+ {
+ LanguageTag aLanguageTag(static_cast<LanguageType>(stringFormat->language));
+ locale = aLanguageTag.getLocale();
+ drawinglayer::primitive2d::TextLayouterDevice aTextLayouter;
- drawinglayer::attribute::FontAttribute fontAttribute(
- font->family, // font family
- "", // (no) font style
- font->Bold() ? 8u : 1u, // weight: 8 = bold
- font->family == "SYMBOL", // symbol
- stringFormat && stringFormat->DirectionVertical(), // vertical
- font->Italic(), // italic
- false, // monospaced
- false, // outline = false, no such thing in MS-EMFPLUS
- stringFormat && stringFormat->DirectionRightToLeft(), // right-to-left
- false); // BiDiStrong
-
- css::lang::Locale locale;
- double stringAlignmentHorizontalOffset = 0.0;
- if (stringFormat)
- {
- SAL_WARN_IF(stringFormat->DirectionRightToLeft(), "drawinglayer", "EMF+\t DrawString Alignment TODO For a right-to-left layout rectangle, the origin should be at the upper right.");
- if (stringFormat->stringAlignment == StringAlignmentNear)
+ aTextLayouter.setFontAttribute(fontAttribute, font->emSize,
+ font->emSize, locale);
+
+ double fTextWidth = aTextLayouter.getTextWidth(text, 0, stringLength);
+ SAL_WARN_IF(stringFormat->DirectionRightToLeft(), "drawinglayer.emf",
+ "EMF+\t DrawString Alignment TODO For a right-to-left layout rectangle, the origin should be at the upper right.");
+ if (stringFormat->stringAlignment == StringAlignmentNear)
// Alignment is to the left side of the layout rectangle (lx, ly, lw, lh)
- {
- stringAlignmentHorizontalOffset = stringFormat->leadingMargin * font->emSize;
- } else if (stringFormat->stringAlignment == StringAlignmentCenter)
+ stringAlignmentHorizontalOffset = stringFormat->leadingMargin * font->emSize;
+ else if (stringFormat->stringAlignment == StringAlignmentCenter)
// Alignment is centered between the origin and extent of the layout rectangle
- {
- stringAlignmentHorizontalOffset = 0.5 * lw + stringFormat->leadingMargin * font->emSize - 0.3 * font->emSize * stringLength;
- } else if (stringFormat->stringAlignment == StringAlignmentFar)
+ stringAlignmentHorizontalOffset = 0.5 * lw + (stringFormat->leadingMargin - stringFormat->trailingMargin) * font->emSize - 0.5 * fTextWidth;
+ else if (stringFormat->stringAlignment == StringAlignmentFar)
// Alignment is to the right side of the layout rectangle
- {
- stringAlignmentHorizontalOffset = lw - stringFormat->trailingMargin * font->emSize - 0.6 * font->emSize * stringLength;
- }
+ stringAlignmentHorizontalOffset = lw - stringFormat->trailingMargin * font->emSize - fTextWidth;
+
+ if (stringFormat->lineAlign == StringAlignmentNear)
+ stringAlignmentVerticalOffset = font->emSize;
+ else if (stringFormat->lineAlign == StringAlignmentCenter)
+ stringAlignmentVerticalOffset = 0.5 * lh + 0.5 * font->emSize;
+ else if (stringFormat->lineAlign == StringAlignmentFar)
+ stringAlignmentVerticalOffset = lh;
+ }
+ else
+ {
+ // By default LeadingMargin is 1/6 inch
+ // TODO for typographic fonts set value to 0.
+ stringAlignmentHorizontalOffset = 16.0;
- LanguageTag aLanguageTag(static_cast< LanguageType >(stringFormat->language));
- locale = aLanguageTag.getLocale();
- }
- else
- {
- // By default LeadingMargin is 1/6 inch
- // TODO for typographic fonts set value to 0.
- stringAlignmentHorizontalOffset = 16.0;
+ // use system default
+ locale = Application::GetSettings().GetLanguageTag().getLocale();
+ }
- // use system default
- locale = Application::GetSettings().GetLanguageTag().getLocale();
- }
+ const basegfx::B2DHomMatrix transformMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
+ ::basegfx::B2DVector(font->emSize, font->emSize),
+ ::basegfx::B2DPoint(lx + stringAlignmentHorizontalOffset,
+ ly + stringAlignmentVerticalOffset));
+
+ Color uncorrectedColor = EMFPGetBrushColorOrARGBColor(flags, brushId);
+ Color color;
- const basegfx::B2DHomMatrix transformMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
- ::basegfx::B2DSize(font->emSize, font->emSize),
- ::basegfx::B2DPoint(lx + stringAlignmentHorizontalOffset, ly + font->emSize));
+ if (mbSetTextContrast)
+ {
+ const auto gammaVal = mnTextContrast / 1000;
+ const basegfx::BColorModifier_gamma gamma(gammaVal);
+
+ // gamma correct transparency color
+ sal_uInt16 alpha = uncorrectedColor.GetAlpha();
+ alpha = std::clamp(std::pow(alpha, 1.0 / gammaVal), 0.0, 1.0) * 255;
+
+ basegfx::BColor modifiedColor(gamma.getModifiedColor(uncorrectedColor.getBColor()));
+ color.SetRed(modifiedColor.getRed() * 255);
+ color.SetGreen(modifiedColor.getGreen() * 255);
+ color.SetBlue(modifiedColor.getBlue() * 255);
+ color.SetAlpha(alpha);
+ }
+ else
+ {
+ color = uncorrectedColor;
+ }
- Color uncorrectedColor = EMFPGetBrushColorOrARGBColor(flags, brushId);
- Color color;
+ mrPropertyHolders.Current().setTextColor(color.getBColor());
+ mrPropertyHolders.Current().setTextColorActive(true);
- if (mbSetTextContrast)
+ if (color.GetAlpha() > 0)
+ {
+ std::vector<double> emptyVector;
+ rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pBaseText;
+ if (font->Underline() || font->Strikeout())
{
- const auto gammaVal = mnTextContrast / 1000;
- const basegfx::BColorModifier_gamma gamma(gammaVal);
-
- // gamma correct transparency color
- sal_uInt16 alpha = uncorrectedColor.GetTransparency();
- alpha = std::clamp(std::pow(alpha, 1.0 / gammaVal), 0.0, 1.0) * 255;
-
- basegfx::BColor modifiedColor(gamma.getModifiedColor(uncorrectedColor.getBColor()));
- color.SetRed(modifiedColor.getRed() * 255);
- color.SetGreen(modifiedColor.getGreen() * 255);
- color.SetBlue(modifiedColor.getBlue() * 255);
- color.SetTransparency(alpha);
+ pBaseText = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
+ transformMatrix,
+ text,
+ 0, // text always starts at 0
+ stringLength,
+ std::move(emptyVector), // EMF-PLUS has no DX-array
+ {},
+ std::move(fontAttribute),
+ locale,
+ color.getBColor(), // Font Color
+ COL_TRANSPARENT, // Fill Color
+ color.getBColor(), // OverlineColor
+ color.getBColor(), // TextlineColor
+ drawinglayer::primitive2d::TEXT_LINE_NONE,
+ font->Underline() ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE,
+ false,
+ font->Strikeout() ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE);
}
else
{
- color = uncorrectedColor;
+ pBaseText = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ transformMatrix,
+ text,
+ 0, // text always starts at 0
+ stringLength,
+ std::move(emptyVector), // EMF-PLUS has no DX-array
+ {},
+ std::move(fontAttribute),
+ std::move(locale),
+ color.getBColor());
}
-
- mrPropertyHolders.Current().setTextColor(color.getBColor());
- mrPropertyHolders.Current().setTextColorActive(true);
-
- if (color.GetTransparency() < 255)
+ drawinglayer::primitive2d::Primitive2DReference aPrimitiveText(pBaseText);
+ if (color.IsTransparent())
{
- std::vector<double> emptyVector;
- drawinglayer::primitive2d::BasePrimitive2D* pBaseText = nullptr;
- if (font->Underline() || font->Strikeout())
- {
- pBaseText = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
- transformMatrix,
- text,
- 0, // text always starts at 0
- stringLength,
- emptyVector, // EMF-PLUS has no DX-array
- fontAttribute,
- locale,
- color.getBColor(),
- COL_TRANSPARENT,
- color.getBColor(),
- color.getBColor(),
- drawinglayer::primitive2d::TEXT_LINE_NONE,
- font->Underline() ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE,
- false,
- font->Strikeout() ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE);
- }
- else
- {
- pBaseText = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
- transformMatrix,
- text,
- 0, // text always starts at 0
- stringLength,
- emptyVector, // EMF-PLUS has no DX-array
- fontAttribute,
- locale,
- color.getBColor());
- }
- drawinglayer::primitive2d::Primitive2DReference aPrimitiveText(pBaseText);
- if (color.GetTransparency() != 0)
- {
- aPrimitiveText = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
- drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText },
- color.GetTransparency() / 255.0);
- }
-
- mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
- maMapTransform,
- drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText } ));
+ aPrimitiveText = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText },
+ (255 - color.GetAlpha()) / 255.0);
}
- }
- else
- {
- SAL_WARN("drawinglayer", "EMF+\t DrawString TODO - drawing with brush not yet supported");
+
+ mrTargetHolders.Current().append(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ maMapTransform,
+ drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText } ));
}
break;
}
case EmfPlusRecordTypeSetPageTransform:
{
rMS.ReadFloat(mfPageScale);
- SAL_INFO("drawinglayer", "EMF+\t Scale: " << mfPageScale << " unit: " << UnitTypeToString(flags));
+ SAL_INFO("drawinglayer.emf", "EMF+\t Scale: " << mfPageScale << " unit: " << UnitTypeToString(flags));
if ((flags == UnitTypeDisplay) || (flags == UnitTypeWorld))
{
- SAL_WARN("drawinglayer", "EMF+\t file error. UnitTypeDisplay and UnitTypeWorld are not supported by SetPageTransform in EMF+ specification.");
+ SAL_WARN("drawinglayer.emf", "EMF+\t file error. UnitTypeDisplay and UnitTypeWorld are not supported by SetPageTransform in EMF+ specification.");
}
else
{
- mnMmX *= mfPageScale * getUnitToPixelMultiplier(static_cast<UnitType>(flags), mnHDPI);
- mnMmY *= mfPageScale * getUnitToPixelMultiplier(static_cast<UnitType>(flags), mnVDPI);
+ mnMmX = std::round(unitToPixel(static_cast<double>(mnMmX) * mfPageScale, flags, Direction::horizontal));
+ mnMmY = std::round(unitToPixel(static_cast<double>(mnMmY) * mfPageScale, flags, Direction::vertical));
mappingChanged();
}
break;
@@ -1715,7 +1762,7 @@ namespace emfplushelper
case EmfPlusRecordTypeSetRenderingOrigin:
{
rMS.ReadInt32(mnOriginX).ReadInt32(mnOriginY);
- SAL_INFO("drawinglayer", "EMF+\t SetRenderingOrigin, [x,y]: " << mnOriginX << "," << mnOriginY);
+ SAL_INFO("drawinglayer.emf", "EMF+\t SetRenderingOrigin, [x,y]: " << mnOriginX << "," << mnOriginY);
break;
}
case EmfPlusRecordTypeSetTextContrast:
@@ -1726,51 +1773,51 @@ namespace emfplushelper
mbSetTextContrast = true;
mnTextContrast = flags & 0xFFF;
SAL_WARN_IF(mnTextContrast > UPPERGAMMA || mnTextContrast < LOWERGAMMA,
- "drawinglayer", "EMF+\t Gamma value is not with bounds 1000 to 2200, value is " << mnTextContrast);
+ "drawinglayer.emf", "EMF+\t Gamma value is not with bounds 1000 to 2200, value is " << mnTextContrast);
mnTextContrast = std::min(mnTextContrast, UPPERGAMMA);
mnTextContrast = std::max(mnTextContrast, LOWERGAMMA);
- SAL_INFO("drawinglayer", "EMF+\t Text contrast: " << (mnTextContrast / 1000) << " gamma");
+ SAL_INFO("drawinglayer.emf", "EMF+\t Text contrast: " << (mnTextContrast / 1000) << " gamma");
break;
}
case EmfPlusRecordTypeSetTextRenderingHint:
{
sal_uInt8 nTextRenderingHint = (flags & 0xFF) >> 1;
- SAL_INFO("drawinglayer", "EMF+\t Text rendering hint: " << TextRenderingHintToString(nTextRenderingHint));
- SAL_WARN("drawinglayer", "EMF+\t TODO SetTextRenderingHint");
+ SAL_INFO("drawinglayer.emf", "EMF+\t Text rendering hint: " << TextRenderingHintToString(nTextRenderingHint));
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO SetTextRenderingHint");
break;
}
case EmfPlusRecordTypeSetAntiAliasMode:
{
bool bUseAntiAlias = (flags & 0x0001);
sal_uInt8 nSmoothingMode = (flags & 0xFE00) >> 1;
- SAL_INFO("drawinglayer", "EMF+\t Antialiasing: " << (bUseAntiAlias ? "enabled" : "disabled"));
- SAL_INFO("drawinglayer", "EMF+\t Smoothing mode: " << SmoothingModeToString(nSmoothingMode));
- SAL_WARN("drawinglayer", "EMF+\t TODO SetAntiAliasMode");
+ SAL_INFO("drawinglayer.emf", "EMF+\t Antialiasing: " << (bUseAntiAlias ? "enabled" : "disabled"));
+ SAL_INFO("drawinglayer.emf", "EMF+\t Smoothing mode: " << SmoothingModeToString(nSmoothingMode));
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO SetAntiAliasMode");
break;
}
case EmfPlusRecordTypeSetInterpolationMode:
{
sal_uInt16 nInterpolationMode = flags & 0xFF;
- SAL_INFO("drawinglayer", "EMF+\t Interpolation mode: " << InterpolationModeToString(nInterpolationMode));
- SAL_WARN("drawinglayer", "EMF+\t TODO InterpolationMode");
+ SAL_INFO("drawinglayer.emf", "EMF+\t Interpolation mode: " << InterpolationModeToString(nInterpolationMode));
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO InterpolationMode");
break;
}
case EmfPlusRecordTypeSetPixelOffsetMode:
{
- SAL_INFO("drawinglayer", "EMF+\t Pixel offset mode: " << PixelOffsetModeToString(flags));
- SAL_WARN("drawinglayer", "EMF+\t TODO SetPixelOffsetMode");
+ SAL_INFO("drawinglayer.emf", "EMF+\t Pixel offset mode: " << PixelOffsetModeToString(flags));
+ SAL_WARN("drawinglayer.emf", "EMF+\t TODO SetPixelOffsetMode");
break;
}
case EmfPlusRecordTypeSetCompositingQuality:
{
- SAL_INFO("drawinglayer", "EMF+\t TODO SetCompositingQuality");
+ SAL_INFO("drawinglayer.emf", "EMF+\t TODO SetCompositingQuality");
break;
}
case EmfPlusRecordTypeSave:
{
sal_uInt32 stackIndex;
rMS.ReadUInt32(stackIndex);
- SAL_INFO("drawinglayer", "EMF+\t Save stack index: " << stackIndex);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Save stack index: " << stackIndex);
GraphicStatePush(mGSStack, stackIndex);
@@ -1780,36 +1827,36 @@ namespace emfplushelper
{
sal_uInt32 stackIndex;
rMS.ReadUInt32(stackIndex);
- SAL_INFO("drawinglayer", "EMF+\t Restore stack index: " << stackIndex);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Restore stack index: " << stackIndex);
- GraphicStatePop(mGSStack, stackIndex, mrPropertyHolders.Current());
+ GraphicStatePop(mGSStack, stackIndex);
break;
}
case EmfPlusRecordTypeBeginContainer:
{
float dx, dy, dw, dh;
ReadRectangle(rMS, dx, dy, dw, dh);
- SAL_INFO("drawinglayer", "EMF+\t Dest RectData: " << dx << "," << dy << " " << dw << "x" << dh);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Dest RectData: " << dx << "," << dy << " " << dw << "x" << dh);
float sx, sy, sw, sh;
ReadRectangle(rMS, sx, sy, sw, sh);
- SAL_INFO("drawinglayer", "EMF+\t Source RectData: " << sx << "," << sy << " " << sw << "x" << sh);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Source RectData: " << sx << "," << sy << " " << sw << "x" << sh);
sal_uInt32 stackIndex;
rMS.ReadUInt32(stackIndex);
- SAL_INFO("drawinglayer", "EMF+\t Begin Container stack index: " << stackIndex << ", PageUnit: " << flags);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Begin Container stack index: " << stackIndex << ", PageUnit: " << flags);
if ((flags == UnitTypeDisplay) || (flags == UnitTypeWorld))
{
- SAL_WARN("drawinglayer", "EMF+\t file error. UnitTypeDisplay and UnitTypeWorld are not supported by BeginContainer in EMF+ specification.");
+ SAL_WARN("drawinglayer.emf", "EMF+\t file error. UnitTypeDisplay and UnitTypeWorld are not supported by BeginContainer in EMF+ specification.");
break;
}
- const float aPageScaleX = getUnitToPixelMultiplier(static_cast<UnitType>(flags), mnHDPI);
- const float aPageScaleY = getUnitToPixelMultiplier(static_cast<UnitType>(flags), mnVDPI);
GraphicStatePush(mGSContainerStack, stackIndex);
const basegfx::B2DHomMatrix transform = basegfx::utils::createScaleTranslateB2DHomMatrix(
- aPageScaleX * ( dw / sw ), aPageScaleY * ( dh / sh ),
- aPageScaleX * ( dx - sx ), aPageScaleY * ( dy - sy) );
+ unitToPixel(static_cast<double>(dw) / sw, flags, Direction::horizontal),
+ unitToPixel(static_cast<double>(dh) / sh, flags, Direction::vertical),
+ unitToPixel(static_cast<double>(dx) - sx, flags, Direction::horizontal),
+ unitToPixel(static_cast<double>(dy) - sy, flags, Direction::vertical));
maWorldTransform *= transform;
mappingChanged();
break;
@@ -1818,7 +1865,7 @@ namespace emfplushelper
{
sal_uInt32 stackIndex;
rMS.ReadUInt32(stackIndex);
- SAL_INFO("drawinglayer", "EMF+\t Begin Container No Params stack index: " << stackIndex);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Begin Container No Params stack index: " << stackIndex);
GraphicStatePush(mGSContainerStack, stackIndex);
break;
@@ -1827,33 +1874,33 @@ namespace emfplushelper
{
sal_uInt32 stackIndex;
rMS.ReadUInt32(stackIndex);
- SAL_INFO("drawinglayer", "EMF+\t End Container stack index: " << stackIndex);
+ SAL_INFO("drawinglayer.emf", "EMF+\t End Container stack index: " << stackIndex);
- GraphicStatePop(mGSContainerStack, stackIndex, mrPropertyHolders.Current());
+ GraphicStatePop(mGSContainerStack, stackIndex);
break;
}
case EmfPlusRecordTypeSetWorldTransform:
{
- SAL_INFO("drawinglayer", "EMF+\t SetWorldTransform, Post multiply: " << bool(flags & 0x2000));
+ SAL_INFO("drawinglayer.emf", "EMF+\t SetWorldTransform, Post multiply: " << bool(flags & 0x2000));
readXForm(rMS, maWorldTransform);
mappingChanged();
- SAL_INFO("drawinglayer", "EMF+\t\t: " << maWorldTransform);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t: " << maWorldTransform);
break;
}
case EmfPlusRecordTypeResetWorldTransform:
{
maWorldTransform.identity();
- SAL_INFO("drawinglayer", "EMF+\t World transform: " << maWorldTransform);
+ SAL_INFO("drawinglayer.emf", "EMF+\t World transform: " << maWorldTransform);
mappingChanged();
break;
}
case EmfPlusRecordTypeMultiplyWorldTransform:
{
- SAL_INFO("drawinglayer", "EMF+\t MultiplyWorldTransform, post multiply: " << bool(flags & 0x2000));
+ SAL_INFO("drawinglayer.emf", "EMF+\t MultiplyWorldTransform, post multiply: " << bool(flags & 0x2000));
basegfx::B2DHomMatrix transform;
readXForm(rMS, transform);
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t Transform matrix: " << transform);
if (flags & 0x2000)
@@ -1870,13 +1917,13 @@ namespace emfplushelper
mappingChanged();
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t World transform matrix: " << maWorldTransform);
break;
}
case EmfPlusRecordTypeTranslateWorldTransform:
{
- SAL_INFO("drawinglayer", "EMF+\t TranslateWorldTransform, Post multiply: " << bool(flags & 0x2000));
+ SAL_INFO("drawinglayer.emf", "EMF+\t TranslateWorldTransform, Post multiply: " << bool(flags & 0x2000));
basegfx::B2DHomMatrix transform;
float eDx, eDy;
@@ -1884,7 +1931,7 @@ namespace emfplushelper
transform.set(0, 2, eDx);
transform.set(1, 2, eDy);
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t Translate matrix: " << transform);
if (flags & 0x2000)
@@ -1901,7 +1948,7 @@ namespace emfplushelper
mappingChanged();
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t World transform matrix: " << maWorldTransform);
break;
}
@@ -1913,9 +1960,9 @@ namespace emfplushelper
transform.set(0, 0, eSx);
transform.set(1, 1, eSy);
- SAL_INFO("drawinglayer", "EMF+\t ScaleWorldTransform Sx: " << eSx <<
+ SAL_INFO("drawinglayer.emf", "EMF+\t ScaleWorldTransform Sx: " << eSx <<
" Sy: " << eSy << ", Post multiply:" << bool(flags & 0x2000));
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t World transform matrix: " << maWorldTransform);
if (flags & 0x2000)
@@ -1932,7 +1979,7 @@ namespace emfplushelper
mappingChanged();
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t World transform matrix: " << maWorldTransform);
break;
}
@@ -1942,20 +1989,20 @@ namespace emfplushelper
float eAngle;
rMS.ReadFloat(eAngle);
- SAL_INFO("drawinglayer", "EMF+\t RotateWorldTransform Angle: " << eAngle <<
+ SAL_INFO("drawinglayer.emf", "EMF+\t RotateWorldTransform Angle: " << eAngle <<
", post multiply: " << bool(flags & 0x2000));
// Skipping flags & 0x2000
// For rotation transformation there is no difference between post and pre multiply
maWorldTransform.rotate(basegfx::deg2rad(eAngle));
mappingChanged();
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t " << maWorldTransform);
break;
}
case EmfPlusRecordTypeResetClip:
{
- SAL_INFO("drawinglayer", "EMF+ ResetClip");
+ SAL_INFO("drawinglayer.emf", "EMF+ ResetClip");
// We don't need to read anything more, as Size needs to be set 0x0000000C
// and DataSize must be set to 0.
@@ -1964,74 +2011,107 @@ namespace emfplushelper
break;
}
case EmfPlusRecordTypeSetClipRect:
- {
- int combineMode = (flags >> 8) & 0xf;
-
- SAL_INFO("drawinglayer", "EMF+\t SetClipRect combine mode: " << combineMode);
-
- float dx, dy, dw, dh;
- ReadRectangle(rMS, dx, dy, dw, dh);
- SAL_INFO("drawinglayer", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
- ::basegfx::B2DPoint mappedPoint1(Map(dx, dy));
- ::basegfx::B2DPoint mappedPoint2(Map(dx + dw, dy + dh));
-
- ::basegfx::B2DPolyPolygon polyPolygon(
- ::basegfx::utils::createPolygonFromRect(
- ::basegfx::B2DRectangle(
- mappedPoint1.getX(),
- mappedPoint1.getY(),
- mappedPoint2.getX(),
- mappedPoint2.getY())));
-
- HandleNewClipRegion(combineClip(mrPropertyHolders.Current().getClipPolyPolygon(),
- combineMode, polyPolygon), mrTargetHolders, mrPropertyHolders);
- break;
- }
case EmfPlusRecordTypeSetClipPath:
+ case EmfPlusRecordTypeSetClipRegion:
{
int combineMode = (flags >> 8) & 0xf;
- SAL_INFO("drawinglayer", "EMF+\t SetClipPath combine mode: " << combineMode);
- SAL_INFO("drawinglayer", "EMF+\t Path in slot: " << (flags & 0xff));
-
- EMFPPath *path = static_cast<EMFPPath*>(maEMFPObjects[flags & 0xff].get());
- if (!path)
+ ::basegfx::B2DPolyPolygon polyPolygon;
+ if (type == EmfPlusRecordTypeSetClipRect)
{
- SAL_WARN("drawinglayer", "EMF+\t TODO Unable to find path in slot: " << (flags & 0xff));
- break;
+ SAL_INFO("drawinglayer.emf", "EMF+\t SetClipRect");
+
+ float dx, dy, dw, dh;
+ ReadRectangle(rMS, dx, dy, dw, dh);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh);
+ ::basegfx::B2DPoint mappedPoint1(Map(dx, dy));
+ ::basegfx::B2DPoint mappedPoint2(Map(dx + dw, dy + dh));
+
+ polyPolygon
+ = ::basegfx::B2DPolyPolygon(::basegfx::utils::createPolygonFromRect(
+ ::basegfx::B2DRectangle(mappedPoint1.getX(), mappedPoint1.getY(),
+ mappedPoint2.getX(), mappedPoint2.getY())));
}
+ else if (type == EmfPlusRecordTypeSetClipPath)
+ {
+ SAL_INFO("drawinglayer.emf", "EMF+\tSetClipPath " << (flags & 0xff));
- ::basegfx::B2DPolyPolygon& clipPoly(path->GetPolygon(*this));
-
- HandleNewClipRegion(combineClip(mrPropertyHolders.Current().getClipPolyPolygon(),
- combineMode, clipPoly), mrTargetHolders, mrPropertyHolders);
- break;
- }
- case EmfPlusRecordTypeSetClipRegion:
- {
- int combineMode = (flags >> 8) & 0xf;
- SAL_INFO("drawinglayer", "EMF+\t Region in slot: " << (flags & 0xff));
- SAL_INFO("drawinglayer", "EMF+\t Combine mode: " << combineMode);
- EMFPRegion *region = static_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get());
- if (!region)
+ EMFPPath* path = dynamic_cast<EMFPPath*>(maEMFPObjects[flags & 0xff].get());
+ if (!path)
+ {
+ SAL_WARN("drawinglayer.emf",
+ "EMF+\t TODO Unable to find path in slot: " << (flags & 0xff));
+ break;
+ }
+ polyPolygon = path->GetPolygon(*this);
+ }
+ else if (type == EmfPlusRecordTypeSetClipRegion)
{
- SAL_WARN("drawinglayer", "EMF+\t TODO Unable to find region in slot: " << (flags & 0xff));
- break;
+ SAL_INFO("drawinglayer.emf", "EMF+\t Region in slot: " << (flags & 0xff));
+ EMFPRegion* region
+ = dynamic_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get());
+ if (!region)
+ {
+ SAL_WARN(
+ "drawinglayer.emf",
+ "EMF+\t TODO Unable to find region in slot: " << (flags & 0xff));
+ break;
+ }
+ polyPolygon = region->regionPolyPolygon;
}
-
- HandleNewClipRegion(combineClip(mrPropertyHolders.Current().getClipPolyPolygon(),
- combineMode, region->regionPolyPolygon), mrTargetHolders, mrPropertyHolders);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Combine mode: " << combineMode);
+ ::basegfx::B2DPolyPolygon aClippedPolyPolygon;
+ if (mrPropertyHolders.Current().getClipPolyPolygonActive())
+ {
+ aClippedPolyPolygon
+ = combineClip(mrPropertyHolders.Current().getClipPolyPolygon(),
+ combineMode, polyPolygon);
+ }
+ else
+ {
+ //Combine with infinity
+ switch (combineMode)
+ {
+ case EmfPlusCombineModeReplace:
+ case EmfPlusCombineModeIntersect:
+ {
+ aClippedPolyPolygon = polyPolygon;
+ break;
+ }
+ case EmfPlusCombineModeUnion:
+ {
+ // Disable clipping as the clipping is infinity
+ aClippedPolyPolygon = ::basegfx::B2DPolyPolygon();
+ break;
+ }
+ case EmfPlusCombineModeXOR:
+ case EmfPlusCombineModeComplement:
+ {
+ //TODO It is not correct and it should be fixed
+ aClippedPolyPolygon = std::move(polyPolygon);
+ break;
+ }
+ case EmfPlusCombineModeExclude:
+ {
+ //TODO It is not correct and it should be fixed
+ aClippedPolyPolygon = ::basegfx::B2DPolyPolygon();
+ break;
+ }
+ }
+ }
+ HandleNewClipRegion(aClippedPolyPolygon, mrTargetHolders, mrPropertyHolders);
break;
}
case EmfPlusRecordTypeOffsetClip:
{
float dx, dy;
rMS.ReadFloat(dx).ReadFloat(dy);
- SAL_INFO("drawinglayer", "EMF+\tOffset x:" << dx << ", y:" << dy);
+ SAL_INFO("drawinglayer.emf", "EMF+\tOffset x:" << dx << ", y:" << dy);
basegfx::B2DPolyPolygon aPolyPolygon(
mrPropertyHolders.Current().getClipPolyPolygon());
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t PolyPolygon before translate: " << aPolyPolygon);
basegfx::B2DPoint aOffset = Map(dx, dy);
@@ -2040,7 +2120,7 @@ namespace emfplushelper
transformMatrix.set(1, 2, aOffset.getY());
aPolyPolygon.transform(transformMatrix);
- SAL_INFO("drawinglayer",
+ SAL_INFO("drawinglayer.emf",
"EMF+\t PolyPolygon after translate: " << aPolyPolygon <<
", mapped offset x" << aOffset.getX() << ", mapped offset y" << aOffset.getY());
HandleNewClipRegion(aPolyPolygon, mrTargetHolders, mrPropertyHolders);
@@ -2053,22 +2133,22 @@ namespace emfplushelper
sal_uInt32 hasMatrix;
sal_uInt32 glyphsCount;
rMS.ReadUInt32(brushIndexOrColor).ReadUInt32(optionFlags).ReadUInt32(hasMatrix).ReadUInt32(glyphsCount);
- SAL_INFO("drawinglayer", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
- SAL_INFO("drawinglayer", "EMF+\t Option flags: 0x" << std::hex << optionFlags << std::dec);
- SAL_INFO("drawinglayer", "EMF+\t Has matrix: " << hasMatrix);
- SAL_INFO("drawinglayer", "EMF+\t Glyphs: " << glyphsCount);
+ SAL_INFO("drawinglayer.emf", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Option flags: 0x" << std::hex << optionFlags << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Has matrix: " << hasMatrix);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Glyphs: " << glyphsCount);
if ((optionFlags & 1) && glyphsCount > 0)
{
std::unique_ptr<float[]> charsPosX(new float[glyphsCount]);
std::unique_ptr<float[]> charsPosY(new float[glyphsCount]);
OUString text = read_uInt16s_ToOUString(rMS, glyphsCount);
- SAL_INFO("drawinglayer", "EMF+\t DrawDriverString string: " << text);
+ SAL_INFO("drawinglayer.emf", "EMF+\t DrawDriverString string: " << text);
for (sal_uInt32 i = 0; i<glyphsCount; i++)
{
rMS.ReadFloat(charsPosX[i]).ReadFloat(charsPosY[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t glyphPosition[" << i << "]: " << charsPosX[i] << "," << charsPosY[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t glyphPosition[" << i << "]: " << charsPosX[i] << "," << charsPosY[i]);
}
basegfx::B2DHomMatrix transform;
@@ -2076,11 +2156,11 @@ namespace emfplushelper
if (hasMatrix)
{
readXForm(rMS, transform);
- SAL_INFO("drawinglayer", "EMF+\tmatrix: " << transform);
+ SAL_INFO("drawinglayer.emf", "EMF+\tmatrix: " << transform);
}
// get the font from the flags
- EMFPFont *font = static_cast< EMFPFont* >( maEMFPObjects[flags & 0xff].get() );
+ EMFPFont *font = dynamic_cast<EMFPFont*>(maEMFPObjects[flags & 0xff].get());
if (!font)
{
break;
@@ -2089,7 +2169,7 @@ namespace emfplushelper
drawinglayer::attribute::FontAttribute fontAttribute(
font->family, // font family
- "", // (no) font style
+ u""_ustr, // (no) font style
font->Bold() ? 8u : 1u, // weight: 8 = bold
font->family == "SYMBOL", // symbol
optionFlags & 0x2, // vertical
@@ -2100,7 +2180,6 @@ namespace emfplushelper
false); // BiDiStrong
const Color color = EMFPGetBrushColorOrARGBColor(flags, brushIndexOrColor);
- std::vector<double> aDXArray; // dummy for DX array (not used)
// generate TextSimplePortionPrimitive2Ds or TextDecoratedPortionPrimitive2D
// for all portions of text with the same charsPosY values
@@ -2113,7 +2192,7 @@ namespace emfplushelper
aLength++;
// generate the DX-Array
- aDXArray.clear();
+ std::vector<double> aDXArray;
for (size_t i = 0; i < aLength - 1; i++)
{
aDXArray.push_back(charsPosX[pos + i + 1] - charsPosX[pos]);
@@ -2122,13 +2201,13 @@ namespace emfplushelper
aDXArray.push_back(0);
basegfx::B2DHomMatrix transformMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
- ::basegfx::B2DSize(font->emSize, font->emSize),
+ ::basegfx::B2DVector(font->emSize, font->emSize),
::basegfx::B2DPoint(charsPosX[pos], charsPosY[pos]));
if (hasMatrix)
transformMatrix *= transform;
- if (color.GetTransparency() < 255)
+ if (color.GetAlpha() > 0)
{
- drawinglayer::primitive2d::BasePrimitive2D* pBaseText = nullptr;
+ rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pBaseText;
if (font->Underline() || font->Strikeout())
{
pBaseText = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
@@ -2136,7 +2215,8 @@ namespace emfplushelper
text,
pos, // take character at current pos
aLength, // use determined length
- aDXArray, // generated DXArray
+ std::move(aDXArray), // generated DXArray
+ {},
fontAttribute,
Application::GetSettings().GetLanguageTag().getLocale(),
color.getBColor(),
@@ -2155,20 +2235,21 @@ namespace emfplushelper
text,
pos, // take character at current pos
aLength, // use determined length
- aDXArray, // generated DXArray
+ std::move(aDXArray), // generated DXArray
+ {},
fontAttribute,
Application::GetSettings().GetLanguageTag().getLocale(),
color.getBColor());
}
drawinglayer::primitive2d::Primitive2DReference aPrimitiveText(pBaseText);
- if (color.GetTransparency() != 0)
+ if (color.IsTransparent())
{
aPrimitiveText = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText },
- color.GetTransparency() / 255.0);
+ (255 - color.GetAlpha()) / 255.0);
}
mrTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
maMapTransform,
drawinglayer::primitive2d::Primitive2DContainer { aPrimitiveText } ));
}
@@ -2179,13 +2260,13 @@ namespace emfplushelper
}
else
{
- SAL_WARN("drawinglayer", "EMF+\tTODO: fonts (non-unicode glyphs chars)");
+ SAL_WARN("drawinglayer.emf", "EMF+\tTODO: fonts (non-unicode glyphs chars)");
}
break;
}
default:
{
- SAL_WARN("drawinglayer", "EMF+ TODO unhandled record type: 0x" << std::hex << type << std::dec);
+ SAL_WARN("drawinglayer.emf", "EMF+ TODO unhandled record type: 0x" << std::hex << type << std::dec);
}
}
}
@@ -2198,7 +2279,7 @@ namespace emfplushelper
}
else
{
- SAL_WARN("drawinglayer", "ImplRenderer::processEMFPlus: "
+ SAL_WARN("drawinglayer.emf", "ImplRenderer::processEMFPlus: "
"size " << size << " > length " << length);
length = 0;
}
diff --git a/drawinglayer/source/tools/emfphelperdata.hxx b/drawinglayer/source/tools/emfphelperdata.hxx
index 500ceb323b02..51561e3161fa 100644
--- a/drawinglayer/source/tools/emfphelperdata.hxx
+++ b/drawinglayer/source/tools/emfphelperdata.hxx
@@ -17,17 +17,16 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPHELPERDATA_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPHELPERDATA_HXX
+#pragma once
#include <wmfemfhelper.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/attribute/linestartendattribute.hxx>
#include <tools/stream.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <map>
// predefines
-class SvStream;
namespace basegfx { class B2DPolyPolygon; }
namespace emfplushelper
@@ -54,9 +53,9 @@ namespace emfplushelper
#define EmfPlusRecordTypeFillRegion 0x4013
#define EmfPlusRecordTypeFillPath 0x4014
#define EmfPlusRecordTypeDrawPath 0x4015
- //TODO EmfPlusRecordTypeFillClosedCurve 0x4016
- //TODO EmfPlusRecordTypeDrawClosedCurve 0x4017
- //TODO EmfPlusRecordTypeDrawCurve 0x4018
+ #define EmfPlusRecordTypeFillClosedCurve 0x4016
+ #define EmfPlusRecordTypeDrawClosedCurve 0x4017
+ #define EmfPlusRecordTypeDrawCurve 0x4018
#define EmfPlusRecordTypeDrawBeziers 0x4019
#define EmfPlusRecordTypeDrawImage 0x401A
#define EmfPlusRecordTypeDrawImagePoints 0x401B
@@ -211,9 +210,15 @@ namespace emfplushelper
GraphicStateMap mGSStack;
GraphicStateMap mGSContainerStack;
+ /* Performance optimizators */
+ /* Extracted Scale values from Transformation Matrix */
+ double mdExtractedXScale;
+ double mdExtractedYScale;
+
/// data holders
wmfemfhelper::TargetHolders& mrTargetHolders;
wmfemfhelper::PropertyHolders& mrPropertyHolders;
+ wmfemfhelper::PropertyHolder aGetDCState;
bool bIsGetDCProcessing;
// readers
@@ -225,7 +230,10 @@ namespace emfplushelper
// stack actions
void GraphicStatePush(GraphicStateMap& map, sal_Int32 index);
- void GraphicStatePop (GraphicStateMap& map, sal_Int32 index, wmfemfhelper::PropertyHolder& rState);
+ void GraphicStatePop(GraphicStateMap& map, sal_Int32 index);
+
+ drawinglayer::attribute::LineStartEndAttribute CreateLineEnd(const sal_Int32 aCap,
+ const float aPenWidth) const;
// primitive creators
void EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon, sal_uInt32 penIndex);
@@ -235,6 +243,14 @@ namespace emfplushelper
// helper functions
Color EMFPGetBrushColorOrARGBColor(const sal_uInt16 flags, const sal_uInt32 brushIndexOrColor) const;
+ enum class Direction
+ {
+ horizontal,
+ vertical
+ };
+ sal_uInt32 DPI(Direction d) { return d == Direction::horizontal ? mnHDPI : mnVDPI; }
+ double unitToPixel(double n, sal_uInt32 aUnitType, Direction d);
+
public:
EmfPlusHelperData(
SvMemoryStream& rMS,
@@ -253,11 +269,7 @@ namespace emfplushelper
static void ReadRectangle(SvStream& s, float& x, float& y, float &width, float& height, bool bCompressed = false);
static bool readXForm(SvStream& rIn, basegfx::B2DHomMatrix& rTarget);
static ::basegfx::B2DPolyPolygon combineClip(::basegfx::B2DPolyPolygon const & leftPolygon, int combineMode, ::basegfx::B2DPolyPolygon const & rightPolygon);
-
- static float getUnitToPixelMultiplier(const UnitType aUnitType, const sal_uInt32 aDPI);
};
}
-#endif // INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPHELPERDATA_HXX
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpimage.cxx b/drawinglayer/source/tools/emfpimage.cxx
index 502eb2b74f0f..67a0cef99ed2 100644
--- a/drawinglayer/source/tools/emfpimage.cxx
+++ b/drawinglayer/source/tools/emfpimage.cxx
@@ -26,20 +26,20 @@ namespace emfplushelper
{
sal_uInt32 header, bitmapType;
s.ReadUInt32(header).ReadUInt32(type);
- SAL_INFO("drawinglayer", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
if (ImageDataTypeBitmap == type)
{
// bitmap
s.ReadInt32(width).ReadInt32(height).ReadInt32(stride).ReadUInt32(pixelFormat).ReadUInt32(bitmapType);
- SAL_INFO("drawinglayer", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << " bitmapType: 0x" << bitmapType << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << " bitmapType: 0x" << bitmapType << std::dec);
if ((bitmapType != 0) || (width == 0))
{
// non native formats
GraphicFilter filter;
- filter.ImportGraphic(graphic, OUString(), s);
- SAL_INFO("drawinglayer", "EMF+\tbitmap width: " << graphic.GetSizePixel().Width() << " height: " << graphic.GetSizePixel().Height());
+ filter.ImportGraphic(graphic, u"", s);
+ SAL_INFO("drawinglayer.emf", "EMF+\tbitmap width: " << graphic.GetSizePixel().Width() << " height: " << graphic.GetSizePixel().Height());
}
}
else if (ImageDataTypeMetafile == type)
@@ -53,12 +53,12 @@ namespace emfplushelper
else
dataSize -= 16;
- SAL_INFO("drawinglayer", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
+ SAL_INFO("drawinglayer.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
GraphicFilter filter;
// workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
SvMemoryStream mfStream(const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ);
- filter.ImportGraphic(graphic, OUString(), mfStream);
+ filter.ImportGraphic(graphic, u"", mfStream);
// debug code - write the stream to debug file /tmp/emf-stream.emf
#if OSL_DEBUG_LEVEL > 1
diff --git a/drawinglayer/source/tools/emfpimage.hxx b/drawinglayer/source/tools/emfpimage.hxx
index ed656e2c33db..75e42e7d21e4 100644
--- a/drawinglayer/source/tools/emfpimage.hxx
+++ b/drawinglayer/source/tools/emfpimage.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPIMAGE_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPIMAGE_HXX
+#pragma once
#include "emfphelperdata.hxx"
#include <vcl/graph.hxx>
@@ -46,6 +45,4 @@ namespace emfplushelper
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpimageattributes.cxx b/drawinglayer/source/tools/emfpimageattributes.cxx
index 8508172fe6a5..11c1f47173e4 100644
--- a/drawinglayer/source/tools/emfpimageattributes.cxx
+++ b/drawinglayer/source/tools/emfpimageattributes.cxx
@@ -22,14 +22,12 @@
#include "emfpimageattributes.hxx"
using namespace ::com::sun::star;
-using namespace ::basegfx;
namespace emfplushelper
{
EMFPImageAttributes::EMFPImageAttributes()
: EMFPObject()
, wrapMode(0)
- , clampColor(Color())
, objectClamp(0)
{
}
@@ -56,18 +54,18 @@ void EMFPImageAttributes::Read(SvStream& s)
clampColor.SetRed(clampColorRed);
clampColor.SetGreen(clampColorGreen);
clampColor.SetBlue(clampColorBlue);
- clampColor.SetTransparency(clampColorAlpha);
+ clampColor.SetAlpha(255 - clampColorAlpha);
- SAL_INFO("drawinglayer", "EMF+\timage attributes");
- SAL_WARN_IF((reserved1 != 0) || (reserved2 != 0), "drawinglayer",
+ SAL_INFO("drawinglayer.emf", "EMF+\timage attributes");
+ SAL_WARN_IF((reserved1 != 0) || (reserved2 != 0), "drawinglayer.emf",
"Reserved field(s) not zero - reserved1: " << std::hex << reserved1
<< " reserved2: " << reserved2);
SAL_WARN_IF((objectClamp != EmpPlusRectClamp) && (objectClamp != EmpPlusBitmapClamp),
- "drawinglayer", "Invalid object clamp - set to" << std::hex << objectClamp);
- SAL_INFO("drawinglayer", "EMF+\t image graphics version: 0x"
- << std::hex << graphicsVersion << " wrap mode: " << wrapMode
- << " clamp color: " << clampColor
- << " object clamp: " << objectClamp);
+ "drawinglayer.emf", "Invalid object clamp - set to" << std::hex << objectClamp);
+ SAL_INFO("drawinglayer.emf", "EMF+\t image graphics version: 0x"
+ << std::hex << graphicsVersion << " wrap mode: " << wrapMode
+ << " clamp color: " << clampColor
+ << " object clamp: " << objectClamp);
}
}
diff --git a/drawinglayer/source/tools/emfpimageattributes.hxx b/drawinglayer/source/tools/emfpimageattributes.hxx
index 0ac76938c9e7..a8ba375538b5 100644
--- a/drawinglayer/source/tools/emfpimageattributes.hxx
+++ b/drawinglayer/source/tools/emfpimageattributes.hxx
@@ -7,11 +7,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPIMAGEATTRIBUTES_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPIMAGEATTRIBUTES_HXX
+#pragma once
#include "emfphelperdata.hxx"
-#include <vector>
namespace emfplushelper
{
@@ -32,6 +30,4 @@ struct EMFPImageAttributes : public EMFPObject
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfppath.cxx b/drawinglayer/source/tools/emfppath.cxx
index 1f16c292cad8..cf841fd999e0 100644
--- a/drawinglayer/source/tools/emfppath.cxx
+++ b/drawinglayer/source/tools/emfppath.cxx
@@ -20,7 +20,6 @@
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <o3tl/safeint.hxx>
#include <sal/log.hxx>
#include "emfppath.hxx"
@@ -35,6 +34,13 @@ namespace
namespace emfplushelper
{
+ typedef double matrix [4][4];
+
+ constexpr sal_uInt32 nDetails = 8;
+ constexpr double alpha[nDetails]
+ = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails,
+ 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails };
+
// see 2.2.2.21 EmfPlusInteger7
// 2.2.2.22 EmfPlusInteger15
// and 2.2.2.37 EmfPlusPointR Object
@@ -58,15 +64,14 @@ namespace emfplushelper
return static_cast<sal_Int16>(nRet);
}
- EMFPPath::EMFPPath (sal_Int32 _nPoints, bool bLines)
+ EMFPPath::EMFPPath (sal_uInt32 _nPoints, bool bLines)
{
- if (_nPoints<0 || o3tl::make_unsigned(_nPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
+ if (_nPoints > SAL_MAX_UINT32 / (2 * sizeof(float)))
{
- _nPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+ _nPoints = SAL_MAX_UINT32 / (2 * sizeof(float));
}
nPoints = _nPoints;
- pPoints.reset( new float [nPoints*2] );
if (!bLines)
pPointTypes.reset( new sal_uInt8 [_nPoints] );
@@ -78,7 +83,8 @@ namespace emfplushelper
void EMFPPath::Read (SvStream& s, sal_uInt32 pathFlags)
{
- for (int i = 0; i < nPoints; i ++)
+ float fx, fy;
+ for (sal_uInt32 i = 0; i < nPoints; i++)
{
if (pathFlags & 0x800)
{
@@ -87,34 +93,36 @@ namespace emfplushelper
// If 0x800 bit is set, the 0x4000 bit is undefined and must be ignored
sal_Int32 x = GetEmfPlusInteger(s);
sal_Int32 y = GetEmfPlusInteger(s);
- pPoints [i*2] = x;
- pPoints [i*2 + 1] = y;
- SAL_INFO("drawinglayer", "EMF+\t\t\tEmfPlusPointR [x,y]: " << x << ", " << y);
+ xPoints.push_back(x);
+ yPoints.push_back(y);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPointR [x,y]: " << x << ", " << y);
}
else if (pathFlags & 0x4000)
{
// EMFPlusPoint: stored in signed short 16bit integer format
sal_Int16 x, y;
- s.ReadInt16( x ).ReadInt16( y );
- SAL_INFO ("drawinglayer", "EMF+\t\t\tEmfPlusPoint [x,y]: " << x << "," << y);
- pPoints [i*2] = x;
- pPoints [i*2 + 1] = y;
+ s.ReadInt16(x).ReadInt16(y);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPoint [x,y]: " << x << ", " << y);
+ xPoints.push_back(x);
+ yPoints.push_back(y);
}
else
{
// EMFPlusPointF: stored in Single (float) format
- s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
- SAL_INFO ("drawinglayer", "EMF+\t EMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
+ s.ReadFloat(fx).ReadFloat(fy);
+ SAL_INFO("drawinglayer.emf", "EMF+\t" << i << ". EMFPlusPointF [x,y]: " << fx << ", " << fy);
+ xPoints.push_back(fx);
+ yPoints.push_back(fy);
}
}
if (pPointTypes)
{
- for (int i = 0; i < nPoints; i++)
+ for (sal_uInt32 i = 0; i < nPoints; i++)
{
s.ReadUChar(pPointTypes[i]);
- SAL_INFO("drawinglayer", "EMF+\tpoint type: " << static_cast<int>(pPointTypes[i]));
+ SAL_INFO("drawinglayer.emf", "EMF+\tpoint type: 0x" << std::hex << static_cast<int>(pPointTypes[i]) << std::dec);
}
}
@@ -125,11 +133,11 @@ namespace emfplushelper
{
::basegfx::B2DPolygon polygon;
aPolygon.clear ();
- int last_normal = 0, p = 0;
+ sal_uInt32 last_normal = 0, p = 0;
::basegfx::B2DPoint prev, mapped;
bool hasPrev = false;
- for (int i = 0; i < nPoints; i ++)
+ for (sal_uInt32 i = 0; i < nPoints; i++)
{
if (p && pPointTypes && (pPointTypes [i] == 0))
{
@@ -140,9 +148,9 @@ namespace emfplushelper
}
if (bMapIt)
- mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
+ mapped = rR.Map(xPoints[i], yPoints [i]);
else
- mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
+ mapped = ::basegfx::B2DPoint(xPoints[i], yPoints[i]);
if (pPointTypes)
{
@@ -150,8 +158,9 @@ namespace emfplushelper
{
if (((i - last_normal )% 3) == 1)
{
+ assert(p != 0);
polygon.setNextControlPoint (p - 1, mapped);
- SAL_INFO ("drawinglayer", "EMF+\t\tPolygon append next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\tPolygon append next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
continue;
}
else if (((i - last_normal) % 3) == 2)
@@ -168,23 +177,22 @@ namespace emfplushelper
}
polygon.append (mapped);
- SAL_INFO ("drawinglayer", "EMF+\t\tPolygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\tPoint: " << xPoints[i] << "," << yPoints[i] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
if (hasPrev)
{
polygon.setPrevControlPoint (p, prev);
- SAL_INFO ("drawinglayer", "EMF+\t\tPolygon append prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\tPolygon append prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
hasPrev = false;
}
- p ++;
+ p++;
- if (pPointTypes && (pPointTypes [i] & 0x80))
+ if (pPointTypes && (pPointTypes [i] & 0x80)) // closed polygon
{
- // closed polygon
polygon.setClosed (true);
aPolygon.append (polygon);
- SAL_INFO ("drawinglayer", "EMF+\t\tClose polygon");
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\tClose polygon");
last_normal = i + 1;
p = 0;
polygon.clear ();
@@ -204,17 +212,17 @@ namespace emfplushelper
#if OSL_DEBUG_LEVEL > 1
for (unsigned int i=0; i<aPolygon.count(); i++) {
polygon = aPolygon.getB2DPolygon(i);
- SAL_INFO ("drawinglayer", "EMF+\t\tPolygon: " << i);
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\tPolygon: " << i);
for (unsigned int j=0; j<polygon.count(); j++) {
::basegfx::B2DPoint point = polygon.getB2DPoint(j);
- SAL_INFO ("drawinglayer", "EMF+\t\t\tPoint: " << point.getX() << "," << point.getY());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\t\tPoint: " << point.getX() << "," << point.getY());
if (polygon.isPrevControlPointUsed(j)) {
point = polygon.getPrevControlPoint(j);
- SAL_INFO ("drawinglayer", "EMF+\t\t\tPrev: " << point.getX() << "," << point.getY());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\t\tPrev: " << point.getX() << "," << point.getY());
}
if (polygon.isNextControlPointUsed(j)) {
point = polygon.getNextControlPoint(j);
- SAL_INFO ("drawinglayer", "EMF+\t\t\tNext: " << point.getX() << "," << point.getY());
+ SAL_INFO ("drawinglayer.emf", "EMF+\t\t\tNext: " << point.getX() << "," << point.getY());
}
}
}
@@ -223,6 +231,91 @@ namespace emfplushelper
return aPolygon;
}
+
+ static void GetCardinalMatrix(float tension, matrix& m)
+ {
+ m[0][1] = 2. - tension;
+ m[0][2] = tension - 2.;
+ m[1][0] = 2. * tension;
+ m[1][1] = tension - 3.;
+ m[1][2] = 3. - 2. * tension;
+ m[3][1] = 1.;
+ m[0][3] = m[2][2] = tension;
+ m[0][0] = m[1][3] = m[2][0] = -tension;
+ m[2][1] = m[2][3] = m[3][0] = m[3][2] = m[3][3] = 0.;
+ }
+
+ static double calculateSplineCoefficients(float p0, float p1, float p2, float p3, sal_uInt32 step, matrix m)
+ {
+ double a = m[0][0] * p0 + m[0][1] * p1 + m[0][2] * p2 + m[0][3] * p3;
+ double b = m[1][0] * p0 + m[1][1] * p1 + m[1][2] * p2 + m[1][3] * p3;
+ double c = m[2][0] * p0 + m[2][2] * p2;
+ double d = p1;
+ return (d + alpha[step] * (c + alpha[step] * (b + alpha[step] * a)));
+ }
+
+ ::basegfx::B2DPolyPolygon& EMFPPath::GetCardinalSpline(EmfPlusHelperData const& rR, float fTension,
+ sal_uInt32 aOffset, sal_uInt32 aNumSegments)
+ {
+ ::basegfx::B2DPolygon polygon;
+ matrix mat;
+ double x, y;
+ if (aNumSegments >= nPoints)
+ aNumSegments = nPoints - 1;
+ GetCardinalMatrix(fTension, mat);
+ // duplicate first point
+ xPoints.push_front(xPoints.front());
+ yPoints.push_front(yPoints.front());
+ // duplicate last point
+ xPoints.push_back(xPoints.back());
+ yPoints.push_back(yPoints.back());
+
+ for (sal_uInt32 i = 3 + aOffset; i < aNumSegments + 3; i++)
+ {
+ for (sal_uInt32 s = 0; s < nDetails; s++)
+ {
+ x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1],
+ xPoints[i], s, mat);
+ y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1],
+ yPoints[i], s, mat);
+ polygon.append(rR.Map(x, y));
+ }
+ }
+ if (polygon.count())
+ aPolygon.append(polygon);
+ return aPolygon;
+ }
+
+ ::basegfx::B2DPolyPolygon& EMFPPath::GetClosedCardinalSpline(EmfPlusHelperData const& rR, float fTension)
+ {
+ ::basegfx::B2DPolygon polygon;
+ matrix mat;
+ double x, y;
+ GetCardinalMatrix(fTension, mat);
+ // add three first points at the end
+ xPoints.push_back(xPoints[0]);
+ yPoints.push_back(yPoints[0]);
+ xPoints.push_back(xPoints[1]);
+ yPoints.push_back(yPoints[1]);
+ xPoints.push_back(xPoints[2]);
+ yPoints.push_back(yPoints[2]);
+
+ for (sal_uInt32 i = 3; i < nPoints + 3; i++)
+ {
+ for (sal_uInt32 s = 0; s < nDetails; s++)
+ {
+ x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1],
+ xPoints[i], s, mat);
+ y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1],
+ yPoints[i], s, mat);
+ polygon.append(rR.Map(x, y));
+ }
+ }
+ polygon.setClosed(true);
+ if (polygon.count())
+ aPolygon.append(polygon);
+ return aPolygon;
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfppath.hxx b/drawinglayer/source/tools/emfppath.hxx
index 98996f834dd9..e6104fcb1fc7 100644
--- a/drawinglayer/source/tools/emfppath.hxx
+++ b/drawinglayer/source/tools/emfppath.hxx
@@ -17,30 +17,31 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPPATH_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPPATH_HXX
+#pragma once
#include "emfphelperdata.hxx"
namespace emfplushelper
{
- struct EMFPPath : public EMFPObject
+ class EMFPPath : public EMFPObject
{
::basegfx::B2DPolyPolygon aPolygon;
- sal_Int32 nPoints;
- std::unique_ptr<float[]> pPoints;
+ sal_uInt32 nPoints;
+ std::deque<float> xPoints, yPoints;
std::unique_ptr<sal_uInt8[]> pPointTypes;
- EMFPPath(sal_Int32 _nPoints, bool bLines = false);
+ public:
+ EMFPPath(sal_uInt32 _nPoints, bool bLines = false);
virtual ~EMFPPath() override;
void Read(SvStream& s, sal_uInt32 pathFlags);
::basegfx::B2DPolyPolygon& GetPolygon(EmfPlusHelperData const & rR, bool bMapIt = true, bool bAddLineToCloseShape = false);
+ ::basegfx::B2DPolyPolygon& GetCardinalSpline(EmfPlusHelperData const& rR, float fTension,
+ sal_uInt32 aOffset, sal_uInt32 aNumSegments);
+ ::basegfx::B2DPolyPolygon& GetClosedCardinalSpline(EmfPlusHelperData const& rR, float fTension);
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx
index c5e7d457be61..aaa944660110 100644
--- a/drawinglayer/source/tools/emfppen.cxx
+++ b/drawinglayer/source/tools/emfppen.cxx
@@ -18,9 +18,9 @@
*/
#include <com/sun/star/rendering/PathCapType.hpp>
-#include <com/sun/star/rendering/PathJoinType.hpp>
#include <o3tl/safeint.hxx>
#include <sal/log.hxx>
+#include <rtl/ustrbuf.hxx>
#include "emfppen.hxx"
#include "emfpcustomlinecap.hxx"
@@ -30,36 +30,15 @@ using namespace ::basegfx;
namespace emfplushelper
{
- namespace {
-
- enum EmfPlusPenData
- {
- PenDataTransform = 0x00000001,
- PenDataStartCap = 0x00000002,
- PenDataEndCap = 0x00000004,
- PenDataJoin = 0x00000008,
- PenDataMiterLimit = 0x00000010,
- PenDataLineStyle = 0x00000020,
- PenDataDashedLineCap = 0x00000040,
- PenDataDashedLineOffset = 0x00000080,
- PenDataDashedLine = 0x00000100,
- PenDataAlignment = 0x00000200,
- PenDataCompoundLine = 0x00000400,
- PenDataCustomStartCap = 0x00000800,
- PenDataCustomEndCap = 0x00001000
- };
-
- }
EMFPPen::EMFPPen()
- : EMFPBrush()
- , penDataFlags(0)
+ : penDataFlags(0)
, penUnit(0)
, penWidth(0.0)
, startCap(0)
, endCap(0)
- , lineJoin(0)
- , miterLimit(0.0)
+ , maLineJoin(basegfx::B2DLineJoin::Miter)
+ , fMiterMinimumAngle(basegfx::deg2rad(5.0))
, dashStyle(0)
, dashCap(0)
, dashOffset(0.0)
@@ -75,143 +54,142 @@ namespace emfplushelper
static OUString PenDataFlagsToString(sal_uInt32 flags)
{
- OUString sFlags;
+ rtl::OUStringBuffer sFlags;
if (flags & EmfPlusPenDataTransform)
- sFlags = "\nEMF+\t\t\tEmfPlusPenDataTransform";
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataTransform");
if (flags & EmfPlusPenDataStartCap)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataStartCap");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataStartCap");
if (flags & EmfPlusPenDataEndCap)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataEndCap");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataEndCap");
if (flags & EmfPlusPenDataJoin)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataJoin");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataJoin");
if (flags & EmfPlusPenDataMiterLimit)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataMiterLimit");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataMiterLimit");
if (flags & EmfPlusPenDataLineStyle)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataLineStyle");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataLineStyle");
if (flags & EmfPlusPenDataDashedLineCap)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLineCap");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLineCap");
if (flags & EmfPlusPenDataDashedLineOffset)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLineOffset");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLineOffset");
if (flags & EmfPlusPenDataDashedLine)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLine");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLine");
if (flags & EmfPlusPenDataAlignment)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataAlignment");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataAlignment");
if (flags & EmfPlusPenDataCompoundLine)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCompoundLine");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCompoundLine");
if (flags & EmfPlusPenDataCustomStartCap)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCustomStartCap");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCustomStartCap");
if (flags & EmfPlusPenDataCustomEndCap)
- sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCustomEndCap");
+ sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCustomEndCap");
- return sFlags;
+ return sFlags.makeStringAndClear();
}
static OUString LineCapTypeToString(sal_uInt32 linecap)
{
switch (linecap)
{
- case LineCapTypeFlat: return "LineCapTypeFlat";
- case LineCapTypeSquare: return "LineCapTypeSquare";
- case LineCapTypeRound: return "LineCapTypeRound";
- case LineCapTypeTriangle: return "LineCapTypeTriangle";
- case LineCapTypeNoAnchor: return "LineCapTypeNoAnchor";
- case LineCapTypeSquareAnchor: return "LineCapTypeSquareAnchor";
- case LineCapTypeRoundAnchor: return "LineCapTypeRoundAchor";
- case LineCapTypeDiamondAnchor: return "LineCapTypeDiamondAnchor";
- case LineCapTypeArrowAnchor: return "LineCapTypeArrowAnchor";
- case LineCapTypeAnchorMask: return "LineCapTypeAnchorMask";
- case LineCapTypeCustom: return "LineCapTypeCustom";
- }
- return "";
- }
-
- static OUString LineJoinTypeToString(sal_uInt32 jointype)
- {
- switch (jointype)
- {
- case LineJoinTypeMiter: return "LineJoinTypeMiter";
- case LineJoinTypeBevel: return "LineJoinTypeBevel";
- case LineJoinTypeRound: return "LineJoinTypeRound";
- case LineJoinTypeMiterClipped: return "LineJoinTypeMiterClipped";
+ case LineCapTypeFlat: return u"LineCapTypeFlat"_ustr;
+ case LineCapTypeSquare: return u"LineCapTypeSquare"_ustr;
+ case LineCapTypeRound: return u"LineCapTypeRound"_ustr;
+ case LineCapTypeTriangle: return u"LineCapTypeTriangle"_ustr;
+ case LineCapTypeNoAnchor: return u"LineCapTypeNoAnchor"_ustr;
+ case LineCapTypeSquareAnchor: return u"LineCapTypeSquareAnchor"_ustr;
+ case LineCapTypeRoundAnchor: return u"LineCapTypeRoundAchor"_ustr;
+ case LineCapTypeDiamondAnchor: return u"LineCapTypeDiamondAnchor"_ustr;
+ case LineCapTypeArrowAnchor: return u"LineCapTypeArrowAnchor"_ustr;
+ case LineCapTypeAnchorMask: return u"LineCapTypeAnchorMask"_ustr;
+ case LineCapTypeCustom: return u"LineCapTypeCustom"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString DashedLineCapTypeToString(sal_uInt32 dashedlinecaptype)
{
switch (dashedlinecaptype)
{
- case DashedLineCapTypeFlat: return "DashedLineCapTypeFlat";
- case DashedLineCapTypeRound: return "DashedLineCapTypeRound";
- case DashedLineCapTypeTriangle: return "DashedLineCapTypeTriangle";
+ case DashedLineCapTypeFlat: return u"DashedLineCapTypeFlat"_ustr;
+ case DashedLineCapTypeRound: return u"DashedLineCapTypeRound"_ustr;
+ case DashedLineCapTypeTriangle: return u"DashedLineCapTypeTriangle"_ustr;
}
- return "";
+ return u""_ustr;
}
static OUString PenAlignmentToString(sal_uInt32 alignment)
{
switch (alignment)
{
- case PenAlignmentCenter: return "PenAlignmentCenter";
- case PenAlignmentInset: return "PenAlignmentInset";
- case PenAlignmentLeft: return "PenAlignmentLeft";
- case PenAlignmentOutset: return "PenAlignmentOutset";
- case PenAlignmentRight: return "PenAlignmentRight";
+ case PenAlignmentCenter: return u"PenAlignmentCenter"_ustr;
+ case PenAlignmentInset: return u"PenAlignmentInset"_ustr;
+ case PenAlignmentLeft: return u"PenAlignmentLeft"_ustr;
+ case PenAlignmentOutset: return u"PenAlignmentOutset"_ustr;
+ case PenAlignmentRight: return u"PenAlignmentRight"_ustr;
}
- return "";
+ return u""_ustr;
}
- /// Convert stroke caps between EMF+ and rendering API
- sal_Int8 EMFPPen::lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
+ drawinglayer::attribute::StrokeAttribute
+ EMFPPen::GetStrokeAttribute(const double aTransformation) const
{
- switch (nEmfStroke)
+ if (penDataFlags & EmfPlusPenDataLineStyle // pen has a predefined line style
+ && dashStyle != EmfPlusLineStyleCustom)
{
- case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
- case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND;
+ const double pw = aTransformation * penWidth;
+ switch (dashStyle)
+ {
+ case EmfPlusLineStyleDash:
+ // [-loplugin:redundantfcast] false positive:
+ return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw });
+ case EmfPlusLineStyleDot:
+ // [-loplugin:redundantfcast] false positive:
+ return drawinglayer::attribute::StrokeAttribute({ pw, pw });
+ case EmfPlusLineStyleDashDot:
+ // [-loplugin:redundantfcast] false positive:
+ return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw, pw, pw });
+ case EmfPlusLineStyleDashDotDot:
+ // [-loplugin:redundantfcast] false positive:
+ return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw, pw, pw, pw, pw });
+ }
}
-
- // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
- // so return BUTT always
- return rendering::PathCapType::BUTT;
- }
-
- sal_Int8 EMFPPen::lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
- {
- switch (nEmfLineJoin)
+ else if (penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line
{
- case EmfPlusLineJoinTypeMiter: // fall-through
- case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
- case EmfPlusLineJoinTypeBevel: return rendering::PathJoinType::BEVEL;
- case EmfPlusLineJoinTypeRound: return rendering::PathJoinType::ROUND;
+ const double pw = aTransformation * penWidth;
+ // StrokeAttribute needs a double vector while the pen provides a float vector
+ std::vector<double> aPattern(dashPattern.size());
+ for (size_t i = 0; i < aPattern.size(); i++)
+ {
+ // convert from float to double and multiply with the adjusted pen width
+ aPattern[i] = pw * dashPattern[i];
+ }
+ return drawinglayer::attribute::StrokeAttribute(std::move(aPattern));
}
-
- assert(false); // Line Join type isn't in specification.
- return 0;
+ // EmfPlusLineStyleSolid: - do nothing special, use default stroke attribute
+ return drawinglayer::attribute::StrokeAttribute();
}
void EMFPPen::Read(SvStream& s, EmfPlusHelperData const & rR)
{
+ sal_Int32 lineJoin = EmfPlusLineJoinTypeMiter;
sal_uInt32 graphicsVersion, penType;
- int i;
s.ReadUInt32(graphicsVersion).ReadUInt32(penType).ReadUInt32(penDataFlags).ReadUInt32(penUnit).ReadFloat(penWidth);
- SAL_INFO("drawinglayer", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion);
- SAL_INFO("drawinglayer", "EMF+\t\tType: " << penType);
- SAL_INFO("drawinglayer", "EMF+\t\tPen data flags: 0x" << penDataFlags << PenDataFlagsToString(penDataFlags));
- SAL_INFO("drawinglayer", "EMF+\t\tUnit: " << UnitTypeToString(penUnit));
- SAL_INFO("drawinglayer", "EMF+\t\tWidth: " << std::dec << penWidth);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tType: " << penType);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tPen data flags: 0x" << penDataFlags << PenDataFlagsToString(penDataFlags));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tUnit: " << UnitTypeToString(penUnit));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tWidth: " << std::dec << penWidth);
// If a zero width is specified, a minimum value must be used, which is determined by the units
if (penWidth == 0.0)
@@ -220,138 +198,153 @@ namespace emfplushelper
: 0.05f; // 0.05f is taken from old EMF+ implementation (case of Unit == Pixel etc.)
}
- if (penDataFlags & PenDataTransform)
+ if (penDataFlags & EmfPlusPenDataTransform)
{
EmfPlusHelperData::readXForm(s, pen_transformation);
- SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataTransform: " << pen_transformation);
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO PenDataTransform: " << pen_transformation);
}
- if (penDataFlags & PenDataStartCap)
+ if (penDataFlags & EmfPlusPenDataStartCap)
{
s.ReadInt32(startCap);
- SAL_INFO("drawinglayer", "EMF+\t\tstartCap: " << LineCapTypeToString(startCap) << " (0x" << std::hex << startCap << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tstartCap: " << LineCapTypeToString(startCap) << " (0x" << std::hex << startCap << ")");
}
else
{
startCap = 0;
}
- if (penDataFlags & PenDataEndCap)
+ if (penDataFlags & EmfPlusPenDataEndCap)
{
s.ReadInt32(endCap);
- SAL_INFO("drawinglayer", "EMF+\t\tendCap: " << LineCapTypeToString(endCap) << " (0x" << std::hex << startCap << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tendCap: " << LineCapTypeToString(endCap) << " (0x" << std::hex << startCap << ")");
}
else
{
endCap = 0;
}
- if (penDataFlags & PenDataJoin)
+ if (penDataFlags & EmfPlusPenDataJoin)
{
s.ReadInt32(lineJoin);
- SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataJoin: " << LineJoinTypeToString(lineJoin) << " (0x" << std::hex << lineJoin << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t LineJoin: " << lineJoin);
+ switch (lineJoin)
+ {
+ case EmfPlusLineJoinTypeBevel:
+ maLineJoin = basegfx::B2DLineJoin::Bevel;
+ break;
+ case EmfPlusLineJoinTypeRound:
+ maLineJoin = basegfx::B2DLineJoin::Round;
+ break;
+ case EmfPlusLineJoinTypeMiter:
+ case EmfPlusLineJoinTypeMiterClipped:
+ default: // If nothing set, then apply Miter (based on MS Paint)
+ maLineJoin = basegfx::B2DLineJoin::Miter;
+ break;
+ }
}
else
- {
- lineJoin = 0;
- }
+ maLineJoin = basegfx::B2DLineJoin::Miter;
- if (penDataFlags & PenDataMiterLimit)
+ if (penDataFlags & EmfPlusPenDataMiterLimit)
{
+ float miterLimit;
s.ReadFloat(miterLimit);
- SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataMiterLimit: " << std::dec << miterLimit);
+
+ // EMF+ JoinTypeMiterClipped is working as our B2DLineJoin::Miter
+ // For EMF+ LineJoinTypeMiter we are simulating it by changing angle
+ if (lineJoin == EmfPlusLineJoinTypeMiter)
+ miterLimit = 3.0 * miterLimit;
+ // asin angle must be in range [-1, 1]
+ if (abs(miterLimit) > 1.0)
+ fMiterMinimumAngle = 2.0 * asin(1.0 / miterLimit);
+ else
+ // enable miter limit for all angles
+ fMiterMinimumAngle = basegfx::deg2rad(180.0);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t\t MiterLimit: " << std::dec << miterLimit
+ << ", Miter minimum angle (rad): " << fMiterMinimumAngle);
}
else
- {
- miterLimit = 0;
- }
+ fMiterMinimumAngle = basegfx::deg2rad(5.0);
+
- if (penDataFlags & PenDataLineStyle)
+ if (penDataFlags & EmfPlusPenDataLineStyle)
{
s.ReadInt32(dashStyle);
- SAL_INFO("drawinglayer", "EMF+\t\tdashStyle: " << DashedLineCapTypeToString(dashStyle) << " (0x" << std::hex << dashStyle << ")");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tdashStyle: " << DashedLineCapTypeToString(dashStyle) << " (0x" << std::hex << dashStyle << ")");
}
else
{
dashStyle = 0;
}
- if (penDataFlags & PenDataDashedLineCap)
+ if (penDataFlags & EmfPlusPenDataDashedLineCap)
{
s.ReadInt32(dashCap);
- SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineCap: 0x" << std::hex << dashCap);
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO PenDataDashedLineCap: 0x" << std::hex << dashCap);
}
else
{
dashCap = 0;
}
- if (penDataFlags & PenDataDashedLineOffset)
+ if (penDataFlags & EmfPlusPenDataDashedLineOffset)
{
s.ReadFloat(dashOffset);
- SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineOffset: 0x" << std::hex << dashOffset);
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO PenDataDashedLineOffset: 0x" << std::hex << dashOffset);
}
else
{
dashOffset = 0;
}
- if (penDataFlags & PenDataDashedLine)
+ if (penDataFlags & EmfPlusPenDataDashedLine)
{
dashStyle = EmfPlusLineStyleCustom;
- sal_Int32 dashPatternLen;
+ sal_uInt32 dashPatternLen;
- s.ReadInt32(dashPatternLen);
- SAL_INFO("drawinglayer", "EMF+\t\t\tdashPatternLen: " << dashPatternLen);
-
- if (dashPatternLen<0 || o3tl::make_unsigned(dashPatternLen)>SAL_MAX_INT32 / sizeof(float))
- {
- dashPatternLen = SAL_MAX_INT32 / sizeof(float);
- }
+ s.ReadUInt32(dashPatternLen);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\tdashPatternLen: " << dashPatternLen);
dashPattern.resize( dashPatternLen );
- for (i = 0; i < dashPatternLen; i++)
+ for (sal_uInt32 i = 0; i < dashPatternLen; i++)
{
s.ReadFloat(dashPattern[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
}
}
- if (penDataFlags & PenDataAlignment)
+ if (penDataFlags & EmfPlusPenDataAlignment)
{
s.ReadInt32(alignment);
- SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataAlignment: " << PenAlignmentToString(alignment) << " (0x" << std::hex << alignment << ")");
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTODO PenDataAlignment: " << PenAlignmentToString(alignment) << " (0x" << std::hex << alignment << ")");
}
else
{
alignment = 0;
}
- if (penDataFlags & PenDataCompoundLine)
+ if (penDataFlags & EmfPlusPenDataCompoundLine)
{
- SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataCompoundLine");
- sal_Int32 compoundArrayLen;
- s.ReadInt32(compoundArrayLen);
-
- if (compoundArrayLen<0 || o3tl::make_unsigned(compoundArrayLen)>SAL_MAX_INT32 / sizeof(float))
- {
- compoundArrayLen = SAL_MAX_INT32 / sizeof(float);
- }
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTODO PenDataCompoundLine");
+ sal_uInt32 compoundArrayLen;
+ s.ReadUInt32(compoundArrayLen);
compoundArray.resize(compoundArrayLen);
- for (i = 0; i < compoundArrayLen; i++)
+ for (sal_uInt32 i = 0; i < compoundArrayLen; i++)
{
s.ReadFloat(compoundArray[i]);
- SAL_INFO("drawinglayer", "EMF+\t\t\t\tcompoundArray[" << i << "]: " << compoundArray[i]);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tcompoundArray[" << i << "]: " << compoundArray[i]);
}
}
- if (penDataFlags & PenDataCustomStartCap)
+ if (penDataFlags & EmfPlusPenDataCustomStartCap)
{
- s.ReadInt32(customStartCapLen);
- SAL_INFO("drawinglayer", "EMF+\t\t\tcustomStartCapLen: " << customStartCapLen);
+ s.ReadUInt32(customStartCapLen);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\tcustomStartCapLen: " << customStartCapLen);
sal_uInt64 const pos = s.Tell();
customStartCap.reset( new EMFPCustomLineCap() );
@@ -365,10 +358,10 @@ namespace emfplushelper
customStartCapLen = 0;
}
- if (penDataFlags & PenDataCustomEndCap)
+ if (penDataFlags & EmfPlusPenDataCustomEndCap)
{
- s.ReadInt32(customEndCapLen);
- SAL_INFO("drawinglayer", "EMF+\t\t\tcustomEndCapLen: " << customEndCapLen);
+ s.ReadUInt32(customEndCapLen);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t\tcustomEndCapLen: " << customEndCapLen);
sal_uInt64 const pos = s.Tell();
customEndCap.reset( new EMFPCustomLineCap() );
diff --git a/drawinglayer/source/tools/emfppen.hxx b/drawinglayer/source/tools/emfppen.hxx
index 72ec12a2bed4..31812c8b0c0e 100644
--- a/drawinglayer/source/tools/emfppen.hxx
+++ b/drawinglayer/source/tools/emfppen.hxx
@@ -17,9 +17,9 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPPEN_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPPEN_HXX
+#pragma once
+#include <drawinglayer/attribute/strokeattribute.hxx>
#include "emfpbrush.hxx"
#include <vector>
@@ -27,6 +27,7 @@ namespace emfplushelper
{
const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
+ const sal_uInt32 EmfPlusLineCapTypeTriangle = 0x00000003;
const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
@@ -103,17 +104,17 @@ namespace emfplushelper
float penWidth;
sal_Int32 startCap;
sal_Int32 endCap;
- sal_Int32 lineJoin;
- float miterLimit;
+ basegfx::B2DLineJoin maLineJoin;
+ double fMiterMinimumAngle;
sal_Int32 dashStyle;
sal_Int32 dashCap;
float dashOffset;
std::vector<float> dashPattern;
sal_Int32 alignment;
std::vector<float> compoundArray;
- sal_Int32 customStartCapLen;
+ sal_uInt32 customStartCapLen;
std::unique_ptr<EMFPCustomLineCap> customStartCap;
- sal_Int32 customEndCapLen;
+ sal_uInt32 customEndCapLen;
std::unique_ptr<EMFPCustomLineCap> customEndCap;
EMFPPen();
@@ -122,11 +123,8 @@ namespace emfplushelper
void Read(SvStream& s, EmfPlusHelperData const & rR);
- static sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke);
- static sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin);
+ drawinglayer::attribute::StrokeAttribute GetStrokeAttribute(const double aTransformation) const;
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpregion.cxx b/drawinglayer/source/tools/emfpregion.cxx
index 7813e23e24ae..9fcced337733 100644
--- a/drawinglayer/source/tools/emfpregion.cxx
+++ b/drawinglayer/source/tools/emfpregion.cxx
@@ -46,7 +46,7 @@ namespace emfplushelper
sal_uInt32 dataType;
::basegfx::B2DPolyPolygon polygon;
s.ReadUInt32(dataType);
- SAL_INFO("drawinglayer", "EMF+\t Region node data type 0x" << std::hex << dataType << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t Region node data type 0x" << std::hex << dataType << std::dec);
switch (dataType)
{
@@ -65,32 +65,31 @@ namespace emfplushelper
{
float dx, dy, dw, dh;
s.ReadFloat(dx).ReadFloat(dy).ReadFloat(dw).ReadFloat(dh);
- SAL_INFO("drawinglayer", "EMF+\t\t RegionNodeDataTypeRect x:" << dx << ", y:" << dy <<
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeRect x:" << dx << ", y:" << dy <<
", width:" << dw << ", height:" << dh);
const ::basegfx::B2DPoint mappedStartPoint(rR.Map(dx, dy));
const ::basegfx::B2DPoint mappedEndPoint(rR.Map(dx + dw, dy + dh));
- const ::basegfx::B2DPolyPolygon polyPolygon(
+ polygon = ::basegfx::B2DPolyPolygon(
::basegfx::utils::createPolygonFromRect(
::basegfx::B2DRectangle(
mappedStartPoint.getX(),
mappedStartPoint.getY(),
mappedEndPoint.getX(),
mappedEndPoint.getY())));
- polygon = polyPolygon;
break;
}
case RegionNodeDataTypePath:
{
sal_Int32 pathLength;
s.ReadInt32(pathLength);
- SAL_INFO("drawinglayer", "EMF+\t\t RegionNodeDataTypePath, Path Length: " << pathLength << " bytes");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypePath, Path Length: " << pathLength << " bytes");
sal_uInt32 header, pathFlags;
sal_Int32 points;
s.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags);
- SAL_INFO("drawinglayer", "EMF+\t\t header: 0x" << std::hex << header <<
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t header: 0x" << std::hex << header <<
" points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec);
EMFPPath path(points);
@@ -100,21 +99,21 @@ namespace emfplushelper
}
case RegionNodeDataTypeEmpty:
{
- SAL_INFO("drawinglayer", "EMF+\t\t RegionNodeDataTypeEmpty");
- SAL_WARN("drawinglayer", "EMF+\t\t TODO we need to set empty polygon here");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeEmpty");
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO we need to set empty polygon here");
polygon = ::basegfx::B2DPolyPolygon();
break;
}
case RegionNodeDataTypeInfinite:
{
- SAL_INFO("drawinglayer", "EMF+\t\t RegionNodeDataTypeInfinite");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeInfinite");
polygon = ::basegfx::B2DPolyPolygon();
break;
}
default:
{
- SAL_WARN("drawinglayer", "EMF+\t\t Unhandled region type: 0x" << std::hex << dataType << std::dec);
+ SAL_WARN("drawinglayer.emf", "EMF+\t\t Unhandled region type: 0x" << std::hex << dataType << std::dec);
polygon = ::basegfx::B2DPolyPolygon();
}
}
@@ -126,7 +125,7 @@ namespace emfplushelper
sal_uInt32 header, count;
s.ReadUInt32(header).ReadUInt32(count);
// An array should be RegionNodeCount+1 of EmfPlusRegionNode objects.
- SAL_INFO("drawinglayer", "EMF+\t version: 0x" << std::hex << header << std::dec << ", region node count: " << count);
+ SAL_INFO("drawinglayer.emf", "EMF+\t version: 0x" << std::hex << header << std::dec << ", region node count: " << count);
regionPolyPolygon = ReadRegionNode(s, rR);
}
diff --git a/drawinglayer/source/tools/emfpregion.hxx b/drawinglayer/source/tools/emfpregion.hxx
index a027d9c62b37..a234abbb5539 100644
--- a/drawinglayer/source/tools/emfpregion.hxx
+++ b/drawinglayer/source/tools/emfpregion.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPREGION_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPREGION_HXX
+#pragma once
#include "emfphelperdata.hxx"
@@ -48,6 +47,4 @@ namespace emfplushelper
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/emfpstringformat.cxx b/drawinglayer/source/tools/emfpstringformat.cxx
index ad08f14a21be..c66aa090f438 100644
--- a/drawinglayer/source/tools/emfpstringformat.cxx
+++ b/drawinglayer/source/tools/emfpstringformat.cxx
@@ -18,6 +18,7 @@
*/
#include <sal/log.hxx>
+#include <rtl/ustrbuf.hxx>
#include "emfpstringformat.hxx"
namespace emfplushelper
@@ -43,78 +44,42 @@ namespace emfplushelper
static OUString StringFormatFlags(sal_uInt32 flag)
{
- OUString sFlags;
+ OUStringBuffer sFlags;
+ // These are extracted from enum in emfpstringformat.hxx
if (flag & StringFormatDirectionRightToLeft)
- sFlags = sFlags.concat("StringFormatDirectionRightToLeft");
+ sFlags.append("StringFormatDirectionRightToLeft ");
- if (flag & StringFormatDirectionRightToLeft)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
-
- sFlags = sFlags.concat("StringFormatDirectionRightToLeft");
- }
+ if (flag & StringFormatDirectionVertical)
+ sFlags.append("StringFormatDirectionVertical ");
if (flag & StringFormatNoFitBlackBox)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
-
- sFlags = sFlags.concat("StringFormatNoFitBlackBox");
- }
+ sFlags.append("StringFormatNoFitBlackBox ");
if (flag & StringFormatDisplayFormatControl)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatDisplayFormatControl ");
- sFlags = sFlags.concat("StringFormatDisplayFormatControl");
- }
if (flag & StringFormatNoFontFallback)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatNoFontFallback ");
- sFlags = sFlags.concat("StringFormatNoFontFallback");
- }
if (flag & StringFormatMeasureTrailingSpaces)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatMeasureTrailingSpaces ");
- sFlags = sFlags.concat("StringFormatMeasureTrailingSpaces");
- }
if (flag & StringFormatNoWrap)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatNoWrap ");
- sFlags = sFlags.concat("StringFormatNoWrap");
- }
if (flag & StringFormatLineLimit)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatLineLimit ");
- sFlags = sFlags.concat("StringFormatLineLimit");
- }
if (flag & StringFormatNoClip)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatNoClip ");
- sFlags = sFlags.concat("StringFormatNoClip");
- }
if (flag & StringFormatBypassGDI)
- {
- if (!sFlags.isEmpty())
- sFlags = sFlags.concat(", ");
+ sFlags.append("StringFormatBypassGDI ");
- sFlags = sFlags.concat("StringFormatBypassGDI");
- }
-
- return sFlags;
+ // There will be 1 extra space in the end. It could be truncated, but
+ // as it is for SAL_INFO() only, it would not be important
+ return sFlags.makeStringAndClear();
}
static OUString StringAlignmentString(sal_uInt32 nAlignment)
@@ -122,14 +87,14 @@ namespace emfplushelper
switch(nAlignment)
{
case StringAlignment::StringAlignmentNear:
- return "StringAlignmentNear";
+ return u"StringAlignmentNear"_ustr;
case StringAlignment::StringAlignmentCenter:
- return "StringAlignmentCenter";
+ return u"StringAlignmentCenter"_ustr;
case StringAlignment::StringAlignmentFar:
- return "StringAlignmentFar";
+ return u"StringAlignmentFar"_ustr;
default:
assert(false && nAlignment && "invalid string alignment value");
- return "INVALID";
+ return u"INVALID"_ustr;
}
}
@@ -138,16 +103,16 @@ namespace emfplushelper
switch(nSubst)
{
case StringDigitSubstitution::StringDigitSubstitutionUser:
- return "StringDigitSubstitutionUser";
+ return u"StringDigitSubstitutionUser"_ustr;
case StringDigitSubstitution::StringDigitSubstitutionNone:
- return "StringDigitSubstitutionNone";
+ return u"StringDigitSubstitutionNone"_ustr;
case StringDigitSubstitution::StringDigitSubstitutionNational:
- return "StringDigitSubstitutionNational";
+ return u"StringDigitSubstitutionNational"_ustr;
case StringDigitSubstitution::StringDigitSubstitutionTraditional:
- return "StringDigitSubstitutionTraditional";
+ return u"StringDigitSubstitutionTraditional"_ustr;
default:
assert(false && nSubst && "invalid string digit substitution value");
- return "INVALID";
+ return u"INVALID"_ustr;
}
}
@@ -156,14 +121,14 @@ namespace emfplushelper
switch(nHotkey)
{
case HotkeyPrefix::HotkeyPrefixNone:
- return "HotkeyPrefixNone";
+ return u"HotkeyPrefixNone"_ustr;
case HotkeyPrefix::HotkeyPrefixShow:
- return "HotkeyPrefixShow";
+ return u"HotkeyPrefixShow"_ustr;
case HotkeyPrefix::HotkeyPrefixHide:
- return "HotkeyPrefixHide";
+ return u"HotkeyPrefixHide"_ustr;
default:
assert(false && nHotkey && "invalid hotkey prefix value");
- return "INVALID";
+ return u"INVALID"_ustr;
}
}
@@ -172,20 +137,20 @@ namespace emfplushelper
switch(nTrimming)
{
case StringTrimming::StringTrimmingNone:
- return "StringTrimmingNone";
+ return u"StringTrimmingNone"_ustr;
case StringTrimming::StringTrimmingCharacter:
- return "StringTrimmingCharacter";
+ return u"StringTrimmingCharacter"_ustr;
case StringTrimming::StringTrimmingWord:
- return "StringTrimmingWord";
+ return u"StringTrimmingWord"_ustr;
case StringTrimming::StringTrimmingEllipsisCharacter:
- return "StringTrimmingEllipsisCharacter";
+ return u"StringTrimmingEllipsisCharacter"_ustr;
case StringTrimming::StringTrimmingEllipsisWord:
- return "StringTrimmingEllipsisWord";
+ return u"StringTrimmingEllipsisWord"_ustr;
case StringTrimming::StringTrimmingEllipsisPath:
- return "StringTrimmingEllipsisPath";
+ return u"StringTrimmingEllipsisPath"_ustr;
default:
assert(false && nTrimming && "invalid trim value");
- return "INVALID";
+ return u"INVALID"_ustr;
}
}
@@ -198,36 +163,32 @@ namespace emfplushelper
// keep only the last 16 bits of language
language >>= 16;
digitLanguage >>= 16;
- SAL_WARN_IF((header >> 12) != 0xdbc01, "drawinglayer", "Invalid header - not 0xdbc01");
- SAL_INFO("drawinglayer", "EMF+\tString format");
- SAL_INFO("drawinglayer", "EMF+\t\tHeader: 0x" << std::hex << (header >> 12));
- SAL_INFO("drawinglayer", "EMF+\t\tVersion: 0x" << (header & 0x1fff) << std::dec);
- SAL_INFO("drawinglayer", "EMF+\t\tStringFormatFlags: " << StringFormatFlags(stringFormatFlags));
- SAL_INFO("drawinglayer", "EMF+\t\tLanguage: sublangid: 0x" << std::hex << (language >> 10) << ", primarylangid: 0x" << (language & 0xF800));
- SAL_INFO("drawinglayer", "EMF+\t\tLineAlign: " << StringAlignmentString(lineAlign));
- SAL_INFO("drawinglayer", "EMF+\t\tDigitSubstitution: " << DigitSubstitutionString(digitSubstitution));
- SAL_INFO("drawinglayer", "EMF+\t\tDigitLanguage: sublangid: 0x" << std::hex << (digitLanguage >> 10) << ", primarylangid: 0x" << (digitLanguage & 0xF800));
- SAL_INFO("drawinglayer", "EMF+\t\tFirstTabOffset: " << firstTabOffset);
- SAL_INFO("drawinglayer", "EMF+\t\tHotkeyPrefix: " << HotkeyPrefixString(hotkeyPrefix));
- SAL_INFO("drawinglayer", "EMF+\t\tLeadingMargin: " << leadingMargin);
- SAL_INFO("drawinglayer", "EMF+\t\tTrailingMargin: " << trailingMargin);
- SAL_INFO("drawinglayer", "EMF+\t\tTracking: " << tracking);
- SAL_INFO("drawinglayer", "EMF+\t\tTrimming: " << StringTrimmingString(trimming));
- SAL_INFO("drawinglayer", "EMF+\t\tTabStopCount: " << tabStopCount);
- SAL_INFO("drawinglayer", "EMF+\t\tRangeCount: " << rangeCount);
-
- SAL_WARN_IF(stringAlignment != StringAlignment::StringAlignmentNear, "drawinglayer", "EMF+\t TODO EMFPStringFormat:StringAlignment");
- SAL_WARN_IF(lineAlign != StringAlignment::StringAlignmentNear, "drawinglayer", "EMF+\t TODO EMFPStringFormat:lineAlign");
+ SAL_WARN_IF((header >> 12) != 0xdbc01, "drawinglayer.emf", "Invalid header - not 0xdbc01");
+ SAL_INFO("drawinglayer.emf", "EMF+\tString format");
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tHeader: 0x" << std::hex << (header >> 12));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tVersion: 0x" << (header & 0x1fff) << std::dec);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tStringFormatFlags: " << StringFormatFlags(stringFormatFlags));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tLanguage: sublangid: 0x" << std::hex << (language >> 10) << ", primarylangid: 0x" << (language & 0xF800));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tLineAlign: " << StringAlignmentString(lineAlign));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tDigitSubstitution: " << DigitSubstitutionString(digitSubstitution));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tDigitLanguage: sublangid: 0x" << std::hex << (digitLanguage >> 10) << ", primarylangid: 0x" << (digitLanguage & 0xF800));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tFirstTabOffset: " << firstTabOffset);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tHotkeyPrefix: " << HotkeyPrefixString(hotkeyPrefix));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tLeadingMargin: " << leadingMargin);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tTrailingMargin: " << trailingMargin);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tTracking: " << tracking);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tTrimming: " << StringTrimmingString(trimming));
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tTabStopCount: " << tabStopCount);
+ SAL_INFO("drawinglayer.emf", "EMF+\t\tRangeCount: " << rangeCount);
+
SAL_WARN_IF(digitSubstitution != StringDigitSubstitution::StringDigitSubstitutionNone,
- "drawinglayer", "EMF+\t TODO EMFPStringFormat:digitSubstitution");
- SAL_WARN_IF(firstTabOffset != 0.0, "drawinglayer", "EMF+\t TODO EMFPStringFormat:firstTabOffset");
- SAL_WARN_IF(hotkeyPrefix != HotkeyPrefix::HotkeyPrefixNone, "drawinglayer", "EMF+\t TODO EMFPStringFormat:hotkeyPrefix");
- SAL_WARN_IF(leadingMargin != 0.0, "drawinglayer", "EMF+\t TODO EMFPStringFormat:leadingMargin");
- SAL_WARN_IF(trailingMargin != 0.0, "drawinglayer", "EMF+\t TODO EMFPStringFormat:trailingMargin");
- SAL_WARN_IF(tracking != 1.0, "drawinglayer", "EMF+\t TODO EMFPStringFormat:tracking");
- SAL_WARN_IF(trimming != StringTrimming::StringTrimmingNone, "drawinglayer", "EMF+\t TODO EMFPStringFormat:trimming");
- SAL_WARN_IF(tabStopCount, "drawinglayer", "EMF+\t TODO EMFPStringFormat:tabStopCount");
- SAL_WARN_IF(rangeCount, "drawinglayer", "EMF+\t TODO EMFPStringFormat:StringFormatData");
+ "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:digitSubstitution");
+ SAL_WARN_IF(firstTabOffset != 0.0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:firstTabOffset");
+ SAL_WARN_IF(hotkeyPrefix != HotkeyPrefix::HotkeyPrefixNone, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:hotkeyPrefix");
+ SAL_WARN_IF(tracking != 1.0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:tracking");
+ SAL_WARN_IF(trimming != StringTrimming::StringTrimmingNone, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:trimming");
+ SAL_WARN_IF(tabStopCount, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:tabStopCount");
+ SAL_WARN_IF(rangeCount != 0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:StringFormatData");
}
}
diff --git a/drawinglayer/source/tools/emfpstringformat.hxx b/drawinglayer/source/tools/emfpstringformat.hxx
index 69cad15a144d..b4d8cb380e36 100644
--- a/drawinglayer/source/tools/emfpstringformat.hxx
+++ b/drawinglayer/source/tools/emfpstringformat.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPSTRINGFORMAT_HXX
-#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPSTRINGFORMAT_HXX
+#pragma once
#include "emfphelperdata.hxx"
@@ -102,6 +101,4 @@ namespace emfplushelper
};
}
-#endif
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 7e68a780a84c..3cffb08bf81c 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -13,43 +13,65 @@
#include <tools/stream.hxx>
#include <tools/XmlWriter.hxx>
+#include <math.h>
#include <memory>
+#include <libxml/parser.h>
#include <sal/log.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/Tools.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokeArrowPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
#include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <primitive2d/textlineprimitive2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
+#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
+#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/attribute/lineattribute.hxx>
#include <drawinglayer/attribute/fontattribute.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <drawinglayer/primitive3d/baseprimitive3d.hxx>
+#include <drawinglayer/primitive3d/Tools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/sdrextrudeprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrlightattribute3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/fillhatchattribute.hxx>
+#include <drawinglayer/attribute/fillgradientattribute.hxx>
+#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
+#include <drawinglayer/attribute/materialattribute3d.hxx>
+#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
using namespace drawinglayer::primitive2d;
namespace drawinglayer
{
-
namespace
{
-
const size_t constMaxActionType = 513;
OUString convertColorToString(const basegfx::BColor& rColor)
@@ -58,6 +80,39 @@ OUString convertColorToString(const basegfx::BColor& rColor)
return "#" + aRGBString;
}
+void writeMatrix(::tools::XmlWriter& rWriter, const basegfx::B2DHomMatrix& rMatrix)
+{
+ rWriter.attribute("xy11", rMatrix.get(0, 0));
+ rWriter.attribute("xy12", rMatrix.get(0, 1));
+ rWriter.attribute("xy13", rMatrix.get(0, 2));
+ rWriter.attribute("xy21", rMatrix.get(1, 0));
+ rWriter.attribute("xy22", rMatrix.get(1, 1));
+ rWriter.attribute("xy23", rMatrix.get(1, 2));
+ rWriter.attribute("xy31", 0);
+ rWriter.attribute("xy32", 0);
+ rWriter.attribute("xy33", 1);
+}
+
+void writeMatrix3D(::tools::XmlWriter& rWriter, const basegfx::B3DHomMatrix& rMatrix)
+{
+ rWriter.attribute("xy11", rMatrix.get(0, 0));
+ rWriter.attribute("xy12", rMatrix.get(0, 1));
+ rWriter.attribute("xy13", rMatrix.get(0, 2));
+ rWriter.attribute("xy14", rMatrix.get(0, 3));
+ rWriter.attribute("xy21", rMatrix.get(1, 0));
+ rWriter.attribute("xy22", rMatrix.get(1, 1));
+ rWriter.attribute("xy23", rMatrix.get(1, 2));
+ rWriter.attribute("xy24", rMatrix.get(1, 3));
+ rWriter.attribute("xy31", rMatrix.get(2, 0));
+ rWriter.attribute("xy32", rMatrix.get(2, 1));
+ rWriter.attribute("xy33", rMatrix.get(2, 2));
+ rWriter.attribute("xy34", rMatrix.get(2, 3));
+ rWriter.attribute("xy41", rMatrix.get(3, 0));
+ rWriter.attribute("xy42", rMatrix.get(3, 1));
+ rWriter.attribute("xy43", rMatrix.get(3, 2));
+ rWriter.attribute("xy44", rMatrix.get(3, 3));
+}
+
void writePolyPolygon(::tools::XmlWriter& rWriter, const basegfx::B2DPolyPolygon& rB2DPolyPolygon)
{
rWriter.startElement("polypolygon");
@@ -70,12 +125,12 @@ void writePolyPolygon(::tools::XmlWriter& rWriter, const basegfx::B2DPolyPolygon
rWriter.attributeDouble("maxy", aB2DRange.getMaxY());
rWriter.attribute("path", basegfx::utils::exportToSvgD(rB2DPolyPolygon, true, true, false));
- for (basegfx::B2DPolygon const & rPolygon : rB2DPolyPolygon)
+ for (basegfx::B2DPolygon const& rPolygon : rB2DPolyPolygon)
{
rWriter.startElement("polygon");
- for (sal_uInt32 i = 0; i <rPolygon.count(); ++i)
+ for (sal_uInt32 i = 0; i < rPolygon.count(); ++i)
{
- basegfx::B2DPoint const & rPoint = rPolygon.getB2DPoint(i);
+ basegfx::B2DPoint const& rPoint = rPolygon.getB2DPoint(i);
rWriter.startElement("point");
rWriter.attribute("x", OUString::number(rPoint.getX()));
@@ -88,11 +143,377 @@ void writePolyPolygon(::tools::XmlWriter& rWriter, const basegfx::B2DPolyPolygon
rWriter.endElement();
}
+void writeStrokeAttribute(::tools::XmlWriter& rWriter,
+ const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute)
+{
+ if (!rStrokeAttribute.getDotDashArray().empty())
+ {
+ rWriter.startElement("stroke");
+
+ OUString sDotDash;
+ for (double fDotDash : rStrokeAttribute.getDotDashArray())
+ {
+ sDotDash += OUString::number(lround(fDotDash)) + " ";
+ }
+ rWriter.attribute("dotDashArray", sDotDash);
+ rWriter.attribute("fullDotDashLength", rStrokeAttribute.getFullDotDashLen());
+ rWriter.endElement();
+ }
+}
+
+void writeLineAttribute(::tools::XmlWriter& rWriter,
+ const drawinglayer::attribute::LineAttribute& rLineAttribute)
+{
+ rWriter.startElement("line");
+ rWriter.attribute("color", convertColorToString(rLineAttribute.getColor()));
+ rWriter.attribute("width", rLineAttribute.getWidth());
+ switch (rLineAttribute.getLineJoin())
+ {
+ case basegfx::B2DLineJoin::NONE:
+ rWriter.attribute("linejoin", "NONE"_ostr);
+ break;
+ case basegfx::B2DLineJoin::Bevel:
+ rWriter.attribute("linejoin", "Bevel"_ostr);
+ break;
+ case basegfx::B2DLineJoin::Miter:
+ {
+ rWriter.attribute("linejoin", "Miter"_ostr);
+ rWriter.attribute("miterangle",
+ basegfx::rad2deg(rLineAttribute.getMiterMinimumAngle()));
+ break;
+ }
+ case basegfx::B2DLineJoin::Round:
+ rWriter.attribute("linejoin", "Round"_ostr);
+ break;
+ default:
+ rWriter.attribute("linejoin", "Unknown"_ostr);
+ break;
+ }
+ switch (rLineAttribute.getLineCap())
+ {
+ case css::drawing::LineCap::LineCap_BUTT:
+ rWriter.attribute("linecap", "BUTT"_ostr);
+ break;
+ case css::drawing::LineCap::LineCap_ROUND:
+ rWriter.attribute("linecap", "ROUND"_ostr);
+ break;
+ case css::drawing::LineCap::LineCap_SQUARE:
+ rWriter.attribute("linecap", "SQUARE"_ostr);
+ break;
+ default:
+ rWriter.attribute("linecap", "Unknown"_ostr);
+ break;
+ }
+
+ rWriter.endElement();
+}
+
+void writeSdrLineAttribute(::tools::XmlWriter& rWriter,
+ const drawinglayer::attribute::SdrLineAttribute& rLineAttribute)
+{
+ if (rLineAttribute.isDefault())
+ return;
+
+ rWriter.startElement("line");
+ rWriter.attribute("color", convertColorToString(rLineAttribute.getColor()));
+ rWriter.attribute("width", rLineAttribute.getWidth());
+ rWriter.attribute("transparence", rLineAttribute.getTransparence());
+
+ switch (rLineAttribute.getJoin())
+ {
+ case basegfx::B2DLineJoin::NONE:
+ rWriter.attribute("linejoin", "NONE"_ostr);
+ break;
+ case basegfx::B2DLineJoin::Bevel:
+ rWriter.attribute("linejoin", "Bevel"_ostr);
+ break;
+ case basegfx::B2DLineJoin::Miter:
+ rWriter.attribute("linejoin", "Miter"_ostr);
+ break;
+ case basegfx::B2DLineJoin::Round:
+ rWriter.attribute("linejoin", "Round"_ostr);
+ break;
+ default:
+ rWriter.attribute("linejoin", "Unknown"_ostr);
+ break;
+ }
+ switch (rLineAttribute.getCap())
+ {
+ case css::drawing::LineCap::LineCap_BUTT:
+ rWriter.attribute("linecap", "BUTT"_ostr);
+ break;
+ case css::drawing::LineCap::LineCap_ROUND:
+ rWriter.attribute("linecap", "ROUND"_ostr);
+ break;
+ case css::drawing::LineCap::LineCap_SQUARE:
+ rWriter.attribute("linecap", "SQUARE"_ostr);
+ break;
+ default:
+ rWriter.attribute("linecap", "Unknown"_ostr);
+ break;
+ }
+
+ if (!rLineAttribute.getDotDashArray().empty())
+ {
+ OUString sDotDash;
+ for (double fDotDash : rLineAttribute.getDotDashArray())
+ {
+ sDotDash += OUString::number(fDotDash) + " ";
+ }
+ rWriter.attribute("dotDashArray", sDotDash);
+ rWriter.attribute("fullDotDashLength", rLineAttribute.getFullDotDashLen());
+ }
+
+ rWriter.endElement();
+}
+
+void writeSdrFillAttribute(::tools::XmlWriter& rWriter,
+ const drawinglayer::attribute::SdrFillAttribute& rFillAttribute)
+{
+ if (rFillAttribute.isDefault())
+ return;
+
+ rWriter.startElement("fill");
+ rWriter.attribute("color", convertColorToString(rFillAttribute.getColor()));
+ rWriter.attribute("transparence", rFillAttribute.getTransparence());
+
+ auto const& rGradient = rFillAttribute.getGradient();
+ if (!rGradient.isDefault())
+ {
+ rWriter.startElement("gradient");
+ switch (rGradient.getStyle())
+ {
+ default: // GradientStyle_MAKE_FIXED_SIZE
+ case css::awt::GradientStyle_LINEAR:
+ rWriter.attribute("style", "Linear"_ostr);
+ break;
+ case css::awt::GradientStyle_AXIAL:
+ rWriter.attribute("style", "Axial"_ostr);
+ break;
+ case css::awt::GradientStyle_RADIAL:
+ rWriter.attribute("style", "Radial"_ostr);
+ break;
+ case css::awt::GradientStyle_ELLIPTICAL:
+ rWriter.attribute("style", "Elliptical"_ostr);
+ break;
+ case css::awt::GradientStyle_SQUARE:
+ rWriter.attribute("style", "Square"_ostr);
+ break;
+ case css::awt::GradientStyle_RECT:
+ rWriter.attribute("style", "Rect"_ostr);
+ break;
+ }
+ rWriter.attribute("border", rGradient.getBorder());
+ rWriter.attribute("offsetX", rGradient.getOffsetX());
+ rWriter.attribute("offsetY", rGradient.getOffsetY());
+ rWriter.attribute("angle", rGradient.getAngle());
+ rWriter.attribute("steps", rGradient.getSteps());
+
+ auto const& rColorStops(rGradient.getColorStops());
+ for (size_t a(0); a < rColorStops.size(); a++)
+ {
+ if (0 == a)
+ rWriter.attribute("startColor",
+ convertColorToString(rColorStops[a].getStopColor()));
+ else if (rColorStops.size() == a + 1)
+ rWriter.attribute("endColor", convertColorToString(rColorStops[a].getStopColor()));
+ else
+ {
+ rWriter.startElement("colorStop");
+ rWriter.attribute("stopOffset", rColorStops[a].getStopOffset());
+ rWriter.attribute("stopColor", convertColorToString(rColorStops[a].getStopColor()));
+ rWriter.endElement();
+ }
+ }
+ rWriter.endElement();
+ }
+
+ auto const& rHatch = rFillAttribute.getHatch();
+ if (!rHatch.isDefault())
+ {
+ rWriter.startElement("hatch");
+ switch (rHatch.getStyle())
+ {
+ case drawinglayer::attribute::HatchStyle::Single:
+ rWriter.attribute("style", "Single"_ostr);
+ break;
+ case drawinglayer::attribute::HatchStyle::Double:
+ rWriter.attribute("style", "Double"_ostr);
+ break;
+ case drawinglayer::attribute::HatchStyle::Triple:
+ rWriter.attribute("style", "Triple"_ostr);
+ break;
+ }
+ rWriter.attribute("distance", rHatch.getDistance());
+ rWriter.attribute("angle", rHatch.getAngle());
+ rWriter.attribute("color", convertColorToString(rHatch.getColor()));
+ rWriter.attribute("minimalDescreteDistance", rHatch.getMinimalDiscreteDistance());
+ rWriter.attribute("isFillBackground", sal_Int32(rHatch.isFillBackground()));
+ rWriter.endElement();
+ }
+
+ auto const& rGraphic = rFillAttribute.getFillGraphic();
+ if (!rGraphic.isDefault())
+ {
+ rWriter.startElement("graphic");
+ // TODO
+ rWriter.endElement();
+ }
+
+ rWriter.endElement();
+}
+
+void writeShadeMode(::tools::XmlWriter& rWriter, const css::drawing::ShadeMode& rMode)
+{
+ switch (rMode)
+ {
+ case css::drawing::ShadeMode_FLAT:
+ rWriter.attribute("shadeMode", "Flat"_ostr);
+ break;
+ case css::drawing::ShadeMode_SMOOTH:
+ rWriter.attribute("shadeMode", "Smooth"_ostr);
+ break;
+ case css::drawing::ShadeMode_PHONG:
+ rWriter.attribute("shadeMode", "Phong"_ostr);
+ break;
+ case css::drawing::ShadeMode_DRAFT:
+ rWriter.attribute("shadeMode", "Draft"_ostr);
+ break;
+ default:
+ rWriter.attribute("shadeMode", "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeProjectionMode(::tools::XmlWriter& rWriter, const css::drawing::ProjectionMode& rMode)
+{
+ switch (rMode)
+ {
+ case css::drawing::ProjectionMode_PARALLEL:
+ rWriter.attribute("projectionMode", "Parallel"_ostr);
+ break;
+ case css::drawing::ProjectionMode_PERSPECTIVE:
+ rWriter.attribute("projectionMode", "Perspective"_ostr);
+ break;
+ default:
+ rWriter.attribute("projectionMode", "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeNormalsKind(::tools::XmlWriter& rWriter, const css::drawing::NormalsKind& rKind)
+{
+ switch (rKind)
+ {
+ case css::drawing::NormalsKind_SPECIFIC:
+ rWriter.attribute("normalsKind", "Specific"_ostr);
+ break;
+ case css::drawing::NormalsKind_FLAT:
+ rWriter.attribute("normalsKind", "Flat"_ostr);
+ break;
+ case css::drawing::NormalsKind_SPHERE:
+ rWriter.attribute("normalsKind", "Sphere"_ostr);
+ break;
+ default:
+ rWriter.attribute("normalsKind", "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeTextureProjectionMode(::tools::XmlWriter& rWriter, const char* pElement,
+ const css::drawing::TextureProjectionMode& rMode)
+{
+ switch (rMode)
+ {
+ case css::drawing::TextureProjectionMode_OBJECTSPECIFIC:
+ rWriter.attribute(pElement, "Specific"_ostr);
+ break;
+ case css::drawing::TextureProjectionMode_PARALLEL:
+ rWriter.attribute(pElement, "Parallel"_ostr);
+ break;
+ case css::drawing::TextureProjectionMode_SPHERE:
+ rWriter.attribute(pElement, "Sphere"_ostr);
+ break;
+ default:
+ rWriter.attribute(pElement, "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeTextureKind(::tools::XmlWriter& rWriter, const css::drawing::TextureKind2& rKind)
+{
+ switch (rKind)
+ {
+ case css::drawing::TextureKind2_LUMINANCE:
+ rWriter.attribute("textureKind", "Luminance"_ostr);
+ break;
+ case css::drawing::TextureKind2_INTENSITY:
+ rWriter.attribute("textureKind", "Intensity"_ostr);
+ break;
+ case css::drawing::TextureKind2_COLOR:
+ rWriter.attribute("textureKind", "Color"_ostr);
+ break;
+ default:
+ rWriter.attribute("textureKind", "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeTextureMode(::tools::XmlWriter& rWriter, const css::drawing::TextureMode& rMode)
+{
+ switch (rMode)
+ {
+ case css::drawing::TextureMode_REPLACE:
+ rWriter.attribute("textureMode", "Replace"_ostr);
+ break;
+ case css::drawing::TextureMode_MODULATE:
+ rWriter.attribute("textureMode", "Modulate"_ostr);
+ break;
+ case css::drawing::TextureMode_BLEND:
+ rWriter.attribute("textureMode", "Blend"_ostr);
+ break;
+ default:
+ rWriter.attribute("textureMode", "Undefined"_ostr);
+ break;
+ }
+}
+
+void writeMaterialAttribute(::tools::XmlWriter& rWriter,
+ const drawinglayer::attribute::MaterialAttribute3D& rMaterial)
+{
+ rWriter.startElement("material");
+ rWriter.attribute("color", convertColorToString(rMaterial.getColor()));
+ rWriter.attribute("specular", convertColorToString(rMaterial.getSpecular()));
+ rWriter.attribute("emission", convertColorToString(rMaterial.getEmission()));
+ rWriter.attribute("specularIntensity", rMaterial.getSpecularIntensity());
+ rWriter.endElement();
+}
+
+void writeSpreadMethod(::tools::XmlWriter& rWriter,
+ const drawinglayer::primitive2d::SpreadMethod& rSpreadMethod)
+{
+ switch (rSpreadMethod)
+ {
+ case drawinglayer::primitive2d::SpreadMethod::Pad:
+ rWriter.attribute("spreadmethod", "pad"_ostr);
+ break;
+ case drawinglayer::primitive2d::SpreadMethod::Reflect:
+ rWriter.attribute("spreadmethod", "reflect"_ostr);
+ break;
+ case drawinglayer::primitive2d::SpreadMethod::Repeat:
+ rWriter.attribute("spreadmethod", "repeat"_ostr);
+ break;
+ default:
+ rWriter.attribute("spreadmethod", "unknown"_ostr);
+ }
+}
+
} // end anonymous namespace
-Primitive2dXmlDump::Primitive2dXmlDump() :
- maFilter(constMaxActionType, false)
-{}
+Primitive2dXmlDump::Primitive2dXmlDump()
+ : maFilter(constMaxActionType, false)
+{
+}
Primitive2dXmlDump::~Primitive2dXmlDump() = default;
@@ -119,6 +540,101 @@ void Primitive2dXmlDump::dump(
pStream->Seek(STREAM_SEEK_TO_BEGIN);
}
+namespace
+{
+class Primitive3DXmlDump
+{
+public:
+ void decomposeAndWrite(const drawinglayer::primitive3d::Primitive3DContainer& rSequence,
+ ::tools::XmlWriter& rWriter)
+ {
+ for (size_t i = 0; i < rSequence.size(); i++)
+ {
+ const drawinglayer::primitive3d::Primitive3DReference& xReference = rSequence[i];
+ const auto* pBasePrimitive
+ = static_cast<const drawinglayer::primitive3d::BasePrimitive3D*>(xReference.get());
+ sal_uInt32 nId = pBasePrimitive->getPrimitive3DID();
+ OUString sCurrentElementTag = drawinglayer::primitive3d::idToString(nId);
+ switch (nId)
+ {
+ case PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D:
+ {
+ const auto* pExtrudePrimitive3D
+ = static_cast<const drawinglayer::primitive3d::SdrExtrudePrimitive3D*>(
+ xReference.get());
+ rWriter.startElement("extrude3D");
+
+ rWriter.startElement("matrix3D");
+ writeMatrix3D(rWriter, pExtrudePrimitive3D->getTransform());
+ rWriter.endElement();
+
+ rWriter.attribute("textureSizeX", pExtrudePrimitive3D->getTextureSize().getX());
+ rWriter.attribute("textureSizeY", pExtrudePrimitive3D->getTextureSize().getY());
+ auto const& rLFSAttribute = pExtrudePrimitive3D->getSdrLFSAttribute();
+ writeSdrLineAttribute(rWriter, rLFSAttribute.getLine());
+ writeSdrFillAttribute(rWriter, rLFSAttribute.getFill());
+
+ rWriter.startElement("object3Dattributes");
+ {
+ auto const& r3DObjectAttributes
+ = pExtrudePrimitive3D->getSdr3DObjectAttribute();
+
+ writeNormalsKind(rWriter, r3DObjectAttributes.getNormalsKind());
+ writeTextureProjectionMode(rWriter, "textureProjectionX",
+ r3DObjectAttributes.getTextureProjectionX());
+ writeTextureProjectionMode(rWriter, "textureProjectionY",
+ r3DObjectAttributes.getTextureProjectionY());
+ writeTextureKind(rWriter, r3DObjectAttributes.getTextureKind());
+ writeTextureMode(rWriter, r3DObjectAttributes.getTextureMode());
+ writeMaterialAttribute(rWriter, r3DObjectAttributes.getMaterial());
+
+ rWriter.attribute("normalsInvert",
+ sal_Int32(r3DObjectAttributes.getNormalsInvert()));
+ rWriter.attribute("doubleSided",
+ sal_Int32(r3DObjectAttributes.getDoubleSided()));
+ rWriter.attribute("shadow3D", sal_Int32(r3DObjectAttributes.getShadow3D()));
+ rWriter.attribute("textureFilter",
+ sal_Int32(r3DObjectAttributes.getTextureFilter()));
+ rWriter.attribute("reducedGeometry",
+ sal_Int32(r3DObjectAttributes.getReducedLineGeometry()));
+ }
+ rWriter.endElement();
+
+ rWriter.attribute("depth", pExtrudePrimitive3D->getDepth());
+ rWriter.attribute("diagonal", pExtrudePrimitive3D->getDiagonal());
+ rWriter.attribute("backScale", pExtrudePrimitive3D->getBackScale());
+ rWriter.attribute("smoothNormals",
+ sal_Int32(pExtrudePrimitive3D->getSmoothNormals()));
+ rWriter.attribute("smoothLids",
+ sal_Int32(pExtrudePrimitive3D->getSmoothLids()));
+ rWriter.attribute("characterMode",
+ sal_Int32(pExtrudePrimitive3D->getCharacterMode()));
+ rWriter.attribute("closeFront",
+ sal_Int32(pExtrudePrimitive3D->getCloseFront()));
+ rWriter.attribute("closeBack", sal_Int32(pExtrudePrimitive3D->getCloseBack()));
+ writePolyPolygon(rWriter, pExtrudePrimitive3D->getPolyPolygon());
+ rWriter.endElement();
+ }
+ break;
+
+ default:
+ {
+ rWriter.startElement("unhandled");
+ rWriter.attribute("id", sCurrentElementTag);
+ rWriter.attribute("idNumber", nId);
+
+ drawinglayer::geometry::ViewInformation3D aViewInformation3D;
+ drawinglayer::primitive3d::Primitive3DContainer aContainer;
+ aContainer = pBasePrimitive->get3DDecomposition(aViewInformation3D);
+ decomposeAndWrite(aContainer, rWriter);
+ rWriter.endElement();
+ }
+ break;
+ }
+ }
+ }
+};
+}
xmlDocUniquePtr Primitive2dXmlDump::dumpAndParse(
const drawinglayer::primitive2d::Primitive2DContainer& rPrimitive2DSequence,
const OUString& rStreamName)
@@ -150,27 +666,73 @@ xmlDocUniquePtr Primitive2dXmlDump::dumpAndParse(
return xmlDocUniquePtr(xmlParseDoc(reinterpret_cast<xmlChar*>(pBuffer.get())));
}
+OUString Primitive2dXmlDump::idToString(sal_uInt32 nId)
+{
+ return drawinglayer::primitive2d::idToString(nId);
+}
+
+void Primitive2dXmlDump::runDecomposeAndRecurse(const BasePrimitive2D* pBasePrimitive,
+ ::tools::XmlWriter& rWriter)
+{
+ drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
+ pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
+ drawinglayer::geometry::ViewInformation2D());
+ decomposeAndWrite(aPrimitiveContainer, rWriter);
+}
+
void Primitive2dXmlDump::decomposeAndWrite(
const drawinglayer::primitive2d::Primitive2DContainer& rPrimitive2DSequence,
::tools::XmlWriter& rWriter)
{
- for (size_t i = 0; i < rPrimitive2DSequence.size(); i++)
+ for (auto const& i : rPrimitive2DSequence)
{
- drawinglayer::primitive2d::Primitive2DReference xPrimitive2DReference = rPrimitive2DSequence[i];
- const BasePrimitive2D* pBasePrimitive = dynamic_cast<const BasePrimitive2D* >(xPrimitive2DReference.get());
- if (!pBasePrimitive)
- continue;
+ const BasePrimitive2D* pBasePrimitive = i.get();
sal_uInt32 nId = pBasePrimitive->getPrimitive2DID();
if (nId < maFilter.size() && maFilter[nId])
continue;
+ // handled by subclass
+ if (decomposeAndWrite(*pBasePrimitive, rWriter))
+ continue;
+
OUString sCurrentElementTag = drawinglayer::primitive2d::idToString(nId);
switch (nId)
{
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
+ {
+ const auto& rBitmapPrimitive2D
+ = static_cast<const BitmapPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("bitmap");
+ writeMatrix(rWriter, rBitmapPrimitive2D.getTransform());
+
+ const Bitmap aBitmap(rBitmapPrimitive2D.getBitmap());
+ const Size aSizePixel(aBitmap.GetSizePixel());
+
+ rWriter.attribute("height", aSizePixel.getHeight());
+ rWriter.attribute("width", aSizePixel.getWidth());
+ rWriter.attribute("checksum", OString(std::to_string(aBitmap.GetChecksum())));
+
+ for (tools::Long y = 0; y < aSizePixel.getHeight(); y++)
+ {
+ rWriter.startElement("data");
+ OUString aBitmapData = u""_ustr;
+ for (tools::Long x = 0; x < aSizePixel.getWidth(); x++)
+ {
+ if (x != 0)
+ aBitmapData = aBitmapData + ",";
+ aBitmapData = aBitmapData + aBitmap.GetPixelColor(x, y).AsRGBHexString();
+ }
+ rWriter.attribute("row", aBitmapData);
+ rWriter.endElement();
+ }
+ rWriter.endElement();
+ }
+ break;
case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D:
{
- const HiddenGeometryPrimitive2D& rHiddenGeometryPrimitive2D = dynamic_cast<const HiddenGeometryPrimitive2D&>(*pBasePrimitive);
+ const auto& rHiddenGeometryPrimitive2D
+ = static_cast<const HiddenGeometryPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("hiddengeometry");
decomposeAndWrite(rHiddenGeometryPrimitive2D.getChildren(), rWriter);
rWriter.endElement();
@@ -179,20 +741,10 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
{
- const TransformPrimitive2D& rTransformPrimitive2D = dynamic_cast<const TransformPrimitive2D&>(*pBasePrimitive);
+ const auto& rTransformPrimitive2D
+ = static_cast<const TransformPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("transform");
-
- basegfx::B2DHomMatrix const & rMatrix = rTransformPrimitive2D.getTransformation();
- rWriter.attributeDouble("xy11", rMatrix.get(0,0));
- rWriter.attributeDouble("xy12", rMatrix.get(0,1));
- rWriter.attributeDouble("xy13", rMatrix.get(0,2));
- rWriter.attributeDouble("xy21", rMatrix.get(1,0));
- rWriter.attributeDouble("xy22", rMatrix.get(1,1));
- rWriter.attributeDouble("xy23", rMatrix.get(1,2));
- rWriter.attributeDouble("xy31", rMatrix.get(2,0));
- rWriter.attributeDouble("xy32", rMatrix.get(2,1));
- rWriter.attributeDouble("xy33", rMatrix.get(2,2));
-
+ writeMatrix(rWriter, rTransformPrimitive2D.getTransformation());
decomposeAndWrite(rTransformPrimitive2D.getChildren(), rWriter);
rWriter.endElement();
}
@@ -200,33 +752,110 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
{
- const PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D = dynamic_cast<const PolyPolygonColorPrimitive2D&>(*pBasePrimitive);
+ const auto& rPolyPolygonColorPrimitive2D
+ = static_cast<const PolyPolygonColorPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("polypolygoncolor");
- rWriter.attribute("color", convertColorToString(rPolyPolygonColorPrimitive2D.getBColor()));
+ rWriter.attribute("color",
+ convertColorToString(rPolyPolygonColorPrimitive2D.getBColor()));
- const basegfx::B2DPolyPolygon& aB2DPolyPolygon(rPolyPolygonColorPrimitive2D.getB2DPolyPolygon());
+ const basegfx::B2DPolyPolygon& aB2DPolyPolygon(
+ rPolyPolygonColorPrimitive2D.getB2DPolyPolygon());
writePolyPolygon(rWriter, aB2DPolyPolygon);
rWriter.endElement();
}
break;
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ {
+ const auto& rPointArrayPrimitive2D
+ = static_cast<const PointArrayPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("pointarray");
- case PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D:
+ rWriter.attribute("color",
+ convertColorToString(rPointArrayPrimitive2D.getRGBColor()));
+
+ const std::vector<basegfx::B2DPoint> aPositions
+ = rPointArrayPrimitive2D.getPositions();
+ for (std::vector<basegfx::B2DPoint>::const_iterator iter = aPositions.begin();
+ iter != aPositions.end(); ++iter)
+ {
+ rWriter.startElement("point");
+ rWriter.attribute("x", OUString::number(iter->getX()));
+ rWriter.attribute("y", OUString::number(iter->getY()));
+ rWriter.endElement();
+ }
+
+ rWriter.endElement();
+ }
+ break;
+
+ case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D:
{
- const PolyPolygonStrokePrimitive2D& rPolyPolygonStrokePrimitive2D = dynamic_cast<const PolyPolygonStrokePrimitive2D&>(*pBasePrimitive);
- rWriter.startElement("polypolygonstroke");
+ const auto& rPolygonStrokeArrowPrimitive2D
+ = static_cast<const PolygonStrokeArrowPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("polygonstrokearrow");
- rWriter.startElement("line");
- const drawinglayer::attribute::LineAttribute& aLineAttribute = rPolyPolygonStrokePrimitive2D.getLineAttribute();
- rWriter.attribute("color", convertColorToString(aLineAttribute.getColor()));
- rWriter.attribute("width", aLineAttribute.getWidth());
- //rWriter.attribute("linejoin", aLineAttribute.getLineJoin());
- //rWriter.attribute("linecap", aLineAttribute.getLineCap());
+ rWriter.startElement("polygon");
+ rWriter.content(basegfx::utils::exportToSvgPoints(
+ rPolygonStrokeArrowPrimitive2D.getB2DPolygon()));
rWriter.endElement();
- //getStrokeAttribute()
+ if (rPolygonStrokeArrowPrimitive2D.getStart().getB2DPolyPolygon().count())
+ {
+ rWriter.startElement("linestartattribute");
+ rWriter.attribute("width",
+ rPolygonStrokeArrowPrimitive2D.getStart().getWidth());
+ rWriter.attribute("centered",
+ static_cast<sal_Int32>(
+ rPolygonStrokeArrowPrimitive2D.getStart().isCentered()));
+ writePolyPolygon(rWriter,
+ rPolygonStrokeArrowPrimitive2D.getStart().getB2DPolyPolygon());
+ rWriter.endElement();
+ }
+
+ if (rPolygonStrokeArrowPrimitive2D.getEnd().getB2DPolyPolygon().count())
+ {
+ rWriter.startElement("lineendattribute");
+ rWriter.attribute("width", rPolygonStrokeArrowPrimitive2D.getEnd().getWidth());
+ rWriter.attribute("centered",
+ static_cast<sal_Int32>(
+ rPolygonStrokeArrowPrimitive2D.getEnd().isCentered()));
+ writePolyPolygon(rWriter,
+ rPolygonStrokeArrowPrimitive2D.getEnd().getB2DPolyPolygon());
+ rWriter.endElement();
+ }
+
+ writeLineAttribute(rWriter, rPolygonStrokeArrowPrimitive2D.getLineAttribute());
+ writeStrokeAttribute(rWriter, rPolygonStrokeArrowPrimitive2D.getStrokeAttribute());
+ rWriter.endElement();
+ }
+ break;
+
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ const auto& rPolygonStrokePrimitive2D
+ = static_cast<const PolygonStrokePrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("polygonstroke");
+
+ rWriter.startElement("polygon");
+ rWriter.content(
+ basegfx::utils::exportToSvgPoints(rPolygonStrokePrimitive2D.getB2DPolygon()));
+ rWriter.endElement();
+
+ writeLineAttribute(rWriter, rPolygonStrokePrimitive2D.getLineAttribute());
+ writeStrokeAttribute(rWriter, rPolygonStrokePrimitive2D.getStrokeAttribute());
+ rWriter.endElement();
+ }
+ break;
+ case PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D:
+ {
+ const auto& rPolyPolygonStrokePrimitive2D
+ = static_cast<const PolyPolygonStrokePrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("polypolygonstroke");
+ writeLineAttribute(rWriter, rPolyPolygonStrokePrimitive2D.getLineAttribute());
+ writeStrokeAttribute(rWriter, rPolyPolygonStrokePrimitive2D.getStrokeAttribute());
writePolyPolygon(rWriter, rPolyPolygonStrokePrimitive2D.getB2DPolyPolygon());
rWriter.endElement();
@@ -235,46 +864,114 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
{
- const PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D = dynamic_cast<const PolygonHairlinePrimitive2D&>(*pBasePrimitive);
+ const auto& rPolygonHairlinePrimitive2D
+ = static_cast<const PolygonHairlinePrimitive2D&>(*pBasePrimitive);
rWriter.startElement("polygonhairline");
- rWriter.attribute("color", convertColorToString(rPolygonHairlinePrimitive2D.getBColor()));
+ rWriter.attribute("color",
+ convertColorToString(rPolygonHairlinePrimitive2D.getBColor()));
rWriter.startElement("polygon");
- rWriter.content(basegfx::utils::exportToSvgPoints(rPolygonHairlinePrimitive2D.getB2DPolygon()));
+ rWriter.content(
+ basegfx::utils::exportToSvgPoints(rPolygonHairlinePrimitive2D.getB2DPolygon()));
rWriter.endElement();
+ rWriter.endElement();
+ }
+ break;
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
+ {
+ const auto& rTextDecoratedPortionPrimitive2D
+ = static_cast<const TextDecoratedPortionPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("textdecoratedportion");
+ writeMatrix(rWriter, rTextDecoratedPortionPrimitive2D.getTextTransform());
+
+ rWriter.attribute("text", rTextDecoratedPortionPrimitive2D.getText());
+ rWriter.attribute(
+ "fontcolor",
+ convertColorToString(rTextDecoratedPortionPrimitive2D.getFontColor()));
+
+ const drawinglayer::attribute::FontAttribute& aFontAttribute
+ = rTextDecoratedPortionPrimitive2D.getFontAttribute();
+ rWriter.attribute("familyname", aFontAttribute.getFamilyName());
+ rWriter.endElement();
+ }
+ break;
+
+ case PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D:
+ {
+ const auto& rTextLinePrimitive2D
+ = static_cast<const TextLinePrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("textline");
+ writeMatrix(rWriter, rTextLinePrimitive2D.getObjectTransformation());
+
+ rWriter.attribute("width", rTextLinePrimitive2D.getWidth());
+ rWriter.attribute("offset", rTextLinePrimitive2D.getOffset());
+ rWriter.attribute("height", rTextLinePrimitive2D.getHeight());
+ rWriter.attribute("color",
+ convertColorToString(rTextLinePrimitive2D.getLineColor()));
rWriter.endElement();
}
break;
case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
{
- const TextSimplePortionPrimitive2D& rTextSimplePortionPrimitive2D = dynamic_cast<const TextSimplePortionPrimitive2D&>(*pBasePrimitive);
+ const auto& rTextSimplePortionPrimitive2D
+ = static_cast<const TextSimplePortionPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("textsimpleportion");
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
- if(rTextSimplePortionPrimitive2D.getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX))
+ if (rTextSimplePortionPrimitive2D.getTextTransform().decompose(aScale, aTranslate,
+ fRotate, fShearX))
{
rWriter.attribute("width", aScale.getX());
rWriter.attribute("height", aScale.getY());
}
rWriter.attribute("x", aTranslate.getX());
rWriter.attribute("y", aTranslate.getY());
- rWriter.attribute("text", rTextSimplePortionPrimitive2D.getText());
- rWriter.attribute("fontcolor", convertColorToString(rTextSimplePortionPrimitive2D.getFontColor()));
-
- const drawinglayer::attribute::FontAttribute& aFontAttribute = rTextSimplePortionPrimitive2D.getFontAttribute();
+ OUString aText = rTextSimplePortionPrimitive2D.getText();
+ // TODO share code with sax_fastparser::FastSaxSerializer::write().
+ rWriter.attribute("text", aText.replaceAll("", "&#9;"));
+ rWriter.attribute("fontcolor", convertColorToString(
+ rTextSimplePortionPrimitive2D.getFontColor()));
+
+ const drawinglayer::attribute::FontAttribute& aFontAttribute
+ = rTextSimplePortionPrimitive2D.getFontAttribute();
rWriter.attribute("familyname", aFontAttribute.getFamilyName());
+
+ if (aFontAttribute.getRTL())
+ {
+ rWriter.attribute("rtl", std::u16string_view{ u"true" });
+ }
+
+ const std::vector<double> aDx = rTextSimplePortionPrimitive2D.getDXArray();
+ if (aDx.size())
+ {
+ for (size_t iDx = 0; iDx < aDx.size(); ++iDx)
+ {
+ OString sName = "dx" + OString::number(iDx);
+ rWriter.attribute(sName, OString::number(aDx[iDx]));
+ }
+ }
+ rWriter.endElement();
+ }
+ break;
+
+ case PRIMITIVE2D_ID_GROUPPRIMITIVE2D:
+ {
+ const auto& rGroupPrimitive2D
+ = static_cast<const GroupPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("group");
+ decomposeAndWrite(rGroupPrimitive2D.getChildren(), rWriter);
rWriter.endElement();
}
break;
case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
{
- const MaskPrimitive2D& rMaskPrimitive2D = dynamic_cast<const MaskPrimitive2D&>(*pBasePrimitive);
+ const auto& rMaskPrimitive2D = static_cast<const MaskPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("mask");
writePolyPolygon(rWriter, rMaskPrimitive2D.getMask());
decomposeAndWrite(rMaskPrimitive2D.getChildren(), rWriter);
@@ -284,18 +981,21 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
{
- const UnifiedTransparencePrimitive2D& rUnifiedTransparencePrimitive2D = dynamic_cast<const UnifiedTransparencePrimitive2D&>(*pBasePrimitive);
+ const auto& rUnifiedTransparencePrimitive2D
+ = static_cast<const UnifiedTransparencePrimitive2D&>(*pBasePrimitive);
rWriter.startElement("unifiedtransparence");
- rWriter.attribute("transparence", OString::number(rUnifiedTransparencePrimitive2D.getTransparence()));
+ rWriter.attribute(
+ "transparence",
+ std::lround(100 * rUnifiedTransparencePrimitive2D.getTransparence()));
decomposeAndWrite(rUnifiedTransparencePrimitive2D.getChildren(), rWriter);
-
rWriter.endElement();
}
break;
case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D:
{
- const ObjectInfoPrimitive2D& rObjectInfoPrimitive2D = dynamic_cast<const ObjectInfoPrimitive2D&>(*pBasePrimitive);
+ const auto& rObjectInfoPrimitive2D
+ = static_cast<const ObjectInfoPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("objectinfo");
decomposeAndWrite(rObjectInfoPrimitive2D.getChildren(), rWriter);
@@ -303,23 +1003,53 @@ void Primitive2dXmlDump::decomposeAndWrite(
}
break;
+ case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D:
+ {
+ const auto& rStructureTagPrimitive2D
+ = static_cast<const StructureTagPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("structuretag");
+ rWriter.attribute("structureelement",
+ sal_Int32(rStructureTagPrimitive2D.getStructureElement()));
+ decomposeAndWrite(rStructureTagPrimitive2D.getChildren(), rWriter);
+ rWriter.endElement();
+ }
+ break;
+
case PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D:
{
- const SvgRadialGradientPrimitive2D& rSvgRadialGradientPrimitive2D = dynamic_cast<const SvgRadialGradientPrimitive2D&>(*pBasePrimitive);
+ const auto& rSvgRadialGradientPrimitive2D
+ = static_cast<const SvgRadialGradientPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("svgradialgradient");
- basegfx::B2DPoint aFocusAttribute = rSvgRadialGradientPrimitive2D.getFocal();
+ if (rSvgRadialGradientPrimitive2D.isFocalSet())
+ {
+ basegfx::B2DPoint aFocalAttribute = rSvgRadialGradientPrimitive2D.getFocal();
+ rWriter.attribute("focalx", aFocalAttribute.getX());
+ rWriter.attribute("focaly", aFocalAttribute.getY());
+ }
- rWriter.attribute("radius", OString::number(rSvgRadialGradientPrimitive2D.getRadius()));
- rWriter.attribute("focusx", aFocusAttribute.getX());
- rWriter.attribute("focusy", aFocusAttribute.getY());
+ basegfx::B2DPoint aStartPoint = rSvgRadialGradientPrimitive2D.getStart();
+ rWriter.attribute("startx", aStartPoint.getX());
+ rWriter.attribute("starty", aStartPoint.getY());
+ rWriter.attribute("radius",
+ OString::number(rSvgRadialGradientPrimitive2D.getRadius()));
+ writeSpreadMethod(rWriter, rSvgRadialGradientPrimitive2D.getSpreadMethod());
+ rWriter.attributeDouble(
+ "opacity",
+ rSvgRadialGradientPrimitive2D.getGradientEntries().front().getOpacity());
+
+ rWriter.startElement("transform");
+ writeMatrix(rWriter, rSvgRadialGradientPrimitive2D.getGradientTransform());
+ rWriter.endElement();
+ writePolyPolygon(rWriter, rSvgRadialGradientPrimitive2D.getPolyPolygon());
rWriter.endElement();
}
break;
case PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D:
{
- const SvgLinearGradientPrimitive2D& rSvgLinearGradientPrimitive2D = dynamic_cast<const SvgLinearGradientPrimitive2D&>(*pBasePrimitive);
+ const auto& rSvgLinearGradientPrimitive2D
+ = static_cast<const SvgLinearGradientPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("svglineargradient");
basegfx::B2DPoint aStartAttribute = rSvgLinearGradientPrimitive2D.getStart();
basegfx::B2DPoint aEndAttribute = rSvgLinearGradientPrimitive2D.getEnd();
@@ -328,20 +1058,13 @@ void Primitive2dXmlDump::decomposeAndWrite(
rWriter.attribute("starty", aStartAttribute.getY());
rWriter.attribute("endx", aEndAttribute.getX());
rWriter.attribute("endy", aEndAttribute.getY());
- //rWriter.attribute("spreadmethod", (int)rSvgLinearGradientPrimitive2D.getSpreadMethod());
- rWriter.attributeDouble("opacity", rSvgLinearGradientPrimitive2D.getGradientEntries().front().getOpacity());
+ writeSpreadMethod(rWriter, rSvgLinearGradientPrimitive2D.getSpreadMethod());
+ rWriter.attributeDouble(
+ "opacity",
+ rSvgLinearGradientPrimitive2D.getGradientEntries().front().getOpacity());
rWriter.startElement("transform");
- basegfx::B2DHomMatrix const & rMatrix = rSvgLinearGradientPrimitive2D.getGradientTransform();
- rWriter.attributeDouble("xy11", rMatrix.get(0,0));
- rWriter.attributeDouble("xy12", rMatrix.get(0,1));
- rWriter.attributeDouble("xy13", rMatrix.get(0,2));
- rWriter.attributeDouble("xy21", rMatrix.get(1,0));
- rWriter.attributeDouble("xy22", rMatrix.get(1,1));
- rWriter.attributeDouble("xy23", rMatrix.get(1,2));
- rWriter.attributeDouble("xy31", rMatrix.get(2,0));
- rWriter.attributeDouble("xy32", rMatrix.get(2,1));
- rWriter.attributeDouble("xy33", rMatrix.get(2,2));
+ writeMatrix(rWriter, rSvgLinearGradientPrimitive2D.getGradientTransform());
rWriter.endElement();
writePolyPolygon(rWriter, rSvgLinearGradientPrimitive2D.getPolyPolygon());
@@ -352,12 +1075,9 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D:
{
- const MetafilePrimitive2D& rMetafilePrimitive2D = dynamic_cast<const MetafilePrimitive2D&>(*pBasePrimitive);
rWriter.startElement("metafile");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
// since the graphic is not rendered in a document, we do not need a concrete view information
- rMetafilePrimitive2D.get2DDecomposition(aPrimitiveContainer, drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer,rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
rWriter.endElement();
}
@@ -367,10 +1087,7 @@ void Primitive2dXmlDump::decomposeAndWrite(
{
// SdrRectanglePrimitive2D is private to us.
rWriter.startElement("sdrrectangle");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
rWriter.endElement();
break;
}
@@ -379,10 +1096,7 @@ void Primitive2dXmlDump::decomposeAndWrite(
{
// SdrBlockTextPrimitive2D is private to us.
rWriter.startElement("sdrblocktext");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
rWriter.endElement();
break;
}
@@ -391,10 +1105,20 @@ void Primitive2dXmlDump::decomposeAndWrite(
{
// TextHierarchyBlockPrimitive2D.
rWriter.startElement("texthierarchyblock");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
+ rWriter.endElement();
+ break;
+ }
+
+ case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D:
+ {
+ rWriter.startElement("texthierarchyedit");
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
+ const auto* pTextHierarchyEditPrimitive
+ = dynamic_cast<const drawinglayer::primitive2d::TextHierarchyEditPrimitive2D*>(
+ pBasePrimitive);
+ if (pTextHierarchyEditPrimitive)
+ decomposeAndWrite(pTextHierarchyEditPrimitive->getChildren(), rWriter);
rWriter.endElement();
break;
}
@@ -403,10 +1127,7 @@ void Primitive2dXmlDump::decomposeAndWrite(
{
// TextHierarchyParagraphPrimitive2D.
rWriter.startElement("texthierarchyparagraph");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
rWriter.endElement();
break;
}
@@ -415,10 +1136,7 @@ void Primitive2dXmlDump::decomposeAndWrite(
{
// TextHierarchyLinePrimitive2D.
rWriter.startElement("texthierarchyline");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ runDecomposeAndRecurse(pBasePrimitive, rWriter);
rWriter.endElement();
break;
}
@@ -426,11 +1144,107 @@ void Primitive2dXmlDump::decomposeAndWrite(
case PRIMITIVE2D_ID_SHADOWPRIMITIVE2D:
{
// ShadowPrimitive2D.
+ const auto& rShadowPrimitive2D
+ = static_cast<const ShadowPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("shadow");
- drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
- pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
- drawinglayer::geometry::ViewInformation2D());
- decomposeAndWrite(aPrimitiveContainer, rWriter);
+ rWriter.attribute("color",
+ convertColorToString(rShadowPrimitive2D.getShadowColor()));
+ rWriter.attributeDouble("blur", rShadowPrimitive2D.getShadowBlur());
+
+ rWriter.startElement("transform");
+ writeMatrix(rWriter, rShadowPrimitive2D.getShadowTransform());
+ rWriter.endElement();
+
+ rWriter.endElement();
+ break;
+ }
+
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
+ {
+ // ModifiedColorPrimitive2D.
+ const auto& rModifiedColorPrimitive2D
+ = static_cast<const ModifiedColorPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("modifiedColor");
+ const basegfx::BColorModifierSharedPtr& aColorModifier
+ = rModifiedColorPrimitive2D.getColorModifier();
+ rWriter.attribute("modifier", aColorModifier->getModifierName());
+
+ decomposeAndWrite(rModifiedColorPrimitive2D.getChildren(), rWriter);
+ rWriter.endElement();
+ break;
+ }
+ case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D:
+ {
+ // SoftEdgePrimitive2D.
+ const auto& rSoftEdgePrimitive2D
+ = static_cast<const SoftEdgePrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("softedge");
+ rWriter.attribute("radius", OUString::number(rSoftEdgePrimitive2D.getRadius()));
+
+ decomposeAndWrite(rSoftEdgePrimitive2D.getChildren(), rWriter);
+ rWriter.endElement();
+ break;
+ }
+
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D:
+ {
+ const auto& rScenePrimitive2D
+ = static_cast<const drawinglayer::primitive2d::ScenePrimitive2D&>(
+ *pBasePrimitive);
+ rWriter.startElement("scene");
+
+ auto const& rSceneAttribute = rScenePrimitive2D.getSdrSceneAttribute();
+
+ rWriter.attribute("shadowSlant", rSceneAttribute.getShadowSlant());
+ rWriter.attribute("isTwoSidedLighting",
+ sal_Int32(rSceneAttribute.getTwoSidedLighting()));
+ writeShadeMode(rWriter, rSceneAttribute.getShadeMode());
+ writeProjectionMode(rWriter, rSceneAttribute.getProjectionMode());
+
+ auto const& rLightingAttribute = rScenePrimitive2D.getSdrLightingAttribute();
+ rWriter.attribute("ambientLightColor",
+ convertColorToString(rLightingAttribute.getAmbientLightColor()));
+ rWriter.startElement("lights");
+ for (auto const& rLight : rLightingAttribute.getLightVector())
+ {
+ rWriter.startElement("light");
+ rWriter.attribute("color", convertColorToString(rLight.getColor()));
+ rWriter.attribute("directionVectorX", rLight.getDirection().getX());
+ rWriter.attribute("directionVectorY", rLight.getDirection().getY());
+ rWriter.attribute("specular", sal_Int32(rLight.getSpecular()));
+ rWriter.endElement();
+ }
+ rWriter.endElement();
+
+ Primitive3DXmlDump aPrimitive3DXmlDump;
+ aPrimitive3DXmlDump.decomposeAndWrite(rScenePrimitive2D.getChildren3D(), rWriter);
+
+ rWriter.endElement();
+ break;
+ }
+
+ case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D:
+ {
+ const PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D
+ = dynamic_cast<const PolyPolygonRGBAPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("polypolygonrgba");
+ rWriter.attribute("color",
+ convertColorToString(rPolyPolygonRGBAPrimitive2D.getBColor()));
+ rWriter.attribute("transparence",
+ std::lround(100 * rPolyPolygonRGBAPrimitive2D.getTransparency()));
+ writePolyPolygon(rWriter, rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon());
+ rWriter.endElement();
+ break;
+ }
+
+ case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+ {
+ const PolyPolygonAlphaGradientPrimitive2D& rPolyPolygonAlphaGradientPrimitive2D
+ = dynamic_cast<const PolyPolygonAlphaGradientPrimitive2D&>(*pBasePrimitive);
+ rWriter.startElement("polypolygonalphagradient");
+ rWriter.attribute("color", convertColorToString(
+ rPolyPolygonAlphaGradientPrimitive2D.getBColor()));
+ writePolyPolygon(rWriter, rPolyPolygonAlphaGradientPrimitive2D.getB2DPolyPolygon());
rWriter.endElement();
break;
}
@@ -438,7 +1252,9 @@ void Primitive2dXmlDump::decomposeAndWrite(
default:
{
rWriter.startElement("unhandled");
- rWriter.attribute("id", OUStringToOString(sCurrentElementTag, RTL_TEXTENCODING_UTF8));
+ rWriter.attribute("id", sCurrentElementTag);
+ rWriter.attribute("idNumber", nId);
+
drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
drawinglayer::geometry::ViewInformation2D());
@@ -447,7 +1263,6 @@ void Primitive2dXmlDump::decomposeAndWrite(
}
break;
}
-
}
}
diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx
index cfab0426ef74..5a983e57afdd 100644
--- a/drawinglayer/source/tools/wmfemfhelper.cxx
+++ b/drawinglayer/source/tools/wmfemfhelper.cxx
@@ -19,19 +19,17 @@
#include <wmfemfhelper.hxx>
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <vcl/alpha.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/metaact.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
@@ -52,6 +50,7 @@
#include <sal/log.hxx>
#include <tools/fract.hxx>
#include <tools/stream.hxx>
+#include <tools/UnitConversion.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/gradient.hxx>
#include <vcl/hatch.hxx>
@@ -79,7 +78,7 @@ namespace drawinglayer::primitive2d
{
protected:
/// local decomposition.
- virtual void create2DDecomposition(Primitive2DContainer& rContainer,
+ virtual Primitive2DReference create2DDecomposition(
const geometry::ViewInformation2D& rViewInformation) const override;
public:
@@ -94,14 +93,14 @@ namespace drawinglayer::primitive2d
}
- void NonOverlappingFillGradientPrimitive2D::create2DDecomposition(
- Primitive2DContainer& rContainer,
+ Primitive2DReference NonOverlappingFillGradientPrimitive2D::create2DDecomposition(
const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if (!getFillGradient().isDefault())
{
- createFill(rContainer, false);
+ return createFill(false);
}
+ return nullptr;
}
} // end of namespace
@@ -115,20 +114,12 @@ namespace wmfemfhelper
interpretation of the MetaFile action flow.
*/
PropertyHolder::PropertyHolder()
- : maTransformation(),
- maMapUnit(MapUnit::Map100thMM),
- maLineColor(),
- maFillColor(),
+ : maMapUnit(MapUnit::Map100thMM),
maTextColor(sal_uInt32(COL_BLACK)),
- maTextFillColor(),
- maTextLineColor(),
- maOverlineColor(),
- maClipPolyPoygon(),
- maFont(),
maRasterOp(RasterOp::OverPaint),
- mnLayoutMode(ComplexTextLayoutFlags::Default),
+ mnLayoutMode(vcl::text::ComplexTextLayoutFlags::Default),
maLanguageType(0),
- mnPushFlags(PushFlags::NONE),
+ mnPushFlags(vcl::PushFlags::NONE),
mbLineColor(false),
mbFillColor(false),
mbTextColor(true),
@@ -162,7 +153,7 @@ namespace wmfemfhelper
maPropertyHolders.push_back(pNew);
}
- void PropertyHolders::Push(PushFlags nPushFlags)
+ void PropertyHolders::Push(vcl::PushFlags nPushFlags)
{
if (bool(nPushFlags))
{
@@ -185,56 +176,56 @@ namespace wmfemfhelper
return;
const PropertyHolder* pTip = maPropertyHolders.back();
- const PushFlags nPushFlags(pTip->getPushFlags());
+ const vcl::PushFlags nPushFlags(pTip->getPushFlags());
- if (nPushFlags != PushFlags::NONE)
+ if (nPushFlags != vcl::PushFlags::NONE)
{
if (nSize > 1)
{
// copy back content for all non-set flags
PropertyHolder* pLast = maPropertyHolders[nSize - 2];
- if (PushFlags::ALL != nPushFlags)
+ if (vcl::PushFlags::ALL != nPushFlags)
{
- if (!(nPushFlags & PushFlags::LINECOLOR))
+ if (!(nPushFlags & vcl::PushFlags::LINECOLOR))
{
pLast->setLineColor(pTip->getLineColor());
pLast->setLineColorActive(pTip->getLineColorActive());
}
- if (!(nPushFlags & PushFlags::FILLCOLOR))
+ if (!(nPushFlags & vcl::PushFlags::FILLCOLOR))
{
pLast->setFillColor(pTip->getFillColor());
pLast->setFillColorActive(pTip->getFillColorActive());
}
- if (!(nPushFlags & PushFlags::FONT))
+ if (!(nPushFlags & vcl::PushFlags::FONT))
{
pLast->setFont(pTip->getFont());
}
- if (!(nPushFlags & PushFlags::TEXTCOLOR))
+ if (!(nPushFlags & vcl::PushFlags::TEXTCOLOR))
{
pLast->setTextColor(pTip->getTextColor());
pLast->setTextColorActive(pTip->getTextColorActive());
}
- if (!(nPushFlags & PushFlags::MAPMODE))
+ if (!(nPushFlags & vcl::PushFlags::MAPMODE))
{
pLast->setTransformation(pTip->getTransformation());
pLast->setMapUnit(pTip->getMapUnit());
}
- if (!(nPushFlags & PushFlags::CLIPREGION))
+ if (!(nPushFlags & vcl::PushFlags::CLIPREGION))
{
pLast->setClipPolyPolygon(pTip->getClipPolyPolygon());
pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive());
}
- if (!(nPushFlags & PushFlags::RASTEROP))
+ if (!(nPushFlags & vcl::PushFlags::RASTEROP))
{
pLast->setRasterOp(pTip->getRasterOp());
}
- if (!(nPushFlags & PushFlags::TEXTFILLCOLOR))
+ if (!(nPushFlags & vcl::PushFlags::TEXTFILLCOLOR))
{
pLast->setTextFillColor(pTip->getTextFillColor());
pLast->setTextFillColorActive(pTip->getTextFillColorActive());
}
- if (!(nPushFlags & PushFlags::TEXTALIGN))
+ if (!(nPushFlags & vcl::PushFlags::TEXTALIGN))
{
if (pLast->getFont().GetAlignment() != pTip->getFont().GetAlignment())
{
@@ -243,24 +234,24 @@ namespace wmfemfhelper
pLast->setFont(aFont);
}
}
- if (!(nPushFlags & PushFlags::REFPOINT))
+ if (!(nPushFlags & vcl::PushFlags::REFPOINT))
{
// not supported
}
- if (!(nPushFlags & PushFlags::TEXTLINECOLOR))
+ if (!(nPushFlags & vcl::PushFlags::TEXTLINECOLOR))
{
pLast->setTextLineColor(pTip->getTextLineColor());
pLast->setTextLineColorActive(pTip->getTextLineColorActive());
}
- if (!(nPushFlags & PushFlags::TEXTLAYOUTMODE))
+ if (!(nPushFlags & vcl::PushFlags::TEXTLAYOUTMODE))
{
pLast->setLayoutMode(pTip->getLayoutMode());
}
- if (!(nPushFlags & PushFlags::TEXTLANGUAGE))
+ if (!(nPushFlags & vcl::PushFlags::TEXTLANGUAGE))
{
pLast->setLanguageType(pTip->getLanguageType());
}
- if (!(nPushFlags & PushFlags::OVERLINECOLOR))
+ if (!(nPushFlags & vcl::PushFlags::OVERLINECOLOR))
{
pLast->setOverlineColor(pTip->getOverlineColor());
pLast->setOverlineColorActive(pTip->getOverlineColorActive());
@@ -322,7 +313,6 @@ namespace wmfemfhelper
data.
*/
TargetHolder::TargetHolder()
- : aTargets()
{
}
@@ -335,25 +325,17 @@ namespace wmfemfhelper
return aTargets.size();
}
- void TargetHolder::append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> pCandidate)
+ void TargetHolder::append(drawinglayer::primitive2d::BasePrimitive2D* pCandidate)
{
if (pCandidate)
{
- aTargets.push_back(std::move(pCandidate));
+ aTargets.push_back(pCandidate);
}
}
drawinglayer::primitive2d::Primitive2DContainer TargetHolder::getPrimitive2DSequence(const PropertyHolder& rPropertyHolder)
{
- const sal_uInt32 nCount(aTargets.size());
- drawinglayer::primitive2d::Primitive2DContainer xRetval(nCount);
-
- for (sal_uInt32 a(0); a < nCount; a++)
- {
- xRetval[a] = aTargets[a].release();
- }
- // Since we have released them from the list
- aTargets.clear();
+ drawinglayer::primitive2d::Primitive2DContainer xRetval = std::move(aTargets);
if (!xRetval.empty() && rPropertyHolder.getClipPolyPolygonActive())
{
@@ -361,12 +343,11 @@ namespace wmfemfhelper
if (rClipPolyPolygon.count())
{
- const drawinglayer::primitive2d::Primitive2DReference xMask(
- new drawinglayer::primitive2d::MaskPrimitive2D(
- rClipPolyPolygon,
- xRetval));
-
- xRetval = drawinglayer::primitive2d::Primitive2DContainer{ xMask };
+ xRetval = drawinglayer::primitive2d::Primitive2DContainer{
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ rClipPolyPolygon,
+ std::move(xRetval))
+ };
}
}
@@ -448,7 +429,7 @@ namespace wmfemfhelper
{
/** helper to create a PointArrayPrimitive2D based on current context */
static void createPointArrayPrimitive(
- const std::vector< basegfx::B2DPoint >& rPositions,
+ std::vector< basegfx::B2DPoint >&& rPositions,
TargetHolder& rTarget,
PropertyHolder const & rProperties,
const basegfx::BColor& rBColor)
@@ -459,22 +440,20 @@ namespace wmfemfhelper
if(rProperties.getTransformation().isIdentity())
{
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>(
- rPositions,
+ new drawinglayer::primitive2d::PointArrayPrimitive2D(
+ std::move(rPositions),
rBColor));
}
else
{
- std::vector< basegfx::B2DPoint > aPositions(rPositions);
-
- for(basegfx::B2DPoint & aPosition : aPositions)
+ for(basegfx::B2DPoint & aPosition : rPositions)
{
aPosition = rProperties.getTransformation() * aPosition;
}
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>(
- aPositions,
+ new drawinglayer::primitive2d::PointArrayPrimitive2D(
+ std::move(rPositions),
rBColor));
}
}
@@ -490,8 +469,8 @@ namespace wmfemfhelper
basegfx::B2DPolygon aLinePolygon(rLinePolygon);
aLinePolygon.transform(rProperties.getTransformation());
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PolygonHairlinePrimitive2D>(
- aLinePolygon,
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ std::move(aLinePolygon),
rProperties.getLineColor()));
}
}
@@ -507,8 +486,8 @@ namespace wmfemfhelper
basegfx::B2DPolyPolygon aFillPolyPolygon(rFillPolyPolygon);
aFillPolyPolygon.transform(rProperties.getTransformation());
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
- aFillPolyPolygon,
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ std::move(aFillPolyPolygon),
rProperties.getFillColor()));
}
}
@@ -530,7 +509,7 @@ namespace wmfemfhelper
{
basegfx::B2DPolygon aLinePolygon(rLinePolygon);
aLinePolygon.transform(rProperties.getTransformation());
- const drawinglayer::attribute::LineAttribute aLineAttribute(
+ drawinglayer::attribute::LineAttribute aLineAttribute(
rProperties.getLineColor(),
bWidthUsed ? rLineInfo.GetWidth() : 0.0,
rLineInfo.GetLineJoin(),
@@ -538,39 +517,23 @@ namespace wmfemfhelper
if(bDashDotUsed)
{
- std::vector< double > fDotDashArray;
- const double fDashLen(rLineInfo.GetDashLen());
- const double fDotLen(rLineInfo.GetDotLen());
- const double fDistance(rLineInfo.GetDistance());
-
- for(sal_uInt16 a(0); a < rLineInfo.GetDashCount(); a++)
- {
- fDotDashArray.push_back(fDashLen);
- fDotDashArray.push_back(fDistance);
- }
-
- for(sal_uInt16 b(0); b < rLineInfo.GetDotCount(); b++)
- {
- fDotDashArray.push_back(fDotLen);
- fDotDashArray.push_back(fDistance);
- }
-
+ std::vector< double > fDotDashArray = rLineInfo.GetDotDashArray();
const double fAccumulated(std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
- const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
- fDotDashArray,
+ drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
+ std::move(fDotDashArray),
fAccumulated);
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>(
- aLinePolygon,
- aLineAttribute,
- aStrokeAttribute));
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ std::move(aLinePolygon),
+ std::move(aLineAttribute),
+ std::move(aStrokeAttribute)));
}
else
{
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>(
- aLinePolygon,
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ std::move(aLinePolygon),
aLineAttribute));
}
}
@@ -623,33 +586,33 @@ namespace wmfemfhelper
position and size in pixels. At the end it will create a view-dependent
transformed embedding of a BitmapPrimitive2D.
*/
- static void createBitmapExPrimitive(
- const BitmapEx& rBitmapEx,
+ static void createBitmapPrimitive(
+ const Bitmap& rBitmap,
const Point& rPoint,
TargetHolder& rTarget,
PropertyHolder const & rProperties)
{
- if(!rBitmapEx.IsEmpty())
+ if(!rBitmap.IsEmpty())
{
basegfx::B2DPoint aPoint(rPoint.X(), rPoint.Y());
aPoint = rProperties.getTransformation() * aPoint;
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::DiscreteBitmapPrimitive2D>(
- rBitmapEx,
+ new drawinglayer::primitive2d::DiscreteBitmapPrimitive2D(
+ rBitmap,
aPoint));
}
}
/** helper to create BitmapPrimitive2D based on current context */
- static void createBitmapExPrimitive(
- const BitmapEx& rBitmapEx,
+ static void createBitmapPrimitive(
+ const Bitmap& rBitmap,
const Point& rPoint,
const Size& rSize,
TargetHolder& rTarget,
PropertyHolder const & rProperties)
{
- if(rBitmapEx.IsEmpty())
+ if(rBitmap.IsEmpty())
return;
basegfx::B2DHomMatrix aObjectTransform;
@@ -662,8 +625,8 @@ namespace wmfemfhelper
aObjectTransform = rProperties.getTransformation() * aObjectTransform;
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::BitmapPrimitive2D>(
- VCLUnoHelper::CreateVCLXBitmap(rBitmapEx),
+ new drawinglayer::primitive2d::BitmapPrimitive2D(
+ rBitmap,
aObjectTransform));
}
@@ -671,20 +634,19 @@ namespace wmfemfhelper
which use a bitmap without transparence but define one of the colors as
transparent)
*/
- static BitmapEx createMaskBmpEx(const Bitmap& rBitmap, const Color& rMaskColor)
+ static Bitmap createMaskBmp(const Bitmap& rBitmap, const Color& rMaskColor)
{
const Color aWhite(COL_WHITE);
- BitmapPalette aBiLevelPalette(2);
-
- aBiLevelPalette[0] = aWhite;
- aBiLevelPalette[1] = rMaskColor;
+ BitmapPalette aBiLevelPalette {
+ aWhite, rMaskColor
+ };
- Bitmap aMask(rBitmap.CreateMask(aWhite));
- Bitmap aSolid(rBitmap.GetSizePixel(), 1, &aBiLevelPalette);
+ AlphaMask aMask(rBitmap.CreateAlphaMask(aWhite));
+ Bitmap aSolid(rBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aBiLevelPalette);
aSolid.Erase(rMaskColor);
- return BitmapEx(aSolid, aMask);
+ return Bitmap(aSolid, aMask);
}
/** helper to convert from a VCL Gradient definition to the corresponding
@@ -712,50 +674,13 @@ namespace wmfemfhelper
aEnd = interpolate(aBlack, aEnd, static_cast<double>(nEndIntens) * 0.01);
}
- drawinglayer::attribute::GradientStyle aGradientStyle(drawinglayer::attribute::GradientStyle::Rect);
-
- switch(rGradient.GetStyle())
- {
- case GradientStyle::Linear :
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Linear;
- break;
- }
- case GradientStyle::Axial :
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Axial;
- break;
- }
- case GradientStyle::Radial :
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Radial;
- break;
- }
- case GradientStyle::Elliptical :
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Elliptical;
- break;
- }
- case GradientStyle::Square :
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Square;
- break;
- }
- default : // GradientStyle::Rect
- {
- aGradientStyle = drawinglayer::attribute::GradientStyle::Rect;
- break;
- }
- }
-
return drawinglayer::attribute::FillGradientAttribute(
- aGradientStyle,
+ rGradient.GetStyle(),
static_cast<double>(rGradient.GetBorder()) * 0.01,
static_cast<double>(rGradient.GetOfsX()) * 0.01,
static_cast<double>(rGradient.GetOfsY()) * 0.01,
- static_cast<double>(rGradient.GetAngle()) * F_PI1800,
- aStart,
- aEnd,
+ toRadians(rGradient.GetAngle()),
+ basegfx::BColorStops(aStart, aEnd),
rGradient.GetSteps());
}
@@ -788,7 +713,7 @@ namespace wmfemfhelper
return drawinglayer::attribute::FillHatchAttribute(
aHatchStyle,
static_cast<double>(rHatch.GetDistance()),
- static_cast<double>(rHatch.GetAngle()) * F_PI1800,
+ toRadians(rHatch.GetAngle()),
rHatch.GetColor().getBColor(),
3, // same default as VCL, a minimum of three discrete units (pixels) offset
false);
@@ -858,8 +783,8 @@ namespace wmfemfhelper
if(!aSubContent.empty())
{
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::GroupPrimitive2D>(
- aSubContent));
+ new drawinglayer::primitive2d::GroupPrimitive2D(
+ std::move(aSubContent)));
}
}
@@ -905,8 +830,8 @@ namespace wmfemfhelper
{
// force content to black
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::ModifiedColorPrimitive2D>(
- aSubContent,
+ new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+ std::move(aSubContent),
std::make_shared<basegfx::BColorModifier_replace>(
basegfx::BColor(0.0, 0.0, 0.0))));
}
@@ -914,8 +839,8 @@ namespace wmfemfhelper
{
// invert content
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::InvertPrimitive2D>(
- aSubContent));
+ new drawinglayer::primitive2d::InvertPrimitive2D(
+ std::move(aSubContent)));
}
}
}
@@ -934,7 +859,7 @@ namespace wmfemfhelper
/** helper to create needed data to emulate the VCL Wallpaper Metafile action.
It is a quite mighty action. This helper is for simple color filled background.
*/
- static std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> CreateColorWallpaper(
+ static rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> CreateColorWallpaper(
const basegfx::B2DRange& rRange,
const basegfx::BColor& rColor,
PropertyHolder const & rPropertyHolder)
@@ -942,7 +867,7 @@ namespace wmfemfhelper
basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(rRange));
aOutline.transform(rPropertyHolder.getTransformation());
- return std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
+ return new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aOutline),
rColor);
}
@@ -950,34 +875,35 @@ namespace wmfemfhelper
/** helper to create needed data to emulate the VCL Wallpaper Metafile action.
It is a quite mighty action. This helper is for gradient filled background.
*/
- static std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> CreateGradientWallpaper(
+ static rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> CreateGradientWallpaper(
const basegfx::B2DRange& rRange,
const Gradient& rGradient,
PropertyHolder const & rPropertyHolder)
{
- const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ basegfx::BColor aSingleColor;
- if(aAttribute.getStartColor() == aAttribute.getEndColor())
+ if (aAttribute.getColorStops().isSingleColor(aSingleColor))
{
// not really a gradient. Create filled rectangle
- return CreateColorWallpaper(rRange, aAttribute.getStartColor(), rPropertyHolder);
+ return CreateColorWallpaper(rRange, aSingleColor, rPropertyHolder);
}
else
{
// really a gradient
- std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D> pRetval(
+ rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pRetval(
new drawinglayer::primitive2d::FillGradientPrimitive2D(
rRange,
- aAttribute));
+ std::move(aAttribute)));
if(!rPropertyHolder.getTransformation().isIdentity())
{
- const drawinglayer::primitive2d::Primitive2DReference xPrim(pRetval.release());
- const drawinglayer::primitive2d::Primitive2DContainer xSeq { xPrim };
+ const drawinglayer::primitive2d::Primitive2DReference xPrim(pRetval);
+ drawinglayer::primitive2d::Primitive2DContainer xSeq { xPrim };
- pRetval.reset(new drawinglayer::primitive2d::TransformPrimitive2D(
+ pRetval = new drawinglayer::primitive2d::TransformPrimitive2D(
rPropertyHolder.getTransformation(),
- xSeq));
+ std::move(xSeq));
}
return pRetval;
@@ -996,12 +922,12 @@ namespace wmfemfhelper
TargetHolder& rTarget,
PropertyHolder const & rProperty)
{
- const BitmapEx aBitmapEx(rWallpaper.GetBitmap());
+ const Bitmap& aBitmap(rWallpaper.GetBitmap());
const WallpaperStyle eWallpaperStyle(rWallpaper.GetStyle());
// if bitmap visualisation is transparent, maybe background
// needs to be filled. Create background
- if(aBitmapEx.IsTransparent()
+ if(aBitmap.HasAlpha()
|| (WallpaperStyle::Tile != eWallpaperStyle && WallpaperStyle::Scale != eWallpaperStyle))
{
if(rWallpaper.IsGradient())
@@ -1012,7 +938,7 @@ namespace wmfemfhelper
rWallpaper.GetGradient(),
rProperty));
}
- else if(!rWallpaper.GetColor().GetTransparency())
+ else if(!rWallpaper.GetColor().IsTransparent())
{
rTarget.append(
CreateColorWallpaper(
@@ -1028,26 +954,24 @@ namespace wmfemfhelper
aWallpaperRange = vcl::unotools::b2DRectangleFromRectangle(rWallpaper.GetRect());
}
- drawinglayer::primitive2d::BasePrimitive2D* pBitmapWallpaperFill =
+ rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pBitmapWallpaperFill =
new drawinglayer::primitive2d::WallpaperBitmapPrimitive2D(
aWallpaperRange,
- aBitmapEx,
+ aBitmap,
eWallpaperStyle);
if(rProperty.getTransformation().isIdentity())
{
// add directly
- rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(pBitmapWallpaperFill));
+ rTarget.append(pBitmapWallpaperFill);
}
else
{
// when a transformation is set, embed to it
- const drawinglayer::primitive2d::Primitive2DReference xPrim(pBitmapWallpaperFill);
-
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
rProperty.getTransformation(),
- drawinglayer::primitive2d::Primitive2DContainer { xPrim }));
+ drawinglayer::primitive2d::Primitive2DContainer { pBitmapWallpaperFill }));
}
}
@@ -1075,8 +999,8 @@ namespace wmfemfhelper
rFontAttribute = drawinglayer::primitive2d::getFontAttributeFromVclFont(
aFontScaling,
rFont,
- bool(rProperty.getLayoutMode() & ComplexTextLayoutFlags::BiDiRtl),
- bool(rProperty.getLayoutMode() & ComplexTextLayoutFlags::BiDiStrong));
+ bool(rProperty.getLayoutMode() & vcl::text::ComplexTextLayoutFlags::BiDiRtl),
+ bool(rProperty.getLayoutMode() & vcl::text::ComplexTextLayoutFlags::BiDiStrong));
// add FontScaling
rTextTransform.scale(aFontScaling.getX(), aFontScaling.getY());
@@ -1102,7 +1026,7 @@ namespace wmfemfhelper
// add FontRotation (if used)
if(rFont.GetOrientation())
{
- rTextTransform.rotate(-rFont.GetOrientation() * F_PI1800);
+ rTextTransform.rotate(-toRadians(rFont.GetOrientation()));
}
}
@@ -1114,11 +1038,12 @@ namespace wmfemfhelper
const OUString& rText,
sal_uInt16 nTextStart,
sal_uInt16 nTextLength,
- const std::vector< double >& rDXArray,
+ std::vector< double >&& rDXArray,
+ std::vector< sal_Bool >&& rKashidaArray,
TargetHolder& rTarget,
PropertyHolder const & rProperty)
{
- drawinglayer::primitive2d::BasePrimitive2D* pResult = nullptr;
+ rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pResult;
const vcl::Font& rFont = rProperty.getFont();
basegfx::B2DVector aAlignmentOffset(0.0, 0.0);
@@ -1140,7 +1065,7 @@ namespace wmfemfhelper
// prepare FontColor and Locale
const basegfx::BColor aFontColor(rProperty.getTextColor());
const Color aFillColor(rFont.GetFillColor());
- const css::lang::Locale aLocale(LanguageTag(rProperty.getLanguageType()).getLocale());
+ css::lang::Locale aLocale(LanguageTag(rProperty.getLanguageType()).getLocale());
const bool bWordLineMode(rFont.IsWordLineMode());
const bool bDecoratedIsNeeded(
@@ -1198,7 +1123,8 @@ namespace wmfemfhelper
rText,
nTextStart,
nTextLength,
- rDXArray,
+ std::vector(rDXArray),
+ std::move(rKashidaArray),
aFontAttribute,
aLocale,
aFontColor,
@@ -1226,9 +1152,10 @@ namespace wmfemfhelper
rText,
nTextStart,
nTextLength,
- rDXArray,
- aFontAttribute,
- aLocale,
+ std::vector(rDXArray),
+ std::move(rKashidaArray),
+ std::move(aFontAttribute),
+ std::move(aLocale),
aFontColor);
}
}
@@ -1242,7 +1169,7 @@ namespace wmfemfhelper
// get text width
double fTextWidth(0.0);
- if(rDXArray.empty())
+ if (rDXArray.empty())
{
fTextWidth = aTextLayouterDevice.getTextWidth(rText, nTextStart, nTextLength);
}
@@ -1251,7 +1178,7 @@ namespace wmfemfhelper
fTextWidth = rDXArray.back();
}
- if(basegfx::fTools::more(fTextWidth, 0.0))
+ if (fTextWidth > 0.0 && !basegfx::fTools::equalZero(fTextWidth))
{
// build text range
const basegfx::B2DRange aTextRange(
@@ -1265,14 +1192,14 @@ namespace wmfemfhelper
if(rFont.GetOrientation())
{
- aTextTransform.rotate(-rFont.GetOrientation() * F_PI1800);
+ aTextTransform.rotate(-toRadians(rFont.GetOrientation()));
}
aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y());
// prepare Primitive2DSequence, put text in foreground
drawinglayer::primitive2d::Primitive2DContainer aSequence(2);
- aSequence[1] = drawinglayer::primitive2d::Primitive2DReference(pResult);
+ aSequence[1] = pResult;
// prepare filled polygon
basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aTextRange));
@@ -1284,7 +1211,7 @@ namespace wmfemfhelper
rProperty.getTextFillColor()));
// set as group at pResult
- pResult = new drawinglayer::primitive2d::GroupPrimitive2D(aSequence);
+ pResult = new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aSequence));
}
}
@@ -1294,22 +1221,20 @@ namespace wmfemfhelper
// add created text primitive to target
if(rProperty.getTransformation().isIdentity())
{
- rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(pResult));
+ rTarget.append(pResult);
}
else
{
// when a transformation is set, embed to it
- const drawinglayer::primitive2d::Primitive2DReference aReference(pResult);
-
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
rProperty.getTransformation(),
- drawinglayer::primitive2d::Primitive2DContainer { aReference }));
+ drawinglayer::primitive2d::Primitive2DContainer { pResult }));
}
}
/** helper which takes complete care for creating the needed textLine primitives */
- static void proccessMetaTextLineAction(
+ static void processMetaTextLineAction(
const MetaTextLineAction& rAction,
TargetHolder& rTarget,
PropertyHolder const & rProperty)
@@ -1330,7 +1255,7 @@ namespace wmfemfhelper
if(!(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed))
return;
- std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargetVector;
+ drawinglayer::primitive2d::Primitive2DContainer aTargets;
basegfx::B2DVector aAlignmentOffset(0.0, 0.0);
drawinglayer::attribute::FontAttribute aFontAttribute;
basegfx::B2DHomMatrix aTextTransform;
@@ -1352,7 +1277,7 @@ namespace wmfemfhelper
if(bOverlineUsed)
{
// create primitive geometry for overline
- aTargetVector.push_back(
+ aTargets.push_back(
new drawinglayer::primitive2d::TextLinePrimitive2D(
aTextTransform,
fLineWidth,
@@ -1365,7 +1290,7 @@ namespace wmfemfhelper
if(bUnderlineUsed)
{
// create primitive geometry for underline
- aTargetVector.push_back(
+ aTargets.push_back(
new drawinglayer::primitive2d::TextLinePrimitive2D(
aTextTransform,
fLineWidth,
@@ -1384,22 +1309,22 @@ namespace wmfemfhelper
// strikeout with character
const sal_Unicode aStrikeoutChar(
drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout ? '/' : 'X');
- const css::lang::Locale aLocale(LanguageTag(
+ css::lang::Locale aLocale(LanguageTag(
rProperty.getLanguageType()).getLocale());
- aTargetVector.push_back(
+ aTargets.push_back(
new drawinglayer::primitive2d::TextCharacterStrikeoutPrimitive2D(
aTextTransform,
fLineWidth,
rProperty.getTextColor(),
aStrikeoutChar,
- aFontAttribute,
- aLocale));
+ std::move(aFontAttribute),
+ std::move(aLocale)));
}
else
{
// strikeout with geometry
- aTargetVector.push_back(
+ aTargets.push_back(
new drawinglayer::primitive2d::TextGeometryStrikeoutPrimitive2D(
aTextTransform,
fLineWidth,
@@ -1410,31 +1335,21 @@ namespace wmfemfhelper
}
}
- if(aTargetVector.empty())
+ if(aTargets.empty())
return;
// add created text primitive to target
if(rProperty.getTransformation().isIdentity())
{
- for(drawinglayer::primitive2d::BasePrimitive2D* a : aTargetVector)
- {
- rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(a));
- }
+ rTarget.append(std::move(aTargets));
}
else
{
// when a transformation is set, embed to it
- drawinglayer::primitive2d::Primitive2DContainer xTargets(aTargetVector.size());
-
- for(size_t a(0); a < aTargetVector.size(); a++)
- {
- xTargets[a] = drawinglayer::primitive2d::Primitive2DReference(aTargetVector[a]);
- }
-
rTarget.append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
rProperty.getTransformation(),
- xTargets));
+ std::move(aTargets)));
}
}
@@ -1508,7 +1423,7 @@ namespace wmfemfhelper
{
if(!aPositions.empty())
{
- createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
+ createPointArrayPrimitive(std::move(aPositions), rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
aPositions.clear();
}
@@ -1524,7 +1439,7 @@ namespace wmfemfhelper
if(!aPositions.empty())
{
- createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
+ createPointArrayPrimitive(std::move(aPositions), rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
}
break;
@@ -1548,7 +1463,7 @@ namespace wmfemfhelper
if(!aPositions.empty())
{
- createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), rPropertyHolders.Current().getLineColor());
+ createPointArrayPrimitive(std::move(aPositions), rTargetHolders.Current(), rPropertyHolders.Current(), rPropertyHolders.Current().getLineColor());
}
}
@@ -1579,7 +1494,6 @@ namespace wmfemfhelper
}
else
{
- aLineInfo.SetLineJoin(basegfx::B2DLineJoin::NONE); // It were lines; force to NONE
createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current());
aLinePolygon.clear();
aLineInfo = pA->GetLineInfo();
@@ -1594,16 +1508,14 @@ namespace wmfemfhelper
aLinePolygon.append(aEnd);
}
- nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction);
+ nAction++;
+ if (nAction < nCount)
+ pAction = rMetaFile.GetAction(nAction);
}
nAction--;
-
- if(aLinePolygon.count())
- {
- aLineInfo.SetLineJoin(basegfx::B2DLineJoin::NONE); // It were lines; force to NONE
+ if (aLinePolygon.count())
createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current());
- }
}
break;
@@ -1657,8 +1569,8 @@ namespace wmfemfhelper
{
double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
- fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
- fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
+ fRadiusX = std::clamp(fRadiusX, 0.0, 1.0);
+ fRadiusY = std::clamp(fRadiusY, 0.0, 1.0);
aOutline = basegfx::utils::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
}
@@ -1814,13 +1726,14 @@ namespace wmfemfhelper
if(nTextLength && rPropertyHolders.Current().getTextColorActive())
{
- const std::vector< double > aDXArray{};
+ std::vector< double > aDXArray{};
processMetaTextAction(
pA->GetPoint(),
pA->GetText(),
nTextIndex,
nTextLength,
- aDXArray,
+ std::move(aDXArray),
+ {},
rTargetHolders.Current(),
rPropertyHolders.Current());
}
@@ -1844,15 +1757,16 @@ namespace wmfemfhelper
{
// prepare DXArray (if used)
std::vector< double > aDXArray;
- long* pDXArray = pA->GetDXArray();
+ const KernArray& rDXArray = pA->GetDXArray();
+ std::vector< sal_Bool > aKashidaArray = pA->GetKashidaArray();
- if(pDXArray)
+ if(!rDXArray.empty())
{
aDXArray.reserve(nTextLength);
for(sal_uInt32 a(0); a < nTextLength; a++)
{
- aDXArray.push_back(static_cast<double>(*(pDXArray + a)));
+ aDXArray.push_back(static_cast<double>(rDXArray[a]));
}
}
@@ -1861,7 +1775,8 @@ namespace wmfemfhelper
pA->GetText(),
nTextIndex,
nTextLength,
- aDXArray,
+ std::move(aDXArray),
+ std::move(aKashidaArray),
rTargetHolders.Current(),
rPropertyHolders.Current());
}
@@ -1924,7 +1839,8 @@ namespace wmfemfhelper
pA->GetText(),
nTextIndex,
nTextLength,
- aTextArray,
+ std::move(aTextArray),
+ {},
rTargetHolders.Current(),
rPropertyHolders.Current());
}
@@ -1982,9 +1898,9 @@ namespace wmfemfhelper
{
// add with transformation
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
rPropertyHolders.Current().getTransformation(),
- xSubContent));
+ std::move(xSubContent)));
}
}
}
@@ -1995,9 +1911,9 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL */
const MetaBmpAction* pA = static_cast<const MetaBmpAction*>(pAction);
- const BitmapEx aBitmapEx(pA->GetBitmap());
+ const Bitmap aBitmap(pA->GetBitmap());
- createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aBitmap, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2005,9 +1921,9 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL */
const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
- const BitmapEx aBitmapEx(pA->GetBitmap());
+ const Bitmap aBitmap(pA->GetBitmap());
- createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aBitmap, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2027,8 +1943,7 @@ namespace wmfemfhelper
aCroppedBitmap.Crop(aCropRectangle);
}
- const BitmapEx aCroppedBitmapEx(aCroppedBitmap);
- createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aCroppedBitmap, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
}
break;
@@ -2037,9 +1952,9 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL: Simply same as MetaActionType::BMP */
const MetaBmpExAction* pA = static_cast<const MetaBmpExAction*>(pAction);
- const BitmapEx& rBitmapEx = pA->GetBitmapEx();
+ const Bitmap& rBitmap = pA->GetBitmap();
- createBitmapExPrimitive(rBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(rBitmap, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2047,9 +1962,9 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL: Simply same as MetaActionType::BMPSCALE */
const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
- const BitmapEx& rBitmapEx = pA->GetBitmapEx();
+ const Bitmap& rBitmap = pA->GetBitmap();
- createBitmapExPrimitive(rBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(rBitmap, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2057,19 +1972,19 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL: Simply same as MetaActionType::BMPSCALEPART */
const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
- const BitmapEx& rBitmapEx = pA->GetBitmapEx();
+ const Bitmap& rBitmap = pA->GetBitmap();
- if(!rBitmapEx.IsEmpty())
+ if(!rBitmap.IsEmpty())
{
- BitmapEx aCroppedBitmapEx(rBitmapEx);
+ Bitmap aCroppedBitmap(rBitmap);
const tools::Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
if(!aCropRectangle.IsEmpty())
{
- aCroppedBitmapEx.Crop(aCropRectangle);
+ aCroppedBitmap.Crop(aCropRectangle);
}
- createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aCroppedBitmap, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
}
break;
@@ -2079,9 +1994,9 @@ namespace wmfemfhelper
/** CHECKED, WORKS WELL: Simply same as MetaActionType::BMP */
/** Huh, no it isn't!? */
const MetaMaskAction* pA = static_cast<const MetaMaskAction*>(pAction);
- const BitmapEx aBitmapEx(createMaskBmpEx(pA->GetBitmap(), pA->GetColor()));
+ const Bitmap aBitmap(createMaskBmp(pA->GetBitmap(), pA->GetColor()));
- createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aBitmap, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2089,9 +2004,9 @@ namespace wmfemfhelper
{
/** CHECKED, WORKS WELL: Simply same as MetaActionType::BMPSCALE */
const MetaMaskScaleAction* pA = static_cast<const MetaMaskScaleAction*>(pAction);
- const BitmapEx aBitmapEx(createMaskBmpEx(pA->GetBitmap(), pA->GetColor()));
+ const Bitmap aBitmap(createMaskBmp(pA->GetBitmap(), pA->GetColor()));
- createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ createBitmapPrimitive(aBitmap, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current());
break;
}
@@ -2111,8 +2026,8 @@ namespace wmfemfhelper
aCroppedBitmap.Crop(aCropRectangle);
}
- const BitmapEx aCroppedBitmapEx(createMaskBmpEx(aCroppedBitmap, pA->GetColor()));
- createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
+ const Bitmap aCroppedBitmap2(createMaskBmp(aCroppedBitmap, pA->GetColor()));
+ createBitmapPrimitive(aCroppedBitmap2, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current());
}
break;
@@ -2130,10 +2045,11 @@ namespace wmfemfhelper
if(!aRange.isEmpty())
{
const Gradient& rGradient = pA->GetGradient();
- const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
basegfx::B2DPolyPolygon aOutline(basegfx::utils::createPolygonFromRect(aRange));
+ basegfx::BColor aSingleColor;
- if(aAttribute.getStartColor() == aAttribute.getEndColor())
+ if (aAttribute.getColorStops().isSingleColor(aSingleColor))
{
// not really a gradient. Create filled rectangle
createFillPrimitive(
@@ -2162,7 +2078,7 @@ namespace wmfemfhelper
xGradient[0] = drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::FillGradientPrimitive2D(
aRange,
- aAttribute));
+ std::move(aAttribute)));
}
// #i112300# clip against polygon representing the rectangle from
@@ -2170,9 +2086,9 @@ namespace wmfemfhelper
// when a MetaGradientAction is executed
aOutline.transform(rPropertyHolders.Current().getTransformation());
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::MaskPrimitive2D>(
- aOutline,
- xGradient));
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ std::move(aOutline),
+ std::move(xGradient)));
}
}
}
@@ -2188,7 +2104,7 @@ namespace wmfemfhelper
if(aOutline.count())
{
const Hatch& rHatch = pA->GetHatch();
- const drawinglayer::attribute::FillHatchAttribute aAttribute(createFillHatchAttribute(rHatch));
+ drawinglayer::attribute::FillHatchAttribute aAttribute(createFillHatchAttribute(rHatch));
aOutline.transform(rPropertyHolders.Current().getTransformation());
@@ -2197,11 +2113,11 @@ namespace wmfemfhelper
new drawinglayer::primitive2d::FillHatchPrimitive2D(
aObjectRange,
basegfx::BColor(),
- aAttribute));
+ std::move(aAttribute)));
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::MaskPrimitive2D>(
- aOutline,
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ std::move(aOutline),
drawinglayer::primitive2d::Primitive2DContainer { aFillHatch }));
}
@@ -2241,7 +2157,7 @@ namespace wmfemfhelper
rWallpaper.GetGradient(),
rPropertyHolders.Current()));
}
- else if(!rWallpaper.GetColor().GetTransparency())
+ else if(!rWallpaper.GetColor().IsTransparent())
{
// create color background
rTargetHolders.Current().append(
@@ -2421,14 +2337,12 @@ namespace wmfemfhelper
// prepare translation, add current transformation
basegfx::B2DVector aVector(pA->GetHorzMove(), pA->GetVertMove());
aVector *= rPropertyHolders.Current().getTransformation();
- basegfx::B2DHomMatrix aTransform(
- basegfx::utils::createTranslateB2DHomMatrix(aVector));
// transform existing region
basegfx::B2DPolyPolygon aClipPolyPolygon(
rPropertyHolders.Current().getClipPolyPolygon());
- aClipPolyPolygon.transform(aTransform);
+ aClipPolyPolygon.translate(aVector);
HandleNewClipRegion(aClipPolyPolygon, rTargetHolders, rPropertyHolders);
}
}
@@ -2528,34 +2442,15 @@ namespace wmfemfhelper
}
else
{
- switch(rMapMode.GetMapUnit())
+ const auto eFrom = MapToO3tlLength(rPropertyHolders.Current().getMapUnit()),
+ eTo = MapToO3tlLength(rMapMode.GetMapUnit());
+ if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
{
- case MapUnit::Map100thMM :
- {
- if(MapUnit::MapTwip == rPropertyHolders.Current().getMapUnit())
- {
- // MapUnit::MapTwip -> MapUnit::Map100thMM
- const double fTwipTo100thMm(127.0 / 72.0);
- aMapping.scale(fTwipTo100thMm, fTwipTo100thMm);
- }
- break;
- }
- case MapUnit::MapTwip :
- {
- if(MapUnit::Map100thMM == rPropertyHolders.Current().getMapUnit())
- {
- // MapUnit::Map100thMM -> MapUnit::MapTwip
- const double f100thMmToTwip(72.0 / 127.0);
- aMapping.scale(f100thMmToTwip, f100thMmToTwip);
- }
- break;
- }
- default :
- {
- OSL_FAIL("implInterpretMetafile: MetaActionType::MAPMODE with unsupported MapUnit (!)");
- break;
- }
+ const double fConvert(o3tl::convert(1.0, eFrom, eTo));
+ aMapping.scale(fConvert, fConvert);
}
+ else
+ OSL_FAIL("implInterpretMetafile: MetaActionType::MAPMODE with unsupported MapUnit (!)");
aMapping = getTransformFromMapMode(rMapMode) * aMapping;
rPropertyHolders.Current().setMapUnit(rMapMode.GetMapUnit());
@@ -2633,8 +2528,8 @@ namespace wmfemfhelper
case MetaActionType::POP :
{
/** CHECKED, WORKS WELL */
- const bool bRegionMayChange(rPropertyHolders.Current().getPushFlags() & PushFlags::CLIPREGION);
- const bool bRasterOpMayChange(rPropertyHolders.Current().getPushFlags() & PushFlags::RASTEROP);
+ const bool bRegionMayChange(rPropertyHolders.Current().getPushFlags() & vcl::PushFlags::CLIPREGION);
+ const bool bRasterOpMayChange(rPropertyHolders.Current().getPushFlags() & vcl::PushFlags::RASTEROP);
if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive())
{
@@ -2703,7 +2598,7 @@ namespace wmfemfhelper
// create primitives there and get them
createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
- const drawinglayer::primitive2d::Primitive2DContainer aSubContent(
+ drawinglayer::primitive2d::Primitive2DContainer aSubContent(
rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()));
// back to old target
@@ -2712,8 +2607,8 @@ namespace wmfemfhelper
if(!aSubContent.empty())
{
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>(
- aSubContent,
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aSubContent),
nTransparence * 0.01));
}
}
@@ -2746,7 +2641,7 @@ namespace wmfemfhelper
// embed using EpsPrimitive
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::EpsPrimitive2D>(
+ new drawinglayer::primitive2d::EpsPrimitive2D(
aObjectTransform,
pA->GetLink(),
pA->GetSubstitute()));
@@ -2786,7 +2681,7 @@ namespace wmfemfhelper
// Font.
const MetaTextLineAction* pA = static_cast<const MetaTextLineAction*>(pAction);
- proccessMetaTextLineAction(
+ processMetaTextLineAction(
*pA,
rTargetHolders.Current(),
rPropertyHolders.Current());
@@ -2853,22 +2748,23 @@ namespace wmfemfhelper
const drawinglayer::primitive2d::Primitive2DReference aEmbeddedTransform(
new drawinglayer::primitive2d::TransformPrimitive2D(
aSubTransform,
- xSubContent));
+ std::move(xSubContent)));
xSubContent = drawinglayer::primitive2d::Primitive2DContainer { aEmbeddedTransform };
}
// check if gradient is a real gradient
const Gradient& rGradient = pA->GetGradient();
- const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ basegfx::BColor aSingleColor;
- if(aAttribute.getStartColor() == aAttribute.getEndColor())
+ if (aAttribute.getColorStops().isSingleColor(aSingleColor))
{
// not really a gradient; create UnifiedTransparencePrimitive2D
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>(
- xSubContent,
- aAttribute.getStartColor().luminance()));
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(xSubContent),
+ aSingleColor.luminance()));
}
else
{
@@ -2880,12 +2776,12 @@ namespace wmfemfhelper
const drawinglayer::primitive2d::Primitive2DReference xTransparence(
new drawinglayer::primitive2d::FillGradientPrimitive2D(
aRange,
- aAttribute));
+ std::move(aAttribute)));
// create transparence primitive
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::TransparencePrimitive2D>(
- xSubContent,
+ new drawinglayer::primitive2d::TransparencePrimitive2D(
+ std::move(xSubContent),
drawinglayer::primitive2d::Primitive2DContainer { xTransparence }));
}
}
@@ -2980,23 +2876,24 @@ namespace wmfemfhelper
// get and check if gradient is a real gradient
const Gradient& rGradient = pMetaGradientExAction->GetGradient();
- const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
+ basegfx::BColor aSingleColor;
- if(aAttribute.getStartColor() == aAttribute.getEndColor())
+ if (aAttribute.getColorStops().isSingleColor(aSingleColor))
{
// not really a gradient
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>(
- aPolyPolygon,
- aAttribute.getStartColor()));
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ std::move(aPolyPolygon),
+ aSingleColor));
}
else
{
// really a gradient
rTargetHolders.Current().append(
- std::make_unique<drawinglayer::primitive2d::PolyPolygonGradientPrimitive2D>(
+ new drawinglayer::primitive2d::PolyPolygonGradientPrimitive2D(
aPolyPolygon,
- aAttribute));
+ std::move(aAttribute)));
}
}
}
@@ -3006,11 +2903,11 @@ namespace wmfemfhelper
if (aEMFPlus)
{
// error: should not yet exist
- SAL_INFO("drawinglayer", "Error: multiple EMF_PLUS_HEADER_INFO");
+ SAL_INFO("drawinglayer.emf", "Error: multiple EMF_PLUS_HEADER_INFO");
}
else
{
- SAL_INFO("drawinglayer", "EMF+ passed to canvas mtf renderer - header info, size: " << pA->GetDataSize());
+ SAL_INFO("drawinglayer.emf", "EMF+ passed to canvas mtf renderer - header info, size: " << pA->GetDataSize());
SvMemoryStream aMemoryStream(const_cast<sal_uInt8 *>(pA->GetData()), pA->GetDataSize(), StreamMode::READ);
aEMFPlus.reset(
@@ -3025,7 +2922,7 @@ namespace wmfemfhelper
if (!aEMFPlus)
{
// error: should exist
- SAL_INFO("drawinglayer", "Error: EMF_PLUS before EMF_PLUS_HEADER_INFO");
+ SAL_INFO("drawinglayer.emf", "Error: EMF_PLUS before EMF_PLUS_HEADER_INFO");
}
else
{
@@ -3038,11 +2935,11 @@ namespace wmfemfhelper
if (char *env = getenv("EMF_PLUS_LIMIT"))
{
limit = atoi(env);
- SAL_INFO("drawinglayer", "EMF+ records limit: " << limit);
+ SAL_INFO("drawinglayer.emf", "EMF+ records limit: " << limit);
}
}
- SAL_INFO("drawinglayer", "EMF+ passed to canvas mtf renderer, size: " << pA->GetDataSize());
+ SAL_INFO("drawinglayer.emf", "EMF+ passed to canvas mtf renderer, size: " << pA->GetDataSize());
if (count < limit)
{