summaryrefslogtreecommitdiffstats
path: root/filter/source/graphicfilter
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/graphicfilter')
-rw-r--r--filter/source/graphicfilter/icgm/actimpr.cxx1041
-rw-r--r--filter/source/graphicfilter/icgm/bitmap.cxx433
-rw-r--r--filter/source/graphicfilter/icgm/bitmap.hxx81
-rw-r--r--filter/source/graphicfilter/icgm/bundles.cxx141
-rw-r--r--filter/source/graphicfilter/icgm/bundles.hxx166
-rw-r--r--filter/source/graphicfilter/icgm/cgm.cxx741
-rw-r--r--filter/source/graphicfilter/icgm/cgm.hxx151
-rw-r--r--filter/source/graphicfilter/icgm/cgmtypes.hxx127
-rw-r--r--filter/source/graphicfilter/icgm/chart.cxx57
-rw-r--r--filter/source/graphicfilter/icgm/chart.hxx84
-rw-r--r--filter/source/graphicfilter/icgm/class0.cxx128
-rw-r--r--filter/source/graphicfilter/icgm/class1.cxx225
-rw-r--r--filter/source/graphicfilter/icgm/class2.cxx233
-rw-r--r--filter/source/graphicfilter/icgm/class3.cxx134
-rw-r--r--filter/source/graphicfilter/icgm/class4.cxx911
-rw-r--r--filter/source/graphicfilter/icgm/class5.cxx532
-rw-r--r--filter/source/graphicfilter/icgm/class7.cxx210
-rw-r--r--filter/source/graphicfilter/icgm/classx.cxx249
-rw-r--r--filter/source/graphicfilter/icgm/elements.cxx336
-rw-r--r--filter/source/graphicfilter/icgm/elements.hxx136
-rw-r--r--filter/source/graphicfilter/icgm/outact.hxx108
21 files changed, 6224 insertions, 0 deletions
diff --git a/filter/source/graphicfilter/icgm/actimpr.cxx b/filter/source/graphicfilter/icgm/actimpr.cxx
new file mode 100644
index 000000000..c77b55184
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/actimpr.cxx
@@ -0,0 +1,1041 @@
+/* -*- 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 <sal/config.h>
+#include <sal/log.hxx>
+
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <vcl/bitmapex.hxx>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/Hatch.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/drawing/XShapeGrouper.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
+#include <com/sun/star/drawing/ShapeCollection.hpp>
+#include <com/sun/star/drawing/TextAdjust.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/helpers.hxx>
+#include <unotools/configmgr.hxx>
+
+#include "bitmap.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+#define MAX_PAGES_FOR_FUZZING 2048
+
+using namespace ::com::sun::star;
+
+CGMImpressOutAct::CGMImpressOutAct(CGM& rCGM, const uno::Reference< frame::XModel > & rModel)
+ : mnCurrentPage(0)
+ , mnGroupActCount(0)
+ , mnGroupLevel(0)
+ , maGroupLevel()
+ , mpCGM(&rCGM)
+ , nFinalTextCount(0)
+{
+ if ( !mpCGM->mbStatus )
+ return;
+
+ bool bStatRet = false;
+
+ uno::Reference< drawing::XDrawPagesSupplier > aDrawPageSup( rModel, uno::UNO_QUERY );
+ if( aDrawPageSup.is() )
+ {
+ maXDrawPages = aDrawPageSup->getDrawPages();
+ if ( maXDrawPages.is() )
+ {
+ maXMultiServiceFactory.set( rModel, uno::UNO_QUERY);
+ if( maXMultiServiceFactory.is() )
+ {
+ maXDrawPage = *o3tl::doAccess<uno::Reference<drawing::XDrawPage>>(maXDrawPages->getByIndex( 0 ));
+ if ( ImplInitPage() )
+ bStatRet = true;
+ }
+ }
+ }
+ mpCGM->mbStatus = bStatRet;
+}
+
+CGMImpressOutAct::~CGMImpressOutAct()
+{
+ for (auto &a : maLockedNewXShapes)
+ a->removeActionLock();
+}
+
+bool CGMImpressOutAct::ImplInitPage()
+{
+ bool bStatRet = false;
+ if( maXDrawPage.is() )
+ {
+ maXShapes = maXDrawPage;
+ if ( maXShapes.is() )
+ {
+ bStatRet = true;
+ }
+ }
+ return bStatRet;
+}
+
+bool CGMImpressOutAct::ImplCreateShape( const OUString& rType )
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return false;
+ uno::Reference< uno::XInterface > xNewShape( maXMultiServiceFactory->createInstance( rType ) );
+ maXShape.set( xNewShape, uno::UNO_QUERY );
+ maXPropSet.set( xNewShape, uno::UNO_QUERY );
+ if ( maXShape.is() && maXPropSet.is() )
+ {
+ maXShapes->add( maXShape );
+ uno::Reference<document::XActionLockable> xLockable(maXShape, uno::UNO_QUERY);
+ if (xLockable)
+ {
+ xLockable->addActionLock();
+ maLockedNewXShapes.push_back(xLockable);
+ }
+ return true;
+ }
+ return false;
+}
+
+void CGMImpressOutAct::ImplSetOrientation( FloatPoint const & rRefPoint, double rOrientation )
+{
+ maXPropSet->setPropertyValue( "RotationPointX", uno::Any(static_cast<sal_Int32>(rRefPoint.X)) );
+ maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>(rRefPoint.Y)) );
+ maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( rOrientation * 100.0 )) );
+}
+
+
+void CGMImpressOutAct::ImplSetLineBundle()
+{
+ drawing::LineStyle eLS;
+
+ sal_uInt32 nLineColor;
+ LineType eLineType;
+ double fLineWidth;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINECOLOR )
+ nLineColor = mpCGM->pElement->pLineBundle->GetColor();
+ else
+ nLineColor = mpCGM->pElement->aLineBundle.GetColor();
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINETYPE )
+ eLineType = mpCGM->pElement->pLineBundle->eLineType;
+ else
+ eLineType = mpCGM->pElement->aLineBundle.eLineType;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINEWIDTH )
+ fLineWidth = mpCGM->pElement->pLineBundle->nLineWidth;
+ else
+ fLineWidth = mpCGM->pElement->aLineBundle.nLineWidth;
+
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nLineColor)) );
+
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fLineWidth)) );
+
+ switch( eLineType )
+ {
+ case LT_NONE :
+ eLS = drawing::LineStyle_NONE;
+ break;
+ case LT_DASH :
+ case LT_DOT :
+ case LT_DASHDOT :
+ case LT_DOTDOTSPACE :
+ case LT_LONGDASH :
+ case LT_DASHDASHDOT :
+ eLS = drawing::LineStyle_DASH;
+ break;
+ case LT_SOLID :
+ default:
+ eLS = drawing::LineStyle_SOLID;
+ break;
+ }
+ maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
+ if ( eLS == drawing::LineStyle_DASH )
+ {
+ drawing::LineDash aLineDash( drawing::DashStyle_RECTRELATIVE, 1, 50, 3, 33, 100 );
+ maXPropSet->setPropertyValue( "LineDash", uno::Any(aLineDash) );
+ }
+}
+
+void CGMImpressOutAct::ImplSetFillBundle()
+{
+ drawing::LineStyle eLS;
+ drawing::FillStyle eFS;
+
+ sal_uInt32 nEdgeColor = 0;
+ EdgeType eEdgeType;
+ double fEdgeWidth = 0;
+
+ sal_uInt32 nFillColor;
+ FillInteriorStyle eFillStyle;
+ sal_uInt32 nHatchIndex;
+
+ if ( mpCGM->pElement->eEdgeVisibility == EV_ON )
+ {
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGETYPE )
+ eEdgeType = mpCGM->pElement->pEdgeBundle->eEdgeType;
+ else
+ eEdgeType = mpCGM->pElement->aEdgeBundle.eEdgeType;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGEWIDTH )
+ fEdgeWidth = mpCGM->pElement->pEdgeBundle->nEdgeWidth;
+ else
+ fEdgeWidth = mpCGM->pElement->aEdgeBundle.nEdgeWidth;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGECOLOR )
+ nEdgeColor = mpCGM->pElement->pEdgeBundle->GetColor();
+ else
+ nEdgeColor = mpCGM->pElement->aEdgeBundle.GetColor();
+ }
+ else
+ eEdgeType = ET_NONE;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ eFillStyle = mpCGM->pElement->pFillBundle->eFillInteriorStyle;
+ else
+ eFillStyle = mpCGM->pElement->aFillBundle.eFillInteriorStyle;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLCOLOR )
+ nFillColor = mpCGM->pElement->pFillBundle->GetColor();
+ else
+ nFillColor = mpCGM->pElement->aFillBundle.GetColor();
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_HATCHINDEX )
+ nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->pFillBundle->nFillHatchIndex);
+ else
+ nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->aFillBundle.nFillHatchIndex);
+
+ maXPropSet->setPropertyValue( "FillColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
+
+ switch ( eFillStyle )
+ {
+ case FIS_HATCH :
+ {
+ if ( nHatchIndex == 0 )
+ eFS = drawing::FillStyle_NONE;
+ else
+ eFS = drawing::FillStyle_HATCH;
+ }
+ break;
+ case FIS_PATTERN :
+ case FIS_SOLID :
+ {
+ eFS = drawing::FillStyle_SOLID;
+ }
+ break;
+
+ case FIS_GEOPATTERN :
+ {
+ if ( mpCGM->pElement->eTransparency == T_ON )
+ nFillColor = mpCGM->pElement->nAuxiliaryColor;
+ eFS = drawing::FillStyle_NONE;
+ }
+ break;
+
+ case FIS_INTERPOLATED :
+ case FIS_GRADIENT :
+ {
+ eFS = drawing::FillStyle_GRADIENT;
+ }
+ break;
+
+ case FIS_HOLLOW :
+ case FIS_EMPTY :
+ default:
+ {
+ eFS = drawing::FillStyle_NONE;
+ }
+ }
+
+ if ( mpCGM->mnAct4PostReset & ACT4_GRADIENT_ACTION )
+ eFS = drawing::FillStyle_GRADIENT;
+
+ if ( eFS == drawing::FillStyle_GRADIENT )
+ {
+ maXPropSet->setPropertyValue( "FillGradient", uno::Any(*mpGradient) );
+ }
+ maXPropSet->setPropertyValue( "FillStyle", uno::Any(eFS) );
+
+ eLS = drawing::LineStyle_NONE;
+ if ( eFillStyle == FIS_HOLLOW )
+ {
+ eLS = drawing::LineStyle_SOLID;
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(sal_Int32(0)) );
+ }
+ else if ( eEdgeType != ET_NONE )
+ {
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nEdgeColor)) );
+
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fEdgeWidth)) );
+
+ switch( eEdgeType )
+ {
+ case ET_DASH :
+ case ET_DOT :
+ case ET_DASHDOT :
+ case ET_DASHDOTDOT :
+ case ET_DOTDOTSPACE :
+ case ET_LONGDASH :
+ case ET_DASHDASHDOT :
+ default: // case ET_SOLID :
+ {
+ eLS = drawing::LineStyle_SOLID;
+ }
+ break;
+ }
+ }
+
+ maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
+
+ if ( eFS != drawing::FillStyle_HATCH )
+ return;
+
+ drawing::Hatch aHatch;
+
+ aHatch.Color = nFillColor;
+ if ( mpCGM->pElement->maHatchMap.find( nHatchIndex ) != mpCGM->pElement->maHatchMap.end() )
+ {
+ HatchEntry& rHatchEntry = mpCGM->pElement->maHatchMap[ nHatchIndex ];
+ switch ( rHatchEntry.HatchStyle )
+ {
+ case 0 : aHatch.Style = drawing::HatchStyle_SINGLE; break;
+ case 1 : aHatch.Style = drawing::HatchStyle_DOUBLE; break;
+ case 2 : aHatch.Style = drawing::HatchStyle_TRIPLE; break;
+ }
+ aHatch.Distance = rHatchEntry.HatchDistance;
+ aHatch.Angle = rHatchEntry.HatchAngle;
+ }
+ else
+ {
+ aHatch.Style = drawing::HatchStyle_TRIPLE;
+ aHatch.Distance = 10 * ( nHatchIndex & 0x1f ) | 100;
+ aHatch.Angle = 15 * ( ( nHatchIndex & 0x1f ) - 5 );
+ }
+ maXPropSet->setPropertyValue( "FillHatch", uno::Any(aHatch) );
+}
+
+void CGMImpressOutAct::ImplSetTextBundle( const uno::Reference< beans::XPropertySet > & rProperty )
+{
+ sal_uInt32 nTextFontIndex;
+ sal_uInt32 nTextColor;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTFONTINDEX )
+ nTextFontIndex = mpCGM->pElement->pTextBundle->nTextFontIndex;
+ else
+ nTextFontIndex = mpCGM->pElement->aTextBundle.nTextFontIndex;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTCOLOR )
+ nTextColor = mpCGM->pElement->pTextBundle->GetColor();
+ else
+ nTextColor = mpCGM->pElement->aTextBundle.GetColor();
+
+ rProperty->setPropertyValue( "CharColor", uno::Any(static_cast<sal_Int32>(nTextColor)) );
+
+ sal_uInt32 nFontType = 0;
+ awt::FontDescriptor aFontDescriptor;
+ FontEntry* pFontEntry = mpCGM->pElement->aFontList.GetFontEntry( nTextFontIndex );
+ if ( pFontEntry )
+ {
+ nFontType = pFontEntry->nFontType;
+ aFontDescriptor.Name = OUString(reinterpret_cast<char*>(pFontEntry->aFontName.data()),
+ pFontEntry->aFontName.size(),
+ RTL_TEXTENCODING_ASCII_US);
+ }
+ aFontDescriptor.Height = sal_Int16( mpCGM->pElement->nCharacterHeight * 1.50 );
+ if ( nFontType & 1 )
+ aFontDescriptor.Slant = awt::FontSlant_ITALIC;
+ if ( nFontType & 2 )
+ aFontDescriptor.Weight = awt::FontWeight::BOLD;
+ else
+ aFontDescriptor.Weight = awt::FontWeight::NORMAL;
+
+ if ( mpCGM->pElement->eUnderlineMode != UM_OFF )
+ {
+ aFontDescriptor.Underline = awt::FontUnderline::SINGLE;
+ }
+ rProperty->setPropertyValue( "FontDescriptor", uno::Any(aFontDescriptor) );
+}
+
+void CGMImpressOutAct::InsertPage()
+{
+ if ( mnCurrentPage ) // one side is always existing, therefore the first side will be left out
+ {
+ uno::Reference< drawing::XDrawPage > xPage = maXDrawPages->insertNewByIndex( 0xffff );
+ maXDrawPage = xPage;
+ if ( !ImplInitPage() )
+ mpCGM->mbStatus = false;
+ if (mnCurrentPage > MAX_PAGES_FOR_FUZZING && utl::ConfigManager::IsFuzzing())
+ {
+ // ofz#21753 that's enough pages for fuzzing, we're not doing anything productive now
+ mpCGM->mbStatus = false;
+ }
+ }
+ mnCurrentPage++;
+}
+
+void CGMImpressOutAct::BeginGroup()
+{
+ if ( mnGroupLevel < CGM_OUTACT_MAX_GROUP_LEVEL )
+ {
+ maGroupLevel[mnGroupLevel] = maXShapes->getCount();
+ }
+ ++mnGroupLevel;
+ mnGroupActCount = mpCGM->mnActCount;
+}
+
+void CGMImpressOutAct::EndGroup()
+{
+ if (!mnGroupLevel)
+ return;
+ --mnGroupLevel;
+ if ( mnGroupLevel >= CGM_OUTACT_MAX_GROUP_LEVEL )
+ return;
+
+ sal_uInt32 nFirstIndex = maGroupLevel[mnGroupLevel];
+ if ( nFirstIndex == 0xffffffff )
+ nFirstIndex = 0;
+ sal_uInt32 nCurrentCount = maXShapes->getCount();
+ if ( ( nCurrentCount - nFirstIndex ) <= 1 )
+ return;
+
+ uno::Reference< drawing::XShapeGrouper > aXShapeGrouper;
+ aXShapeGrouper.set( maXDrawPage, uno::UNO_QUERY );
+ if( !aXShapeGrouper.is() )
+ return;
+
+ uno::Reference< drawing::XShapes > aXShapes = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
+ for ( sal_uInt32 i = nFirstIndex; i < nCurrentCount; i++ )
+ {
+ uno::Reference< drawing::XShape > aXShape = *o3tl::doAccess<uno::Reference<drawing::XShape>>(maXShapes->getByIndex( i ));
+ if (aXShape.is() )
+ {
+ aXShapes->add( aXShape );
+ }
+ }
+ aXShapeGrouper->group( aXShapes );
+}
+
+void CGMImpressOutAct::EndGrouping()
+{
+ while ( mnGroupLevel )
+ {
+ EndGroup();
+ }
+}
+
+void CGMImpressOutAct::DrawRectangle( FloatRect const & rFloatRect )
+{
+ if (mnGroupActCount == (mpCGM->mnActCount - 1)) // POWERPOINT HACK !!!
+ return;
+ if (useless(rFloatRect.Left))
+ {
+ SAL_WARN("filter.icgm", "bad left: " << rFloatRect.Left);
+ return;
+ }
+ if (useless(rFloatRect.Top))
+ {
+ SAL_WARN("filter.icgm", "bad top: " << rFloatRect.Top);
+ return;
+ }
+ double fWidth = rFloatRect.Right - rFloatRect.Left;
+ if (useless(fWidth))
+ {
+ SAL_WARN("filter.icgm", "bad width: " << fWidth);
+ return;
+ }
+ double fHeight = rFloatRect.Bottom - rFloatRect.Top;
+ if (useless(fHeight))
+ {
+ SAL_WARN("filter.icgm", "bad height: " << fHeight);
+ return;
+ }
+ if (!ImplCreateShape( "com.sun.star.drawing.RectangleShape"))
+ return;
+ maXShape->setSize(awt::Size(fWidth, fHeight));
+ maXShape->setPosition(awt::Point(rFloatRect.Left, rFloatRect.Top));
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawEllipse( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation )
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
+ return;
+
+ drawing::CircleKind eCircleKind = drawing::CircleKind_FULL;
+ uno::Any aAny( &eCircleKind, ::cppu::UnoType<drawing::CircleKind>::get() );
+ maXPropSet->setPropertyValue( "CircleKind", aAny );
+
+ tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
+ tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
+ if ( nXSize < 1 )
+ nXSize = 1;
+ if ( nYSize < 1 )
+ nYSize = 1;
+ maXShape->setSize( awt::Size( nXSize, nYSize ) );
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
+
+ if ( rOrientation != 0 )
+ {
+ ImplSetOrientation( rCenter, rOrientation );
+ }
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawEllipticalArc( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation,
+ sal_uInt32 nType, double& fStartAngle, double& fEndAngle )
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
+ return;
+
+ uno::Any aAny;
+ drawing::CircleKind eCircleKind;
+
+
+ tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
+ tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
+ if ( nXSize < 1 )
+ nXSize = 1;
+ if ( nYSize < 1 )
+ nYSize = 1;
+
+ maXShape->setSize( awt::Size ( nXSize, nYSize ) );
+
+ if ( rOrientation != 0 )
+ {
+ fStartAngle = NormAngle360(fStartAngle + rOrientation);
+ fEndAngle = NormAngle360(fEndAngle + rOrientation);
+ }
+ switch( nType )
+ {
+ case 0 : eCircleKind = drawing::CircleKind_SECTION; break;
+ case 1 : eCircleKind = drawing::CircleKind_CUT; break;
+ case 2 : eCircleKind = drawing::CircleKind_ARC; break;
+ default : eCircleKind = drawing::CircleKind_FULL; break;
+ }
+ if ( static_cast<tools::Long>(fStartAngle) == static_cast<tools::Long>(fEndAngle) )
+ {
+ eCircleKind = drawing::CircleKind_FULL;
+ maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
+ }
+ else
+ {
+ maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
+ maXPropSet->setPropertyValue( "CircleStartAngle", uno::Any(static_cast<sal_Int32>( fStartAngle * 100 )) );
+ maXPropSet->setPropertyValue( "CircleEndAngle", uno::Any(static_cast<sal_Int32>( fEndAngle * 100 )) );
+ }
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
+ if ( rOrientation != 0 )
+ {
+ ImplSetOrientation( rCenter, rOrientation );
+ }
+ if ( eCircleKind == drawing::CircleKind_ARC )
+ {
+ ImplSetLineBundle();
+ }
+ else
+ {
+ ImplSetFillBundle();
+ if ( nType == 2 )
+ {
+ ImplSetLineBundle();
+ aAny <<= drawing::FillStyle_NONE;
+ maXPropSet->setPropertyValue( "FillStyle", aAny );
+ }
+ }
+}
+
+void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
+{
+ if ( !pBmpDesc->mbStatus || pBmpDesc->mxBitmap.IsEmpty() )
+ return;
+
+ FloatPoint aOrigin = pBmpDesc->mnOrigin;
+ double fdx = pBmpDesc->mndx;
+ double fdy = pBmpDesc->mndy;
+
+ BmpMirrorFlags nMirr = BmpMirrorFlags::NONE;
+ if ( pBmpDesc->mbVMirror )
+ nMirr |= BmpMirrorFlags::Vertical;
+ if ( nMirr != BmpMirrorFlags::NONE )
+ pBmpDesc->mxBitmap.Mirror( nMirr );
+
+ mpCGM->ImplMapPoint( aOrigin );
+ mpCGM->ImplMapX( fdx );
+ mpCGM->ImplMapY( fdy );
+
+ if ( !ImplCreateShape( "com.sun.star.drawing.GraphicObjectShape" ) )
+ return;
+
+ maXShape->setSize( awt::Size( static_cast<tools::Long>(fdx), static_cast<tools::Long>(fdy) ) );
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>(aOrigin.X), static_cast<tools::Long>(aOrigin.Y) ) );
+
+ if ( pBmpDesc->mnOrientation != 0 )
+ {
+ ImplSetOrientation( aOrigin, pBmpDesc->mnOrientation );
+ }
+
+ uno::Reference< awt::XBitmap > xBitmap( VCLUnoHelper::CreateBitmap( pBmpDesc->mxBitmap ) );
+ maXPropSet->setPropertyValue( "GraphicObjectFillBitmap", uno::Any(xBitmap) );
+}
+
+void CGMImpressOutAct::DrawPolygon( tools::Polygon& rPoly )
+{
+ sal_uInt16 nPoints = rPoly.GetSize();
+
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyPolygonShape" )) )
+ return;
+
+ drawing::PointSequenceSequence aRetval;
+
+ // prepare inside polygons
+ aRetval.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ for( sal_uInt16 n = 0; n < nPoints; n++ )
+ *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
+
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygon", aParam );
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawPolyLine( tools::Polygon& rPoly )
+{
+ sal_uInt16 nPoints = rPoly.GetSize();
+
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyLineShape" )) )
+ return;
+
+ drawing::PointSequenceSequence aRetval;
+
+ // prepare inside polygons
+ aRetval.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ for( sal_uInt16 n = 0; n < nPoints; n++ )
+ *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
+
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygon", aParam );
+ ImplSetLineBundle();
+}
+
+void CGMImpressOutAct::DrawPolybezier( tools::Polygon& rPolygon )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.OpenBezierShape" )) )
+ return;
+
+ drawing::PolyPolygonBezierCoords aRetval;
+
+ aRetval.Coordinates.realloc( 1 );
+ aRetval.Flags.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
+ drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc( nPoints );
+ pOuterFlags->realloc( nPoints );
+
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+ drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
+
+ for( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ *pInnerSequence++ = awt::Point( rPolygon[ i ].X(), rPolygon[ i ].Y() );
+ *pInnerFlags++ = static_cast<drawing::PolygonFlags>(rPolygon.GetFlags( i ));
+ }
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam );
+ ImplSetLineBundle();
+}
+
+void CGMImpressOutAct::DrawPolyPolygon( tools::PolyPolygon const & rPolyPolygon )
+{
+ sal_uInt32 nNumPolys = rPolyPolygon.Count();
+ if ( !(nNumPolys && ImplCreateShape( "com.sun.star.drawing.ClosedBezierShape" )) )
+ return;
+
+ drawing::PolyPolygonBezierCoords aRetval;
+
+ // prepare inside polygons
+ aRetval.Coordinates.realloc(static_cast<sal_Int32>(nNumPolys));
+ aRetval.Flags.realloc(static_cast<sal_Int32>(nNumPolys));
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
+ drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
+
+ for( sal_uInt32 a = 0; a < nNumPolys; a++ )
+ {
+ const tools::Polygon& aPolygon( rPolyPolygon.GetObject( a ) );
+ sal_uInt32 nNumPoints = aPolygon.GetSize();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nNumPoints));
+ pOuterFlags->realloc(static_cast<sal_Int32>(nNumPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+ drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
+
+ for( sal_uInt32 b = 0; b < nNumPoints; b++ )
+ {
+ *pInnerSequence++ = awt::Point( aPolygon.GetPoint( b ).X(), aPolygon.GetPoint( b ).Y() ) ;
+ *pInnerFlags++ = static_cast<drawing::PolygonFlags>(aPolygon.GetFlags( b ));
+ }
+ pOuterSequence++;
+ pOuterFlags++;
+ }
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam);
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawText(awt::Point const & rTextPos, awt::Size const & rTextSize, const OUString& rString, FinalFlag eFlag)
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.TextShape" ) )
+ return;
+
+ uno::Any aAny;
+ tools::Long nWidth = rTextSize.Width;
+ tools::Long nHeight = rTextSize.Height;
+
+ awt::Point aTextPos( rTextPos );
+ switch ( mpCGM->pElement->eTextAlignmentV )
+ {
+ case TAV_HALF :
+ {
+ aTextPos.Y = o3tl::saturating_add(aTextPos.X, static_cast<sal_Int32>((mpCGM->pElement->nCharacterHeight * -1.5) / 2));
+ }
+ break;
+
+ case TAV_BASE :
+ case TAV_BOTTOM :
+ case TAV_NORMAL :
+ aTextPos.Y = o3tl::saturating_add(aTextPos.Y, static_cast<sal_Int32>(mpCGM->pElement->nCharacterHeight * -1.5));
+ break;
+ case TAV_TOP :
+ break;
+ case TAV_CAP:
+ case TAV_CONT:
+ break; // -Wall these two were not here.
+ }
+
+ if ( nWidth < 0 )
+ {
+ nWidth = -nWidth;
+ }
+ else if ( nWidth == 0 )
+ {
+ nWidth = -1;
+ }
+ if ( nHeight < 0 )
+ {
+ nHeight = -nHeight;
+ }
+ else if ( nHeight == 0 )
+ {
+ nHeight = -1;
+ }
+ maXShape->setPosition( aTextPos );
+ maXShape->setSize( awt::Size( nWidth, nHeight ) );
+ double nX = mpCGM->pElement->nCharacterOrientation[ 2 ];
+ double nY = mpCGM->pElement->nCharacterOrientation[ 3 ];
+ double fSqrt = std::hypot(nX, nY);
+ double nOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY < 0 )
+ nOrientation = 360 - nOrientation;
+
+ if ( nOrientation )
+ {
+ maXPropSet->setPropertyValue( "RotationPointX", uno::Any(aTextPos.X) );
+ maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>( aTextPos.Y + nHeight )) );
+ maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( nOrientation * 100 )) );
+ }
+ if ( nWidth == -1 )
+ {
+ aAny <<= true;
+ maXPropSet->setPropertyValue( "TextAutoGrowWidth", aAny );
+
+ drawing::TextAdjust eTextAdjust;
+ switch ( mpCGM->pElement->eTextAlignmentH )
+ {
+ case TAH_RIGHT :
+ eTextAdjust = drawing::TextAdjust_RIGHT;
+ break;
+ case TAH_LEFT :
+ case TAH_CONT :
+ case TAH_NORMAL :
+ eTextAdjust = drawing::TextAdjust_LEFT;
+ break;
+ case TAH_CENTER :
+ eTextAdjust = drawing::TextAdjust_CENTER;
+ break;
+ }
+ maXPropSet->setPropertyValue( "TextHorizontalAdjust", uno::Any(eTextAdjust) );
+ }
+ if ( nHeight == -1 )
+ {
+ maXPropSet->setPropertyValue( "TextAutoGrowHeight", uno::Any(true) );
+ }
+ uno::Reference< text::XText > xText;
+ uno::Any aFirstQuery( maXShape->queryInterface( cppu::UnoType<text::XText>::get()));
+ if( aFirstQuery >>= xText )
+ {
+ uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
+ {
+ aXTextCursor->gotoEnd( false );
+ uno::Reference< text::XTextRange > aCursorText;
+ uno::Any aSecondQuery( aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
+ if ( aSecondQuery >>= aCursorText )
+ {
+ uno::Reference< beans::XPropertySet > aCursorPropSet;
+
+ uno::Any aQuery( aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
+ if( aQuery >>= aCursorPropSet )
+ {
+ if ( nWidth != -1 ) // paragraph adjusting in a valid textbox ?
+ {
+ switch ( mpCGM->pElement->eTextAlignmentH )
+ {
+ case TAH_RIGHT :
+ aAny <<= sal_Int16(style::HorizontalAlignment_RIGHT);
+ break;
+ case TAH_LEFT :
+ case TAH_CONT :
+ case TAH_NORMAL :
+ aAny <<= sal_Int16(style::HorizontalAlignment_LEFT);
+ break;
+ case TAH_CENTER :
+ aAny <<= sal_Int16(style::HorizontalAlignment_CENTER);
+ break;
+ }
+ aCursorPropSet->setPropertyValue( "ParaAdjust", aAny );
+ }
+ if ( nWidth > 0 && nHeight > 0 ) // restricted text
+ {
+ aAny <<= true;
+ maXPropSet->setPropertyValue( "TextFitToSize", aAny );
+ }
+ aCursorText->setString(rString);
+ aXTextCursor->gotoEnd( true );
+ ImplSetTextBundle( aCursorPropSet );
+ }
+ }
+ }
+ }
+ if ( eFlag == FF_NOT_FINAL )
+ {
+ nFinalTextCount = maXShapes->getCount();
+ }
+}
+
+void CGMImpressOutAct::AppendText( const char* pString )
+{
+ if ( !nFinalTextCount )
+ return;
+
+ uno::Reference< drawing::XShape > aShape = *o3tl::doAccess<uno::Reference<drawing::XShape>>(maXShapes->getByIndex( nFinalTextCount - 1 ));
+ if ( !aShape.is() )
+ return;
+
+ uno::Reference< text::XText > xText;
+ uno::Any aFirstQuery( aShape->queryInterface( cppu::UnoType<text::XText>::get()) );
+ if( !(aFirstQuery >>= xText) )
+ return;
+
+ OUString aStr(pString, strlen(pString), RTL_TEXTENCODING_ASCII_US);
+
+ uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
+ if ( !aXTextCursor.is() )
+ return;
+
+ aXTextCursor->gotoEnd( false );
+ uno::Reference< text::XTextRange > aCursorText;
+ uno::Any aSecondQuery(aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
+ if ( aSecondQuery >>= aCursorText )
+ {
+ uno::Reference< beans::XPropertySet > aPropSet;
+ uno::Any aQuery(aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
+ if( aQuery >>= aPropSet )
+ {
+ aCursorText->setString( aStr );
+ aXTextCursor->gotoEnd( true );
+ ImplSetTextBundle( aPropSet );
+ }
+ }
+}
+
+
+void CGMImpressOutAct::BeginFigure()
+{
+ if (!maPoints.empty())
+ EndFigure();
+
+ BeginGroup();
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::CloseRegion()
+{
+ if (maPoints.size() > 2)
+ {
+ NewRegion();
+ DrawPolyPolygon( maPolyPolygon );
+ maPolyPolygon.Clear();
+ }
+}
+
+void CGMImpressOutAct::NewRegion()
+{
+ if (maPoints.size() > 2)
+ {
+ tools::Polygon aPolygon(maPoints.size(), maPoints.data(), maFlags.data());
+ maPolyPolygon.Insert( aPolygon );
+ }
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::EndFigure()
+{
+ NewRegion();
+ DrawPolyPolygon( maPolyPolygon );
+ maPolyPolygon.Clear();
+ EndGroup();
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::RegPolyLine( tools::Polygon const & rPolygon, bool bReverse )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( !nPoints )
+ return;
+
+ if ( bReverse )
+ {
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ maPoints.push_back(rPolygon.GetPoint(nPoints - i - 1));
+ maFlags.push_back(rPolygon.GetFlags(nPoints - i - 1));
+ }
+ }
+ else
+ {
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ maPoints.push_back(rPolygon.GetPoint(i));
+ maFlags.push_back(rPolygon.GetFlags(i));
+ }
+ }
+}
+
+void CGMImpressOutAct::SetGradientOffset( tools::Long nHorzOfs, tools::Long nVertOfs )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->XOffset = ( static_cast<sal_uInt16>(nHorzOfs) & 0x7f );
+ mpGradient->YOffset = ( static_cast<sal_uInt16>(nVertOfs) & 0x7f );
+}
+
+void CGMImpressOutAct::SetGradientAngle( tools::Long nAngle )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->Angle = sal::static_int_cast< sal_Int16 >(nAngle);
+}
+
+void CGMImpressOutAct::SetGradientDescriptor( sal_uInt32 nColorFrom, sal_uInt32 nColorTo )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->StartColor = nColorFrom;
+ mpGradient->EndColor = nColorTo;
+}
+
+void CGMImpressOutAct::SetGradientStyle( sal_uInt32 nStyle )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ switch ( nStyle )
+ {
+ case 0xff :
+ {
+ mpGradient->Style = awt::GradientStyle_AXIAL;
+ }
+ break;
+ case 4 :
+ {
+ mpGradient->Style = awt::GradientStyle_RADIAL; // CONICAL
+ }
+ break;
+ case 3 :
+ {
+ mpGradient->Style = awt::GradientStyle_RECT;
+ }
+ break;
+ case 2 :
+ {
+ mpGradient->Style = awt::GradientStyle_ELLIPTICAL;
+ }
+ break;
+ default :
+ {
+ mpGradient->Style = awt::GradientStyle_LINEAR;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bitmap.cxx b/filter/source/graphicfilter/icgm/bitmap.cxx
new file mode 100644
index 000000000..67652d9ec
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bitmap.cxx
@@ -0,0 +1,433 @@
+/* -*- 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 <sal/log.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <memory>
+
+#include "bitmap.hxx"
+#include "elements.hxx"
+
+namespace {
+
+Color BMCOL(sal_uInt32 _col) {
+ return Color( static_cast<sal_Int8>(_col >> 16 ), static_cast<sal_Int8>( _col >> 8 ), static_cast<sal_Int8>(_col) );
+}
+
+}
+
+CGMBitmap::CGMBitmap( CGM& rCGM ) :
+ mpCGM ( &rCGM ),
+ pCGMBitmapDescriptor ( new CGMBitmapDescriptor )
+{
+ ImplGetBitmap( *pCGMBitmapDescriptor );
+};
+
+
+CGMBitmap::~CGMBitmap()
+{
+}
+
+namespace
+{
+ bool isLegalBitsPerPixel(sal_uInt32 nBitsPerPixel)
+ {
+ switch (nBitsPerPixel)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 24:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+}
+
+void CGMBitmap::ImplGetBitmap( CGMBitmapDescriptor& rDesc )
+{
+ rDesc.mbStatus = true;
+
+ if (!ImplGetDimensions(rDesc) || !rDesc.mpBuf)
+ return;
+
+ if (!isLegalBitsPerPixel(rDesc.mnDstBitsPerPixel))
+ {
+ rDesc.mbStatus = false;
+ return;
+ }
+
+ try
+ {
+ if (rDesc.mnScanSize)
+ {
+ vcl::bitmap::RawBitmap aBitmap( Size( rDesc.mnX, rDesc.mnY ), 24 );
+
+ // the picture may either be read from left to right or right to left, from top to bottom ...
+
+ tools::Long nxCount = rDesc.mnX + 1; // +1 because we are using prefix decreasing
+ tools::Long nyCount = rDesc.mnY + 1;
+ tools::Long nx, ny, nxC;
+
+ switch ( rDesc.mnDstBitsPerPixel ) {
+ case 1 : {
+ std::vector<Color> palette(2);
+ if ( rDesc.mnLocalColorPrecision == 1 )
+ palette = ImplGeneratePalette( rDesc );
+ else {
+ palette[0] = BMCOL( mpCGM->pElement->nBackGroundColor );
+ palette[1] = ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ ? BMCOL( mpCGM->pElement->pFillBundle->GetColor() )
+ : BMCOL( mpCGM->pElement->aFillBundle.GetColor() );
+ };
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+ // this is not fast, but a one bit/pixel format is rarely used
+ const sal_uInt8* pPos = rDesc.mpBuf + (nx >> 3);
+ if (pPos >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+ sal_uInt8 colorIndex = static_cast<sal_uInt8>((*pPos >> ((nx & 7)^7))) & 1;
+ aBitmap.SetPixel(ny, nx, palette[colorIndex]);
+ }
+ }
+ }
+ break;
+
+ case 2 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+ // this is not fast, but a two bits/pixel format is rarely used
+ const sal_uInt8* pPos = rDesc.mpBuf + (nx >> 2);
+ if (pPos >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>( (*pPos >> (((nx & 3)^3) << 1))) & 3]);
+ }
+ }
+ }
+ break;
+
+ case 4 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ sal_uInt8 nDat = *pTemp++;
+
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat >> 4)]);
+ if ( --nxC ) {
+ ++nx;
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat & 15)]);
+ } else
+ break;
+ }
+ }
+ }
+ break;
+
+ case 8 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ aBitmap.SetPixel(ny, nx, palette[*(pTemp++)]);
+ }
+ }
+ }
+ break;
+
+ case 24 : {
+ Color aBitmapColor;
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp + 2 >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ aBitmapColor.SetRed( *pTemp++ );
+ aBitmapColor.SetGreen( *pTemp++ );
+ aBitmapColor.SetBlue( *pTemp++ );
+ aBitmap.SetPixel(ny, nx, aBitmapColor);
+ }
+ }
+ }
+ break;
+ }
+
+ if ( rDesc.mbStatus )
+ rDesc.mxBitmap = vcl::bitmap::CreateFromData(std::move(aBitmap));
+ }
+
+ double nX = rDesc.mnR.X - rDesc.mnQ.X;
+ double nY = rDesc.mnR.Y - rDesc.mnQ.Y;
+
+ rDesc.mndy = std::hypot(nX, nY);
+
+ nX = rDesc.mnR.X - rDesc.mnP.X;
+ nY = rDesc.mnR.Y - rDesc.mnP.Y;
+
+ rDesc.mndx = std::hypot(nX, nY);
+
+ nX = rDesc.mnR.X - rDesc.mnP.X;
+ nY = rDesc.mnR.Y - rDesc.mnP.Y;
+
+ double fSqrt = std::hypot(nX, nY);
+ rDesc.mnOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY > 0 )
+ rDesc.mnOrientation = 360 - rDesc.mnOrientation;
+
+ nX = rDesc.mnQ.X - rDesc.mnR.X;
+ nY = rDesc.mnQ.Y - rDesc.mnR.Y;
+
+ double fAngle = basegfx::deg2rad( 360 - rDesc.mnOrientation );
+ double fSin = sin(fAngle);
+ double fCos = cos(fAngle);
+ nX = fCos * nX + fSin * nY;
+ nY = -( fSin * nX - fCos * nY );
+
+ fSqrt = std::hypot(nX, nY);
+ fAngle = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY > 0 )
+ fAngle = 360 - fAngle;
+
+ if ( fAngle > 180 ) { // is the picture build upwards or downwards ?
+ rDesc.mnOrigin = rDesc.mnP;
+ } else {
+ rDesc.mbVMirror = true;
+ rDesc.mnOrigin = rDesc.mnP;
+ rDesc.mnOrigin.X += rDesc.mnQ.X - rDesc.mnR.X;
+ rDesc.mnOrigin.Y += rDesc.mnQ.Y - rDesc.mnR.Y;
+ }
+ }
+ catch (const std::bad_alloc&)
+ {
+ rDesc.mbStatus = false;
+ }
+}
+
+std::vector<Color> CGMBitmap::ImplGeneratePalette( CGMBitmapDescriptor const & rDesc )
+{
+ sal_uInt16 nColors = sal::static_int_cast< sal_uInt16 >(
+ 1 << rDesc.mnDstBitsPerPixel);
+ std::vector<Color> palette( nColors );
+ for ( sal_uInt16 i = 0; i < nColors; i++ )
+ {
+ palette[i] = BMCOL( mpCGM->pElement->aLatestColorTable[ i ] );
+ }
+ return palette;
+}
+
+
+bool CGMBitmap::ImplGetDimensions( CGMBitmapDescriptor& rDesc )
+{
+ mpCGM->ImplGetPoint( rDesc.mnP ); // parallelogram p < - > r
+ mpCGM->ImplGetPoint( rDesc.mnQ ); // |
+ mpCGM->ImplGetPoint( rDesc.mnR ); // q
+ sal_uInt32 nPrecision = mpCGM->pElement->nIntegerPrecision;
+ rDesc.mnX = mpCGM->ImplGetUI( nPrecision );
+ rDesc.mnY = mpCGM->ImplGetUI( nPrecision );
+ rDesc.mnLocalColorPrecision = mpCGM->ImplGetI( nPrecision );
+ rDesc.mnScanSize = 0;
+ switch( rDesc.mnLocalColorPrecision )
+ {
+ case tools::Long(0x80000001) : // monochrome ( bit = 0->backgroundcolor )
+ case 0 : // bit = 1->fillcolor
+ rDesc.mnDstBitsPerPixel = 1;
+ break;
+ case 1 : // 2 color indexed ( monochrome )
+ case -1 :
+ rDesc.mnDstBitsPerPixel = 1;
+ break;
+ case 2 : // 4 color indexed
+ case -2 :
+ rDesc.mnDstBitsPerPixel = 2;
+ break;
+ case 4 : // 16 color indexed
+ case -4 :
+ rDesc.mnDstBitsPerPixel = 4;
+ break;
+ case 8 : // 256 color indexed
+ case -8 :
+ rDesc.mnDstBitsPerPixel = 8;
+ rDesc.mnScanSize = rDesc.mnX;
+ break;
+ case 16 : // NS
+ case -16 :
+ rDesc.mbStatus = false;
+ break;
+ case 24 : // 24 bit directColor ( 8 bits each component )
+ case -24 :
+ rDesc.mnDstBitsPerPixel = 24;
+ break;
+ case 32 : // NS
+ case -32 :
+ rDesc.mbStatus = false;
+ break;
+
+ }
+ // mnCompressionMode == 0 : CCOMP_RUNLENGTH
+ // == 1 : CCOMP_PACKED ( no compression. each row starts on a 4 byte boundary )
+ if ( ( rDesc.mnCompressionMode = mpCGM->ImplGetUI16() ) != 1 )
+ rDesc.mbStatus = false;
+
+ if ( !( rDesc.mnX || rDesc.mnY ) )
+ rDesc.mbStatus = false;
+
+ sal_uInt32 nHeaderSize = 2 + 3 * nPrecision + 3 * mpCGM->ImplGetPointSize();
+
+ sal_uInt32 nWidthBits;
+ if (o3tl::checked_multiply(rDesc.mnX, rDesc.mnDstBitsPerPixel, nWidthBits))
+ {
+ rDesc.mbStatus = false;
+ return false;
+ }
+
+ rDesc.mnScanSize = (nWidthBits + 7) >> 3;
+
+ sal_uInt32 nScanSize;
+ nScanSize = rDesc.mnScanSize;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // try a scansize without dw alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 1 ) & ~1;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // then we'll try word alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // and last we'll try dword alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 1 ) & ~1; // and LAST BUT NOT LEAST we'll try word alignment without aligning the last line
+ if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
+ {
+ nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
+ if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
+ {
+ mpCGM->mnParaSize = 0; // this format is corrupt
+ rDesc.mbStatus = false;
+ }
+ }
+ }
+ }
+ }
+ rDesc.mnScanSize = nScanSize;
+ if ( rDesc.mbStatus )
+ {
+ rDesc.mpBuf = mpCGM->mpSource + mpCGM->mnParaSize; // mpBuf now points to the first scanline
+ rDesc.mpEndBuf = mpCGM->mpEndValidSource;
+ mpCGM->mnParaSize += rDesc.mnScanSize * rDesc.mnY;
+ }
+ return rDesc.mbStatus;
+}
+
+
+void CGMBitmap::ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescriptor& rDest )
+{
+ if (utl::ConfigManager::IsFuzzing() && rDest.mxBitmap.GetSizePixel().Height() + rSource.mnY > SAL_MAX_UINT16)
+ {
+ SAL_WARN("filter.icgm", "bitmap would expand too much");
+ rDest.mbStatus = false;
+ return;
+ }
+ rDest.mxBitmap.Expand( 0, rSource.mnY );
+ rDest.mxBitmap.CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
+ tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), &rSource.mxBitmap );
+
+ if ( ( rSource.mnR.Y == rDest.mnQ.Y ) && ( rSource.mnR.X == rDest.mnQ.X ) )
+ { // Insert on Bottom
+ if ( mpCGM->mnVDCYmul == -1 )
+ rDest.mnOrigin = rSource.mnOrigin; // new origin
+ FloatPoint aFloatPoint;
+ aFloatPoint.X = rSource.mnQ.X - rSource.mnR.X;
+ aFloatPoint.Y = rSource.mnQ.Y - rSource.mnR.Y;
+ rDest.mnQ.X += aFloatPoint.X;
+ rDest.mnQ.Y += aFloatPoint.Y;
+ rDest.mnP = rSource.mnP;
+ rDest.mnR = rSource.mnR;
+ }
+ else
+ { // Insert on Top
+ if ( mpCGM->mnVDCYmul == 1 )
+ rDest.mnOrigin = rSource.mnOrigin; // new origin
+ rDest.mnP = rSource.mnP;
+ rDest.mnR = rSource.mnR;
+ }
+ rDest.mnY += rSource.mnY;
+ rDest.mndy += rSource.mndy;
+};
+
+std::unique_ptr<CGMBitmap> CGMBitmap::GetNext()
+{
+ std::unique_ptr<CGMBitmap> xCGMTempBitmap;
+ if (!pCGMBitmapDescriptor->mxBitmap.IsEmpty() && pCGMBitmapDescriptor->mbStatus)
+ {
+ xCGMTempBitmap.reset(new CGMBitmap(*mpCGM));
+ if ( ( static_cast<tools::Long>(xCGMTempBitmap->pCGMBitmapDescriptor->mnOrientation) == static_cast<tools::Long>(pCGMBitmapDescriptor->mnOrientation) ) &&
+ ( ( ( xCGMTempBitmap->pCGMBitmapDescriptor->mnR.X == pCGMBitmapDescriptor->mnQ.X ) &&
+ ( xCGMTempBitmap->pCGMBitmapDescriptor->mnR.Y == pCGMBitmapDescriptor->mnQ.Y ) ) ||
+ ( ( xCGMTempBitmap->pCGMBitmapDescriptor->mnQ.X == pCGMBitmapDescriptor->mnR.X ) &&
+ ( xCGMTempBitmap->pCGMBitmapDescriptor->mnQ.Y == pCGMBitmapDescriptor->mnR.Y ) ) ) )
+ {
+ ImplInsert( *(xCGMTempBitmap->pCGMBitmapDescriptor), *pCGMBitmapDescriptor );
+ xCGMTempBitmap.reset();
+ return xCGMTempBitmap;
+ }
+
+ pCGMBitmapDescriptor.swap(xCGMTempBitmap->pCGMBitmapDescriptor);
+ }
+ return xCGMTempBitmap;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bitmap.hxx b/filter/source/graphicfilter/icgm/bitmap.hxx
new file mode 100644
index 000000000..3e7b80f51
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bitmap.hxx
@@ -0,0 +1,81 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "cgm.hxx"
+#include <vcl/bitmapex.hxx>
+#include <vector>
+
+class CGM;
+
+class CGMBitmapDescriptor
+{
+ public:
+ sal_uInt8* mpBuf;
+ sal_uInt8* mpEndBuf;
+ BitmapEx mxBitmap;
+ bool mbStatus;
+ bool mbVMirror;
+ sal_uInt32 mnDstBitsPerPixel;
+ sal_uInt32 mnScanSize; // bytes per line
+ FloatPoint mnP, mnQ, mnR;
+
+ FloatPoint mnOrigin;
+ double mndx, mndy;
+ double mnOrientation;
+
+ sal_uInt32 mnX, mnY;
+ tools::Long mnLocalColorPrecision;
+ sal_uInt32 mnCompressionMode;
+
+ CGMBitmapDescriptor()
+ : mpBuf(nullptr)
+ , mpEndBuf(nullptr)
+ , mbStatus(false)
+ , mbVMirror(false)
+ , mnDstBitsPerPixel(0)
+ , mnScanSize(0)
+ , mndx(0.0)
+ , mndy(0.0)
+ , mnOrientation(0.0)
+ , mnX(0)
+ , mnY(0)
+ , mnLocalColorPrecision(0)
+ , mnCompressionMode(0)
+ { };
+};
+
+class CGMBitmap
+{
+ CGM* mpCGM;
+ std::unique_ptr<CGMBitmapDescriptor>
+ pCGMBitmapDescriptor;
+ bool ImplGetDimensions( CGMBitmapDescriptor& );
+ std::vector<Color> ImplGeneratePalette( CGMBitmapDescriptor const & );
+ void ImplGetBitmap( CGMBitmapDescriptor& );
+ void ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescriptor& rDest );
+public:
+ explicit CGMBitmap( CGM& rCGM );
+ ~CGMBitmap();
+ CGMBitmapDescriptor* GetBitmap() { return pCGMBitmapDescriptor.get();}
+ std::unique_ptr<CGMBitmap> GetNext();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bundles.cxx b/filter/source/graphicfilter/icgm/bundles.cxx
new file mode 100644
index 000000000..64e63a750
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bundles.cxx
@@ -0,0 +1,141 @@
+/* -*- 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 "bundles.hxx"
+
+#include <string.h>
+
+void Bundle::SetColor( sal_uInt32 nColor )
+{
+ mnColor = nColor;
+}
+
+CGMFList::CGMFList()
+ : nFontNameCount(0)
+ , nCharSetCount(0)
+{
+}
+
+FontEntry* CGMFList::GetFontEntry( sal_uInt32 nIndex )
+{
+ sal_uInt32 nInd = nIndex;
+ if ( nInd )
+ nInd--;
+ return ( nInd < aFontEntryList.size() ) ? &aFontEntryList[nInd] : nullptr;
+}
+
+static sal_Int8* ImplSearchEntry( sal_Int8* pSource, sal_Int8 const * pDest, sal_uInt32 nComp, sal_uInt32 nSize )
+{
+ while ( nComp-- >= nSize )
+ {
+ sal_uInt32 i;
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
+ break;
+ }
+ if ( i == nSize )
+ return pSource;
+ pSource++;
+ }
+ return nullptr;
+}
+
+void CGMFList::InsertName( sal_uInt8 const * pSource, sal_uInt32 nSize )
+{
+ FontEntry* pFontEntry;
+ if (nFontNameCount == aFontEntryList.size())
+ {
+ aFontEntryList.push_back(FontEntry());
+ pFontEntry = &aFontEntryList.back();
+ }
+ else
+ {
+ pFontEntry = &aFontEntryList[nFontNameCount];
+ }
+ nFontNameCount++;
+
+ if (nSize == 0)
+ return;
+
+ std::vector<sal_Int8> aBuf(pSource, pSource + nSize);
+ sal_Int8* pFound = ImplSearchEntry(aBuf.data(), reinterpret_cast<sal_Int8 const *>("ITALIC"), nSize, 6);
+ if (pFound)
+ {
+ pFontEntry->nFontType |= 1;
+ sal_uInt32 nPrev = pFound - aBuf.data();
+ sal_uInt32 nToCopyOfs = 6;
+ if ( nPrev && ( pFound[ -1 ] == '-' || pFound[ -1 ] == ' ' ) )
+ {
+ nPrev--;
+ pFound--;
+ nToCopyOfs++;
+ }
+ sal_uInt32 nToCopy = nSize - nToCopyOfs - nPrev;
+ if ( nToCopy )
+ {
+ memmove( pFound, pFound + nToCopyOfs, nToCopy );
+ }
+ nSize -= nToCopyOfs;
+ }
+ pFound = ImplSearchEntry(aBuf.data(), reinterpret_cast<sal_Int8 const *>("BOLD"), nSize, 4);
+ if ( pFound )
+ {
+ pFontEntry->nFontType |= 2;
+
+ sal_uInt32 nPrev = pFound - aBuf.data();
+ sal_uInt32 nToCopyOfs = 4;
+ if ( nPrev && ( pFound[ -1 ] == '-' || pFound[ -1 ] == ' ' ) )
+ {
+ nPrev--;
+ pFound--;
+ nToCopyOfs++;
+ }
+ sal_uInt32 nToCopy = nSize - nToCopyOfs - nPrev;
+ if ( nToCopy )
+ {
+ memmove( pFound, pFound + nToCopyOfs, nToCopy );
+ }
+ nSize -= nToCopyOfs;
+ }
+ pFontEntry->aFontName.assign(aBuf.data(), aBuf.data() + nSize);
+}
+
+void CGMFList::InsertCharSet( sal_uInt8 const * pSource, sal_uInt32 nSize )
+{
+ FontEntry* pFontEntry;
+ if (nCharSetCount == aFontEntryList.size())
+ {
+ aFontEntryList.push_back(FontEntry());
+ pFontEntry = &aFontEntryList.back();
+ }
+ else
+ {
+ pFontEntry = &aFontEntryList[nCharSetCount];
+ }
+ nCharSetCount++;
+
+ if (nSize == 0)
+ return;
+
+ pFontEntry->aCharSetValue.assign(pSource, pSource + nSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bundles.hxx b/filter/source/graphicfilter/icgm/bundles.hxx
new file mode 100644
index 000000000..209eae6dd
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bundles.hxx
@@ -0,0 +1,166 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include "cgmtypes.hxx"
+#include <vector>
+#include <memory>
+
+
+class Bundle
+{
+
+ tools::Long mnBundleIndex;
+ sal_uInt32 mnColor;
+
+public:
+ void SetColor( sal_uInt32 nColor ) ;
+ sal_uInt32 GetColor() const { return mnColor;}
+ tools::Long GetIndex() const { return mnBundleIndex; } ;
+ void SetIndex( tools::Long nBundleIndex ) { mnBundleIndex = nBundleIndex; } ;
+
+ Bundle()
+ : mnBundleIndex( 0 )
+ , mnColor( 0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() { return std::make_unique<Bundle>( *this ); };
+
+ virtual ~Bundle() {} ;
+
+ Bundle(Bundle const &) = default;
+ Bundle(Bundle &&) = default;
+ Bundle & operator =(Bundle const &) = default;
+ Bundle & operator =(Bundle &&) = default;
+};
+
+
+class LineBundle : public Bundle
+{
+public:
+
+ LineType eLineType;
+ double nLineWidth;
+
+ LineBundle()
+ : eLineType(LT_SOLID)
+ , nLineWidth(0)
+ {}
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<LineBundle>( *this ); }
+};
+
+
+class MarkerBundle : public Bundle
+{
+public:
+
+ MarkerType eMarkerType;
+ double nMarkerSize;
+
+ MarkerBundle()
+ : eMarkerType( MT_POINT )
+ , nMarkerSize( 0.0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<MarkerBundle>( *this ); } ;
+};
+
+
+class EdgeBundle : public Bundle
+{
+public:
+
+ EdgeType eEdgeType;
+ double nEdgeWidth;
+
+ EdgeBundle()
+ : eEdgeType(ET_NONE)
+ , nEdgeWidth(0)
+ {}
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<EdgeBundle>( *this ); }
+};
+
+
+class TextBundle : public Bundle
+{
+public:
+
+ sal_uInt32 nTextFontIndex;
+ TextPrecision eTextPrecision;
+ double nCharacterExpansion;
+ double nCharacterSpacing;
+
+ TextBundle()
+ : nTextFontIndex( 0 )
+ , eTextPrecision( TPR_UNDEFINED )
+ , nCharacterExpansion( 0.0 )
+ , nCharacterSpacing( 0.0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<TextBundle>( *this ); } ;
+};
+
+
+class FillBundle : public Bundle
+{
+public:
+
+ FillInteriorStyle eFillInteriorStyle;
+ tools::Long nFillPatternIndex;
+ tools::Long nFillHatchIndex;
+
+ FillBundle()
+ : eFillInteriorStyle(FIS_HOLLOW)
+ , nFillPatternIndex(0)
+ , nFillHatchIndex(0)
+ {}
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<FillBundle>( *this ); }
+};
+
+
+struct FontEntry
+{
+ std::vector<sal_Int8> aFontName;
+ std::vector<sal_Int8> aCharSetValue;
+ sal_uInt32 nFontType; // bit 0 = 1 -> Italic,
+ // bit 1 = 1 -> Bold
+ FontEntry()
+ : nFontType(0)
+ {
+ }
+};
+
+class CGMFList
+{
+ sal_uInt32 nFontNameCount;
+ sal_uInt32 nCharSetCount;
+ std::vector<FontEntry> aFontEntryList;
+
+public:
+ CGMFList();
+
+ FontEntry* GetFontEntry( sal_uInt32 );
+ void InsertName( sal_uInt8 const * pSource, sal_uInt32 nSize );
+ void InsertCharSet( sal_uInt8 const * pSource, sal_uInt32 nSize );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgm.cxx b/filter/source/graphicfilter/icgm/cgm.cxx
new file mode 100644
index 000000000..1cf7c7ca0
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgm.cxx
@@ -0,0 +1,741 @@
+/* -*- 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/task/XStatusIndicator.hpp>
+#include <o3tl/safeint.hxx>
+#include <osl/endian.h>
+#include <tools/stream.hxx>
+#include "bitmap.hxx"
+#include "chart.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+#include <memory>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+
+constexpr double gnOutdx = 28000; // Output size in 1/100TH mm
+constexpr double gnOutdy = 21000; // on which is mapped
+
+CGM::CGM(uno::Reference< frame::XModel > const & rModel)
+ : mnVDCXadd(0)
+ , mnVDCYadd(0)
+ , mnVDCXmul(0)
+ , mnVDCYmul(0)
+ , mnVDCdx(0)
+ , mnVDCdy(0)
+ , mnXFraction(0)
+ , mnYFraction(0)
+ , mbAngReverse(false)
+ , mbStatus(true)
+ , mbMetaFile(false)
+ , mbIsFinished(false)
+ , mbPicture(false)
+ , mbPictureBody(false)
+ , mbFigure(false)
+ , mbFirstOutPut(false)
+ , mbInDefaultReplacement(false)
+ , mnAct4PostReset(0)
+ , mpOutAct(new CGMImpressOutAct(*this, rModel))
+ , mpSource(nullptr)
+ , mpEndValidSource(nullptr)
+ , mnParaSize(0)
+ , mnActCount(0)
+ , mnEscape(0)
+ , mnElementClass(0)
+ , mnElementID(0)
+ , mnElementSize(0)
+{
+ pElement.reset( new CGMElements );
+ pCopyOfE.reset( new CGMElements );
+}
+
+CGM::~CGM()
+{
+ maDefRepList.clear();
+ maDefRepSizeList.clear();
+};
+
+sal_uInt32 CGM::GetBackGroundColor() const
+{
+ return pElement ? pElement->aColorTable[ 0 ] : 0;
+}
+
+sal_uInt32 CGM::ImplGetUI16()
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (mpEndValidSource - pSource < 2)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += 2;
+ return ( pSource[ 0 ] << 8 ) + pSource[ 1 ];
+};
+
+sal_uInt8 CGM::ImplGetByte( sal_uInt32 nSource, sal_uInt32 nPrecision )
+{
+ return static_cast<sal_uInt8>( nSource >> ( ( nPrecision - 1 ) << 3 ) );
+};
+
+sal_Int32 CGM::ImplGetI( sal_uInt32 nPrecision )
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (pSource > mpEndValidSource || o3tl::make_unsigned(mpEndValidSource - pSource) < nPrecision)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += nPrecision;
+ switch( nPrecision )
+ {
+ case 1 :
+ {
+ return static_cast<char>(*pSource);
+ }
+
+ case 2 :
+ {
+ return static_cast<sal_Int16>( ( pSource[ 0 ] << 8 ) | pSource[ 1 ] );
+ }
+
+ case 3 :
+ {
+ return ( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | pSource[ 2 ] << 8 ) >> 8;
+ }
+ case 4:
+ {
+ return static_cast<sal_Int32>( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | ( pSource[ 2 ] << 8 ) | ( pSource[ 3 ] ) );
+ }
+ default:
+ mbStatus = false;
+ return 0;
+ }
+}
+
+sal_uInt32 CGM::ImplGetUI( sal_uInt32 nPrecision )
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (pSource > mpEndValidSource || o3tl::make_unsigned(mpEndValidSource - pSource) < nPrecision)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += nPrecision;
+ switch( nPrecision )
+ {
+ case 1 :
+ return static_cast<sal_Int8>(*pSource);
+ case 2 :
+ {
+ return static_cast<sal_uInt16>( ( pSource[ 0 ] << 8 ) | pSource[ 1 ] );
+ }
+ case 3 :
+ {
+ return ( pSource[ 0 ] << 16 ) | ( pSource[ 1 ] << 8 ) | pSource[ 2 ];
+ }
+ case 4:
+ {
+ return static_cast<sal_uInt32>( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | ( pSource[ 2 ] << 8 ) | ( pSource[ 3 ] ) );
+ }
+ default:
+ mbStatus = false;
+ return 0;
+ }
+}
+
+void CGM::ImplGetSwitch4( const sal_uInt8* pSource, sal_uInt8* pDest )
+{
+ for ( int i = 0; i < 4; i++ )
+ {
+ pDest[ i ] = pSource[ i ^ 3 ]; // Little Endian <-> Big Endian switch
+ }
+}
+
+void CGM::ImplGetSwitch8( const sal_uInt8* pSource, sal_uInt8* pDest )
+{
+ for ( int i = 0; i < 8; i++ )
+ {
+ pDest[ i ] = pSource[ i ^ 7 ]; // Little Endian <-> Big Endian switch
+ }
+}
+
+double CGM::ImplGetFloat( RealPrecision eRealPrecision, sal_uInt32 nRealSize )
+{
+ void* pPtr;
+ sal_uInt8 aBuf[8];
+ double nRetValue;
+ double fDoubleBuf;
+ float fFloatBuf;
+
+#ifdef OSL_BIGENDIAN
+ const bool bCompatible = true;
+#else
+ const bool bCompatible = false;
+#endif
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nRealSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( bCompatible )
+ {
+ pPtr = mpSource + mnParaSize;
+ }
+ else
+ {
+ if ( nRealSize == 4 )
+ ImplGetSwitch4( mpSource + mnParaSize, &aBuf[0] );
+ else
+ ImplGetSwitch8( mpSource + mnParaSize, &aBuf[0] );
+ pPtr = &aBuf;
+ }
+ if ( eRealPrecision == RP_FLOAT )
+ {
+ if ( nRealSize == 4 )
+ {
+ memcpy( static_cast<void*>(&fFloatBuf), pPtr, 4 );
+ nRetValue = static_cast<double>(fFloatBuf);
+ }
+ else
+ {
+ memcpy( static_cast<void*>(&fDoubleBuf), pPtr, 8 );
+ nRetValue = fDoubleBuf;
+ }
+ }
+ else // ->RP_FIXED
+ {
+ tools::Long nVal;
+ const int nSwitch = bCompatible ? 0 : 1 ;
+ if ( nRealSize == 4 )
+ {
+ sal_uInt16* pShort = static_cast<sal_uInt16*>(pPtr);
+ nVal = pShort[ nSwitch ];
+ nVal <<= 16;
+ nVal |= pShort[ nSwitch ^ 1 ];
+ nRetValue = static_cast<double>(nVal);
+ nRetValue /= 65536;
+ }
+ else
+ {
+ sal_Int32* pLong = static_cast<sal_Int32*>(pPtr);
+ nRetValue = static_cast<double>(abs( pLong[ nSwitch ] ));
+ nRetValue *= 65536;
+ nVal = static_cast<sal_uInt32>( pLong[ nSwitch ^ 1 ] );
+ nVal >>= 16;
+ nRetValue += static_cast<double>(nVal);
+ if ( pLong[ nSwitch ] < 0 )
+ {
+ nRetValue = -nRetValue;
+ }
+ nRetValue /= 65536;
+ }
+ }
+ mnParaSize += nRealSize;
+ return nRetValue;
+}
+
+sal_uInt32 CGM::ImplGetPointSize()
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ return pElement->nVDCIntegerPrecision << 1;
+ else
+ return pElement->nVDCRealSize << 1;
+}
+
+inline double CGM::ImplGetIX()
+{
+ return ( ( ImplGetI( pElement->nVDCIntegerPrecision ) + mnVDCXadd ) * mnVDCXmul );
+}
+
+inline double CGM::ImplGetFX()
+{
+ return ( ( ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize ) + mnVDCXadd ) * mnVDCXmul );
+}
+
+inline double CGM::ImplGetIY()
+{
+ return ( ( ImplGetI( pElement->nVDCIntegerPrecision ) + mnVDCYadd ) * mnVDCYmul );
+}
+
+inline double CGM::ImplGetFY()
+{
+ return ( ( ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize ) + mnVDCYadd ) * mnVDCYmul );
+}
+
+void CGM::ImplGetPoint( FloatPoint& rFloatPoint, bool bMap )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatPoint.X = ImplGetIX();
+ rFloatPoint.Y = ImplGetIY();
+ }
+ else // ->floating points
+ {
+ rFloatPoint.X = ImplGetFX();
+ rFloatPoint.Y = ImplGetFY();
+ }
+ if ( bMap )
+ ImplMapPoint( rFloatPoint );
+}
+
+void CGM::ImplGetRectangle( FloatRect& rFloatRect, bool bMap )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatRect.Left = ImplGetIX();
+ rFloatRect.Bottom = ImplGetIY();
+ rFloatRect.Right = ImplGetIX();
+ rFloatRect.Top = ImplGetIY();
+ }
+ else // ->floating points
+ {
+ rFloatRect.Left = ImplGetFX();
+ rFloatRect.Bottom = ImplGetFY();
+ rFloatRect.Right = ImplGetFX();
+ rFloatRect.Top = ImplGetFY();
+ }
+ if ( bMap )
+ {
+ ImplMapX( rFloatRect.Left );
+ ImplMapX( rFloatRect.Right );
+ ImplMapY( rFloatRect.Top );
+ ImplMapY( rFloatRect.Bottom );
+ rFloatRect.Justify();
+ }
+}
+
+void CGM::ImplGetRectangleNS( FloatRect& rFloatRect )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatRect.Left = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Bottom = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Right = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Top = ImplGetI( pElement->nVDCIntegerPrecision );
+ }
+ else // ->floating points
+ {
+ rFloatRect.Left = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Bottom = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Right = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Top = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+}
+
+sal_uInt32 CGM::ImplGetBitmapColor( bool bDirect )
+{
+ // the background color is always a direct color
+
+ sal_uInt32 nTmp;
+ if ( ( pElement->eColorSelectionMode == CSM_DIRECT ) || bDirect )
+ {
+ sal_uInt32 nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ sal_uInt32 nDiff = pElement->nColorValueExtent[ 3 ] - pElement->nColorValueExtent[ 0 ] + 1;
+
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 0 ] ) << 8 ) / nDiff;
+ nTmp = nColor << 16 & 0xff0000;
+
+ nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ nDiff = pElement->nColorValueExtent[ 4 ] - pElement->nColorValueExtent[ 1 ] + 1;
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 1 ] ) << 8 ) / nDiff;
+ nTmp |= nColor << 8 & 0xff00;
+
+ nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ nDiff = pElement->nColorValueExtent[ 5 ] - pElement->nColorValueExtent[ 2 ] + 1;
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 2 ] ) << 8 ) / nDiff;
+ nTmp |= static_cast<sal_uInt8>(nColor);
+ }
+ else
+ {
+ sal_uInt32 nIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ nTmp = pElement->aColorTable[ static_cast<sal_uInt8>(nIndex) ] ;
+ }
+ return nTmp;
+}
+
+// call this function each time after the mapmode settings has been changed
+void CGM::ImplSetMapMode()
+{
+ int nAngReverse = 1;
+ mnVDCdx = pElement->aVDCExtent.Right - pElement->aVDCExtent.Left;
+
+ mnVDCXadd = -pElement->aVDCExtent.Left;
+ mnVDCXmul = 1;
+ if ( mnVDCdx < 0 )
+ {
+ nAngReverse ^= 1;
+ mnVDCdx = -mnVDCdx;
+ mnVDCXmul = -1;
+ }
+
+ mnVDCdy = pElement->aVDCExtent.Bottom - pElement->aVDCExtent.Top;
+ mnVDCYadd = -pElement->aVDCExtent.Top;
+ mnVDCYmul = 1;
+ if ( mnVDCdy < 0 )
+ {
+ nAngReverse ^= 1;
+ mnVDCdy = -mnVDCdy;
+ mnVDCYmul = -1;
+ }
+ if ( nAngReverse )
+ mbAngReverse = true;
+ else
+ mbAngReverse = false;
+
+ if (mnVDCdy == 0.0 || mnVDCdx == 0.0 || gnOutdy == 0.0)
+ {
+ mbStatus = false;
+ return;
+ }
+
+ double fQuo1 = mnVDCdx / mnVDCdy;
+ double fQuo2 = gnOutdx / gnOutdy;
+ if ( fQuo2 < fQuo1 )
+ {
+ mnXFraction = gnOutdx / mnVDCdx;
+ mnYFraction = gnOutdy * ( fQuo2 / fQuo1 ) / mnVDCdy;
+ }
+ else
+ {
+ mnXFraction = gnOutdx * ( fQuo1 / fQuo2 ) / mnVDCdx;
+ mnYFraction = gnOutdy / mnVDCdy;
+ }
+}
+
+void CGM::ImplMapDouble( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= ( mnXFraction + mnYFraction ) / 2;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= ( mnXFraction + mnYFraction ) / 2;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplMapX( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= mnXFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= mnXFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplMapY( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= mnYFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= mnYFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+// convert a point to the current VC mapmode (1/100TH mm)
+void CGM::ImplMapPoint( FloatPoint& rFloatPoint )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ rFloatPoint.X *= mnXFraction;
+ rFloatPoint.Y *= mnYFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ rFloatPoint.X *= mnXFraction;
+ rFloatPoint.Y *= mnYFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ {
+ rFloatPoint.X = -rFloatPoint.X;
+ rFloatPoint.Y = -rFloatPoint.Y;
+ }
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplDoClass()
+{
+ switch ( mnElementClass )
+ {
+ case 0 : ImplDoClass0(); break;
+ case 1 : ImplDoClass1(); break;
+ case 2 : ImplDoClass2(); break;
+ case 3 : ImplDoClass3(); break;
+ case 4 :
+ {
+ ImplDoClass4();
+ mnAct4PostReset = 0;
+ }
+ break;
+ case 5 : ImplDoClass5(); break;
+ case 6 : ImplDoClass6(); break;
+ case 7 : ImplDoClass7(); break;
+ case 8 : ImplDoClass8(); break;
+ case 9 : ImplDoClass9(); break;
+ case 15 :ImplDoClass15(); break;
+ default: break;
+ }
+ mnActCount++;
+};
+
+void CGM::ImplDefaultReplacement()
+{
+ if (maDefRepList.empty())
+ return;
+
+ if (mbInDefaultReplacement)
+ {
+ SAL_WARN("filter.icgm", "recursion in ImplDefaultReplacement");
+ return;
+ }
+
+ mbInDefaultReplacement = true;
+
+ sal_uInt32 nOldEscape = mnEscape;
+ sal_uInt32 nOldElementClass = mnElementClass;
+ sal_uInt32 nOldElementID = mnElementID;
+ sal_uInt32 nOldElementSize = mnElementSize;
+ sal_uInt8* pOldBuf = mpSource;
+ sal_uInt8* pOldEndValidSource = mpEndValidSource;
+
+ for ( size_t i = 0, n = maDefRepList.size(); i < n; ++i )
+ {
+ sal_uInt8* pBuf = maDefRepList[ i ].get();
+ sal_uInt32 nElementSize = maDefRepSizeList[ i ];
+ mpEndValidSource = pBuf + nElementSize;
+ sal_uInt32 nCount = 0;
+ while ( mbStatus && ( nCount < nElementSize ) )
+ {
+ mpSource = pBuf + nCount;
+ mnParaSize = 0;
+ mnEscape = ImplGetUI16();
+ mnElementClass = mnEscape >> 12;
+ mnElementID = ( mnEscape & 0x0fe0 ) >> 5;
+ mnElementSize = mnEscape & 0x1f;
+ if ( mnElementSize == 31 )
+ {
+ mnElementSize = ImplGetUI16();
+ }
+ nCount += mnParaSize;
+ mnParaSize = 0;
+ mpSource = pBuf + nCount;
+ if ( mnElementSize & 1 )
+ nCount++;
+ nCount += mnElementSize;
+ if ( ( mnElementClass != 1 ) || ( mnElementID != 0xc ) ) // recursion is not possible here!!
+ ImplDoClass();
+ }
+ }
+ mnEscape = nOldEscape;
+ mnElementClass = nOldElementClass;
+ mnElementID = nOldElementID;
+ mnParaSize = mnElementSize = nOldElementSize;
+ mpSource = pOldBuf;
+ mpEndValidSource = pOldEndValidSource;
+
+ mbInDefaultReplacement = false;
+}
+
+bool CGM::Write( SvStream& rIStm )
+{
+ if ( !mpBuf )
+ mpBuf.reset( new sal_uInt8[ 0xffff ] );
+
+ mnParaSize = 0;
+ mpSource = mpBuf.get();
+ if (rIStm.ReadBytes(mpSource, 2) != 2)
+ return false;
+ mpEndValidSource = mpSource + 2;
+ mnEscape = ImplGetUI16();
+ mnElementClass = mnEscape >> 12;
+ mnElementID = ( mnEscape & 0x0fe0 ) >> 5;
+ mnElementSize = mnEscape & 0x1f;
+
+ if ( mnElementSize == 31 )
+ {
+ if (rIStm.ReadBytes(mpSource + mnParaSize, 2) != 2)
+ return false;
+ mpEndValidSource = mpSource + mnParaSize + 2;
+ mnElementSize = ImplGetUI16();
+ }
+ mnParaSize = 0;
+ if (mnElementSize)
+ {
+ if (rIStm.ReadBytes(mpSource, mnElementSize) != mnElementSize)
+ return false;
+ mpEndValidSource = mpSource + mnElementSize;
+ }
+
+ if ( mnElementSize & 1 )
+ rIStm.SeekRel( 1 );
+ ImplDoClass();
+
+ return mbStatus;
+};
+
+// GraphicImport - the exported function
+extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32
+ImportCGM(SvStream& rIn, uno::Reference< frame::XModel > const & rXModel, css::uno::Reference<css::task::XStatusIndicator> const & aXStatInd)
+{
+
+ sal_uInt32 nStatus = 0; // retvalue == 0 -> ERROR
+ // == 0xffrrggbb -> background color in the lower 24 bits
+
+ if( rXModel.is() )
+ {
+ try
+ {
+ CGM aCGM(rXModel);
+ if (aCGM.IsValid())
+ {
+ rIn.SetEndian(SvStreamEndian::BIG);
+ sal_uInt64 const nInSize = rIn.remainingSize();
+ rIn.Seek(0);
+
+ sal_uInt32 nNext = 0;
+ sal_uInt32 nAdd = nInSize / 20;
+ bool bProgressBar = aXStatInd.is();
+ if ( bProgressBar )
+ aXStatInd->start( "CGM Import" , nInSize );
+
+ while (aCGM.IsValid() && (rIn.Tell() < nInSize) && !aCGM.IsFinished())
+ {
+ if ( bProgressBar )
+ {
+ sal_uInt32 nCurrentPos = rIn.Tell();
+ if ( nCurrentPos >= nNext )
+ {
+ aXStatInd->setValue( nCurrentPos );
+ nNext = nCurrentPos + nAdd;
+ }
+ }
+
+ if (!aCGM.Write(rIn))
+ break;
+ }
+ if ( aCGM.IsValid() )
+ {
+ nStatus = aCGM.GetBackGroundColor() | 0xff000000;
+ }
+ if ( bProgressBar )
+ aXStatInd->end();
+ }
+ }
+ catch (const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.icgm", "");
+ nStatus = 0;
+ }
+ }
+ return nStatus;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgm.hxx b/filter/source/graphicfilter/icgm/cgm.hxx
new file mode 100644
index 000000000..b344cb22e
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgm.hxx
@@ -0,0 +1,151 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <cmath>
+#include <memory>
+#include <vector>
+#include "cgmtypes.hxx"
+
+class Graphic;
+class SvStream;
+class CGMChart;
+class CGMBitmap;
+class CGMImpressOutAct;
+class CGMElements;
+class GDIMetaFile;
+class VirtualDevice;
+
+class CGM
+{
+ friend class CGMChart;
+ friend class CGMBitmap;
+ friend class CGMElements;
+ friend class CGMImpressOutAct;
+
+ double mnVDCXadd;
+ double mnVDCYadd;
+ double mnVDCXmul;
+ double mnVDCYmul;
+ double mnVDCdx;
+ double mnVDCdy;
+ double mnXFraction;
+ double mnYFraction;
+ bool mbAngReverse; // AngularDirection
+
+ bool mbStatus;
+ bool mbMetaFile;
+ bool mbIsFinished;
+ bool mbPicture;
+ bool mbPictureBody;
+ bool mbFigure;
+ bool mbFirstOutPut;
+ bool mbInDefaultReplacement;
+ sal_uInt32 mnAct4PostReset;
+ std::unique_ptr<CGMBitmap> mpBitmapInUse;
+ std::unique_ptr<CGMChart> mpChart; // if sal_True->"SHWSLIDEREC"
+ // otherwise "BEGINPIC" commands
+ // controls page inserting
+ std::unique_ptr<CGMElements> pElement;
+ std::unique_ptr<CGMElements> pCopyOfE;
+ std::unique_ptr<CGMImpressOutAct> mpOutAct;
+ ::std::vector< std::unique_ptr<sal_uInt8[]> > maDefRepList;
+ ::std::vector< sal_uInt32 > maDefRepSizeList;
+
+ sal_uInt8* mpSource; // start of source buffer that is not increased
+ // ( instead use mnParaCount to index )
+ sal_uInt8* mpEndValidSource; // end position in source buffer of last valid data
+ sal_uInt32 mnParaSize; // actual parameter size which has been done so far
+ sal_uInt32 mnActCount; // increased by each action
+ std::unique_ptr<sal_uInt8[]>
+ mpBuf; // source stream operation -> then this is allocated for
+ // the temp input buffer
+
+ sal_uInt32 mnEscape;
+ sal_uInt32 mnElementClass;
+ sal_uInt32 mnElementID;
+ sal_uInt32 mnElementSize; // full parameter size for the latest action
+
+ sal_uInt32 ImplGetUI16();
+ static sal_uInt8 ImplGetByte( sal_uInt32 nSource, sal_uInt32 nPrecision );
+ sal_Int32 ImplGetI( sal_uInt32 nPrecision );
+ sal_uInt32 ImplGetUI( sal_uInt32 nPrecision );
+ static void ImplGetSwitch4( const sal_uInt8* pSource, sal_uInt8* pDest );
+ static void ImplGetSwitch8( const sal_uInt8* pSource, sal_uInt8* pDest );
+ double ImplGetFloat( RealPrecision, sal_uInt32 nRealSize );
+ sal_uInt32 ImplGetBitmapColor( bool bDirectColor = false );
+ void ImplSetMapMode();
+ void ImplSetUnderlineMode();
+ void ImplMapDouble( double& );
+ void ImplMapX( double& );
+ void ImplMapY( double& );
+ void ImplMapPoint( FloatPoint& );
+ inline double ImplGetIY();
+ inline double ImplGetFY();
+ inline double ImplGetIX();
+ inline double ImplGetFX();
+ sal_uInt32 ImplGetPointSize();
+ void ImplGetPoint( FloatPoint& rFloatPoint, bool bMap = false );
+ void ImplGetRectangle( FloatRect&, bool bMap = false );
+ void ImplGetRectangleNS( FloatRect& );
+ void ImplGetVector( double* );
+ static double ImplGetOrientation( FloatPoint const & rCenter, FloatPoint const & rPoint );
+ static void ImplSwitchStartEndAngle( double& rStartAngle, double& rEndAngle );
+ bool ImplGetEllipse( FloatPoint& rCenter, FloatPoint& rRadius, double& rOrientation );
+
+ void ImplDefaultReplacement();
+ void ImplDoClass();
+ void ImplDoClass0();
+ void ImplDoClass1();
+ void ImplDoClass2();
+ void ImplDoClass3();
+ void ImplDoClass4();
+ void ImplDoClass5();
+ void ImplDoClass6();
+ void ImplDoClass7();
+ void ImplDoClass8();
+ void ImplDoClass9();
+ void ImplDoClass15();
+
+ public:
+
+ ~CGM();
+
+ CGM(css::uno::Reference< css::frame::XModel > const & rModel);
+ sal_uInt32 GetBackGroundColor() const;
+ bool IsValid() const { return mbStatus; };
+ bool IsFinished() const { return mbIsFinished; };
+ bool Write( SvStream& rIStm );
+
+};
+
+inline bool useless(double value)
+{
+ if (!std::isfinite(value))
+ return true;
+ int exp;
+ std::frexp(value, &exp);
+ const int maxbits = sizeof(tools::Long) * 8;
+ return exp > maxbits;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgmtypes.hxx b/filter/source/graphicfilter/icgm/cgmtypes.hxx
new file mode 100644
index 000000000..5b7def212
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgmtypes.hxx
@@ -0,0 +1,127 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <tools/long.hxx>
+
+struct FloatPoint
+{
+ double X;
+ double Y;
+ FloatPoint():X(0), Y(0){};
+};
+
+struct FloatRect
+{
+ double Left;
+ double Top;
+ double Right;
+ double Bottom;
+ FloatRect():Left(0), Top(0), Right(0), Bottom(0){};
+ void Justify()
+ {
+ double fTemp;
+ if ( Left > Right )
+ {
+ fTemp = Left;
+ Left = Right;
+ Right = fTemp;
+ }
+ if ( Top > Bottom )
+ {
+ fTemp = Top;
+ Top = Bottom;
+ Bottom = fTemp;
+ }
+ }
+};
+
+struct HatchEntry
+{
+ int HatchStyle;
+ tools::Long HatchDistance;
+ tools::Long HatchAngle;
+};
+
+#define ASF_LINETYPE 0x00000001UL
+#define ASF_LINEWIDTH 0x00000002UL
+#define ASF_LINECOLOR 0x00000004UL
+#define ASF_MARKERTYPE 0x00000008UL
+#define ASF_MARKERSIZE 0x00000010UL
+#define ASF_MARKERCOLOR 0x00000020UL // NS
+#define ASF_FILLINTERIORSTYLE 0x00000040UL
+#define ASF_HATCHINDEX 0x00000080UL
+#define ASF_PATTERNINDEX 0x00000100UL
+#define ASF_BITMAPINDEX 0x00000200UL // NS
+#define ASF_FILLCOLOR 0x00000400UL
+#define ASF_EDGETYPE 0x00000800UL
+#define ASF_EDGEWIDTH 0x00001000UL
+#define ASF_EDGECOLOR 0x00002000UL
+#define ASF_TEXTFONTINDEX 0x00004000UL
+#define ASF_TEXTPRECISION 0x00008000UL
+#define ASF_CHARACTEREXPANSION 0x00010000UL
+#define ASF_CHARACTERSPACING 0x00020000UL
+#define ASF_TEXTCOLOR 0x00040000UL
+
+#define ACT4_GRADIENT_ACTION 0x00000001UL
+
+enum RealPrecision { RP_FLOAT = 0, RP_FIXED = 1 };
+
+enum ScalingMode { SM_ABSTRACT = 0, SM_METRIC = 1 };
+
+enum VDCType { VDC_INTEGER = 0, VDC_REAL = 1 };
+enum DeviceViewPortMode { DVPM_FRACTION = 0, DVPM_METRIC = 1, DVPM_DEVICE = 2 };
+enum DeviceViewPortMap { DVPM_NOT_FORCED = 0, DVPM_FORCED = 1 };
+enum DeviceViewPortMapH { DVPMH_LEFT = 0, DVPMH_CENTER = 1, CVPMH_RIGHT = 2 };
+enum DeviceViewPortMapV { DVPMV_BOTTOM = 0, DVPMV_CENTER = 1, DVPMV_TOP = 2 };
+
+enum ClipIndicator { CI_OFF = 0, CI_ON = 1 };
+
+enum ColorSelectionMode { CSM_INDEXED = 0, CSM_DIRECT = 1 };
+enum ColorModel { CM_RGB = 0, CM_CMYK = 1 };
+
+enum CharacterCodingA { CCA_BASIC_7 = 0, CCA_BASIC_8 = 1, CCA_EXT_7 = 2, CCA_EXT_8 = 3 };
+enum TextPrecision { TPR_STRING = 0, TPR_CHARACTER = 1, TPR_STROKE = 2, TPR_UNDEFINED = 0xffff };
+enum TextPath { TPR_RIGHT = 0, TPR_LEFT = 1, TPR_UP = 2, TPR_DOWN = 3 };
+enum TextAlignmentH { TAH_NORMAL = 0, TAH_LEFT = 1, TAH_CENTER = 2, TAH_RIGHT = 3, TAH_CONT = 4 };
+enum TextAlignmentV { TAV_NORMAL = 0, TAV_TOP = 1, TAV_CAP = 2, TAV_HALF = 3, TAV_BASE = 4, TAV_BOTTOM = 5, TAV_CONT = 6 };
+enum UnderlineMode { UM_OFF = 0, UM_LOW = 1, UM_HIGH = 2, UM_STRIKEOUT = 4, UM_OVERSCORE = 8 };
+enum FinalFlag { FF_NOT_FINAL = 0, FF_FINAL = 1 };
+
+enum LineType { LT_SOLID = 1, LT_DASH = 2, LT_DOT = 3, LT_DASHDOT = 4, LT_DASHDOTDOT = 5, // Standard
+ LT_NONE = -4, LT_DOTDOTSPACE = -3, LT_LONGDASH = -2, LT_DASHDASHDOT = -1 }; // GDSF Styles
+enum SpecMode { SM_ABSOLUTE = 0, SM_SCALED = 1 };
+enum LineCapType { LCT_BUTT = 0, LCT_ROUND = 1, LCT_SQUARE = 2, LCT_TRIANGLE = 3, LCT_ARROW = 4, LCT_NONE = -1 };
+enum LineJoinType { LJT_MITER = 0, LJT_ROUND = 1, LJT_BEVEL = 2, LJT_NONE = -1 };
+
+
+enum EdgeType { ET_SOLID = 1, ET_DASH = 2, ET_DOT = 3, ET_DASHDOT = 4, ET_DASHDOTDOT = 5, // Standard
+ ET_NONE = -4, ET_DOTDOTSPACE = -3, ET_LONGDASH = -2, ET_DASHDASHDOT = -1 }; // GDSF Styles
+enum EdgeVisibility { EV_OFF = 0, EV_ON = 1 };
+
+enum MarkerType { MT_POINT = 1, MT_PLUS = 2, MT_STAR = 3, MT_CIRCLE = 4, MT_CROSS = 5 };
+
+enum Transparency { T_OFF = 0, T_ON = 1 };
+
+enum FillInteriorStyle { FIS_HOLLOW = 0, FIS_SOLID = 1, FIS_PATTERN = 2, FIS_HATCH = 3, FIS_EMPTY = 4, FIS_GEOPATTERN = 5,
+ FIS_INTERPOLATED = 6, FIS_GRADIENT = 7 };
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/chart.cxx b/filter/source/graphicfilter/icgm/chart.cxx
new file mode 100644
index 000000000..91818149a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/chart.cxx
@@ -0,0 +1,57 @@
+/* -*- 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 "chart.hxx"
+
+
+CGMChart::CGMChart()
+ : mnCurrentFileType(0)
+{
+ for ( sal_Int8 i = 0; i < 7; i++ )
+ {
+ mDataNode[ i ].nZoneEnum = i;
+ }
+}
+
+CGMChart::~CGMChart()
+{
+ // delete the whole textentry structure
+ for (const auto & pTextEntry : maTextEntryList)
+ {
+ if ( pTextEntry )
+ delete [] pTextEntry->pText;
+ }
+}
+
+void CGMChart::InsertTextEntry( std::unique_ptr<TextEntry> pTextEntry )
+{
+ maTextEntryList.push_back( std::move(pTextEntry) );
+}
+
+void CGMChart::ResetAnnotation()
+{
+ mDataNode[ 0 ].nZoneEnum = 0;
+}
+
+bool CGMChart::IsAnnotation() const
+{
+ return ( mDataNode[ 0 ].nZoneEnum == 0 );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/chart.hxx b/filter/source/graphicfilter/icgm/chart.hxx
new file mode 100644
index 000000000..ef77ace0e
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/chart.hxx
@@ -0,0 +1,84 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+#include <memory>
+#include <vector>
+
+/* FILE TYPE CONSTANTS: */
+#define BULCHART 32 /* Bullet chart file. */
+/* the following were added although SPC doesn't have a #define */
+/* for them... */
+#define AUTOTTLCHT 95 /* Autobuild TTL CHT */
+#define AUTOBULCHT 96 /* Autobuild BUL CHT */
+#define AUTOTABCHT 97 /* Autobuild TAB CHT */
+
+typedef struct TextEntry
+{
+ sal_uInt16 nTypeOfText;
+ sal_uInt16 nRowOrLineNum;
+ sal_uInt16 nColumnNum;
+ sal_uInt16 nZoneSize; // textzone attributes
+ sal_uInt16 nLineType;
+ sal_uInt16 nAttributes;
+ char* pText; // null terminated text
+} TextEntry;
+
+struct DataNode
+{
+ sal_Int16 nBoxX1;
+ sal_Int16 nBoxY1;
+ sal_Int16 nBoxX2;
+ sal_Int16 nBoxY2;
+ sal_Int8 nZoneEnum;
+ DataNode()
+ : nBoxX1(0)
+ , nBoxY1(0)
+ , nBoxX2(0)
+ , nBoxY2(0)
+ , nZoneEnum(0)
+ {
+ }
+};
+
+class CGM;
+class CGMImpressOutAct;
+class CGMChart final
+{
+ friend class CGM;
+ friend class CGMImpressOutAct;
+
+ sal_Int8 mnCurrentFileType;
+ ::std::vector< std::unique_ptr<TextEntry> > maTextEntryList;
+ DataNode mDataNode[ 7 ];
+
+ public:
+ CGMChart();
+ ~CGMChart();
+
+ void InsertTextEntry( std::unique_ptr<TextEntry> );
+
+ void ResetAnnotation();
+ bool IsAnnotation() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class0.cxx b/filter/source/graphicfilter/icgm/class0.cxx
new file mode 100644
index 000000000..a31bce5d2
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class0.cxx
@@ -0,0 +1,128 @@
+/* -*- 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 "bitmap.hxx"
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass0()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Begin Metafile*/
+ {
+ ImplSetMapMode();
+ mbMetaFile = true;
+ }
+ break;
+ case 0x02 : /*End MetaFile*/
+ {
+ if ( mpBitmapInUse ) // process existing graphic
+ {
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+ mbIsFinished = true;
+ mbPictureBody = false;
+ mbMetaFile = false;
+ }
+ break;
+ case 0x03 : /*Begin Picture*/
+ {
+ if (mbPicture || mbInDefaultReplacement)
+ mbStatus = false;
+ else
+ {
+ *pCopyOfE = *pElement;
+ ImplDefaultReplacement();
+ ImplSetMapMode();
+ mbPicture = mbFirstOutPut = true;
+ mbFigure = false;
+ mnAct4PostReset = 0;
+ if ( mpChart == nullptr ) // normal CGM Files determines "BeginPic"
+ mpOutAct->InsertPage(); // as the next slide
+ }
+ }
+ break;
+ case 0x04 : /*Begin Picture Body*/
+ mbPictureBody = true;
+ break;
+ case 0x05 : /* End Picture*/
+ {
+ if ( mbPicture )
+ {
+ if ( mpBitmapInUse ) // process existing graphic
+ {
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+ mpOutAct->EndFigure(); // close potential figures
+ mpOutAct->EndGrouping(); // finish potential groups
+ *pElement = *pCopyOfE;
+ mbFigure = mbFirstOutPut = mbPicture = mbPictureBody = false;
+ }
+ else
+ mbStatus = false;
+ }
+ break;
+ case 0x06 : /*Begin Segment*/
+ pElement->bSegmentCount = true;
+ break;
+ case 0x07 : /*End Segment*/
+ pElement->bSegmentCount = true;
+ break;
+ case 0x08 : /*Begin Figure*/
+ mbFigure = true;
+ mpOutAct->BeginFigure();
+ break;
+ case 0x09 : /*End Figure*/
+ mpOutAct->EndFigure();
+ mbFigure = false;
+ break;
+ case 0x0d : /*Begin Protection vcl::Region */break;
+ case 0x0e : /*End Protection vcl::Region */break;
+ case 0x0f : /*Begin Compound Line */break;
+ case 0x10 : /*End Compound Line */break;
+ case 0x11 : /*Begin Compound Text Path */break;
+ case 0x12 : /*End Compound Text Path */break;
+ case 0x13 : /*Begin Tile Array */break; // NS
+ case 0x14 : /*End Tile Array */break; // NS
+ case 0xff : /*Filter Setup */break;
+ case 0xfe : /*Begin Block Text vcl::Region */break;
+ case 0xfd : /*End Block Text vcl::Region */break;
+ case 0xfc : /*Begin Group*/
+ mpOutAct->BeginGroup();
+ break;
+ case 0xfb : /*End Group*/
+ mpOutAct->EndGroup();
+ break;
+ case 0xfa : /*Begin Patch */break;
+ case 0xf9 : /*Begin Patch */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class1.cxx b/filter/source/graphicfilter/icgm/class1.cxx
new file mode 100644
index 000000000..07a6fe253
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class1.cxx
@@ -0,0 +1,225 @@
+/* -*- 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 <sal/config.h>
+#include <sal/log.hxx>
+
+#include <o3tl/safeint.hxx>
+
+#include "bundles.hxx"
+#include "cgm.hxx"
+#include "elements.hxx"
+
+
+void CGM::ImplDoClass1()
+{
+ tools::Long nInteger, nI0, nI1;
+ sal_uInt32 nUInteger;
+
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Metafile Version*/
+ pElement->nMetaFileVersion = ImplGetI( pElement->nIntegerPrecision );
+ break;
+ case 0x02 : /*Metafile Description */break;
+ case 0x03 : /*VDC Type*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eVDCType = VDC_INTEGER; break;
+ case 1 : pElement->eVDCType = VDC_REAL; break;
+ default: mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x04 : /*Integer Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nIntegerPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Real Precision*/
+ {
+ nUInteger = ImplGetUI16();
+ nI0 = ImplGetI( pElement->nIntegerPrecision ); // exponent
+ nI1 = ImplGetI( pElement->nIntegerPrecision ); // mantissa
+ switch( nUInteger )
+ {
+ case 0 :
+ pElement->eRealPrecision = RP_FLOAT;
+ switch ( nI0 )
+ {
+ case 9 :
+ if ( nI1 != 23 )
+ mbStatus = false;
+ pElement->nRealSize = 4;
+ break;
+ case 12 :
+ if ( nI1 != 52 )
+ mbStatus =false;
+ pElement->nRealSize = 8;
+ break;
+ default:
+ mbStatus = false;
+ break;
+ }
+ break;
+ case 1 :
+ pElement->eRealPrecision = RP_FIXED;
+ if ( nI0 != nI1 )
+ mbStatus = false;
+ if ( nI0 == 16 )
+ pElement->nRealSize = 4;
+ else if ( nI0 == 32 )
+ pElement->nRealSize = 8;
+ else
+ mbStatus = false;
+ break;
+ default :
+ mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x06 : /*Index Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nIndexPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x07 : /*Color Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nColorPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x08 : /*Color Index Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nColorIndexPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x09 : /*Maximum Colour Index*/
+ {
+ pElement->nColorMaximumIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ if ( ( pElement->nColorMaximumIndex > 256 /*255*/ ) || ( pElement->nColorMaximumIndex == 0 ) )
+ mbStatus = false;
+ }
+ break;
+ case 0x0a : /*Color Value Extent*/
+ {
+ nI1 = 6;
+ }
+ break;
+ case 0x0b : /*MetaFile Element List */break;
+ case 0x0c : /*MetaFile Default Replacement*/
+ {
+ if ( mnElementSize > 1 )
+ {
+ std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ mnElementSize ]);
+ memcpy( pBuf.get(), mpSource, mnElementSize );
+ maDefRepList.push_back( std::move(pBuf) );
+ maDefRepSizeList.push_back( mnElementSize );
+ }
+ mnParaSize = mnElementSize;
+ }
+ break;
+ case 0x0d : /*Font List*/
+ {
+ while ( mnParaSize < mnElementSize )
+ {
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ pElement->aFontList.InsertName( mpSource + mnParaSize, nSize );
+ mnParaSize += nSize;
+ }
+ }
+ break;
+ case 0x0e : /*Character Set List*/
+ {
+ while ( mnParaSize < mnElementSize )
+ {
+ ImplGetUI16(); // skip CharSetType
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ pElement->aFontList.InsertCharSet( mpSource + mnParaSize, nSize );
+ mnParaSize += nSize;
+ }
+ }
+ break;
+ case 0x0f : /*Character Coding Announcer*/
+ {
+ auto nCharacterCoding = ImplGetUI16();
+ if (nCharacterCoding <= CCA_EXT_8)
+ pElement->eCharacterCodingA = static_cast<CharacterCodingA>(nCharacterCoding);
+ else
+ SAL_WARN("filter.icgm", "CharacterCoding " << nCharacterCoding << " requested, but legal max is " << CCA_EXT_8);
+ }
+ break;
+ case 0x10 : /*Name Precision */break; // NS
+ case 0x11 : /*Maximum VDC Extent */break; // NS
+ case 0x12 : /*Segment Priority Extent */break; // NS
+ case 0x13 : /*Color Model */break; // NS
+ case 0x14 : /*Color Calibration */break; // NS
+ case 0x15 : /*Font Properties */break; // NS
+ case 0x16 : /*Glyph Mapping */break; // NS
+ case 0x17 : /*Symbol Library List */break; // NS
+ case 0xfc : /*Inquire Function Support */break;
+ case 0xfa : /*End Metafile Defaults Replacement */break;
+ case 0xf8 : /*Set Color Value Desc Extent */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class2.cxx b/filter/source/graphicfilter/icgm/class2.cxx
new file mode 100644
index 000000000..8d410e475
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class2.cxx
@@ -0,0 +1,233 @@
+/* -*- 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 "cgm.hxx"
+#include "bundles.hxx"
+#include "elements.hxx"
+
+
+void CGM::ImplDoClass2()
+{
+ sal_uInt32 nUInteger;
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Scaling Mode*/
+ {
+ if ( mnElementSize ) // HACK (NASA.CGM)
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eScalingMode = SM_ABSTRACT; break;
+ case 1 : pElement->eScalingMode = SM_METRIC; break;
+ default : mbStatus = false; break;
+ }
+ pElement->nScalingFactor = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ ImplSetMapMode();
+ }
+ }
+ break;
+ case 0x02 : /*Color Selection Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eColorSelectionMode = CSM_INDEXED; break;
+ case 1 : pElement->eColorSelectionMode = CSM_DIRECT; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x03 : /*Line Width Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eLineWidthSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eLineWidthSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x04 : /*Marker Size Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eMarkerSizeSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eMarkerSizeSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Edge Width Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eEdgeWidthSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eEdgeWidthSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x06 : /*VDC Extent*/
+ {
+ ImplGetRectangleNS( pElement->aVDCExtent );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x07 : /*Background Color*/
+ pElement->nBackGroundColor = ImplGetBitmapColor( true );
+ break;
+ case 0x08 : /*Device Viewport*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ ImplGetRectangle( pElement->aDeviceViewPort );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x09 : /*Device Viewport Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eDeviceViewPortMode = DVPM_FRACTION; break;
+ case 1 : pElement->eDeviceViewPortMode = DVPM_METRIC; break;
+ case 2 : pElement->eDeviceViewPortMode = DVPM_DEVICE; break;
+ default : mbStatus = false; break;
+ }
+ pElement->nDeviceViewPortScale = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x0a : /*Device Viewport Mapping*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMap = DVPM_NOT_FORCED; break;
+ case 1 : pElement->eDeviceViewPortMap = DVPM_FORCED; break;
+ default : mbStatus = false; break;
+ }
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMapH = DVPMH_LEFT; break;
+ case 1 : pElement->eDeviceViewPortMapH = DVPMH_CENTER; break;
+ case 2 : pElement->eDeviceViewPortMapH = CVPMH_RIGHT; break;
+ default : mbStatus = false; break;
+ }
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMapV = DVPMV_BOTTOM; break;
+ case 1 : pElement->eDeviceViewPortMapV = DVPMV_CENTER; break;
+ case 2 : pElement->eDeviceViewPortMapV = DVPMV_TOP; break;
+ default : mbStatus = false; break;
+ }
+ ImplSetMapMode();
+ }
+ break;
+ case 0x0b : /*Line Representation*/
+ {
+ LineBundle aTempLineBundle;
+ aTempLineBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempLineBundle.eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempLineBundle.nLineWidth = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempLineBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateLineBundle = aTempLineBundle.GetIndex() == pElement->pLineBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aLineList, aTempLineBundle );
+ if (bUpdateLineBundle)
+ pElement->pLineBundle = static_cast<LineBundle*>(CGMElements::GetBundleIndex(aTempLineBundle.GetIndex(), pElement->aLineList, pElement->aLineBundle));
+ }
+ break;
+ case 0x0c : /*Marker Representation*/
+ {
+ MarkerBundle aTempMarkerBundle;
+ aTempMarkerBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempMarkerBundle.eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempMarkerBundle.nMarkerSize = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempMarkerBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateMarkerBundle = aTempMarkerBundle.GetIndex() == pElement->pMarkerBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aMarkerList, aTempMarkerBundle );
+ if (bUpdateMarkerBundle)
+ pElement->pMarkerBundle = static_cast<MarkerBundle*>(CGMElements::GetBundleIndex(aTempMarkerBundle.GetIndex(), pElement->aMarkerList, pElement->aMarkerBundle));
+ }
+ break;
+ case 0x0d : /*Text Representation*/
+ {
+ TextBundle aTempTextBundle;
+ aTempTextBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempTextBundle.nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ aTempTextBundle.eTextPrecision = static_cast<TextPrecision>(ImplGetI( pElement->nIndexPrecision ));
+ aTempTextBundle.nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempTextBundle.nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempTextBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateTextBundle = aTempTextBundle.GetIndex() == pElement->pTextBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aTextList, aTempTextBundle );
+ if (bUpdateTextBundle)
+ pElement->pTextBundle = static_cast<TextBundle*>(CGMElements::GetBundleIndex(aTempTextBundle.GetIndex(), pElement->aTextList, pElement->aTextBundle));
+ }
+ break;
+ case 0x0e : /*Fill Representation*/
+ {
+ FillBundle aTempFillBundle;
+ aTempFillBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempFillBundle.eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetI( pElement->nIndexPrecision ));
+ aTempFillBundle.SetColor( ImplGetBitmapColor() );
+ aTempFillBundle.nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ aTempFillBundle.nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ const bool bUpdateFillBundle = aTempFillBundle.GetIndex() == pElement->pFillBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aFillList, aTempFillBundle );
+ if (bUpdateFillBundle)
+ pElement->pFillBundle = static_cast<FillBundle*>(CGMElements::GetBundleIndex(aTempFillBundle.GetIndex(), pElement->aFillList, pElement->aFillBundle));
+ }
+ break;
+ case 0x0f : /*Edge Representation*/
+ {
+ EdgeBundle aTempEdgeBundle;
+ aTempEdgeBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempEdgeBundle.eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempEdgeBundle.nEdgeWidth = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempEdgeBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateEdgeBundle = aTempEdgeBundle.GetIndex() == pElement->pEdgeBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aEdgeList, aTempEdgeBundle );
+ if (bUpdateEdgeBundle)
+ pElement->pEdgeBundle = static_cast<EdgeBundle*>(CGMElements::GetBundleIndex(aTempEdgeBundle.GetIndex(), pElement->aEdgeList, pElement->aEdgeBundle));
+ }
+ break;
+ case 0x10 : /*Interior Style Specification Mode */break; // NS
+ case 0x11 : /*Line and Edge Type Definition */break;
+ case 0x12 : /*Hatch Style Definition */break; // NS
+ case 0x13 : /*Geometric Pattern Definition */break; // NS
+ case 0xff : /*inquire VDC EXTENT */break;
+ case 0xfe : /*inquire Background Color */break;
+ case 0xfd : /*inquire Device Viewport */break;
+ case 0xfc : /*set Font Selection Mode */break;
+ case 0xfb : /*inquire Color Selection Mode */break;
+ case 0xfa : /*inquire Font Selection Mode */break;
+ case 0xf9 : /*set Char Height Spec Mode*/
+ {
+ ImplGetUI16(); // -Wall is this really needed?
+ }
+ break;
+ case 0xf8 : /*set Background Style */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class3.cxx b/filter/source/graphicfilter/icgm/class3.cxx
new file mode 100644
index 000000000..3cc25730f
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class3.cxx
@@ -0,0 +1,134 @@
+/* -*- 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 "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass3()
+{
+ sal_uInt32 nUInteger;
+ switch ( mnElementID )
+ {
+ case 0x01 : /*VDC Integer Precision*/
+ {
+ switch( ImplGetI( pElement->nIntegerPrecision ) )
+ {
+ case 16 : pElement->nVDCIntegerPrecision = 2; break;
+ case 32 : pElement->nVDCIntegerPrecision = 4; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x02 : /*VDC Real Precision*/
+ {
+ nUInteger = ImplGetUI16();
+ const tools::Long nI0 = ImplGetI( pElement->nIntegerPrecision ); // exponent
+ const tools::Long nI1 = ImplGetI( pElement->nIntegerPrecision ); // mantissa
+ switch( nUInteger )
+ {
+ case 0 :
+ pElement->eVDCRealPrecision = RP_FLOAT;
+ switch ( nI0 )
+ {
+ case 9 :
+ if ( nI1 != 23 )
+ mbStatus = false;
+ pElement->nVDCRealSize = 4;
+ break;
+ case 12 :
+ if ( nI1 != 52 )
+ mbStatus =false;
+ pElement->nVDCRealSize = 8;
+ break;
+ default:
+ mbStatus = false;
+ break;
+ }
+ break;
+ case 1 :
+ pElement->eVDCRealPrecision = RP_FIXED;
+ if ( nI0 != nI1 )
+ mbStatus = false;
+ if ( nI0 == 16 )
+ pElement->nVDCRealSize = 4;
+ else if ( nI0 == 32 )
+ pElement->nVDCRealSize = 8;
+ else
+ mbStatus = false;
+ break;
+ default :
+ mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x03 : /*Auxiliary Colour*/
+ {
+ pElement->nAuxiliaryColor = ImplGetBitmapColor();
+ }
+ break;
+ case 0x04 : /*Transparency*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eTransparency = T_OFF; break;
+ case 1 : pElement->eTransparency = T_ON; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Clip Rectangle*/
+ ImplGetRectangle( pElement->aClipRect );
+ break;
+ case 0x06 : /*Clip Indicator*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eClipIndicator = CI_OFF; break;
+ case 1 : pElement->eClipIndicator = CI_ON; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x07 : /*Line Clipping Mode */break; // NS
+ case 0x08 : /*Marker Clipping Mode */break; // NS
+ case 0x09 : /*Edge Clipping Mode */break; // NS
+ case 0x0a : /*New Region*/
+ mpOutAct->NewRegion();
+ break;
+ case 0x0b : /*Save Primitive Context */break; // NS
+ case 0x0c : /*Restore Primitive Context */break; // NS
+ case 0x11 : /*Protection vcl::Region Indicator */break;
+ case 0x12 : /*Generalized Text Path Mode */break; // NS
+ case 0x13 : /*Mitre Limit*/
+ pElement->nMitreLimit = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ break; // NS
+ case 0x14 : /*Transparent Cell Color */break; // NS
+ case 0xfc : /*Text Path Alignment Modes */break;
+ case 0xfd : /*Pop Transformation Stack */break;
+ case 0xfe : /*Push Transformation Stack */break;
+ case 0xff : /*Set Patch ID */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class4.cxx b/filter/source/graphicfilter/icgm/class4.cxx
new file mode 100644
index 000000000..af66ff26a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class4.cxx
@@ -0,0 +1,911 @@
+/* -*- 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 "bitmap.hxx"
+#include "cgm.hxx"
+#include "chart.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+#include <o3tl/float_int_conversion.hxx>
+#include <o3tl/safeint.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+double CGM::ImplGetOrientation( FloatPoint const & rCenter, FloatPoint const & rPoint )
+{
+ double nX = rPoint.X - rCenter.X;
+ double nY = rPoint.Y - rCenter.Y;
+
+ double fSqrt = std::hypot(nX, nY);
+ double fOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if (nY > 0)
+ fOrientation = 360 - fOrientation;
+
+ return fOrientation;
+}
+
+
+void CGM::ImplSwitchStartEndAngle( double& rStartAngle, double& rEndAngle )
+{
+ double nTemp;
+ nTemp = rStartAngle;
+ rStartAngle = rEndAngle;
+ rEndAngle = nTemp;
+}
+
+
+void CGM::ImplGetVector( double* pVector )
+{
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ for ( sal_uInt32 i = 0; i < 4; i++ )
+ {
+ pVector[ i ] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ }
+ else
+ {
+ for ( sal_uInt32 i = 0; i < 4; i++ )
+ {
+ pVector[ i ] = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ }
+ pVector[ 0 ] *= mnVDCXmul;
+ pVector[ 2 ] *= mnVDCXmul;
+ pVector[ 1 ] *= mnVDCYmul;
+ pVector[ 3 ] *= mnVDCYmul;
+}
+
+
+bool CGM::ImplGetEllipse( FloatPoint& rCenter, FloatPoint& rRadius, double& rAngle )
+{
+ FloatPoint aPoint1, aPoint2;
+ double fRot1, fRot2;
+ ImplGetPoint( rCenter, true );
+ ImplGetPoint( aPoint1, true );
+ ImplGetPoint( aPoint2, true );
+ fRot1 = ImplGetOrientation( rCenter, aPoint1 );
+ fRot2 = ImplGetOrientation( rCenter, aPoint2 );
+ rAngle = ImplGetOrientation( rCenter, aPoint1 );
+ aPoint1.X -= rCenter.X;
+ aPoint1.Y -= rCenter.Y;
+ rRadius.X = std::hypot(aPoint1.X, aPoint1.Y);
+ aPoint2.X -= rCenter.X;
+ aPoint2.Y -= rCenter.Y;
+ rRadius.Y = std::hypot(aPoint2.X, aPoint2.Y);
+
+ if ( fRot1 > fRot2 )
+ {
+ if ( ( fRot1 - fRot2 ) < 180 )
+ return false;
+ }
+ else
+ {
+ if ( ( fRot2 - fRot1 ) > 180 )
+ return false;
+ }
+ return true;
+}
+
+void CGM::ImplDoClass4()
+{
+ if ( mbFirstOutPut )
+ mpOutAct->FirstOutPut();
+
+ if ( mpBitmapInUse && ( mnElementID != 9 ) ) // process existed graphic
+ { // because there are now no pending bitmap actions
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+
+ if ( ( mpChart == nullptr ) || mpChart->IsAnnotation() )
+ {
+ switch ( mnElementID )
+ {
+ case 0x01 : /*PolyLine*/
+ {
+ sal_uInt32 nPoints = mnElementSize / ImplGetPointSize();
+ tools::Polygon aPolygon( static_cast<sal_uInt16>(nPoints) );
+ for ( sal_uInt32 i = 0; i < nPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), i );
+ }
+ if ( mbFigure )
+ mpOutAct->RegPolyLine( aPolygon );
+ else
+ mpOutAct->DrawPolyLine( aPolygon );
+ }
+ break;
+
+ case 0x02 : /*Disjoint PolyLine*/
+ {
+ sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
+ mnElementSize / ImplGetPointSize());
+ if ( ! ( nPoints & 1 ) )
+ {
+ nPoints >>= 1;
+ FloatPoint aFloatPoint;
+ if ( mbFigure )
+ {
+ tools::Polygon aPolygon( nPoints );
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
+ }
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ else
+ {
+ mpOutAct->BeginGroup();
+ tools::Polygon aPolygon( sal_uInt16(2) );
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 1);
+ mpOutAct->DrawPolyLine( aPolygon );
+ }
+ mpOutAct->EndGroup();
+ }
+ }
+ }
+ break;
+
+ case 0x03 : /*PolyMarker*/ break;
+ case 0x04 : /*Text*/
+ {
+ FloatPoint aFloatPoint;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint ( aFloatPoint, true );
+ sal_uInt32 nType = ImplGetUI16();
+ sal_uInt32 nSize = ImplGetUI( 1 );
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
+
+ awt::Size aSize;
+ awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
+ mpOutAct->DrawText(aPoint, aSize, aStr, static_cast<FinalFlag>(nType));
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x05 : /*Restricted Text*/
+ {
+ double dx, dy;
+ FloatPoint aFloatPoint;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ dx = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ dy = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ dx = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ dy = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ ImplMapDouble( dx );
+ ImplMapDouble( dy );
+
+ ImplGetPoint ( aFloatPoint, true );
+ sal_uInt32 nType = ImplGetUI16();
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
+
+ awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
+ awt::Size aSize(static_cast<tools::Long>(dx), static_cast<tools::Long>(dy));
+ mpOutAct->DrawText(aPoint, aSize , aStr, static_cast<FinalFlag>(nType));
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x06 : /*Append Text*/
+ {
+ (void)ImplGetUI16(); // nType
+ sal_uInt32 nSize = ImplGetUI( 1 );
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) <= nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ mpSource[ mnParaSize + nSize ] = 0;
+
+ mpOutAct->AppendText( reinterpret_cast<char*>(mpSource) + mnParaSize );
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x07 : /*Polygon*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
+ mnElementSize / ImplGetPointSize());
+ tools::Polygon aPolygon( nPoints );
+ for ( sal_uInt16 i = 0; i < nPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
+ }
+ mpOutAct->DrawPolygon( aPolygon );
+ }
+ break;
+
+ case 0x08 : /*Polygon Set*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ std::vector<Point> aPoints;
+ tools::PolyPolygon aPolyPolygon;
+ FloatPoint aFloatPoint;
+
+ while ( mnParaSize < mnElementSize )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ sal_uInt32 nEdgeFlag = ImplGetUI16();
+ aPoints.push_back(Point(static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y)));
+ if ( ( nEdgeFlag & 2 ) || ( mnParaSize == mnElementSize ) )
+ {
+ aPolyPolygon.Insert(tools::Polygon(aPoints.size(), aPoints.data()));
+ aPoints.clear();
+ }
+ }
+ mpOutAct->DrawPolyPolygon( aPolyPolygon );
+ }
+ break;
+
+ case 0x09 : /*Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ if ( mpBitmapInUse )
+ {
+ std::unique_ptr<CGMBitmap> xBmpDesc(mpBitmapInUse->GetNext());
+ if (xBmpDesc) // we possibly get a bitmap back which does not fit to
+ { // to the previous -> we need to delete this one too
+ mpOutAct->DrawBitmap(xBmpDesc->GetBitmap());
+ }
+ }
+ else
+ {
+ mpBitmapInUse.reset( new CGMBitmap( *this ) );
+ }
+ }
+ break;
+
+ case 0x0a : /*Generalized Drawing Primitive*/
+ {
+ ImplGetI( pElement->nIntegerPrecision ); //-Wall is this needed
+ ImplGetUI( pElement->nIntegerPrecision ); //-Wall is this needed
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x0b : /*Rectangle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ FloatRect aFloatRect;
+ ImplGetRectangle( aFloatRect, true );
+ mpOutAct->DrawRectangle( aFloatRect );
+ }
+ break;
+
+ case 0x0c : /*Circle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ double fRotation = 0;
+ FloatPoint aCenter, aRadius;
+ ImplGetPoint( aCenter, true );
+ if ( pElement->eVDCType == VDC_REAL )
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+ mpOutAct->DrawEllipse( aCenter, aRadius, fRotation );
+ }
+ break;
+
+ case 0x0d : /*Circular Arc 3 Point*/
+ {
+ FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
+ ImplGetPoint( aStartingPoint, true );
+ ImplGetPoint( aIntermediatePoint, true );
+ ImplGetPoint( aEndingPoint, true );
+
+ double fA = aIntermediatePoint.X - aStartingPoint.X;
+ double fB = aIntermediatePoint.Y - aStartingPoint.Y;
+ double fC = aEndingPoint.X - aStartingPoint.X;
+ double fD = aEndingPoint.Y - aStartingPoint.Y;
+
+ double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
+ double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
+
+ double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
+
+ bool bUseless = fG == 0;
+
+ FloatPoint aCenterPoint;
+ if (!bUseless)
+ {
+ aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
+ aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
+ bUseless = useless(aCenterPoint.X) || useless(aCenterPoint.Y);
+ }
+
+ if (!bUseless)
+ bUseless = useless(aStartingPoint.X) || useless(aStartingPoint.Y);
+
+ if (!bUseless)
+ {
+ double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
+ double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
+ double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
+
+ int nSwitch = 0;
+
+ if ( fStartAngle > fEndAngle )
+ {
+ nSwitch ^=1;
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
+ {
+ nSwitch ^=1;
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ double fRadius = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
+
+ if ( mbFigure )
+ {
+ double fLeft = aCenterPoint.X - fRadius;
+ double fTop = aCenterPoint.Y - fRadius;
+ double fRight = fLeft + (2 * fRadius);
+ double fBottom = fTop + (2 * fRadius);
+ bUseless = useless(fLeft) || useless(fTop) || useless(2 * fRadius) || useless(fRight) || useless(fBottom);
+ if (!bUseless)
+ {
+ double fCenterCalc = fLeft + fRight;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ double fCenterCalc = fTop + fBottom;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * fRadius, 2 * fRadius));
+ tools::Polygon aPolygon( aBoundingBox, Point( static_cast<tools::Long>(aStartingPoint.X), static_cast<tools::Long>(aStartingPoint.Y) ) ,Point( static_cast<tools::Long>(aEndingPoint.X), static_cast<tools::Long>(aEndingPoint.Y) ), PolyStyle::Arc );
+ if ( nSwitch )
+ mpOutAct->RegPolyLine( aPolygon, true );
+ else
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ }
+ else
+ {
+ fG = 0;
+ FloatPoint aRadius;
+ aRadius.X = aRadius.Y = fRadius;
+ mpOutAct->DrawEllipticalArc( aCenterPoint, aRadius, fG, 2, fStartAngle, fEndAngle );
+ }
+ }
+ }
+ break;
+
+ case 0x0e : /*Circular Arc 3 Point Close*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
+ ImplGetPoint( aStartingPoint );
+ ImplGetPoint( aIntermediatePoint );
+ ImplGetPoint( aEndingPoint );
+
+ double fA = aIntermediatePoint.X - aStartingPoint.X;
+ double fB = aIntermediatePoint.Y - aStartingPoint.Y;
+ double fC = aEndingPoint.X - aStartingPoint.X;
+ double fD = aEndingPoint.Y - aStartingPoint.Y;
+
+ double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
+ double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
+
+ double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
+
+ if ( fG != 0 )
+ {
+ FloatPoint aCenterPoint;
+ aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
+ aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
+ double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
+ double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
+ double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
+
+ if ( fStartAngle > fEndAngle )
+ {
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
+ {
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ FloatPoint fRadius;
+ fRadius.Y = fRadius.X = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
+
+ sal_uInt32 nType = ImplGetUI16();
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+
+ double fOrientation = 0;
+ mpOutAct->DrawEllipticalArc( aCenterPoint, fRadius, fOrientation, nType, fStartAngle, fEndAngle );
+ }
+ }
+ break;
+
+ case 0x0f : /*Circular Arc Centre*/
+ {
+ double fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint( aCenter, true );
+ ImplGetVector( &vector[ 0 ] );
+
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ const double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt != 0.0 ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ const double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt != 0.0 ? basegfx::rad2deg(acos(vector[ 2 ] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( mbAngReverse )
+ ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
+
+ if ( mbFigure )
+ {
+ double fLeft = aCenter.X - aRadius.X;
+ double fTop = aCenter.Y - aRadius.X;
+ double fRight = fLeft + (2 * aRadius.X);
+ double fBottom = fTop + (2 * aRadius.X);
+ bUseless = useless(fLeft) || useless(fTop) || useless(2 * aRadius.X) || useless(fRight) || useless(fBottom);
+ if (!bUseless)
+ {
+ double fCenterCalc = fLeft + fRight;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ double fCenterCalc = fTop + fBottom;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * aRadius.X, 2 * aRadius.X));
+ tools::Polygon aPolygon( aBoundingBox,
+ Point( static_cast<tools::Long>(vector[ 0 ]), static_cast<tools::Long>(vector[ 1 ]) ),
+ Point( static_cast<tools::Long>(vector[ 2 ]), static_cast<tools::Long>(vector[ 3 ]) ), PolyStyle::Arc );
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ }
+ else
+ {
+ double fOrientation = 0;
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation, 2, fStartAngle, fEndAngle );
+ }
+ }
+
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x10 : /*Circular Arc Centre Close*/
+ {
+ double fOrientation, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint( aCenter, true );
+ ImplGetVector( &vector[ 0 ] );
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+
+ sal_uInt32 nType = ImplGetUI16();
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ const double fStartSqrt = std::hypot(vector[0], vector[1]);
+ double fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ const double fEndSqrt = std::hypot(vector[2], vector[3]);
+ double fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( mbAngReverse )
+ ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
+
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+ fOrientation = 0;
+
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fStartAngle, fEndAngle );
+ }
+
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x11 : /*Ellipse*/
+ {
+ double fOrientation;
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetEllipse( aCenter, aRadius, fOrientation ) ;
+ mpOutAct->DrawEllipse( aCenter, aRadius, fOrientation ) ;
+ }
+ break;
+
+ case 0x12 : /*Elliptical Arc*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
+ ImplGetVector( &vector[ 0 ] );
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( bDirection )
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ 2, fStartAngle, fEndAngle );
+ else
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ 2, fEndAngle, fStartAngle);
+ }
+ }
+ break;
+
+ case 0x13 : /*Elliptical Arc Close*/
+ {
+ double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
+ ImplGetVector( &vector[ 0 ] );
+
+ sal_uInt32 nType = ImplGetUI16();
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+
+ if ( bDirection )
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fStartAngle, fEndAngle );
+ else
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fEndAngle, fStartAngle);
+ }
+ }
+ break;
+ case 0x14 : /*Circular Arc Centre Reversed*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x15 : /*Connection Edge */ // NS
+ {
+// if ( mbFigure )
+// mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x16 : /*Hyperbolic Arc */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x17 : /*Parabolic Arc */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x18 : /*Non Uniform B-Spline */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x19 : /*Non Uniform Rational B-Spline */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1a : /*Polybezier*/
+ {
+ sal_uInt32 nOrder = ImplGetI( pElement->nIntegerPrecision );
+
+ sal_uInt16 nNumberOfPoints = sal::static_int_cast< sal_uInt16 >(( mnElementSize - pElement->nIntegerPrecision ) / ImplGetPointSize());
+
+ tools::Polygon aPolygon( nNumberOfPoints );
+
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
+ }
+ if ( nOrder & 4 )
+ {
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
+ {
+ if ( ( i % 3 ) == 0 )
+ aPolygon.SetFlags( i, PolyFlags::Normal );
+ else
+ aPolygon.SetFlags( i, PolyFlags::Control );
+ }
+ }
+ else
+ {
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
+ {
+ switch ( i & 3 )
+ {
+ case 0 :
+ case 3 : aPolygon.SetFlags( i, PolyFlags::Normal ); break;
+ default : aPolygon.SetFlags( i, PolyFlags::Control ); break;
+ }
+ }
+ }
+ if ( mbFigure )
+ mpOutAct->RegPolyLine( aPolygon );
+ else
+ mpOutAct->DrawPolybezier( aPolygon );
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x1b : /*Polysymbol */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1c : /*Bitonal Tile */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1d : /*Tile */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1e : /*Insert Object*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xff : /*Polybezier*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfe : /*Sharp Polybezier*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfd : /*Polyspline*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfc : /*Rounded Rectangle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfb : /*Begin Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfa : /*End Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf9 : /*Insert File*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf8 : /*Block Text*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf7 : /*Variable Width Polyline*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf6 : /*Elliptical Arc 3 Point*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf1 : /*Hyperlink Definition */break;
+ default: break;
+ }
+ }
+ else
+ mnParaSize = mnElementSize;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class5.cxx b/filter/source/graphicfilter/icgm/class5.cxx
new file mode 100644
index 000000000..7cfd9911c
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class5.cxx
@@ -0,0 +1,532 @@
+/* -*- 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 .
+ */
+
+//#define VCL_NEED_BASETSD
+
+#include <sal/log.hxx>
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+void CGM::ImplDoClass5()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Line Bundle Index*/
+ pElement->pLineBundle = static_cast<LineBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aLineList, pElement->aLineBundle ));
+ break;
+ case 0x02 : /*Line Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_LINETYPE )
+ pElement->pLineBundle->eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aLineBundle.eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x03 : /*Line Width*/
+ {
+ double nWidth;
+ if ( pElement->eLineWidthSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25; // scaling in 1/4 mm
+
+ if ( pElement->nAspectSourceFlags & ASF_LINEWIDTH )
+ pElement->pLineBundle->nLineWidth = nWidth;
+ else
+ pElement->aLineBundle.nLineWidth = nWidth;
+ }
+ break;
+ case 0x04 : /*Line Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_LINECOLOR )
+ pElement->pLineBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aLineBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x05 : /*Marker Bundle Index*/
+ pElement->pMarkerBundle = static_cast<MarkerBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aMarkerList, pElement->aMarkerBundle ));
+ break;
+ case 0x06 : /*Marker Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_MARKERTYPE )
+ pElement->pMarkerBundle->eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aMarkerBundle.eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x07 : /*Marker Size*/
+ {
+ double nWidth;
+ if ( pElement->eMarkerSizeSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25;
+ if ( pElement->nAspectSourceFlags & ASF_MARKERSIZE )
+ pElement->pMarkerBundle->nMarkerSize = nWidth;
+ else
+ pElement->aMarkerBundle.nMarkerSize = nWidth;
+ }
+ break;
+ case 0x08 : /*Marker Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_MARKERCOLOR )
+ pElement->pMarkerBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aMarkerBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x09 : /*Text Bundle Index*/
+ pElement->pTextBundle = static_cast<TextBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aTextList, pElement->aTextBundle ));
+ break;
+ case 0x0a : /*Text Font Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_TEXTFONTINDEX )
+ pElement->pTextBundle->nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aTextBundle.nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x0b : /*Text Precision*/
+ {
+ TextBundle* pBundle;
+ if ( pElement->nAspectSourceFlags & ASF_TEXTPRECISION )
+ pBundle = pElement->pTextBundle;
+ else
+ pBundle = &pElement->aTextBundle;
+ switch( ImplGetUI16() )
+ {
+ case 0 : pBundle->eTextPrecision = TPR_STRING; break;
+ case 1 : pBundle->eTextPrecision = TPR_CHARACTER; break;
+ case 2 : pBundle->eTextPrecision = TPR_STROKE; break;
+ default : pBundle->eTextPrecision = TPR_UNDEFINED; break;
+ }
+ }
+ break;
+ case 0x0c : /*Character Expansion Factor*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_CHARACTEREXPANSION )
+ pElement->pTextBundle->nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ else
+ pElement->aTextBundle.nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x0d : /*Character Spacing*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_CHARACTERSPACING )
+ pElement->pTextBundle->nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ else
+ pElement->aTextBundle.nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x0e : /*Text Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_TEXTCOLOR )
+ pElement->pTextBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aTextBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x0f : /*Character Height*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ pElement->nCharacterHeight = ImplGetI( pElement->nVDCIntegerPrecision );
+ else // ->floating points
+ pElement->nCharacterHeight = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ ImplMapDouble( pElement->nCharacterHeight );
+ pElement->nCharacterHeight /= 18.0;
+ }
+ break;
+ case 0x10 : /*Character Orientation*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ pElement->nCharacterOrientation[0] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[1] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[2] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[3] = ImplGetI( pElement->nVDCIntegerPrecision );
+ }
+ else // ->floating points
+ {
+ pElement->nCharacterOrientation[0] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[1] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[2] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[3] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ }
+ break;
+ case 0x11 : /*Text Path*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eTextPath = TPR_RIGHT; break;
+ case 1 : pElement->eTextPath = TPR_LEFT; break;
+ case 2 : pElement->eTextPath = TPR_UP; break;
+ case 3 : pElement->eTextPath = TPR_DOWN; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x12 : /*Text Alignment*/
+ {
+ auto nTextAlign = ImplGetUI16();
+ if (nTextAlign > TextAlignmentH::TAH_CONT)
+ SAL_WARN("filter.icgm", "TextAlign out of range");
+ else
+ pElement->eTextAlignmentH = static_cast<TextAlignmentH>(nTextAlign);
+ nTextAlign = ImplGetUI16();
+ if (nTextAlign > TextAlignmentV::TAV_CONT)
+ SAL_WARN("filter.icgm", "TextAlign out of range");
+ else
+ pElement->eTextAlignmentV = static_cast<TextAlignmentV>(nTextAlign);
+ pElement->nTextAlignmentHCont = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ pElement->nTextAlignmentVCont = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x13 : /*Character Set Index*/
+ pElement->nCharacterSetIndex = ImplGetI( pElement->nIndexPrecision );
+ break;
+ case 0x14 : /*Alternate Character Set Index*/
+ pElement->nAlternateCharacterSetIndex = ImplGetI( pElement->nIndexPrecision );
+ break;
+ case 0x15 : /*Fill Bundle Index*/
+ pElement->pFillBundle = static_cast<FillBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aFillList, pElement->aFillBundle ));
+ break;
+ case 0x16 : /*Fill Interior Style*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ pElement->pFillBundle->eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetUI16());
+ else
+ pElement->aFillBundle.eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetUI16());
+ }
+ break;
+ case 0x17 : /*Fill Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_FILLCOLOR )
+ pElement->pFillBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aFillBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x18 : /*Fill Hatch Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_HATCHINDEX )
+ pElement->pFillBundle->nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aFillBundle.nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x19 : /*Fill Pattern Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_PATTERNINDEX )
+ pElement->pFillBundle->nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aFillBundle.nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x1a : /*Edge Bundle Index*/
+ pElement->pEdgeBundle = static_cast<EdgeBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aEdgeList, pElement->aEdgeBundle ));
+ break;
+ case 0x1b : /*Edge Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_EDGETYPE )
+ pElement->pEdgeBundle->eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aEdgeBundle.eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x1c : /*Edge Width*/
+ {
+ double nWidth;
+ if ( pElement->eEdgeWidthSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25;
+ if ( pElement->nAspectSourceFlags & ASF_EDGEWIDTH )
+ pElement->pEdgeBundle->nEdgeWidth = nWidth;
+ else
+ pElement->aEdgeBundle.nEdgeWidth = nWidth;
+ }
+ break;
+ case 0x1d : /*Edge Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_EDGECOLOR )
+ pElement->pEdgeBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aEdgeBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x1e : /*Edge Visibility*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eEdgeVisibility = EV_OFF; break;
+ case 1 : pElement->eEdgeVisibility = EV_ON; break;
+ default : mbStatus = false;
+ }
+ }
+ break;
+ case 0x1f : /*Fill Reference Point*/
+ ImplGetPoint( pElement->aFillRefPoint );
+ break;
+ case 0x20 : /*Pattern Table" )*/ break;
+ case 0x21 : /*Pattern Size" )*/ break;
+ case 0x22 : /*Color Table*/
+ {
+ sal_uInt32 nColorStartIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ if ( ( nColorStartIndex > 255 ) ||
+ ( ( ( mnElementSize - pElement->nColorIndexPrecision ) % ( pElement->nColorPrecision * 3 ) ) != 0 ) )
+ {
+ mbStatus = false;
+ }
+ else
+ {
+ sal_uInt32 nColors = ( mnElementSize - pElement->nColorIndexPrecision ) / ( 3 * pElement->nColorPrecision );
+ if ( nColors )
+ {
+ sal_uInt32 nMaxColorIndex = nColorStartIndex + nColors - 1;
+ sal_uInt32 nIndex;
+ if ( nMaxColorIndex > 255 )
+ {
+ mbStatus = false;
+ break;
+ }
+ if ( pElement->nLatestColorMaximumIndex < nMaxColorIndex )
+ pElement->nLatestColorMaximumIndex = nMaxColorIndex;
+
+ for ( nIndex = nColorStartIndex; nIndex <= nMaxColorIndex; nIndex++ )
+ {
+ pElement->aLatestColorTable[ nIndex ] = ImplGetBitmapColor( true );
+ }
+
+ pElement->nColorMaximumIndex = pElement->nLatestColorMaximumIndex;
+ for ( nIndex = nColorStartIndex; nIndex <= nMaxColorIndex; nIndex++ )
+ {
+ if ( !pElement->aColorTableEntryIs[ nIndex ] )
+ {
+ pElement->aColorTableEntryIs[ nIndex ] = 1;
+ pElement->aColorTable[ nIndex ] = pElement->aLatestColorTable[ nIndex ];
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x23 : /*Aspect Source Flags*/
+ {
+ int nFlags = mnElementSize >> 2;
+ while ( nFlags-- > 0 )
+ {
+ sal_uInt32 nFlag = 0;
+ switch( ImplGetUI16() )
+ {
+ case 0 : nFlag = ASF_LINETYPE; break;
+ case 1 : nFlag = ASF_LINEWIDTH; break;
+ case 2 : nFlag = ASF_LINECOLOR; break;
+ case 3 : nFlag = ASF_MARKERTYPE; break;
+ case 4 : nFlag = ASF_MARKERSIZE; break;
+ case 5 : nFlag = ASF_MARKERCOLOR; break;
+ case 6 : nFlag = ASF_FILLINTERIORSTYLE; break;
+ case 7 : nFlag = ASF_HATCHINDEX; break;
+ case 8 : nFlag = ASF_PATTERNINDEX; break;
+ case 9 : nFlag = ASF_BITMAPINDEX; break;
+ case 10 : nFlag = ASF_FILLCOLOR; break;
+ case 11 : nFlag = ASF_EDGETYPE; break;
+ case 12 : nFlag = ASF_EDGEWIDTH; break;
+ case 13 : nFlag = ASF_EDGECOLOR; break;
+ case 14 : nFlag = ASF_TEXTFONTINDEX; break;
+ case 15 : nFlag = ASF_TEXTPRECISION; break;
+ case 16 : nFlag = ASF_CHARACTEREXPANSION; break;
+ case 17 : nFlag = ASF_CHARACTERSPACING; break;
+ case 18 : nFlag = ASF_TEXTCOLOR; break;
+ default : mbStatus = false; break;
+ }
+ sal_uInt32 nASF = ImplGetUI16();
+ switch ( nASF )
+ {
+ case 0 : pElement->nAspectSourceFlags &= ~nFlag; break; // INDIVIDUAL
+ case 1 : pElement->nAspectSourceFlags |= nFlag; break; // BUNDLED
+ default : mbStatus = false; break;
+ }
+ }
+ }
+ break;
+ case 0x24 : /*Pick Identifier*/ break;
+ case 0x25 : /*Line Cap*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eLineCapType = LCT_BUTT; break;
+ case 1 : pElement->eLineCapType = LCT_ROUND; break;
+ case 2 : pElement->eLineCapType = LCT_SQUARE; break;
+ case 3 : pElement->eLineCapType = LCT_TRIANGLE; break;
+ case 4 : pElement->eLineCapType = LCT_ARROW; break;
+ default : pElement->eLineCapType = LCT_NONE; break;
+ }
+ }
+ break;
+ case 0x26 : /*Line Join*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eLineJoinType = LJT_MITER; break;
+ case 1 : pElement->eLineJoinType = LJT_ROUND; break;
+ case 2 : pElement->eLineJoinType = LJT_BEVEL; break;
+ default : pElement->eLineJoinType = LJT_NONE; break;
+ }
+ }
+ break;
+ case 0x27 : /*Line Type Continuation*/ break; // NS
+ case 0x28 : /*Line Type Initial Offset*/ break; // NS
+ case 0x29 : /*Text Score Type*/ break;
+ case 0x2a : /*Restricted Text Type*/ break;
+ case 0x2b : /*Interpolated interior*/ break;
+ case 0x2c : /*Edge Cap*/ break; // NS
+ case 0x2d : /*Edge Join*/ break;
+ case 0x2e : /*Edge Type Continuation*/ break; // NS
+ case 0x2f : /*Edge Type Initial Offset*/ break; // NS
+ case 0x30 : /*Symbol Library Index*/ break; // NS
+ case 0x31 : /*Symbol Color*/ break; // NS
+ case 0x32 : /*Symbol Size*/ break; // NS
+ case 0x33 : /*Symbol Orientation*/ break; // NS
+ case 0x50 : /*Block Text vcl::Region Margins*/ break;
+ case 0x51 : /*Block Text vcl::Region Expansion*/ break;
+ case 0x52 : /*Block Text vcl::Region Anchor*/ break;
+ case 0x53 : /*Block Text Paragraph Horizontal Alignment*/ break;
+ case 0x54 : /*Block Text Paragraph Vertical Alignment*/ break;
+ case 0x55 : /*Block Text Line Flow*/ break;
+ case 0x60 : /*Block Text Paragraph Spacing*/ break;
+ case 0x61 : /*Block Text Paragraph Indent*/ break;
+ case 0x62 : /*Block Text Paragraph Tabs*/ break;
+ case 0x63 : /*Block Text Paragraph Bullets*/ break;
+ case 0x64 : /*Block Text Paragraph Bullet Level*/ break;
+ case 0x65 : /*Block Text Paragraph Line Horizontal Alignment*/ break;
+ case 0x66 : /*Block Text Paragraph Line Vertical Alignment*/ break;
+ case 0x67 : /*Block Text Paragragh Line Spacing*/ break;
+ case 0x68 : /*Block Text Paragraph Word Wrap*/ break;
+ case 0x70 : /*Block Text Forward Advance Distance*/ break;
+ case 0x71 : /*Word Spacing*/ break;
+ case 0x72 : /*External Leading*/ break;
+ case 0x7a : /*set Gradient Offset*/
+ {
+ tools::Long nHorzOffset = ImplGetI( pElement->nIndexPrecision );
+ tools::Long nVertOffset = ImplGetI( pElement->nIndexPrecision );
+ (void)ImplGetUI16(); // nType
+ mpOutAct->SetGradientOffset( nHorzOffset, nVertOffset );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7b : /*set Gradient Edge*/
+ {
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7c : /*set Gradient Angle*/
+ {
+ mpOutAct->SetGradientAngle( ImplGetI( pElement->nIndexPrecision ) );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7d : /*set Gradient Description*/
+ {
+ ImplGetI( pElement->nIndexPrecision ); // -Wall is this needed?
+ sal_uInt32 nNumberOfStages = ImplGetI( pElement->nIndexPrecision );
+ sal_uInt32 i, nColorFrom = 0;
+ sal_uInt32 nColorTo = 0xffffff;
+
+ const size_t nRemainingSize = mpEndValidSource - (mpSource + mnParaSize);
+ const size_t nMaxPossibleRecords = nRemainingSize/pElement->nRealSize;
+
+ if (nNumberOfStages > nMaxPossibleRecords)
+ {
+ mbStatus = false;
+ break;
+ }
+
+ for ( i = 0; i < nNumberOfStages; i++ )
+ {
+ ImplGetFloat(pElement->eRealPrecision, pElement->nRealSize);
+ }
+
+ for ( i = 0; i <= nNumberOfStages; i++ )
+ {
+ sal_uInt32 nPara = mnParaSize + 24;
+ if ( i == 0 )
+ {
+ nColorTo = ImplGetBitmapColor();
+ nColorFrom = nColorTo ^ 0xffffff;
+ }
+ else if ( i == 1 )
+ nColorFrom = ImplGetBitmapColor();
+ mnParaSize = nPara;
+ }
+ if ( nNumberOfStages > 1 )
+ mpOutAct->SetGradientStyle( 0xff );
+
+ mpOutAct->SetGradientDescriptor( nColorFrom, nColorTo );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7e : /*set Gradient Style*/
+ {
+ sal_uInt32 nStyle = ImplGetUI16();
+ (void)ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize ); // fRatio
+ mpOutAct->SetGradientStyle( nStyle );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0xff : /*inquire Font metrics*/ break;
+ case 0xfe : /*inquire character widths*/ break;
+ case 0xfd : /*set Text Font*/ break;
+ case 0xfc : /*set current position*/ break;
+ case 0xfb : /*set current position mode*/ break;
+ case 0xfa : /*set character height mode*/ break;
+ case 0xf9 : /*set Transform matrix 2D*/ break;
+ case 0xf8 : /*set Transform matrix 3D*/ break;
+ case 0xf7 : /*pop transformation state*/ break;
+ case 0xf6 : /*clear transformation state*/ break;
+ case 0xf5 : /*set character widths*/ break;
+ case 0xf4 : /*set color name - for Pantone support*/ break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class7.cxx b/filter/source/graphicfilter/icgm/class7.cxx
new file mode 100644
index 000000000..63bce3296
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class7.cxx
@@ -0,0 +1,210 @@
+/* -*- 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 <sal/config.h>
+
+#include <o3tl/safeint.hxx>
+
+#include "cgm.hxx"
+#include "chart.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass7()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Message */break;
+ case 0x02 :
+ {
+ if (mpEndValidSource - mpSource < 12)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ sal_uInt16* pTemp = reinterpret_cast<sal_uInt16*>(mpSource);
+ sal_uInt16 nOpcode = pTemp[ 4 ];
+
+ sal_uInt8* pAppData = mpSource + 12;
+
+ if ( mpChart || ( nOpcode == 0 ) )
+ {
+ switch ( nOpcode )
+ {
+ case 0x000 : /*AppData - Beginning of File Opcodes*/
+ {
+ if (mpEndValidSource - pAppData < 4)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( mpChart == nullptr )
+ mpChart.reset( new CGMChart );
+ mpChart->mnCurrentFileType = pAppData[ 3 ];
+ }
+ break;
+ case 0x001 : /*AppData - End of File Opcodes */break;
+ case 0x190 : /*AppData - FDESC */break;
+ case 0x192 : /*AppData - FNOTES */break;
+ case 0x1F4 : /*AppData - BOGENFILE */break;
+ case 0x1F5 : /*AppData - EOGENFILE */break;
+ case 0x1F8 : /*AppData - BOCHTGROUP */break;
+ case 0x1F9 : /*AppData - EOCHTGROUP */break;
+ case 0x1FC : /*AppData - BOCHTDATA */break;
+ case 0x1FD : /*AppData - EOCHTDATA*/
+ {
+ // mpOutAct->DrawChart();
+ }
+ break;
+ case 0x200 : /*AppData - BOSYMGROUP */break;
+ case 0x201 : /*AppData - EOSYMGROUP */break;
+ case 0x204 : /*AppData - BEGSYMBOL */break;
+ case 0x205 : /*AppData - ENDSYMBOL */break;
+ case 0x208 : /*AppData - BOSHWGROUP */break;
+ case 0x209 : /*AppData - EOSHWGROUP */break;
+ case 0x260 : /*AppData - BEGGROUP */break;
+ case 0x262 : /*AppData - ENDGROUP */break;
+ case 0x264 : /*AppData - DATANODE*/
+ {
+ if (o3tl::make_unsigned(mpEndValidSource - pAppData) < sizeof(DataNode))
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ mpChart->mDataNode[ 0 ] = *reinterpret_cast<DataNode*>( pAppData );
+ sal_Int8 nZoneEnum = mpChart->mDataNode[ 0 ].nZoneEnum;
+ if (nZoneEnum > 0 && nZoneEnum <= 6)
+ mpChart->mDataNode[ nZoneEnum ] = *reinterpret_cast<DataNode*>( pAppData );
+ }
+ break;
+ case 0x2BE : /*AppData - SHWSLIDEREC*/
+ {
+ if (mpEndValidSource - pAppData < 17)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( pAppData[ 16 ] == 0 ) // a blank template ?
+ {
+ if ( pAppData[ 2 ] == 46 )
+ {
+ // this starts the document -> maybe we could insert a new document
+ }
+ else if ( pAppData[ 2 ] & 0x80 )
+ {
+ // this is a template
+ }
+ else
+ {
+ mpOutAct->InsertPage();
+ }
+ }
+ mpChart->ResetAnnotation();
+ }
+ break;
+ case 0x2C0 : /*AppData - SHWKEYTABLE */break;
+ case 0x2C2 : /*AppData - SHWBUTTONTAB */break;
+ case 0x2C4 : /*AppData - SHWGLOBAL */break;
+ case 0x2C6 : /*AppData - SHWTITLE */break;
+ case 0x2CA : /*AppData - SHWAPP */break;
+ case 0x320 : /*AppData - TEXT*/
+ {
+ if (mpEndValidSource - pAppData < 9)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ std::unique_ptr<TextEntry> pTextEntry(new TextEntry);
+ pTextEntry->nTypeOfText = *reinterpret_cast<sal_uInt16*>( pAppData );
+ pTextEntry->nRowOrLineNum = *reinterpret_cast<sal_uInt16*>( pAppData + 2 );
+ pTextEntry->nColumnNum = *reinterpret_cast<sal_uInt16*>( pAppData + 4 );
+ sal_uInt16 nAttributes = *reinterpret_cast<sal_uInt16*>( pAppData + 6 );
+ pTextEntry->nZoneSize = nAttributes & 0xff;
+ pTextEntry->nLineType = ( nAttributes >> 8 ) & 0xf;
+ nAttributes >>= 12;
+ pTextEntry->nAttributes = nAttributes;
+ pAppData += 8;
+ auto nMaxLen = mpEndValidSource - pAppData;
+ sal_uInt32 nLen = strnlen(reinterpret_cast<char*>(pAppData), nMaxLen);
+ pTextEntry->pText = new char[nLen + 1];
+ memcpy( pTextEntry->pText, pAppData, nLen );
+ pTextEntry->pText[nLen] = 0;
+ pAppData += nLen;
+
+ mpChart->InsertTextEntry( std::move(pTextEntry) );
+ }
+ break;
+ case 0x321 : /*AppData - IOC_TABS */break;
+ case 0x322 : /*AppData - CHARTZONE*/
+ break;
+ case 0x324 : /*AppData - TITLEZONE */break;
+ case 0x328 : /*AppData - FOOTNOTEZONE */break;
+ case 0x32A : /*AppData - LEGENDZONE */break;
+ case 0x330 : /*AppData - PAGEORIENTDIM*/
+ break;
+ case 0x334 : /*AppData - CHTZONEOPTN*/
+ break;
+ case 0x336 : /*AppData - CHTINTL*/
+ break;
+ case 0x338 : /*AppData - CHTLINESPC */break;
+ case 0x384 : /*AppData - ORGGRIDSTATE */break;
+ case 0x386 : /*AppData - ORGSCRSTATE */break;
+ case 0x388 : /*AppData - ORGTREESTATE */break;
+ case 0x38A : /*AppData - ORGTEXTOPTN */break;
+ case 0x38E : /*AppData - ORGBOXOPTN */break;
+ case 0x390 : /*AppData - ORGBOXDIM */break;
+ case 0x392 : /*AppData - ORGBOX */break;
+ case 0x3EA : /*AppData - TTLTEXTOPTN */break;
+ case 0x3EE : /*AppData - TTLAUTOBUILD */break;
+ case 0x44E : /*AppData - BULTEXTOPTN */break;
+ case 0x452 : /*AppData - BULLETOPTN*/
+ break;
+ case 0x454 : /*AppData - BULLETLINES*/break;
+ case 0x456 : /*AppData - BULAUTOBUILD */break;
+ case 0x4B2 : /*AppData - TBLTEXTOPTN */break;
+ case 0x4B6 : /*AppData - TBLOPTN */break;
+ case 0x4B8 : /*AppData - TBLCOLOPTN */break;
+ case 0x4BA : /*AppData - TBLLEGENDOPTN */break;
+ case 0x4BC : /*AppData - TBLRANGEOPTN */break;
+ case 0x4BE : /*AppData - TBLROWOPTN */break;
+ case 0x4C0 : /*AppData - TBLAUTOBUILD */break;
+ case 0x518 : /*AppData - PIECHARTOPTN */break;
+ case 0x51A : /*AppData - PIELEGENDOPTN */break;
+ case 0x51C : /*AppData - PIETEXTOPTN */break;
+ case 0x51E : /*AppData - PIEOPTN */break;
+ case 0x520 : /*AppData - PIEPCTLABOPTN */break;
+ case 0x522 : /*AppData - PIEVALLABOPTN */break;
+ case 0x524 : /*AppData - PIESLICE */break;
+ case 0x57A : /*AppData - XYAXISOPTN */break;
+ case 0x57C : /*AppData - XYGRIDOPTN */break;
+ case 0x57D : /*AppData - XYGRIDSHOWFILL */break;
+ case 0x57E : /*AppData - XYSERIESOPTN */break;
+ case 0x580 : /*AppData - XYSTYLEOPTN */break;
+ case 0x582 : /*AppData - XYTABLEOPTN */break;
+ case 0x584 : /*AppData - XYTEXTOPTN */break;
+ case 0x586 : /*AppData - XYDATAOPTN */break;
+ case 0x58A : /*AppData - XYLEGENDOPN */break;
+ case 0x58C : /*AppData - XYCALCULATION */break;
+ case 0x58E : /*AppData - XYXVALUE */break;
+ case 0x590 : /*AppData - XYYVALUE */break;
+ case 0x592 : /*AppData - XYXEXTVALUE */break;
+ case 0x618 : /*AppData - IOC_CHTCOLRTAB */break;
+ case 0x619 : /*AppData - IOC_CHTFONTTAB */break;
+ case 0x1fff : /*AppData - 0x1fff */break;
+ default : /*UNKNOWN Application Data */break;
+ }
+ }
+ mnParaSize = mnElementSize;
+ break;
+ }
+ default: break;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/classx.cxx b/filter/source/graphicfilter/icgm/classx.cxx
new file mode 100644
index 000000000..2b624f63b
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/classx.cxx
@@ -0,0 +1,249 @@
+/* -*- 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 "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplSetUnderlineMode()
+{
+ sal_uInt32 nMode = ImplGetUI16();
+ switch ( nMode )
+ {
+ case 1 : pElement->eUnderlineMode = UM_LOW; break;
+ case 2 : pElement->eUnderlineMode = UM_HIGH; break;
+ case 4 : pElement->eUnderlineMode = UM_STRIKEOUT; break;
+ case 8 : pElement->eUnderlineMode = UM_OVERSCORE; break;
+ default: pElement->eUnderlineMode = UM_OFF; break;
+ }
+ pElement->nUnderlineColor = ImplGetBitmapColor();
+}
+
+void CGM::ImplDoClass6()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Escape*/
+ {
+ tools::Long nIdentifier = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nIdentifier )
+ {
+ case 0 : /*inquire function support */break;
+ case -1 : /*set underline mode*/
+ {
+ ImplSetUnderlineMode();
+ }
+ break;
+ case -2 : /*set script mode */break;
+ case -3 : /*set shadow mode */break;
+ case -6 : /*inquire origin offset */break;
+ case -8 : /*set media size */break;
+ case -10 : /*set character mode */break;
+ case -14 : /*resolution mode */break;
+ case -17 : /*line cap */break;
+ case -18 : /*line join */break;
+ case -19 : /*edge join */break;
+ case -30 : /*media type */break;
+ case -31 : /*number of copies */break;
+ case -32 : /*orientation */break;
+ case -33 : /*device color representation */break;
+ case -34 : /*device font list */break;
+ case -35 : /*color reversal mode */break;
+ case -36 : /*line cap attributes */break;
+ case -37 : /*begin effect */break;
+ case -38 : /*end effect */break;
+ case -39 : /*begin effect definition */break;
+ case -40 : /*end effect definition */break;
+ case -41 : /*end style definition */break;
+ case -42 : /*begin eps data */break;
+ case -43 : /*eps data */break;
+ case -44 : /*end eps data */break;
+ case -45 : /*set background style */break;
+ case -46 : /*set eps mode */break;
+ case -47 : /*fill mode */break;
+ case -48 : /*begin symbol */break;
+ case -49 : /*end symbol */break;
+ case -50 : /*begin layer */break;
+ case -51 : /*end layer */break;
+ case -52 : /*layer visibility */break;
+ case -53 : /*inquire foreign data */break;
+ case -54 : /*set text offset */break;
+ case -55 : /*begin group */break;
+ case -56 : /*end group */break;
+ case -100 : /*begin patch */break;
+ case -101 : /*end patch */break;
+ case -102 : /*begin block text region */break;
+ case -103 : /*end block text region */break;
+ case -120 : /*region margins */break;
+ case -121 : /*region expansions */break;
+ case -122 : /*region anchor */break;
+ case -123 : /*paragraph horizontal align */break;
+ case -124 : /*paragraph vertical align */break;
+ case -125 : /*region line flow */break;
+ case -130 : /*paragraph spacing */break;
+ case -131 : /*paragraph indentation */break;
+ case -132 : /*paragraph tabs */break;
+ case -133 : /*paragraph bullet */break;
+ case -134 : /*paragraph bullet level */break;
+ case -135 : /*line horizontal align */break;
+ case -136 : /*line vertical align */break;
+ case -137 : /*line spacing */break;
+ case -138 : /*word wrap */break;
+ case -150 : /*forward advance distance */break;
+ case -151 : /*word spacing */break;
+ case -152 : /*external leading */break;
+ case -160 : /*set gradient offset */break;
+ case -161 : /*set gradient edge */break;
+ case -162 : /*set gradient angle */break;
+ case -163 : /*set gradient description */break;
+ case -164 : /*set gradient style */break;
+ case -165 : /*set background style */break;
+ case -170 : /*geometric pattern draw style */break;
+ case -190 : /*set character width */break;
+ case -191 : /*hyperlink definitions */break;
+ case -192 : /*set color name for pantone */break;
+ case -32746 : /*set text font */break;
+ case -32747 : /*font selection mode */break;
+ case -32752 : /*connecting edge */break;
+ case -32753 : /*set drawing mode */break;
+ case -32754 : /*inquire clip rectangle */break;
+ case -32755 : /*protection region indicator */break;
+ case -32756 : /*end protection region */break;
+ case -32757 : /*begin protection region */break;
+ case -32758 : /*geometric pattern definition */break;
+ case -32759 : /*hatch style definition */break;
+ case -32760 : /*close figure */break;
+ case -32761 : /*end figure*/
+ {
+ mpOutAct->EndFigure();
+ mbFigure = false;
+ }
+ break;
+ case -32762 : /*begin figure*/
+ {
+ mbFigure = true;
+ mpOutAct->BeginFigure();
+ }
+ break;
+ case -32763 : /*pop transformation */break;
+ case -32764 : /*push transformation */break;
+ case -32765 : /*copy segment */break;
+ case -32766 : /*endseg */break;
+ case -32767 : /*begin segment */break;
+ default : break;
+ }
+ mnParaSize = mnElementSize;
+ }
+ break;
+ case 0x02 : /*Get Escape */break;
+ case 0x11 : /*Set Underline Mode*/
+ {
+ ImplSetUnderlineMode();
+ }
+ break;
+ case 0x12 : /*Set Script Mode */break;
+ case 0x13 : /*Set Shadow Mode */break;
+ case 0x18 : /*Set Media Size */break;
+ case 0x20 : /*Set Character Mode */break;
+ case 0x24 : /*Resolution Mode */break;
+ case 0x27 : /*Line Cap */break;
+ case 0x28 : /*Line Join */break;
+ case 0x29 : /*Edge Join */break;
+ case 0x40 : /*Media Type */break;
+ case 0x41 : /*Number of Copies */break;
+ case 0x42 : /*Origin */break;
+ case 0x45 : /*Color Reversal Mode */break;
+ case 0x46 : /*Line Cap Attributes */break;
+ case 0x49 : /*Begin Effect Definition */break;
+ case 0x50 : /*End Effect Definition */break;
+ case 0x51 : /*Line End Style Attributes */break;
+ case 0x52 : /*Begin Data */break;
+ case 0x53 : /*Data */break;
+ case 0x54 : /*End Data */break;
+ case 0x55 : /*Set Background Style */break;
+ case 0x56 : /*Set EPS Mode */break;
+ case 0x57 : /*Fill Mode */break;
+ case 0x58 : /*Begin Symbol */break;
+ case 0x59 : /*End Symbol */break;
+ case 0x60 : /*Begin Layer */break;
+ case 0x61 : /*End Layer */break;
+ case 0x62 : /*Layer Visibility */break;
+ case 0x64 : /*Set Text Offset */break;
+ case 0xFF : /*Inquire Function Support */break;
+ case 0xFE : /*Inquire Origin */break;
+ case 0xFD : /*Inquire Foreign Data Mode */break;
+ case 0xFC : /*Inquire Text Extent */break;
+ case 0xFB : /*Inquire DPI */break;
+ default: break;
+ }
+};
+
+
+void CGM::ImplDoClass8()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Copy Segment */break; // NS
+ case 0x02 : /*Inheritance Filter */break; // NS
+ case 0x03 : /*Clip Inheritance */break; // NS
+ case 0x04 : /*Segment Transformation */break;
+ case 0x05 : /*Segment Highlighting */break; // NS
+ case 0x06 : /*Segment Display Priority */break; // NS
+ case 0x07 : /*Segment Pick Priority */break; // NS
+ case 0xfe : /*INQ Current Position */break;
+ case 0xff : /*INQ Inserted Object Extent */break;
+ default: break; // NS
+ }
+};
+
+
+void CGM::ImplDoClass9()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Pixel Array */break; // NS
+ case 0x02 : /*Create Bitmap */break; // NS
+ case 0x03 : /*Delete Bitmap */break; // NS
+ case 0x04 : /*Select Drawing Bitmap */break; // NS
+ case 0x05 : /*Display Bitmap */break; // NS
+ case 0x06 : /*Drawing Mode */break;
+ case 0x07 : /*Mapped Bitmap ForeGround Color */break; // NS
+ case 0x08 : /*Fill Bitmap */break; // NS
+ case 0x09 : /*Two Operand BitBlt */break; // NS
+ case 0x0a : /*Three Operand BitBlt */break; // NS
+ default: break;
+ }
+};
+
+
+void CGM::ImplDoClass15()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Inquire Error Stack */break;
+ case 0x02 : /*Pop Error Stack */break;
+ case 0x03 : /*Empty Error Stack */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/elements.cxx b/filter/source/graphicfilter/icgm/elements.cxx
new file mode 100644
index 000000000..9a0221066
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/elements.cxx
@@ -0,0 +1,336 @@
+/* -*- 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 "elements.hxx"
+
+#include <algorithm>
+
+CGMElements::CGMElements()
+{
+ Init();
+};
+
+
+CGMElements::~CGMElements()
+{
+}
+
+
+CGMElements& CGMElements::operator=( const CGMElements& rSource )
+{
+ if (this == &rSource)
+ return *this;
+
+ sal_uInt32 nIndex;
+
+ nVDCIntegerPrecision = rSource.nVDCIntegerPrecision;
+ nIntegerPrecision = rSource.nIntegerPrecision;
+ eRealPrecision = rSource.eRealPrecision;
+ nRealSize = rSource.nRealSize;
+ nIndexPrecision = rSource.nIndexPrecision;
+ nColorPrecision = rSource.nColorPrecision;
+ nColorIndexPrecision = rSource.nColorIndexPrecision;
+
+ nMetaFileVersion = rSource.nMetaFileVersion;
+ eScalingMode = rSource.eScalingMode;
+ nScalingFactor = rSource.nScalingFactor;
+ eVDCType = rSource.eVDCType;
+ eVDCRealPrecision = rSource.eVDCRealPrecision;
+ nVDCRealSize = rSource.nVDCRealSize;
+ aVDCExtent = rSource.aVDCExtent;
+ aVDCExtentMaximum = rSource.aVDCExtentMaximum;
+ eDeviceViewPortMode = rSource.eDeviceViewPortMode;
+ nDeviceViewPortScale = rSource.nDeviceViewPortScale;
+ eDeviceViewPortMap = rSource.eDeviceViewPortMap;
+ eDeviceViewPortMapH = rSource.eDeviceViewPortMapH;
+ eDeviceViewPortMapV = rSource.eDeviceViewPortMapV;
+ aDeviceViewPort = rSource.aDeviceViewPort;
+ nMitreLimit = rSource.nMitreLimit;
+ eClipIndicator = rSource.eClipIndicator;
+ aClipRect = rSource.aClipRect;
+ eColorSelectionMode = rSource.eColorSelectionMode;
+ nColorMaximumIndex = rSource.nColorMaximumIndex;
+ nLatestColorMaximumIndex = rSource.nLatestColorMaximumIndex;
+
+ for ( nIndex = 1; nIndex < 256; nIndex++ ) // do not overwrite the background color
+ {
+ aColorTableEntryIs[ nIndex ] = rSource.aColorTableEntryIs[ nIndex ];
+ aColorTable[ nIndex ] = rSource.aColorTable[ nIndex ];
+ aLatestColorTable[ nIndex ] = rSource.aColorTable[ nIndex ];
+ }
+
+ for ( nIndex = 0; nIndex < 8; nIndex++ )
+ {
+ nColorValueExtent[ nIndex ] = rSource.nColorValueExtent[ nIndex ];
+ }
+ nAspectSourceFlags = rSource.nAspectSourceFlags;
+
+ CopyAllBundles( rSource.aLineList, aLineList );
+ aLineBundle = rSource.aLineBundle;
+ pLineBundle = static_cast<LineBundle*>(GetBundle( aLineList, rSource.pLineBundle->GetIndex() ));
+ eLineWidthSpecMode = rSource.eLineWidthSpecMode;
+ eLineCapType = rSource.eLineCapType;
+ eLineJoinType = rSource.eLineJoinType;
+
+ CopyAllBundles( rSource.aMarkerList, aMarkerList );
+ aMarkerBundle = rSource.aMarkerBundle;
+ pMarkerBundle = static_cast<MarkerBundle*>(GetBundle( aMarkerList, rSource.pMarkerBundle->GetIndex() ));
+ eMarkerSizeSpecMode = rSource.eMarkerSizeSpecMode;
+
+ CopyAllBundles( rSource.aEdgeList, aEdgeList );
+ aEdgeBundle = rSource.aEdgeBundle;
+ pEdgeBundle = static_cast<EdgeBundle*>(GetBundle( aEdgeList, rSource.pEdgeBundle->GetIndex() ));
+ eEdgeVisibility = rSource.eEdgeVisibility;
+ eEdgeWidthSpecMode = rSource.eEdgeWidthSpecMode;
+
+ CopyAllBundles( rSource.aTextList, aTextList );
+ aTextBundle = rSource.aTextBundle;
+ pTextBundle = static_cast<TextBundle*>(GetBundle( aTextList, rSource.pTextBundle->GetIndex() ));
+ nCharacterHeight = rSource.nCharacterHeight;
+ nCharacterOrientation[ 0 ] = rSource.nCharacterOrientation[ 0 ];
+ nCharacterOrientation[ 1 ] = rSource.nCharacterOrientation[ 1 ];
+ nCharacterOrientation[ 2 ] = rSource.nCharacterOrientation[ 2 ];
+ nCharacterOrientation[ 3 ] = rSource.nCharacterOrientation[ 3 ];
+ eUnderlineMode = rSource.eUnderlineMode;
+ nUnderlineColor = rSource.nUnderlineColor;
+ eTextPath = rSource.eTextPath;
+ eTextAlignmentH = rSource.eTextAlignmentH;
+ eTextAlignmentV = rSource.eTextAlignmentV;
+ nTextAlignmentHCont = rSource.nTextAlignmentHCont;
+ nTextAlignmentVCont = rSource.nTextAlignmentVCont;
+ nCharacterSetIndex = rSource.nCharacterSetIndex;
+ nAlternateCharacterSetIndex = rSource.nAlternateCharacterSetIndex;
+ aFontList = rSource.aFontList;
+ eCharacterCodingA = rSource.eCharacterCodingA;
+
+ CopyAllBundles( rSource.aFillList, aFillList );
+ aFillBundle = rSource.aFillBundle;
+ pFillBundle = static_cast<FillBundle*>(GetBundle( aFillList, rSource.pFillBundle->GetIndex() ));
+ aFillRefPoint = rSource.aFillRefPoint;
+ eTransparency = rSource.eTransparency;
+ nAuxiliaryColor = rSource.nAuxiliaryColor;
+
+ maHatchMap = rSource.maHatchMap;
+ bSegmentCount = rSource.bSegmentCount;
+ return *this;
+}
+
+
+void CGMElements::Init()
+{
+
+ nIntegerPrecision = nIndexPrecision = 2;
+ nRealSize = nVDCRealSize = 4;
+ nColorIndexPrecision = 1;
+ nColorPrecision = 1;
+ nVDCIntegerPrecision = 2;
+ eRealPrecision = eVDCRealPrecision = RP_FIXED; //RP_FLOAT;
+
+ nMetaFileVersion = 1;
+ eScalingMode = SM_ABSTRACT;
+ eVDCType = VDC_INTEGER;
+ aVDCExtent.Left = aVDCExtent.Bottom = 0;
+// aVDCExtent.Right = aVDCExtent.Top = 32767;
+ aVDCExtent.Right = aVDCExtent.Top = 1.0;
+ aVDCExtentMaximum.Left = aVDCExtentMaximum.Bottom = 0;
+// aVDCExtentMaximum.Right = aVDCExtentMaximum.Top = 32767;
+ aVDCExtentMaximum.Right = aVDCExtentMaximum.Top = 1.0;
+
+ eDeviceViewPortMode = DVPM_FRACTION;
+ nDeviceViewPortScale = 1;
+ eDeviceViewPortMap = DVPM_FORCED;
+ eDeviceViewPortMapH = DVPMH_LEFT;
+ eDeviceViewPortMapV = DVPMV_BOTTOM;
+ aDeviceViewPort.Left = 0;
+ aDeviceViewPort.Top = 1;
+ aDeviceViewPort.Right = 0;
+ aDeviceViewPort.Bottom = 1;
+
+ nMitreLimit = 32767;
+ eClipIndicator = CI_ON;
+ aClipRect = aVDCExtent;
+
+ eColorSelectionMode = CSM_INDEXED;
+ nColorMaximumIndex = 63;
+ int i;
+ for ( i = 0; i < 256; aColorTableEntryIs[ i++ ] = 0 ) ;
+ aColorTable[ 0 ] = 0;
+ for ( i = 1; i < 256; aColorTable[ i++ ] = 0xffffff ) ;
+ nLatestColorMaximumIndex = 63;
+ aLatestColorTable[ 0 ] = 0;
+ for ( i = 1; i < 256; aLatestColorTable[ i++ ] = 0xffffff ) ;
+ nColorValueExtent[ 0 ] = nColorValueExtent[ 1 ] = nColorValueExtent[ 2 ] = 0;
+ nColorValueExtent[ 3 ] = nColorValueExtent[ 4 ] = nColorValueExtent[ 5 ] = 255;
+
+ nAspectSourceFlags = 0; // all flags are individual
+
+ eLineWidthSpecMode = SM_SCALED; // line parameter
+ eLineCapType = LCT_NONE;
+ eLineJoinType = LJT_NONE;
+ pLineBundle = &aLineBundle; // line bundle parameter
+ aLineBundle.SetIndex( 1 );
+ aLineBundle.eLineType = LT_SOLID;
+ aLineBundle.nLineWidth = 1;
+ aLineBundle.SetColor( 0xffffff );
+ InsertBundle( aLineList, aLineBundle );
+
+ eMarkerSizeSpecMode = SM_SCALED; // marker parameter
+ pMarkerBundle = &aMarkerBundle; // marker bundle parameter
+ aMarkerBundle.SetIndex( 1 );
+ aMarkerBundle.eMarkerType = MT_STAR;
+ aMarkerBundle.nMarkerSize = 1;
+ aMarkerBundle.SetColor( 0xffffff );
+ InsertBundle( aMarkerList, aMarkerBundle );
+
+ eEdgeVisibility = EV_OFF; // edge parameter
+ eEdgeWidthSpecMode = SM_SCALED;
+ pEdgeBundle = &aEdgeBundle; // edge bundle parameter
+ aEdgeBundle.SetIndex( 1 );
+ aEdgeBundle.eEdgeType = ET_SOLID;
+ aEdgeBundle.nEdgeWidth = 1;
+ aEdgeBundle.SetColor( 0xffffff );
+ InsertBundle( aEdgeList, aEdgeBundle );
+
+ nCharacterHeight = 327; // text parameter
+ nCharacterOrientation[0] = 0;
+ nCharacterOrientation[1] = 1;
+ nCharacterOrientation[2] = 1;
+ nCharacterOrientation[3] = 0;
+ eUnderlineMode = UM_OFF;
+ nUnderlineColor = 0xffffff;
+ eTextPath = TPR_RIGHT;
+ eTextAlignmentH = TAH_NORMAL;
+ eTextAlignmentV = TAV_NORMAL;
+ nCharacterSetIndex = nAlternateCharacterSetIndex = 1;
+ eCharacterCodingA = CCA_BASIC_7;
+ pTextBundle = &aTextBundle; // text bundle parameter
+ aTextBundle.SetIndex( 1 );
+ aTextBundle.nTextFontIndex = 1;
+ aTextBundle.eTextPrecision = TPR_STRING;
+ aTextBundle.nCharacterExpansion = 1;
+ aTextBundle.nCharacterSpacing = 0;
+ aTextBundle.SetColor( 0xffffff );
+ InsertBundle( aTextList, aTextBundle );
+
+ pFillBundle = &aFillBundle; // fill bundle parameter
+ aFillBundle.SetIndex( 1 );
+ aFillBundle.eFillInteriorStyle = FIS_HOLLOW;
+ aFillBundle.nFillHatchIndex = 1;
+ aFillBundle.nFillPatternIndex = 1;
+ aFillBundle.SetColor( 0xffffff );
+ InsertBundle( aFillList, aFillBundle );
+
+ ImplInsertHatch( 0, 0, 0, 0 );
+ ImplInsertHatch( 1, 0, 125, 0 );
+ ImplInsertHatch( 2, 0, 125, 900 );
+ ImplInsertHatch( 3, 0, 125, 450 );
+ ImplInsertHatch( 4, 0, 125, 1350 );
+ ImplInsertHatch( 5, 1, 125, 0 );
+ ImplInsertHatch( 6, 1, 125, 450 );
+ ImplInsertHatch( -1, 0, 75, 0 );
+ ImplInsertHatch( -2, 0, 75, 900 );
+ ImplInsertHatch( -3, 0, 75, 450 );
+ ImplInsertHatch( -4, 0, 75, 1350 );
+ ImplInsertHatch( -5, 1, 75, 0 );
+ ImplInsertHatch( -6, 1, 75, 450 );
+ ImplInsertHatch( -7, 2, 125, 0 );
+ ImplInsertHatch( -8, 2, 125, 900 );
+ ImplInsertHatch( -9, 2, 125, 450 );
+ ImplInsertHatch( -10, 2, 125, 1350 );
+ ImplInsertHatch( -11, 0, 40, 0 );
+ ImplInsertHatch( -12, 0, 40, 900 );
+ ImplInsertHatch( -13, 0, 40, 450 );
+ ImplInsertHatch( -14, 0, 40, 1350 );
+ ImplInsertHatch( -15, 1, 40, 0 );
+ ImplInsertHatch( -16, 1, 40, 900 );
+ ImplInsertHatch( -21, 0, 250, 0 );
+ ImplInsertHatch( -22, 0, 250, 900 );
+ ImplInsertHatch( -23, 0, 250, 450 );
+ ImplInsertHatch( -24, 0, 250, 1350 );
+ ImplInsertHatch( -25, 1, 250, 0 );
+ ImplInsertHatch( -26, 1, 250, 450 );
+
+ eTransparency = T_ON;
+
+ nBackGroundColor = nAuxiliaryColor = 0;
+
+ bSegmentCount = false;
+
+ nScalingFactor = 1.0;
+ nTextAlignmentVCont = nTextAlignmentHCont = 0.0;
+}
+
+
+void CGMElements::ImplInsertHatch( sal_Int32 nKey, int nStyle, tools::Long nDistance, tools::Long nAngle )
+{
+ HatchEntry& rEntry = maHatchMap[nKey];
+ rEntry.HatchStyle = nStyle;
+ rEntry.HatchDistance = nDistance;
+ rEntry.HatchAngle = nAngle;
+}
+
+
+void CGMElements::CopyAllBundles( const BundleList& rSource, BundleList& rDest )
+{
+ rDest.clear();
+
+ for (auto & pPtr : rSource)
+ {
+ rDest.push_back( pPtr->Clone() );
+ }
+};
+
+
+Bundle* CGMElements::GetBundleIndex( tools::Long nIndex, BundleList& rList, Bundle& rBundle )
+{
+ rBundle.SetIndex( nIndex );
+ Bundle* pBundle = GetBundle( rList, nIndex );
+ if ( !pBundle )
+ pBundle = InsertBundle( rList, rBundle );
+ return pBundle;
+}
+
+
+Bundle* CGMElements::GetBundle( BundleList& rList, tools::Long nIndex )
+{
+ for (auto const & i : rList) {
+ if ( i->GetIndex() == nIndex ) {
+ return i.get();
+ }
+ }
+ return nullptr;
+}
+
+
+Bundle* CGMElements::InsertBundle( BundleList& rList, Bundle& rBundle )
+{
+ Bundle* pBundle = GetBundle( rList, rBundle.GetIndex() );
+ if ( pBundle )
+ {
+ auto it = std::find_if(rList.begin(), rList.end(),
+ [&pBundle](const std::unique_ptr<Bundle>& rxBundle) { return rxBundle.get() == pBundle; });
+ if (it != rList.end())
+ rList.erase( it );
+ }
+ rList.push_back( rBundle.Clone() );
+ return rList.back().get();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/elements.hxx b/filter/source/graphicfilter/icgm/elements.hxx
new file mode 100644
index 000000000..3f4bd710a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/elements.hxx
@@ -0,0 +1,136 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include "bundles.hxx"
+#include "cgmtypes.hxx"
+#include <vector>
+#include <map>
+
+#define nBackGroundColor aColorTable[ 0 ]
+
+typedef ::std::vector< std::unique_ptr<Bundle> > BundleList;
+
+class CGMElements
+{
+ void ImplInsertHatch( sal_Int32 Key, int Style, tools::Long Distance, tools::Long Angle );
+ public:
+ tools::Long nMetaFileVersion;
+
+ sal_uInt32 nIntegerPrecision; // maybe 1, 2, 4 Bytes
+ sal_uInt32 nIndexPrecision; // " " "
+ RealPrecision eRealPrecision;
+ sal_uInt32 nRealSize; // maybe 4 or 8 bytes
+ sal_uInt32 nColorPrecision; // " " "
+ sal_uInt32 nColorIndexPrecision;// " " "
+
+ ScalingMode eScalingMode;
+ double nScalingFactor;
+
+ VDCType eVDCType; // Integer / Real
+ sal_uInt32 nVDCIntegerPrecision;
+ RealPrecision eVDCRealPrecision;
+ sal_uInt32 nVDCRealSize;
+ FloatRect aVDCExtent;
+ FloatRect aVDCExtentMaximum;
+
+ DeviceViewPortMode eDeviceViewPortMode;
+ double nDeviceViewPortScale;
+ DeviceViewPortMap eDeviceViewPortMap;
+ DeviceViewPortMapH eDeviceViewPortMapH;
+ DeviceViewPortMapV eDeviceViewPortMapV;
+ FloatRect aDeviceViewPort;
+
+ double nMitreLimit;
+
+ ClipIndicator eClipIndicator;
+ FloatRect aClipRect;
+
+ ColorSelectionMode eColorSelectionMode;
+ sal_uInt32 nColorMaximumIndex; // default 63
+ sal_uInt32 nLatestColorMaximumIndex; // default 63
+ sal_Int8 aColorTableEntryIs[ 256 ];
+ sal_uInt32 aColorTable[ 256 ];
+ sal_uInt32 aLatestColorTable[ 256 ];
+ sal_uInt32 nColorValueExtent[ 8 ]; // RGB, CMYK
+
+ // ASPECT SOURCE FLAGS
+ sal_uInt32 nAspectSourceFlags; // bit = 0 -> INDIVIDUAL
+ // 1 -> BUNDLED
+
+ LineBundle* pLineBundle; // Pointer to the current LineBundleIndex
+ LineBundle aLineBundle;
+ BundleList aLineList;
+ SpecMode eLineWidthSpecMode;
+ LineCapType eLineCapType;
+ LineJoinType eLineJoinType;
+
+ MarkerBundle* pMarkerBundle; // Pointer to the current MarkerBundleIndex
+ MarkerBundle aMarkerBundle;
+ BundleList aMarkerList;
+ SpecMode eMarkerSizeSpecMode;
+
+ EdgeBundle* pEdgeBundle; // Pointer to the current EdgeBundleIndex
+ EdgeBundle aEdgeBundle;
+ BundleList aEdgeList;
+ EdgeVisibility eEdgeVisibility;
+ SpecMode eEdgeWidthSpecMode;
+
+ TextBundle* pTextBundle; // Pointer to the current TextBundleIndex
+ TextBundle aTextBundle;
+ BundleList aTextList;
+ double nCharacterHeight;
+ double nCharacterOrientation[ 4 ];
+ UnderlineMode eUnderlineMode;
+ sal_uInt32 nUnderlineColor;
+ TextPath eTextPath;
+ TextAlignmentH eTextAlignmentH;
+ TextAlignmentV eTextAlignmentV;
+ double nTextAlignmentHCont;
+ double nTextAlignmentVCont;
+ tools::Long nCharacterSetIndex;
+ tools::Long nAlternateCharacterSetIndex;
+ CharacterCodingA eCharacterCodingA;
+ CGMFList aFontList;
+
+ FillBundle* pFillBundle; // Pointer to the current EdgeBundleIndex
+ FillBundle aFillBundle;
+ BundleList aFillList;
+ FloatPoint aFillRefPoint;
+ ::std::map<sal_uInt32, HatchEntry>
+ maHatchMap;
+
+ Transparency eTransparency;
+
+ sal_uInt32 nAuxiliaryColor;
+
+ // Delimiter Counts -> which will be increased by each 'begin' operation
+ // and decreased by each 'end' operation
+ bool bSegmentCount;
+ explicit CGMElements();
+ ~CGMElements();
+ CGMElements& operator=( const CGMElements& );
+ void Init();
+ static Bundle* GetBundleIndex( tools::Long nIndex, BundleList&, Bundle& );
+ static Bundle* GetBundle( BundleList& rList, tools::Long nIndex );
+ static Bundle* InsertBundle( BundleList&, Bundle& );
+ static void CopyAllBundles( const BundleList& Source, BundleList& Dest );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/outact.hxx b/filter/source/graphicfilter/icgm/outact.hxx
new file mode 100644
index 000000000..b06fffda8
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/outact.hxx
@@ -0,0 +1,108 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/document/XActionLockable.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+
+#define CGM_OUTACT_MAX_GROUP_LEVEL 64
+
+#include "cgm.hxx"
+#include <tools/poly.hxx>
+#include <array>
+#include <memory>
+
+class CGM;
+class CGMBitmapDescriptor;
+
+class CGMImpressOutAct
+{
+ sal_uInt16 mnCurrentPage; // defaulted to zero
+
+ sal_uInt32 mnGroupActCount; // grouping
+ sal_uInt32 mnGroupLevel;
+ std::array<sal_uInt32, CGM_OUTACT_MAX_GROUP_LEVEL>
+ maGroupLevel;
+
+ std::vector<PolyFlags> maFlags;
+ std::vector<Point> maPoints;
+ tools::PolyPolygon maPolyPolygon;
+ std::unique_ptr<css::awt::Gradient>
+ mpGradient;
+
+ CGM* mpCGM;
+
+ css::uno::Reference< css::drawing::XDrawPages > maXDrawPages;
+ css::uno::Reference< css::drawing::XDrawPage > maXDrawPage;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > maXMultiServiceFactory;
+ css::uno::Reference< css::drawing::XShape > maXShape;
+
+ css::uno::Reference< css::beans::XPropertySet > maXPropSet;
+ css::uno::Reference< css::drawing::XShapes > maXShapes;
+ std::vector<css::uno::Reference<css::document::XActionLockable>> maLockedNewXShapes;
+
+ sal_uInt32 nFinalTextCount;
+
+ bool ImplCreateShape( const OUString& rType );
+ bool ImplInitPage();
+ void ImplSetOrientation( FloatPoint const & RefPoint, double Orientation );
+ void ImplSetLineBundle();
+ void ImplSetFillBundle();
+ void ImplSetTextBundle( const css::uno::Reference< css::beans::XPropertySet > & );
+public:
+ CGMImpressOutAct( CGM&, const css::uno::Reference< css::frame::XModel > & );
+ ~CGMImpressOutAct();
+ void InsertPage();
+ void BeginGroup();
+ void EndGroup();
+ void EndGrouping();
+ void DrawRectangle( FloatRect const & );
+ void DrawEllipse( FloatPoint const & center, FloatPoint const &, double& Orientation );
+ void DrawEllipticalArc( FloatPoint const & center, FloatPoint const & size, double& orientation,
+ sal_uInt32 etype, double& startangle, double& endangle );
+ void DrawBitmap( CGMBitmapDescriptor* );
+ void DrawPolygon( tools::Polygon& );
+ void DrawPolyLine( tools::Polygon& );
+ void DrawPolybezier( tools::Polygon& );
+ void DrawPolyPolygon( tools::PolyPolygon const & );
+ void DrawText(css::awt::Point const & TextRectPos, css::awt::Size const & TextRectSize, const OUString& rString, FinalFlag);
+ void AppendText( const char* String );
+
+ void FirstOutPut() { mpCGM->mbFirstOutPut = false; } ;
+ void BeginFigure();
+ void CloseRegion();
+ void NewRegion();
+ void EndFigure();
+ void RegPolyLine( tools::Polygon const &, bool bReverse = false );
+ void SetGradientOffset( tools::Long nHorzOfs, tools::Long nVertOfs );
+ void SetGradientAngle( tools::Long nAngle );
+ void SetGradientDescriptor( sal_uInt32 nColorFrom, sal_uInt32 nColorTo );
+ void SetGradientStyle( sal_uInt32 nStyle );
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */