summaryrefslogtreecommitdiff
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
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>
-rw-r--r--cppcanvas/Library_cppcanvas.mk7
-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
16 files changed, 1664 insertions, 1033 deletions
diff --git a/cppcanvas/Library_cppcanvas.mk b/cppcanvas/Library_cppcanvas.mk
index 893918dbec9a..13841d227880 100644
--- a/cppcanvas/Library_cppcanvas.mk
+++ b/cppcanvas/Library_cppcanvas.mk
@@ -50,7 +50,14 @@ $(eval $(call gb_Library_use_libraries,cppcanvas,\
$(eval $(call gb_Library_add_exception_objects,cppcanvas,\
cppcanvas/source/mtfrenderer/bitmapaction \
cppcanvas/source/mtfrenderer/cachedprimitivebase \
+ cppcanvas/source/mtfrenderer/emfpbrush \
+ cppcanvas/source/mtfrenderer/emfpcustomlinecap \
+ cppcanvas/source/mtfrenderer/emfpfont \
+ cppcanvas/source/mtfrenderer/emfpimage \
cppcanvas/source/mtfrenderer/emfplus \
+ cppcanvas/source/mtfrenderer/emfppen \
+ cppcanvas/source/mtfrenderer/emfppath \
+ cppcanvas/source/mtfrenderer/emfpregion \
cppcanvas/source/mtfrenderer/implrenderer \
cppcanvas/source/mtfrenderer/lineaction \
cppcanvas/source/mtfrenderer/mtftools \
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: */