summaryrefslogtreecommitdiff
path: root/cppcanvas/source/mtfrenderer
diff options
context:
space:
mode:
authorMark Page <aptitude@btconnect.com>2016-11-24 11:33:23 +0000
committerjan iversen <jani@documentfoundation.org>2017-01-23 11:44:45 +0000
commitf671121525b854b6776d7e0ae1ad04d50d7373dc (patch)
tree233a425f92aca7b77d6d992baf5768f29db6c198 /cppcanvas/source/mtfrenderer
parent04f1d35e7eda2c3b178649610d609ee99342bf41 (diff)
Split emfplus.cxx into multiple files
This helps make emfplus.cxx more readable. No source code was changed, only moved except these renamed to avoid inheritance warnings:: EMFPBrush::transformation renamed to brush_transformation EMFPPen::transformation renamed to pen_transformation Change-Id: I6952d6300c9c459833c2dda2b715d851b9e80de7 Reviewed-on: https://gerrit.libreoffice.org/31165 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: jan iversen <jani@documentfoundation.org>
Diffstat (limited to 'cppcanvas/source/mtfrenderer')
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpbrush.cxx313
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpbrush.hxx122
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx163
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx47
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpfont.cxx74
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpfont.hxx42
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpimage.cxx100
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpimage.hxx44
-rw-r--r--cppcanvas/source/mtfrenderer/emfplus.cxx1047
-rw-r--r--cppcanvas/source/mtfrenderer/emfppath.cxx189
-rw-r--r--cppcanvas/source/mtfrenderer/emfppath.hxx48
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfppen.cxx284
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfppen.hxx80
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpregion.cxx94
-rwxr-xr-xcppcanvas/source/mtfrenderer/emfpregion.hxx43
15 files changed, 1657 insertions, 1033 deletions
diff --git a/cppcanvas/source/mtfrenderer/emfpbrush.cxx b/cppcanvas/source/mtfrenderer/emfpbrush.cxx
new file mode 100755
index 000000000000..9de0f4c3432c
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpbrush.cxx
@@ -0,0 +1,313 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfpbrush.hxx>
+#include <emfppath.hxx>
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ EMFPBrush::EMFPBrush()
+ : type(0)
+ , additionalFlags(0)
+ , wrapMode(0)
+ , areaX(0.0)
+ , areaY(0.0)
+ , areaWidth(0.0)
+ , areaHeight(0.0)
+ , hasTransformation(false)
+ , blendPoints(0)
+ , blendPositions(nullptr)
+ , blendFactors(nullptr)
+ , colorblendPoints(0)
+ , colorblendPositions(nullptr)
+ , colorblendColors(nullptr)
+ , surroundColorsNumber(0)
+ , surroundColors(nullptr)
+ , path(nullptr)
+ , hatchStyle(HatchStyleHorizontal)
+ {
+ }
+
+ EMFPBrush::~EMFPBrush()
+ {
+ if (blendPositions != nullptr) {
+ delete[] blendPositions;
+ blendPositions = nullptr;
+ }
+ if (colorblendPositions != nullptr) {
+ delete[] colorblendPositions;
+ colorblendPositions = nullptr;
+ }
+ if (colorblendColors != nullptr) {
+ delete[] colorblendColors;
+ colorblendColors = nullptr;
+ }
+ if (surroundColors != nullptr) {
+ delete[] surroundColors;
+ surroundColors = nullptr;
+ }
+ if (path) {
+ delete path;
+ path = nullptr;
+ }
+ }
+
+ void EMFPBrush::Read(SvStream& s, ImplRenderer& rR)
+ {
+ sal_uInt32 header;
+
+ s.ReadUInt32(header).ReadUInt32(type);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tbrush");
+ SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+ switch (type) {
+ case 0:
+ {
+ sal_uInt32 color;
+
+ s.ReadUInt32(color);
+ solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
+ break;
+ }
+ case 1:
+ {
+ sal_uInt32 style;
+ sal_uInt32 foregroundColor;
+ sal_uInt32 backgroundColor;
+ s.ReadUInt32(style);
+ s.ReadUInt32(foregroundColor);
+ s.ReadUInt32(backgroundColor);
+
+ hatchStyle = static_cast<EmfPlusHatchStyle>(style);
+ solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
+ secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString());
+ break;
+ }
+ // path gradient
+ case 3:
+ {
+ s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
+
+ sal_uInt32 color;
+
+ s.ReadUInt32(color);
+ solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
+
+ s.ReadFloat(areaX).ReadFloat(areaY);
+ SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
+
+ s.ReadInt32(surroundColorsNumber);
+ SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
+
+ if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
+ surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
+
+ surroundColors = new ::Color[surroundColorsNumber];
+ for (int i = 0; i < surroundColorsNumber; i++) {
+ s.ReadUInt32(color);
+ surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ if (i == 0)
+ secondColor = surroundColors[0];
+ SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
+ }
+
+ if (additionalFlags & 0x01) {
+ sal_Int32 pathLength;
+
+ s.ReadInt32(pathLength);
+ SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
+
+ sal_uInt64 const pos = s.Tell();
+
+ sal_uInt32 pathHeader;
+ sal_Int32 pathPoints, pathFlags;
+ s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
+ SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
+
+ path = new EMFPPath(pathPoints);
+ path->Read(s, pathFlags, rR);
+
+ s.Seek(pos + pathLength);
+
+ const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false)));
+ areaWidth = aBounds.getWidth();
+ areaHeight = aBounds.getHeight();
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight());
+
+
+ if (additionalFlags & 0x02) {
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
+ ReadXForm(s, brush_transformation);
+ hasTransformation = true;
+ SAL_INFO("cppcanvas.emf",
+ "EMF+\tm11: " << brush_transformation.eM11 << " m12: " << brush_transformation.eM12 <<
+ "\nEMF+\tm21: " << brush_transformation.eM21 << " m22: " << brush_transformation.eM22 <<
+ "\nEMF+\tdx: " << brush_transformation.eDx << " dy: " << brush_transformation.eDy);
+
+ }
+ if (additionalFlags & 0x08) {
+ s.ReadInt32(blendPoints);
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
+ if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
+ blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+ blendPositions = new float[2 * blendPoints];
+ blendFactors = blendPositions + blendPoints;
+ for (int i = 0; i < blendPoints; i++) {
+ s.ReadFloat(blendPositions[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]);
+ }
+ for (int i = 0; i < blendPoints; i++) {
+ s.ReadFloat(blendFactors[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]);
+ }
+ }
+
+ if (additionalFlags & 0x04) {
+ s.ReadInt32(colorblendPoints);
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
+ if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
+ colorblendPoints = SAL_MAX_INT32 / sizeof(float);
+ if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color))
+ colorblendPoints = SAL_MAX_INT32 / sizeof(::Color);
+ colorblendPositions = new float[colorblendPoints];
+ colorblendColors = new ::Color[colorblendPoints];
+ for (int i = 0; i < colorblendPoints; i++) {
+ s.ReadFloat(colorblendPositions[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
+ }
+ for (int i = 0; i < colorblendPoints; i++) {
+ s.ReadUInt32(color);
+ colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
+ }
+ }
+ }
+ break;
+ }
+ // linear gradient
+ case 4:
+ {
+ s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
+
+ s.ReadFloat(areaX).ReadFloat(areaY).ReadFloat(areaWidth).ReadFloat(areaHeight);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
+
+ sal_uInt32 color;
+
+ s.ReadUInt32(color);
+ solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
+
+ s.ReadUInt32(color);
+ secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
+
+ // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
+ s.ReadUInt32(color);
+ s.ReadUInt32(color);
+
+ if (additionalFlags & 0x02) {
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
+ ReadXForm(s, brush_transformation);
+ hasTransformation = true;
+ SAL_INFO("cppcanvas.emf",
+ "EMF+\tm11: " << brush_transformation.eM11 << " m12: " << brush_transformation.eM12 <<
+ "\nEMF+\tm21: " << brush_transformation.eM21 << " m22: " << brush_transformation.eM22 <<
+ "\nEMF+\tdx: " << brush_transformation.eDx << " dy: " << brush_transformation.eDy);
+ }
+ if (additionalFlags & 0x08) {
+ s.ReadInt32(blendPoints);
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
+ if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
+ blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+ blendPositions = new float[2 * blendPoints];
+ blendFactors = blendPositions + blendPoints;
+ for (int i = 0; i < blendPoints; i++) {
+ s.ReadFloat(blendPositions[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]);
+ }
+ for (int i = 0; i < blendPoints; i++) {
+ s.ReadFloat(blendFactors[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]);
+ }
+ }
+
+ if (additionalFlags & 0x04) {
+ s.ReadInt32(colorblendPoints);
+ SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
+ if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
+ colorblendPoints = SAL_MAX_INT32 / sizeof(float);
+ if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color))
+ colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color);
+ colorblendPositions = new float[colorblendPoints];
+ colorblendColors = new ::Color[colorblendPoints];
+ for (int i = 0; i < colorblendPoints; i++) {
+ s.ReadFloat(colorblendPositions[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
+ }
+ for (int i = 0; i < colorblendPoints; i++) {
+ s.ReadUInt32(color);
+ colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
+ }
+ }
+
+ break;
+ }
+ default:
+ SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpbrush.hxx b/cppcanvas/source/mtfrenderer/emfpbrush.hxx
new file mode 100755
index 000000000000..88fe7b840961
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpbrush.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ enum EmfPlusHatchStyle
+ {
+ HatchStyleHorizontal = 0x00000000,
+ HatchStyleVertical = 0x00000001,
+ HatchStyleForwardDiagonal = 0x00000002,
+ HatchStyleBackwardDiagonal = 0x00000003,
+ HatchStyleLargeGrid = 0x00000004,
+ HatchStyleDiagonalCross = 0x00000005,
+ HatchStyle05Percent = 0x00000006,
+ HatchStyle10Percent = 0x00000007,
+ HatchStyle20Percent = 0x00000008,
+ HatchStyle25Percent = 0x00000009,
+ HatchStyle30Percent = 0x0000000A,
+ HatchStyle40Percent = 0x0000000B,
+ HatchStyle50Percent = 0x0000000C,
+ HatchStyle60Percent = 0x0000000D,
+ HatchStyle70Percent = 0x0000000E,
+ HatchStyle75Percent = 0x0000000F,
+ HatchStyle80Percent = 0x00000010,
+ HatchStyle90Percent = 0x00000011,
+ HatchStyleLightDownwardDiagonal = 0x00000012,
+ HatchStyleLightUpwardDiagonal = 0x00000013,
+ HatchStyleDarkDownwardDiagonal = 0x00000014,
+ HatchStyleDarkUpwardDiagonal = 0x00000015,
+ HatchStyleWideDownwardDiagonal = 0x00000016,
+ HatchStyleWideUpwardDiagonal = 0x00000017,
+ HatchStyleLightVertical = 0x00000018,
+ HatchStyleLightHorizontal = 0x00000019,
+ HatchStyleNarrowVertical = 0x0000001A,
+ HatchStyleNarrowHorizontal = 0x0000001B,
+ HatchStyleDarkVertical = 0x0000001C,
+ HatchStyleDarkHorizontal = 0x0000001D,
+ HatchStyleDashedDownwardDiagonal = 0x0000001E,
+ HatchStyleDashedUpwardDiagonal = 0x0000001F,
+ HatchStyleDashedHorizontal = 0x00000020,
+ HatchStyleDashedVertical = 0x00000021,
+ HatchStyleSmallConfetti = 0x00000022,
+ HatchStyleLargeConfetti = 0x00000023,
+ HatchStyleZigZag = 0x00000024,
+ HatchStyleWave = 0x00000025,
+ HatchStyleDiagonalBrick = 0x00000026,
+ HatchStyleHorizontalBrick = 0x00000027,
+ HatchStyleWeave = 0x00000028,
+ HatchStylePlaid = 0x00000029,
+ HatchStyleDivot = 0x0000002A,
+ HatchStyleDottedGrid = 0x0000002B,
+ HatchStyleDottedDiamond = 0x0000002C,
+ HatchStyleShingle = 0x0000002D,
+ HatchStyleTrellis = 0x0000002E,
+ HatchStyleSphere = 0x0000002F,
+ HatchStyleSmallGrid = 0x00000030,
+ HatchStyleSmallCheckerBoard = 0x00000031,
+ HatchStyleLargeCheckerBoard = 0x00000032,
+ HatchStyleOutlinedDiamond = 0x00000033,
+ HatchStyleSolidDiamond = 0x00000034
+ };
+
+ struct EMFPPath;
+
+ struct EMFPBrush : public EMFPObject
+ {
+ ::Color solidColor;
+ sal_uInt32 type;
+ sal_uInt32 additionalFlags;
+
+ /* linear gradient */
+ sal_Int32 wrapMode;
+ float areaX, areaY, areaWidth, areaHeight;
+ ::Color secondColor; // first color is stored in solidColor;
+ XForm brush_transformation;
+ bool hasTransformation;
+ sal_Int32 blendPoints;
+ float* blendPositions;
+ float* blendFactors;
+ sal_Int32 colorblendPoints;
+ float* colorblendPositions;
+ ::Color* colorblendColors;
+ sal_Int32 surroundColorsNumber;
+ ::Color* surroundColors;
+ EMFPPath *path;
+ EmfPlusHatchStyle hatchStyle;
+
+ EMFPBrush();
+ virtual ~EMFPBrush() override;
+
+ sal_uInt32 GetType() const { return type; }
+ const ::Color& GetColor() const { return solidColor; }
+
+ void Read(SvStream& s, ImplRenderer& rR);
+ };
+ }
+}
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx
new file mode 100755
index 000000000000..9ef47171ebea
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+
+#include <emfpcustomlinecap.hxx>
+#include <emfppath.hxx>
+#include <emfppen.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
+ const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
+
+ const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
+ const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
+
+ EMFPCustomLineCap::EMFPCustomLineCap()
+ : EMFPObject()
+ , type(0)
+ , strokeStartCap(0)
+ , strokeEndCap(0)
+ , strokeJoin(0)
+ , miterLimit(0.0)
+ , mbIsFilled(false)
+ {
+ }
+
+ void EMFPCustomLineCap::SetAttributes(rendering::StrokeAttributes& aAttributes)
+ {
+ aAttributes.StartCapType = EMFPPen::lcl_convertStrokeCap(strokeStartCap);
+ aAttributes.EndCapType = EMFPPen::lcl_convertStrokeCap(strokeEndCap);
+ aAttributes.JoinType = EMFPPen::lcl_convertLineJoinType(strokeJoin);
+
+ aAttributes.MiterLimit = miterLimit;
+ }
+
+ void EMFPCustomLineCap::ReadPath(SvStream& s, ImplRenderer& rR, bool bFill)
+ {
+ sal_Int32 pathLength;
+ s.ReadInt32(pathLength);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
+
+ sal_uInt32 pathHeader;
+ sal_Int32 pathPoints, pathFlags;
+ s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
+ SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
+
+ EMFPPath path(pathPoints);
+ path.Read(s, pathFlags, rR);
+
+ polygon = path.GetPolygon(rR, false);
+ mbIsFilled = bFill;
+
+ // transformation to convert the path to what LibreOffice
+ // expects
+ B2DHomMatrix aMatrix;
+ aMatrix.scale(1.0, -1.0);
+
+ polygon.transform(aMatrix);
+ };
+
+ void EMFPCustomLineCap::Read(SvStream& s, ImplRenderer& rR)
+ {
+ sal_uInt32 header;
+
+ s.ReadUInt32(header).ReadUInt32(type);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
+ SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+ if (type == EmfPlusCustomLineCapDataTypeDefault)
+ {
+ sal_uInt32 customLineCapDataFlags, baseCap;
+ float baseInset;
+ float widthScale;
+ float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
+
+ s.ReadUInt32(customLineCapDataFlags).ReadUInt32(baseCap).ReadFloat(baseInset)
+ .ReadUInt32(strokeStartCap).ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin)
+ .ReadFloat(miterLimit).ReadFloat(widthScale)
+ .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(strokeHotSpotX).ReadFloat(strokeHotSpotY);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
+
+ if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
+ {
+ ReadPath(s, rR, true);
+ }
+
+ if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
+ {
+ ReadPath(s, rR, false);
+ }
+ }
+ else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
+ {
+ // TODO only reads the data, does not use them [I've had
+ // no test document to be able to implement it]
+
+ sal_Int32 width, height, middleInset, fillState, lineStartCap;
+ sal_Int32 lineEndCap, lineJoin, widthScale;
+ float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
+
+ s.ReadInt32(width).ReadInt32(height).ReadInt32(middleInset).ReadInt32(fillState).ReadInt32(lineStartCap)
+ .ReadInt32(lineEndCap).ReadInt32(lineJoin).ReadFloat(miterLimit).ReadInt32(widthScale)
+ .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(lineHotSpotX).ReadFloat(lineHotSpotY);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx
new file mode 100755
index 000000000000..c5b96a10e81e
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct EMFPCustomLineCap : public EMFPObject
+ {
+ sal_uInt32 type;
+ sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
+ float miterLimit;
+ basegfx::B2DPolyPolygon polygon;
+ bool mbIsFilled;
+
+ EMFPCustomLineCap();
+
+ void SetAttributes(com::sun::star::rendering::StrokeAttributes& aAttributes);
+ void ReadPath(SvStream& s, ImplRenderer& rR, bool bFill);
+ void Read(SvStream& s, ImplRenderer& rR);
+ };
+ }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpfont.cxx b/cppcanvas/source/mtfrenderer/emfpfont.cxx
new file mode 100755
index 000000000000..2df7981e6ab6
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpfont.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfpfont.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ void EMFPFont::Read(SvMemoryStream &s)
+ {
+ sal_uInt32 header;
+ sal_uInt32 reserved;
+ sal_uInt32 length;
+
+ s.ReadUInt32(header).ReadFloat(emSize).ReadUInt32(sizeUnit).ReadInt32(fontFlags).ReadUInt32(reserved).ReadUInt32(length);
+
+ OSL_ASSERT((header >> 12) == 0xdbc01);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tfont\nEMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
+ SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
+
+ if (length > 0 && length < 0x4000)
+ {
+ rtl_uString *pStr = rtl_uString_alloc(length);
+ sal_Unicode *chars = pStr->buffer;
+
+ for (sal_uInt32 i = 0; i < length; ++i)
+ s.ReadUtf16(chars[i]);
+
+ family = OUString(pStr, SAL_NO_ACQUIRE);
+ SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << family);
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpfont.hxx b/cppcanvas/source/mtfrenderer/emfpfont.hxx
new file mode 100755
index 000000000000..aa9d0c45942a
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpfont.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct EMFPFont : public EMFPObject
+ {
+ float emSize;
+ sal_uInt32 sizeUnit;
+ sal_Int32 fontFlags;
+ OUString family;
+
+ void Read(SvMemoryStream &s);
+ };
+ }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpimage.cxx b/cppcanvas/source/mtfrenderer/emfpimage.cxx
new file mode 100755
index 000000000000..c9c5176ef853
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpimage.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <emfpimage.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ void EMFPImage::Read(SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream)
+ {
+ sal_uInt32 header, bitmapType;
+
+ s.ReadUInt32(header).ReadUInt32(type);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+ if (type == 1) { // bitmap
+ s.ReadInt32(width).ReadInt32(height).ReadInt32(stride).ReadInt32(pixelFormat).ReadUInt32(bitmapType);
+ SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
+ if ((bitmapType != 0) || (width == 0)) { // non native formats
+ GraphicFilter filter;
+
+ filter.ImportGraphic(graphic, OUString(), s);
+ SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
+ }
+
+ }
+ else if (type == 2) { // metafile
+ sal_Int32 mfType, mfSize;
+
+ s.ReadInt32(mfType).ReadInt32(mfSize);
+ if (bUseWholeStream)
+ dataSize = s.remainingSize();
+ else
+ dataSize -= 16;
+ SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
+
+ GraphicFilter filter;
+ // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
+ SvMemoryStream mfStream(const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ);
+
+ filter.ImportGraphic(graphic, OUString(), mfStream);
+
+ // debug code - write the stream to debug file /tmp/emf-stream.emf
+#if OSL_DEBUG_LEVEL > 1
+ mfStream.Seek(0);
+ static sal_Int32 emfp_debug_stream_number = 0;
+ OUString emfp_debug_filename = "/tmp/emf-embedded-stream" +
+ OUString::number(emfp_debug_stream_number++) + ".emf";
+
+ SvFileStream file(emfp_debug_filename, StreamMode::WRITE | StreamMode::TRUNC);
+
+ mfStream.WriteStream(file);
+ file.Flush();
+ file.Close();
+#endif
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpimage.hxx b/cppcanvas/source/mtfrenderer/emfpimage.hxx
new file mode 100755
index 000000000000..a30c73e03dde
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpimage.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct EMFPImage : public EMFPObject
+ {
+ sal_uInt32 type;
+ sal_Int32 width;
+ sal_Int32 height;
+ sal_Int32 stride;
+ sal_Int32 pixelFormat;
+ Graphic graphic;
+
+ void Read(SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream);
+ };
+ }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index b1c02f1cd0db..11dbf62f8872 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -47,6 +47,14 @@
#include <polypolyaction.hxx>
#include <textaction.hxx>
+#include <emfpbrush.hxx>
+#include <emfpcustomlinecap.hxx>
+#include <emfpfont.hxx>
+#include <emfpimage.hxx>
+#include <emfppath.hxx>
+#include <emfppen.hxx>
+#include <emfpregion.hxx>
+
namespace
{
@@ -96,27 +104,6 @@ namespace
#define EmfPlusRegionInitialStateInfinite 0x10000003
-const sal_Int32 EmfPlusLineStyleSolid = 0x00000000;
-const sal_Int32 EmfPlusLineStyleDash = 0x00000001;
-const sal_Int32 EmfPlusLineStyleDot = 0x00000002;
-const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
-const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
-const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
-
-const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
-const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
-
-const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
-const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
-
-const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
-const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
-
-const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
-const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
-const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
-const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
-
enum EmfPlusCombineMode
{
EmfPlusCombineModeReplace = 0x00000000,
@@ -127,63 +114,6 @@ enum EmfPlusCombineMode
EmfPlusCombineModeComplement = 0x00000005
};
-enum EmfPlusHatchStyle
-{
- HatchStyleHorizontal = 0x00000000,
- HatchStyleVertical = 0x00000001,
- HatchStyleForwardDiagonal = 0x00000002,
- HatchStyleBackwardDiagonal = 0x00000003,
- HatchStyleLargeGrid = 0x00000004,
- HatchStyleDiagonalCross = 0x00000005,
- HatchStyle05Percent = 0x00000006,
- HatchStyle10Percent = 0x00000007,
- HatchStyle20Percent = 0x00000008,
- HatchStyle25Percent = 0x00000009,
- HatchStyle30Percent = 0x0000000A,
- HatchStyle40Percent = 0x0000000B,
- HatchStyle50Percent = 0x0000000C,
- HatchStyle60Percent = 0x0000000D,
- HatchStyle70Percent = 0x0000000E,
- HatchStyle75Percent = 0x0000000F,
- HatchStyle80Percent = 0x00000010,
- HatchStyle90Percent = 0x00000011,
- HatchStyleLightDownwardDiagonal = 0x00000012,
- HatchStyleLightUpwardDiagonal = 0x00000013,
- HatchStyleDarkDownwardDiagonal = 0x00000014,
- HatchStyleDarkUpwardDiagonal = 0x00000015,
- HatchStyleWideDownwardDiagonal = 0x00000016,
- HatchStyleWideUpwardDiagonal = 0x00000017,
- HatchStyleLightVertical = 0x00000018,
- HatchStyleLightHorizontal = 0x00000019,
- HatchStyleNarrowVertical = 0x0000001A,
- HatchStyleNarrowHorizontal = 0x0000001B,
- HatchStyleDarkVertical = 0x0000001C,
- HatchStyleDarkHorizontal = 0x0000001D,
- HatchStyleDashedDownwardDiagonal = 0x0000001E,
- HatchStyleDashedUpwardDiagonal = 0x0000001F,
- HatchStyleDashedHorizontal = 0x00000020,
- HatchStyleDashedVertical = 0x00000021,
- HatchStyleSmallConfetti = 0x00000022,
- HatchStyleLargeConfetti = 0x00000023,
- HatchStyleZigZag = 0x00000024,
- HatchStyleWave = 0x00000025,
- HatchStyleDiagonalBrick = 0x00000026,
- HatchStyleHorizontalBrick = 0x00000027,
- HatchStyleWeave = 0x00000028,
- HatchStylePlaid = 0x00000029,
- HatchStyleDivot = 0x0000002A,
- HatchStyleDottedGrid = 0x0000002B,
- HatchStyleDottedDiamond = 0x0000002C,
- HatchStyleShingle = 0x0000002D,
- HatchStyleTrellis = 0x0000002E,
- HatchStyleSphere = 0x0000002F,
- HatchStyleSmallGrid = 0x00000030,
- HatchStyleSmallCheckerBoard = 0x00000031,
- HatchStyleLargeCheckerBoard = 0x00000032,
- HatchStyleOutlinedDiamond = 0x00000033,
- HatchStyleSolidDiamond = 0x00000034
-};
-
const char* emfTypeToName(sal_uInt16 type)
{
switch(type)
@@ -234,955 +164,6 @@ namespace cppcanvas
{
namespace internal
{
- struct EMFPPath : public EMFPObject
- {
- ::basegfx::B2DPolyPolygon aPolygon;
- sal_Int32 nPoints;
- float* pPoints;
- sal_uInt8* pPointTypes;
-
- public:
- EMFPPath (sal_Int32 _nPoints, bool bLines = false)
- {
- if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
- _nPoints = SAL_MAX_INT32/(2*sizeof(float));
- nPoints = _nPoints;
- pPoints = new float [nPoints*2];
- if (!bLines)
- pPointTypes = new sal_uInt8 [_nPoints];
- else
- pPointTypes = nullptr;
- }
-
- virtual ~EMFPPath () override
- {
- delete [] pPoints;
- delete [] pPointTypes;
- }
-
- // TODO: remove rR argument when debug code is not longer needed
- void Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
- {
- for (int i = 0; i < nPoints; i ++) {
- if (pathFlags & 0x4000) {
- // EMFPlusPoint: stored in signed short 16bit integer format
- sal_Int16 x, y;
-
- s.ReadInt16( x ).ReadInt16( y );
- SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPoint [x,y]: " << x << "," << y);
- pPoints [i*2] = x;
- pPoints [i*2 + 1] = y;
- } else if (!(pathFlags & 0xC000)) {
- // EMFPlusPointF: stored in Single (float) format
- s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
- SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
- } else { //if (pathFlags & 0x8000)
- // EMFPlusPointR: points are stored in EMFPlusInteger7 or
- // EMFPlusInteger15 objects, see section 2.2.2.21/22
- SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - parse EMFPlusPointR object (section 2.2.1.6)");
- }
-
- }
-
- if (pPointTypes)
- for (int i = 0; i < nPoints; i ++) {
- s.ReadUChar( pPointTypes [i] );
- SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
- }
-
- aPolygon.clear ();
-
-#if OSL_DEBUG_LEVEL > 1
- const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
-
- SAL_INFO ("cppcanvas.emf",
- "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
-#else
- (void) rR; // avoid warnings
-#endif
- }
-
- ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
- {
- ::basegfx::B2DPolygon polygon;
-
- aPolygon.clear ();
-
- int last_normal = 0, p = 0;
- ::basegfx::B2DPoint prev, mapped;
- bool hasPrev = false;
- for (int i = 0; i < nPoints; i ++) {
- if (p && pPointTypes && (pPointTypes [i] == 0)) {
- aPolygon.append (polygon);
- last_normal = i;
- p = 0;
- polygon.clear ();
- }
-
- if (bMapIt)
- mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
- else
- mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
- if (pPointTypes) {
- if ((pPointTypes [i] & 0x07) == 3) {
- if (((i - last_normal )% 3) == 1) {
- polygon.setNextControlPoint (p - 1, mapped);
- SAL_INFO ("cppcanvas.emf", "polygon append next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
- continue;
- } else if (((i - last_normal) % 3) == 2) {
- prev = mapped;
- hasPrev = true;
- continue;
- }
- } else
- last_normal = i;
- }
- polygon.append (mapped);
- SAL_INFO ("cppcanvas.emf", "polygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
- if (hasPrev) {
- polygon.setPrevControlPoint (p, prev);
- SAL_INFO ("cppcanvas.emf", "polygon append prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
- hasPrev = false;
- }
- p ++;
- if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
- polygon.setClosed (true);
- aPolygon.append (polygon);
- SAL_INFO ("cppcanvas.emf", "close polygon");
- last_normal = i + 1;
- p = 0;
- polygon.clear ();
- }
- }
-
- if (polygon.count ()) {
- aPolygon.append (polygon);
-
-#if OSL_DEBUG_LEVEL > 1
- for (unsigned int i=0; i<aPolygon.count(); i++) {
- polygon = aPolygon.getB2DPolygon(i);
- SAL_INFO ("cppcanvas.emf", "polygon: " << i);
- for (unsigned int j=0; j<polygon.count(); j++) {
- ::basegfx::B2DPoint point = polygon.getB2DPoint(j);
- SAL_INFO ("cppcanvas.emf", "point: " << point.getX() << "," << point.getY());
- if (polygon.isPrevControlPointUsed(j)) {
- point = polygon.getPrevControlPoint(j);
- SAL_INFO ("cppcanvas.emf", "prev: " << point.getX() << "," << point.getY());
- }
- if (polygon.isNextControlPointUsed(j)) {
- point = polygon.getNextControlPoint(j);
- SAL_INFO ("cppcanvas.emf", "next: " << point.getX() << "," << point.getY());
- }
- }
- }
-#endif
- }
-
- return aPolygon;
- }
- };
-
- struct EMFPRegion : public EMFPObject
- {
- sal_Int32 parts;
- sal_Int32 *combineMode;
- sal_Int32 initialState;
- float ix, iy, iw, ih;
-
- EMFPRegion ()
- : parts(0)
- , combineMode(nullptr)
- , initialState(0)
- , ix(0.0)
- , iy(0.0)
- , iw(0.0)
- , ih(0.0)
- {
- }
-
- virtual ~EMFPRegion () override
- {
- if (combineMode) {
- delete [] combineMode;
- combineMode = nullptr;
- }
- }
-
- void Read (SvStream& s)
- {
- sal_uInt32 header;
-
- s.ReadUInt32( header ).ReadInt32( parts );
-
- SAL_INFO ("cppcanvas.emf", "EMF+\tregion");
- SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec );
-
- if (parts) {
- if( parts<0 || sal_uInt32(parts)>SAL_MAX_INT32/sizeof(sal_Int32) )
- parts = SAL_MAX_INT32/sizeof(sal_Int32);
-
- combineMode = new sal_Int32 [parts];
-
- for (int i = 0; i < parts; i ++) {
- s.ReadInt32( combineMode [i] );
- SAL_INFO ("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode [i] << std::dec);
- }
- }
-
- s.ReadInt32( initialState );
- SAL_INFO ("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
- }
- };
-
- struct EMFPBrush : public EMFPObject
- {
- ::Color solidColor;
- sal_uInt32 type;
- sal_uInt32 additionalFlags;
-
- /* linear gradient */
- sal_Int32 wrapMode;
- float areaX, areaY, areaWidth, areaHeight;
- ::Color secondColor; // first color is stored in solidColor;
- XForm transformation;
- bool hasTransformation;
- sal_Int32 blendPoints;
- float* blendPositions;
- float* blendFactors;
- sal_Int32 colorblendPoints;
- float* colorblendPositions;
- ::Color* colorblendColors;
- sal_Int32 surroundColorsNumber;
- ::Color* surroundColors;
- EMFPPath *path;
- EmfPlusHatchStyle hatchStyle;
-
- public:
- EMFPBrush ()
- : type(0)
- , additionalFlags(0)
- , wrapMode(0)
- , areaX(0.0)
- , areaY(0.0)
- , areaWidth(0.0)
- , areaHeight(0.0)
- , hasTransformation(false)
- , blendPoints(0)
- , blendPositions(nullptr)
- , blendFactors(nullptr)
- , colorblendPoints(0)
- , colorblendPositions(nullptr)
- , colorblendColors(nullptr)
- , surroundColorsNumber(0)
- , surroundColors(nullptr)
- , path(nullptr)
- , hatchStyle(HatchStyleHorizontal)
- {
- }
-
- virtual ~EMFPBrush () override
- {
- if (blendPositions != nullptr) {
- delete[] blendPositions;
- blendPositions = nullptr;
- }
- if (colorblendPositions != nullptr) {
- delete[] colorblendPositions;
- colorblendPositions = nullptr;
- }
- if (colorblendColors != nullptr) {
- delete[] colorblendColors;
- colorblendColors = nullptr;
- }
- if (surroundColors != nullptr) {
- delete[] surroundColors;
- surroundColors = nullptr;
- }
- if (path) {
- delete path;
- path = nullptr;
- }
- }
-
- sal_uInt32 GetType() const { return type; }
- const ::Color& GetColor() const { return solidColor; }
-
- void Read (SvStream& s, ImplRenderer& rR)
- {
- sal_uInt32 header;
-
- s.ReadUInt32( header ).ReadUInt32( type );
-
- SAL_INFO ("cppcanvas.emf", "EMF+\tbrush");
- SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
-
- switch (type) {
- case 0:
- {
- sal_uInt32 color;
-
- s.ReadUInt32( color );
- solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO ("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
- break;
- }
- case 1:
- {
- sal_uInt32 style;
- sal_uInt32 foregroundColor;
- sal_uInt32 backgroundColor;
- s.ReadUInt32( style );
- s.ReadUInt32( foregroundColor );
- s.ReadUInt32( backgroundColor );
-
- hatchStyle = static_cast<EmfPlusHatchStyle>(style);
- solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
- secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
- SAL_INFO ("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString());
- break;
- }
- // path gradient
- case 3:
- {
- s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
-
- SAL_INFO ("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
-
- sal_uInt32 color;
-
- s.ReadUInt32( color );
- solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
-
- s.ReadFloat( areaX ).ReadFloat( areaY );
- SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
-
- s.ReadInt32( surroundColorsNumber );
- SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
-
- if( surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32/sizeof(::Color) )
- surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
-
- surroundColors = new ::Color [surroundColorsNumber];
- for (int i = 0; i < surroundColorsNumber; i++) {
- s.ReadUInt32( color );
- surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- if (i == 0)
- secondColor = surroundColors [0];
- SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
- }
-
- if (additionalFlags & 0x01) {
- sal_Int32 pathLength;
-
- s.ReadInt32( pathLength );
- SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
-
- sal_uInt64 const pos = s.Tell ();
-
- sal_uInt32 pathHeader;
- sal_Int32 pathPoints, pathFlags;
- s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
-
- SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
- SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
- path = new EMFPPath (pathPoints);
- path->Read (s, pathFlags, rR);
-
- s.Seek (pos + pathLength);
-
- const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
- areaWidth = aBounds.getWidth ();
- areaHeight = aBounds.getHeight ();
-
- SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << " " << aBounds.getWidth () << "x" << aBounds.getHeight ());
-
-
- if (additionalFlags & 0x02) {
- SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
- ReadXForm( s, transformation );
- hasTransformation = true;
- SAL_INFO("cppcanvas.emf",
- "EMF+\tm11: " << transformation.eM11 << " m12: " << transformation.eM12 <<
- "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
- "\nEMF+\tdx: " << transformation.eDx << " dy: " << transformation.eDy);
-
- }
- if (additionalFlags & 0x08) {
- s.ReadInt32( blendPoints );
- SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
- if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
- blendPoints = SAL_MAX_INT32/(2*sizeof(float));
- blendPositions = new float [2*blendPoints];
- blendFactors = blendPositions + blendPoints;
- for (int i=0; i < blendPoints; i ++) {
- s.ReadFloat( blendPositions [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
- }
- for (int i=0; i < blendPoints; i ++) {
- s.ReadFloat( blendFactors [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
- }
- }
-
- if (additionalFlags & 0x04) {
- s.ReadInt32( colorblendPoints );
- SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
- if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
- colorblendPoints = SAL_MAX_INT32/sizeof(float);
- if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
- colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
- colorblendPositions = new float [colorblendPoints];
- colorblendColors = new ::Color [colorblendPoints];
- for (int i=0; i < colorblendPoints; i ++) {
- s.ReadFloat( colorblendPositions [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
- }
- for (int i=0; i < colorblendPoints; i ++) {
- s.ReadUInt32( color );
- colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
- }
- }
- }
- break;
- }
- // linear gradient
- case 4:
- {
- s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
-
- SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
-
- s.ReadFloat( areaX ).ReadFloat( areaY ).ReadFloat( areaWidth ).ReadFloat( areaHeight );
-
- SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
-
- sal_uInt32 color;
-
- s.ReadUInt32( color );
- solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
-
- s.ReadUInt32( color );
- secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
-
- // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
- s.ReadUInt32( color );
- s.ReadUInt32( color );
-
- if (additionalFlags & 0x02) {
- SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
- ReadXForm( s, transformation );
- hasTransformation = true;
- SAL_INFO("cppcanvas.emf",
- "EMF+\tm11: " << transformation.eM11 << " m12: " << transformation.eM12 <<
- "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
- "\nEMF+\tdx: " << transformation.eDx << " dy: " << transformation.eDy);
- }
- if (additionalFlags & 0x08) {
- s.ReadInt32( blendPoints );
- SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
- if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
- blendPoints = SAL_MAX_INT32/(2*sizeof(float));
- blendPositions = new float [2*blendPoints];
- blendFactors = blendPositions + blendPoints;
- for (int i=0; i < blendPoints; i ++) {
- s.ReadFloat( blendPositions [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
- }
- for (int i=0; i < blendPoints; i ++) {
- s.ReadFloat( blendFactors [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
- }
- }
-
- if (additionalFlags & 0x04) {
- s.ReadInt32( colorblendPoints );
- SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
- if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
- colorblendPoints = SAL_MAX_INT32/sizeof(float);
- if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
- colorblendPoints = sal_uInt32(SAL_MAX_INT32)/sizeof(::Color);
- colorblendPositions = new float [colorblendPoints];
- colorblendColors = new ::Color [colorblendPoints];
- for (int i=0; i < colorblendPoints; i ++) {
- s.ReadFloat( colorblendPositions [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
- }
- for (int i=0; i < colorblendPoints; i ++) {
- s.ReadUInt32( color );
- colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
- SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
- }
- }
-
- break;
- }
- default:
- SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
- }
- }
- };
-
- /// Convert stroke caps between EMF+ and rendering API
- sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
- {
- switch (nEmfStroke)
- {
- case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
- case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND;
- }
-
- // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
- // so return BUTT always
- return rendering::PathCapType::BUTT;
- }
-
- sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
- {
- switch (nEmfLineJoin)
- {
- case EmfPlusLineJoinTypeMiter: // fall-through
- case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
- case EmfPlusLineJoinTypeBevel: return rendering::PathJoinType::BEVEL;
- case EmfPlusLineJoinTypeRound: return rendering::PathJoinType::ROUND;
- }
- assert(false); // Line Join type isn't in specification.
- return 0;
- }
-
- struct EMFPCustomLineCap : public EMFPObject
- {
- sal_uInt32 type;
- sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
- float miterLimit;
- basegfx::B2DPolyPolygon polygon;
- bool mbIsFilled;
-
- public:
- EMFPCustomLineCap()
- : EMFPObject()
- , type(0)
- , strokeStartCap(0)
- , strokeEndCap(0)
- , strokeJoin(0)
- , miterLimit(0.0)
- , mbIsFilled(false)
- {
- }
-
- void SetAttributes(rendering::StrokeAttributes& aAttributes)
- {
- aAttributes.StartCapType = lcl_convertStrokeCap(strokeStartCap);
- aAttributes.EndCapType = lcl_convertStrokeCap(strokeEndCap);
- aAttributes.JoinType = lcl_convertLineJoinType(strokeJoin);
-
- aAttributes.MiterLimit = miterLimit;
- }
-
- void ReadPath(SvStream& s, ImplRenderer& rR, bool bFill)
- {
- sal_Int32 pathLength;
- s.ReadInt32( pathLength );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
-
- sal_uInt32 pathHeader;
- sal_Int32 pathPoints, pathFlags;
- s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
- SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
- EMFPPath path(pathPoints);
- path.Read(s, pathFlags, rR);
-
- polygon = path.GetPolygon(rR, false);
- mbIsFilled = bFill;
-
- // transformation to convert the path to what LibreOffice
- // expects
- B2DHomMatrix aMatrix;
- aMatrix.scale(1.0, -1.0);
-
- polygon.transform(aMatrix);
- };
-
- void Read (SvStream& s, ImplRenderer& rR)
- {
- sal_uInt32 header;
-
- s.ReadUInt32( header ).ReadUInt32( type );
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
- SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
-
- if (type == EmfPlusCustomLineCapDataTypeDefault)
- {
- sal_uInt32 customLineCapDataFlags, baseCap;
- float baseInset;
- float widthScale;
- float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
-
- s.ReadUInt32( customLineCapDataFlags ).ReadUInt32( baseCap ).ReadFloat( baseInset )
- .ReadUInt32( strokeStartCap ).ReadUInt32( strokeEndCap ).ReadUInt32( strokeJoin )
- .ReadFloat( miterLimit ).ReadFloat( widthScale )
- .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( strokeHotSpotX ).ReadFloat( strokeHotSpotY );
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
- SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
-
- if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
- {
- ReadPath(s, rR, true);
- }
-
- if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
- {
- ReadPath(s, rR, false);
- }
- }
- else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
- {
- // TODO only reads the data, does not use them [I've had
- // no test document to be able to implement it]
-
- sal_Int32 width, height, middleInset, fillState, lineStartCap;
- sal_Int32 lineEndCap, lineJoin, widthScale;
- float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
-
- s.ReadInt32( width ).ReadInt32( height ).ReadInt32( middleInset ).ReadInt32( fillState ).ReadInt32( lineStartCap )
- .ReadInt32( lineEndCap ).ReadInt32( lineJoin ).ReadFloat( miterLimit ).ReadInt32( widthScale )
- .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( lineHotSpotX ).ReadFloat( lineHotSpotY );
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
- }
- }
- };
-
- struct EMFPPen : public EMFPBrush
- {
- XForm transformation;
- float width;
- sal_Int32 startCap;
- sal_Int32 endCap;
- sal_Int32 lineJoin;
- float mitterLimit;
- sal_Int32 dashStyle;
- sal_Int32 dashCap;
- float dashOffset;
- sal_Int32 dashPatternLen;
- float *dashPattern;
- sal_Int32 alignment;
- sal_Int32 compoundArrayLen;
- float *compoundArray;
- sal_Int32 customStartCapLen;
- EMFPCustomLineCap *customStartCap;
- sal_Int32 customEndCapLen;
- EMFPCustomLineCap *customEndCap;
-
- public:
- EMFPPen ()
- : EMFPBrush()
- , width(0.0)
- , startCap(0)
- , endCap(0)
- , lineJoin(0)
- , mitterLimit(0.0)
- , dashStyle(0)
- , dashCap(0)
- , dashOffset(0.0)
- , dashPatternLen(0)
- , dashPattern(nullptr)
- , alignment(0)
- , compoundArrayLen(0)
- , compoundArray(nullptr)
- , customStartCapLen(0)
- , customStartCap(nullptr)
- , customEndCapLen(0)
- , customEndCap(nullptr)
- {
- }
-
- virtual ~EMFPPen() override
- {
- delete[] dashPattern;
- delete[] compoundArray;
- delete customStartCap;
- delete customEndCap;
- }
-
- void SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
- {
-#if OSL_DEBUG_LEVEL > 1
- if (width == 0.0) {
- SAL_INFO ("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
- }
-#endif
- rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getLength());
- }
-
- void SetStrokeAttributes(rendering::StrokeAttributes& rStrokeAttributes)
- {
- rStrokeAttributes.JoinType = lcl_convertLineJoinType(lineJoin);
-
- if (dashStyle != EmfPlusLineStyleSolid)
- {
- const float dash[] = {3, 3};
- const float dot[] = {1, 3};
- const float dashdot[] = {3, 3, 1, 3};
- const float dashdotdot[] = {3, 3, 1, 3, 1, 3};
-
- sal_Int32 nLen = 0;
- const float *pPattern = nullptr;
- switch (dashStyle)
- {
- case EmfPlusLineStyleDash: nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
- case EmfPlusLineStyleDot: nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
- case EmfPlusLineStyleDashDot: nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
- case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
- case EmfPlusLineStyleCustom: nLen = dashPatternLen; pPattern = dashPattern; break;
- }
- if (nLen > 0)
- {
- uno::Sequence<double> aDashArray(nLen);
- for (int i = 0; i < nLen; ++i)
- aDashArray[i] = pPattern[i];
-
- rStrokeAttributes.DashArray = aDashArray;
- }
- }
- }
-
- void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
- {
- sal_uInt32 header, unknown, penFlags, unknown2;
- int i;
-
- s.ReadUInt32( header ).ReadUInt32( unknown ).ReadUInt32( penFlags ).ReadUInt32( unknown2 ).ReadFloat( width );
-
- SAL_INFO("cppcanvas.emf", "EMF+\tpen");
- SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " unknown: 0x" << unknown <<
- " additional flags: 0x" << penFlags << " unknown: 0x" << unknown2 << " width: " << std::dec << width );
-
- if (penFlags & 1)
- ReadXForm( s, transformation );
-
- if (penFlags & 2)
- {
- s.ReadInt32( startCap );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tstartCap: 0x" << std::hex << startCap);
- }
- else
- startCap = 0;
-
- if (penFlags & 4)
- {
- s.ReadInt32( endCap );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tendCap: 0x" << std::hex << endCap);
- }
- else
- endCap = 0;
-
- if (penFlags & 8)
- s.ReadInt32( lineJoin );
- else
- lineJoin = 0;
-
- if (penFlags & 16)
- s.ReadFloat( mitterLimit );
- else
- mitterLimit = 0;
-
- if (penFlags & 32)
- {
- s.ReadInt32( dashStyle );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tdashStyle: 0x" << std::hex << dashStyle);
- }
- else
- dashStyle = 0;
-
- if (penFlags & 64)
- s.ReadInt32( dashCap );
- else
- dashCap = 0;
-
- if (penFlags & 128)
- s.ReadFloat( dashOffset );
- else
- dashOffset = 0;
-
- if (penFlags & 256)
- {
- dashStyle = EmfPlusLineStyleCustom;
-
- s.ReadInt32( dashPatternLen );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tdashPatternLen: " << dashPatternLen);
-
- if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
- dashPatternLen = SAL_MAX_INT32/sizeof(float);
- dashPattern = new float [dashPatternLen];
- for (i = 0; i < dashPatternLen; i++)
- {
- s.ReadFloat( dashPattern [i] );
- SAL_INFO("cppcanvas.emf", "EMF+\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
- }
- }
- else
- dashPatternLen = 0;
-
- if (penFlags & 512)
- s.ReadInt32( alignment );
- else
- alignment = 0;
-
- if (penFlags & 1024) {
- s.ReadInt32( compoundArrayLen );
- if( compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32/sizeof(float) )
- compoundArrayLen = SAL_MAX_INT32/sizeof(float);
- compoundArray = new float [compoundArrayLen];
- for (i = 0; i < compoundArrayLen; i++)
- s.ReadFloat( compoundArray [i] );
- } else
- compoundArrayLen = 0;
-
- if (penFlags & 2048)
- {
- s.ReadInt32( customStartCapLen );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomStartCapLen: " << customStartCapLen);
- sal_uInt64 const pos = s.Tell();
-
- customStartCap = new EMFPCustomLineCap();
- customStartCap->Read(s, rR);
-
- // maybe we don't read everything yet, play it safe ;-)
- s.Seek(pos + customStartCapLen);
- }
- else
- customStartCapLen = 0;
-
- if (penFlags & 4096)
- {
- s.ReadInt32( customEndCapLen );
- SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomEndCapLen: " << customEndCapLen);
- sal_uInt64 const pos = s.Tell();
-
- customEndCap = new EMFPCustomLineCap();
- customEndCap->Read(s, rR);
-
- // maybe we don't read everything yet, play it safe ;-)
- s.Seek(pos + customEndCapLen);
- }
- else
- customEndCapLen = 0;
-
- EMFPBrush::Read (s, rR);
- }
- };
-
- struct EMFPImage : public EMFPObject
- {
- sal_uInt32 type;
- sal_Int32 width;
- sal_Int32 height;
- sal_Int32 stride;
- sal_Int32 pixelFormat;
- Graphic graphic;
-
-
- void Read (SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream)
- {
- sal_uInt32 header, bitmapType;
-
- s.ReadUInt32( header ).ReadUInt32( type );
-
- SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec );
-
- if (type == 1) { // bitmap
- s.ReadInt32( width ).ReadInt32( height ).ReadInt32( stride ).ReadInt32( pixelFormat ).ReadUInt32( bitmapType );
- SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
- if ((bitmapType != 0) || (width == 0)) { // non native formats
- GraphicFilter filter;
-
- filter.ImportGraphic (graphic, OUString(), s);
- SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
- }
-
- } else if (type == 2) { // metafile
- sal_Int32 mfType, mfSize;
-
- s.ReadInt32( mfType ).ReadInt32( mfSize );
- if (bUseWholeStream)
- dataSize = s.remainingSize();
- else
- dataSize -= 16;
- SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
-
- GraphicFilter filter;
- // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
- SvMemoryStream mfStream (const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ);
-
- filter.ImportGraphic (graphic, OUString(), mfStream);
-
- // debug code - write the stream to debug file /tmp/emf-stream.emf
-#if OSL_DEBUG_LEVEL > 1
- mfStream.Seek(0);
- static sal_Int32 emfp_debug_stream_number = 0;
- OUString emfp_debug_filename = "/tmp/emf-embedded-stream" +
- OUString::number(emfp_debug_stream_number++) + ".emf";
-
- SvFileStream file( emfp_debug_filename, StreamMode::WRITE | StreamMode::TRUNC );
-
- mfStream.WriteStream(file);
- file.Flush();
- file.Close();
-#endif
- }
- }
- };
-
- struct EMFPFont : public EMFPObject
- {
- float emSize;
- sal_uInt32 sizeUnit;
- sal_Int32 fontFlags;
- OUString family;
-
- void Read (SvMemoryStream &s)
- {
- sal_uInt32 header;
- sal_uInt32 reserved;
- sal_uInt32 length;
-
- s.ReadUInt32( header ).ReadFloat( emSize ).ReadUInt32( sizeUnit ).ReadInt32( fontFlags ).ReadUInt32( reserved ).ReadUInt32( length );
-
- OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
-
- SAL_INFO("cppcanvas.emf", "EMF+\tfont\nEMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
- SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
-
- if (length > 0 && length < 0x4000)
- {
- rtl_uString *pStr = rtl_uString_alloc(length);
- sal_Unicode *chars = pStr->buffer;
-
- for (sal_uInt32 i = 0; i < length; ++i)
- s.ReadUtf16(chars[i]);
-
- family = OUString(pStr, SAL_NO_ACQUIRE);
- SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << family);
- }
- }
- };
-
void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, bool bCompressed)
{
if (bCompressed) {
@@ -1368,12 +349,12 @@ namespace cppcanvas
if (brush->hasTransformation) {
::basegfx::B2DHomMatrix aTransformation;
- aTransformation.set (0, 0, brush->transformation.eM11);
- aTransformation.set (0, 1, brush->transformation.eM21);
- aTransformation.set (0, 2, brush->transformation.eDx);
- aTransformation.set (1, 0, brush->transformation.eM12);
- aTransformation.set (1, 1, brush->transformation.eM22);
- aTransformation.set (1, 2, brush->transformation.eDy);
+ aTransformation.set (0, 0, brush->brush_transformation.eM11);
+ aTransformation.set (0, 1, brush->brush_transformation.eM21);
+ aTransformation.set (0, 2, brush->brush_transformation.eDx);
+ aTransformation.set (1, 0, brush->brush_transformation.eM12);
+ aTransformation.set (1, 1, brush->brush_transformation.eM22);
+ aTransformation.set (1, 2, brush->brush_transformation.eDy);
aTextureTransformation *= aTransformation;
}
diff --git a/cppcanvas/source/mtfrenderer/emfppath.cxx b/cppcanvas/source/mtfrenderer/emfppath.cxx
new file mode 100644
index 000000000000..54de41b06091
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfppath.cxx
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfppath.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ EMFPPath::EMFPPath (sal_Int32 _nPoints, bool bLines)
+ {
+ if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
+ _nPoints = SAL_MAX_INT32/(2*sizeof(float));
+ nPoints = _nPoints;
+ pPoints = new float [nPoints*2];
+ if (!bLines)
+ pPointTypes = new sal_uInt8 [_nPoints];
+ else
+ pPointTypes = nullptr;
+ }
+
+ EMFPPath::~EMFPPath ()
+ {
+ delete [] pPoints;
+ delete [] pPointTypes;
+ }
+
+ // TODO: remove rR argument when debug code is not longer needed
+ void EMFPPath::Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
+ {
+ for (int i = 0; i < nPoints; i ++) {
+ if (pathFlags & 0x4000) {
+ // EMFPlusPoint: stored in signed short 16bit integer format
+ sal_Int16 x, y;
+
+ s.ReadInt16( x ).ReadInt16( y );
+ SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPoint [x,y]: " << x << "," << y);
+ pPoints [i*2] = x;
+ pPoints [i*2 + 1] = y;
+ } else if (!(pathFlags & 0xC000)) {
+ // EMFPlusPointF: stored in Single (float) format
+ s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
+ SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
+ } else { //if (pathFlags & 0x8000)
+ // EMFPlusPointR: points are stored in EMFPlusInteger7 or
+ // EMFPlusInteger15 objects, see section 2.2.2.21/22
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - parse EMFPlusPointR object (section 2.2.1.6)");
+ }
+
+ }
+
+ if (pPointTypes)
+ for (int i = 0; i < nPoints; i ++) {
+ s.ReadUChar( pPointTypes [i] );
+ SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
+ }
+
+ aPolygon.clear ();
+
+#if OSL_DEBUG_LEVEL > 1
+ const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
+
+ SAL_INFO ("cppcanvas.emf",
+ "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
+#else
+ (void) rR; // avoid warnings
+#endif
+ }
+
+ ::basegfx::B2DPolyPolygon& EMFPPath::GetPolygon (ImplRenderer& rR, bool bMapIt)
+ {
+ ::basegfx::B2DPolygon polygon;
+
+ aPolygon.clear ();
+
+ int last_normal = 0, p = 0;
+ ::basegfx::B2DPoint prev, mapped;
+ bool hasPrev = false;
+ for (int i = 0; i < nPoints; i ++) {
+ if (p && pPointTypes && (pPointTypes [i] == 0)) {
+ aPolygon.append (polygon);
+ last_normal = i;
+ p = 0;
+ polygon.clear ();
+ }
+
+ if (bMapIt)
+ mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
+ else
+ mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
+ if (pPointTypes) {
+ if ((pPointTypes [i] & 0x07) == 3) {
+ if (((i - last_normal )% 3) == 1) {
+ polygon.setNextControlPoint (p - 1, mapped);
+ SAL_INFO ("cppcanvas.emf", "polygon append next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
+ continue;
+ } else if (((i - last_normal) % 3) == 2) {
+ prev = mapped;
+ hasPrev = true;
+ continue;
+ }
+ } else
+ last_normal = i;
+ }
+ polygon.append (mapped);
+ SAL_INFO ("cppcanvas.emf", "polygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
+ if (hasPrev) {
+ polygon.setPrevControlPoint (p, prev);
+ SAL_INFO ("cppcanvas.emf", "polygon append prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
+ hasPrev = false;
+ }
+ p ++;
+ if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
+ polygon.setClosed (true);
+ aPolygon.append (polygon);
+ SAL_INFO ("cppcanvas.emf", "close polygon");
+ last_normal = i + 1;
+ p = 0;
+ polygon.clear ();
+ }
+ }
+
+ if (polygon.count ()) {
+ aPolygon.append (polygon);
+
+#if OSL_DEBUG_LEVEL > 1
+ for (unsigned int i=0; i<aPolygon.count(); i++) {
+ polygon = aPolygon.getB2DPolygon(i);
+ SAL_INFO ("cppcanvas.emf", "polygon: " << i);
+ for (unsigned int j=0; j<polygon.count(); j++) {
+ ::basegfx::B2DPoint point = polygon.getB2DPoint(j);
+ SAL_INFO ("cppcanvas.emf", "point: " << point.getX() << "," << point.getY());
+ if (polygon.isPrevControlPointUsed(j)) {
+ point = polygon.getPrevControlPoint(j);
+ SAL_INFO ("cppcanvas.emf", "prev: " << point.getX() << "," << point.getY());
+ }
+ if (polygon.isNextControlPointUsed(j)) {
+ point = polygon.getNextControlPoint(j);
+ SAL_INFO ("cppcanvas.emf", "next: " << point.getX() << "," << point.getY());
+ }
+ }
+ }
+#endif
+ }
+
+ return aPolygon;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfppath.hxx b/cppcanvas/source/mtfrenderer/emfppath.hxx
new file mode 100644
index 000000000000..ace3e83ad04d
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfppath.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPATH_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPATH_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct EMFPPath : public EMFPObject
+ {
+ ::basegfx::B2DPolyPolygon aPolygon;
+ sal_Int32 nPoints;
+ float* pPoints;
+ sal_uInt8* pPointTypes;
+
+ EMFPPath(sal_Int32 _nPoints, bool bLines = false);
+
+ virtual ~EMFPPath() override;
+
+ // TODO: remove rR argument when debug code is not longer needed
+ void Read(SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR);
+
+ ::basegfx::B2DPolyPolygon& GetPolygon(ImplRenderer& rR, bool bMapIt = true);
+ };
+ }
+}
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPATH_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfppen.cxx b/cppcanvas/source/mtfrenderer/emfppen.cxx
new file mode 100755
index 000000000000..229e9c945a36
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfppen.cxx
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfppen.hxx>
+#include <emfpcustomlinecap.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ const sal_Int32 EmfPlusLineStyleSolid = 0x00000000;
+ const sal_Int32 EmfPlusLineStyleDash = 0x00000001;
+ const sal_Int32 EmfPlusLineStyleDot = 0x00000002;
+ const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
+ const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
+ const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
+
+ EMFPPen::EMFPPen()
+ : EMFPBrush()
+ , width(0.0)
+ , startCap(0)
+ , endCap(0)
+ , lineJoin(0)
+ , mitterLimit(0.0)
+ , dashStyle(0)
+ , dashCap(0)
+ , dashOffset(0.0)
+ , dashPatternLen(0)
+ , dashPattern(nullptr)
+ , alignment(0)
+ , compoundArrayLen(0)
+ , compoundArray(nullptr)
+ , customStartCapLen(0)
+ , customStartCap(nullptr)
+ , customEndCapLen(0)
+ , customEndCap(nullptr)
+ {
+ }
+
+ EMFPPen::~EMFPPen()
+ {
+ delete[] dashPattern;
+ delete[] compoundArray;
+ delete customStartCap;
+ delete customEndCap;
+ }
+
+ void EMFPPen::SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if (width == 0.0) {
+ SAL_INFO("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
+ }
+#endif
+ rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize(width == 0.0 ? 0.05 : width, 0)).getLength());
+ }
+
+ /// Convert stroke caps between EMF+ and rendering API
+ sal_Int8 EMFPPen::lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
+ {
+ switch (nEmfStroke)
+ {
+ case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
+ case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND;
+ }
+
+ // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
+ // so return BUTT always
+ return rendering::PathCapType::BUTT;
+ }
+
+ sal_Int8 EMFPPen::lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
+ {
+ switch (nEmfLineJoin)
+ {
+ case EmfPlusLineJoinTypeMiter: // fall-through
+ case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
+ case EmfPlusLineJoinTypeBevel: return rendering::PathJoinType::BEVEL;
+ case EmfPlusLineJoinTypeRound: return rendering::PathJoinType::ROUND;
+ }
+ assert(false); // Line Join type isn't in specification.
+ return 0;
+ }
+
+
+ void EMFPPen::SetStrokeAttributes(rendering::StrokeAttributes& rStrokeAttributes)
+ {
+ rStrokeAttributes.JoinType = lcl_convertLineJoinType(lineJoin);
+
+ if (dashStyle != EmfPlusLineStyleSolid)
+ {
+ const float dash[] = { 3, 3 };
+ const float dot[] = { 1, 3 };
+ const float dashdot[] = { 3, 3, 1, 3 };
+ const float dashdotdot[] = { 3, 3, 1, 3, 1, 3 };
+
+ sal_Int32 nLen = 0;
+ const float *pPattern = nullptr;
+ switch (dashStyle)
+ {
+ case EmfPlusLineStyleDash: nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
+ case EmfPlusLineStyleDot: nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
+ case EmfPlusLineStyleDashDot: nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
+ case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
+ case EmfPlusLineStyleCustom: nLen = dashPatternLen; pPattern = dashPattern; break;
+ }
+ if (nLen > 0)
+ {
+ uno::Sequence<double> aDashArray(nLen);
+ for (int i = 0; i < nLen; ++i)
+ aDashArray[i] = pPattern[i];
+
+ rStrokeAttributes.DashArray = aDashArray;
+ }
+ }
+ }
+
+ void EMFPPen::Read(SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32)
+ {
+ sal_uInt32 header, unknown, penFlags, unknown2;
+ int i;
+
+ s.ReadUInt32(header).ReadUInt32(unknown).ReadUInt32(penFlags).ReadUInt32(unknown2).ReadFloat(width);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tpen");
+ SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " unknown: 0x" << unknown <<
+ " additional flags: 0x" << penFlags << " unknown: 0x" << unknown2 << " width: " << std::dec << width);
+
+ if (penFlags & 1)
+ ReadXForm(s, pen_transformation);
+
+ if (penFlags & 2)
+ {
+ s.ReadInt32(startCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstartCap: 0x" << std::hex << startCap);
+ }
+ else
+ startCap = 0;
+
+ if (penFlags & 4)
+ {
+ s.ReadInt32(endCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tendCap: 0x" << std::hex << endCap);
+ }
+ else
+ endCap = 0;
+
+ if (penFlags & 8)
+ s.ReadInt32(lineJoin);
+ else
+ lineJoin = 0;
+
+ if (penFlags & 16)
+ s.ReadFloat(mitterLimit);
+ else
+ mitterLimit = 0;
+
+ if (penFlags & 32)
+ {
+ s.ReadInt32(dashStyle);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tdashStyle: 0x" << std::hex << dashStyle);
+ }
+ else
+ dashStyle = 0;
+
+ if (penFlags & 64)
+ s.ReadInt32(dashCap);
+ else
+ dashCap = 0;
+
+ if (penFlags & 128)
+ s.ReadFloat(dashOffset);
+ else
+ dashOffset = 0;
+
+ if (penFlags & 256)
+ {
+ dashStyle = EmfPlusLineStyleCustom;
+
+ s.ReadInt32(dashPatternLen);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tdashPatternLen: " << dashPatternLen);
+
+ if (dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32 / sizeof(float))
+ dashPatternLen = SAL_MAX_INT32 / sizeof(float);
+ dashPattern = new float[dashPatternLen];
+ for (i = 0; i < dashPatternLen; i++)
+ {
+ s.ReadFloat(dashPattern[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
+ }
+ }
+ else
+ dashPatternLen = 0;
+
+ if (penFlags & 512)
+ s.ReadInt32(alignment);
+ else
+ alignment = 0;
+
+ if (penFlags & 1024) {
+ s.ReadInt32(compoundArrayLen);
+ if (compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32 / sizeof(float))
+ compoundArrayLen = SAL_MAX_INT32 / sizeof(float);
+ compoundArray = new float[compoundArrayLen];
+ for (i = 0; i < compoundArrayLen; i++)
+ s.ReadFloat(compoundArray[i]);
+ }
+ else
+ compoundArrayLen = 0;
+
+ if (penFlags & 2048)
+ {
+ s.ReadInt32(customStartCapLen);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomStartCapLen: " << customStartCapLen);
+ sal_uInt64 const pos = s.Tell();
+
+ customStartCap = new EMFPCustomLineCap();
+ customStartCap->Read(s, rR);
+
+ // maybe we don't read everything yet, play it safe ;-)
+ s.Seek(pos + customStartCapLen);
+ }
+ else
+ customStartCapLen = 0;
+
+ if (penFlags & 4096)
+ {
+ s.ReadInt32(customEndCapLen);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomEndCapLen: " << customEndCapLen);
+ sal_uInt64 const pos = s.Tell();
+
+ customEndCap = new EMFPCustomLineCap();
+ customEndCap->Read(s, rR);
+
+ // maybe we don't read everything yet, play it safe ;-)
+ s.Seek(pos + customEndCapLen);
+ }
+ else
+ customEndCapLen = 0;
+
+ EMFPBrush::Read(s, rR);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfppen.hxx b/cppcanvas/source/mtfrenderer/emfppen.hxx
new file mode 100755
index 000000000000..98ec4468dd68
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfppen.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPEN_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPEN_HXX
+
+#include <emfpbrush.hxx>
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
+ const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
+
+ const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
+ const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
+ const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
+ const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
+
+ struct EMFPCustomLineCap;
+
+ struct EMFPPen : public EMFPBrush
+ {
+ XForm pen_transformation; //TODO: This isn't used
+ float width;
+ sal_Int32 startCap;
+ sal_Int32 endCap;
+ sal_Int32 lineJoin;
+ float mitterLimit;
+ sal_Int32 dashStyle;
+ sal_Int32 dashCap;
+ float dashOffset;
+ sal_Int32 dashPatternLen;
+ float *dashPattern;
+ sal_Int32 alignment;
+ sal_Int32 compoundArrayLen;
+ float *compoundArray;
+ sal_Int32 customStartCapLen;
+ EMFPCustomLineCap *customStartCap;
+ sal_Int32 customEndCapLen;
+ EMFPCustomLineCap *customEndCap;
+
+ EMFPPen();
+
+ virtual ~EMFPPen() override;
+
+ void SetStrokeWidth(com::sun::star::rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState);
+
+ void SetStrokeAttributes(com::sun::star::rendering::StrokeAttributes& rStrokeAttributes);
+
+ void Read(SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32);
+
+ static sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke);
+ static sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin);
+
+ };
+ }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPPEN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpregion.cxx b/cppcanvas/source/mtfrenderer/emfpregion.cxx
new file mode 100755
index 000000000000..99db436fb5aa
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpregion.cxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfpregion.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ EMFPRegion::EMFPRegion()
+ : parts(0)
+ , combineMode(nullptr)
+ , initialState(0)
+ , ix(0.0)
+ , iy(0.0)
+ , iw(0.0)
+ , ih(0.0)
+ {
+ }
+
+ EMFPRegion::~EMFPRegion()
+ {
+ if (combineMode) {
+ delete[] combineMode;
+ combineMode = nullptr;
+ }
+ }
+
+ void EMFPRegion::Read(SvStream& s)
+ {
+ sal_uInt32 header;
+
+ s.ReadUInt32(header).ReadInt32(parts);
+
+ SAL_INFO("cppcanvas.emf", "EMF+\tregion");
+ SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec);
+
+ if (parts) {
+ if (parts<0 || sal_uInt32(parts)>SAL_MAX_INT32 / sizeof(sal_Int32))
+ parts = SAL_MAX_INT32 / sizeof(sal_Int32);
+
+ combineMode = new sal_Int32[parts];
+
+ for (int i = 0; i < parts; i++) {
+ s.ReadInt32(combineMode[i]);
+ SAL_INFO("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode[i] << std::dec);
+ }
+ }
+
+ s.ReadInt32(initialState);
+ SAL_INFO("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpregion.hxx b/cppcanvas/source/mtfrenderer/emfpregion.hxx
new file mode 100755
index 000000000000..876aebcdbd67
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpregion.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPREGION_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPREGION_HXX
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct EMFPRegion : public EMFPObject
+ {
+ sal_Int32 parts;
+ sal_Int32 *combineMode;
+ sal_Int32 initialState;
+ float ix, iy, iw, ih;
+
+ EMFPRegion();
+ virtual ~EMFPRegion() override;
+ void Read(SvStream& s);
+ };
+ }
+}
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPREGION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */