diff options
Diffstat (limited to 'filter/source/graphicfilter/icgm/actimpr.cxx')
-rw-r--r-- | filter/source/graphicfilter/icgm/actimpr.cxx | 1041 |
1 files changed, 1041 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: */ |