diff options
author | Mark Page <aptitude@btconnect.com> | 2016-11-24 11:33:23 +0000 |
---|---|---|
committer | jan iversen <jani@documentfoundation.org> | 2017-01-23 11:44:45 +0000 |
commit | f671121525b854b6776d7e0ae1ad04d50d7373dc (patch) | |
tree | 233a425f92aca7b77d6d992baf5768f29db6c198 /cppcanvas | |
parent | 04f1d35e7eda2c3b178649610d609ee99342bf41 (diff) |
Split emfplus.cxx into multiple files
This helps make emfplus.cxx more readable.
No source code was changed, only moved except these
renamed to avoid inheritance warnings::
EMFPBrush::transformation renamed to brush_transformation
EMFPPen::transformation renamed to pen_transformation
Change-Id: I6952d6300c9c459833c2dda2b715d851b9e80de7
Reviewed-on: https://gerrit.libreoffice.org/31165
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: jan iversen <jani@documentfoundation.org>
Diffstat (limited to 'cppcanvas')
-rw-r--r-- | cppcanvas/Library_cppcanvas.mk | 7 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpbrush.cxx | 313 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpbrush.hxx | 122 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx | 163 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx | 47 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpfont.cxx | 74 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpfont.hxx | 42 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpimage.cxx | 100 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpimage.hxx | 44 | ||||
-rw-r--r-- | cppcanvas/source/mtfrenderer/emfplus.cxx | 1047 | ||||
-rw-r--r-- | cppcanvas/source/mtfrenderer/emfppath.cxx | 189 | ||||
-rw-r--r-- | cppcanvas/source/mtfrenderer/emfppath.hxx | 48 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfppen.cxx | 284 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfppen.hxx | 80 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpregion.cxx | 94 | ||||
-rwxr-xr-x | cppcanvas/source/mtfrenderer/emfpregion.hxx | 43 |
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: */ |