Update clang plugin. Change-Id: I0d862e8c08ef829d4f452108fec6176532af3ecb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190712 Tested-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
1099 lines
49 KiB
C++
1099 lines
49 KiB
C++
/* -*- 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 <pdf/pdfwriter_impl.hxx>
|
|
#include <pdf/EncryptionHashTransporter.hxx>
|
|
|
|
#include <vcl/dibtools.hxx>
|
|
#include <vcl/pdfextoutdevdata.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
#include <vcl/gdimtf.hxx>
|
|
#include <vcl/metaact.hxx>
|
|
#include <vcl/BitmapReadAccess.hxx>
|
|
#include <vcl/graph.hxx>
|
|
#include <pdf/IPDFEncryptor.hxx>
|
|
|
|
#include <unotools/streamwrap.hxx>
|
|
|
|
#include <tools/helpers.hxx>
|
|
#include <tools/fract.hxx>
|
|
#include <tools/stream.hxx>
|
|
|
|
#include <comphelper/fileformat.h>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/propertyvalue.hxx>
|
|
|
|
#include <com/sun/star/beans/PropertyValue.hpp>
|
|
#include <com/sun/star/io/XSeekable.hpp>
|
|
#include <com/sun/star/graphic/GraphicProvider.hpp>
|
|
#include <com/sun/star/graphic/XGraphicProvider.hpp>
|
|
#include <com/sun/star/beans/XMaterialHolder.hpp>
|
|
|
|
#include <o3tl/unit_conversion.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <vcl/skia/SkiaHelper.hxx>
|
|
|
|
#include <sal/log.hxx>
|
|
#include <memory>
|
|
|
|
using namespace vcl;
|
|
using namespace com::sun::star;
|
|
using namespace com::sun::star::uno;
|
|
using namespace com::sun::star::beans;
|
|
|
|
static bool lcl_canUsePDFAxialShading(const Gradient& rGradient);
|
|
|
|
void PDFWriterImpl::implWriteGradient( const tools::PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient,
|
|
VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
|
|
{
|
|
GDIMetaFile aTmpMtf;
|
|
Gradient aGradient(i_rGradient);
|
|
|
|
aGradient.AddGradientActions( i_rPolyPoly.GetBoundRect(), aTmpMtf );
|
|
|
|
m_rOuterFace.Push();
|
|
m_rOuterFace.IntersectClipRegion( i_rPolyPoly.getB2DPolyPolygon() );
|
|
playMetafile( aTmpMtf, nullptr, i_rContext, i_pDummyVDev );
|
|
m_rOuterFace.Pop();
|
|
}
|
|
|
|
void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSize, const Bitmap& i_rBitmap, const Graphic& i_Graphic,
|
|
VirtualDevice const * i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
|
|
{
|
|
if ( i_rBitmap.IsEmpty() || !i_rSize.Width() || !i_rSize.Height() )
|
|
return;
|
|
|
|
Bitmap aBitmap( i_rBitmap );
|
|
Point aPoint( i_rPoint );
|
|
Size aSize( i_rSize );
|
|
|
|
// #i19065# Negative sizes have mirror semantics on
|
|
// OutputDevice. Bitmap and co. have no idea about that, so
|
|
// perform that _before_ doing anything with aBitmapEx.
|
|
BmpMirrorFlags nMirrorFlags(BmpMirrorFlags::NONE);
|
|
if( aSize.Width() < 0 )
|
|
{
|
|
aSize.setWidth( aSize.Width() * -1 );
|
|
aPoint.AdjustX( -(aSize.Width()) );
|
|
nMirrorFlags |= BmpMirrorFlags::Horizontal;
|
|
}
|
|
if( aSize.Height() < 0 )
|
|
{
|
|
aSize.setHeight( aSize.Height() * -1 );
|
|
aPoint.AdjustY( -(aSize.Height()) );
|
|
nMirrorFlags |= BmpMirrorFlags::Vertical;
|
|
}
|
|
|
|
if( nMirrorFlags != BmpMirrorFlags::NONE )
|
|
{
|
|
aBitmap.Mirror( nMirrorFlags );
|
|
}
|
|
|
|
bool bIsJpeg = false, bIsPng = false;
|
|
if( i_Graphic.GetType() != GraphicType::NONE && i_Graphic.GetBitmap() == aBitmap )
|
|
{
|
|
GfxLinkType eType = i_Graphic.GetGfxLink().GetType();
|
|
bIsJpeg = (eType == GfxLinkType::NativeJpg);
|
|
bIsPng = (eType == GfxLinkType::NativePng);
|
|
}
|
|
|
|
// Do not downsample images smaller than 50x50px.
|
|
const Size aBmpSize(aBitmap.GetSizePixel());
|
|
if (i_rContext.m_nMaxImageResolution > 50 && aBmpSize.getWidth() > 50
|
|
&& aBmpSize.getHeight() > 50)
|
|
{
|
|
// do downsampling if necessary
|
|
const Size aDstSizeTwip( i_pDummyVDev->PixelToLogic(i_pDummyVDev->LogicToPixel(aSize), MapMode(MapUnit::MapTwip)) );
|
|
const double fBmpPixelX = aBmpSize.Width();
|
|
const double fBmpPixelY = aBmpSize.Height();
|
|
const double fMaxPixelX
|
|
= o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in)
|
|
* i_rContext.m_nMaxImageResolution;
|
|
const double fMaxPixelY
|
|
= o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in)
|
|
* i_rContext.m_nMaxImageResolution;
|
|
|
|
// check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
|
|
if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
|
|
( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
|
|
( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
|
|
{
|
|
// do scaling
|
|
Size aNewBmpSize;
|
|
const double fBmpWH = fBmpPixelX / fBmpPixelY;
|
|
const double fMaxWH = fMaxPixelX / fMaxPixelY;
|
|
|
|
if( fBmpWH < fMaxWH )
|
|
{
|
|
aNewBmpSize.setWidth(basegfx::fround<tools::Long>(fMaxPixelY * fBmpWH));
|
|
aNewBmpSize.setHeight(basegfx::fround<tools::Long>(fMaxPixelY));
|
|
}
|
|
else if( fBmpWH > 0.0 )
|
|
{
|
|
aNewBmpSize.setWidth(basegfx::fround<tools::Long>(fMaxPixelX));
|
|
aNewBmpSize.setHeight(basegfx::fround<tools::Long>(fMaxPixelX / fBmpWH));
|
|
}
|
|
|
|
if( aNewBmpSize.Width() && aNewBmpSize.Height() )
|
|
{
|
|
// #i121233# Use best quality for PDF exports
|
|
aBitmap.Scale( aNewBmpSize, BmpScaleFlag::BestQuality );
|
|
}
|
|
else
|
|
{
|
|
aBitmap.SetEmpty();
|
|
}
|
|
}
|
|
}
|
|
|
|
const Size aSizePixel( aBitmap.GetSizePixel() );
|
|
if ( !(aSizePixel.Width() && aSizePixel.Height()) )
|
|
return;
|
|
|
|
if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
|
|
aBitmap.Convert(BmpConversion::N8BitGreys);
|
|
bool bUseJPGCompression = !i_rContext.m_bOnlyLosslessCompression;
|
|
if ( bIsPng || ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
|
|
bUseJPGCompression = false;
|
|
|
|
auto pStrm=std::make_shared<SvMemoryStream>();
|
|
AlphaMask aAlphaMask;
|
|
|
|
bool bTrueColorJPG = true;
|
|
if ( bUseJPGCompression )
|
|
{
|
|
// TODO this checks could be done much earlier, saving us
|
|
// from trying conversion & stores before...
|
|
if ( !aBitmap.HasAlpha() )
|
|
{
|
|
const auto aCacheEntry=m_aPDFBmpCache.find(
|
|
aBitmap.GetChecksum());
|
|
if ( aCacheEntry != m_aPDFBmpCache.end() )
|
|
{
|
|
m_rOuterFace.DrawJPGBitmap( *aCacheEntry->second, true, aSizePixel,
|
|
tools::Rectangle( aPoint, aSize ), aAlphaMask, i_Graphic );
|
|
return;
|
|
}
|
|
}
|
|
sal_uInt32 nZippedFileSize = 0; // sj: we will calculate the filesize of a zipped bitmap
|
|
if ( !bIsJpeg ) // to determine if jpeg compression is useful
|
|
{
|
|
SvMemoryStream aTemp;
|
|
aTemp.SetCompressMode( aTemp.GetCompressMode() | SvStreamCompressFlags::ZBITMAP );
|
|
aTemp.SetVersion( SOFFICE_FILEFORMAT_40 ); // sj: up from version 40 our bitmap stream operator
|
|
WriteDIBBitmapEx(aBitmap, aTemp); // is capable of zlib stream compression
|
|
nZippedFileSize = aTemp.TellEnd();
|
|
}
|
|
if ( aBitmap.HasAlpha() )
|
|
aAlphaMask = aBitmap.CreateAlphaMask();
|
|
Graphic aGraphic(aBitmap.CreateColorBitmap());
|
|
|
|
Sequence< PropertyValue > aFilterData{
|
|
comphelper::makePropertyValue(u"Quality"_ustr, sal_Int32(i_rContext.m_nJPEGQuality)),
|
|
comphelper::makePropertyValue(u"ColorMode"_ustr, sal_Int32(0))
|
|
};
|
|
|
|
try
|
|
{
|
|
uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( *pStrm );
|
|
uno::Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
|
|
const uno::Reference< uno::XComponentContext >& xContext( comphelper::getProcessComponentContext() );
|
|
uno::Reference< graphic::XGraphicProvider > xGraphicProvider( graphic::GraphicProvider::create(xContext) );
|
|
uno::Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
|
|
uno::Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
|
|
uno::Sequence< beans::PropertyValue > aOutMediaProperties{
|
|
comphelper::makePropertyValue(u"OutputStream"_ustr, xOut),
|
|
comphelper::makePropertyValue(u"MimeType"_ustr, u"image/jpeg"_ustr),
|
|
comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData)
|
|
};
|
|
xGraphicProvider->storeGraphic( xGraphic, aOutMediaProperties );
|
|
xOut->flush();
|
|
if ( !bIsJpeg && xSeekable->getLength() > nZippedFileSize )
|
|
{
|
|
bUseJPGCompression = false;
|
|
}
|
|
else
|
|
{
|
|
pStrm->Seek( STREAM_SEEK_TO_END );
|
|
|
|
xSeekable->seek( 0 );
|
|
Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(u"InputStream"_ustr,
|
|
xStream) };
|
|
uno::Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
|
|
if ( xPropSet.is() )
|
|
{
|
|
sal_Int16 nBitsPerPixel = 24;
|
|
if ( xPropSet->getPropertyValue(u"BitsPerPixel"_ustr) >>= nBitsPerPixel )
|
|
{
|
|
bTrueColorJPG = nBitsPerPixel != 8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
bUseJPGCompression = false;
|
|
}
|
|
}
|
|
if ( bUseJPGCompression )
|
|
{
|
|
m_rOuterFace.DrawJPGBitmap( *pStrm, bTrueColorJPG, aSizePixel, tools::Rectangle( aPoint, aSize ), aAlphaMask, i_Graphic );
|
|
if (!aBitmap.HasAlpha() && bTrueColorJPG)
|
|
{
|
|
// Cache last jpeg export
|
|
m_aPDFBmpCache.insert(
|
|
{aBitmap.GetChecksum(), pStrm});
|
|
}
|
|
}
|
|
else if ( aBitmap.HasAlpha() )
|
|
m_rOuterFace.DrawBitmap( aPoint, aSize, aBitmap );
|
|
else
|
|
m_rOuterFace.DrawBitmap( aPoint, aSize, aBitmap, i_Graphic );
|
|
|
|
}
|
|
|
|
void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevData* i_pOutDevData, const vcl::PDFWriter::PlayMetafileContext& i_rContext, VirtualDevice* pDummyVDev )
|
|
{
|
|
bool bAssertionFired( false );
|
|
|
|
ScopedVclPtr<VirtualDevice> xPrivateDevice;
|
|
if( ! pDummyVDev )
|
|
{
|
|
xPrivateDevice.disposeAndReset(VclPtr<VirtualDevice>::Create());
|
|
pDummyVDev = xPrivateDevice.get();
|
|
pDummyVDev->EnableOutput( false );
|
|
pDummyVDev->SetMapMode( i_rMtf.GetPrefMapMode() );
|
|
}
|
|
const GDIMetaFile& aMtf( i_rMtf );
|
|
|
|
for( sal_uInt32 i = 0, nCount = aMtf.GetActionSize(); i < nCount; )
|
|
{
|
|
if ( !i_pOutDevData || !i_pOutDevData->PlaySyncPageAct( m_rOuterFace, i, aMtf ) )
|
|
{
|
|
const MetaAction* pAction = aMtf.GetAction( i );
|
|
const MetaActionType nType = pAction->GetType();
|
|
|
|
switch( nType )
|
|
{
|
|
case MetaActionType::PIXEL:
|
|
{
|
|
const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
|
|
m_rOuterFace.DrawPixel( pA->GetPoint(), pA->GetColor() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::POINT:
|
|
{
|
|
const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
|
|
m_rOuterFace.DrawPixel( pA->GetPoint() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::LINE:
|
|
{
|
|
const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
|
|
if ( pA->GetLineInfo().IsDefault() )
|
|
m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint() );
|
|
else
|
|
m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint(), pA->GetLineInfo() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::RECT:
|
|
{
|
|
const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
|
|
m_rOuterFace.DrawRect( pA->GetRect() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::ROUNDRECT:
|
|
{
|
|
const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
|
|
m_rOuterFace.DrawRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::ELLIPSE:
|
|
{
|
|
const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
|
|
m_rOuterFace.DrawEllipse( pA->GetRect() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::ARC:
|
|
{
|
|
const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
|
|
m_rOuterFace.DrawArc( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::PIE:
|
|
{
|
|
const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
|
|
m_rOuterFace.DrawPie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::CHORD:
|
|
{
|
|
const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
|
|
m_rOuterFace.DrawChord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::POLYGON:
|
|
{
|
|
const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pAction);
|
|
m_rOuterFace.DrawPolygon( pA->GetPolygon() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::POLYLINE:
|
|
{
|
|
const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
|
|
if ( pA->GetLineInfo().IsDefault() )
|
|
m_rOuterFace.DrawPolyLine( pA->GetPolygon() );
|
|
else
|
|
m_rOuterFace.DrawPolyLine( pA->GetPolygon(), pA->GetLineInfo() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::POLYPOLYGON:
|
|
{
|
|
const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pAction);
|
|
m_rOuterFace.DrawPolyPolygon( pA->GetPolyPolygon() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::GRADIENT:
|
|
{
|
|
const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
|
|
const Gradient& rGradient = pA->GetGradient();
|
|
if (lcl_canUsePDFAxialShading(rGradient))
|
|
{
|
|
m_rOuterFace.DrawGradient( pA->GetRect(), rGradient );
|
|
}
|
|
else
|
|
{
|
|
const tools::PolyPolygon aPolyPoly( pA->GetRect() );
|
|
implWriteGradient( aPolyPoly, rGradient, pDummyVDev, i_rContext );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::GRADIENTEX:
|
|
{
|
|
const MetaGradientExAction* pA = static_cast<const MetaGradientExAction*>(pAction);
|
|
const Gradient& rGradient = pA->GetGradient();
|
|
|
|
if (lcl_canUsePDFAxialShading(rGradient))
|
|
m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), rGradient );
|
|
else
|
|
implWriteGradient( pA->GetPolyPolygon(), rGradient, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::HATCH:
|
|
{
|
|
const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
|
|
m_rOuterFace.DrawHatch( pA->GetPolyPolygon(), pA->GetHatch() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::Transparent:
|
|
{
|
|
const MetaTransparentAction* pA = static_cast<const MetaTransparentAction*>(pAction);
|
|
m_rOuterFace.DrawTransparent( pA->GetPolyPolygon(), pA->GetTransparence() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::FLOATTRANSPARENT:
|
|
{
|
|
const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
|
|
|
|
GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
|
|
const Point& rPos = pA->GetPoint();
|
|
const Size& rSize= pA->GetSize();
|
|
const Gradient& rTransparenceGradient = pA->GetGradient();
|
|
|
|
// special case constant alpha value
|
|
if( rTransparenceGradient.GetStartColor() == rTransparenceGradient.GetEndColor() )
|
|
{
|
|
const Color aTransCol( rTransparenceGradient.GetStartColor() );
|
|
const sal_uInt16 nTransPercent = aTransCol.GetLuminance() * 100 / 255;
|
|
m_rOuterFace.BeginTransparencyGroup();
|
|
|
|
// tdf#138826 adjust the aTmpMtf to start at rPos (see also #i112076#)
|
|
Point aMtfOrigin(aTmpMtf.GetPrefMapMode().GetOrigin());
|
|
if (rPos != aMtfOrigin)
|
|
aTmpMtf.Move(rPos.X() - aMtfOrigin.X(), rPos.Y() - aMtfOrigin.Y());
|
|
|
|
playMetafile( aTmpMtf, nullptr, i_rContext, pDummyVDev );
|
|
m_rOuterFace.EndTransparencyGroup( tools::Rectangle( rPos, rSize ), nTransPercent );
|
|
}
|
|
else
|
|
{
|
|
const Size aDstSizeTwip( pDummyVDev->PixelToLogic(pDummyVDev->LogicToPixel(rSize), MapMode(MapUnit::MapTwip)) );
|
|
|
|
// i#115962# Always use at least 300 DPI for bitmap conversion of transparence gradients,
|
|
// else the quality is not acceptable (see bugdoc as example)
|
|
sal_Int32 nMaxBmpDPI(300);
|
|
|
|
if( i_rContext.m_nMaxImageResolution > 50 )
|
|
{
|
|
if ( nMaxBmpDPI > i_rContext.m_nMaxImageResolution )
|
|
nMaxBmpDPI = i_rContext.m_nMaxImageResolution;
|
|
}
|
|
const sal_Int32 nPixelX = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI;
|
|
const sal_Int32 nPixelY = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI;
|
|
if ( nPixelX && nPixelY )
|
|
{
|
|
Size aDstSizePixel( nPixelX, nPixelY );
|
|
ScopedVclPtrInstance<VirtualDevice> xVDev(DeviceFormat::WITH_ALPHA);
|
|
if( xVDev->SetOutputSizePixel( aDstSizePixel, true, true ) )
|
|
{
|
|
Point aPoint;
|
|
|
|
MapMode aMapMode( pDummyVDev->GetMapMode() );
|
|
aMapMode.SetOrigin( aPoint );
|
|
xVDev->SetMapMode( aMapMode );
|
|
const bool bVDevOldMap = xVDev->IsMapModeEnabled();
|
|
Size aDstSize( xVDev->PixelToLogic( aDstSizePixel ) );
|
|
|
|
Point aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
|
|
if ( aMtfOrigin.X() || aMtfOrigin.Y() )
|
|
aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
|
|
double fScaleX = static_cast<double>(aDstSize.Width()) / static_cast<double>(aTmpMtf.GetPrefSize().Width());
|
|
double fScaleY = static_cast<double>(aDstSize.Height()) / static_cast<double>(aTmpMtf.GetPrefSize().Height());
|
|
if( fScaleX != 1.0 || fScaleY != 1.0 )
|
|
aTmpMtf.Scale( fScaleX, fScaleY );
|
|
aTmpMtf.SetPrefMapMode( aMapMode );
|
|
|
|
// create paint bitmap
|
|
aTmpMtf.WindStart();
|
|
aTmpMtf.Play(*xVDev, aPoint, aDstSize);
|
|
aTmpMtf.WindStart();
|
|
xVDev->EnableMapMode( false );
|
|
Bitmap aPaint(xVDev->GetBitmap(aPoint, xVDev->GetOutputSizePixel()));
|
|
xVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
|
|
|
|
// create alpha mask from gradient
|
|
xVDev->SetDrawMode( DrawModeFlags::GrayGradient );
|
|
xVDev->DrawGradient( tools::Rectangle( aPoint, aDstSize ), rTransparenceGradient );
|
|
xVDev->SetDrawMode( DrawModeFlags::Default );
|
|
xVDev->EnableMapMode( false );
|
|
|
|
AlphaMask aAlpha(xVDev->GetBitmap(Point(), xVDev->GetOutputSizePixel()));
|
|
#if HAVE_FEATURE_SKIA
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
// In release builds, we always invert
|
|
// regardless of whether Skia is enabled or not.
|
|
// But in debug builds, we can't invert when
|
|
// Skia is enabled.
|
|
if ( !SkiaHelper::isVCLSkiaEnabled() )
|
|
#endif
|
|
#endif
|
|
{
|
|
// When Skia is disabled, the alpha mask
|
|
// must be inverted a second time. To test
|
|
// this code, export the following
|
|
// document to PDF:
|
|
// https://bugs.documentfoundation.org/attachment.cgi?id=188084
|
|
aAlpha.Invert(); // convert to alpha
|
|
}
|
|
aAlpha.BlendWith(aPaint.CreateAlphaMask());
|
|
|
|
xVDev.disposeAndClear();
|
|
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( rPos, rSize, Bitmap(aPaint.CreateColorBitmap(), aAlpha ), aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::EPS:
|
|
{
|
|
const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pAction);
|
|
const GDIMetaFile& aSubstitute( pA->GetSubstitute() );
|
|
|
|
m_rOuterFace.Push();
|
|
pDummyVDev->Push();
|
|
|
|
MapMode aMapMode( aSubstitute.GetPrefMapMode() );
|
|
Size aOutSize( OutputDevice::LogicToLogic( pA->GetSize(), pDummyVDev->GetMapMode(), aMapMode ) );
|
|
aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
|
|
aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
|
|
aMapMode.SetOrigin( OutputDevice::LogicToLogic( pA->GetPoint(), pDummyVDev->GetMapMode(), aMapMode ) );
|
|
|
|
m_rOuterFace.SetMapMode( aMapMode );
|
|
pDummyVDev->SetMapMode( aMapMode );
|
|
playMetafile( aSubstitute, nullptr, i_rContext, pDummyVDev );
|
|
pDummyVDev->Pop();
|
|
m_rOuterFace.Pop();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::COMMENT:
|
|
if( ! i_rContext.m_bTransparenciesWereRemoved )
|
|
{
|
|
const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
|
|
|
|
if( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
|
|
{
|
|
const MetaGradientExAction* pGradAction = nullptr;
|
|
bool bDone = false;
|
|
|
|
while( !bDone && ( ++i < nCount ) )
|
|
{
|
|
pAction = aMtf.GetAction( i );
|
|
|
|
if( pAction->GetType() == MetaActionType::GRADIENTEX )
|
|
pGradAction = static_cast<const MetaGradientExAction*>(pAction);
|
|
else if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
|
|
( static_cast<const MetaCommentAction*>(pAction)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END")) )
|
|
{
|
|
bDone = true;
|
|
}
|
|
}
|
|
|
|
if( pGradAction )
|
|
{
|
|
if (lcl_canUsePDFAxialShading(pGradAction->GetGradient()))
|
|
{
|
|
m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() );
|
|
}
|
|
else
|
|
{
|
|
implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const sal_uInt8* pData = pA->GetData();
|
|
if ( pData )
|
|
{
|
|
SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pData), pA->GetDataSize(), StreamMode::READ );
|
|
bool bSkipSequence = false;
|
|
OString sSeqEnd;
|
|
|
|
if( pA->GetComment() == "XPATHSTROKE_SEQ_BEGIN" )
|
|
{
|
|
sSeqEnd = "XPATHSTROKE_SEQ_END"_ostr;
|
|
SvtGraphicStroke aStroke;
|
|
ReadSvtGraphicStroke( aMemStm, aStroke );
|
|
|
|
tools::Polygon aPath;
|
|
aStroke.getPath( aPath );
|
|
|
|
tools::PolyPolygon aStartArrow;
|
|
tools::PolyPolygon aEndArrow;
|
|
double fTransparency( aStroke.getTransparency() );
|
|
double fStrokeWidth( aStroke.getStrokeWidth() );
|
|
SvtGraphicStroke::DashArray aDashArray;
|
|
|
|
aStroke.getStartArrow( aStartArrow );
|
|
aStroke.getEndArrow( aEndArrow );
|
|
aStroke.getDashArray( aDashArray );
|
|
|
|
bSkipSequence = true;
|
|
if ( aStartArrow.Count() || aEndArrow.Count() )
|
|
bSkipSequence = false;
|
|
if ( !aDashArray.empty() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
|
|
bSkipSequence = false;
|
|
if ( bSkipSequence )
|
|
{
|
|
PDFWriter::ExtLineInfo aInfo;
|
|
aInfo.m_fLineWidth = fStrokeWidth;
|
|
aInfo.m_fTransparency = fTransparency;
|
|
aInfo.m_fMiterLimit = aStroke.getMiterLimit();
|
|
switch( aStroke.getCapType() )
|
|
{
|
|
default:
|
|
case SvtGraphicStroke::capButt: aInfo.m_eCap = PDFWriter::capButt;break;
|
|
case SvtGraphicStroke::capRound: aInfo.m_eCap = PDFWriter::capRound;break;
|
|
case SvtGraphicStroke::capSquare: aInfo.m_eCap = PDFWriter::capSquare;break;
|
|
}
|
|
switch( aStroke.getJoinType() )
|
|
{
|
|
default:
|
|
case SvtGraphicStroke::joinMiter: aInfo.m_eJoin = PDFWriter::joinMiter;break;
|
|
case SvtGraphicStroke::joinRound: aInfo.m_eJoin = PDFWriter::joinRound;break;
|
|
case SvtGraphicStroke::joinBevel: aInfo.m_eJoin = PDFWriter::joinBevel;break;
|
|
case SvtGraphicStroke::joinNone:
|
|
aInfo.m_eJoin = PDFWriter::joinMiter;
|
|
aInfo.m_fMiterLimit = 0.0;
|
|
break;
|
|
}
|
|
aInfo.m_aDashArray = std::move(aDashArray);
|
|
|
|
if(SvtGraphicStroke::joinNone == aStroke.getJoinType()
|
|
&& fStrokeWidth > 0.0)
|
|
{
|
|
// emulate no edge rounding by handling single edges
|
|
const sal_uInt16 nPoints(aPath.GetSize());
|
|
const bool bCurve(aPath.HasFlags());
|
|
|
|
for(sal_uInt16 a(0); a + 1 < nPoints; a++)
|
|
{
|
|
if(bCurve
|
|
&& PolyFlags::Normal != aPath.GetFlags(a + 1)
|
|
&& a + 2 < nPoints
|
|
&& PolyFlags::Normal != aPath.GetFlags(a + 2)
|
|
&& a + 3 < nPoints)
|
|
{
|
|
const tools::Polygon aSnippet(4,
|
|
aPath.GetConstPointAry() + a,
|
|
aPath.GetConstFlagAry() + a);
|
|
m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
|
|
a += 2;
|
|
}
|
|
else
|
|
{
|
|
const tools::Polygon aSnippet(2,
|
|
aPath.GetConstPointAry() + a);
|
|
m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_rOuterFace.DrawPolyLine( aPath, aInfo );
|
|
}
|
|
}
|
|
}
|
|
else if ( pA->GetComment() == "XPATHFILL_SEQ_BEGIN" )
|
|
{
|
|
sSeqEnd = "XPATHFILL_SEQ_END"_ostr;
|
|
SvtGraphicFill aFill;
|
|
ReadSvtGraphicFill( aMemStm, aFill );
|
|
|
|
if ( ( aFill.getFillType() == SvtGraphicFill::fillSolid ) && ( aFill.getFillRule() == SvtGraphicFill::fillEvenOdd ) )
|
|
{
|
|
double fTransparency = aFill.getTransparency();
|
|
if ( fTransparency == 0.0 )
|
|
{
|
|
tools::PolyPolygon aPath;
|
|
aFill.getPath( aPath );
|
|
|
|
bSkipSequence = true;
|
|
m_rOuterFace.DrawPolyPolygon( aPath );
|
|
}
|
|
else if ( fTransparency == 1.0 )
|
|
bSkipSequence = true;
|
|
}
|
|
}
|
|
if ( bSkipSequence )
|
|
{
|
|
while( ++i < nCount )
|
|
{
|
|
pAction = aMtf.GetAction( i );
|
|
if ( pAction->GetType() == MetaActionType::COMMENT )
|
|
{
|
|
OString sComment( static_cast<const MetaCommentAction*>(pAction)->GetComment() );
|
|
if (sComment == sSeqEnd)
|
|
break;
|
|
}
|
|
// #i44496#
|
|
// the replacement action for stroke is a filled rectangle
|
|
// the set fillcolor of the replacement is part of the graphics
|
|
// state and must not be skipped
|
|
else if( pAction->GetType() == MetaActionType::FILLCOLOR )
|
|
{
|
|
const MetaFillColorAction* pMA = static_cast<const MetaFillColorAction*>(pAction);
|
|
if( pMA->IsSetting() )
|
|
m_rOuterFace.SetFillColor( pMA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetFillColor();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMP:
|
|
{
|
|
const MetaBmpAction* pA = static_cast<const MetaBmpAction*>(pAction);
|
|
Bitmap aBitmap( pA->GetBitmap() );
|
|
Size aSize( OutputDevice::LogicToLogic( aBitmap.GetPrefSize(),
|
|
aBitmap.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
|
|
if( ! ( aSize.Width() && aSize.Height() ) )
|
|
aSize = pDummyVDev->PixelToLogic( aBitmap.GetSizePixel() );
|
|
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetPoint(), aSize, aBitmap, aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMPSCALE:
|
|
{
|
|
const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), pA->GetBitmap(), aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMPSCALEPART:
|
|
{
|
|
const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pAction);
|
|
Bitmap aBitmap( pA->GetBitmap() );
|
|
aBitmap.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmap, aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMPEX:
|
|
{
|
|
const MetaBmpExAction* pA = static_cast<const MetaBmpExAction*>(pAction);
|
|
Bitmap aBitmap( pA->GetBitmap() );
|
|
Size aSize( OutputDevice::LogicToLogic( aBitmap.GetPrefSize(),
|
|
aBitmap.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetPoint(), aSize, aBitmap, aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMPEXSCALE:
|
|
{
|
|
const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
|
|
Bitmap aBitmap( pA->GetBitmap() );
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), aBitmap, aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::BMPEXSCALEPART:
|
|
{
|
|
const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
|
|
|
|
Bitmap aBitmapEx( pA->GetBitmap() );
|
|
aBitmapEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
|
|
Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
|
|
implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, aGraphic, pDummyVDev, i_rContext );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::MASK:
|
|
case MetaActionType::MASKSCALE:
|
|
case MetaActionType::MASKSCALEPART:
|
|
{
|
|
SAL_WARN( "vcl", "MetaMask...Action not supported yet" );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXT:
|
|
{
|
|
const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
|
|
m_rOuterFace.DrawText( pA->GetPoint(), pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) ) );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTRECT:
|
|
{
|
|
const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
|
|
m_rOuterFace.DrawText( pA->GetRect(), pA->GetText(), pA->GetStyle() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTARRAY:
|
|
{
|
|
const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
|
|
m_rOuterFace.DrawTextArray(pA->GetPoint(), pA->GetText(), pA->GetDXArray(),
|
|
pA->GetKashidaArray(), pA->GetIndex(), pA->GetLen(),
|
|
pA->GetLayoutContextIndex(),
|
|
pA->GetLayoutContextLen());
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::STRETCHTEXT:
|
|
{
|
|
const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
|
|
m_rOuterFace.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTLINE:
|
|
{
|
|
const MetaTextLineAction* pA = static_cast<const MetaTextLineAction*>(pAction);
|
|
m_rOuterFace.DrawTextLine( pA->GetStartPoint(), pA->GetWidth(), pA->GetStrikeout(), pA->GetUnderline(), pA->GetOverline() );
|
|
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::CLIPREGION:
|
|
{
|
|
const MetaClipRegionAction* pA = static_cast<const MetaClipRegionAction*>(pAction);
|
|
|
|
if( pA->IsClipping() )
|
|
{
|
|
if( pA->GetRegion().IsEmpty() )
|
|
m_rOuterFace.SetClipRegion( basegfx::B2DPolyPolygon() );
|
|
else
|
|
{
|
|
const vcl::Region& aReg( pA->GetRegion() );
|
|
m_rOuterFace.SetClipRegion( aReg.GetAsB2DPolyPolygon() );
|
|
}
|
|
}
|
|
else
|
|
m_rOuterFace.SetClipRegion();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::ISECTRECTCLIPREGION:
|
|
{
|
|
const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pAction);
|
|
m_rOuterFace.IntersectClipRegion( pA->GetRect() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::ISECTREGIONCLIPREGION:
|
|
{
|
|
const MetaISectRegionClipRegionAction* pA = static_cast<const MetaISectRegionClipRegionAction*>(pAction);
|
|
const vcl::Region& aReg( pA->GetRegion() );
|
|
m_rOuterFace.IntersectClipRegion( aReg.GetAsB2DPolyPolygon() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::MOVECLIPREGION:
|
|
{
|
|
const MetaMoveClipRegionAction* pA = static_cast<const MetaMoveClipRegionAction*>(pAction);
|
|
m_rOuterFace.MoveClipRegion( pA->GetHorzMove(), pA->GetVertMove() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::MAPMODE:
|
|
{
|
|
const_cast< MetaAction* >( pAction )->Execute( pDummyVDev );
|
|
m_rOuterFace.SetMapMode( pDummyVDev->GetMapMode() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::LINECOLOR:
|
|
{
|
|
const MetaLineColorAction* pA = static_cast<const MetaLineColorAction*>(pAction);
|
|
|
|
if( pA->IsSetting() )
|
|
m_rOuterFace.SetLineColor( pA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetLineColor();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::FILLCOLOR:
|
|
{
|
|
const MetaFillColorAction* pA = static_cast<const MetaFillColorAction*>(pAction);
|
|
|
|
if( pA->IsSetting() )
|
|
m_rOuterFace.SetFillColor( pA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetFillColor();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTLINECOLOR:
|
|
{
|
|
const MetaTextLineColorAction* pA = static_cast<const MetaTextLineColorAction*>(pAction);
|
|
|
|
if( pA->IsSetting() )
|
|
m_rOuterFace.SetTextLineColor( pA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetTextLineColor();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::OVERLINECOLOR:
|
|
{
|
|
const MetaOverlineColorAction* pA = static_cast<const MetaOverlineColorAction*>(pAction);
|
|
|
|
if( pA->IsSetting() )
|
|
m_rOuterFace.SetOverlineColor( pA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetOverlineColor();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTFILLCOLOR:
|
|
{
|
|
const MetaTextFillColorAction* pA = static_cast<const MetaTextFillColorAction*>(pAction);
|
|
|
|
if( pA->IsSetting() )
|
|
m_rOuterFace.SetTextFillColor( pA->GetColor() );
|
|
else
|
|
m_rOuterFace.SetTextFillColor();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTCOLOR:
|
|
{
|
|
const MetaTextColorAction* pA = static_cast<const MetaTextColorAction*>(pAction);
|
|
m_rOuterFace.SetTextColor( pA->GetColor() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTALIGN:
|
|
{
|
|
const MetaTextAlignAction* pA = static_cast<const MetaTextAlignAction*>(pAction);
|
|
m_rOuterFace.SetTextAlign( pA->GetTextAlign() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::FONT:
|
|
{
|
|
const MetaFontAction* pA = static_cast<const MetaFontAction*>(pAction);
|
|
m_rOuterFace.SetFont( pA->GetFont() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::PUSH:
|
|
{
|
|
const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
|
|
|
|
pDummyVDev->Push( pA->GetFlags() );
|
|
m_rOuterFace.Push( pA->GetFlags() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::POP:
|
|
{
|
|
pDummyVDev->Pop();
|
|
m_rOuterFace.Pop();
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::LAYOUTMODE:
|
|
{
|
|
const MetaLayoutModeAction* pA = static_cast<const MetaLayoutModeAction*>(pAction);
|
|
m_rOuterFace.SetLayoutMode( pA->GetLayoutMode() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::TEXTLANGUAGE:
|
|
{
|
|
const MetaTextLanguageAction* pA = static_cast<const MetaTextLanguageAction*>(pAction);
|
|
m_rOuterFace.SetDigitLanguage( pA->GetTextLanguage() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::WALLPAPER:
|
|
{
|
|
const MetaWallpaperAction* pA = static_cast<const MetaWallpaperAction*>(pAction);
|
|
m_rOuterFace.DrawWallpaper( pA->GetRect(), pA->GetWallpaper() );
|
|
}
|
|
break;
|
|
|
|
case MetaActionType::RASTEROP:
|
|
case MetaActionType::REFPOINT:
|
|
{
|
|
// !!! >>> we don't want to support this actions
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// #i24604# Made assertion fire only once per
|
|
// metafile. The asserted actions here are all
|
|
// deprecated
|
|
if( !bAssertionFired )
|
|
{
|
|
bAssertionFired = true;
|
|
SAL_WARN( "vcl", "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered " << static_cast<int>(nType) );
|
|
}
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Encryption methods
|
|
|
|
void PDFWriterImpl::checkAndEnableStreamEncryption(sal_Int32 nObject)
|
|
{
|
|
if (!m_aContext.Encryption.canEncrypt() || !m_pPDFEncryptor)
|
|
return;
|
|
|
|
m_pPDFEncryptor->enableStreamEncryption();
|
|
m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, nObject);
|
|
}
|
|
|
|
void PDFWriterImpl::disableStreamEncryption()
|
|
{
|
|
if (m_pPDFEncryptor)
|
|
m_pPDFEncryptor->disableStreamEncryption();
|
|
}
|
|
|
|
void PDFWriterImpl::enableStringEncryption(sal_Int32 nObject)
|
|
{
|
|
if (!m_aContext.Encryption.canEncrypt() || !m_pPDFEncryptor)
|
|
return;
|
|
|
|
m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, nObject);
|
|
}
|
|
|
|
|
|
|
|
void PDFWriterImpl::DrawHatchLine_DrawLine(const Point& rStartPoint, const Point& rEndPoint)
|
|
{
|
|
drawLine(rStartPoint, rEndPoint);
|
|
}
|
|
|
|
static bool lcl_canUsePDFAxialShading(const Gradient& rGradient) {
|
|
switch (rGradient.GetStyle())
|
|
{
|
|
case css::awt::GradientStyle_LINEAR:
|
|
case css::awt::GradientStyle_AXIAL:
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// TODO: handle step count
|
|
return rGradient.GetSteps() <= 0;
|
|
}
|
|
|
|
void PDFWriterImpl::ImplClearFontData(bool bNewFontLists)
|
|
{
|
|
VirtualDevice::ImplClearFontData(bNewFontLists);
|
|
if (bNewFontLists && AcquireGraphics())
|
|
{
|
|
ReleaseFontCollection();
|
|
ReleaseFontCache();
|
|
}
|
|
}
|
|
|
|
void PDFWriterImpl::ImplRefreshFontData(bool bNewFontLists)
|
|
{
|
|
if (bNewFontLists && AcquireGraphics())
|
|
{
|
|
SetFontCollectionFromSVData();
|
|
ResetNewFontCache();
|
|
}
|
|
}
|
|
|
|
vcl::Region PDFWriterImpl::ClipToDeviceBounds(vcl::Region aRegion) const
|
|
{
|
|
return aRegion;
|
|
}
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|