From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- oox/qa/token/tokenmap-test.cxx | 66 + oox/qa/unit/CryptoTest.cxx | 501 ++++++++ oox/qa/unit/data/FaultyPathStart.odp | Bin 0 -> 14582 bytes oox/qa/unit/data/MCGR_FontworkColorGradient.fodp | 662 ++++++++++ oox/qa/unit/data/MCGR_FontworkColorGradient.fodt | 331 +++++ oox/qa/unit/data/ReferenceShapeFill.fodp | 838 ++++++++++++ oox/qa/unit/data/ThemeShapesReference.pptx | Bin 0 -> 42644 bytes oox/qa/unit/data/WPC_BentConnector.docx | Bin 0 -> 20260 bytes oox/qa/unit/data/WPC_CanvasBackground.docx | Bin 0 -> 18810 bytes oox/qa/unit/data/WPC_CurvedConnector2.docx | Bin 0 -> 20635 bytes oox/qa/unit/data/WPC_CurvedConnector5.docx | Bin 0 -> 21262 bytes oox/qa/unit/data/WPC_Glow.docx | Bin 0 -> 22506 bytes oox/qa/unit/data/WPC_MulticolorGradient.docx | Bin 0 -> 30096 bytes oox/qa/unit/data/WPC_Shadow.docx | Bin 0 -> 21385 bytes oox/qa/unit/data/WPC_Textwrap_in_ellipse.docx | Bin 0 -> 20014 bytes oox/qa/unit/data/WPC_ThemeColor.docx | Bin 0 -> 18941 bytes oox/qa/unit/data/WPC_tdf104671_Cloud.docx | Bin 0 -> 20431 bytes .../data/WPC_tdf158339_shape_text_in_group.docx | Bin 0 -> 20454 bytes .../WPC_tdf158348_shape_text_in_table_cell.docx | Bin 0 -> 19725 bytes .../WPC_tdf48610_Textbox_with_table_inside.docx | Bin 0 -> 22920 bytes .../data/camera-rotation-revolution-nonwps.pptx | Bin 0 -> 31425 bytes oox/qa/unit/data/camera-rotation-revolution.docx | Bin 0 -> 23748 bytes oox/qa/unit/data/chart-data-label-char-color.docx | Bin 0 -> 26014 bytes oox/qa/unit/data/chart-theme-override.pptx | Bin 0 -> 37016 bytes oox/qa/unit/data/customshape-position.docx | Bin 0 -> 42054 bytes oox/qa/unit/data/dml-groupshape-polygon.docx | Bin 0 -> 24492 bytes oox/qa/unit/data/endParaRPr-newline-textsize.pptx | Bin 0 -> 13349 bytes .../unit/data/gradient-multistep-transparency.pptx | Bin 0 -> 34042 bytes oox/qa/unit/data/graphic-stroke.pptx | Bin 0 -> 29396 bytes oox/qa/unit/data/group-spt202.docx | Bin 0 -> 28238 bytes oox/qa/unit/data/import-characters.pptx | Bin 0 -> 33620 bytes oox/qa/unit/data/import-mce.pptx | Bin 0 -> 33763 bytes oox/qa/unit/data/multiple-group-shapes.docx | Bin 0 -> 29653 bytes oox/qa/unit/data/preset-adjust-value.pptx | Bin 0 -> 33233 bytes oox/qa/unit/data/refer-to-theme.pptx | Bin 0 -> 33853 bytes oox/qa/unit/data/shape-non-autosize-with-text.docx | Bin 0 -> 35448 bytes oox/qa/unit/data/shape-text-adjust-left.pptx | Bin 0 -> 59199 bytes oox/qa/unit/data/shape-text-alignment.pptx | Bin 0 -> 30844 bytes oox/qa/unit/data/smartart-groupshape.pptx | Bin 0 -> 40995 bytes oox/qa/unit/data/table-shadow.pptx | Bin 0 -> 16837 bytes oox/qa/unit/data/tdf100391_TextAreaRect.odp | Bin 0 -> 13624 bytes oox/qa/unit/data/tdf109169_OctagonBevel.odt | Bin 0 -> 11122 bytes oox/qa/unit/data/tdf112450_vml_polyline.docx | Bin 0 -> 18114 bytes .../data/tdf113187_arcTo_withoutReferences.pptx | Bin 0 -> 14733 bytes oox/qa/unit/data/tdf125085_WordArtFontText.pptx | Bin 0 -> 16891 bytes oox/qa/unit/data/tdf125085_WordArtFontTheme.pptx | Bin 0 -> 15548 bytes oox/qa/unit/data/tdf125582_TextOnCircle.pptx | Bin 0 -> 15956 bytes oox/qa/unit/data/tdf125885_WordArt.docx | Bin 0 -> 22071 bytes oox/qa/unit/data/tdf125885_WordArt2.docx | Bin 0 -> 20175 bytes oox/qa/unit/data/tdf125885_WordArt3.docx | Bin 0 -> 56757 bytes oox/qa/unit/data/tdf128568_FontworkBitmapFill.odt | Bin 0 -> 17770 bytes .../unit/data/tdf128568_FontworkFontProperties.odt | Bin 0 -> 30995 bytes oox/qa/unit/data/tdf131082.pptx | Bin 0 -> 25881 bytes .../unit/data/tdf137314_vml_rotation_unit_fd.docx | Bin 0 -> 18070 bytes .../unit/data/tdf139618_ImportWordArtGradient.pptx | Bin 0 -> 22072 bytes .../data/tdf139618_ThemeColorTransparency.pptx | Bin 0 -> 26093 bytes oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx | Bin 0 -> 38286 bytes oox/qa/unit/data/tdf141463_GroupTransform.pptx | Bin 0 -> 16921 bytes .../data/tdf141786_PolylineConnectorInGroup.odt | Bin 0 -> 10127 bytes oox/qa/unit/data/tdf141786_RotatedShapeInGroup.odt | Bin 0 -> 15507 bytes oox/qa/unit/data/tdf142602_CustomShapeArrows.odt | Bin 0 -> 11637 bytes oox/qa/unit/data/tdf142605_CurveSize.odp | Bin 0 -> 11220 bytes oox/qa/unit/data/tdf147978_endsubpath.odp | Bin 0 -> 14505 bytes .../unit/data/tdf147978_enhancedPath_commandA.odp | Bin 0 -> 12755 bytes .../data/tdf147978_enhancedPath_commandHIJK.odp | Bin 0 -> 14922 bytes .../unit/data/tdf147978_enhancedPath_commandT.odp | Bin 0 -> 12869 bytes .../unit/data/tdf147978_enhancedPath_commandXY.odp | Bin 0 -> 13166 bytes .../unit/data/tdf147978_enhancedPath_subpath.pptx | Bin 0 -> 15040 bytes oox/qa/unit/data/tdf148784_StretchCommandQ.odp | Bin 0 -> 15311 bytes oox/qa/unit/data/tdf148784_StretchCommandVW.odp | Bin 0 -> 15218 bytes oox/qa/unit/data/tdf148784_StretchXY.odp | Bin 0 -> 11512 bytes oox/qa/unit/data/tdf149538_upright.pptx | Bin 0 -> 25829 bytes oox/qa/unit/data/tdf149551_TextRot.pptx | Bin 0 -> 15419 bytes oox/qa/unit/data/tdf149551_vert270AndTextRot.pptx | Bin 0 -> 15368 bytes oox/qa/unit/data/tdf149551_vert_and_padding.pptx | Bin 0 -> 25217 bytes oox/qa/unit/data/tdf151008_eaVertAnchor.pptx | Bin 0 -> 19773 bytes .../unit/data/tdf151518_SmartArtTextLocation.docx | Bin 0 -> 66839 bytes .../data/tdf152840_WordArt_non_accent_color.docx | Bin 0 -> 21925 bytes .../data/tdf152840_theme_color_non_accent.docx | Bin 0 -> 22932 bytes .../unit/data/tdf152896_WordArt_color_darken.docx | Bin 0 -> 18545 bytes .../tdf153246_VML_export_Fontwork_Adjustment.odt | Bin 0 -> 20601 bytes .../tdf153258_VML_import_WordArt_detection.docx | Bin 0 -> 51228 bytes oox/qa/unit/data/tdf153260_VML_trim_export.odt | Bin 0 -> 19650 bytes .../unit/data/tdf153296_VML_export_ArchUpCurve.odt | Bin 0 -> 18377 bytes oox/qa/unit/data/tdf153296_VML_export_SlantUp.odt | Bin 0 -> 72920 bytes .../unit/data/tdf155327_WordArtDefaultColor.pptx | Bin 0 -> 19757 bytes oox/qa/unit/data/tdf155412_typeface.pptx | Bin 0 -> 23138 bytes .../tdf155825_MCGR_SourceOffsetRangeDifferent.fodp | 642 ++++++++++ .../data/tdf155827_MCGR_AxialColorLinearTrans.fodp | 644 ++++++++++ oox/qa/unit/data/tdf155852_MCGR_StepCount4.fodp | 637 +++++++++ oox/qa/unit/data/tdf156902_GlowOnGroup.docx | Bin 0 -> 34795 bytes .../unit/data/tdf157289_circularArrow_export.fodp | 816 ++++++++++++ oox/qa/unit/data/tdf51195_Fontwork_DirectColor.odt | Bin 0 -> 19099 bytes oox/qa/unit/data/tdf51195_Fontwork_Distance.odt | Bin 0 -> 14952 bytes oox/qa/unit/data/tdf51195_Fontwork_ThemeColor.fodt | 475 +++++++ .../unit/data/tdf51195_Fontwork_axialGradient.fodt | 462 +++++++ .../data/tdf51195_Fontwork_ellipticalGradient.fodt | 728 +++++++++++ .../data/tdf51195_Fontwork_linearGradient.fodt | 416 ++++++ .../data/tdf51195_Fontwork_radialGradient.fodt | 395 ++++++ .../unit/data/tdf51195_Fontwork_rectGradient.fodt | 493 +++++++ .../data/tdf51195_Fontwork_squareGradient.fodt | 488 +++++++ .../unit/data/tdf54095_SmartArtThemeTextColor.docx | Bin 0 -> 21161 bytes .../data/testTdf132557_footerCustomShapes.pptx | Bin 0 -> 20137 bytes oox/qa/unit/data/theme-tint.pptx | Bin 0 -> 16742 bytes oox/qa/unit/data/theme.pptx | Bin 0 -> 33063 bytes oox/qa/unit/data/transparent-text.pptx | Bin 0 -> 32797 bytes oox/qa/unit/data/vba/complex1.bin | Bin 0 -> 1086 bytes oox/qa/unit/data/vba/reference/complex1.bin | Bin 0 -> 579 bytes oox/qa/unit/data/vba/reference/simple1.bin | Bin 0 -> 18 bytes oox/qa/unit/data/vba/reference/simple2.bin | Bin 0 -> 13 bytes oox/qa/unit/data/vba/reference/simple3.bin | 1 + oox/qa/unit/data/vba/reference/spec321.bin | Bin 0 -> 29 bytes oox/qa/unit/data/vba/reference/spec322.bin | Bin 0 -> 51 bytes oox/qa/unit/data/vba/reference/spec323.bin | Bin 0 -> 7 bytes oox/qa/unit/data/vba/simple1.bin | Bin 0 -> 13 bytes oox/qa/unit/data/vba/simple2.bin | Bin 0 -> 11 bytes oox/qa/unit/data/vba/simple3.bin | 1 + oox/qa/unit/data/vba/spec321.bin | 1 + oox/qa/unit/data/vba/spec322.bin | 1 + oox/qa/unit/data/vba/spec323.bin | 1 + oox/qa/unit/data/watermark.docx | Bin 0 -> 21621 bytes oox/qa/unit/drawingml.cxx | 706 ++++++++++ oox/qa/unit/export.cxx | 1352 ++++++++++++++++++++ oox/qa/unit/mathml.cxx | 48 + oox/qa/unit/mcgr.cxx | 135 ++ oox/qa/unit/shape.cxx | 834 ++++++++++++ oox/qa/unit/vba_compression.cxx | 255 ++++ oox/qa/unit/vba_encryption.cxx | 82 ++ oox/qa/unit/vml.cxx | 247 ++++ oox/qa/unit/wpc_drawing_canvas.cxx | 343 +++++ 130 files changed, 12601 insertions(+) create mode 100644 oox/qa/token/tokenmap-test.cxx create mode 100644 oox/qa/unit/CryptoTest.cxx create mode 100644 oox/qa/unit/data/FaultyPathStart.odp create mode 100644 oox/qa/unit/data/MCGR_FontworkColorGradient.fodp create mode 100644 oox/qa/unit/data/MCGR_FontworkColorGradient.fodt create mode 100644 oox/qa/unit/data/ReferenceShapeFill.fodp create mode 100644 oox/qa/unit/data/ThemeShapesReference.pptx create mode 100644 oox/qa/unit/data/WPC_BentConnector.docx create mode 100644 oox/qa/unit/data/WPC_CanvasBackground.docx create mode 100644 oox/qa/unit/data/WPC_CurvedConnector2.docx create mode 100644 oox/qa/unit/data/WPC_CurvedConnector5.docx create mode 100644 oox/qa/unit/data/WPC_Glow.docx create mode 100644 oox/qa/unit/data/WPC_MulticolorGradient.docx create mode 100644 oox/qa/unit/data/WPC_Shadow.docx create mode 100644 oox/qa/unit/data/WPC_Textwrap_in_ellipse.docx create mode 100644 oox/qa/unit/data/WPC_ThemeColor.docx create mode 100644 oox/qa/unit/data/WPC_tdf104671_Cloud.docx create mode 100644 oox/qa/unit/data/WPC_tdf158339_shape_text_in_group.docx create mode 100644 oox/qa/unit/data/WPC_tdf158348_shape_text_in_table_cell.docx create mode 100644 oox/qa/unit/data/WPC_tdf48610_Textbox_with_table_inside.docx create mode 100644 oox/qa/unit/data/camera-rotation-revolution-nonwps.pptx create mode 100644 oox/qa/unit/data/camera-rotation-revolution.docx create mode 100644 oox/qa/unit/data/chart-data-label-char-color.docx create mode 100644 oox/qa/unit/data/chart-theme-override.pptx create mode 100644 oox/qa/unit/data/customshape-position.docx create mode 100644 oox/qa/unit/data/dml-groupshape-polygon.docx create mode 100644 oox/qa/unit/data/endParaRPr-newline-textsize.pptx create mode 100644 oox/qa/unit/data/gradient-multistep-transparency.pptx create mode 100644 oox/qa/unit/data/graphic-stroke.pptx create mode 100644 oox/qa/unit/data/group-spt202.docx create mode 100644 oox/qa/unit/data/import-characters.pptx create mode 100644 oox/qa/unit/data/import-mce.pptx create mode 100644 oox/qa/unit/data/multiple-group-shapes.docx create mode 100644 oox/qa/unit/data/preset-adjust-value.pptx create mode 100644 oox/qa/unit/data/refer-to-theme.pptx create mode 100644 oox/qa/unit/data/shape-non-autosize-with-text.docx create mode 100644 oox/qa/unit/data/shape-text-adjust-left.pptx create mode 100644 oox/qa/unit/data/shape-text-alignment.pptx create mode 100644 oox/qa/unit/data/smartart-groupshape.pptx create mode 100644 oox/qa/unit/data/table-shadow.pptx create mode 100644 oox/qa/unit/data/tdf100391_TextAreaRect.odp create mode 100644 oox/qa/unit/data/tdf109169_OctagonBevel.odt create mode 100644 oox/qa/unit/data/tdf112450_vml_polyline.docx create mode 100644 oox/qa/unit/data/tdf113187_arcTo_withoutReferences.pptx create mode 100644 oox/qa/unit/data/tdf125085_WordArtFontText.pptx create mode 100644 oox/qa/unit/data/tdf125085_WordArtFontTheme.pptx create mode 100644 oox/qa/unit/data/tdf125582_TextOnCircle.pptx create mode 100644 oox/qa/unit/data/tdf125885_WordArt.docx create mode 100644 oox/qa/unit/data/tdf125885_WordArt2.docx create mode 100644 oox/qa/unit/data/tdf125885_WordArt3.docx create mode 100644 oox/qa/unit/data/tdf128568_FontworkBitmapFill.odt create mode 100644 oox/qa/unit/data/tdf128568_FontworkFontProperties.odt create mode 100644 oox/qa/unit/data/tdf131082.pptx create mode 100644 oox/qa/unit/data/tdf137314_vml_rotation_unit_fd.docx create mode 100644 oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx create mode 100644 oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx create mode 100644 oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx create mode 100644 oox/qa/unit/data/tdf141463_GroupTransform.pptx create mode 100644 oox/qa/unit/data/tdf141786_PolylineConnectorInGroup.odt create mode 100644 oox/qa/unit/data/tdf141786_RotatedShapeInGroup.odt create mode 100644 oox/qa/unit/data/tdf142602_CustomShapeArrows.odt create mode 100644 oox/qa/unit/data/tdf142605_CurveSize.odp create mode 100644 oox/qa/unit/data/tdf147978_endsubpath.odp create mode 100644 oox/qa/unit/data/tdf147978_enhancedPath_commandA.odp create mode 100644 oox/qa/unit/data/tdf147978_enhancedPath_commandHIJK.odp create mode 100644 oox/qa/unit/data/tdf147978_enhancedPath_commandT.odp create mode 100644 oox/qa/unit/data/tdf147978_enhancedPath_commandXY.odp create mode 100644 oox/qa/unit/data/tdf147978_enhancedPath_subpath.pptx create mode 100644 oox/qa/unit/data/tdf148784_StretchCommandQ.odp create mode 100644 oox/qa/unit/data/tdf148784_StretchCommandVW.odp create mode 100644 oox/qa/unit/data/tdf148784_StretchXY.odp create mode 100644 oox/qa/unit/data/tdf149538_upright.pptx create mode 100644 oox/qa/unit/data/tdf149551_TextRot.pptx create mode 100644 oox/qa/unit/data/tdf149551_vert270AndTextRot.pptx create mode 100644 oox/qa/unit/data/tdf149551_vert_and_padding.pptx create mode 100644 oox/qa/unit/data/tdf151008_eaVertAnchor.pptx create mode 100644 oox/qa/unit/data/tdf151518_SmartArtTextLocation.docx create mode 100644 oox/qa/unit/data/tdf152840_WordArt_non_accent_color.docx create mode 100644 oox/qa/unit/data/tdf152840_theme_color_non_accent.docx create mode 100644 oox/qa/unit/data/tdf152896_WordArt_color_darken.docx create mode 100644 oox/qa/unit/data/tdf153246_VML_export_Fontwork_Adjustment.odt create mode 100644 oox/qa/unit/data/tdf153258_VML_import_WordArt_detection.docx create mode 100644 oox/qa/unit/data/tdf153260_VML_trim_export.odt create mode 100644 oox/qa/unit/data/tdf153296_VML_export_ArchUpCurve.odt create mode 100644 oox/qa/unit/data/tdf153296_VML_export_SlantUp.odt create mode 100644 oox/qa/unit/data/tdf155327_WordArtDefaultColor.pptx create mode 100644 oox/qa/unit/data/tdf155412_typeface.pptx create mode 100644 oox/qa/unit/data/tdf155825_MCGR_SourceOffsetRangeDifferent.fodp create mode 100644 oox/qa/unit/data/tdf155827_MCGR_AxialColorLinearTrans.fodp create mode 100644 oox/qa/unit/data/tdf155852_MCGR_StepCount4.fodp create mode 100644 oox/qa/unit/data/tdf156902_GlowOnGroup.docx create mode 100644 oox/qa/unit/data/tdf157289_circularArrow_export.fodp create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_DirectColor.odt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_Distance.odt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_ThemeColor.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_axialGradient.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_ellipticalGradient.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_linearGradient.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_radialGradient.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_rectGradient.fodt create mode 100644 oox/qa/unit/data/tdf51195_Fontwork_squareGradient.fodt create mode 100644 oox/qa/unit/data/tdf54095_SmartArtThemeTextColor.docx create mode 100644 oox/qa/unit/data/testTdf132557_footerCustomShapes.pptx create mode 100644 oox/qa/unit/data/theme-tint.pptx create mode 100644 oox/qa/unit/data/theme.pptx create mode 100644 oox/qa/unit/data/transparent-text.pptx create mode 100644 oox/qa/unit/data/vba/complex1.bin create mode 100644 oox/qa/unit/data/vba/reference/complex1.bin create mode 100644 oox/qa/unit/data/vba/reference/simple1.bin create mode 100644 oox/qa/unit/data/vba/reference/simple2.bin create mode 100644 oox/qa/unit/data/vba/reference/simple3.bin create mode 100644 oox/qa/unit/data/vba/reference/spec321.bin create mode 100644 oox/qa/unit/data/vba/reference/spec322.bin create mode 100644 oox/qa/unit/data/vba/reference/spec323.bin create mode 100644 oox/qa/unit/data/vba/simple1.bin create mode 100644 oox/qa/unit/data/vba/simple2.bin create mode 100644 oox/qa/unit/data/vba/simple3.bin create mode 100644 oox/qa/unit/data/vba/spec321.bin create mode 100644 oox/qa/unit/data/vba/spec322.bin create mode 100644 oox/qa/unit/data/vba/spec323.bin create mode 100644 oox/qa/unit/data/watermark.docx create mode 100644 oox/qa/unit/drawingml.cxx create mode 100644 oox/qa/unit/export.cxx create mode 100644 oox/qa/unit/mathml.cxx create mode 100644 oox/qa/unit/mcgr.cxx create mode 100644 oox/qa/unit/shape.cxx create mode 100644 oox/qa/unit/vba_compression.cxx create mode 100644 oox/qa/unit/vba_encryption.cxx create mode 100644 oox/qa/unit/vml.cxx create mode 100644 oox/qa/unit/wpc_drawing_canvas.cxx (limited to 'oox/qa') diff --git a/oox/qa/token/tokenmap-test.cxx b/oox/qa/token/tokenmap-test.cxx new file mode 100644 index 0000000000..e30b6aef80 --- /dev/null +++ b/oox/qa/token/tokenmap-test.cxx @@ -0,0 +1,66 @@ +/* -*- 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 +#include +#include +#include + +#include +#include + +using namespace com::sun::star::uno; + +namespace oox { + +class TokenmapTest: public CppUnit::TestFixture +{ +public: + void test_roundTrip(); + void test_roundTripUnicode(); + + CPPUNIT_TEST_SUITE(TokenmapTest); + + CPPUNIT_TEST(test_roundTrip); + CPPUNIT_TEST(test_roundTripUnicode); + CPPUNIT_TEST_SUITE_END(); + +private: + TokenMap tokenMap; +}; + +void TokenmapTest::test_roundTrip() +{ + for ( sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken ) + { + // check that the getIdentifier <-> getToken roundtrip works + Sequence< sal_Int8 > rUtf8Name = tokenMap.getUtf8TokenName(nToken); + sal_Int32 ret = tokenMap.getTokenFromUTF8( + reinterpret_cast< const char * >(rUtf8Name.getConstArray()), + rUtf8Name.getLength() ); + CPPUNIT_ASSERT_EQUAL(ret, nToken); + } +} + +void TokenmapTest::test_roundTripUnicode() +{ + for (sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken) + { + // check that the getIdentifier <-> getToken roundtrip works for OUString + OUString sName = tokenMap.getUnicodeTokenName(nToken); + sal_Int32 ret = oox::TokenMap::getTokenFromUnicode(sName); + CPPUNIT_ASSERT_EQUAL(ret, nToken); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TokenmapTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/oox/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx new file mode 100644 index 0000000000..be04c92804 --- /dev/null +++ b/oox/qa/unit/CryptoTest.cxx @@ -0,0 +1,501 @@ +/* -*- 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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if USE_TLS_NSS +#include +#endif + +using namespace css; + +class CryptoTest : public CppUnit::TestFixture +{ +public: + virtual ~CryptoTest() override; + void testCryptoHash(); + void testRoundUp(); + void testStandard2007(); + void testAgileEncryptionVerifier(); + void testAgileEncryptionInfoWritingAndParsing(); + void testAgileDataIntegrityHmacKey(); + void testAgileEncryptingAndDecrypting(); + + CPPUNIT_TEST_SUITE(CryptoTest); + CPPUNIT_TEST(testCryptoHash); + CPPUNIT_TEST(testRoundUp); + CPPUNIT_TEST(testStandard2007); + CPPUNIT_TEST(testAgileEncryptionVerifier); + CPPUNIT_TEST(testAgileEncryptionInfoWritingAndParsing); + CPPUNIT_TEST(testAgileDataIntegrityHmacKey); + CPPUNIT_TEST(testAgileEncryptingAndDecrypting); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace +{ +std::string toString(std::vector const& aInput) +{ + std::stringstream aStream; + for (auto const& aValue : aInput) + { + aStream << std::setw(2) << std::setfill('0') << std::hex << static_cast(aValue); + } + + return aStream.str(); +} +} + +CryptoTest::~CryptoTest() +{ +#if USE_TLS_NSS + NSS_Shutdown(); +#endif +} + +void CryptoTest::testCryptoHash() +{ + // Check examples from Wikipedia (https://en.wikipedia.org/wiki/HMAC) + OString aContentString("The quick brown fox jumps over the lazy dog"_ostr); + std::vector aContent(aContentString.getStr(), + aContentString.getStr() + aContentString.getLength()); + std::vector aKey = { 'k', 'e', 'y' }; + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA1); + aCryptoHash.update(aContent); + std::vector aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"), + toString(aHash)); + } + + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA256); + aCryptoHash.update(aContent); + std::vector aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"), + toString(aHash)); + } + + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA384); + aCryptoHash.update(aContent); + std::vector aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL(std::string("d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1" + "ae50700582a96cf35e1e554995fe4e03381c237"), + toString(aHash)); + } + + { + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA512); + aCryptoHash.update(aContent); + std::vector aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549" + "f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a"), + toString(aHash)); + } +} + +void CryptoTest::testRoundUp() +{ + CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(16, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(32, 16)); + CPPUNIT_ASSERT_EQUAL(64, oox::crypto::roundUp(64, 16)); + + CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(01, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(17, 16)); + CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(31, 16)); +} + +void CryptoTest::testStandard2007() +{ + oox::crypto::Standard2007Engine aEngine; + { + aEngine.setupEncryption("Password"); + + SvMemoryStream aEncryptionInfo; + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), false); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(224), aEncryptionInfo.GetSize()); + } + + SvMemoryStream aUnencryptedInput; + SvMemoryStream aEncryptedStream; + + OString aTestString = "1234567890ABCDEFG"_ostr; + + aUnencryptedInput.WriteBytes(aTestString.getStr(), aTestString.getLength() + 1); + aUnencryptedInput.Seek(STREAM_SEEK_TO_BEGIN); + + { + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aUnencryptedInput)); + uno::Reference xOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptedStream)); + + aEngine.encrypt(xInputStream, xOutputStream, aUnencryptedInput.GetSize()); + + xOutputStream->flush(); + + const sal_uInt8* pData = static_cast(aEncryptedStream.GetData()); + sal_uInt64 nSize = aEncryptedStream.GetSize(); + + std::vector aData(nSize); + std::copy(pData, pData + nSize, aData.data()); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(40), nSize); + } + + aEncryptedStream.Seek(STREAM_SEEK_TO_BEGIN); + SvMemoryStream aUnencryptedOutput; + + { + oox::BinaryXInputStream aBinaryInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptedStream), true); + oox::BinaryXOutputStream aBinaryOutputStream( + new utl::OSeekableOutputStreamWrapper(aUnencryptedOutput), true); + + aEngine.decrypt(aBinaryInputStream, aBinaryOutputStream); + aBinaryOutputStream.close(); + aBinaryInputStream.close(); + + const char* pData = static_cast(aUnencryptedOutput.GetData()); + sal_uInt64 nSize = aUnencryptedOutput.GetSize(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(18), nSize); + + OString aString(pData); + + CPPUNIT_ASSERT_EQUAL(aTestString, aString); + } +} + +void CryptoTest::testAgileEncryptionVerifier() +{ + oox::crypto::AgileEngine aEngine; + + OUString aPassword("Password"); + + aEngine.setupEncryptionParameters({ 100000, 16, 128, 20, 16, OUString("AES"), + OUString("ChainingModeCBC"), OUString("SHA1") }); + + CPPUNIT_ASSERT_EQUAL(true, aEngine.generateAndEncryptVerifierHash(aPassword)); + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + + aEngine.setupEncryptionParameters({ 100000, 16, 128, 48, 16, OUString("AES"), + OUString("ChainingModeCBC"), OUString("SHA384") }); + + CPPUNIT_ASSERT_EQUAL(true, aEngine.generateAndEncryptVerifierHash(aPassword)); + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + + aEngine.setupEncryptionParameters({ 100000, 16, 256, 64, 16, OUString("AES"), + OUString("ChainingModeCBC"), OUString("SHA512") }); + + CPPUNIT_ASSERT_EQUAL(true, aEngine.generateAndEncryptVerifierHash(aPassword)); + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); +} + +void CryptoTest::testAgileEncryptionInfoWritingAndParsing() +{ + OUString aPassword("Password"); + std::vector aKeyDataSalt; + + { // Preset AES128 - SHA1 + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + + aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_128_SHA1); + aEngine.setupEncryption(aPassword); + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(996), aEncryptionInfo.GetSize()); + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + + oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(128), rInfo.keyBits); + CPPUNIT_ASSERT_EQUAL(sal_Int32(20), rInfo.hashSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); + CPPUNIT_ASSERT_EQUAL(OUString("AES"), rInfo.cipherAlgorithm); + CPPUNIT_ASSERT_EQUAL(OUString("ChainingModeCBC"), rInfo.cipherChaining); + CPPUNIT_ASSERT_EQUAL(OUString("SHA1"), rInfo.hashAlgorithm); + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + } + } + + { // Preset AES128 - SHA384 + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + + aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_128_SHA384); + aEngine.setupEncryption(aPassword); + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(1040), aEncryptionInfo.GetSize()); + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + + oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(128), rInfo.keyBits); + CPPUNIT_ASSERT_EQUAL(sal_Int32(48), rInfo.hashSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); + CPPUNIT_ASSERT_EQUAL(OUString("AES"), rInfo.cipherAlgorithm); + CPPUNIT_ASSERT_EQUAL(OUString("ChainingModeCBC"), rInfo.cipherChaining); + CPPUNIT_ASSERT_EQUAL(OUString("SHA384"), rInfo.hashAlgorithm); + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + } + } + + { // Preset AES256 - SHA512 + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + + aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_256_SHA512); + aEngine.setupEncryption(aPassword); + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(1112), aEncryptionInfo.GetSize()); + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + + oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(256), rInfo.keyBits); + CPPUNIT_ASSERT_EQUAL(sal_Int32(64), rInfo.hashSize); + CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); + CPPUNIT_ASSERT_EQUAL(OUString("AES"), rInfo.cipherAlgorithm); + CPPUNIT_ASSERT_EQUAL(OUString("ChainingModeCBC"), rInfo.cipherChaining); + CPPUNIT_ASSERT_EQUAL(OUString("SHA512"), rInfo.hashAlgorithm); + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash("Wrong")); + CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); + } + } +} + +void CryptoTest::testAgileDataIntegrityHmacKey() +{ + OUString aPassword("Password"); + + std::vector aKeyDataSalt; + + std::vector aHmacKey; + std::vector aHmacEncryptedKey; + + SvMemoryStream aEncryptionInfo; + { + oox::crypto::AgileEngine aEngine; + aEngine.setupEncryption(aPassword); + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + + aHmacKey = aEngine.getInfo().hmacKey; + aKeyDataSalt = aEngine.getInfo().keyDataSalt; + aHmacEncryptedKey = aEngine.getInfo().hmacEncryptedKey; + } + + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xInputStream->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); + CPPUNIT_ASSERT(aEngine.generateEncryptionKey(aPassword)); + + CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(aEngine.getInfo().keyDataSalt)); + + CPPUNIT_ASSERT_EQUAL(toString(aHmacEncryptedKey), + toString(aEngine.getInfo().hmacEncryptedKey)); + + CPPUNIT_ASSERT_EQUAL(size_t(64), aHmacKey.size()); + CPPUNIT_ASSERT_EQUAL(toString(aHmacKey), toString(aEngine.getInfo().hmacKey)); + } +} + +void CryptoTest::testAgileEncryptingAndDecrypting() +{ + OUString aPassword("Password"); + + SvMemoryStream aEncryptionInfo; + SvMemoryStream aEncryptedStream; + + OString aTestString = "1234567890ABCDEFGH"_ostr; + + { + oox::crypto::AgileEngine aEngine; + + // Setup input + SvMemoryStream aUnencryptedInput; + uno::Reference xInputStream( + new utl::OSeekableInputStreamWrapper(aUnencryptedInput)); + + aUnencryptedInput.WriteBytes(aTestString.getStr(), aTestString.getLength() + 1); + aUnencryptedInput.Seek(STREAM_SEEK_TO_BEGIN); + + // Setup output + uno::Reference xOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptedStream)); + + // Write content + aEngine.setupEncryption(aPassword); + aEngine.encrypt(xInputStream, xOutputStream, aUnencryptedInput.GetSize()); + xOutputStream->flush(); + + // Check content + sal_uInt64 nSize = aEncryptedStream.GetSize(); + + CPPUNIT_ASSERT_EQUAL(sal_uInt64(40), nSize); + + // Setup and write encryption info + oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( + new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); + aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); + aBinaryEncryptionInfoOutputStream.close(); + } + + aEncryptedStream.Seek(STREAM_SEEK_TO_BEGIN); + aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); + + { + oox::crypto::AgileEngine aEngine; + + // Read encryption info + uno::Reference xEncryptionInfo( + new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); + + xEncryptionInfo->skipBytes(4); // Encryption type -> Agile + + CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xEncryptionInfo)); + + // Setup password + CPPUNIT_ASSERT(aEngine.generateEncryptionKey(aPassword)); + + // Setup encrypted input stream + oox::BinaryXInputStream aBinaryInputStream( + new utl::OSeekableInputStreamWrapper(aEncryptedStream), true); + + // Setup output stream + SvMemoryStream aUnencryptedOutput; + oox::BinaryXOutputStream aBinaryOutputStream( + new utl::OSeekableOutputStreamWrapper(aUnencryptedOutput), true); + + // Decrypt + aEngine.decrypt(aBinaryInputStream, aBinaryOutputStream); + aBinaryOutputStream.close(); + aBinaryInputStream.close(); + + // Check decrypted output + CPPUNIT_ASSERT_EQUAL(sal_uInt64(19), aUnencryptedOutput.GetSize()); + + OString aString(static_cast(aUnencryptedOutput.GetData())); + CPPUNIT_ASSERT_EQUAL(aTestString, aString); + + // Check data integrity + CPPUNIT_ASSERT_EQUAL(true, aEngine.checkDataIntegrity()); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/data/FaultyPathStart.odp b/oox/qa/unit/data/FaultyPathStart.odp new file mode 100644 index 0000000000..219795ffa5 Binary files /dev/null and b/oox/qa/unit/data/FaultyPathStart.odp differ diff --git a/oox/qa/unit/data/MCGR_FontworkColorGradient.fodp b/oox/qa/unit/data/MCGR_FontworkColorGradient.fodp new file mode 100644 index 0000000000..e82401442c --- /dev/null +++ b/oox/qa/unit/data/MCGR_FontworkColorGradient.fodp @@ -0,0 +1,662 @@ + + + + 2023-06-08T12:15:12.97800000024x16impressPT2M30S2B2020/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/ca9341cf60f3f9350662d30b61f6eadefca24667Regina Henschel2023-06-08T12:17:40.279000000Regina Henschel + + + -245 + -3142 + 30369 + 16510 + + + view1 + false + false + true + true + true + true + false + false + true + 1500 + false + Hw== + Hw== + + false + true + false + 0 + 0 + false + true + true + 4 + 0 + -231 + -11545 + 47915 + 16742 + 2000 + 2000 + 500 + 500 + 2000 + 4 + 2000 + 4 + false + 1500 + true + false + true + false + false + + + + + true + 1250 + EPSON6FC99C (WP-4025 Series) + + + de + DE + + + + + + iAv+/0VQU09ONkZDOTlDIChXUC00MDI1IFNlcmllcykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARVBTT04gV1AtNDAyNSBTZXJpZXMAAAAAAAAAAAAAAAAWAAEAWgoAAAAAAAAEAAhSAAAEdAAAM1ROVwAAAAAKAEUAUABTAE8ATgA2AEYAQwA5ADkAQwAgACgAVwBQAC0ANAAwADIANQAgAFMAZQByAGkAZQBzACkAAAAAAAAAAAABBAAB3AB0CQ+bgAcBAAkAmgs0CGQAAQAHAFgCAgABAFgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0CQAAAQEBAQABAAABAAAAAAAAAAAAAAA4AAAAfAgAALQIAABAAAAA9AgAAIAAAAAAAAAAAAAAAAMACQRFAFAAUwBPAE4AIABXAFAALQA0ADAAMgA1ACAAUwBlAHIAaQBlAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABYAgAAAAAAAAAAAAABAAAAAgAAAAAAAQBYAlgCBwAAAAAACQA0CJoLHgAeAB4AHgA0CJoLOwORBAEAAAAOABYAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAAAAAAAAACAAAAAAIAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABkAGQANAiaCx4AHgAeAB4ACQAAAAAAAAAAAAAA//8AAAAAAAAAAB4AHgABAAAAAwDgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAAgAAAAAAAAAAAAEAMgAyANT+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYACoAAAAgAAEAAAAgAAAAQAAAAAYAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wAAAAAAAAAAAABCAAAAAQAAALAAAAAAAAAAAAAAAAAAAAAeAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBARIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmYMAFBSSU5URVJfTkFNRRwARVBTT042RkM5OUMgKFdQLTQwMjUgU2VyaWVzKQsARFJJVkVSX05BTUUUAEVQU09OIFdQLTQwMjUgU2VyaWVz + false + false + false + $(inst)/share/palette%3B$(user)/config/standard.sob + false + 0 + 0 + true + false + false + true + false + true + 0 + $(inst)/share/palette/html.soc + $(inst)/share/palette%3B$(user)/config/standard.sod + $(inst)/share/palette%3B$(user)/config/standard.soe + $(inst)/share/palette%3B$(user)/config/standard.soh + $(inst)/share/palette%3B$(user)/config/standard.sog + true + 4 + false + false + true + low-resolution + false + false + false + true + false + true + true + true + false + false + false + 6 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Simple + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/MCGR_FontworkColorGradient.fodt b/oox/qa/unit/data/MCGR_FontworkColorGradient.fodt new file mode 100644 index 0000000000..17052a44b9 --- /dev/null +++ b/oox/qa/unit/data/MCGR_FontworkColorGradient.fodt @@ -0,0 +1,331 @@ + + + + 2023-06-08T12:08:34.452000000A6querPT2M6S2B2020/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/ca9341cf60f3f9350662d30b61f6eadefca24667Regina Henschel2023-06-08T12:10:27.725000000Regina Henschel + + + 0 + 0 + 30249 + 9082 + true + false + + + view2 + 8223 + 1000 + 0 + 0 + 30247 + 9081 + 0 + 1 + false + 100 + false + false + false + true + false + false + + + + + true + + false + false + false + false + true + 1 + true + false + false + false + + false + + false + false + false + + 0 + false + true + true + false + false + false + + 0 + + true + high-resolution + false + false + false + false + true + false + false + true + false + false + true + true + false + false + false + false + false + true + false + false + true + false + false + false + false + false + false + 1621794 + 1306543 + false + false + false + true + false + false + true + true + false + true + true + false + false + false + false + false + true + false + false + false + false + false + false + false + true + 0 + true + false + false + true + false + 0 + true + false + true + true + true + true + false + false + false + false + false + true + + false + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Simple + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/ReferenceShapeFill.fodp b/oox/qa/unit/data/ReferenceShapeFill.fodp new file mode 100644 index 0000000000..432891b0d8 --- /dev/null +++ b/oox/qa/unit/data/ReferenceShapeFill.fodp @@ -0,0 +1,838 @@ + + + + PowerPoint Presentationquikeequikee12023-01-01T23:48:392023-01-01T23:48:54P0DLibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341fa16.0000Widescreen1 + + + -2187 + -513 + 34909 + 23435 + + + view1 + false + false + true + true + true + true + false + false + true + 1500 + false + Hw== + Hw== + + false + true + false + 0 + 0 + false + true + true + 4 + 0 + -2703 + -512 + 34880 + 24439 + 2000 + 2000 + 500 + 500 + 2000 + 4 + 2000 + 4 + false + 1500 + true + false + true + false + false + + + + + 6 + false + false + false + false + false + 0 + false + false + true + true + true + true + false + true + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.soe + true + true + xgH+/0N1cHMtUERGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ1VQUzpDdXBzLVBERgAAAAAAAAAAAAAAAAAAAAAAAAAWAAMArwAAAAAAAAAEAAhSAAAEdAAASm9iRGF0YSAxCnByaW50ZXI9Q3Vwcy1QREYKb3JpZW50YXRpb249UG9ydHJhaXQKY29waWVzPTEKY29sbGF0ZT1mYWxzZQptYXJnaW5hZGp1c3RtZW50PTAsMCwnMCwwCmNvbG9yZGVwdGg9MjQKcHNsZXZlbD0wCnBkZmRldmljZT0xCmNvbG9yZGV2aWNlPTAKUFBEQ29udGV4dERhdGEKUGFnZVNpemU6QTQAABIAQ09NUEFUX0RVUExFWF9NT0RFEwBEdXBsZXhNb2RlOjpVbmtub3duDABQUklOVEVSX05BTUUIAEN1cHMtUERGCwBEUklWRVJfTkFNRQ0AQ1VQUzpDdXBzLVBERg== + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.sog + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.sob + 2540 + Cups-PDF + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.soc + 4 + true + 0 + false + 0 + false + false + low-resolution + true + false + false + true + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.sod + false + false + true + $(brandbaseurl)/share/palette%3B$(userpath)/config/standard.soh + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + Shape Fill + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oox/qa/unit/data/ThemeShapesReference.pptx b/oox/qa/unit/data/ThemeShapesReference.pptx new file mode 100644 index 0000000000..d871cc56a0 Binary files /dev/null and b/oox/qa/unit/data/ThemeShapesReference.pptx differ diff --git a/oox/qa/unit/data/WPC_BentConnector.docx b/oox/qa/unit/data/WPC_BentConnector.docx new file mode 100644 index 0000000000..27cc978077 Binary files /dev/null and b/oox/qa/unit/data/WPC_BentConnector.docx differ diff --git a/oox/qa/unit/data/WPC_CanvasBackground.docx b/oox/qa/unit/data/WPC_CanvasBackground.docx new file mode 100644 index 0000000000..bc5b3dda86 Binary files /dev/null and b/oox/qa/unit/data/WPC_CanvasBackground.docx differ diff --git a/oox/qa/unit/data/WPC_CurvedConnector2.docx b/oox/qa/unit/data/WPC_CurvedConnector2.docx new file mode 100644 index 0000000000..3f914fdf5c Binary files /dev/null and b/oox/qa/unit/data/WPC_CurvedConnector2.docx differ diff --git a/oox/qa/unit/data/WPC_CurvedConnector5.docx b/oox/qa/unit/data/WPC_CurvedConnector5.docx new file mode 100644 index 0000000000..e92f9ecc21 Binary files /dev/null and b/oox/qa/unit/data/WPC_CurvedConnector5.docx differ diff --git a/oox/qa/unit/data/WPC_Glow.docx b/oox/qa/unit/data/WPC_Glow.docx new file mode 100644 index 0000000000..29f9a7466a Binary files /dev/null and b/oox/qa/unit/data/WPC_Glow.docx differ diff --git a/oox/qa/unit/data/WPC_MulticolorGradient.docx b/oox/qa/unit/data/WPC_MulticolorGradient.docx new file mode 100644 index 0000000000..4d874fa480 Binary files /dev/null and b/oox/qa/unit/data/WPC_MulticolorGradient.docx differ diff --git a/oox/qa/unit/data/WPC_Shadow.docx b/oox/qa/unit/data/WPC_Shadow.docx new file mode 100644 index 0000000000..44e282fedd Binary files /dev/null and b/oox/qa/unit/data/WPC_Shadow.docx differ diff --git a/oox/qa/unit/data/WPC_Textwrap_in_ellipse.docx b/oox/qa/unit/data/WPC_Textwrap_in_ellipse.docx new file mode 100644 index 0000000000..1729db3972 Binary files /dev/null and b/oox/qa/unit/data/WPC_Textwrap_in_ellipse.docx differ diff --git a/oox/qa/unit/data/WPC_ThemeColor.docx b/oox/qa/unit/data/WPC_ThemeColor.docx new file mode 100644 index 0000000000..20cc52f6fc Binary files /dev/null and b/oox/qa/unit/data/WPC_ThemeColor.docx differ diff --git a/oox/qa/unit/data/WPC_tdf104671_Cloud.docx b/oox/qa/unit/data/WPC_tdf104671_Cloud.docx new file mode 100644 index 0000000000..5cd1ca53b6 Binary files /dev/null and b/oox/qa/unit/data/WPC_tdf104671_Cloud.docx differ diff --git a/oox/qa/unit/data/WPC_tdf158339_shape_text_in_group.docx b/oox/qa/unit/data/WPC_tdf158339_shape_text_in_group.docx new file mode 100644 index 0000000000..b34071cd99 Binary files /dev/null and b/oox/qa/unit/data/WPC_tdf158339_shape_text_in_group.docx differ diff --git a/oox/qa/unit/data/WPC_tdf158348_shape_text_in_table_cell.docx b/oox/qa/unit/data/WPC_tdf158348_shape_text_in_table_cell.docx new file mode 100644 index 0000000000..e8f2cf73d3 Binary files /dev/null and b/oox/qa/unit/data/WPC_tdf158348_shape_text_in_table_cell.docx differ diff --git a/oox/qa/unit/data/WPC_tdf48610_Textbox_with_table_inside.docx b/oox/qa/unit/data/WPC_tdf48610_Textbox_with_table_inside.docx new file mode 100644 index 0000000000..353ba6aafc Binary files /dev/null and b/oox/qa/unit/data/WPC_tdf48610_Textbox_with_table_inside.docx differ diff --git a/oox/qa/unit/data/camera-rotation-revolution-nonwps.pptx b/oox/qa/unit/data/camera-rotation-revolution-nonwps.pptx new file mode 100644 index 0000000000..db26dc032c Binary files /dev/null and b/oox/qa/unit/data/camera-rotation-revolution-nonwps.pptx differ diff --git a/oox/qa/unit/data/camera-rotation-revolution.docx b/oox/qa/unit/data/camera-rotation-revolution.docx new file mode 100644 index 0000000000..74054aa82b Binary files /dev/null and b/oox/qa/unit/data/camera-rotation-revolution.docx differ diff --git a/oox/qa/unit/data/chart-data-label-char-color.docx b/oox/qa/unit/data/chart-data-label-char-color.docx new file mode 100644 index 0000000000..0e389f9237 Binary files /dev/null and b/oox/qa/unit/data/chart-data-label-char-color.docx differ diff --git a/oox/qa/unit/data/chart-theme-override.pptx b/oox/qa/unit/data/chart-theme-override.pptx new file mode 100644 index 0000000000..85243b678b Binary files /dev/null and b/oox/qa/unit/data/chart-theme-override.pptx differ diff --git a/oox/qa/unit/data/customshape-position.docx b/oox/qa/unit/data/customshape-position.docx new file mode 100644 index 0000000000..227928f201 Binary files /dev/null and b/oox/qa/unit/data/customshape-position.docx differ diff --git a/oox/qa/unit/data/dml-groupshape-polygon.docx b/oox/qa/unit/data/dml-groupshape-polygon.docx new file mode 100644 index 0000000000..6d20b0342f Binary files /dev/null and b/oox/qa/unit/data/dml-groupshape-polygon.docx differ diff --git a/oox/qa/unit/data/endParaRPr-newline-textsize.pptx b/oox/qa/unit/data/endParaRPr-newline-textsize.pptx new file mode 100644 index 0000000000..109f818ec8 Binary files /dev/null and b/oox/qa/unit/data/endParaRPr-newline-textsize.pptx differ diff --git a/oox/qa/unit/data/gradient-multistep-transparency.pptx b/oox/qa/unit/data/gradient-multistep-transparency.pptx new file mode 100644 index 0000000000..83946c71b4 Binary files /dev/null and b/oox/qa/unit/data/gradient-multistep-transparency.pptx differ diff --git a/oox/qa/unit/data/graphic-stroke.pptx b/oox/qa/unit/data/graphic-stroke.pptx new file mode 100644 index 0000000000..f4465476fc Binary files /dev/null and b/oox/qa/unit/data/graphic-stroke.pptx differ diff --git a/oox/qa/unit/data/group-spt202.docx b/oox/qa/unit/data/group-spt202.docx new file mode 100644 index 0000000000..14bf00b50e Binary files /dev/null and b/oox/qa/unit/data/group-spt202.docx differ diff --git a/oox/qa/unit/data/import-characters.pptx b/oox/qa/unit/data/import-characters.pptx new file mode 100644 index 0000000000..2933802364 Binary files /dev/null and b/oox/qa/unit/data/import-characters.pptx differ diff --git a/oox/qa/unit/data/import-mce.pptx b/oox/qa/unit/data/import-mce.pptx new file mode 100644 index 0000000000..65cf1cbabf Binary files /dev/null and b/oox/qa/unit/data/import-mce.pptx differ diff --git a/oox/qa/unit/data/multiple-group-shapes.docx b/oox/qa/unit/data/multiple-group-shapes.docx new file mode 100644 index 0000000000..c751bcdf65 Binary files /dev/null and b/oox/qa/unit/data/multiple-group-shapes.docx differ diff --git a/oox/qa/unit/data/preset-adjust-value.pptx b/oox/qa/unit/data/preset-adjust-value.pptx new file mode 100644 index 0000000000..d1d570a19d Binary files /dev/null and b/oox/qa/unit/data/preset-adjust-value.pptx differ diff --git a/oox/qa/unit/data/refer-to-theme.pptx b/oox/qa/unit/data/refer-to-theme.pptx new file mode 100644 index 0000000000..9f05bf7b07 Binary files /dev/null and b/oox/qa/unit/data/refer-to-theme.pptx differ diff --git a/oox/qa/unit/data/shape-non-autosize-with-text.docx b/oox/qa/unit/data/shape-non-autosize-with-text.docx new file mode 100644 index 0000000000..b9ae501f4b Binary files /dev/null and b/oox/qa/unit/data/shape-non-autosize-with-text.docx differ diff --git a/oox/qa/unit/data/shape-text-adjust-left.pptx b/oox/qa/unit/data/shape-text-adjust-left.pptx new file mode 100644 index 0000000000..d197425b97 Binary files /dev/null and b/oox/qa/unit/data/shape-text-adjust-left.pptx differ diff --git a/oox/qa/unit/data/shape-text-alignment.pptx b/oox/qa/unit/data/shape-text-alignment.pptx new file mode 100644 index 0000000000..ff4ff06f2f Binary files /dev/null and b/oox/qa/unit/data/shape-text-alignment.pptx differ diff --git a/oox/qa/unit/data/smartart-groupshape.pptx b/oox/qa/unit/data/smartart-groupshape.pptx new file mode 100644 index 0000000000..81dcee1e52 Binary files /dev/null and b/oox/qa/unit/data/smartart-groupshape.pptx differ diff --git a/oox/qa/unit/data/table-shadow.pptx b/oox/qa/unit/data/table-shadow.pptx new file mode 100644 index 0000000000..3247404cbc Binary files /dev/null and b/oox/qa/unit/data/table-shadow.pptx differ diff --git a/oox/qa/unit/data/tdf100391_TextAreaRect.odp b/oox/qa/unit/data/tdf100391_TextAreaRect.odp new file mode 100644 index 0000000000..b9b9e5b39e Binary files /dev/null and b/oox/qa/unit/data/tdf100391_TextAreaRect.odp differ diff --git a/oox/qa/unit/data/tdf109169_OctagonBevel.odt b/oox/qa/unit/data/tdf109169_OctagonBevel.odt new file mode 100644 index 0000000000..2ba39b102e Binary files /dev/null and b/oox/qa/unit/data/tdf109169_OctagonBevel.odt differ diff --git a/oox/qa/unit/data/tdf112450_vml_polyline.docx b/oox/qa/unit/data/tdf112450_vml_polyline.docx new file mode 100644 index 0000000000..a31124ee77 Binary files /dev/null and b/oox/qa/unit/data/tdf112450_vml_polyline.docx differ diff --git a/oox/qa/unit/data/tdf113187_arcTo_withoutReferences.pptx b/oox/qa/unit/data/tdf113187_arcTo_withoutReferences.pptx new file mode 100644 index 0000000000..1862c0257f Binary files /dev/null and b/oox/qa/unit/data/tdf113187_arcTo_withoutReferences.pptx differ diff --git a/oox/qa/unit/data/tdf125085_WordArtFontText.pptx b/oox/qa/unit/data/tdf125085_WordArtFontText.pptx new file mode 100644 index 0000000000..a9dab6d1cc Binary files /dev/null and b/oox/qa/unit/data/tdf125085_WordArtFontText.pptx differ diff --git a/oox/qa/unit/data/tdf125085_WordArtFontTheme.pptx b/oox/qa/unit/data/tdf125085_WordArtFontTheme.pptx new file mode 100644 index 0000000000..f4c37692af Binary files /dev/null and b/oox/qa/unit/data/tdf125085_WordArtFontTheme.pptx differ diff --git a/oox/qa/unit/data/tdf125582_TextOnCircle.pptx b/oox/qa/unit/data/tdf125582_TextOnCircle.pptx new file mode 100644 index 0000000000..b2c09e5153 Binary files /dev/null and b/oox/qa/unit/data/tdf125582_TextOnCircle.pptx differ diff --git a/oox/qa/unit/data/tdf125885_WordArt.docx b/oox/qa/unit/data/tdf125885_WordArt.docx new file mode 100644 index 0000000000..1aeecc3f03 Binary files /dev/null and b/oox/qa/unit/data/tdf125885_WordArt.docx differ diff --git a/oox/qa/unit/data/tdf125885_WordArt2.docx b/oox/qa/unit/data/tdf125885_WordArt2.docx new file mode 100644 index 0000000000..9e00e46d4d Binary files /dev/null and b/oox/qa/unit/data/tdf125885_WordArt2.docx differ diff --git a/oox/qa/unit/data/tdf125885_WordArt3.docx b/oox/qa/unit/data/tdf125885_WordArt3.docx new file mode 100644 index 0000000000..f14b54644e Binary files /dev/null and b/oox/qa/unit/data/tdf125885_WordArt3.docx differ diff --git a/oox/qa/unit/data/tdf128568_FontworkBitmapFill.odt b/oox/qa/unit/data/tdf128568_FontworkBitmapFill.odt new file mode 100644 index 0000000000..30a0730a10 Binary files /dev/null and b/oox/qa/unit/data/tdf128568_FontworkBitmapFill.odt differ diff --git a/oox/qa/unit/data/tdf128568_FontworkFontProperties.odt b/oox/qa/unit/data/tdf128568_FontworkFontProperties.odt new file mode 100644 index 0000000000..549d0fb029 Binary files /dev/null and b/oox/qa/unit/data/tdf128568_FontworkFontProperties.odt differ diff --git a/oox/qa/unit/data/tdf131082.pptx b/oox/qa/unit/data/tdf131082.pptx new file mode 100644 index 0000000000..dbe88126f9 Binary files /dev/null and b/oox/qa/unit/data/tdf131082.pptx differ diff --git a/oox/qa/unit/data/tdf137314_vml_rotation_unit_fd.docx b/oox/qa/unit/data/tdf137314_vml_rotation_unit_fd.docx new file mode 100644 index 0000000000..17c8cabc0c Binary files /dev/null and b/oox/qa/unit/data/tdf137314_vml_rotation_unit_fd.docx differ diff --git a/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx b/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx new file mode 100644 index 0000000000..8fd4bcc181 Binary files /dev/null and b/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx differ diff --git a/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx b/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx new file mode 100644 index 0000000000..405135783e Binary files /dev/null and b/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx differ diff --git a/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx b/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx new file mode 100644 index 0000000000..5da52ceb3c Binary files /dev/null and b/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx differ diff --git a/oox/qa/unit/data/tdf141463_GroupTransform.pptx b/oox/qa/unit/data/tdf141463_GroupTransform.pptx new file mode 100644 index 0000000000..36c5062623 Binary files /dev/null and b/oox/qa/unit/data/tdf141463_GroupTransform.pptx differ diff --git a/oox/qa/unit/data/tdf141786_PolylineConnectorInGroup.odt b/oox/qa/unit/data/tdf141786_PolylineConnectorInGroup.odt new file mode 100644 index 0000000000..d40dccac8c Binary files /dev/null and b/oox/qa/unit/data/tdf141786_PolylineConnectorInGroup.odt differ diff --git a/oox/qa/unit/data/tdf141786_RotatedShapeInGroup.odt b/oox/qa/unit/data/tdf141786_RotatedShapeInGroup.odt new file mode 100644 index 0000000000..e932cf47b8 Binary files /dev/null and b/oox/qa/unit/data/tdf141786_RotatedShapeInGroup.odt differ diff --git a/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt b/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt new file mode 100644 index 0000000000..bc0357a1a8 Binary files /dev/null and b/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt differ diff --git a/oox/qa/unit/data/tdf142605_CurveSize.odp b/oox/qa/unit/data/tdf142605_CurveSize.odp new file mode 100644 index 0000000000..c797d378f1 Binary files /dev/null and b/oox/qa/unit/data/tdf142605_CurveSize.odp differ diff --git a/oox/qa/unit/data/tdf147978_endsubpath.odp b/oox/qa/unit/data/tdf147978_endsubpath.odp new file mode 100644 index 0000000000..2dfd55de1b Binary files /dev/null and b/oox/qa/unit/data/tdf147978_endsubpath.odp differ diff --git a/oox/qa/unit/data/tdf147978_enhancedPath_commandA.odp b/oox/qa/unit/data/tdf147978_enhancedPath_commandA.odp new file mode 100644 index 0000000000..99ddda7c13 Binary files /dev/null and b/oox/qa/unit/data/tdf147978_enhancedPath_commandA.odp differ diff --git a/oox/qa/unit/data/tdf147978_enhancedPath_commandHIJK.odp b/oox/qa/unit/data/tdf147978_enhancedPath_commandHIJK.odp new file mode 100644 index 0000000000..49e01bc093 Binary files /dev/null and b/oox/qa/unit/data/tdf147978_enhancedPath_commandHIJK.odp differ diff --git a/oox/qa/unit/data/tdf147978_enhancedPath_commandT.odp b/oox/qa/unit/data/tdf147978_enhancedPath_commandT.odp new file mode 100644 index 0000000000..3dcd0d5675 Binary files /dev/null and b/oox/qa/unit/data/tdf147978_enhancedPath_commandT.odp differ diff --git a/oox/qa/unit/data/tdf147978_enhancedPath_commandXY.odp b/oox/qa/unit/data/tdf147978_enhancedPath_commandXY.odp new file mode 100644 index 0000000000..6112251783 Binary files /dev/null and b/oox/qa/unit/data/tdf147978_enhancedPath_commandXY.odp differ diff --git a/oox/qa/unit/data/tdf147978_enhancedPath_subpath.pptx b/oox/qa/unit/data/tdf147978_enhancedPath_subpath.pptx new file mode 100644 index 0000000000..bbedc7ab98 Binary files /dev/null and b/oox/qa/unit/data/tdf147978_enhancedPath_subpath.pptx differ diff --git a/oox/qa/unit/data/tdf148784_StretchCommandQ.odp b/oox/qa/unit/data/tdf148784_StretchCommandQ.odp new file mode 100644 index 0000000000..3da092b2c5 Binary files /dev/null and b/oox/qa/unit/data/tdf148784_StretchCommandQ.odp differ diff --git a/oox/qa/unit/data/tdf148784_StretchCommandVW.odp b/oox/qa/unit/data/tdf148784_StretchCommandVW.odp new file mode 100644 index 0000000000..bf1054a205 Binary files /dev/null and b/oox/qa/unit/data/tdf148784_StretchCommandVW.odp differ diff --git a/oox/qa/unit/data/tdf148784_StretchXY.odp b/oox/qa/unit/data/tdf148784_StretchXY.odp new file mode 100644 index 0000000000..f9df40570e Binary files /dev/null and b/oox/qa/unit/data/tdf148784_StretchXY.odp differ diff --git a/oox/qa/unit/data/tdf149538_upright.pptx b/oox/qa/unit/data/tdf149538_upright.pptx new file mode 100644 index 0000000000..a477b3b121 Binary files /dev/null and b/oox/qa/unit/data/tdf149538_upright.pptx differ diff --git a/oox/qa/unit/data/tdf149551_TextRot.pptx b/oox/qa/unit/data/tdf149551_TextRot.pptx new file mode 100644 index 0000000000..98c547530c Binary files /dev/null and b/oox/qa/unit/data/tdf149551_TextRot.pptx differ diff --git a/oox/qa/unit/data/tdf149551_vert270AndTextRot.pptx b/oox/qa/unit/data/tdf149551_vert270AndTextRot.pptx new file mode 100644 index 0000000000..b90a8fe917 Binary files /dev/null and b/oox/qa/unit/data/tdf149551_vert270AndTextRot.pptx differ diff --git a/oox/qa/unit/data/tdf149551_vert_and_padding.pptx b/oox/qa/unit/data/tdf149551_vert_and_padding.pptx new file mode 100644 index 0000000000..02b4855ff9 Binary files /dev/null and b/oox/qa/unit/data/tdf149551_vert_and_padding.pptx differ diff --git a/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx b/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx new file mode 100644 index 0000000000..999cd22040 Binary files /dev/null and b/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx differ diff --git a/oox/qa/unit/data/tdf151518_SmartArtTextLocation.docx b/oox/qa/unit/data/tdf151518_SmartArtTextLocation.docx new file mode 100644 index 0000000000..ec99be6bff Binary files /dev/null and b/oox/qa/unit/data/tdf151518_SmartArtTextLocation.docx differ diff --git a/oox/qa/unit/data/tdf152840_WordArt_non_accent_color.docx b/oox/qa/unit/data/tdf152840_WordArt_non_accent_color.docx new file mode 100644 index 0000000000..8777220372 Binary files /dev/null and b/oox/qa/unit/data/tdf152840_WordArt_non_accent_color.docx differ diff --git a/oox/qa/unit/data/tdf152840_theme_color_non_accent.docx b/oox/qa/unit/data/tdf152840_theme_color_non_accent.docx new file mode 100644 index 0000000000..2bb4e1340e Binary files /dev/null and b/oox/qa/unit/data/tdf152840_theme_color_non_accent.docx differ diff --git a/oox/qa/unit/data/tdf152896_WordArt_color_darken.docx b/oox/qa/unit/data/tdf152896_WordArt_color_darken.docx new file mode 100644 index 0000000000..1f8f8e4e0e Binary files /dev/null and b/oox/qa/unit/data/tdf152896_WordArt_color_darken.docx differ diff --git a/oox/qa/unit/data/tdf153246_VML_export_Fontwork_Adjustment.odt b/oox/qa/unit/data/tdf153246_VML_export_Fontwork_Adjustment.odt new file mode 100644 index 0000000000..1a26191821 Binary files /dev/null and b/oox/qa/unit/data/tdf153246_VML_export_Fontwork_Adjustment.odt differ diff --git a/oox/qa/unit/data/tdf153258_VML_import_WordArt_detection.docx b/oox/qa/unit/data/tdf153258_VML_import_WordArt_detection.docx new file mode 100644 index 0000000000..15944490e9 Binary files /dev/null and b/oox/qa/unit/data/tdf153258_VML_import_WordArt_detection.docx differ diff --git a/oox/qa/unit/data/tdf153260_VML_trim_export.odt b/oox/qa/unit/data/tdf153260_VML_trim_export.odt new file mode 100644 index 0000000000..407a27fff2 Binary files /dev/null and b/oox/qa/unit/data/tdf153260_VML_trim_export.odt differ diff --git a/oox/qa/unit/data/tdf153296_VML_export_ArchUpCurve.odt b/oox/qa/unit/data/tdf153296_VML_export_ArchUpCurve.odt new file mode 100644 index 0000000000..37e0f779d0 Binary files /dev/null and b/oox/qa/unit/data/tdf153296_VML_export_ArchUpCurve.odt differ diff --git a/oox/qa/unit/data/tdf153296_VML_export_SlantUp.odt b/oox/qa/unit/data/tdf153296_VML_export_SlantUp.odt new file mode 100644 index 0000000000..223ec5d169 Binary files /dev/null and b/oox/qa/unit/data/tdf153296_VML_export_SlantUp.odt differ diff --git a/oox/qa/unit/data/tdf155327_WordArtDefaultColor.pptx b/oox/qa/unit/data/tdf155327_WordArtDefaultColor.pptx new file mode 100644 index 0000000000..a813f4a329 Binary files /dev/null and b/oox/qa/unit/data/tdf155327_WordArtDefaultColor.pptx differ diff --git a/oox/qa/unit/data/tdf155412_typeface.pptx b/oox/qa/unit/data/tdf155412_typeface.pptx new file mode 100644 index 0000000000..30a486e70f Binary files /dev/null and b/oox/qa/unit/data/tdf155412_typeface.pptx differ diff --git a/oox/qa/unit/data/tdf155825_MCGR_SourceOffsetRangeDifferent.fodp b/oox/qa/unit/data/tdf155825_MCGR_SourceOffsetRangeDifferent.fodp new file mode 100644 index 0000000000..97b39689d5 --- /dev/null +++ b/oox/qa/unit/data/tdf155825_MCGR_SourceOffsetRangeDifferent.fodp @@ -0,0 +1,642 @@ + + + + 2023-06-14T00:44:04.16300000024x16impressPT3M3S3B2020/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/0028c2311ca14669ca530cd4db422cd3cf9438caRegina Henschel2023-06-14T13:59:18.149000000Regina Henschel + + + 344 + -6588 + 37359 + 12991 + + + view1 + false + false + true + true + true + true + false + false + true + 1500 + false + Hw== + Hw== + + false + true + false + 0 + 0 + false + true + true + 4 + 0 + 836 + -5097 + 34675 + 12116 + 2000 + 2000 + 500 + 500 + 2000 + 4 + 2000 + 4 + false + 1500 + false + false + true + false + false + + + + + true + 1250 + EPSON6FC99C (WP-4025 Series) + + + de + DE + + + + + + iAv+/0VQU09ONkZDOTlDIChXUC00MDI1IFNlcmllcykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARVBTT04gV1AtNDAyNSBTZXJpZXMAAAAAAAAAAAAAAAAWAAEAWgoAAAAAAAAEAAhSAAAEdAAAM1ROVwAAAAAKAEUAUABTAE8ATgA2AEYAQwA5ADkAQwAgACgAVwBQAC0ANAAwADIANQAgAFMAZQByAGkAZQBzACkAAAAAAAAAAAABBAAB3AB0CQ+bgAcBAAkAmgs0CGQAAQAHAFgCAgABAFgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0CQAAAQEBAQABAAABAAAAAAAAAAAAAAA4AAAAfAgAALQIAABAAAAA9AgAAIAAAAAAAAAAAAAAAAMACQRFAFAAUwBPAE4AIABXAFAALQA0ADAAMgA1ACAAUwBlAHIAaQBlAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABYAgAAAAAAAAAAAAABAAAAAgAAAAAAAQBYAlgCBwAAAAAACQA0CJoLHgAeAB4AHgA0CJoLOwORBAEAAAAOABYAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAAAAAAAAACAAAAAAIAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABkAGQANAiaCx4AHgAeAB4ACQAAAAAAAAAAAAAA//8AAAAAAAAAAB4AHgABAAAAAwDgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAAgAAAAAAAAAAAAEAMgAyANT+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYACoAAAAgAAEAAAAgAAAAQAAAAAYAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wAAAAAAAAAAAABCAAAAAQAAALAAAAAAAAAAAAAAAAAAAAAeAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBARIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmYMAFBSSU5URVJfTkFNRRwARVBTT042RkM5OUMgKFdQLTQwMjUgU2VyaWVzKQsARFJJVkVSX05BTUUUAEVQU09OIFdQLTQwMjUgU2VyaWVz + false + false + false + $(inst)/share/palette%3B$(user)/config/standard.sob + false + 0 + 0 + true + false + false + true + false + true + 0 + $(inst)/share/palette/libreoffice.soc + $(inst)/share/palette%3B$(user)/config/standard.sod + $(inst)/share/palette%3B$(user)/config/standard.soe + $(inst)/share/palette%3B$(user)/config/standard.soh + $(inst)/share/palette%3B$(user)/config/standard.sog + true + 4 + false + false + true + low-resolution + false + false + false + true + false + true + true + true + false + false + false + 6 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/tdf155827_MCGR_AxialColorLinearTrans.fodp b/oox/qa/unit/data/tdf155827_MCGR_AxialColorLinearTrans.fodp new file mode 100644 index 0000000000..f556699980 --- /dev/null +++ b/oox/qa/unit/data/tdf155827_MCGR_AxialColorLinearTrans.fodp @@ -0,0 +1,644 @@ + + + + 2023-06-16T14:29:43.28500000024x16impressPT33M34S4LODev_13_Jun/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/d4ee93a54e790acab470667591d61d424831e665Regina Henschel2023-06-16T15:25:09.016000000Regina Henschel + + + -235 + -6182 + 36454 + 16497 + + + view1 + false + false + true + true + true + true + false + false + true + 1500 + false + Hw== + Hw== + + false + true + false + 0 + 0 + false + true + true + 4 + 0 + -235 + -6182 + 36455 + 16498 + 2000 + 2000 + 500 + 500 + 2000 + 4 + 2000 + 4 + false + 1500 + true + false + true + false + false + + + + + true + 1250 + EPSON6FC99C (WP-4025 Series) + + + de + DE + + + + + + iAv+/0VQU09ONkZDOTlDIChXUC00MDI1IFNlcmllcykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARVBTT04gV1AtNDAyNSBTZXJpZXMAAAAAAAAAAAAAAAAWAAEAWgoAAAAAAAAEAAhSAAAEdAAAM1ROVwAAAAAKAEUAUABTAE8ATgA2AEYAQwA5ADkAQwAgACgAVwBQAC0ANAAwADIANQAgAFMAZQByAGkAZQBzACkAAAAAAAAAAAABBAAB3AB0CQ+bgAcBAAkAmgs0CGQAAQAHAFgCAgABAFgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0CQAAAQEBAQABAAABAAAAAAAAAAAAAAA4AAAAfAgAALQIAABAAAAA9AgAAIAAAAAAAAAAAAAAAAMACQRFAFAAUwBPAE4AIABXAFAALQA0ADAAMgA1ACAAUwBlAHIAaQBlAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABYAgAAAAAAAAAAAAABAAAAAgAAAAAAAQBYAlgCBwAAAAAACQA0CJoLHgAeAB4AHgA0CJoLOwORBAEAAAAOABYAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAAAAAAAAACAAAAAAIAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABkAGQANAiaCx4AHgAeAB4ACQAAAAAAAAAAAAAA//8AAAAAAAAAAB4AHgABAAAAAwDgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAAgAAAAAAAAAAAAEAMgAyANT+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYACoAAAAgAAEAAAAgAAAAQAAAAAYAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wAAAAAAAAAAAABCAAAAAQAAALAAAAAAAAAAAAAAAAAAAAAeAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBARIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmYMAFBSSU5URVJfTkFNRRwARVBTT042RkM5OUMgKFdQLTQwMjUgU2VyaWVzKQsARFJJVkVSX05BTUUUAEVQU09OIFdQLTQwMjUgU2VyaWVz + false + false + false + $(inst)/share/palette%3B$(user)/config/standard.sob + false + 0 + 0 + true + false + false + true + false + true + 0 + $(inst)/share/palette/html.soc + $(inst)/share/palette%3B$(user)/config/standard.sod + $(inst)/share/palette%3B$(user)/config/standard.soe + $(inst)/share/palette%3B$(user)/config/standard.soh + $(inst)/share/palette%3B$(user)/config/standard.sog + true + 4 + false + false + true + low-resolution + false + false + false + true + false + true + true + true + false + false + false + 6 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/tdf155852_MCGR_StepCount4.fodp b/oox/qa/unit/data/tdf155852_MCGR_StepCount4.fodp new file mode 100644 index 0000000000..309cb3b0b1 --- /dev/null +++ b/oox/qa/unit/data/tdf155852_MCGR_StepCount4.fodp @@ -0,0 +1,637 @@ + + + + 2023-06-15T14:04:51.506000000PT7M34S3B2020/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/977878814a3573627026e31edb8a51c8f30c8a0cRegina Henschel2023-06-15T14:52:02.192000000Regina Henschel + + + -231 + -8197 + 41102 + 16741 + + + view1 + false + false + true + true + true + true + false + false + true + 1500 + false + Hw== + Hw== + + false + true + false + 0 + 0 + false + true + true + 4 + 0 + -231 + -8197 + 41103 + 16742 + 2000 + 2000 + 500 + 500 + 2000 + 4 + 2000 + 4 + false + 1500 + true + false + false + false + false + + + + + true + 1250 + EPSON6FC99C (WP-4025 Series) + + + de + DE + + + + + + iAv+/0VQU09ONkZDOTlDIChXUC00MDI1IFNlcmllcykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARVBTT04gV1AtNDAyNSBTZXJpZXMAAAAAAAAAAAAAAAAWAAEAWgoAAAAAAAAEAAhSAAAEdAAAM1ROVwAAAAAKAEUAUABTAE8ATgA2AEYAQwA5ADkAQwAgACgAVwBQAC0ANAAwADIANQAgAFMAZQByAGkAZQBzACkAAAAAAAAAAAABBAAB3AB0CQ+bgAcBAAkAmgs0CGQAAQAHAFgCAgABAFgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0CQAAAQEBAQABAAABAAAAAAAAAAAAAAA4AAAAfAgAALQIAABAAAAA9AgAAIAAAAAAAAAAAAAAAAMACQRFAFAAUwBPAE4AIABXAFAALQA0ADAAMgA1ACAAUwBlAHIAaQBlAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABYAgAAAAAAAAAAAAABAAAAAgAAAAAAAQBYAlgCBwAAAAAACQA0CJoLHgAeAB4AHgA0CJoLOwORBAEAAAAOABYAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAAAAAAAAACAAAAAAIAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABkAGQANAiaCx4AHgAeAB4ACQAAAAAAAAAAAAAA//8AAAAAAAAAAB4AHgABAAAAAwDgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAAgAAAAAAAAAAAAEAMgAyANT+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYACoAAAAgAAEAAAAgAAAAQAAAAAYAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wAAAAAAAAAAAABCAAAAAQAAALAAAAAAAAAAAAAAAAAAAAAeAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBARIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmYMAFBSSU5URVJfTkFNRRwARVBTT042RkM5OUMgKFdQLTQwMjUgU2VyaWVzKQsARFJJVkVSX05BTUUUAEVQU09OIFdQLTQwMjUgU2VyaWVz + false + false + false + $(inst)/share/palette%3B$(user)/config/standard.sob + false + 0 + 0 + true + false + false + true + false + true + 0 + $(inst)/share/palette/html.soc + $(inst)/share/palette%3B$(user)/config/standard.sod + $(inst)/share/palette%3B$(user)/config/standard.soe + $(inst)/share/palette%3B$(user)/config/standard.soh + $(inst)/share/palette%3B$(user)/config/standard.sog + true + 4 + false + false + true + low-resolution + false + false + false + true + false + true + true + true + false + false + false + 6 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/tdf156902_GlowOnGroup.docx b/oox/qa/unit/data/tdf156902_GlowOnGroup.docx new file mode 100644 index 0000000000..0c176eefa0 Binary files /dev/null and b/oox/qa/unit/data/tdf156902_GlowOnGroup.docx differ diff --git a/oox/qa/unit/data/tdf157289_circularArrow_export.fodp b/oox/qa/unit/data/tdf157289_circularArrow_export.fodp new file mode 100644 index 0000000000..5a60c12f0d --- /dev/null +++ b/oox/qa/unit/data/tdf157289_circularArrow_export.fodp @@ -0,0 +1,816 @@ + + + + Regina Henschel2023-10-03T19:35:53.8910000002023-10-03T19:51:14.403000000Regina HenschelPT8M25S2LODev_27_Sep/24.2.0.0.alpha0$Windows_X86_64 LibreOffice_project/2902ab24ecc5ffbf4907ea83b2028508b9de6364 + + + -7708 + -7628 + 25739 + 15092 + + + view1 + false + false + false + true + true + true + false + true + true + 1500 + false + Hw== + Hw== + + false + true + true + 0 + 0 + false + true + true + 4 + 0 + -7708 + -7628 + 42774 + 31152 + 1000 + 1000 + 200 + 200 + 1000 + 5 + 1000 + 5 + false + 1500 + false + false + false + false + false + + + + + true + 1250 + EPSON6FC99C (WP-4025 Series) + iAv+/0VQU09ONkZDOTlDIChXUC00MDI1IFNlcmllcykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARVBTT04gV1AtNDAyNSBTZXJpZXMAAAAAAAAAAAAAAAAWAAEAWgoAAAAAAAAEAAhSAAAEdAAAM1ROVwAAAAAKAEUAUABTAE8ATgA2AEYAQwA5ADkAQwAgACgAVwBQAC0ANAAwADIANQAgAFMAZQByAGkAZQBzACkAAAAAAAAAAAABBAAB3AB0CQ+bgAcBAAkAmgs0CGQAAQAHAFgCAgABAFgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0CQAAAQEBAQABAAABAAAAAAAAAAAAAAA4AAAAfAgAALQIAABAAAAA9AgAAIAAAAAAAAAAAAAAAAMABwRFAFAAUwBPAE4AIABXAFAALQA0ADAAMgA1ACAAUwBlAHIAaQBlAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABYAgAAAAAAAAAAAAABAAAAAgAAAAAAAQBYAlgCBwAAAAAACQA0CJoLHgAeAB4AHgA0CJoLOwORBAEAAAAOABYAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAAAAAAAAACAAAAAAIAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABkAGQANAiaCx4AHgAeAB4ACQAAAAAAAAAAAAAA//8AAAAAAAAAAB4AHgABAAAAAwDgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAAgAAAAAAAAAAAAEAMgAyANT+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYACoAAAAgAAEAAAAgAAAAQAAAAAYAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wAAAAAAAAAAAABCAAAAAQAAALAAAAAAAAAAAAAAAAAAAAAeAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBARIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmYMAFBSSU5URVJfTkFNRRwARVBTT042RkM5OUMgKFdQLTQwMjUgU2VyaWVzKQsARFJJVkVSX05BTUUUAEVQU09OIFdQLTQwMjUgU2VyaWVz + false + false + false + $(inst)/share/palette%3B$(user)/config/standard.sob + false + 0 + 0 + true + false + false + true + false + true + 0 + $(inst)/share/palette%3B$(user)/config/standard.soc + $(inst)/share/palette%3B$(user)/config/standard.sod + $(inst)/share/palette%3B$(user)/config/standard.soe + $(inst)/share/palette%3B$(user)/config/standard.soh + $(inst)/share/palette%3B$(user)/config/standard.sog + true + 4 + false + false + true + low-resolution + false + false + false + true + false + true + true + true + false + false + false + 6 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oox/qa/unit/data/tdf51195_Fontwork_DirectColor.odt b/oox/qa/unit/data/tdf51195_Fontwork_DirectColor.odt new file mode 100644 index 0000000000..6388b07675 Binary files /dev/null and b/oox/qa/unit/data/tdf51195_Fontwork_DirectColor.odt differ diff --git a/oox/qa/unit/data/tdf51195_Fontwork_Distance.odt b/oox/qa/unit/data/tdf51195_Fontwork_Distance.odt new file mode 100644 index 0000000000..e747afd955 Binary files /dev/null and b/oox/qa/unit/data/tdf51195_Fontwork_Distance.odt differ diff --git a/oox/qa/unit/data/tdf51195_Fontwork_ThemeColor.fodt b/oox/qa/unit/data/tdf51195_Fontwork_ThemeColor.fodt new file mode 100644 index 0000000000..f7af1acc9b --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_ThemeColor.fodt @@ -0,0 +1,475 @@ + + + + 62023-02-20T21:58:51.947000000PT14M1SLibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341faDinA6 quer MS Default ThemeRegina Henschel2023-02-20T23:08:30.917000000Regina Henschel16.0000 + + + 0 + 0 + 51472 + 29917 + true + false + + + view2 + 18837 + 1002 + 0 + 0 + 51470 + 29916 + 0 + 1 + false + 75 + false + false + false + false + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + true + true + true + false + false + true + true + false + true + + true + true + true + true + false + true + true + false + false + true + true + true + true + true + false + false + false + 1265926 + false + + true + false + false + 1959839 + true + false + false + false + 1 + true + true + false + false + true + false + false + true + false + true + false + true + 0 + + false + true + true + true + + 0 + false + false + false + false + high-resolution + true + true + true + true + true + false + false + false + false + true + + true + true + true + true + + false + false + true + true + true + true + true + true + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Theme “Office Theme” “Office” + + darker 50% + + + + + + + lighter 40% + + + + + + + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_axialGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_axialGradient.fodt new file mode 100644 index 0000000000..70f1448397 --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_axialGradient.fodt @@ -0,0 +1,462 @@ + + + + Regina HenschelRegina Henschel42023-03-07T11:11:002023-03-07T19:15:08.288000000PT13M45SLibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341fa16.0000 + + + 0 + 0 + 38994 + 22664 + true + false + + + view2 + 12598 + 1002 + 0 + 0 + 38993 + 22662 + 0 + 1 + false + 99 + false + false + false + false + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + true + true + true + false + false + true + true + false + true + + true + true + true + true + false + true + true + false + false + true + true + true + true + true + false + false + false + 435364 + false + + true + false + false + 590465 + true + false + false + false + 1 + true + true + false + false + true + false + false + false + false + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + true + true + true + true + false + false + false + false + true + + true + true + true + true + + false + false + true + false + true + true + true + true + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Happy Birthday + + + + + + + + + + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_ellipticalGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_ellipticalGradient.fodt new file mode 100644 index 0000000000..01eeed1fd9 --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_ellipticalGradient.fodt @@ -0,0 +1,728 @@ + + + + 2023-03-07T20:31:28.577000000A6querPT18M50S6LibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341faRegina Henschel2023-03-08T11:23:06.729000000Regina Henschel + + + 0 + 0 + 48255 + 28048 + true + false + + + view2 + 17226 + 1000 + 0 + 0 + 48253 + 28046 + 0 + 1 + false + 80 + false + false + false + true + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + false + true + false + false + false + false + true + false + false + + false + false + true + false + false + true + true + false + false + false + false + false + false + true + false + false + false + 1306543 + false + + true + false + false + 1623591 + true + false + false + false + 1 + true + true + false + false + false + false + false + false + true + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + false + false + false + true + false + false + false + false + true + + true + false + true + false + + false + false + false + false + false + false + false + false + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dummy + + Happy Birthday + + + + + + + + + + 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 + + + + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_linearGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_linearGradient.fodt new file mode 100644 index 0000000000..26673c2c9b --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_linearGradient.fodt @@ -0,0 +1,416 @@ + + + + 2023-03-06T23:35:14.878000000A6querPT12M51S5LibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341faRegina Henschel2023-03-06T23:50:30.505000000Regina Henschel + + + 0 + 0 + 38604 + 22438 + true + false + + + view2 + 12400 + 1000 + 0 + 0 + 38603 + 22437 + 0 + 1 + false + 100 + false + false + false + true + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + false + true + false + false + false + false + true + false + false + + false + false + true + false + false + true + true + false + false + false + false + false + false + true + false + false + false + 1306543 + false + + true + false + false + 1639407 + true + false + false + false + 1 + true + true + false + false + false + false + false + false + true + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + false + false + false + true + false + false + false + false + true + + true + false + true + false + + false + false + false + false + false + false + false + false + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Happy Birthday + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dummy + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_radialGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_radialGradient.fodt new file mode 100644 index 0000000000..2979e9a895 --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_radialGradient.fodt @@ -0,0 +1,395 @@ + + + + 2023-03-07T20:31:28.577000000A6querPT9M4S3LibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341faRegina Henschel2023-03-07T20:51:21.698000000Regina Henschel + + + 0 + 0 + 48255 + 28048 + true + false + + + view2 + 17226 + 1000 + 0 + 0 + 48253 + 28046 + 0 + 1 + false + 80 + false + false + false + true + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + false + true + false + false + false + false + true + false + false + + false + false + true + false + false + true + true + false + false + false + false + false + false + true + false + false + false + 1306543 + false + + true + false + false + 1424207 + true + false + false + false + 1 + true + true + false + false + false + false + false + false + true + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + false + false + false + true + false + false + false + false + true + + true + false + true + false + + false + false + false + false + false + false + false + false + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dummy + + Happy Birthday + + + + + + + + + + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_rectGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_rectGradient.fodt new file mode 100644 index 0000000000..018363fdab --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_rectGradient.fodt @@ -0,0 +1,493 @@ + + + + Regina HenschelRegina Henschel82023-02-26T00:05:002023-03-08T14:56:20.660000000PT26M38SLibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341fa16.0000 + + + 0 + 0 + 48255 + 28048 + true + false + + + view2 + 17228 + 1002 + 0 + 0 + 48253 + 28046 + 0 + 1 + false + 80 + false + false + false + false + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + true + true + true + false + false + true + true + false + true + + true + true + true + true + false + true + true + false + false + true + true + true + true + true + false + false + false + 1801999 + false + + true + false + false + 2341708 + true + false + false + false + 1 + true + true + false + false + true + false + false + false + false + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + true + true + true + true + false + false + false + false + true + + true + true + true + true + + false + false + true + false + true + true + true + true + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Happy Birthday + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oox/qa/unit/data/tdf51195_Fontwork_squareGradient.fodt b/oox/qa/unit/data/tdf51195_Fontwork_squareGradient.fodt new file mode 100644 index 0000000000..6ab0b87822 --- /dev/null +++ b/oox/qa/unit/data/tdf51195_Fontwork_squareGradient.fodt @@ -0,0 +1,488 @@ + + + + Regina HenschelRegina Henschel72023-02-26T00:05:002023-03-08T14:15:28.240000000PT1H35M48SLibreOfficeDev/7.6.0.0.alpha1$Linux_X86_64 LibreOffice_project/d7984b1f13530624080dca2068c2cfa08d5341fa16.0000 + + + 0 + 0 + 48255 + 28048 + true + false + + + view2 + 17228 + 1002 + 0 + 0 + 48253 + 28046 + 0 + 1 + false + 80 + false + false + false + false + false + false + + + + + true + false + true + false + true + false + false + true + false + 0 + true + true + true + false + false + true + true + false + true + + true + true + true + true + false + true + true + false + false + true + true + true + true + true + false + false + false + 852270 + false + + true + false + false + 1301645 + true + false + false + false + 1 + true + true + false + false + true + false + false + false + false + true + false + true + 0 + + false + true + true + true + + 0 + false + true + false + false + high-resolution + true + true + true + true + true + false + false + false + false + true + + true + true + true + true + + false + false + true + false + true + true + true + true + false + false + false + false + false + false + 0 + true + false + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Happy Birthday + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dummy + + + diff --git a/oox/qa/unit/data/tdf54095_SmartArtThemeTextColor.docx b/oox/qa/unit/data/tdf54095_SmartArtThemeTextColor.docx new file mode 100644 index 0000000000..8aff8469bb Binary files /dev/null and b/oox/qa/unit/data/tdf54095_SmartArtThemeTextColor.docx differ diff --git a/oox/qa/unit/data/testTdf132557_footerCustomShapes.pptx b/oox/qa/unit/data/testTdf132557_footerCustomShapes.pptx new file mode 100644 index 0000000000..4dbf3717d1 Binary files /dev/null and b/oox/qa/unit/data/testTdf132557_footerCustomShapes.pptx differ diff --git a/oox/qa/unit/data/theme-tint.pptx b/oox/qa/unit/data/theme-tint.pptx new file mode 100644 index 0000000000..23ab7589de Binary files /dev/null and b/oox/qa/unit/data/theme-tint.pptx differ diff --git a/oox/qa/unit/data/theme.pptx b/oox/qa/unit/data/theme.pptx new file mode 100644 index 0000000000..5268e40413 Binary files /dev/null and b/oox/qa/unit/data/theme.pptx differ diff --git a/oox/qa/unit/data/transparent-text.pptx b/oox/qa/unit/data/transparent-text.pptx new file mode 100644 index 0000000000..b7b3ede4dc Binary files /dev/null and b/oox/qa/unit/data/transparent-text.pptx differ diff --git a/oox/qa/unit/data/vba/complex1.bin b/oox/qa/unit/data/vba/complex1.bin new file mode 100644 index 0000000000..3902082903 Binary files /dev/null and b/oox/qa/unit/data/vba/complex1.bin differ diff --git a/oox/qa/unit/data/vba/reference/complex1.bin b/oox/qa/unit/data/vba/reference/complex1.bin new file mode 100644 index 0000000000..335b8e808e Binary files /dev/null and b/oox/qa/unit/data/vba/reference/complex1.bin differ diff --git a/oox/qa/unit/data/vba/reference/simple1.bin b/oox/qa/unit/data/vba/reference/simple1.bin new file mode 100644 index 0000000000..a4644fbb72 Binary files /dev/null and b/oox/qa/unit/data/vba/reference/simple1.bin differ diff --git a/oox/qa/unit/data/vba/reference/simple2.bin b/oox/qa/unit/data/vba/reference/simple2.bin new file mode 100644 index 0000000000..5de3f5ae05 Binary files /dev/null and b/oox/qa/unit/data/vba/reference/simple2.bin differ diff --git a/oox/qa/unit/data/vba/reference/simple3.bin b/oox/qa/unit/data/vba/reference/simple3.bin new file mode 100644 index 0000000000..a38e8a8686 --- /dev/null +++ b/oox/qa/unit/data/vba/reference/simple3.bin @@ -0,0 +1 @@ + diff --git a/oox/qa/unit/data/vba/reference/spec321.bin b/oox/qa/unit/data/vba/reference/spec321.bin new file mode 100644 index 0000000000..3120c7f501 Binary files /dev/null and b/oox/qa/unit/data/vba/reference/spec321.bin differ diff --git a/oox/qa/unit/data/vba/reference/spec322.bin b/oox/qa/unit/data/vba/reference/spec322.bin new file mode 100644 index 0000000000..7724b62a44 Binary files /dev/null and b/oox/qa/unit/data/vba/reference/spec322.bin differ diff --git a/oox/qa/unit/data/vba/reference/spec323.bin b/oox/qa/unit/data/vba/reference/spec323.bin new file mode 100644 index 0000000000..51104ee0b4 Binary files /dev/null and b/oox/qa/unit/data/vba/reference/spec323.bin differ diff --git a/oox/qa/unit/data/vba/simple1.bin b/oox/qa/unit/data/vba/simple1.bin new file mode 100644 index 0000000000..d59c1d5ef0 Binary files /dev/null and b/oox/qa/unit/data/vba/simple1.bin differ diff --git a/oox/qa/unit/data/vba/simple2.bin b/oox/qa/unit/data/vba/simple2.bin new file mode 100644 index 0000000000..1b9b88b16d Binary files /dev/null and b/oox/qa/unit/data/vba/simple2.bin differ diff --git a/oox/qa/unit/data/vba/simple3.bin b/oox/qa/unit/data/vba/simple3.bin new file mode 100644 index 0000000000..72060e8a2d --- /dev/null +++ b/oox/qa/unit/data/vba/simple3.bin @@ -0,0 +1 @@ + diff --git a/oox/qa/unit/data/vba/spec321.bin b/oox/qa/unit/data/vba/spec321.bin new file mode 100644 index 0000000000..c5d48c9fc2 --- /dev/null +++ b/oox/qa/unit/data/vba/spec321.bin @@ -0,0 +1 @@ +abcdefghijklmnopqrstuv. \ No newline at end of file diff --git a/oox/qa/unit/data/vba/spec322.bin b/oox/qa/unit/data/vba/spec322.bin new file mode 100644 index 0000000000..781c426c0a --- /dev/null +++ b/oox/qa/unit/data/vba/spec322.bin @@ -0,0 +1 @@ +#aaabcdefaaaaghijaaaaaklaaamnopqaaaaaaaaaaaarstuvwxyzaaa \ No newline at end of file diff --git a/oox/qa/unit/data/vba/spec323.bin b/oox/qa/unit/data/vba/spec323.bin new file mode 100644 index 0000000000..9ca58b98a7 --- /dev/null +++ b/oox/qa/unit/data/vba/spec323.bin @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/oox/qa/unit/data/watermark.docx b/oox/qa/unit/data/watermark.docx new file mode 100644 index 0000000000..c9eacff9a6 Binary files /dev/null and b/oox/qa/unit/data/watermark.docx differ diff --git a/oox/qa/unit/drawingml.cxx b/oox/qa/unit/drawingml.cxx new file mode 100644 index 0000000000..ba2eaf75a1 --- /dev/null +++ b/oox/qa/unit/drawingml.cxx @@ -0,0 +1,706 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Gets one child of xShape, which one is specified by nIndex. +uno::Reference getChildShape(const uno::Reference& xShape, + sal_Int32 nIndex) +{ + uno::Reference xGroup(xShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xGroup.is()); + + CPPUNIT_ASSERT(xGroup->getCount() > nIndex); + + uno::Reference xRet(xGroup->getByIndex(nIndex), uno::UNO_QUERY); + CPPUNIT_ASSERT(xRet.is()); + + return xRet; +} +} + +/// oox drawingml tests. +class OoxDrawingmlTest : public UnoApiTest +{ +public: + OoxDrawingmlTest() + : UnoApiTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTransparentText) +{ + loadFromFile(u"transparent-text.pptx"); + saveAndReload("Impress Office Open XML"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xParagraph( + xShape->createEnumeration()->nextElement(), uno::UNO_QUERY); + uno::Reference xPortion(xParagraph->createEnumeration()->nextElement(), + uno::UNO_QUERY); + + sal_Int16 nTransparency = 0; + xPortion->getPropertyValue("CharTransparence") >>= nTransparency; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 75 + // - Actual : 0 + // i.e. the transparency of the character color was lost on import/export. + CPPUNIT_ASSERT_EQUAL(static_cast(75), nTransparency); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf131082) +{ + loadFromFile(u"tdf131082.pptx"); + saveAndReload("Impress Office Open XML"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference XPropSet(getChildShape(getChildShape(xShape, 0), 0), + uno::UNO_QUERY); + + drawing::FillStyle eFillStyle = drawing::FillStyle_NONE; + XPropSet->getPropertyValue("FillStyle") >>= eFillStyle; + + // Without the accompanying fix in place, this test would have failed with: + // with drawing::FillStyle_NONE - 0 + CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, eFillStyle); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testPresetAdjustValue) +{ + loadFromFile(u"preset-adjust-value.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + uno::Sequence aAdjustmentSeq; + aGeoPropMap.getValue("AdjustmentValues") >>= aAdjustmentSeq; + CPPUNIT_ASSERT_EQUAL(static_cast(1), aAdjustmentSeq.getLength()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 11587 + // - Actual : 10813 + // i.e. the adjust value was set from the placeholder, not from the shape. + CPPUNIT_ASSERT_EQUAL(static_cast(11587), aAdjustmentSeq[0].Value.get()); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testChartDataLabelCharColor) +{ + loadFromFile(u"chart-data-label-char-color.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xModel(xShape->getPropertyValue("Model"), + uno::UNO_QUERY); + uno::Reference xDiagram(xModel->getFirstDiagram(), + uno::UNO_QUERY); + + uno::Reference xCoordinateSystem( + xDiagram->getCoordinateSystems()[0], uno::UNO_QUERY); + + uno::Reference xChartType(xCoordinateSystem->getChartTypes()[0], + uno::UNO_QUERY); + + uno::Reference xDataSeries = xChartType->getDataSeries()[0]; + + uno::Reference xDataPoint = xDataSeries->getDataPointByIndex(0); + + uno::Sequence> aLabels; + xDataPoint->getPropertyValue("CustomLabelFields") >>= aLabels; + uno::Reference xLabel = aLabels[0]; + + Color nCharColor; + xLabel->getPropertyValue("CharColor") >>= nCharColor; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 16777215 + // - Actual : -1 + // i.e. the data label had no explicit (white) color. + CPPUNIT_ASSERT_EQUAL(COL_WHITE, nCharColor); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testGradientMultiStepTransparency) +{ + // Load a document with a multi-step gradient. + loadFromFile(u"gradient-multistep-transparency.pptx"); + + // Check the end transparency of the gradient. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("Rectangle 4"), xShape->getName()); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + awt::Gradient2 aTransparence; + xShapeProps->getPropertyValue("FillTransparenceGradient") >>= aTransparence; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 16777215 (COL_WHITE) + // - Actual : 3487029 (0x353535) + // i.e. the end transparency was not 100%, but was 21%, leading to an unexpected visible line on + // the right of this shape. + // MCGR: Use the completely imported transparency gradient to check for correctness + const basegfx::BColorStops aColorStops + = model::gradient::getColorStopsFromUno(aTransparence.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(5), aColorStops.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.00, aColorStops[0].getStopOffset(), 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.19, aColorStops[1].getStopOffset(), 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.35, aColorStops[2].getStopOffset(), 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.58, aColorStops[3].getStopOffset(), 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.00, aColorStops[4].getStopOffset(), 1E-3); + CPPUNIT_ASSERT_EQUAL(Color(0xffffff), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT_EQUAL(Color(0x9e9e9e), Color(aColorStops[1].getStopColor())); + CPPUNIT_ASSERT_EQUAL(Color(0x363636), Color(aColorStops[2].getStopColor())); + CPPUNIT_ASSERT_EQUAL(Color(0x000000), Color(aColorStops[3].getStopColor())); + CPPUNIT_ASSERT_EQUAL(Color(0x000000), Color(aColorStops[4].getStopColor())); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testShapeTextAlignment) +{ + loadFromFile(u"shape-text-alignment.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + sal_Int16 nParaAdjust = -1; + CPPUNIT_ASSERT(xShape->getPropertyValue("ParaAdjust") >>= nParaAdjust); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 3 + // i.e. text which is meant to be left-aligned was centered at a paragraph level. + CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_LEFT, + static_cast(nParaAdjust)); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testShapeTextAdjustLeft) +{ + loadFromFile(u"shape-text-adjust-left.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + drawing::TextHorizontalAdjust eAdjust; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 3 (center) + // - Actual : 1 (block) + // i.e. text was center-adjusted, not default-adjusted (~left). + CPPUNIT_ASSERT(xShape->getPropertyValue("TextHorizontalAdjust") >>= eAdjust); + CPPUNIT_ASSERT_EQUAL(drawing::TextHorizontalAdjust_BLOCK, eAdjust); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testCameraRotationRevolution) +{ + loadFromFile(u"camera-rotation-revolution.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape0(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape1(xDrawPage->getByIndex(1), uno::UNO_QUERY); + uno::Reference xShapeProps0(xShape0, uno::UNO_QUERY); + uno::Reference xShapeProps1(xShape1, uno::UNO_QUERY); + sal_Int32 nRotateAngle0; + sal_Int32 nRotateAngle1; + xShapeProps0->getPropertyValue("RotateAngle") >>= nRotateAngle0; + xShapeProps1->getPropertyValue("RotateAngle") >>= nRotateAngle1; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 8000 + // - Actual : 0 + // so the camera rotation would not have been factored into how the shape is displayed + CPPUNIT_ASSERT_EQUAL(static_cast(8000), nRotateAngle0); + CPPUNIT_ASSERT_EQUAL(static_cast(27000), nRotateAngle1); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf146534_CameraRotationRevolutionNonWpsShapes) +{ + loadFromFile(u"camera-rotation-revolution-nonwps.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape0(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape1(xDrawPage->getByIndex(1), uno::UNO_QUERY); + uno::Reference xShapeProps0(xShape0, uno::UNO_QUERY); + uno::Reference xShapeProps1(xShape1, uno::UNO_QUERY); + sal_Int32 nRotateAngle0; + sal_Int32 nRotateAngle1; + xShapeProps0->getPropertyValue("RotateAngle") >>= nRotateAngle0; + xShapeProps1->getPropertyValue("RotateAngle") >>= nRotateAngle1; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 9000 + // - Actual : 0 + // so the camera rotation would not have been factored into how the shape is displayed + CPPUNIT_ASSERT_EQUAL(static_cast(9000), nRotateAngle0); + CPPUNIT_ASSERT_EQUAL(static_cast(30500), nRotateAngle1); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTableShadow) +{ + auto verify = [](const uno::Reference& xComponent) { + uno::Reference xDrawPagesSupplier(xComponent, uno::UNO_QUERY); + uno::Reference xDrawPage( + xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + bool bShadow = false; + CPPUNIT_ASSERT(xShape->getPropertyValue("Shadow") >>= bShadow); + + CPPUNIT_ASSERT(bShadow); + Color nColor; + CPPUNIT_ASSERT(xShape->getPropertyValue("ShadowColor") >>= nColor); + CPPUNIT_ASSERT_EQUAL(Color(0xff0000), nColor); + }; + loadFromFile(u"table-shadow.pptx"); + // Without the accompanying fix in place, this test would have failed, because shadow on a table + // was lost on import. + verify(mxComponent); + + saveAndReload("Impress Office Open XML"); + + // Without the accompanying fix in place, this test would have failed, because shadow on a table + // was lost on export. + verify(mxComponent); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testGroupShapeSmartArt) +{ + // Given a file with a smartart inside a group shape: + loadFromFile(u"smartart-groupshape.pptx"); + + // Then make sure that the smartart is not just an empty group shape: + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xSmartArt(xGroup->getByIndex(0), uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed, because we lost all + // children of the group shape representing the smartart. + CPPUNIT_ASSERT_GREATER(static_cast(0), xSmartArt->getCount()); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf142605_CurveSize) +{ + // The document contains a Bezier curve, where the control points are outside the bounding + // rectangle of the shape. Error was, that the export uses a path size which included the + // control points. + loadFromFile(u"tdf142605_CurveSize.odp"); + saveAndReload("Impress Office Open XML"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + auto xPage = xDrawPagesSupplier->getDrawPages()->getByIndex(0); + uno::Reference xDrawPage(xPage, uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape.is()); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapeProps.is()); + uno::Reference xShapeNamed(xShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapeNamed.is()); + CPPUNIT_ASSERT_EQUAL(u"Bézier curve 1"_ustr, xShapeNamed->getName()); + + css::awt::Rectangle aBoundRect; + xShapeProps->getPropertyValue("BoundRect") >>= aBoundRect; + // Without fix, size was 6262 x 3509, and position was 10037|6790. + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(8601), aBoundRect.Width, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(4601), aBoundRect.Height, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(7699), aBoundRect.X, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(5699), aBoundRect.Y, 1); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testChartThemeOverride) +{ + // Given a document with 2 slides, slide1 has a chart with a theme override and slide2 has a + // shape: + loadFromFile(u"chart-theme-override.pptx"); + + // Then make sure that the slide 2 shape's text color is blue, not red: + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(1), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xText(xShape->getText(), uno::UNO_QUERY); + uno::Reference xPara(xText->createEnumeration()->nextElement(), + uno::UNO_QUERY); + uno::Reference xPortion(xPara->createEnumeration()->nextElement(), + uno::UNO_QUERY); + sal_Int32 nActual{ 0 }; + xPortion->getPropertyValue("CharColor") >>= nActual; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 4485828 (0x4472c4) + // - Actual : 16711680 (0xff0000) + // i.e. the text color was red, not blue. + CPPUNIT_ASSERT_EQUAL(static_cast(0x4472C4), nActual); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testPptxTheme) +{ + // Given a PPTX file with a slide -> master slide -> theme: + loadFromFile(u"theme.pptx"); + + // Then make sure the theme + referring to that theme is imported: + // Check the imported theme of the master page: + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage( + xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + uno::Reference xMasterpage(xDrawPage->getMasterPage(), uno::UNO_QUERY); + + uno::Reference xTheme; + xMasterpage->getPropertyValue("Theme") >>= xTheme; + + // We expect the theme to be set on the master page + CPPUNIT_ASSERT(xTheme.is()); + auto* pUnoTheme = dynamic_cast(xTheme.get()); + CPPUNIT_ASSERT(pUnoTheme); + auto pTheme = pUnoTheme->getTheme(); + + CPPUNIT_ASSERT_EQUAL(OUString("Office Theme"), pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(OUString("Office"), pTheme->getColorSet()->getName()); + + CPPUNIT_ASSERT_EQUAL(Color(0x954F72), + pTheme->getColorSet()->getColor(model::ThemeColorType::FollowedHyperlink)); + + // Check the reference to that theme: + uno::Reference xDrawPageShapes(xDrawPage, uno::UNO_QUERY); + uno::Reference xShape(xDrawPageShapes->getByIndex(0), uno::UNO_QUERY); + uno::Reference xText(xShape->getText(), uno::UNO_QUERY); + uno::Reference xPara(xText->createEnumeration()->nextElement(), + uno::UNO_QUERY); + uno::Reference xPortion(xPara->createEnumeration()->nextElement(), + uno::UNO_QUERY); + + // Check the theme colors are as expected + { + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xPortion->getPropertyValue("CharComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent1, aComplexColor.getThemeColorType()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, + aComplexColor.getTransformations()[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(6000), aComplexColor.getTransformations()[0].mnValue); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumOff, + aComplexColor.getTransformations()[1].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(4000), aComplexColor.getTransformations()[1].mnValue); + } +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf132557_footerCustomShapes) +{ + // slide with date, footer, slide number with custom shapes + loadFromFile(u"testTdf132557_footerCustomShapes.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // Test if we were able to import the footer shapes with CustomShape service. + uno::Reference xShapeDateTime(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.CustomShape"), + xShapeDateTime->getShapeType()); + // Without the accompanying fix in place, this test would have failed with: + // An uncaught exception of type com.sun.star.lang.IndexOutOfBoundsException + // i.e. the shape wasn't on the slide there since it was imported as a property, not a shape. + + uno::Reference xShapeFooter(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.CustomShape"), + xShapeFooter->getShapeType()); + + uno::Reference xShapeSlideNum(xDrawPage->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.CustomShape"), + xShapeSlideNum->getShapeType()); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testThemeColorTint_Table) +{ + // Given a document with a table style, using theme color with tinting in the A2 cell: + loadFromFile(u"theme-tint.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xTable; + CPPUNIT_ASSERT(xShape->getPropertyValue("Model") >>= xTable); + uno::Reference xA1(xTable->getCellByPosition(0, 0), uno::UNO_QUERY); + + // check theme color + { + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xA1->getPropertyValue("FillComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent1, aComplexColor.getThemeColorType()); + { + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(0), rTrans.size()); + } + } + + { + uno::Reference xA2(xTable->getCellByPosition(0, 1), uno::UNO_QUERY); + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xA2->getPropertyValue("FillComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent1, aComplexColor.getThemeColorType()); + { + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rTrans.size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::Tint, rTrans[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(4000), rTrans[0].mnValue); + } + } +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testThemeColor_Shape) +{ + // Given a document with a table style, using theme color with tinting in the A2 cell: + loadFromFile(u"ThemeShapesReference.pptx"); + + // Then make sure that we only import theming info to the doc model if the effects are limited + // to lum mod / off that we can handle (i.e. no tint/shade): + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // check line and fill theme color of shape1 + { + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xShape->getPropertyValue("FillComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + { + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent6, aComplexColor.getThemeColorType()); + + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(2), rTrans.size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, rTrans[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(4000), rTrans[0].mnValue); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumOff, rTrans[1].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(6000), rTrans[1].mnValue); + } + + CPPUNIT_ASSERT(xShape->getPropertyValue("LineComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + { + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent6, aComplexColor.getThemeColorType()); + + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rTrans.size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, rTrans[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(5000), rTrans[0].mnValue); + } + } + // check line and fill theme color of shape2 + { + uno::Reference xComplexColor; + uno::Reference xShape(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape->getPropertyValue("FillComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + { + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent1, aComplexColor.getThemeColorType()); + + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(0), rTrans.size()); + } + + CPPUNIT_ASSERT(xShape->getPropertyValue("LineComplexColor") >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + { + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent1, aComplexColor.getThemeColorType()); + + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rTrans.size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, rTrans[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(7500), rTrans[0].mnValue); + } + } +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testVert270AndTextRot) +{ + // tdf##149551. The document contains a shape with attributes 'rot="720000"' and 'vert="vert270"' + // of the element. Without the fix the simulation of vert270 had overwritten the text + // rotation angle and thus 'rot'="720000" was lost. + loadFromFile(u"tdf149551_vert270AndTextRot.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + + // Without the fix the property "TextRotateAngle" does not exist. + comphelper::SequenceAsHashMap::iterator it = aGeoPropMap.find("TextRotateAngle"); + CPPUNIT_ASSERT(it != aGeoPropMap.end()); + sal_Int32 nAngle; + // MS 720000 clockwise -> ODF -12deg counter-clockwise + it->second >>= nAngle; + CPPUNIT_ASSERT_EQUAL(sal_Int32(-12), nAngle); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTextRot) +{ + // tdf#149551 The document contains a shape with attribute 'rot="720000"' of the element. + // Without fix, the text rotation angle was saved in "TextPreRotateAngle" instead of + // "TextRotateAngle". That resulted in unrotated but sheared text. + loadFromFile(u"tdf149551_TextRot.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + + // Without the fix the property "TextRotateAngle" does not exist. + comphelper::SequenceAsHashMap::iterator it = aGeoPropMap.find("TextRotateAngle"); + CPPUNIT_ASSERT(it != aGeoPropMap.end()); + sal_Int32 nAngle; + // MS 720000 clockwise -> ODF -12deg counter-clockwise + it->second >>= nAngle; + CPPUNIT_ASSERT_EQUAL(sal_Int32(-12), nAngle); + + // Because writing mode is LR_TB, the property "TextPreRotateAngle" may missing, or in case it + // exists, its value must be 0. Without fix it had value -12. + it = aGeoPropMap.find("TextPreRotateAngle"); + if (it != aGeoPropMap.end()) + { + it->second >>= nAngle; + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nAngle); + } +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf113187ConstantArcTo) +{ + loadFromFile(u"tdf113187_arcTo_withoutReferences.pptx"); + + // Get ViewBox of shape + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + + // Without the fix width and height of the ViewBox were 0 and thus the shape was not shown. + auto aViewBox = aGeoPropMap["ViewBox"].get(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3600000), aViewBox.Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3600000), aViewBox.Height); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf125085WordArtFontTheme) +{ + // The font info for the shape is in the theme, the text run has no font settings. + loadFromFile(u"tdf125085_WordArtFontTheme.pptx"); + + // Get shape and its properties + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + + // Make sure shape has correct font and local. + // Without the fix some application defaults were used. + OUString sFontName; + xShapeProps->getPropertyValue("CharFontNameComplex") >>= sFontName; + CPPUNIT_ASSERT_EQUAL(u"Noto Serif Hebrew"_ustr, sFontName); + css::lang::Locale aLocal; + xShapeProps->getPropertyValue("CharLocaleComplex") >>= aLocal; + CPPUNIT_ASSERT_EQUAL(u"IL"_ustr, aLocal.Country); + CPPUNIT_ASSERT_EQUAL(u"he"_ustr, aLocal.Language); +} + +CPPUNIT_TEST_FIXTURE(OoxDrawingmlTest, testTdf125085WordArtFontText) +{ + // The font info for the shape is in the text run inside the shape. + loadFromFile(u"tdf125085_WordArtFontText.pptx"); + + // Get shape and its properties + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + + // Make sure shape has correct font and local. + // Without the fix some application defaults were used. + OUString sFontName; + xShapeProps->getPropertyValue("CharFontNameComplex") >>= sFontName; + CPPUNIT_ASSERT_EQUAL(u"Noto Serif Hebrew"_ustr, sFontName); + css::lang::Locale aLocal; + xShapeProps->getPropertyValue("CharLocaleComplex") >>= aLocal; + CPPUNIT_ASSERT_EQUAL(u"IL"_ustr, aLocal.Country); + CPPUNIT_ASSERT_EQUAL(u"he"_ustr, aLocal.Language); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx new file mode 100644 index 0000000000..415c5fe8d0 --- /dev/null +++ b/oox/qa/unit/export.cxx @@ -0,0 +1,1352 @@ +/* -*- 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 + +using namespace ::com::sun::star; + +namespace +{ +/// Covers ooox/source/export/ fixes. +class Test : public UnoApiXmlTest +{ +public: + Test() + : UnoApiXmlTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testPolylineConnectorPosition) +{ + // Given a document with a group shape and therein a polyline and a connector. + loadFromFile(u"tdf141786_PolylineConnectorInGroup.odt"); + // When saving that to DOCX: + save("Office Open XML Text"); + + // Then make sure polyline and connector have the correct position. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // For child elements of groups in Writer the position has to be adapted to be relative + // to group instead of being relative to anchor. That was missing for polyline and + // connector. + // Polyline: Without fix it would have failed with expected: 0, actual: 1800360 + assertXPath(pXmlDoc, "//wpg:wgp/wps:wsp[1]/wps:spPr/a:xfrm/a:off"_ostr, "x"_ostr, "0"); + // ... failed with expected: 509400, actual: 1229400 + assertXPath(pXmlDoc, "//wpg:wgp/wps:wsp[1]/wps:spPr/a:xfrm/a:off"_ostr, "y"_ostr, "509400"); + + // Connector: Without fix it would have failed with expected: 763200, actual: 2563560 + assertXPath(pXmlDoc, "//wpg:wgp/wps:wsp[3]/wps:spPr/a:xfrm/a:off"_ostr, "x"_ostr, "763200"); + // ... failed with expected: 0, actual: 720000 + assertXPath(pXmlDoc, "//wpg:wgp/wps:wsp[3]/wps:spPr/a:xfrm/a:off"_ostr, "y"_ostr, "0"); + // Polyline and connector were shifted 1800360EMU right, 720000EMU down. +} + +CPPUNIT_TEST_FIXTURE(Test, testRotatedShapePosition) +{ + // Given a document with a group shape and therein a rotated custom shape. + loadFromFile(u"tdf141786_RotatedShapeInGroup.odt"); + + // FIXME: validation error in OOXML export: Errors: 3 + skipValidation(); + + // When saving that to DOCX: + save("Office Open XML Text"); + + // Then make sure the rotated child shape has the correct position. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // For a group itself and for shapes outside of groups, the position calculation is done in + // DocxSdrExport. For child elements of groups it has to be done in + // DrawingML::WriteShapeTransformation(), but was missing. + // Without fix it would have failed with expected: 469440, actual: 92160 + // The shape was about 1cm shifted up and partly outside its group. + assertXPath(pXmlDoc, "//wpg:wgp/wps:wsp[1]/wps:spPr/a:xfrm/a:off"_ostr, "y"_ostr, "469440"); +} + +CPPUNIT_TEST_FIXTURE(Test, testDmlGroupshapePolygon) +{ + // Given a document with a group shape, containing a single polygon child shape: + loadFromFile(u"dml-groupshape-polygon.docx"); + + // FIXME: validation error in OOXML export: Errors: 9 + skipValidation(); + + // When saving that to DOCX: + save("Office Open XML Text"); + + // Then make sure that the group shape, the group shape's child size and the child shape's size + // match: + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:ext"_ostr, "cx"_ostr, "5328360"); + // Without the accompanying fix in place, this test would have failed, the element was + // not written. + assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:chExt"_ostr, "cx"_ostr, "5328360"); + assertXPath(pXmlDoc, "//wps:spPr/a:xfrm/a:ext"_ostr, "cx"_ostr, "5328360"); +} + +CPPUNIT_TEST_FIXTURE(Test, testCustomShapeArrowExport) +{ + // Given a document with a few different kinds of arrow shapes in it: + loadFromFile(u"tdf142602_CustomShapeArrows.odt"); + + // FIXME: validation error in OOXML export: Errors: 11 + skipValidation(); + + // When saving that to DOCX: + save("Office Open XML Text"); + + // Then the shapes should retain their correct control values. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // Without the fix the output OOXML would have no tags in it. + + // Right arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "rightArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 46321"); + + // Left arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "leftArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 52939"); + + // Down arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "downArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 59399"); + + // Up arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "upArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 63885"); + + // Left-right arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "leftRightArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 53522"); + + // Up-down arrow + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "upDownArrow"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 50000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 62743"); + + // Right arrow callout + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "rightArrowCallout"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 25002"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 25000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]"_ostr, + "fmla"_ostr, "val 25052"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]"_ostr, + "fmla"_ostr, "val 66667"); + + // Left arrow callout + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "leftArrowCallout"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 25002"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 25000"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]"_ostr, + "fmla"_ostr, "val 25057"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]"_ostr, + "fmla"_ostr, "val 66673"); + + // Down arrow callout + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "downArrowCallout"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 29415"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 29413"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]"_ostr, + "fmla"_ostr, "val 16667"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]"_ostr, + "fmla"_ostr, "val 66667"); + + // Up arrow callout + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom"_ostr, + "prst"_ostr, "upArrowCallout"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]"_ostr, + "fmla"_ostr, "val 31033"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]"_ostr, + "fmla"_ostr, "val 31030"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]"_ostr, + "fmla"_ostr, "val 16667"); + assertXPath(pXmlDoc, + "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/" + "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]"_ostr, + "fmla"_ostr, "val 66660"); +} + +CPPUNIT_TEST_FIXTURE(Test, testCameraRevolutionGrabBag) +{ + // Given a PPTX file that contains camera revolution (rotation around z axis) applied shapes + loadFromFile(u"camera-rotation-revolution-nonwps.pptx"); + + // When saving that document: + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // Then make sure the revolution is exported without a problem: + // First shape textbox: + assertXPath(pXmlDoc, "//p:sp[1]/p:spPr/a:scene3d/a:camera/a:rot"_ostr, "rev"_ostr, "5400000"); + + // Second shape rectangle: + assertXPath(pXmlDoc, "//p:sp[2]/p:spPr/a:scene3d/a:camera/a:rot"_ostr, "rev"_ostr, "18300000"); + + // Make sure Shape3DProperties don't leak under txBody + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 + // - Actual : 1 + // - In <>, XPath '//p:sp[1]/p:txBody/a:bodyPr/a:scene3d/a:camera/a:rot' number of nodes is incorrect + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:bodyPr/a:scene3d/a:camera/a:rot"_ostr, 0); + assertXPath(pXmlDoc, "//p:sp[2]/p:txBody/a:bodyPr/a:scene3d/a:camera/a:rot"_ostr, 0); +} + +CPPUNIT_TEST_FIXTURE(Test, testReferToTheme) +{ + // Given a PPTX file that contains references to a theme: + loadFromFile(u"refer-to-theme.pptx"); + + // When saving that document: + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // Then make sure the shape text color is a scheme color: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - XPath '//p:sp/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr' number of nodes is incorrect + // i.e. the element was not written. + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr"_ostr, + "val"_ostr, "accent1"); + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumMod"_ostr, + 0); + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumOff"_ostr, + 0); + + // Second shape: lighter color: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - XPath '//p:sp[2]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr' number of nodes is incorrect + // i.e. the effects case did not write scheme colors. + assertXPath(pXmlDoc, "//p:sp[2]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr"_ostr, + "val"_ostr, "accent1"); + assertXPath(pXmlDoc, "//p:sp[2]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumMod"_ostr, + "val"_ostr, "40000"); + assertXPath(pXmlDoc, "//p:sp[2]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumOff"_ostr, + "val"_ostr, "60000"); + + // Third shape, darker color: + assertXPath(pXmlDoc, "//p:sp[3]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr"_ostr, + "val"_ostr, "accent1"); + assertXPath(pXmlDoc, "//p:sp[3]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumMod"_ostr, + "val"_ostr, "75000"); + assertXPath(pXmlDoc, "//p:sp[3]/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr/a:lumOff"_ostr, + 0); +} + +CPPUNIT_TEST_FIXTURE(Test, testThemeColor_ShapeFill) +{ + // Given an ODP file that contains references to a theme for shape fill: + loadFromFile(u"ReferenceShapeFill.fodp"); + + // When saving that document: + save("Impress Office Open XML"); + + // Then make sure the shape fill color is a scheme color. + // Note that this was already working from PPTX files via grab-bags, + //so this test intentionally uses an ODP file as input. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + assertXPath(pXmlDoc, "//p:sp[1]/p:spPr/a:solidFill/a:schemeClr"_ostr, "val"_ostr, "accent6"); + assertXPath(pXmlDoc, "//p:sp[1]/p:spPr/a:solidFill/a:schemeClr/a:lumMod"_ostr, "val"_ostr, + "75000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf146690_endParagraphRunPropertiesNewLinesTextSize) +{ + // Given a PPTX file that contains references to a theme: + loadFromFile(u"endParaRPr-newline-textsize.pptx"); + + // When saving that document: + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // Make sure the text size is exported correctly: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 500 + // - Actual : 1800 + // i.e. the endParaRPr 'size' wasn't exported correctly + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p[1]/a:endParaRPr"_ostr, "sz"_ostr, "500"); + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p[2]/a:endParaRPr"_ostr, "sz"_ostr, "500"); + assertXPath(pXmlDoc, "//p:sp[1]/p:txBody/a:p[3]/a:endParaRPr"_ostr, "sz"_ostr, "500"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_endsubpath) +{ + // Given an odp file that contains a non-primitive custom shape with command N + loadFromFile(u"tdf147978_endsubpath.odp"); + + // When saving that document: + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // Then make sure the pathLst has two child elements, + // Without the accompanying fix in place, only one element a:path was exported. + assertXPathChildren(pXmlDoc, "//a:pathLst"_ostr, 2); + // and make sure first path with no stroke, second with no fill + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "stroke"_ostr, "0"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]"_ostr, "fill"_ostr, "none"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_commandA) +{ + // Given an odp file that contains a non-primitive custom shape with command N + loadFromFile(u"tdf147978_enhancedPath_commandA.odp"); + + // When saving that document: + save("Impress Office Open XML"); + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // Then make sure the path has a child element arcTo. Prior to the fix that part of the curve was + // not exported at all. In odp it is a command A. Such does not exist in OOXML and is therefore + // exported as a:lnTo followed by a:arcTo + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:lnTo"_ostr, 2); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, 1); + // And assert its attribute values + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "wR"_ostr, "7200"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "hR"_ostr, "5400"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "stAng"_ostr, "7719588"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "swAng"_ostr, "-5799266"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_commandT) +{ + // The odp file contains a non-primitive custom shape with commands MTZ + loadFromFile(u"tdf147978_enhancedPath_commandT.odp"); + + // Export to pptx had only exported the command M and has used a wrong path size + save("Impress Office Open XML"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // File has draw:viewBox="0 0 216 216" + assertXPath(pXmlDoc, "//a:pathLst/a:path"_ostr, "w"_ostr, "216"); + assertXPath(pXmlDoc, "//a:pathLst/a:path"_ostr, "h"_ostr, "216"); + // Command T is exported as lnTo followed by arcTo. + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:moveTo"_ostr, 1); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:lnTo"_ostr, 1); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, 1); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:close"_ostr, 1); + // And assert its values + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:moveTo/a:pt"_ostr, "x"_ostr, "108"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:moveTo/a:pt"_ostr, "y"_ostr, "162"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:lnTo/a:pt"_ostr, "x"_ostr, "138"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:lnTo/a:pt"_ostr, "y"_ostr, "110"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "wR"_ostr, "108"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "hR"_ostr, "54"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "stAng"_ostr, "18000000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo"_ostr, "swAng"_ostr, "18000000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_commandXY) +{ + // The odp file contains a non-primitive custom shapes with commands XY + loadFromFile(u"tdf147978_enhancedPath_commandXY.odp"); + + // Export to pptx had dropped commands X and Y. + save("Impress Office Open XML"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // File has draw:viewBox="0 0 10 10" + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "w"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "h"_ostr, "10"); + // Shape has M 0 5 Y 5 0 10 5 5 10 F Y 0 5 N M 10 10 X 0 0 + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:moveTo/a:pt"_ostr, "x"_ostr, "0"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:moveTo/a:pt"_ostr, "y"_ostr, "5"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[1]"_ostr, "wR"_ostr, "5"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[1]"_ostr, "hR"_ostr, "5"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[1]"_ostr, "stAng"_ostr, "10800000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[1]"_ostr, "swAng"_ostr, "5400000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[2]"_ostr, "stAng"_ostr, "16200000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[2]"_ostr, "swAng"_ostr, "5400000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[3]"_ostr, "stAng"_ostr, "0"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[3]"_ostr, "swAng"_ostr, "5400000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[4]"_ostr, "stAng"_ostr, "0"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]/a:arcTo[4]"_ostr, "swAng"_ostr, "-5400000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:moveTo/a:pt"_ostr, "x"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:moveTo/a:pt"_ostr, "y"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:arcTo"_ostr, "wR"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:arcTo"_ostr, "hR"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:arcTo"_ostr, "stAng"_ostr, "5400000"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]/a:arcTo"_ostr, "swAng"_ostr, "5400000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_commandHIJK) +{ + // The odp file contains a non-primitive custom shapes with commands H,I,J,K + loadFromFile(u"tdf147978_enhancedPath_commandHIJK.odp"); + + // Export to pptx had dropped commands X and Y. + save("Impress Office Open XML"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // File has draw:viewBox="0 0 80 80" + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "w"_ostr, "80"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "h"_ostr, "80"); + // File uses from back to front J (lighten), I (lightenLess), normal fill, K (darkenLess), + // H (darken). New feature, old versions did not export these at all. + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "fill"_ostr, "lighten"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]"_ostr, "fill"_ostr, "lightenLess"); + assertXPathNoAttribute(pXmlDoc, "//a:pathLst/a:path[3]"_ostr, "fill"_ostr); + assertXPath(pXmlDoc, "//a:pathLst/a:path[4]"_ostr, "fill"_ostr, "darkenLess"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[5]"_ostr, "fill"_ostr, "darken"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf147978_subpath) +{ + // The odp file contains a non-primitive custom shapes with commands H,I,J,K + loadFromFile(u"tdf147978_enhancedPath_subpath.pptx"); + + // Export to pptx had dropped the subpaths. + save("Impress Office Open XML"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // File should have four subpaths with increasing path size + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "w"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "h"_ostr, "10"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]"_ostr, "w"_ostr, "20"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]"_ostr, "h"_ostr, "20"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[3]"_ostr, "w"_ostr, "40"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[3]"_ostr, "h"_ostr, "40"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[4]"_ostr, "w"_ostr, "80"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[4]"_ostr, "h"_ostr, "80"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf100391TextAreaRect) +{ + // The document has a custom shape of type "non-primitive" to trigger the custGeom export + loadFromFile(u"tdf100391_TextAreaRect.odp"); + // When saving to PPTX the textarea rect was set to default instead of using the actual area + save("Impress Office Open XML"); + + // Verify the markup. Without fix the values were l="l", t="t", r="r", b="b" + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + assertXPath(pXmlDoc, "//a:custGeom/a:rect"_ostr, "l"_ostr, "textAreaLeft"); + assertXPath(pXmlDoc, "//a:custGeom/a:rect"_ostr, "t"_ostr, "textAreaTop"); + assertXPath(pXmlDoc, "//a:custGeom/a:rect"_ostr, "r"_ostr, "textAreaRight"); + assertXPath(pXmlDoc, "//a:custGeom/a:rect"_ostr, "b"_ostr, "textAreaBottom"); + // The values are calculated in guides, for example + assertXPath(pXmlDoc, "//a:custGeom/a:gdLst/a:gd[1]"_ostr, "name"_ostr, "textAreaLeft"); + assertXPath(pXmlDoc, "//a:custGeom/a:gdLst/a:gd[1]"_ostr, "fmla"_ostr, "*/ 1440000 w 2880000"); + // The test reflects the state of Apr 2022. It needs to be adapted when export of handles and + // guides is implemented. +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf109169_OctagonBevel) +{ + // The odp file contains an "Octagon Bevel" shape. Such has shading not in commands H,I,J,K + // but shading is generated in ctor of EnhancedCustomShape2d from the Type value. + loadFromFile(u"tdf109169_OctagonBevel.odt"); + + // FIXME: validation error in OOXML export: Errors: 1 + skipValidation(); + + // Export to docx had not written a:fill or a:stroke attributes at all. + save("Office Open XML Text"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + // File should have six subpaths, one with stroke and five with fill + assertXPath(pXmlDoc, "//a:pathLst/a:path[1]"_ostr, "stroke"_ostr, "0"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[2]"_ostr, "fill"_ostr, "darkenLess"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[3]"_ostr, "fill"_ostr, "darken"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[4]"_ostr, "fill"_ostr, "darken"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[5]"_ostr, "fill"_ostr, "lightenLess"); + assertXPath(pXmlDoc, "//a:pathLst/a:path[6]"_ostr, "fill"_ostr, "lighten"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFaultyPathCommandsAWT) +{ + // The odp file contains shapes whose path starts with command A, W, T or L. That is a faulty + // path. LO is tolerant and renders it so that is makes a moveTo to the start point of the arc or + // the end of the line respectively. Export to OOXML does the same now and writes a moveTo + // instead of the normally used lnTo. If a lnTo is written, MS Office shows nothing of the shape. + loadFromFile(u"FaultyPathStart.odp"); + + save("Impress Office Open XML"); + + // Verify the markup: + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // First child of a:path should be a moveTo in all four shapes. + assertXPath(pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"_ostr); + assertXPath(pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"_ostr); + assertXPath(pXmlDoc, "//p:spTree/p:sp[3]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"_ostr); + assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"_ostr); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf148784StretchXY) +{ + // The document has a custom shapes of type "non-primitive" to trigger the custGeom export. + // They use formulas with 'right' and 'bottom'. + // When saving to PPTX the attributes stretchpoint-x and stretchpoint-y were not considered. The + // line at right and bottom edge were positioned inside as if the shape had a square size. + loadFromFile(u"tdf148784_StretchXY.odp"); + save("Impress Office Open XML"); + + // Verify the markup. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + + // x-position of last segment should be same as path width. It was 21600 without fix. + sal_Int32 nWidth + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/@w"_ostr) + .toInt32(); + sal_Int32 nPosX + = getXPathContent( + pXmlDoc, + "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo[4]/a:pt/@x"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchX", nWidth, nPosX); + + // y-position of last segment should be same as path height. It was 21600 without fix. + sal_Int32 nHeight + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/@h"_ostr) + .toInt32(); + sal_Int32 nPosY + = getXPathContent( + pXmlDoc, + "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo[4]/a:pt/@y"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchY", nHeight, nPosY); + + // The test reflects the state of Apr 2022. It needs to be adapted when export of handles and + // guides is implemented. +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf148784StretchCommandQ) +{ + // The document has a custom shapes of type "non-primitive" to trigger the custGeom export. + // They use formulas with 'right' and 'bottom'. + // When saving to PPTX the attributes stretchpoint-x and stretchpoint-y were not considered. + // That results in wrong arcs on the right or bottom side of the shape. + loadFromFile(u"tdf148784_StretchCommandQ.odp"); + save("Impress Office Open XML"); + + // Verify the markup. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + + // x-position of second quadBezTo control should be same as path width. It was 21600 without fix. + sal_Int32 nWidth + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/@w"_ostr) + .toInt32(); + sal_Int32 nPosX + = getXPathContent( + pXmlDoc, + "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:quadBezTo[2]/a:pt/@x"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchX", nWidth, nPosX); + + // y-position of third quadBezTo control should be same as path height. It was 21600 without fix. + sal_Int32 nHeight + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/@h"_ostr) + .toInt32(); + sal_Int32 nPosY + = getXPathContent( + pXmlDoc, + "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:quadBezTo[3]/a:pt/@y"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchY", nHeight, nPosY); + + // The test reflects the state of Apr 2022. It needs to be adapted when export of handles and + // guides is implemented. +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf148784StretchCommandVW) +{ + // The document has a custom shapes of type "non-primitive" to trigger the custGeom export. + // It should not need adaption when export of handles and guides is implemented because it + // has only fixed values in the path. + // When saving to PPTX the attributes stretchpoint-x and stretchpoint-y were not considered. + // That results in circles instead of ellipses. + loadFromFile(u"tdf148784_StretchCommandVW.odp"); + save("Impress Office Open XML"); + + // Verify the markup. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + + // wR of first ArcTo in first shape should be same as path width/2. It was 10800 without fix. + sal_Int32 nHalfWidth + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/@w"_ostr) + .toInt32() + / 2; + sal_Int32 nWR + = getXPathContent( + pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:arcTo[1]/@wR"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchX", nHalfWidth, nWR); + + // hR of first ArcTo in second shape should be same as path height /2. It was 10800 without fix. + sal_Int32 nHalfHeight + = getXPathContent(pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/@h"_ostr) + .toInt32() + / 2; + sal_Int32 nHR + = getXPathContent( + pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:arcTo[1]/@hR"_ostr) + .toInt32(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("StretchY", nHalfHeight, nHR); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf149551VertPadding) +{ + // The document has shape[1] with attribute vert="vert270" and shape[2] with vert="vert". The text + // has paddings lIns="720000"=2cm, tIns="360000"=1cm, rIns="0" and bIns="0". + // After load and save the paddings were rotated and a 90deg text rotation was added. + loadFromFile(u"tdf149551_vert_and_padding.pptx"); + save("Impress Office Open XML"); + + // Verify the markup. The values must be the same as in the original file. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + for (sal_Int32 i = 1; i <= 2; i++) + { + OString sElement = "//p:spTree/p:sp[" + OString::number(i) + "]/p:txBody/a:bodyPr"; + assertXPath(pXmlDoc, sElement, "lIns"_ostr, "720000"); + assertXPath(pXmlDoc, sElement, "tIns"_ostr, "360000"); + assertXPath(pXmlDoc, sElement, "rIns"_ostr, "0"); + assertXPath(pXmlDoc, sElement, "bIns"_ostr, "0"); + assertXPathNoAttribute(pXmlDoc, sElement, "rot"_ostr); + } +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf149538upright) +{ + // The document has a shape with attribute upright="1" in the bodyPr element. On import it is + // emulated by rotating the text area rectangle. On export there should be an upright="1" + // attribute but no 'rot' attribute. Without the fix the 'rot' attribute with values from + // the emulation was written out. + loadFromFile(u"tdf149538_upright.pptx"); + save("Impress Office Open XML"); + + // Verify the markup. The values must be the same as in the original file. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + assertXPath(pXmlDoc, "//p:spTree/p:sp/p:txBody/a:bodyPr"_ostr, "upright"_ostr, "1"); + assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp/p:txBody/a:bodyPr"_ostr, "rot"_ostr); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf151008VertAnchor) +{ + loadFromFile(u"tdf151008_eaVertAnchor.pptx"); + save("Impress Office Open XML"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // The order of the shapes in the file is by name "Right", "Center", "Left", "RightMiddle", + // "CenterMiddle" and "LeftMiddle". I access the shapes here by index, because the XPath is + // easier then. + // As of Sep 2022 LibreOffice does not write the default anchorCtr="0" + // Right + assertXPath(pXmlDoc, "//p:spTree/p:sp[1]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "t"); + assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[1]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr); + // Center + assertXPath(pXmlDoc, "//p:spTree/p:sp[2]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "ctr"); + assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[2]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr); + // Left + assertXPath(pXmlDoc, "//p:spTree/p:sp[3]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "b"); + assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[3]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr); + // RightMiddle + assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "t"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr, "1"); + // CenterMiddle + assertXPath(pXmlDoc, "//p:spTree/p:sp[5]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "ctr"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[5]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr, "1"); + // LeftMiddle + assertXPath(pXmlDoc, "//p:spTree/p:sp[6]/p:txBody/a:bodyPr"_ostr, "anchor"_ostr, "b"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[6]/p:txBody/a:bodyPr"_ostr, "anchorCtr"_ostr, "1"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkBitmapFill) +{ + // The document has a Fontwork shape with bitmap fill. + loadFromFile(u"tdf128568_FontworkBitmapFill.odt"); + + // FIXME: validation error in OOXML export: Errors: 1 + // Attribute ID is not allowed in element v:shape + skipValidation(); + + // Saving that to DOCX: + save("Office Open XML Text"); + + // Make sure it is exported to VML and has no txbxContent but a textpath element. Without fix it + // was exported as DML 'abc transform', but that is not able to use bitmap fill in Word. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + assertXPath(pXmlDoc, "//mc:alternateContent"_ostr, 0); + assertXPath(pXmlDoc, "//v:shape/v:textbox/v:txbxContent"_ostr, 0); + assertXPath(pXmlDoc, "//v:shape/v:textpath"_ostr, 1); + + // Without fix the bitmap was referenced by v:imagedata element. But that produces a picture + // in Word not a WordArt shape. Instead a v:fill has to be used. + assertXPath(pXmlDoc, "//v:shape/v:imagedata"_ostr, 0); + assertXPath(pXmlDoc, "//v:shape/v:fill"_ostr, 1); + assertXPath(pXmlDoc, "//v:shape/v:fill[@r:id]"_ostr, 1); + + // The fill is set to 'stretched' in LO, that is type="frame" in VML. That was not implemented + // in VML export. + assertXPath(pXmlDoc, "//v:shape/v:fill"_ostr, "type"_ostr, "frame"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkFontProperties) +{ + // The document has five Fontwork shapes. They have bitmap fill and thus are exported to VML. + // They differ in font properties e.g. font weight and character spacing. + loadFromFile(u"tdf128568_FontworkFontProperties.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Make sure the style attribute of the textpath element has the needed items. Without fix only + // font-family and font-size were written. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + OUString sStyle; + // bold + sStyle = getXPath(pXmlDoc, "(//v:shape)[1]/v:textpath"_ostr, "style"_ostr); + CPPUNIT_ASSERT(sStyle.indexOf("font-weight:bold") > -1); + // italic + sStyle = getXPath(pXmlDoc, "(//v:shape)[2]/v:textpath"_ostr, "style"_ostr); + CPPUNIT_ASSERT(sStyle.indexOf("font-style:italic") > -1); + // character spacing 'very loose', 150 * 655, see escherex.cxx + sStyle = getXPath(pXmlDoc, "(//v:shape)[3]/v:textpath"_ostr, "style"_ostr); + CPPUNIT_ASSERT(sStyle.indexOf("v-text-spacing:98250f") > -1); + // character spacing 'tight', 90 * 655, see escherex.cxx + sStyle = getXPath(pXmlDoc, "(//v:shape)[4]/v:textpath"_ostr, "style"_ostr); + CPPUNIT_ASSERT(sStyle.indexOf("v-text-spacing:58950f") > -1); + // same letter heights + sStyle = getXPath(pXmlDoc, "(//v:shape)[5]/v:textpath"_ostr, "style"_ostr); + CPPUNIT_ASSERT(sStyle.indexOf("v-same-letter-heights:t") > -1); +} + +CPPUNIT_TEST_FIXTURE(Test, testVMLFontworkSlantUp) +{ + // The document has a Fontwork shape type 'textSlantUp' (172). When exporting to docx, Word does + // not recognize its markup as preset WordArt, because the used markup differs from what Word + // expects for this type of shape. As a result Word saves the shape as having custom geometry + // and such is not understand by LibreOffice. + loadFromFile(u"tdf153296_VML_export_SlantUp.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. I could identify the following two problems to hinder Word from + // accepting the markup. There might exist more problems. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // Make sure a element exists and has an o:connecttype attribute + assertXPath(pXmlDoc, "//v:shapetype/v:path"_ostr, 1); + assertXPath(pXmlDoc, "//v:shapetype/v:path[@o:connecttype]"_ostr, 1); + + // Make sure the handle position is written without reference to a formula + OUString sPosition = getXPath(pXmlDoc, "//v:h"_ostr, "position"_ostr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), sPosition.indexOf("@")); + CPPUNIT_ASSERT_EQUAL(OUString("topLeft,#0"), sPosition); +} + +CPPUNIT_TEST_FIXTURE(Test, testVMLFontworkArchUp) +{ + // The document has a Fontwork shape type 'textArchUp' (172). When exporting to docx, the shape + // was not exported as VML Fontwork but as a rectangle. + loadFromFile(u"tdf153296_VML_export_ArchUpCurve.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // Make sure there is no element + assertXPath(pXmlDoc, "//v:rect"_ostr, 0); + // ..., but a element with subelement + assertXPath(pXmlDoc, "//v:shapetype/v:textpath"_ostr, 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testVMLAdjustmentExport) +{ + // The document has a Fontwork shape type 'textCirclePour' (150). When exporting to docx, the + // adjustment values were not exported at all. + loadFromFile(u"tdf153246_VML_export_Fontwork_Adjustment.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // Make sure an "adj" attribute exists + assertXPath(pXmlDoc, "//v:shape[@adj]"_ostr, 1); + // ... and has the correct values + OUString sAdjustments = getXPath(pXmlDoc, "//v:shape"_ostr, "adj"_ostr); + sal_Int32 nTokenStart = 0; + OUString sAngle = sAdjustments.getToken(0, ',', nTokenStart); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(-7341733), sAngle.toInt32(), 2); + OUString sRadius = sAdjustments.copy(nTokenStart); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(5296), sRadius.toInt32(), 2); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkDirectColor) +{ + // The document has a Fontwork shape with fill #2e8b57 plus 60% transparency and line color + // #ff7f50 with 20% transparency. When exporting to docx, line color was not exported at all + // and fill color was replaced with character color. + loadFromFile(u"tdf51195_Fontwork_DirectColor.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + static constexpr OString sElement = "//w:txbxContent/w:p/w:r/w:rPr/"_ostr; + + // Make sure the fallback in has correct value. + assertXPath(pXmlDoc, sElement + "w:color", "val"_ostr, "2E8B57"); + + // ... and exists and has correct values. + assertXPath(pXmlDoc, sElement + "w14:textOutline", 1); + assertXPath(pXmlDoc, sElement + "w14:textOutline/w14:solidFill/w14:srgbClr", "val"_ostr, + "ff7f50"); + assertXPath(pXmlDoc, sElement + "w14:textOutline/w14:solidFill/w14:srgbClr/w14:alpha", + "val"_ostr, "20000"); + assertXPath(pXmlDoc, sElement + "w14:textOutline/w14:round", 1); + + // ... and w14:textFill exists and has correct values. + assertXPath(pXmlDoc, sElement + "w14:textFill", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:srgbClr", "val"_ostr, "2e8b57"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:srgbClr/w14:alpha", "val"_ostr, + "60000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkThemeColor) +{ + // The document has a Fontwork shape with fill theme color 'lt2' and 50% darker, and a Fontwork + // shape with theme color 'dk2' and 40% lighter. When exporting to docx, fill color was not + // exported as theme color at all, and it was replaced with character color. + loadFromFile(u"tdf51195_Fontwork_ThemeColor.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // shape with 'darker' + OString sElement = "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure the fallback in has correct values + assertXPath(pXmlDoc, sElement + "w:color", "val"_ostr, "948A54"); + assertXPath(pXmlDoc, sElement + "w:color", "themeColor"_ostr, "light2"); + assertXPath(pXmlDoc, sElement + "w:color", "themeShade"_ostr, "80"); + + // ... and w14:textFill exists and has correct values. + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:schemeClr", "val"_ostr, "bg2"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:schemeClr/w14:lumMod", + "val"_ostr, "50000"); + + // shape with 'lighter' + sElement = "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/" + "a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/w:rPr/"_ostr; + + // Make sure the fallback in has correct values + assertXPath(pXmlDoc, sElement + "w:color", "val"_ostr, "558ED5"); + assertXPath(pXmlDoc, sElement + "w:color", "themeColor"_ostr, "dark2"); + assertXPath(pXmlDoc, sElement + "w:color", "themeTint"_ostr, "99"); + + // ... and w14:textFill exists and has correct values. + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:schemeClr", "val"_ostr, "tx2"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:schemeClr/w14:lumMod", + "val"_ostr, "60000"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:solidFill/w14:schemeClr/w14:lumOff", + "val"_ostr, "40000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkDistance) +{ + // LO ignores 'Spacing to Borders' of the 'Text Attributes' for Fontwork shapes. Word interprets + // them. Make sure we force them to zero on export to docx, otherwise Word might wrap the text. + loadFromFile(u"tdf51195_Fontwork_Distance.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + assertXPathAttrs(pXmlDoc, + "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:bodyPr"_ostr, + { { "lIns", "0" }, { "rIns", "0" }, { "tIns", "0" }, { "bIns", "0" } }); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkLinGradientRGBColor) +{ + // The document has a Fontwork shape with UI settings: linear gradient fill with angle 330deg, + // start color #ffff00 (Yellow) with 'Intensity' 80%, end color #4682B4 (Steel Blue), Transition + // Start 25% and solid transparency 30%. + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_linearGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + // 330deg gradient rotation = 120deg color transition direction + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:lin", "ang"_ostr, "7200000"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:lin", "scaled"_ostr, "0"); + + // Make sure the color stops have correct position and color + // The 'intensity' property in the UI has a different algorithm than the 'lumMod' attribute in + // OOXML. Therefore it cannot be exported as 'lumMod' but need to be incorporated into the color. + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:srgbClr", "val"_ostr, "cccc00"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:srgbClr/w14:alpha", "val"_ostr, "30000"); + + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "25000"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:srgbClr", "val"_ostr, "cccc00"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:srgbClr/w14:alpha", "val"_ostr, "30000"); + + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "100000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr", "val"_ostr, "4682b4"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr/w14:alpha", "val"_ostr, "30000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkAxialGradientTransparency) +{ + // The document has a Fontwork shape with UI settings: solid fill theme color Accent3 25% darker, + // Transparency gradient Type Axial with Angle 160deg, Transition start 40%, + // Start value 5%, End value 90% + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_axialGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + // 160deg gradient rotation = 290deg (360deg-160deg+90deg) color transition direction + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:lin", "ang"_ostr, "17400000"); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:lin", "scaled"_ostr, "0"); + + // Make sure the color stops have correct position and color + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + // gradient is in transparency, color is always the same. + for (char ch = '1'; ch <= '3'; ++ch) + { + assertXPath(pXmlDoc, sElement + "w14:gs[" + OStringChar(ch) + "]/w14:schemeClr", "val"_ostr, + "accent3"); + assertXPath(pXmlDoc, sElement + "w14:gs[" + OStringChar(ch) + "]/w14:schemeClr/w14:lumMod", + "val"_ostr, "75000"); + } + // transparency values are not exactly like in UI because converting through rgb-color. + // border 40% in UI means 20% on each side. + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "20000"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:schemeClr/w14:alpha", "val"_ostr, "89800"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "50000"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:schemeClr/w14:alpha", "val"_ostr, "4710"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "80000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:alpha", "val"_ostr, "89800"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkRadialGradient) +{ + // The document has a Fontwork shape with UI settings: gradient fill, Type radial, + // From Color #40E0D0, To Color #FF0000, Center x|y 75%|20%, no transparency + // Transition start 10% + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_radialGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path", "path"_ostr, "circle"); + assertXPathAttrs(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path/w14:fillToRect", + { { "l", "75000" }, { "t", "20000" }, { "r", "25000" }, { "b", "80000" } }); + + // Make sure the color stops have correct position and color + // The first stop is duplicated to force Word to render the gradient same as LO. + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:srgbClr", "val"_ostr, "ff0000"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:srgbClr", "val"_ostr, "ff0000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "90000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr", "val"_ostr, "40e0d0"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkEllipticalGradient) +{ + // The document has a Fontwork shape with UI settings: solid fill, Color #00008B (deep blue), + // transparency gradient type Ellipsoid, Center x|y 50%|50%, Transition Start 50%, + // Start 70%, End 0%. + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_ellipticalGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path", "path"_ostr, "circle"); + assertXPathAttrs(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path/w14:fillToRect", + { { "l", "50000" }, { "t", "50000" }, { "r", "50000" }, { "b", "50000" } }); + + // Make sure the color stops have correct position and color + // transparency values are not exactly like in UI because converting through rgb-color. + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:srgbClr", "val"_ostr, "00008b"); + // stop is duplicated to force Word to same rendering as LO does. + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:srgbClr", "val"_ostr, "00008b"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "50000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr", "val"_ostr, "00008b"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr/w14:alpha", "val"_ostr, "69800"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkSquareGradient) +{ + // The document has a Fontwork shape with UI settings: gradient fill Type "Square (Quadratic)", + // From Color #4963ef 40%, To Color #ffff6e 90%, Center x|y 100%|50%, + // no transparency + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_squareGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path", "path"_ostr, "rect"); + assertXPathAttrs(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path/w14:fillToRect", + { { "l", "100000" }, { "t", "50000" }, { "r", "0" }, { "b", "50000" } }); + + // Make sure the color stops have correct position and color + // The 'intensity' property in the UI has a different algorithm than the 'lumMod' attribute in + // OOXML. Therefore it cannot be exported as 'lumMod' but need to be incorporated into the color. + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:srgbClr", "val"_ostr, "e6e663"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:srgbClr", "val"_ostr, "e6e663"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "100000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:srgbClr", "val"_ostr, "1d4860"); +} + +CPPUNIT_TEST_FIXTURE(Test, testFontworkRectGradient) +{ + // The document has a Fontwork shape with UI settings: solid color theme Accent 4 60% lighter, + // transparency gradient Type "Rectangular", Center x|y 50%|50%, Transition start 10%, + // Start value 70%, End value 5%. + // Without fix the gradient was not exported at all. + loadFromFile(u"tdf51195_Fontwork_rectGradient.fodt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + + // Save to DOCX: + save("Office Open XML Text"); + + // Examine the saved markup. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // path to shape text run properties + OString sElement = "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/" + "wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/w:txbxContent/w:p/w:r/" + "w:rPr/"_ostr; + + // Make sure w14:textFill and w14:gradFill elements exist with child elements + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst", 1); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:gsLst/w14:gs", 3); + assertXPath(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path", "path"_ostr, "rect"); + assertXPathAttrs(pXmlDoc, sElement + "w14:textFill/w14:gradFill/w14:path/w14:fillToRect", + { { "l", "50000" }, { "t", "50000" }, { "r", "50000" }, { "b", "50000" } }); + + // Make sure the color stops have correct position and color + // transparency values are not exactly like in UI because converting through rgb-color. + sElement += "w14:textFill/w14:gradFill/w14:gsLst/"; + assertXPath(pXmlDoc, sElement + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:schemeClr", "val"_ostr, "accent4"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:schemeClr/w14:lumMod", "val"_ostr, "40000"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:schemeClr/w14:lumOff", "val"_ostr, "60000"); + assertXPath(pXmlDoc, sElement + "w14:gs[1]/w14:schemeClr/w14:alpha", "val"_ostr, "4710"); + // The first stop is duplicated to force Word to render the gradient same as LO. + assertXPath(pXmlDoc, sElement + "w14:gs[2]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:schemeClr", "val"_ostr, "accent4"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:schemeClr/w14:lumMod", "val"_ostr, "40000"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:schemeClr/w14:lumOff", "val"_ostr, "60000"); + assertXPath(pXmlDoc, sElement + "w14:gs[2]/w14:schemeClr/w14:alpha", "val"_ostr, "4710"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]", "pos"_ostr, "90000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr", "val"_ostr, "accent4"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:lumMod", "val"_ostr, "40000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:lumOff", "val"_ostr, "60000"); + assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:alpha", "val"_ostr, "69800"); +} + +CPPUNIT_TEST_FIXTURE(Test, testThemeColorTransparency) +{ + // The document has first a Fontwork shape with solid fill theme color with transparency and + // outline transparency and second a textbox with character transparency. + // Without fix the transparency was not written to file. + loadFromFile(u"tdf139618_ThemeColorTransparency.pptx"); + + save("Impress Office Open XML"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + + // Make sure a:alpha is written for line color and for fill color. + // Make sure fill color is a schemeClr. + OString sElement = "/p:sld/p:cSld/p:spTree/p:sp[1]/p:txBody/a:p/a:r/a:rPr/"_ostr; + assertXPath(pXmlDoc, sElement + "a:ln/a:solidFill/a:srgbClr/a:alpha", "val"_ostr, "25000"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr", "val"_ostr, "accent1"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumMod", "val"_ostr, "60000"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumOff", "val"_ostr, "40000"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:alpha", "val"_ostr, "35000"); + + // Make sure a:alpha is written for characters and fill color is a schemeClr. + sElement = "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p/a:r/a:rPr/"_ostr; + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr", "val"_ostr, "accent4"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumMod", "val"_ostr, "75000"); + assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:alpha", "val"_ostr, "20000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testThemeFontTypeface) +{ + // Saving the document had produced a file which PowerPoint wants to repair. The mandatory + // attribute 'typeface' was missing in the elements. + + loadFromFile(u"tdf155412_typeface.pptx"); + + save("Impress Office Open XML"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/theme/theme1.xml"); + + // Make sure typeface is written. + OString sElement = "/a:theme/a:themeElements/a:fontScheme/"_ostr; + assertXPath(pXmlDoc, sElement + "a:majorFont/a:ea", "typeface"_ostr, ""); + assertXPath(pXmlDoc, sElement + "a:minorFont/a:ea", "typeface"_ostr, ""); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf157289CircularArrowExport) +{ + // The document has a custom shape of type "circular-arrow". Such uses a B command where + // the ellipse bounding box is defined by bottom-right vertex first and then top-left vertex. + // When saving to PPTX this had resulted in negative radii for the ellipse. + loadFromFile(u"tdf157289_circularArrow_export.fodp"); + save("Impress Office Open XML"); + + // Verify the markup. Both wR and hR must be positive. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo[1]"_ostr, "wR"_ostr, "6750"); + assertXPath(pXmlDoc, "//a:pathLst/a:path/a:arcTo[1]"_ostr, "hR"_ostr, "6750"); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/mathml.cxx b/oox/qa/unit/mathml.cxx new file mode 100644 index 0000000000..3e1b8c55b8 --- /dev/null +++ b/oox/qa/unit/mathml.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +using namespace ::com::sun::star; + +/// oox mathml tests. +class OoxMathmlTest : public UnoApiTest +{ +public: + OoxMathmlTest() + : UnoApiTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(OoxMathmlTest, testImportCharacters) +{ + // Without the accompanying fix in place, this failed with an assertion failure on import. + loadFromFile(u"import-characters.pptx"); +} + +CPPUNIT_TEST_FIXTURE(OoxMathmlTest, testImportMce) +{ + loadFromFile(u"import-mce.pptx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // Without the accompanying fix in place, this failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. both the math object and its replacement image was imported, as two separate objects. + CPPUNIT_ASSERT_EQUAL(static_cast(1), xDrawPage->getCount()); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/mcgr.cxx b/oox/qa/unit/mcgr.cxx new file mode 100644 index 0000000000..edb9b9bf76 --- /dev/null +++ b/oox/qa/unit/mcgr.cxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Covers tests for multi-color gradient (MCGR) feature, available since LO 7.6.0. +class TestMCGR : public UnoApiXmlTest +{ +public: + TestMCGR() + : UnoApiXmlTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(TestMCGR, testFontworkColorGradient) +{ + // Given a document with three-color gradient on a Fontwork. + loadFromFile(u"MCGR_FontworkColorGradient.fodp"); + // Save it to PPTX + save("Impress Office Open XML"); + // And make sure a multi-color gradient fill is exported. + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + // linear gradient with 30deg angle + assertXPath(pXmlDoc, "//a:r/a:rPr/a:gradFill/a:lin"_ostr, "ang"_ostr, "3600000"); + // three color stops, no transparency + static constexpr OString sPath = "//a:r/a:rPr/a:gradFill/a:gsLst/"_ostr; + assertXPath(pXmlDoc, sPath + "a:gs", 3); + assertXPath(pXmlDoc, sPath + "a:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sPath + "a:gs[1]/a:srgbClr", "val"_ostr, "ff1493"); + assertXPath(pXmlDoc, sPath + "a:gs[2]", "pos"_ostr, "30000"); + assertXPath(pXmlDoc, sPath + "a:gs[2]/a:srgbClr", "val"_ostr, "ffff00"); + assertXPath(pXmlDoc, sPath + "a:gs[3]", "pos"_ostr, "100000"); + assertXPath(pXmlDoc, sPath + "a:gs[3]/a:srgbClr", "val"_ostr, "00ffff"); +} + +CPPUNIT_TEST_FIXTURE(TestMCGR, testFontworkColorGradientWord) +{ + // Fontwork is handled different in Word than in PowerPoint documents. So we need a separate + // test for a text document. + // Given a document with three-color gradient on a Fontwork. + loadFromFile(u"MCGR_FontworkColorGradient.fodt"); + // Save it to DOCX + save("Office Open XML Text"); + // And make sure a multi-color gradient fill is exported. + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + // linear gradient with 30deg angle + assertXPath(pXmlDoc, "//w14:lin"_ostr, "ang"_ostr, "3600000"); + // three color stops, no transparency + static constexpr OString sPath = "//w14:gradFill/w14:gsLst/"_ostr; + assertXPath(pXmlDoc, sPath + "w14:gs", 3); + assertXPath(pXmlDoc, sPath + "w14:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sPath + "w14:gs[1]/w14:srgbClr", "val"_ostr, "ff1493"); + assertXPath(pXmlDoc, sPath + "w14:gs[2]", "pos"_ostr, "30000"); + assertXPath(pXmlDoc, sPath + "w14:gs[2]/w14:srgbClr", "val"_ostr, "ffff00"); + assertXPath(pXmlDoc, sPath + "w14:gs[3]", "pos"_ostr, "100000"); + assertXPath(pXmlDoc, sPath + "w14:gs[3]/w14:srgbClr", "val"_ostr, "00ffff"); +} + +CPPUNIT_TEST_FIXTURE(TestMCGR, testTdf155825_SourcOffsetRangeDifferent) +{ + // Color gradient has offset range [0,0.8] and transparency gradient has offset range [0,1]. + loadFromFile(u"tdf155825_MCGR_SourceOffsetRangeDifferent.fodp"); + // Save it to PPTX + // Without fix, a debug-build would have crashed in oox/source/export/drawingml.cxx from + // assert(false && "oox::WriteGradientFill: non-synchronized gradients (!)"); + save("Impress Office Open XML"); +} + +CPPUNIT_TEST_FIXTURE(TestMCGR, testStepCount) +{ + // Given a document with two-color gradient with StepCount 4. + loadFromFile(u"tdf155852_MCGR_StepCount4.fodp"); + // Save it to PPTX + save("Impress Office Open XML"); + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + + // Without the fix the colors in the sections were wrong. And when opening a file with StepCount + // and saving it immediately to pptx, a continuous gradient might be produced. + + static constexpr OString sPath = "//a:gradFill/a:gsLst/"_ostr; + // The default way of load and save would have produced 2 stops, but we need start stop, end stop + // and 3*2 inner stops. + assertXPath(pXmlDoc, sPath + "a:gs", 8); + // A sharp color changes needs a pair of two stops with same offset. + assertXPath(pXmlDoc, sPath + "a:gs[@pos='25000']", 2); + assertXPath(pXmlDoc, sPath + "a:gs[@pos='50000']", 2); + assertXPath(pXmlDoc, sPath + "a:gs[@pos='75000']", 2); + // Without fix the color was 808080. + assertXPath(pXmlDoc, sPath + "a:gs[@pos='75000'][1]/a:srgbClr", "val"_ostr, "55aaaa"); + // Without fix the color was 40bfbf, producing a gradient in the last segment. + assertXPath(pXmlDoc, sPath + "a:gs[@pos='75000'][2]/a:srgbClr", "val"_ostr, "00ffff"); +} + +CPPUNIT_TEST_FIXTURE(TestMCGR, testAxialColorLinearTrans) +{ + // Given a document with a shape with axial color gradient from inside red to outside cyan and + // two-stop linear transparency gradient from start 80% to end 0%. + loadFromFile(u"tdf155827_MCGR_AxialColorLinearTrans.fodp"); + // Save it to PPTX + save("Impress Office Open XML"); + // OOXML has transparency together with color. Transparency is stored as opacity. + // Expected: pos 0 #00ffff 20000, pos 50000 #ff0000 60000, pos 100000 #00ffff 100000. + // Because of conversion through gray color the opacity values are not exact. If rounding + // method will be changed, the test needs to be adjusted. + + xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml"); + static constexpr OString sPath = "//a:gradFill/a:gsLst/"_ostr; + assertXPath(pXmlDoc, sPath + "a:gs", 3); + assertXPath(pXmlDoc, sPath + "a:gs[1]", "pos"_ostr, "0"); + assertXPath(pXmlDoc, sPath + "a:gs[1]/a:srgbClr", "val"_ostr, "00ffff"); + assertXPath(pXmlDoc, sPath + "a:gs[1]/a:srgbClr/a:alpha", "val"_ostr, "20000"); + assertXPath(pXmlDoc, sPath + "a:gs[2]", "pos"_ostr, "50000"); + assertXPath(pXmlDoc, sPath + "a:gs[2]/a:srgbClr", "val"_ostr, "ff0000"); + assertXPath(pXmlDoc, sPath + "a:gs[2]/a:srgbClr/a:alpha", "val"_ostr, "60396"); + assertXPath(pXmlDoc, sPath + "a:gs[3]", "pos"_ostr, "100000"); + assertXPath(pXmlDoc, sPath + "a:gs[3]/a:srgbClr", "val"_ostr, "00ffff"); + // no element for default val="100000" + assertXPath(pXmlDoc, sPath + "a:gs[3]/a:srgbClr/a:alpha", 0); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx new file mode 100644 index 0000000000..490c81bf9b --- /dev/null +++ b/oox/qa/unit/shape.cxx @@ -0,0 +1,834 @@ +/* -*- 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 + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Gets one child of xShape, which one is specified by nIndex. +uno::Reference getChildShape(const uno::Reference& xShape, + sal_Int32 nIndex) +{ + uno::Reference xGroup(xShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xGroup.is()); + + CPPUNIT_ASSERT(xGroup->getCount() > nIndex); + + uno::Reference xRet(xGroup->getByIndex(nIndex), uno::UNO_QUERY); + CPPUNIT_ASSERT(xRet.is()); + + return xRet; +} +} + +/// oox shape tests. +class OoxShapeTest : public UnoApiTest +{ +public: + OoxShapeTest() + : UnoApiTest("/oox/qa/unit/data/") + { + } + uno::Reference getShapeByName(std::u16string_view aName); +}; + +uno::Reference OoxShapeTest::getShapeByName(std::u16string_view aName) +{ + uno::Reference xRet; + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i) + { + uno::Reference xShape(xDrawPage->getByIndex(i), uno::UNO_QUERY); + if (xShape->getName() == aName) + { + xRet.set(xShape, uno::UNO_QUERY); + break; + } + } + + return xRet; +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testGroupTransform) +{ + loadFromFile(u"tdf141463_GroupTransform.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape(getChildShape(xGroup, 0), uno::UNO_QUERY); + uno::Reference xPropSet(xShape, uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed in several properties. + + sal_Int32 nAngle; + xPropSet->getPropertyValue("ShearAngle") >>= nAngle; + // Failed with - Expected: 0 + // - Actual : -810 + // i.e. the shape was sheared although shearing does not exist in oox + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nAngle); + + xPropSet->getPropertyValue("RotateAngle") >>= nAngle; + // Failed with - Expected: 26000 (is in 1/100deg) + // - Actual : 26481 (is in 1/100deg) + // 100deg in PowerPoint UI = 360deg - 100deg in LO. + CPPUNIT_ASSERT_EQUAL(sal_Int32(26000), nAngle); + + sal_Int32 nActual = xShape->getSize().Width; + // The group has ext.cy=2880000 and chExt.cy=4320000 resulting in Y-scale=2/3. + // The child has ext 2880000 x 1440000. Because of rotation angle 80deg, the Y-scale has to be + // applied to the width, resulting in 2880000 * 2/3 = 1920000EMU = 5333Hmm + // ToDo: Expected value currently 1 off. + // Failed with - Expected: 5332 + // - Actual : 5432 + CPPUNIT_ASSERT_EQUAL(sal_Int32(5332), nActual); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testMultipleGroupShapes) +{ + loadFromFile(u"multiple-group-shapes.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. the 2 group shapes from the document were imported as a single one. + CPPUNIT_ASSERT_EQUAL(static_cast(2), xDrawPage->getCount()); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testCustomshapePosition) +{ + loadFromFile(u"customshape-position.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + + sal_Int32 nY{}; + xShape->getPropertyValue("VertOrientPosition") >>= nY; + // 581025 in the document. + sal_Int32 nExpected = rtl::math::round(581025.0 / 360); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1614 + // - Actual : 0 + // i.e. the position of the shape was lost on import due to the rounded corners. + CPPUNIT_ASSERT_EQUAL(nExpected, nY); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf125582_TextOnCircle) +{ + // The document contains a shape with a:prstTxWarp="textCircle" with two paragraphs. + // PowerPoint aligns the bottom of the text with the path, LO had aligned the middle of the + // text with the path, which resulted in smaller text. + loadFromFile(u"tdf125582_TextOnCircle.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xPropSet(xShape, uno::UNO_QUERY); + + // BoundRect of Fontwork shape depends on dpi. + if (IsDefaultDPI()) + { + SdrObjCustomShape& rSdrCustomShape( + static_cast(*SdrObject::getSdrObjectFromXShape(xShape))); + // Without the fix in place width was 3639, but should be 4784 for 96dpi. + tools::Rectangle aBoundRect(rSdrCustomShape.GetCurrentBoundRect()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(4784), aBoundRect.GetWidth(), 5); + } + + drawing::TextVerticalAdjust eAdjust; + xPropSet->getPropertyValue("TextVerticalAdjust") >>= eAdjust; + CPPUNIT_ASSERT_EQUAL_MESSAGE("TextVerticalAdjust", drawing::TextVerticalAdjust_BOTTOM, eAdjust); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf151008VertAnchor) +{ + // The document contains shapes with all six kind of anchor positions in pptx. The text in the + // shapes is larger than the shape and has no word wrap. That way anchor position is visible + // in case you inspect the file manually. + loadFromFile(u"tdf151008_eaVertAnchor.pptx"); + + struct anchorDesc + { + OUString sShapeName; + drawing::TextHorizontalAdjust eAnchorHori; + drawing::TextVerticalAdjust eAnchorVert; + }; + anchorDesc aExpected[6] + = { { u"Right"_ustr, drawing::TextHorizontalAdjust_RIGHT, drawing::TextVerticalAdjust_TOP }, + { u"Center"_ustr, drawing::TextHorizontalAdjust_CENTER, + drawing::TextVerticalAdjust_TOP }, + { u"Left"_ustr, drawing::TextHorizontalAdjust_LEFT, drawing::TextVerticalAdjust_TOP }, + { u"RightMiddle"_ustr, drawing::TextHorizontalAdjust_RIGHT, + drawing::TextVerticalAdjust_CENTER }, + { u"CenterMiddle"_ustr, drawing::TextHorizontalAdjust_CENTER, + drawing::TextVerticalAdjust_CENTER }, + { u"LeftMiddle"_ustr, drawing::TextHorizontalAdjust_LEFT, + drawing::TextVerticalAdjust_CENTER } }; + // without the fix horizontal and vertical anchor positions were exchanged + for (size_t i = 0; i < 6; ++i) + { + uno::Reference xShape(getShapeByName(aExpected[i].sShapeName), + uno::UNO_QUERY); + drawing::TextHorizontalAdjust eHori; + CPPUNIT_ASSERT(xShape->getPropertyValue("TextHorizontalAdjust") >>= eHori); + drawing::TextVerticalAdjust eVert; + CPPUNIT_ASSERT(xShape->getPropertyValue("TextVerticalAdjust") >>= eVert); + CPPUNIT_ASSERT_EQUAL(aExpected[i].eAnchorHori, eHori); + CPPUNIT_ASSERT_EQUAL(aExpected[i].eAnchorVert, eVert); + } +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf151518VertAnchor) +{ + // Make sure SmartArt is loaded as group shape + bool bUseGroup = officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get(); + if (!bUseGroup) + { + std::shared_ptr pChange( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(true, pChange); + pChange->commit(); + } + + // The document contains SmartArt with shapes with not default text area. Without fix the + // text was shifted up because of wrong values in TextLowerDistance and TextUpperDistance. + loadFromFile(u"tdf151518_SmartArtTextLocation.docx"); + + struct TextDistance + { + OUString sShapeName; + sal_Int16 nSubShapeIndex; + sal_Int32 nLowerDistance; + sal_Int32 nUpperDistance; + }; + TextDistance aExpected[4] = { { u"Diagram Target List"_ustr, 2, 2979, 201 }, + { u"Diagram Nested Target"_ustr, 1, 3203, 127 }, + { u"Diagram Stacked Venn"_ustr, 1, 3112, -302 }, + { u"Diagram Grouped List"_ustr, 1, 4106, 196 } }; + // without the fix the observed distances were + // {4434, -464}, {4674, -751}, {4620, -1399}, {6152, -744} + for (size_t i = 0; i < 4; ++i) + { + uno::Reference xDiagramShape(getShapeByName(aExpected[i].sShapeName), + uno::UNO_QUERY); + uno::Reference xShapeProps( + xDiagramShape->getByIndex(aExpected[i].nSubShapeIndex), uno::UNO_QUERY); + sal_Int32 nLower; + sal_Int32 nUpper; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue("TextLowerDistance") >>= nLower); + CPPUNIT_ASSERT(xShapeProps->getPropertyValue("TextUpperDistance") >>= nUpper); + CPPUNIT_ASSERT_EQUAL(aExpected[i].nLowerDistance, nLower); + CPPUNIT_ASSERT_EQUAL(aExpected[i].nUpperDistance, nUpper); + } + + if (!bUseGroup) + { + std::shared_ptr pChange( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(false, pChange); + pChange->commit(); + } +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf54095_SmartArtThemeTextColor) +{ + // The document contains a SmartArt where the color for the texts in the shapes is given by + // the theme. + // Error was, that the theme was not considered and therefore the text was white. + + // Make sure it is not loaded as metafile but with single shapes. + bool bUseGroup = officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get(); + if (!bUseGroup) + { + std::shared_ptr pChange( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(true, pChange); + pChange->commit(); + } + + // get SmartArt + loadFromFile(u"tdf54095_SmartArtThemeTextColor.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xSmartArt(xDrawPage->getByIndex(0), uno::UNO_QUERY); + // shape 0 is the background shape without text + uno::Reference xShape(xSmartArt->getByIndex(1), uno::UNO_QUERY); + + // text color + uno::Reference xText(xShape->getText(), uno::UNO_QUERY); + uno::Reference xPara(xText->createEnumeration()->nextElement(), + uno::UNO_QUERY); + uno::Reference xPortion(xPara->createEnumeration()->nextElement(), + uno::UNO_QUERY); + Color nActualColor{ 0 }; + xPortion->getPropertyValue("CharColor") >>= nActualColor; + // Without fix the test would have failed with: + // - Expected: rgba[1f497dff] + // - Actual : rgba[ffffffff], that is text was white + CPPUNIT_ASSERT_EQUAL(Color(0x1F497D), nActualColor); + + // clrScheme. For map between name in docx and index from CharComplexColor see + // oox::drawingml::Color::getSchemeColorIndex() + // Without fix the color scheme was "lt1" (1) but should be "dk2" (2). + uno::Reference xComplexColor; + xPortion->getPropertyValue("CharComplexColor") >>= xComplexColor; + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Dark2, aComplexColor.getThemeColorType()); + + if (!bUseGroup) + { + std::shared_ptr pChange( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(false, pChange); + pChange->commit(); + } +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterFontwork) +{ + loadFromFile(u"tdf125885_WordArt.docx"); + // Without the patch WordArt in text document was imported as rectangular custom shape with + // attached frame. So there was no artistic text at all. Now it is imported as Fontwork. + // This test covers some basic properties. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + + // Is it a Fontwork? + bool bTextBox = bool(); + CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"TextBox"_ustr) >>= bTextBox); + CPPUNIT_ASSERT(!bTextBox); + + uno::Reference xTextFrame; + xShapeProps->getPropertyValue(u"TextBoxContent"_ustr) >>= xTextFrame; + CPPUNIT_ASSERT(!xTextFrame.is()); + + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue(u"CustomShapeGeometry"_ustr) >>= aGeoPropSeq; + CPPUNIT_ASSERT(aGeoPropSeq.getLength() > 0); + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + + uno::Sequence aTextPathSeq; + aGeoPropMap.getValue(u"TextPath"_ustr) >>= aTextPathSeq; + CPPUNIT_ASSERT(aTextPathSeq.getLength() > 0); + + comphelper::SequenceAsHashMap aTextPathPropMap(aTextPathSeq); + bool bTextPathOn = bool(); + CPPUNIT_ASSERT(aTextPathPropMap.getValue(u"TextPath"_ustr) >>= bTextPathOn); + CPPUNIT_ASSERT(bTextPathOn); + + // Is it the correct kind of Fontwork? + uno::Sequence aAdjustmentSeq; + aGeoPropMap.getValue(u"AdjustmentValues"_ustr) >>= aAdjustmentSeq; + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aAdjustmentSeq.getLength()); + + uno::Sequence> aHandleSeq; + aGeoPropMap.getValue(u"Handles"_ustr) >>= aHandleSeq; + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aHandleSeq.getLength()); + + awt::Rectangle aViewBox; + aGeoPropMap.getValue(u"ViewBox"_ustr) >>= aViewBox; + CPPUNIT_ASSERT_EQUAL(sal_Int32(21600), aViewBox.Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(21600), aViewBox.Height); + + CPPUNIT_ASSERT_EQUAL(uno::Any(u"textDoubleWave1"_ustr), + aGeoPropMap.getValue(u"PresetTextWarp"_ustr)); + + CPPUNIT_ASSERT_EQUAL(uno::Any(u"mso-spt158"_ustr), aGeoPropMap.getValue(u"Type"_ustr)); + + // Are properties correctly copied to shape? + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(0, 0, 255)), + xShapeProps->getPropertyValue(u"FillColor"_ustr)); + + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_SOLID), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + + CPPUNIT_ASSERT_EQUAL(uno::Any(u"Courier New"_ustr), + xShapeProps->getPropertyValue(u"CharFontName"_ustr)); + + CPPUNIT_ASSERT_EQUAL(uno::Any(float(awt::FontWeight::BOLD)), + xShapeProps->getPropertyValue("CharWeight")); + + lang::Locale aCharLocale; + xShapeProps->getPropertyValue(u"CharLocale"_ustr) >>= aCharLocale; + CPPUNIT_ASSERT_EQUAL(OUString("en"), aCharLocale.Language); + CPPUNIT_ASSERT_EQUAL(OUString("US"), aCharLocale.Country); + + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::TextHorizontalAdjust_RIGHT), + xShapeProps->getPropertyValue(u"TextHorizontalAdjust"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterFontwork2) +{ + loadFromFile(u"tdf125885_WordArt2.docx"); + // Without the patch WordArt in text document was imported as rectangular custom shape with + // attached frame. So there was no artistic text at all. Now it is imported as Fontwork. + // This test covers whether theme color properties are correctly converted on import. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + + // Fill + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(4000)), + xShapeProps->getPropertyValue(u"FillColorLumMod"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(6000)), + xShapeProps->getPropertyValue(u"FillColorLumOff"_ustr)); + // ID "6" for the theme "accent3" is not yet in API, but defined in enum PredefinedClrSchemeID + // in drawingml/clrscheme.hxx. + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(6)), + xShapeProps->getPropertyValue(u"FillColorTheme"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(215, 228, 189)), + xShapeProps->getPropertyValue(u"FillColor"_ustr)); + + // Stroke + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineCap_ROUND), + xShapeProps->getPropertyValue(u"LineCap"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_DASH), + xShapeProps->getPropertyValue(u"LineStyle"_ustr)); + // Stroke has only the resulted color, but no reference to the used theme color "accent2". + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(149, 55, 53)), + xShapeProps->getPropertyValue(u"LineColor"_ustr)); + drawing::LineDash aLineDash; + xShapeProps->getPropertyValue(u"LineDash"_ustr) >>= aLineDash; + CPPUNIT_ASSERT_EQUAL(drawing::DashStyle_ROUNDRELATIVE, aLineDash.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(1), aLineDash.Dots); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aLineDash.DotLen); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aLineDash.Dashes); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aLineDash.DashLen); + CPPUNIT_ASSERT_EQUAL(sal_Int32(199), aLineDash.Distance); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(635)), + xShapeProps->getPropertyValue(u"LineWidth"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(20)), + xShapeProps->getPropertyValue(u"LineTransparence"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineJoint_BEVEL), + xShapeProps->getPropertyValue(u"LineJoint"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterFontwork3) +{ + loadFromFile(u"tdf125885_WordArt3.docx"); + // Without the patch WordArt in text document was imported as rectangular custom shape with + // attached frame. So there was no artistic text at all. Now it is imported as Fontwork. + // This test covers some aspects of import of gradient fill. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // linear gradient, MSO UI 21deg + { + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x0000ff), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xf79646), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(sal_Int16(690), aGradient.Angle); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.YOffset); + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style); + } + + // radial gradient, centered + { + uno::Reference xShapeProps(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.40000000000000002)); + CPPUNIT_ASSERT_EQUAL(Color(0xf79646), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x0000ff), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(sal_Int16(900), aGradient.Angle); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.YOffset); + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style); + } + + // rectangular gradient, focus right, bottom + { + uno::Reference xShapeProps(xDrawPage->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xf79646), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x0000ff), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(sal_Int16(900), aGradient.Angle); + CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.YOffset); + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RECT, aGradient.Style); + } +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterFontworkNonAccentColor) +{ + loadFromFile(u"tdf152840_WordArt_non_accent_color.docx"); + // The file contains WordArt which uses the theme colors "Background 1", "Text 1", "Background 2" + // and "Text 2". + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // The ID for the theme colors is not yet in API, but defined in enum PredefinedClrSchemeID + // in drawingml/clrscheme.hxx. Without fix the ID was -1 meaning no theme is used, and the color + // was Black (=0). + + // background 1 = lt1 = ID 1 + uno::Reference xShape0Props(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(1)), + xShape0Props->getPropertyValue(u"FillColorTheme"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(255, 204, 153)), + xShape0Props->getPropertyValue(u"FillColor"_ustr)); + + // text 1 = dk1 = ID 0 + uno::Reference xShape1Props(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(0)), + xShape1Props->getPropertyValue(u"FillColorTheme"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(255, 0, 0)), + xShape1Props->getPropertyValue(u"FillColor"_ustr)); + + // background 2 = lt2 = ID 3 + uno::Reference xShape2Props(xDrawPage->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(3)), + xShape2Props->getPropertyValue(u"FillColorTheme"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(235, 221, 195)), + xShape2Props->getPropertyValue(u"FillColor"_ustr)); + + // text 2 = dk2 = ID 2 + uno::Reference xShape3Props(xDrawPage->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(2)), + xShape3Props->getPropertyValue(u"FillColorTheme"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(119, 95, 85)), + xShape3Props->getPropertyValue(u"FillColor"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterShapeFillNonAccentColor) +{ + loadFromFile(u"tdf152840_theme_color_non_accent.docx"); + // The file contains shapes which uses the theme colors "bg2", "bg1", "tx1" and "tx2" in this + // order as fill color. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // The ID for the theme colors is not yet in API, but defined in enum PredefinedClrSchemeID + // in drawingml/clrscheme.hxx. Without fix the ID was -1 meaning no theme is used. + uno::Reference xShape0Props(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(3)), + xShape0Props->getPropertyValue(u"FillColorTheme"_ustr)); + uno::Reference xShape1Props(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(1)), + xShape1Props->getPropertyValue(u"FillColorTheme"_ustr)); + uno::Reference xShape2Props(xDrawPage->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(0)), + xShape2Props->getPropertyValue(u"FillColorTheme"_ustr)); + uno::Reference xShape3Props(xDrawPage->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(2)), + xShape3Props->getPropertyValue(u"FillColorTheme"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWriterFontworkDarkenTransparency) +{ + loadFromFile(u"tdf152896_WordArt_color_darken.docx"); + // The file contains a WordArt shape with theme colors "Background 2", shading mode "Darken 25%" + // and "20% Transparency". Word writes this as w:color element with additional w14:textFill + // element. In such case the w14:textFill element supersedes the w:color element. Error was, that + // the darkening was applied twice, once from w:color and the other time from w14:textFill. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + // Without the fix in place the test would have failed with + // Expected: 13676402 (= 0xD0AF72 = rgb(208, 175, 114) => luminance 63.14%) + // Actual: 11897660 (= 0xB58B3C = rgb(181, 139, 60) => luminance 47.25% ) + // The original "Background 2" is 0xEBDDC3 = rgb(235, 221, 195) => luminance 84.31% + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(208, 175, 114)), + xShapeProps->getPropertyValue(u"FillColor"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testImportWordArtGradient) +{ + loadFromFile(u"tdf139618_ImportWordArtGradient.pptx"); + // Without the patch all WordArt was imported with solid color. Now gradient is imported. + // This test covers several aspects of import of gradient fill. + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // linear gradient, MSO UI 21deg, solid transparency on outline + { + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xffc000), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xc00000), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(690), aGradient.Angle); + + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_SOLID), + xShapeProps->getPropertyValue(u"LineStyle"_ustr)); + sal_Int32 nOutlineColor; + xShapeProps->getPropertyValue(u"LineColor"_ustr) >>= nOutlineColor; + CPPUNIT_ASSERT_EQUAL(sal_Int32(7384391), nOutlineColor); + sal_Int16 nLineTransparence; + xShapeProps->getPropertyValue(u"LineTransparence"_ustr) >>= nLineTransparence; + CPPUNIT_ASSERT_EQUAL(sal_Int16(60), nLineTransparence); + } + + // radial gradient, direct color with transparency, focus center, dotted outline + // The stop color transparency is imported as transparency gradient with same geometry. + { + uno::Reference xShapeProps(xDrawPage->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x0083e0), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xe6e600), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.YOffset); + + xShapeProps->getPropertyValue(u"FillTransparenceGradient"_ustr) >>= aGradient; + // MCGR: Use the completely imported transparency gradient to check for correctness + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + // Transparency is encoded in gray color. + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x666666), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x4d4d4d), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.YOffset); + + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_DASH), + xShapeProps->getPropertyValue(u"LineStyle"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineCap_ROUND), + xShapeProps->getPropertyValue(u"LineCap"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(7384391)), + xShapeProps->getPropertyValue(u"LineColor"_ustr)); + drawing::LineDash aLineDash; + xShapeProps->getPropertyValue(u"LineDash"_ustr) >>= aLineDash; + CPPUNIT_ASSERT_EQUAL(drawing::DashStyle_ROUNDRELATIVE, aLineDash.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(1), aLineDash.Dots); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aLineDash.Dashes); + } + + // solid theme color accent 1, rectangular transparency gradient, focus top-right, no outline + // FillProperties::pushToPropMap imports this currently (Mar 2023) as color gradient. + // Thus no theme color is tested but direct color. + { + uno::Reference xShapeProps(xDrawPage->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(u"FillGradient"_ustr) >>= aGradient; + + // MCGR: Use the completely imported transparency gradient to check for correctness + basegfx::BColorStops aColorStops; + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x4472c4), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x4472c4), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RECT, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.YOffset); + + xShapeProps->getPropertyValue(u"FillTransparenceGradient"_ustr) >>= aGradient; + // MCGR: Use the completely imported transparency gradient to check for correctness + aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops); + + // Transparency is encoded in gray color. + CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size()); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0)); + CPPUNIT_ASSERT_EQUAL(Color(0x000000), Color(aColorStops[0].getStopColor())); + CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0)); + CPPUNIT_ASSERT_EQUAL(Color(0xFFFFFF), Color(aColorStops[1].getStopColor())); + + CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RECT, aGradient.Style); + CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.XOffset); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.YOffset); + + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_NONE), + xShapeProps->getPropertyValue(u"LineStyle"_ustr)); + } +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWordArtBitmapFill) +{ + // The document has a WordArt shape with bitmap fill. + // Without fix it was imported as solid color fill. + loadFromFile(u"tdf139618_WordArtBitmapFill.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_BITMAP), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + + // Test some bitmap properties + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::BitmapMode_REPEAT), + xShapeProps->getPropertyValue(u"FillBitmapMode"_ustr)); + CPPUNIT_ASSERT_EQUAL(uno::Any(true), xShapeProps->getPropertyValue(u"FillBitmapTile"_ustr)); + uno::Reference xBitmap; + xShapeProps->getPropertyValue(u"FillBitmap"_ustr) >>= xBitmap; + + uno::Reference xGraphic; + xGraphic.set(xBitmap, uno::UNO_QUERY); + uno::Reference xGraphicDescriptor(xGraphic, uno::UNO_QUERY_THROW); + OUString sMimeType; + CPPUNIT_ASSERT(xGraphicDescriptor->getPropertyValue("MimeType") >>= sMimeType); + CPPUNIT_ASSERT_EQUAL(OUString("image/jpeg"), sMimeType); + awt::Size aSize100thMM; + CPPUNIT_ASSERT(xGraphicDescriptor->getPropertyValue("Size100thMM") >>= aSize100thMM); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1592), aSize100thMM.Width); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1592), aSize100thMM.Height); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWordArtDefaultColor) +{ + // The document has a WordArt shape for which the text color is not explicitly set. In such cases + // MS Office uses the scheme color 'tx1'. Without fix it was imported as 'fill none'. The shape + // existed but was not visible on screen. + loadFromFile(u"tdf155327_WordArtDefaultColor.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_SOLID), + xShapeProps->getPropertyValue(u"FillStyle"_ustr)); + + CPPUNIT_ASSERT_EQUAL(uno::Any(Color(3, 74, 144)), + xShapeProps->getPropertyValue(u"FillColor"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testGlowOnGroup) +{ + // The document contains a group of two shapes. A glow-effect is set on the group. + // Without the fix, the children of the group were not imported at all. + loadFromFile(u"tdf156902_GlowOnGroup.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xGroup->getCount()); +} +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vba_compression.cxx b/oox/qa/unit/vba_compression.cxx new file mode 100644 index 0000000000..906e30bfc6 --- /dev/null +++ b/oox/qa/unit/vba_compression.cxx @@ -0,0 +1,255 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include + +class TestVbaCompression : public CppUnit::TestFixture +{ +public: + // just a sequence of bytes that should not be compressed at all + void testSimple1(); + + // a sequence containing one subsequence that can be compressed + void testSimple2(); + + void testSimple3(); + + // real stream from a document + void testComplex1(); + + // tests taken from the VBA specification + // section 3.2 + + // section 3.2.1 + void testSpec321(); + // section 3.2.2 + void testSpec322(); + // section 3.2.3 + void testSpec323(); + + CPPUNIT_TEST_SUITE(TestVbaCompression); + CPPUNIT_TEST(testSimple1); + CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST(testSimple3); + CPPUNIT_TEST(testComplex1); + CPPUNIT_TEST(testSpec321); + CPPUNIT_TEST(testSpec322); + CPPUNIT_TEST(testSpec323); + CPPUNIT_TEST_SUITE_END(); + +private: + static OUString const & getDebugDirUrl() { + struct DebugDirUrl { + DebugDirUrl() : url("$UserInstallation/debug/") { + rtl::Bootstrap::expandMacros(url); + //TODO: provide an OUString -> OUString expansion function, and which throws on + // failure + auto e = osl::Directory::create(url); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); + } + OUString url; + }; + static DebugDirUrl url; + return url.url; + } + + test::Directories m_directories; +}; + +namespace { + +void ReadFiles(const OUString& rTestFile, const OUString& rReference, + SvMemoryStream& rOutputMemoryStream, SvMemoryStream& rReferenceMemoryStream, + const OUString& rDebugPath) +{ + SvFileStream aInputStream(rTestFile, StreamMode::READ); + SvMemoryStream aInputMemoryStream(4096, 4096); + aInputMemoryStream.WriteStream(aInputStream); + + VBACompression aCompression(rOutputMemoryStream, aInputMemoryStream); + aCompression.write(); + + SvFileStream aReferenceStream(rReference, StreamMode::READ); + rReferenceMemoryStream.WriteStream(aReferenceStream); + + rOutputMemoryStream.Seek(0); + SvFileStream aDebugStream(rDebugPath, StreamMode::WRITE); + aDebugStream.WriteStream(rOutputMemoryStream); +} + +} + +void TestVbaCompression::testSimple1() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple1.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple1.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, + aReferenceMemoryStream, getDebugDirUrl() + "vba_debug.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testSimple2() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple2.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple2.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug2.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testSimple3() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/simple3.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/simple3.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug3.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testComplex1() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/complex1.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/complex1.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_complex1.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testSpec321() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec321.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec321.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec321.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testSpec322() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec322.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec322.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec322.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +void TestVbaCompression::testSpec323() +{ + OUString aTestFile = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/spec323.bin"); + OUString aReference = m_directories.getPathFromSrc(u"/oox/qa/unit/data/vba/reference/spec323.bin"); + + SvMemoryStream aOutputMemoryStream(4096, 4096); + SvMemoryStream aReferenceMemoryStream(4096, 4096); + ReadFiles(aTestFile, aReference, aOutputMemoryStream, aReferenceMemoryStream, getDebugDirUrl() + "vba_debug_spec323.bin"); + + CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize()); + + const sal_uInt8* pReferenceData = static_cast( aReferenceMemoryStream.GetData() ); + const sal_uInt8* pData = static_cast( aOutputMemoryStream.GetData() ); + + const sal_uInt64 nSize = std::min(aReferenceMemoryStream.GetSize(), + aOutputMemoryStream.GetSize()); + for (sal_uInt64 i = 0; i < nSize; ++i) + { + CPPUNIT_ASSERT_EQUAL(static_cast(pReferenceData[i]), static_cast(pData[i])); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaCompression); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vba_encryption.cxx b/oox/qa/unit/vba_encryption.cxx new file mode 100644 index 0000000000..023cc197ba --- /dev/null +++ b/oox/qa/unit/vba_encryption.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +class TestVbaEncryption : public CppUnit::TestFixture +{ +public: +#if 0 + // an initial test for the encryption taken from the spec + void testSimple1(); + + void testSimple2(); +#endif + + void testProjKey1(); + + CPPUNIT_TEST_SUITE(TestVbaEncryption); + // CPPUNIT_TEST(testSimple1); + // CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST(testProjKey1); + CPPUNIT_TEST_SUITE_END(); +}; + +#if 0 +void TestVbaEncryption::testSimple1() +{ + sal_uInt8 nSeed = 0x07; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x04; + sal_uInt8 pData[] = { 0x00, 0x00, 0x00, 0x00 }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); +} + +void TestVbaEncryption::testSimple2() +{ + sal_uInt8 nSeed = 0x15; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x01; + sal_uInt8 pData[] = { 0xFF }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); + sal_uInt8 pExpectedData[] = "1517CAF1D6F9D7F9D706"; + size_t length = sizeof(pExpectedData); + aEncryptedStream.Seek(0); + for (size_t i = 0; i < length; ++i) + { + unsigned char val = 0; + aEncryptedStream.ReadUChar(val); + CPPUNIT_ASSERT_EQUAL((int)pExpectedData[i], (int)sal_uInt8(val)); + } +} +#endif + +void TestVbaEncryption::testProjKey1() +{ + sal_uInt8 nProjKey = VBAEncryption::calculateProjKey("{917DED54-440B-4FD1-A5C1-74ACF261E600}"); + CPPUNIT_ASSERT_EQUAL(int(0xdf), static_cast(nProjKey)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaEncryption); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/vml.cxx b/oox/qa/unit/vml.cxx new file mode 100644 index 0000000000..c0918b2682 --- /dev/null +++ b/oox/qa/unit/vml.cxx @@ -0,0 +1,247 @@ +/* -*- 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +/// oox vml tests. +class OoxVmlTest : public UnoApiTest +{ +public: + OoxVmlTest() + : UnoApiTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, tdf112450_vml_polyline) +{ + // Load a document with v:polyline shapes. Error was, that the size was set to zero and the + // points were zero because of missing decode from length with unit. + loadFromFile(u"tdf112450_vml_polyline.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + { + // This tests a polyline shape which is not closed. + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + // Without fix in place, Geometry had 2 points, both 0|0. + drawing::PointSequenceSequence aGeometry; + xShapeProps->getPropertyValue("Geometry") >>= aGeometry; + drawing::PointSequence aPolygon = aGeometry[0]; + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(6879), aPolygon[3].X, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(487), aPolygon[3].Y, 1); + // Without fix in place, width and height were zero + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(6879), xShape->getSize().Width, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1926), xShape->getSize().Height, 1); + // After the fix the shape has still to be PolygonKind_PLIN + drawing::PolygonKind ePolygonKind; + xShapeProps->getPropertyValue("PolygonKind") >>= ePolygonKind; + CPPUNIT_ASSERT_EQUAL(drawing::PolygonKind_PLIN, ePolygonKind); + } + { + uno::Reference xShape(xDrawPage->getByIndex(1), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + // Without fix in place, Geometry had 2 points, both 0|0. + drawing::PointSequenceSequence aGeometry; + xShapeProps->getPropertyValue("Geometry") >>= aGeometry; + drawing::PointSequence aPolygon = aGeometry[0]; + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(5062), aPolygon[2].X, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(2247), aPolygon[2].Y, 1); + // Without fix in place, width and height were zero + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(6163), xShape->getSize().Width, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(2247), xShape->getSize().Height, 1); + // Without fix in place the shape was not closed, it had PolygonKind_PLIN + drawing::PolygonKind ePolygonKind; + xShapeProps->getPropertyValue("PolygonKind") >>= ePolygonKind; + CPPUNIT_ASSERT_EQUAL(drawing::PolygonKind_POLY, ePolygonKind); + } + { + // This tests a filled shape where v:polyline does not have attribute coordsize + uno::Reference xShape(xDrawPage->getByIndex(2), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + // Without fix in place, Geometry had 2 points, both 0|0. + drawing::PointSequenceSequence aGeometry; + xShapeProps->getPropertyValue("Geometry") >>= aGeometry; + drawing::PointSequence aPolygon = aGeometry[0]; + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(2095), aPolygon[3].X, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(608), aPolygon[3].Y, 1); + // Without fix in place, width and height were zero + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(5634), xShape->getSize().Width, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(2485), xShape->getSize().Height, 1); + // Without fix in place the shape was not closed, it had PolygonKind_PLIN + drawing::PolygonKind ePolygonKind; + xShapeProps->getPropertyValue("PolygonKind") >>= ePolygonKind; + CPPUNIT_ASSERT_EQUAL(drawing::PolygonKind_POLY, ePolygonKind); + } +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, tdf137314_vml_rotation_unit_fd) +{ + // Load a document with a 30deg rotated arc on a drawing canvas. Rotation is given + // as 1966080fd. Error was, that the vml angle unit "fd" was not converted to Degree100. + loadFromFile(u"tdf137314_vml_rotation_unit_fd.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape(xGroup->getByIndex(1), uno::UNO_QUERY); + uno::Reference xShapeProps(xShape, uno::UNO_QUERY); + drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords; + xShapeProps->getPropertyValue("PolyPolygonBezier") >>= aPolyPolygonBezierCoords; + drawing::PointSequence aPolygon = aPolyPolygonBezierCoords.Coordinates[1]; + // Without fix in place, the vector was -1441|1490. + // [1] and [2] are Bezier-curve control points. + sal_Int32 nDiffX = aPolygon[3].X - aPolygon[0].X; + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1490), nDiffX, 1); + sal_Int32 nDiffY = aPolygon[3].Y - aPolygon[0].Y; + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1441), nDiffY, 1); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testSpt202ShapeType) +{ + // Load a document with a groupshape, 2nd child is a , its type has o:spt set to 202 + // (TextBox). + loadFromFile(u"group-spt202.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape(xGroup->getByIndex(1), uno::UNO_QUERY); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: com.sun.star.drawing.TextShape + // - Actual : com.sun.star.drawing.CustomShape + // and then the size of the group shape was incorrect, e.g. its right edge was outside the page + // boundaries. + CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.TextShape"), xShape->getShapeType()); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testShapeNonAutosizeWithText) +{ + // Load a document which has a group shape, containing a single child. + // 17.78 cm is the full group shape width, 19431/64008 is the child shape's relative width inside + // that, so 5.3975 cm should be the shape width. + loadFromFile(u"shape-non-autosize-with-text.docx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShape(xGroup->getByIndex(0), uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have failed with: + // - Actual : 1115 + // - Expected: 5398 + // because the width was determined using its text size, not using the explicit size. + CPPUNIT_ASSERT_EQUAL(static_cast(5398), xShape->getSize().Width); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testGraphicStroke) +{ + loadFromFile(u"graphic-stroke.pptx"); + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xDrawPage->getCount()); + + uno::Reference xShape; + uno::Reference xInfo(xDrawPage->getByIndex(0), uno::UNO_QUERY); + if (xInfo->supportsService("com.sun.star.drawing.OLE2Shape")) + xShape.set(xInfo, uno::UNO_QUERY); + + CPPUNIT_ASSERT(xShape.is()); + + drawing::LineStyle eLineStyle{}; + xShape->getPropertyValue("LineStyle") >>= eLineStyle; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. line style was NONE, not SOLID. + CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_SOLID, eLineStyle); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testWatermark) +{ + // Given a document with a picture watermark, and the "washout" checkbox is ticked on the Word + // UI: + // When loading that document: + loadFromFile(u"watermark.docx"); + + // Then make sure the watermark effect is not lost on import: + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); + drawing::ColorMode eMode{}; + xShape->getPropertyValue("GraphicColorMode") >>= eMode; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 3 + // - Actual : 0 + // i.e. the color mode was STANDARD, not WATERMARK. + CPPUNIT_ASSERT_EQUAL(drawing::ColorMode_WATERMARK, eMode); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testWriterFontworkTrimTrue) +{ + // The document contains a shape, that will be exported as VML shape to docx. Error was that the + // attribute trim was not written out and thus import had treated it as the default 'false' and + // had reduced the shape height. + loadFromFile(u"tdf153260_VML_trim_export.odt"); + + // FIXME: tdf#153183 validation error in OOXML export: Errors: 1 + // Attribute 'ID' is not allowed to appear in element 'v:shape'. + skipValidation(); + saveAndReload("Office Open XML Text"); + + uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xShape(xDrawPageSupplier->getDrawPage()->getByIndex(0), + uno::UNO_QUERY); + + // Make sure the shape height is not changed. + // Without the fix the test would have failed with expected 4999 actual 1732. + awt::Size aSize = xShape->getSize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(4999, aSize.Height, 2); +} + +CPPUNIT_TEST_FIXTURE(OoxVmlTest, testVMLDetectWordArtOnImport) +{ + // The document contains a WordArt shape with type other than "fontwork-foo". Error was that + // WordArt was not detected and thus shrinking shape to text content was not prevented. + loadFromFile(u"tdf153258_VML_import_WordArt_detection.docx"); + + uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xShape(xDrawPageSupplier->getDrawPage()->getByIndex(0), + uno::UNO_QUERY); + + // Make sure the shape width and height is not changed. + awt::Size aSize = xShape->getSize(); + // Without the fix the test would have failed with expected 7514 actual 1453. + CPPUNIT_ASSERT_DOUBLES_EQUAL(7514, aSize.Width, 2); + // Without the fix the test would have failed with expected 4540 actual 309. + CPPUNIT_ASSERT_DOUBLES_EQUAL(4540, aSize.Height, 2); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/qa/unit/wpc_drawing_canvas.cxx b/oox/qa/unit/wpc_drawing_canvas.cxx new file mode 100644 index 0000000000..eadd1a2644 --- /dev/null +++ b/oox/qa/unit/wpc_drawing_canvas.cxx @@ -0,0 +1,343 @@ +/* -*- 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace ::com::sun::star; + +namespace +{ +/// The test suite covers tests for import of Word drawing canvas (wpc), available since LO 24.2. +/// Before its implementation the VML fallback was used. That lost properties because VML is not able +/// to describe them or the VML import of LO has deficits. +class TestWPC : public UnoApiXmlTest +{ +public: + TestWPC() + : UnoApiXmlTest("/oox/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_Table_inside_Textbox) +{ + // The document has a table inside a text box on a drawing canvas. + loadFromFile(u"WPC_tdf48610_Textbox_with_table_inside.docx"); + + // Make sure the table exists. Without import of drawing canvas, the table was lost. + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xTables(xTextDocument->getTextTables(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_Text_in_ellipse) +{ + // The document has text in an ellipse on a drawing canvas. + loadFromFile(u"WPC_Textwrap_in_ellipse.docx"); + + // The VML import creates for an ellipse not a custom shape but a legacy ellipse and that has no + // word wrap. Thus the text was in one line and overflows the shape. This overflow becomes visible + // in the bounding box. Without fix the rectangle width was 9398 Hmm. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + // getByIndex(0) gives the background shape, the ellipse is at index 1 + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + awt::Rectangle aBoundRect; + xShapeProps->getPropertyValue(UNO_NAME_MISC_OBJ_BOUNDRECT) >>= aBoundRect; + // The tolerance 10 is estimated and can be adjusted if required for HiDPI. + CPPUNIT_ASSERT_DOUBLES_EQUAL(4740, aBoundRect.Width, 10); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_MulticolorGradient) +{ + // The document has a shape with multi color gradient fill on a drawing canvas. + loadFromFile(u"WPC_MulticolorGradient.docx"); + + // The VML import was not able to import multicolor gradients. Thus only start and end color + // were imported, ColorStops had only two elements. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + awt::Gradient2 aGradient; + xShapeProps->getPropertyValue(UNO_NAME_FILLGRADIENT) >>= aGradient; + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aGradient.ColorStops.getLength()); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_CanvasBackground) +{ + // The document has a drawing canvas with color fill. + loadFromFile(u"WPC_CanvasBackground.docx"); + + // The VML import displayed the background as if it was transparent. Thus the BoundRect + // of the shape which represents the background was zero. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xGroup->getByIndex(0), uno::UNO_QUERY); + awt::Rectangle aBoundRect; + xShapeProps->getPropertyValue(UNO_NAME_MISC_OBJ_BOUNDRECT) >>= aBoundRect; + CPPUNIT_ASSERT(aBoundRect.Width > 0); + CPPUNIT_ASSERT(aBoundRect.Height > 0); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_Glow) +{ + // The document has a shape with glow effect. + loadFromFile(u"WPC_Glow.docx"); + + // VML does not know any glow effect. Thus it was lost on import. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + + // Check glow properties + sal_Int32 nGlowEffectRad = 0; + xShapeProps->getPropertyValue(u"GlowEffectRadius"_ustr) >>= nGlowEffectRad; + CPPUNIT_ASSERT_EQUAL(sal_Int32(564), nGlowEffectRad); // 16 pt = 564.444... mm/100 + Color nGlowEffectColor; + xShapeProps->getPropertyValue(u"GlowEffectColor"_ustr) >>= nGlowEffectColor; + CPPUNIT_ASSERT_EQUAL(Color(0xFFFF00), nGlowEffectColor); // "Yellow" + sal_Int16 nGlowEffectTransparency = 0; + xShapeProps->getPropertyValue(u"GlowEffectTransparency"_ustr) >>= nGlowEffectTransparency; + CPPUNIT_ASSERT_EQUAL(sal_Int16(10), nGlowEffectTransparency); // 10% +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_BentConnector) +{ + // The document has two shapes connected with a bentConnector on a drawing canvas. + loadFromFile(u"WPC_BentConnector.docx"); + + // VML has no information about the target shapes of the connector. The connector was imported as + // custom shape, not as connector shape + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xInfo(xGroup->getByIndex(2), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInfo->supportsService("com.sun.star.drawing.ConnectorShape")); + + uno::Reference xShapeProps(xGroup->getByIndex(2), uno::UNO_QUERY); + com::sun::star::drawing::ConnectorType eEdgeKind; + xShapeProps->getPropertyValue(UNO_NAME_EDGEKIND) >>= eEdgeKind; + CPPUNIT_ASSERT_EQUAL(drawing::ConnectorType::ConnectorType_STANDARD, eEdgeKind); + + sal_Int32 nEdgeLineDelta; + xShapeProps->getPropertyValue(UNO_NAME_EDGELINE1DELTA) >>= nEdgeLineDelta; + CPPUNIT_ASSERT_EQUAL(sal_Int32(-635), nEdgeLineDelta); + xShapeProps->getPropertyValue(UNO_NAME_EDGELINE2DELTA) >>= nEdgeLineDelta; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1949), nEdgeLineDelta); + xShapeProps->getPropertyValue(UNO_NAME_EDGELINE3DELTA) >>= nEdgeLineDelta; + CPPUNIT_ASSERT_EQUAL(sal_Int32(887), nEdgeLineDelta); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_ThemeColor) +{ + // The document has a shape with color fill used as pseudo background and a 'heart' shape with + // color fill and colored line. All colors are theme colors. + loadFromFile(u"WPC_ThemeColor.docx"); + + // VML has no information about theme colors. Thus ThemeColorType was always 'Unknown'. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + + // Check color of shape used for pseudo background + { + uno::Reference xShapeProps(xGroup->getByIndex(0), uno::UNO_QUERY); + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue(UNO_NAME_FILL_COMPLEX_COLOR) + >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Dark2, aComplexColor.getThemeColorType()); + { + auto const& rTrans = aComplexColor.getTransformations(); + CPPUNIT_ASSERT_EQUAL(size_t(2), rTrans.size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, rTrans[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(7500), rTrans[1].mnValue); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumOff, rTrans[1].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2500), rTrans[0].mnValue); + } + } + // Check colors of 'heart' shape + { + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue(UNO_NAME_FILL_COMPLEX_COLOR) + >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent5, aComplexColor.getThemeColorType()); + } + { + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue(UNO_NAME_LINE_COMPLEX_COLOR) + >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent4, aComplexColor.getThemeColorType()); + } +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_tdf104671_Cloud) +{ + // The document has 'cloud' shape on a drawing canvas. + loadFromFile(u"WPC_tdf104671_Cloud.docx"); + + // MS Office writes the 'cloud' shape without type to the VML fallback. Thus the VLM import uses + // ClosedBezierShape with several closed polygons. That produces holes because of the even-odd + // rule, and inner lines. The fix uses the mc:Choice alternative which provides the type for a + // custom shape. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xInfo(xGroup->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInfo->supportsService("com.sun.star.drawing.CustomShape")); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_Shadow) +{ + // The document has a shape with blur shadow on a drawing canvas. + loadFromFile(u"WPC_Shadow.docx"); + + // The VML fallback contains a block shadow. Blur is not available in VML. The VML import does not + // import shadow at all. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + bool bHasShadow = false; + xShapeProps->getPropertyValue(UNO_NAME_SHADOW) >>= bHasShadow; + CPPUNIT_ASSERT(bHasShadow); + sal_Int32 nValue; + xShapeProps->getPropertyValue(UNO_NAME_SHADOWBLUR) >>= nValue; + CPPUNIT_ASSERT_EQUAL(sal_Int32(282), nValue); + xShapeProps->getPropertyValue(UNO_NAME_SHADOWXDIST) >>= nValue; + CPPUNIT_ASSERT_EQUAL(sal_Int32(224), nValue); + xShapeProps->getPropertyValue(UNO_NAME_SHADOWYDIST) >>= nValue; + CPPUNIT_ASSERT_EQUAL(sal_Int32(224), nValue); + Color nColor; + xShapeProps->getPropertyValue(UNO_NAME_SHADOWCOLOR) >>= nColor; + CPPUNIT_ASSERT_EQUAL(Color(0x808080), nColor); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_tdf158339_shape_text_in_group) +{ + // The document has a group of two shapes with text. This group is child of a drawing canvas. + // Without fix the text of the shapes were imported as separate text boxes. + loadFromFile(u"WPC_tdf158339_shape_text_in_group.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + // Make sure there is only one object on that page. Without fix there were three objects. + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xDrawPage->getCount()); + // Get the group which represents the drawing canvas and the group object inside. + uno::Reference xCanvas(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xGroup(xCanvas->getByIndex(1), uno::UNO_QUERY); + // Get the properties of the second shape inside the group + uno::Reference xShapeProps(xGroup->getByIndex(1), uno::UNO_QUERY); + // and make sure the shape has text. + uno::Reference xTextFrame; + xShapeProps->getPropertyValue(u"TextBoxContent"_ustr) >>= xTextFrame; + CPPUNIT_ASSERT(xTextFrame.is()); + CPPUNIT_ASSERT_EQUAL(OUString("Group"), xTextFrame->getText()->getString()); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_tdf158348_shape_text_in_table_cell) +{ + // The document has a shape with text on a drawing canvas in a table cell. + // Without fix the text of the shape becomes part of the paragraph of the table cell. + loadFromFile(u"WPC_tdf158348_shape_text_in_table_cell.docx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // Get the shape and make sure it has text. + uno::Reference xCanvas(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xShapeProps(xCanvas->getByIndex(1), uno::UNO_QUERY); + uno::Reference xTextFrame; + xShapeProps->getPropertyValue(u"TextBoxContent"_ustr) >>= xTextFrame; + CPPUNIT_ASSERT(xTextFrame.is()); + // The string was empty without fix. + CPPUNIT_ASSERT_EQUAL(u"Inside shape"_ustr, xTextFrame->getText()->getString()); + + // Get the table and make sure the cell has only its own text. + uno::Reference xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xTextTable( + xTablesSupplier->getTextTables()->getByName(u"Table1"_ustr), uno::UNO_QUERY); + uno::Reference xCellA1(xTextTable->getCellByName("A1"), uno::UNO_QUERY); + // The string had started with "Inside shape" without fix. + CPPUNIT_ASSERT(xCellA1->getString().startsWith("Inside table")); +} + +CPPUNIT_TEST_FIXTURE(TestWPC, WPC_CurvedConnector2) +{ + // The document has two shapes connected with a curvedConnector2 on a drawing canvas. + // This connector is a single Bezier segment without handles. + loadFromFile(u"WPC_CurvedConnector2.docx"); + + // LO and OOXML differ in the position of the control points. LibreOffice uses 2/3 but OOXML + // uses 1/2 of width or height. The path by LO looks more round. + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + uno::Reference xGroup(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference xInfo(xGroup->getByIndex(3), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInfo->supportsService("com.sun.star.drawing.ConnectorShape")); + + uno::Reference xShapeProps(xGroup->getByIndex(3), uno::UNO_QUERY); + com::sun::star::drawing::ConnectorType eEdgeKind; + xShapeProps->getPropertyValue(UNO_NAME_EDGEKIND) >>= eEdgeKind; + CPPUNIT_ASSERT_EQUAL(drawing::ConnectorType::ConnectorType_CURVE, eEdgeKind); + + // Make sure the path is OOXML compatible + drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords; + xShapeProps->getPropertyValue("PolyPolygonBezier") >>= aPolyPolygonBezierCoords; + drawing::PointSequence aPolygon = aPolyPolygonBezierCoords.Coordinates[0]; + // First control point. LO routing would generate point (4372|5584). + CPPUNIT_ASSERT_EQUAL(sal_Int32(5149), aPolygon[1].Y); + // Second control point. LO routing would generate point (5887|6458). + CPPUNIT_ASSERT_EQUAL(sal_Int32(6645), aPolygon[2].X); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3