diff options
Diffstat (limited to '')
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: */ |