diff options
Diffstat (limited to 'vcl/source/filter/svm/SvmReader.cxx')
-rw-r--r-- | vcl/source/filter/svm/SvmReader.cxx | 1438 |
1 files changed, 1438 insertions, 0 deletions
diff --git a/vcl/source/filter/svm/SvmReader.cxx b/vcl/source/filter/svm/SvmReader.cxx new file mode 100644 index 000000000..f02451ea3 --- /dev/null +++ b/vcl/source/filter/svm/SvmReader.cxx @@ -0,0 +1,1438 @@ +/* -*- 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 <osl/thread.h> +#include <tools/stream.hxx> +#include <tools/vcompat.hxx> + +#include <vcl/filter/SvmReader.hxx> +#include <vcl/TypeSerializer.hxx> +#include <vcl/dibtools.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/metaact.hxx> + +#include "SvmConverter.hxx" + +namespace +{ +class DepthGuard +{ +private: + ImplMetaReadData& m_rData; + rtl_TextEncoding m_eOrigCharSet; + +public: + DepthGuard(ImplMetaReadData& rData, SvStream const& rIStm) + : m_rData(rData) + , m_eOrigCharSet(m_rData.meActualCharSet) + { + ++m_rData.mnParseDepth; + m_rData.meActualCharSet = rIStm.GetStreamCharSet(); + } + bool TooDeep() const { return m_rData.mnParseDepth > 1024; } + ~DepthGuard() + { + --m_rData.mnParseDepth; + m_rData.meActualCharSet = m_eOrigCharSet; + } +}; +} + +SvmReader::SvmReader(SvStream& rIStm) + : mrStream(rIStm) +{ +} + +SvStream& SvmReader::Read(GDIMetaFile& rMetaFile, ImplMetaReadData* pData) +{ + if (mrStream.GetError()) + { + SAL_WARN("vcl.gdi", "Stream error: " << mrStream.GetError()); + return mrStream; + } + + sal_uInt64 nStmPos = mrStream.Tell(); + SvStreamEndian nOldFormat = mrStream.GetEndian(); + + mrStream.SetEndian(SvStreamEndian::LITTLE); + + try + { + char aId[7]; + aId[0] = 0; + aId[6] = 0; + mrStream.ReadBytes(aId, 6); + if (mrStream.good() && !strcmp(aId, "VCLMTF")) + { + // new format + sal_uInt32 nStmCompressMode = 0; + sal_uInt32 nCount = 0; + std::unique_ptr<VersionCompatRead> pCompat(new VersionCompatRead(mrStream)); + + mrStream.ReadUInt32(nStmCompressMode); + TypeSerializer aSerializer(mrStream); + MapMode aMapMode; + aSerializer.readMapMode(aMapMode); + rMetaFile.SetPrefMapMode(aMapMode); + Size aSize; + aSerializer.readSize(aSize); + rMetaFile.SetPrefSize(aSize); + mrStream.ReadUInt32(nCount); + + pCompat.reset(); // destructor writes stuff into the header + + std::unique_ptr<ImplMetaReadData> xReadData; + if (!pData) + { + xReadData.reset(new ImplMetaReadData); + pData = xReadData.get(); + } + DepthGuard aDepthGuard(*pData, mrStream); + + if (aDepthGuard.TooDeep()) + throw std::runtime_error("too much recursion"); + + for (sal_uInt32 nAction = 0; (nAction < nCount) && !mrStream.eof(); nAction++) + { + rtl::Reference<MetaAction> pAction = MetaActionHandler(pData); + if (pAction) + { + if (pAction->GetType() == MetaActionType::COMMENT) + { + MetaCommentAction* pCommentAct + = static_cast<MetaCommentAction*>(pAction.get()); + + if (pCommentAct->GetComment() == "EMF_PLUS") + rMetaFile.UseCanvas(true); + } + rMetaFile.AddAction(pAction); + } + } + } + else + { + mrStream.Seek(nStmPos); + SVMConverter(mrStream, rMetaFile); + } + } + catch (...) + { + SAL_WARN("vcl", "GDIMetaFile exception during load"); + mrStream.SetError(SVSTREAM_FILEFORMAT_ERROR); + }; + + // check for errors + if (mrStream.GetError()) + { + rMetaFile.Clear(); + mrStream.Seek(nStmPos); + } + + mrStream.SetEndian(nOldFormat); + return mrStream; +} + +rtl::Reference<MetaAction> SvmReader::MetaActionHandler(ImplMetaReadData* pData) +{ + rtl::Reference<MetaAction> pAction; + sal_uInt16 nTmp = 0; + mrStream.ReadUInt16(nTmp); + MetaActionType nType = static_cast<MetaActionType>(nTmp); + + switch (nType) + { + case MetaActionType::NONE: + return DefaultHandler(); + case MetaActionType::PIXEL: + return PixelHandler(); + case MetaActionType::POINT: + return PointHandler(); + case MetaActionType::LINE: + return LineHandler(); + case MetaActionType::RECT: + return RectHandler(); + case MetaActionType::ROUNDRECT: + return RoundRectHandler(); + case MetaActionType::ELLIPSE: + return EllipseHandler(); + case MetaActionType::ARC: + return ArcHandler(); + case MetaActionType::PIE: + return PieHandler(); + case MetaActionType::CHORD: + return ChordHandler(); + case MetaActionType::POLYLINE: + return PolyLineHandler(); + case MetaActionType::POLYGON: + return PolygonHandler(); + case MetaActionType::POLYPOLYGON: + return PolyPolygonHandler(); + case MetaActionType::TEXT: + return TextHandler(pData); + case MetaActionType::TEXTARRAY: + return TextArrayHandler(pData); + case MetaActionType::STRETCHTEXT: + return StretchTextHandler(pData); + case MetaActionType::TEXTRECT: + return TextRectHandler(pData); + case MetaActionType::TEXTLINE: + return TextLineHandler(); + case MetaActionType::BMP: + return BmpHandler(); + case MetaActionType::BMPSCALE: + return BmpScaleHandler(); + case MetaActionType::BMPSCALEPART: + return BmpScalePartHandler(); + case MetaActionType::BMPEX: + return BmpExHandler(); + case MetaActionType::BMPEXSCALE: + return BmpExScaleHandler(); + case MetaActionType::BMPEXSCALEPART: + return BmpExScalePartHandler(); + case MetaActionType::MASK: + return MaskHandler(); + case MetaActionType::MASKSCALE: + return MaskScaleHandler(); + case MetaActionType::MASKSCALEPART: + return MaskScalePartHandler(); + case MetaActionType::GRADIENT: + return GradientHandler(); + case MetaActionType::GRADIENTEX: + return GradientExHandler(); + case MetaActionType::HATCH: + return HatchHandler(); + case MetaActionType::WALLPAPER: + return WallpaperHandler(); + case MetaActionType::CLIPREGION: + return ClipRegionHandler(); + case MetaActionType::ISECTRECTCLIPREGION: + return ISectRectClipRegionHandler(); + case MetaActionType::ISECTREGIONCLIPREGION: + return ISectRegionClipRegionHandler(); + case MetaActionType::MOVECLIPREGION: + return MoveClipRegionHandler(); + case MetaActionType::LINECOLOR: + return LineColorHandler(); + case MetaActionType::FILLCOLOR: + return FillColorHandler(); + case MetaActionType::TEXTCOLOR: + return TextColorHandler(); + case MetaActionType::TEXTFILLCOLOR: + return TextFillColorHandler(); + case MetaActionType::TEXTLINECOLOR: + return TextLineColorHandler(); + case MetaActionType::OVERLINECOLOR: + return OverlineColorHandler(); + case MetaActionType::TEXTALIGN: + return TextAlignHandler(); + case MetaActionType::MAPMODE: + return MapModeHandler(); + case MetaActionType::FONT: + return FontHandler(pData); + case MetaActionType::PUSH: + return PushHandler(); + case MetaActionType::POP: + return PopHandler(); + case MetaActionType::RASTEROP: + return RasterOpHandler(); + case MetaActionType::Transparent: + return TransparentHandler(); + case MetaActionType::FLOATTRANSPARENT: + return FloatTransparentHandler(pData); + case MetaActionType::EPS: + return EPSHandler(); + case MetaActionType::REFPOINT: + return RefPointHandler(); + case MetaActionType::COMMENT: + return CommentHandler(); + case MetaActionType::LAYOUTMODE: + return LayoutModeHandler(); + case MetaActionType::TEXTLANGUAGE: + return TextLanguageHandler(); + + default: + { + VersionCompatRead aCompat(mrStream); + } + break; + } + + return pAction; +} + +void SvmReader::ReadColor(Color& rColor) +{ + sal_uInt32 nTmp(0); + mrStream.ReadUInt32(nTmp); + rColor = ::Color(ColorTransparency, nTmp); +} + +rtl::Reference<MetaAction> SvmReader::LineColorHandler() +{ + rtl::Reference<MetaLineColorAction> pAction(new MetaLineColorAction); + + VersionCompatRead aCompat(mrStream); + Color aColor; + ReadColor(aColor); + bool aBool(false); + mrStream.ReadCharAsBool(aBool); + + pAction->SetSetting(aBool); + pAction->SetColor(aColor); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::FillColorHandler() +{ + rtl::Reference<MetaFillColorAction> pAction(new MetaFillColorAction); + + VersionCompatRead aCompat(mrStream); + + Color aColor; + ReadColor(aColor); + bool aBool(false); + mrStream.ReadCharAsBool(aBool); + + pAction->SetColor(aColor); + pAction->SetSetting(aBool); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::RectHandler() +{ + rtl::Reference<MetaRectAction> pAction(new MetaRectAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + pAction->SetRect(aRectangle); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PointHandler() +{ + rtl::Reference<MetaPointAction> pAction(new MetaPointAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPoint; + aSerializer.readPoint(aPoint); + pAction->SetPoint(aPoint); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PixelHandler() +{ + rtl::Reference<MetaPixelAction> pAction(new MetaPixelAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPoint; + aSerializer.readPoint(aPoint); + Color aColor; + ReadColor(aColor); + + pAction->SetPoint(aPoint); + pAction->SetColor(aColor); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::LineHandler() +{ + rtl::Reference<MetaLineAction> pAction(new MetaLineAction); + + VersionCompatRead aCompat(mrStream); + + // Version 1 + TypeSerializer aSerializer(mrStream); + Point aPoint; + Point aEndPoint; + aSerializer.readPoint(aPoint); + aSerializer.readPoint(aEndPoint); + + pAction->SetStartPoint(aPoint); + pAction->SetEndPoint(aEndPoint); + + // Version 2 + if (aCompat.GetVersion() >= 2) + { + LineInfo aLineInfo; + ReadLineInfo(mrStream, aLineInfo); + pAction->SetLineInfo(aLineInfo); + } + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::RoundRectHandler() +{ + rtl::Reference<MetaRoundRectAction> pAction(new MetaRoundRectAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + sal_uInt32 HorzRound(0); + sal_uInt32 VertRound(0); + mrStream.ReadUInt32(HorzRound).ReadUInt32(VertRound); + + pAction->SetRect(aRectangle); + pAction->SetHorzRound(HorzRound); + pAction->SetVertRound(VertRound); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::EllipseHandler() +{ + rtl::Reference<MetaEllipseAction> pAction(new MetaEllipseAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + + pAction->SetRect(aRectangle); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::ArcHandler() +{ + rtl::Reference<MetaArcAction> pAction(new MetaArcAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + Point aPoint; + aSerializer.readPoint(aPoint); + Point aEndPoint; + aSerializer.readPoint(aEndPoint); + + pAction->SetRect(aRectangle); + pAction->SetStartPoint(aPoint); + pAction->SetEndPoint(aEndPoint); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PieHandler() +{ + rtl::Reference<MetaPieAction> pAction(new MetaPieAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + Point aPoint; + aSerializer.readPoint(aPoint); + Point aEndPoint; + aSerializer.readPoint(aEndPoint); + + pAction->SetRect(aRectangle); + pAction->SetStartPoint(aPoint); + pAction->SetEndPoint(aEndPoint); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::ChordHandler() +{ + rtl::Reference<MetaChordAction> pAction(new MetaChordAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRectangle; + aSerializer.readRectangle(aRectangle); + Point aPoint; + aSerializer.readPoint(aPoint); + Point aEndPoint; + aSerializer.readPoint(aEndPoint); + + pAction->SetRect(aRectangle); + pAction->SetStartPoint(aPoint); + pAction->SetEndPoint(aEndPoint); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PolyLineHandler() +{ + rtl::Reference<MetaPolyLineAction> pAction(new MetaPolyLineAction); + + VersionCompatRead aCompat(mrStream); + + // Version 1 + tools::Polygon aPolygon; + ReadPolygon(mrStream, aPolygon); + + // Version 2 + if (aCompat.GetVersion() >= 2) + { + LineInfo aLineInfo; + ReadLineInfo(mrStream, aLineInfo); + pAction->SetLineInfo(aLineInfo); + } + if (aCompat.GetVersion() >= 3) + { + sal_uInt8 bHasPolyFlags(0); + mrStream.ReadUChar(bHasPolyFlags); + if (bHasPolyFlags) + aPolygon.Read(mrStream); + } + pAction->SetPolygon(aPolygon); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PolygonHandler() +{ + rtl::Reference<MetaPolygonAction> pAction(new MetaPolygonAction); + + VersionCompatRead aCompat(mrStream); + + tools::Polygon aPolygon; + ReadPolygon(mrStream, aPolygon); // Version 1 + + if (aCompat.GetVersion() >= 2) // Version 2 + { + sal_uInt8 bHasPolyFlags(0); + mrStream.ReadUChar(bHasPolyFlags); + if (bHasPolyFlags) + aPolygon.Read(mrStream); + } + + pAction->SetPolygon(aPolygon); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PolyPolygonHandler() +{ + rtl::Reference<MetaPolyPolygonAction> pAction(new MetaPolyPolygonAction); + + VersionCompatRead aCompat(mrStream); + tools::PolyPolygon aPolyPolygon; + ReadPolyPolygon(mrStream, aPolyPolygon); // Version 1 + + if (aCompat.GetVersion() < 2) // Version 2 + { + pAction->SetPolyPolygon(aPolyPolygon); + return pAction; + } + + sal_uInt16 nNumberOfComplexPolygons(0); + mrStream.ReadUInt16(nNumberOfComplexPolygons); + const size_t nMinRecordSize = sizeof(sal_uInt16); + const size_t nMaxRecords = mrStream.remainingSize() / nMinRecordSize; + if (nNumberOfComplexPolygons > nMaxRecords) + { + SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords << " max possible entries, but " + << nNumberOfComplexPolygons + << " claimed, truncating"); + nNumberOfComplexPolygons = nMaxRecords; + } + for (sal_uInt16 i = 0; i < nNumberOfComplexPolygons; ++i) + { + sal_uInt16 nIndex(0); + mrStream.ReadUInt16(nIndex); + tools::Polygon aPoly; + aPoly.Read(mrStream); + if (nIndex >= aPolyPolygon.Count()) + { + SAL_WARN("vcl.gdi", "svm contains polygon index " << nIndex + << " outside possible range " + << aPolyPolygon.Count()); + continue; + } + aPolyPolygon.Replace(aPoly, nIndex); + } + + pAction->SetPolyPolygon(aPolyPolygon); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextHandler(const ImplMetaReadData* pData) +{ + rtl::Reference<MetaTextAction> pAction(new MetaTextAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPoint; + aSerializer.readPoint(aPoint); + OUString aStr = mrStream.ReadUniOrByteString(pData->meActualCharSet); + sal_uInt16 nTmpIndex(0); + mrStream.ReadUInt16(nTmpIndex); + sal_uInt16 nTmpLen(0); + mrStream.ReadUInt16(nTmpLen); + + pAction->SetPoint(aPoint); + + if (aCompat.GetVersion() >= 2) // Version 2 + aStr = read_uInt16_lenPrefixed_uInt16s_ToOUString(mrStream); + + if (nTmpIndex > aStr.getLength()) + { + SAL_WARN("vcl.gdi", "inconsistent offset"); + nTmpIndex = aStr.getLength(); + } + + if (nTmpLen > aStr.getLength() - nTmpIndex) + { + SAL_WARN("vcl.gdi", "inconsistent len"); + nTmpLen = aStr.getLength() - nTmpIndex; + } + + pAction->SetIndex(nTmpIndex); + pAction->SetLen(nTmpLen); + + pAction->SetText(aStr); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextArrayHandler(const ImplMetaReadData* pData) +{ + rtl::Reference<MetaTextArrayAction> pAction(new MetaTextArrayAction); + + std::vector<sal_Int32> aArray; + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPoint; + aSerializer.readPoint(aPoint); + pAction->SetPoint(aPoint); + + OUString aStr = mrStream.ReadUniOrByteString(pData->meActualCharSet); + pAction->SetText(aStr); + + sal_uInt16 nTmpIndex(0); + mrStream.ReadUInt16(nTmpIndex); + + sal_uInt16 nTmpLen(0); + mrStream.ReadUInt16(nTmpLen); + + sal_Int32 nAryLen(0); + mrStream.ReadInt32(nAryLen); + + if (nTmpLen > aStr.getLength() - nTmpIndex) + { + SAL_WARN("vcl.gdi", "inconsistent offset and len"); + pAction->SetIndex(0); + pAction->SetLen(aStr.getLength()); + return pAction; + } + + pAction->SetIndex(nTmpIndex); + pAction->SetLen(nTmpLen); + + if (nAryLen) + { + // #i9762#, #106172# Ensure that DX array is at least mnLen entries long + if (nTmpLen >= nAryLen) + { + try + { + aArray.resize(nTmpLen); + sal_Int32 i; + sal_Int32 val(0); + for (i = 0; i < nAryLen; i++) + { + mrStream.ReadInt32(val); + aArray[i] = val; + } + // #106172# setup remainder + for (; i < nTmpLen; i++) + aArray[i] = 0; + } + catch (std::bad_alloc&) + { + } + } + else + { + return pAction; + } + } + + if (aCompat.GetVersion() >= 2) // Version 2 + { + aStr = read_uInt16_lenPrefixed_uInt16s_ToOUString(mrStream); + pAction->SetText(aStr); + + if (nTmpLen > aStr.getLength() - nTmpIndex) + { + SAL_WARN("vcl.gdi", "inconsistent offset and len"); + pAction->SetIndex(0); + pAction->SetLen(aStr.getLength()); + aArray.clear(); + } + } + + if (!aArray.empty()) + pAction->SetDXArray(std::move(aArray)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::StretchTextHandler(const ImplMetaReadData* pData) +{ + rtl::Reference<MetaStretchTextAction> pAction(new MetaStretchTextAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPoint; + aSerializer.readPoint(aPoint); + OUString aStr = mrStream.ReadUniOrByteString(pData->meActualCharSet); + sal_uInt32 nTmpWidth(0); + mrStream.ReadUInt32(nTmpWidth); + sal_uInt16 nTmpIndex(0); + mrStream.ReadUInt16(nTmpIndex); + sal_uInt16 nTmpLen(0); + mrStream.ReadUInt16(nTmpLen); + + pAction->SetPoint(aPoint); + pAction->SetWidth(nTmpWidth); + + if (aCompat.GetVersion() >= 2) // Version 2 + aStr = read_uInt16_lenPrefixed_uInt16s_ToOUString(mrStream); + + if (nTmpIndex > aStr.getLength()) + { + SAL_WARN("vcl.gdi", "inconsistent offset"); + nTmpIndex = aStr.getLength(); + } + + if (nTmpLen > aStr.getLength() - nTmpIndex) + { + SAL_WARN("vcl.gdi", "inconsistent len"); + nTmpLen = aStr.getLength() - nTmpIndex; + } + + pAction->SetIndex(nTmpIndex); + pAction->SetLen(nTmpLen); + + pAction->SetText(aStr); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextRectHandler(const ImplMetaReadData* pData) +{ + rtl::Reference<MetaTextRectAction> pAction(new MetaTextRectAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRect; + aSerializer.readRectangle(aRect); + OUString aStr = mrStream.ReadUniOrByteString(pData->meActualCharSet); + sal_uInt16 nTmp(0); + mrStream.ReadUInt16(nTmp); + + pAction->SetRect(aRect); + pAction->SetStyle(static_cast<DrawTextFlags>(nTmp)); + + if (aCompat.GetVersion() >= 2) // Version 2 + aStr = read_uInt16_lenPrefixed_uInt16s_ToOUString(mrStream); + + pAction->SetText(aStr); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextLineHandler() +{ + rtl::Reference<MetaTextLineAction> pAction(new MetaTextLineAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aPos; + aSerializer.readPoint(aPos); + sal_Int32 nTempWidth(0); + mrStream.ReadInt32(nTempWidth); + + pAction->SetStartPoint(aPos); + pAction->SetWidth(nTempWidth); + + sal_uInt32 nTempStrikeout(0); + mrStream.ReadUInt32(nTempStrikeout); + sal_uInt32 nTempUnderline(0); + mrStream.ReadUInt32(nTempUnderline); + + pAction->SetStrikeout(static_cast<FontStrikeout>(nTempStrikeout & SAL_MAX_ENUM)); + pAction->SetUnderline(static_cast<FontLineStyle>(nTempUnderline & SAL_MAX_ENUM)); + + if (aCompat.GetVersion() >= 2) + { + sal_uInt32 nTempOverline(0); + mrStream.ReadUInt32(nTempOverline); + pAction->SetOverline(static_cast<FontLineStyle>(nTempOverline & SAL_MAX_ENUM)); + } + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::BmpHandler() +{ + rtl::Reference<MetaBmpAction> pAction(new MetaBmpAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + pAction->SetBitmap(aBmp); + pAction->SetPoint(aPoint); + + return pAction; +} + +namespace +{ +void sanitizeNegativeSizeDimensions(Size& rSize) +{ + if (rSize.Width() < 0) + { + SAL_WARN("vcl.gdi", "sanitizeNegativeSizeDimensions: negative width"); + rSize.setWidth(0); + } + + if (rSize.Height() < 0) + { + SAL_WARN("vcl.gdi", "sanitizeNegativeSizeDimensions: negative height"); + rSize.setHeight(0); + } +} +} + +rtl::Reference<MetaAction> SvmReader::BmpScaleHandler() +{ + rtl::Reference<MetaBmpScaleAction> pAction(new MetaBmpScaleAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + Size aSz; + aSerializer.readSize(aSz); + sanitizeNegativeSizeDimensions(aSz); + + pAction->SetBitmap(aBmp); + pAction->SetPoint(aPoint); + pAction->SetSize(aSz); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::BmpScalePartHandler() +{ + rtl::Reference<MetaBmpScalePartAction> pAction(new MetaBmpScalePartAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + TypeSerializer aSerializer(mrStream); + Point aDestPoint; + aSerializer.readPoint(aDestPoint); + Size aDestSize; + aSerializer.readSize(aDestSize); + Point aSrcPoint; + aSerializer.readPoint(aSrcPoint); + Size aSrcSize; + aSerializer.readSize(aSrcSize); + + pAction->SetBitmap(aBmp); + pAction->SetDestPoint(aDestPoint); + pAction->SetDestSize(aDestSize); + pAction->SetSrcPoint(aSrcPoint); + pAction->SetSrcSize(aSrcSize); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::BmpExHandler() +{ + rtl::Reference<MetaBmpExAction> pAction(new MetaBmpExAction); + + VersionCompatRead aCompat(mrStream); + BitmapEx aBmpEx; + ReadDIBBitmapEx(aBmpEx, mrStream); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + pAction->SetPoint(aPoint); + pAction->SetBitmapEx(aBmpEx); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::BmpExScaleHandler() +{ + rtl::Reference<MetaBmpExScaleAction> pAction(new MetaBmpExScaleAction); + + VersionCompatRead aCompat(mrStream); + BitmapEx aBmpEx; + ReadDIBBitmapEx(aBmpEx, mrStream); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + Size aSize; + aSerializer.readSize(aSize); + sanitizeNegativeSizeDimensions(aSize); + + pAction->SetBitmapEx(aBmpEx); + pAction->SetPoint(aPoint); + pAction->SetSize(aSize); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::BmpExScalePartHandler() +{ + rtl::Reference<MetaBmpExScalePartAction> pAction(new MetaBmpExScalePartAction); + + VersionCompatRead aCompat(mrStream); + BitmapEx aBmpEx; + ReadDIBBitmapEx(aBmpEx, mrStream); + TypeSerializer aSerializer(mrStream); + Point aDstPoint; + aSerializer.readPoint(aDstPoint); + Size aDstSize; + aSerializer.readSize(aDstSize); + Point aSrcPoint; + aSerializer.readPoint(aSrcPoint); + Size aSrcSize; + aSerializer.readSize(aSrcSize); + + pAction->SetBitmapEx(aBmpEx); + pAction->SetDestPoint(aDstPoint); + pAction->SetDestSize(aDstSize); + pAction->SetSrcPoint(aSrcPoint); + pAction->SetSrcSize(aSrcSize); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::MaskHandler() +{ + rtl::Reference<MetaMaskAction> pAction(new MetaMaskAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + pAction->SetBitmap(aBmp); + pAction->SetPoint(aPoint); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::MaskScaleHandler() +{ + rtl::Reference<MetaMaskScaleAction> pAction(new MetaMaskScaleAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + Size aSize; + aSerializer.readSize(aSize); + + pAction->SetBitmap(aBmp); + pAction->SetPoint(aPoint); + pAction->SetSize(aSize); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::MaskScalePartHandler() +{ + rtl::Reference<MetaMaskScalePartAction> pAction(new MetaMaskScalePartAction); + + VersionCompatRead aCompat(mrStream); + Bitmap aBmp; + ReadDIB(aBmp, mrStream, true); + Color aColor; + ReadColor(aColor); + TypeSerializer aSerializer(mrStream); + Point aDstPt; + aSerializer.readPoint(aDstPt); + Size aDstSz; + aSerializer.readSize(aDstSz); + Point aSrcPt; + aSerializer.readPoint(aSrcPt); + Size aSrcSz; + aSerializer.readSize(aSrcSz); + + pAction->SetBitmap(aBmp); + pAction->SetColor(aColor); + pAction->SetDestPoint(aDstPt); + pAction->SetDestSize(aDstSz); + pAction->SetSrcPoint(aSrcPt); + pAction->SetSrcSize(aSrcSz); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::GradientHandler() +{ + rtl::Reference<MetaGradientAction> pAction(new MetaGradientAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + tools::Rectangle aRect; + aSerializer.readRectangle(aRect); + Gradient aGradient; + aSerializer.readGradient(aGradient); + + pAction->SetRect(aRect); + pAction->SetGradient(aGradient); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::GradientExHandler() +{ + rtl::Reference<MetaGradientExAction> pAction(new MetaGradientExAction); + + VersionCompatRead aCompat(mrStream); + tools::PolyPolygon aPolyPoly; + ReadPolyPolygon(mrStream, aPolyPoly); + TypeSerializer aSerializer(mrStream); + Gradient aGradient; + aSerializer.readGradient(aGradient); + + pAction->SetGradient(aGradient); + pAction->SetPolyPolygon(aPolyPoly); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::HatchHandler() +{ + rtl::Reference<MetaHatchAction> pAction(new MetaHatchAction); + + VersionCompatRead aCompat(mrStream); + tools::PolyPolygon aPolyPoly; + ReadPolyPolygon(mrStream, aPolyPoly); + Hatch aHatch; + ReadHatch(mrStream, aHatch); + + pAction->SetPolyPolygon(aPolyPoly); + pAction->SetHatch(aHatch); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::WallpaperHandler() +{ + rtl::Reference<MetaWallpaperAction> pAction(new MetaWallpaperAction); + + VersionCompatRead aCompat(mrStream); + Wallpaper aWallpaper; + ReadWallpaper(mrStream, aWallpaper); + + pAction->SetWallpaper(aWallpaper); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::ClipRegionHandler() +{ + rtl::Reference<MetaClipRegionAction> pAction(new MetaClipRegionAction); + + VersionCompatRead aCompat(mrStream); + vcl::Region aRegion; + ReadRegion(mrStream, aRegion); + bool aClip(false); + mrStream.ReadCharAsBool(aClip); + + pAction->SetRegion(aRegion); + pAction->SetClipping(aClip); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::ISectRectClipRegionHandler() +{ + rtl::Reference<MetaISectRectClipRegionAction> pAction(new MetaISectRectClipRegionAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + tools::Rectangle aRect; + aSerializer.readRectangle(aRect); + + pAction->SetRect(aRect); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::ISectRegionClipRegionHandler() +{ + rtl::Reference<MetaISectRegionClipRegionAction> pAction(new MetaISectRegionClipRegionAction); + + VersionCompatRead aCompat(mrStream); + vcl::Region aRegion; + ReadRegion(mrStream, aRegion); + pAction->SetRegion(aRegion); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::MoveClipRegionHandler() +{ + rtl::Reference<MetaMoveClipRegionAction> pAction(new MetaMoveClipRegionAction); + + VersionCompatRead aCompat(mrStream); + sal_Int32 nTmpHM(0), nTmpVM(0); + mrStream.ReadInt32(nTmpHM).ReadInt32(nTmpVM); + + pAction->SetHorzMove(nTmpHM); + pAction->SetVertMove(nTmpVM); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextColorHandler() +{ + rtl::Reference<MetaTextColorAction> pAction(new MetaTextColorAction); + + VersionCompatRead aCompat(mrStream); + Color aColor; + ReadColor(aColor); + + pAction->SetColor(aColor); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextFillColorHandler() +{ + rtl::Reference<MetaTextFillColorAction> pAction(new MetaTextFillColorAction); + + VersionCompatRead aCompat(mrStream); + Color aColor; + ReadColor(aColor); + bool bSet(false); + mrStream.ReadCharAsBool(bSet); + + pAction->SetColor(aColor); + pAction->SetSetting(bSet); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextLineColorHandler() +{ + rtl::Reference<MetaTextLineColorAction> pAction(new MetaTextLineColorAction); + + VersionCompatRead aCompat(mrStream); + Color aColor; + ReadColor(aColor); + bool bSet(false); + mrStream.ReadCharAsBool(bSet); + + pAction->SetColor(aColor); + pAction->SetSetting(bSet); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::OverlineColorHandler() +{ + rtl::Reference<MetaOverlineColorAction> pAction(new MetaOverlineColorAction); + + VersionCompatRead aCompat(mrStream); + Color aColor; + ReadColor(aColor); + bool bSet(false); + mrStream.ReadCharAsBool(bSet); + + pAction->SetColor(aColor); + pAction->SetSetting(bSet); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextAlignHandler() +{ + rtl::Reference<MetaTextAlignAction> pAction(new MetaTextAlignAction); + + VersionCompatRead aCompat(mrStream); + sal_uInt16 nTmp16(0); + mrStream.ReadUInt16(nTmp16); + + pAction->SetTextAlign(static_cast<TextAlign>(nTmp16)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::MapModeHandler() +{ + rtl::Reference<MetaMapModeAction> pAction(new MetaMapModeAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + MapMode aMapMode; + aSerializer.readMapMode(aMapMode); + + pAction->SetMapMode(aMapMode); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::FontHandler(ImplMetaReadData* pData) +{ + rtl::Reference<MetaFontAction> pAction(new MetaFontAction); + + VersionCompatRead aCompat(mrStream); + vcl::Font aFont; + ReadFont(mrStream, aFont); + pData->meActualCharSet = aFont.GetCharSet(); + if (pData->meActualCharSet == RTL_TEXTENCODING_DONTKNOW) + pData->meActualCharSet = osl_getThreadTextEncoding(); + + pAction->SetFont(aFont); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PushHandler() +{ + rtl::Reference<MetaPushAction> pAction(new MetaPushAction); + + VersionCompatRead aCompat(mrStream); + sal_uInt16 nTmp(0); + mrStream.ReadUInt16(nTmp); + + pAction->SetPushFlags(static_cast<vcl::PushFlags>(nTmp)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::PopHandler() +{ + rtl::Reference<MetaPopAction> pAction(new MetaPopAction); + + VersionCompatRead aCompat(mrStream); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::RasterOpHandler() +{ + rtl::Reference<MetaRasterOpAction> pAction(new MetaRasterOpAction); + + sal_uInt16 nTmp16(0); + + VersionCompatRead aCompat(mrStream); + mrStream.ReadUInt16(nTmp16); + + pAction->SetRasterOp(static_cast<RasterOp>(nTmp16)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TransparentHandler() +{ + rtl::Reference<MetaTransparentAction> pAction(new MetaTransparentAction); + + VersionCompatRead aCompat(mrStream); + tools::PolyPolygon aPolyPoly; + ReadPolyPolygon(mrStream, aPolyPoly); + sal_uInt16 nTransPercent(0); + mrStream.ReadUInt16(nTransPercent); + + pAction->SetPolyPolygon(aPolyPoly); + pAction->SetTransparence(nTransPercent); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::FloatTransparentHandler(ImplMetaReadData* pData) +{ + rtl::Reference<MetaFloatTransparentAction> pAction(new MetaFloatTransparentAction); + + VersionCompatRead aCompat(mrStream); + GDIMetaFile aMtf; + SvmReader aReader(mrStream); + aReader.Read(aMtf, pData); + TypeSerializer aSerializer(mrStream); + Point aPoint; + aSerializer.readPoint(aPoint); + + Size aSize; + aSerializer.readSize(aSize); + sanitizeNegativeSizeDimensions(aSize); + + Gradient aGradient; + aSerializer.readGradient(aGradient); + + pAction->SetGDIMetaFile(aMtf); + pAction->SetPoint(aPoint); + pAction->SetSize(aSize); + pAction->SetGradient(aGradient); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::EPSHandler() +{ + rtl::Reference<MetaEPSAction> pAction(new MetaEPSAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + GfxLink aGfxLink; + aSerializer.readGfxLink(aGfxLink); + Point aPoint; + aSerializer.readPoint(aPoint); + Size aSize; + aSerializer.readSize(aSize); + GDIMetaFile aSubst; + Read(aSubst); + + pAction->SetLink(aGfxLink); + pAction->SetPoint(aPoint); + pAction->SetSize(aSize); + pAction->SetSubstitute(aSubst); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::RefPointHandler() +{ + rtl::Reference<MetaRefPointAction> pAction(new MetaRefPointAction); + + VersionCompatRead aCompat(mrStream); + TypeSerializer aSerializer(mrStream); + + Point aRefPoint; + aSerializer.readPoint(aRefPoint); + bool bSet(false); + mrStream.ReadCharAsBool(bSet); + + pAction->SetRefPoint(aRefPoint); + pAction->SetSetting(bSet); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::CommentHandler() +{ + rtl::Reference<MetaCommentAction> pAction(new MetaCommentAction); + + VersionCompatRead aCompat(mrStream); + OString aComment; + aComment = read_uInt16_lenPrefixed_uInt8s_ToOString(mrStream); + sal_Int32 nValue(0); + sal_uInt32 nDataSize(0); + mrStream.ReadInt32(nValue).ReadUInt32(nDataSize); + + if (nDataSize > mrStream.remainingSize()) + { + SAL_WARN("vcl.gdi", "Parsing error: " << mrStream.remainingSize() << " available data, but " + << nDataSize << " claimed, truncating"); + nDataSize = mrStream.remainingSize(); + } + + SAL_INFO("vcl.gdi", "MetaCommentAction::Read " << aComment); + + std::unique_ptr<sal_uInt8[]> pData; + pData.reset(); + + if (nDataSize) + { + pData.reset(new sal_uInt8[nDataSize]); + mrStream.ReadBytes(pData.get(), nDataSize); + } + + pAction->SetComment(aComment); + pAction->SetDataSize(nDataSize); + pAction->SetValue(nValue); + pAction->SetData(pData.get(), nDataSize); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::LayoutModeHandler() +{ + rtl::Reference<MetaLayoutModeAction> pAction(new MetaLayoutModeAction); + + VersionCompatRead aCompat(mrStream); + sal_uInt32 tmp(0); + mrStream.ReadUInt32(tmp); + + pAction->SetLayoutMode(static_cast<vcl::text::ComplexTextLayoutFlags>(tmp)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::TextLanguageHandler() +{ + rtl::Reference<MetaTextLanguageAction> pAction(new MetaTextLanguageAction); + + VersionCompatRead aCompat(mrStream); + sal_uInt16 nTmp = 0; + mrStream.ReadUInt16(nTmp); + + pAction->SetTextLanguage(static_cast<LanguageType>(nTmp)); + + return pAction; +} + +rtl::Reference<MetaAction> SvmReader::DefaultHandler() +{ + return rtl::Reference<MetaAction>(new MetaAction); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |