summaryrefslogtreecommitdiffstats
path: root/drawinglayer/source/tools/emfppen.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drawinglayer/source/tools/emfppen.cxx389
1 files changed, 389 insertions, 0 deletions
diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx
new file mode 100644
index 000000000..c5e7d457b
--- /dev/null
+++ b/drawinglayer/source/tools/emfppen.cxx
@@ -0,0 +1,389 @@
+/* -*- 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 <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+
+#include "emfppen.hxx"
+#include "emfpcustomlinecap.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace emfplushelper
+{
+ namespace {
+
+ enum EmfPlusPenData
+ {
+ PenDataTransform = 0x00000001,
+ PenDataStartCap = 0x00000002,
+ PenDataEndCap = 0x00000004,
+ PenDataJoin = 0x00000008,
+ PenDataMiterLimit = 0x00000010,
+ PenDataLineStyle = 0x00000020,
+ PenDataDashedLineCap = 0x00000040,
+ PenDataDashedLineOffset = 0x00000080,
+ PenDataDashedLine = 0x00000100,
+ PenDataAlignment = 0x00000200,
+ PenDataCompoundLine = 0x00000400,
+ PenDataCustomStartCap = 0x00000800,
+ PenDataCustomEndCap = 0x00001000
+ };
+
+ }
+
+ EMFPPen::EMFPPen()
+ : EMFPBrush()
+ , penDataFlags(0)
+ , penUnit(0)
+ , penWidth(0.0)
+ , startCap(0)
+ , endCap(0)
+ , lineJoin(0)
+ , miterLimit(0.0)
+ , dashStyle(0)
+ , dashCap(0)
+ , dashOffset(0.0)
+ , alignment(0)
+ , customStartCapLen(0)
+ , customEndCapLen(0)
+ {
+ }
+
+ EMFPPen::~EMFPPen()
+ {
+ }
+
+ static OUString PenDataFlagsToString(sal_uInt32 flags)
+ {
+ OUString sFlags;
+
+ if (flags & EmfPlusPenDataTransform)
+ sFlags = "\nEMF+\t\t\tEmfPlusPenDataTransform";
+
+ if (flags & EmfPlusPenDataStartCap)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataStartCap");
+
+ if (flags & EmfPlusPenDataEndCap)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataEndCap");
+
+ if (flags & EmfPlusPenDataJoin)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataJoin");
+
+ if (flags & EmfPlusPenDataMiterLimit)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataMiterLimit");
+
+ if (flags & EmfPlusPenDataLineStyle)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataLineStyle");
+
+ if (flags & EmfPlusPenDataDashedLineCap)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLineCap");
+
+ if (flags & EmfPlusPenDataDashedLineOffset)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLineOffset");
+
+ if (flags & EmfPlusPenDataDashedLine)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataDashedLine");
+
+ if (flags & EmfPlusPenDataAlignment)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataAlignment");
+
+ if (flags & EmfPlusPenDataCompoundLine)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCompoundLine");
+
+ if (flags & EmfPlusPenDataCustomStartCap)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCustomStartCap");
+
+ if (flags & EmfPlusPenDataCustomEndCap)
+ sFlags = sFlags.concat("\nEMF+\t\t\tEmfPlusPenDataCustomEndCap");
+
+ return sFlags;
+ }
+
+ static OUString LineCapTypeToString(sal_uInt32 linecap)
+ {
+ switch (linecap)
+ {
+ case LineCapTypeFlat: return "LineCapTypeFlat";
+ case LineCapTypeSquare: return "LineCapTypeSquare";
+ case LineCapTypeRound: return "LineCapTypeRound";
+ case LineCapTypeTriangle: return "LineCapTypeTriangle";
+ case LineCapTypeNoAnchor: return "LineCapTypeNoAnchor";
+ case LineCapTypeSquareAnchor: return "LineCapTypeSquareAnchor";
+ case LineCapTypeRoundAnchor: return "LineCapTypeRoundAchor";
+ case LineCapTypeDiamondAnchor: return "LineCapTypeDiamondAnchor";
+ case LineCapTypeArrowAnchor: return "LineCapTypeArrowAnchor";
+ case LineCapTypeAnchorMask: return "LineCapTypeAnchorMask";
+ case LineCapTypeCustom: return "LineCapTypeCustom";
+ }
+ return "";
+ }
+
+ static OUString LineJoinTypeToString(sal_uInt32 jointype)
+ {
+ switch (jointype)
+ {
+ case LineJoinTypeMiter: return "LineJoinTypeMiter";
+ case LineJoinTypeBevel: return "LineJoinTypeBevel";
+ case LineJoinTypeRound: return "LineJoinTypeRound";
+ case LineJoinTypeMiterClipped: return "LineJoinTypeMiterClipped";
+ }
+ return "";
+ }
+
+ static OUString DashedLineCapTypeToString(sal_uInt32 dashedlinecaptype)
+ {
+ switch (dashedlinecaptype)
+ {
+ case DashedLineCapTypeFlat: return "DashedLineCapTypeFlat";
+ case DashedLineCapTypeRound: return "DashedLineCapTypeRound";
+ case DashedLineCapTypeTriangle: return "DashedLineCapTypeTriangle";
+ }
+ return "";
+ }
+
+ static OUString PenAlignmentToString(sal_uInt32 alignment)
+ {
+ switch (alignment)
+ {
+ case PenAlignmentCenter: return "PenAlignmentCenter";
+ case PenAlignmentInset: return "PenAlignmentInset";
+ case PenAlignmentLeft: return "PenAlignmentLeft";
+ case PenAlignmentOutset: return "PenAlignmentOutset";
+ case PenAlignmentRight: return "PenAlignmentRight";
+ }
+ return "";
+ }
+
+ /// 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::Read(SvStream& s, EmfPlusHelperData const & rR)
+ {
+ sal_uInt32 graphicsVersion, penType;
+ int i;
+ s.ReadUInt32(graphicsVersion).ReadUInt32(penType).ReadUInt32(penDataFlags).ReadUInt32(penUnit).ReadFloat(penWidth);
+ SAL_INFO("drawinglayer", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion);
+ SAL_INFO("drawinglayer", "EMF+\t\tType: " << penType);
+ SAL_INFO("drawinglayer", "EMF+\t\tPen data flags: 0x" << penDataFlags << PenDataFlagsToString(penDataFlags));
+ SAL_INFO("drawinglayer", "EMF+\t\tUnit: " << UnitTypeToString(penUnit));
+ SAL_INFO("drawinglayer", "EMF+\t\tWidth: " << std::dec << penWidth);
+
+ // If a zero width is specified, a minimum value must be used, which is determined by the units
+ if (penWidth == 0.0)
+ { //TODO Check if these values is correct
+ penWidth = penUnit == 0 ? 0.18f
+ : 0.05f; // 0.05f is taken from old EMF+ implementation (case of Unit == Pixel etc.)
+ }
+
+ if (penDataFlags & PenDataTransform)
+ {
+ EmfPlusHelperData::readXForm(s, pen_transformation);
+ SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataTransform: " << pen_transformation);
+ }
+
+ if (penDataFlags & PenDataStartCap)
+ {
+ s.ReadInt32(startCap);
+ SAL_INFO("drawinglayer", "EMF+\t\tstartCap: " << LineCapTypeToString(startCap) << " (0x" << std::hex << startCap << ")");
+ }
+ else
+ {
+ startCap = 0;
+ }
+
+ if (penDataFlags & PenDataEndCap)
+ {
+ s.ReadInt32(endCap);
+ SAL_INFO("drawinglayer", "EMF+\t\tendCap: " << LineCapTypeToString(endCap) << " (0x" << std::hex << startCap << ")");
+ }
+ else
+ {
+ endCap = 0;
+ }
+
+ if (penDataFlags & PenDataJoin)
+ {
+ s.ReadInt32(lineJoin);
+ SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataJoin: " << LineJoinTypeToString(lineJoin) << " (0x" << std::hex << lineJoin << ")");
+ }
+ else
+ {
+ lineJoin = 0;
+ }
+
+ if (penDataFlags & PenDataMiterLimit)
+ {
+ s.ReadFloat(miterLimit);
+ SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataMiterLimit: " << std::dec << miterLimit);
+ }
+ else
+ {
+ miterLimit = 0;
+ }
+
+ if (penDataFlags & PenDataLineStyle)
+ {
+ s.ReadInt32(dashStyle);
+ SAL_INFO("drawinglayer", "EMF+\t\tdashStyle: " << DashedLineCapTypeToString(dashStyle) << " (0x" << std::hex << dashStyle << ")");
+ }
+ else
+ {
+ dashStyle = 0;
+ }
+
+ if (penDataFlags & PenDataDashedLineCap)
+ {
+ s.ReadInt32(dashCap);
+ SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineCap: 0x" << std::hex << dashCap);
+ }
+ else
+ {
+ dashCap = 0;
+ }
+
+ if (penDataFlags & PenDataDashedLineOffset)
+ {
+ s.ReadFloat(dashOffset);
+ SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineOffset: 0x" << std::hex << dashOffset);
+ }
+ else
+ {
+ dashOffset = 0;
+ }
+
+ if (penDataFlags & PenDataDashedLine)
+ {
+ dashStyle = EmfPlusLineStyleCustom;
+ sal_Int32 dashPatternLen;
+
+ s.ReadInt32(dashPatternLen);
+ SAL_INFO("drawinglayer", "EMF+\t\t\tdashPatternLen: " << dashPatternLen);
+
+ if (dashPatternLen<0 || o3tl::make_unsigned(dashPatternLen)>SAL_MAX_INT32 / sizeof(float))
+ {
+ dashPatternLen = SAL_MAX_INT32 / sizeof(float);
+ }
+
+ dashPattern.resize( dashPatternLen );
+
+ for (i = 0; i < dashPatternLen; i++)
+ {
+ s.ReadFloat(dashPattern[i]);
+ SAL_INFO("drawinglayer", "EMF+\t\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
+ }
+ }
+
+ if (penDataFlags & PenDataAlignment)
+ {
+ s.ReadInt32(alignment);
+ SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataAlignment: " << PenAlignmentToString(alignment) << " (0x" << std::hex << alignment << ")");
+ }
+ else
+ {
+ alignment = 0;
+ }
+
+ if (penDataFlags & PenDataCompoundLine)
+ {
+ SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataCompoundLine");
+ sal_Int32 compoundArrayLen;
+ s.ReadInt32(compoundArrayLen);
+
+ if (compoundArrayLen<0 || o3tl::make_unsigned(compoundArrayLen)>SAL_MAX_INT32 / sizeof(float))
+ {
+ compoundArrayLen = SAL_MAX_INT32 / sizeof(float);
+ }
+
+ compoundArray.resize(compoundArrayLen);
+
+ for (i = 0; i < compoundArrayLen; i++)
+ {
+ s.ReadFloat(compoundArray[i]);
+ SAL_INFO("drawinglayer", "EMF+\t\t\t\tcompoundArray[" << i << "]: " << compoundArray[i]);
+ }
+ }
+
+ if (penDataFlags & PenDataCustomStartCap)
+ {
+ s.ReadInt32(customStartCapLen);
+ SAL_INFO("drawinglayer", "EMF+\t\t\tcustomStartCapLen: " << customStartCapLen);
+ sal_uInt64 const pos = s.Tell();
+
+ customStartCap.reset( new EMFPCustomLineCap() );
+ customStartCap->Read(s, rR);
+
+ // maybe we don't read everything yet, play it safe ;-)
+ s.Seek(pos + customStartCapLen);
+ }
+ else
+ {
+ customStartCapLen = 0;
+ }
+
+ if (penDataFlags & PenDataCustomEndCap)
+ {
+ s.ReadInt32(customEndCapLen);
+ SAL_INFO("drawinglayer", "EMF+\t\t\tcustomEndCapLen: " << customEndCapLen);
+ sal_uInt64 const pos = s.Tell();
+
+ customEndCap.reset( 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: */