[Libreoffice-commits] core.git: Branch 'feature/emfplusprimitiveparser' - emfio/inc emfio/Library_emfio.mk emfio/source include/vcl
Armin Le Grand
Armin.Le.Grand at cib.de
Thu Jun 15 14:35:40 UTC 2017
emfio/Library_emfio.mk | 8
emfio/inc/emfreader.hxx | 55
emfio/inc/mtftools.hxx | 667 ++++++++++
emfio/inc/wmfreader.hxx | 106 +
emfio/source/emfuno/xemfparser.cxx | 101 -
emfio/source/reader/emfreader.cxx | 1941 +++++++++++++++++++++++++++++++
emfio/source/reader/mtftools.cxx | 2283 +++++++++++++++++++++++++++++++++++++
emfio/source/reader/wmfreader.cxx | 1846 +++++++++++++++++++++++++++++
include/vcl/dibtools.hxx | 3
9 files changed, 6958 insertions(+), 52 deletions(-)
New commits:
commit c81257a117f13195bde5548116bb6d5edfc1a720
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Jun 15 16:35:31 2017 +0200
emfplus: add rough version of local reader
Complete redevelopent is too expensive, start with
adding a copy of the existing vcl importer which
will in the next steps be adapted to import primitives
instead of MetaFile(Actions). Adapted namespace, made
compile and added sample code to roughly use it
Change-Id: I79e7ea0d78099fbbe18e2a595457b2ab353f58ea
diff --git a/emfio/Library_emfio.mk b/emfio/Library_emfio.mk
index e9a14249271a..ff209f5da3bf 100644
--- a/emfio/Library_emfio.mk
+++ b/emfio/Library_emfio.mk
@@ -25,6 +25,10 @@ $(eval $(call gb_Library_set_include,emfio,\
-I$(SRCDIR)/emfio/inc \
))
+$(eval $(call gb_Library_use_custom_headers,emfio,\
+ officecfg/registry \
+))
+
$(eval $(call gb_Library_use_external,emfio,boost_headers))
$(eval $(call gb_Library_set_precompiled_header,emfio,$(SRCDIR)/emfio/inc/pch/precompiled_emfio))
@@ -37,6 +41,7 @@ $(eval $(call gb_Library_use_libraries,emfio,\
cppu \
cppuhelper \
sal \
+ comphelper \
tl \
sax \
vcl \
@@ -47,6 +52,9 @@ $(eval $(call gb_Library_use_libraries,emfio,\
$(eval $(call gb_Library_add_exception_objects,emfio,\
emfio/source/emfuno/emfuno \
emfio/source/emfuno/xemfparser \
+ emfio/source/reader/mtftools \
+ emfio/source/reader/wmfreader \
+ emfio/source/reader/emfreader \
))
# vim: set noet sw=4 ts=4:
diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
new file mode 100644
index 000000000000..c4f7e17e574d
--- /dev/null
+++ b/emfio/inc/emfreader.hxx
@@ -0,0 +1,55 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_EMFREADER_HXX
+#define INCLUDED_EMFIO_INC_EMFREADER_HXX
+
+#include <mtftools.hxx>
+
+namespace emfio
+{
+ class EmfReader : public MtfTools
+ {
+ bool bRecordPath;
+ sal_Int32 nRecordCount;
+ bool bEMFPlus;
+
+ bool ReadHeader();
+ // reads and converts the rectangle
+ static tools::Rectangle ReadRectangle(sal_Int32, sal_Int32, sal_Int32, sal_Int32);
+
+ public:
+ EmfReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile, FilterConfigItem* pConfigItem = nullptr);
+ ~EmfReader();
+
+ bool ReadEnhWMF();
+ private:
+ template <class T> void ReadAndDrawPolyPolygon();
+ template <class T> void ReadAndDrawPolyLine();
+ template <class T> tools::Polygon ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints);
+ template <class T, class Drawer> void ReadAndDrawPolygon(Drawer drawer, const bool skipFirst);
+
+ tools::Rectangle ReadRectangle();
+ void ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC);
+ };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/inc/mtftools.hxx b/emfio/inc/mtftools.hxx
new file mode 100644
index 000000000000..f20925f5a147
--- /dev/null
+++ b/emfio/inc/mtftools.hxx
@@ -0,0 +1,667 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_MTFTOOLS_HXX
+#define INCLUDED_EMFIO_INC_MTFTOOLS_HXX
+
+#include <memory>
+#include <sal/config.h>
+
+//#include <vcl/graph.hxx>
+#include <basegfx/tools/b2dclipstate.hxx>
+#include <tools/poly.hxx>
+#include <vcl/font.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+//#include <vcl/bitmapaccess.hxx>
+#include <vcl/lineinfo.hxx>
+//#include <vcl/fltcall.hxx>
+#include <o3tl/make_unique.hxx>
+#include <vcl/outdevstate.hxx>
+#include <vcl/FilterConfigItem.hxx>
+
+#define ERROR 0
+#define NULLREGION 1
+#define COMPLEXREGION 3
+
+#define RGN_AND 1
+#define RGN_OR 2
+#define RGN_XOR 3
+#define RGN_DIFF 4
+#define RGN_COPY 5
+
+namespace emfio
+{
+ enum class BkMode
+ {
+ NONE = 0,
+ Transparent = 1,
+ OPAQUE = 2,
+ };
+}
+
+/* xform stuff */
+#define MWT_IDENTITY 1
+#define MWT_LEFTMULTIPLY 2
+#define MWT_RIGHTMULTIPLY 3
+#define MWT_SET 4
+
+#define ENHMETA_STOCK_OBJECT 0x80000000
+
+/* Stock Logical Objects */
+#define WHITE_BRUSH 0
+#define LTGRAY_BRUSH 1
+#define GRAY_BRUSH 2
+#define DKGRAY_BRUSH 3
+#define BLACK_BRUSH 4
+#define NULL_BRUSH 5
+#define WHITE_PEN 6
+#define BLACK_PEN 7
+#define NULL_PEN 8
+#define ANSI_FIXED_FONT 11
+#define ANSI_VAR_FONT 12
+#define SYSTEM_FIXED_FONT 16
+
+namespace emfio
+{
+ enum class WMFRasterOp {
+ NONE = 0,
+ Black = 1,
+ Not = 6,
+ XorPen = 7,
+ Nop = 11,
+ CopyPen = 13
+ };
+}
+
+/* Mapping modes */
+#define MM_TEXT 1
+#define MM_LOMETRIC 2
+#define MM_HIMETRIC 3
+#define MM_LOENGLISH 4
+#define MM_HIENGLISH 5
+#define MM_TWIPS 6
+#define MM_ISOTROPIC 7
+#define MM_ANISOTROPIC 8
+
+/* Graphics modes */
+#define GM_COMPATIBLE 1
+#define GM_ADVANCED 2
+
+/* StretchBlt() modes */
+#define BLACKONWHITE 1
+#define WHITEONBLACK 2
+#define COLORONCOLOR 3
+#define HALFTONE 4
+#define STRETCH_ANDSCANS BLACKONWHITE
+#define STRETCH_ORSCANS WHITEONBLACK
+#define STRETCH_DELETESCANS COLORONCOLOR
+
+#define LF_FACESIZE 32
+
+namespace emfio
+{
+ struct LOGFONTW
+ {
+ sal_Int32 lfHeight;
+ sal_Int32 lfWidth;
+ sal_Int32 lfEscapement;
+ sal_Int32 lfOrientation;
+ sal_Int32 lfWeight;
+ sal_uInt8 lfItalic;
+ sal_uInt8 lfUnderline;
+ sal_uInt8 lfStrikeOut;
+ sal_uInt8 lfCharSet;
+ sal_uInt8 lfOutPrecision;
+ sal_uInt8 lfClipPrecision;
+ sal_uInt8 lfQuality;
+ sal_uInt8 lfPitchAndFamily;
+ OUString alfFaceName;
+ };
+ struct WMF_EXTERNALHEADER;
+}
+
+#define TA_NOUPDATECP 0x0000
+#define TA_UPDATECP 0x0001
+#define TA_LEFT 0x0000
+#define TA_RIGHT 0x0002
+#define TA_CENTER 0x0006
+#define TA_RIGHT_CENTER (TA_RIGHT | TA_CENTER)
+#define TA_TOP 0x0000
+#define TA_BOTTOM 0x0008
+#define TA_BASELINE 0x0018
+
+#define SRCCOPY 0x00CC0020L
+#define SRCPAINT 0x00EE0086L
+#define SRCAND 0x008800C6L
+#define SRCINVERT 0x00660046L
+#define SRCERASE 0x00440328L
+#define PATCOPY 0x00F00021L
+#define PATINVERT 0x005A0049L
+#define BLACKNESS 0x00000042L
+#define WHITENESS 0x00FF0062L
+
+#define PS_SOLID 0
+#define PS_DASH 1
+#define PS_DOT 2
+#define PS_DASHDOT 3
+#define PS_DASHDOTDOT 4
+#define PS_NULL 5
+#define PS_INSIDEFRAME 6
+#define PS_STYLE_MASK 15
+
+#define PS_ENDCAP_ROUND 0x000
+#define PS_ENDCAP_SQUARE 0x100
+#define PS_ENDCAP_FLAT 0x200
+#define PS_ENDCAP_STYLE_MASK 0xF00
+
+#define PS_JOIN_ROUND 0x0000
+#define PS_JOIN_BEVEL 0x1000
+#define PS_JOIN_MITER 0x2000
+#define PS_JOIN_STYLE_MASK 0xF000
+
+#define ANSI_CHARSET 0
+#define DEFAULT_CHARSET 1
+#define SYMBOL_CHARSET 2
+#define SHIFTJIS_CHARSET 128
+#define HANGEUL_CHARSET 129
+#define GB2312_CHARSET 134
+#define CHINESEBIG5_CHARSET 136
+#define OEM_CHARSET 255
+/*WINVER >= 0x0400*/
+#define JOHAB_CHARSET 130
+#define HEBREW_CHARSET 177
+#define ARABIC_CHARSET 178
+#define GREEK_CHARSET 161
+#define TURKISH_CHARSET 162
+#define VIETNAMESE_CHARSET 163
+#define THAI_CHARSET 222
+#define EASTEUROPE_CHARSET 238
+#define RUSSIAN_CHARSET 204
+#define MAC_CHARSET 77
+#define BALTIC_CHARSET 186
+
+#define ETO_CLIPPED 0x0004
+/*WINVER >= 0x0400*/
+#define ETO_GLYPH_INDEX 0x0010
+#define ETO_RTLREADING 0x0080
+/*_WIN32_WINNT >= 0x0500*/
+#define ETO_PDY 0x2000
+
+#define DEFAULT_PITCH 0x00
+#define FIXED_PITCH 0x01
+#define VARIABLE_PITCH 0x02
+
+/* Font Families */
+#define FF_DONTCARE 0x00
+#define FF_ROMAN 0x10
+#define FF_SWISS 0x20
+#define FF_MODERN 0x30
+#define FF_SCRIPT 0x40
+#define FF_DECORATIVE 0x50
+
+#define FW_THIN 100
+#define FW_EXTRALIGHT 200
+#define FW_LIGHT 300
+#define FW_NORMAL 400
+#define FW_MEDIUM 500
+#define FW_SEMIBOLD 600
+#define FW_BOLD 700
+#define FW_EXTRABOLD 800
+#define FW_ULTRALIGHT 200
+#define FW_ULTRABOLD 800
+#define FW_BLACK 900
+
+#define BS_SOLID 0
+#define BS_NULL 1
+#define BS_HOLLOW 1
+#define BS_HATCHED 2
+#define BS_PATTERN 3
+#define BS_INDEXED 4
+#define BS_DIBPATTERN 5
+#define BS_DIBPATTERNPT 6
+#define BS_PATTERN8X8 7
+#define BS_DIBPATTERN8X8 8
+#define BS_MONOPATTERN 9
+
+
+#define RDH_RECTANGLES 1
+
+#define W_MFCOMMENT 15
+
+#define PRIVATE_ESCAPE_UNICODE 2
+
+//Scalar constants
+
+#define UNDOCUMENTED_WIN_RCL_RELATION 32
+#define MS_FIXPOINT_BITCOUNT_28_4 4
+#define HUNDREDTH_MILLIMETERS_PER_MILLIINCH 2.54
+#define MILLIINCH_PER_TWIPS 1.44
+
+//============================ WmfReader ==================================
+
+namespace emfio
+{
+ class WinMtfClipPath
+ {
+ basegfx::tools::B2DClipState maClip;
+
+ public:
+ WinMtfClipPath() : maClip() {};
+
+ void setClipPath(const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode);
+ void intersectClipRect(const tools::Rectangle& rRect);
+ void excludeClipRect(const tools::Rectangle& rRect);
+ void moveClipRegion(const Size& rSize);
+ void setDefaultClipPath();
+
+ bool isEmpty() const { return maClip.isCleared(); }
+
+ basegfx::B2DPolyPolygon getClipPath() const;
+
+ bool operator==(const WinMtfClipPath& rPath) const
+ {
+ return maClip == rPath.maClip;
+ };
+ };
+
+ class WinMtfPathObj : public tools::PolyPolygon
+ {
+ bool bClosed;
+
+ public:
+
+ WinMtfPathObj() :
+ bClosed(true)
+ {}
+
+ void Init()
+ {
+ Clear();
+ bClosed = true;
+ }
+
+ void ClosePath();
+ void AddPoint(const Point& rPoint);
+ void AddPolygon(const tools::Polygon& rPoly);
+ void AddPolyLine(const tools::Polygon& rPoly);
+ void AddPolyPolygon(const tools::PolyPolygon& rPolyPolygon);
+ };
+
+ struct GDIObj
+ {
+ virtual ~GDIObj() = default; // Polymorphic base class
+ };
+
+ struct WinMtfFontStyle : GDIObj
+ {
+ vcl::Font aFont;
+
+ explicit WinMtfFontStyle(LOGFONTW& rLogFont);
+ };
+
+ enum class WinMtfFillStyleType
+ {
+ Solid, Pattern
+ };
+
+ struct WinMtfFillStyle : GDIObj
+ {
+ Color aFillColor;
+ bool bTransparent;
+ WinMtfFillStyleType aType;
+ Bitmap aBmp;
+
+ WinMtfFillStyle()
+ : aFillColor(Color(COL_BLACK))
+ , bTransparent(false)
+ , aType(WinMtfFillStyleType::Solid)
+ {}
+
+ WinMtfFillStyle(const Color& rColor, bool bTrans = false)
+ : aFillColor(rColor)
+ , bTransparent(bTrans)
+ , aType(WinMtfFillStyleType::Solid)
+ {}
+
+ explicit WinMtfFillStyle(Bitmap& rBmp)
+ : bTransparent(false)
+ , aType(WinMtfFillStyleType::Pattern)
+ , aBmp(rBmp)
+ {}
+
+ bool operator==(const WinMtfFillStyle& rStyle)
+ {
+ return aFillColor == rStyle.aFillColor
+ && bTransparent == rStyle.bTransparent
+ && aType == rStyle.aType;
+ }
+ };
+
+ struct WinMtfLineStyle : GDIObj
+ {
+ Color aLineColor;
+ LineInfo aLineInfo;
+ bool bTransparent;
+
+ WinMtfLineStyle()
+ : aLineColor(COL_BLACK)
+ , bTransparent(false)
+ {}
+
+ WinMtfLineStyle(const Color& rColor, bool bTrans = false)
+ : aLineColor(rColor)
+ , bTransparent(bTrans)
+ {}
+
+ WinMtfLineStyle(const Color& rColor, const LineInfo& rStyle, bool bTrans)
+ : aLineColor(rColor)
+ , aLineInfo(rStyle)
+ , bTransparent(bTrans)
+ {}
+
+ bool operator==(const WinMtfLineStyle& rStyle)
+ {
+ return aLineColor == rStyle.aLineColor
+ && bTransparent == rStyle.bTransparent
+ && aLineInfo == rStyle.aLineInfo;
+ }
+ };
+
+ struct XForm
+ {
+ float eM11;
+ float eM12;
+ float eM21;
+ float eM22;
+ float eDx;
+ float eDy;
+
+ XForm()
+ : eM11(1.0f)
+ , eM12(0.0f)
+ , eM21(0.0f)
+ , eM22(1.0f)
+ , eDx(0.0f)
+ , eDy(0.0f)
+ {}
+ };
+
+ SvStream& operator >> (SvStream& rInStream, XForm& rXForm);
+
+ struct SaveStruct
+ {
+ BkMode nBkMode;
+ sal_uInt32 nMapMode, nGfxMode;
+ ComplexTextLayoutFlags nTextLayoutMode;
+ sal_Int32 nWinOrgX, nWinOrgY, nWinExtX, nWinExtY;
+ sal_Int32 nDevOrgX, nDevOrgY, nDevWidth, nDevHeight;
+
+ WinMtfLineStyle aLineStyle;
+ WinMtfFillStyle aFillStyle;
+
+ vcl::Font aFont;
+ Color aBkColor;
+ Color aTextColor;
+ sal_uInt32 nTextAlign;
+ RasterOp eRasterOp;
+
+ Point aActPos;
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+ XForm aXForm;
+
+ bool bFillStyleSelected;
+ };
+
+ struct BSaveStruct
+ {
+ BitmapEx aBmpEx;
+ tools::Rectangle aOutRect;
+ sal_uInt32 nWinRop;
+
+ BSaveStruct(const Bitmap& rBmp, const tools::Rectangle& rOutRect, sal_uInt32 nRop)
+ : aBmpEx(rBmp)
+ , aOutRect(rOutRect)
+ , nWinRop(nRop)
+ {}
+
+ BSaveStruct(const BitmapEx& rBmpEx, const tools::Rectangle& rOutRect, sal_uInt32 nRop)
+ : aBmpEx(rBmpEx)
+ , aOutRect(rOutRect)
+ , nWinRop(nRop)
+ {}
+ };
+
+ class MtfToolsWriter final
+ {
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+
+ WinMtfLineStyle maLatestLineStyle;
+ WinMtfLineStyle maLineStyle;
+ WinMtfLineStyle m_NopLineStyle;
+ WinMtfFillStyle maLatestFillStyle;
+ WinMtfFillStyle maFillStyle;
+ WinMtfFillStyle m_NopFillStyle;
+ vcl::Font maLatestFont;
+ vcl::Font maFont;
+ sal_uInt32 mnLatestTextAlign;
+ sal_uInt32 mnTextAlign;
+ Color maLatestTextColor;
+ Color maTextColor;
+ Color maLatestBkColor;
+ Color maBkColor;
+ ComplexTextLayoutFlags mnLatestTextLayoutMode;
+ ComplexTextLayoutFlags mnTextLayoutMode;
+ BkMode mnLatestBkMode;
+ BkMode mnBkMode;
+ RasterOp meLatestRasterOp;
+ RasterOp meRasterOp;
+
+ std::vector< std::unique_ptr<GDIObj> > vGDIObj;
+
+ Point maActPos;
+
+ WMFRasterOp mnRop;
+ bool mbNopMode;
+ bool mbFillStyleSelected;
+ bool mbClipNeedsUpdate;
+ bool mbComplexClip;
+
+ std::vector< std::shared_ptr<SaveStruct> > vSaveStack;
+
+ sal_uInt32 mnGfxMode;
+ sal_uInt32 mnMapMode;
+
+ XForm maXForm;
+ sal_Int32 mnDevOrgX, mnDevOrgY;
+ sal_Int32 mnDevWidth, mnDevHeight;
+ sal_Int32 mnWinOrgX, mnWinOrgY; // aktuel window origin
+ sal_Int32 mnWinExtX, mnWinExtY; // aktuel window extend
+ bool mbIsMapWinSet;
+ bool mbIsMapDevSet;
+
+ sal_Int32 mnPixX, mnPixY; // Reference Device in pixel
+ sal_Int32 mnMillX, mnMillY; // Reference Device in Mill
+ tools::Rectangle mrclFrame; // rectangle in logical units 1/100th mm
+ tools::Rectangle mrclBounds;
+
+ GDIMetaFile* mpGDIMetaFile;
+
+ void UpdateLineStyle();
+ void UpdateFillStyle();
+
+ Point ImplMap(const Point& rPt);
+ Point ImplScale(const Point& rPt);
+ Size ImplMap(const Size& rSize, bool bDoWorldTransform = true);
+ tools::Rectangle ImplMap(const tools::Rectangle& rRectangle);
+ void ImplMap(vcl::Font& rFont);
+ tools::Polygon& ImplMap(tools::Polygon& rPolygon);
+ tools::PolyPolygon& ImplMap(tools::PolyPolygon& rPolyPolygon);
+ void ImplScale(tools::Polygon& rPolygon);
+ tools::PolyPolygon& ImplScale(tools::PolyPolygon& rPolyPolygon);
+ void ImplResizeObjectArry(sal_uInt32 nNewEntry);
+ void ImplSetNonPersistentLineColorTransparenz();
+ void ImplDrawClippedPolyPolygon(const tools::PolyPolygon& rPolyPoly);
+ void ImplDrawBitmap(const Point& rPos, const Size& rSize, const BitmapEx& rBitmap);
+
+ public:
+
+ void SetDevByWin(); //Hack to set varying defaults for incompletely defined files.
+ void SetDevOrg(const Point& rPoint);
+ void SetDevOrgOffset(sal_Int32 nXAdd, sal_Int32 nYAdd);
+ void SetDevExt(const Size& rSize, bool regular = true);
+ void ScaleDevExt(double fX, double fY);
+
+ void SetWinOrg(const Point& rPoint, bool bIsEMF = false);
+ void SetWinOrgOffset(sal_Int32 nX, sal_Int32 nY);
+ void SetWinExt(const Size& rSize, bool bIsEMF = false);
+ void ScaleWinExt(double fX, double fY);
+
+ void SetrclBounds(const tools::Rectangle& rRect);
+ void SetrclFrame(const tools::Rectangle& rRect);
+ void SetRefPix(const Size& rSize);
+ void SetRefMill(const Size& rSize);
+
+ void SetMapMode(sal_uInt32 mnMapMode);
+ void SetWorldTransform(const XForm& rXForm);
+ void ModifyWorldTransform(const XForm& rXForm, sal_uInt32 nMode);
+
+ void Push();
+ void Pop();
+
+ WMFRasterOp SetRasterOp(WMFRasterOp nRasterOp);
+ void StrokeAndFillPath(bool bStroke, bool bFill);
+
+ void SetGfxMode(sal_Int32 nGfxMode) { mnGfxMode = nGfxMode; };
+ sal_Int32 GetGfxMode() const { return mnGfxMode; };
+ void SetBkMode(BkMode nMode);
+ void SetBkColor(const Color& rColor);
+ void SetTextColor(const Color& rColor);
+ void SetTextAlign(sal_uInt32 nAlign);
+
+ void CreateObject(std::unique_ptr<GDIObj> pObject);
+ void CreateObjectIndexed(sal_Int32 nIndex, std::unique_ptr<GDIObj> pObject);
+
+ void CreateObject()
+ {
+ CreateObject(o3tl::make_unique<GDIObj>());
+ }
+
+ void DeleteObject(sal_Int32 nIndex);
+ void SelectObject(sal_Int32 nIndex);
+ rtl_TextEncoding GetCharSet() { return maFont.GetCharSet(); };
+ const vcl::Font& GetFont() const { return maFont; }
+ void SetTextLayoutMode(ComplexTextLayoutFlags nLayoutMode);
+
+ void ClearPath() { aPathObj.Init(); };
+ void ClosePath() { aPathObj.ClosePath(); };
+ const tools::PolyPolygon& GetPathObj() { return aPathObj; };
+
+ void MoveTo(const Point& rPoint, bool bRecordPath = false);
+ void LineTo(const Point& rPoint, bool bRecordPath = false);
+ void DrawPixel(const Point& rSource, const Color& rColor);
+ void DrawRect(const tools::Rectangle& rRect, bool bEdge = true);
+ void DrawRoundRect(const tools::Rectangle& rRect, const Size& rSize);
+ void DrawEllipse(const tools::Rectangle& rRect);
+ void DrawArc(
+ const tools::Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle,
+ bool bDrawTo = false
+ );
+ void DrawPie(
+ const tools::Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawChord(
+ const tools::Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawPolygon(tools::Polygon& rPolygon, bool bRecordPath);
+ void DrawPolyPolygon(tools::PolyPolygon& rPolyPolygon, bool bRecordPath = false);
+ void DrawPolyLine(tools::Polygon& rPolygon,
+ bool bDrawTo = false,
+ bool bRecordPath = false
+ );
+ void DrawPolyBezier(tools::Polygon& rPolygin,
+ bool bDrawTo,
+ bool bRecordPath
+ );
+ void DrawText(Point& rPosition,
+ OUString& rString,
+ long* pDXArry = nullptr,
+ long* pDYArry = nullptr,
+ bool bRecordPath = false,
+ sal_Int32 nGraphicsMode = GM_COMPATIBLE);
+
+ void ResolveBitmapActions(std::vector<std::unique_ptr<BSaveStruct>>& rSaveList);
+
+ void IntersectClipRect(const tools::Rectangle& rRect);
+ void ExcludeClipRect(const tools::Rectangle& rRect);
+ void MoveClipRegion(const Size& rSize);
+ void SetClipPath(
+ const tools::PolyPolygon& rPolyPoly,
+ sal_Int32 nClippingMode,
+ bool bIsMapped
+ );
+ void SetDefaultClipPath();
+ void UpdateClipRegion();
+ void AddFromGDIMetaFile(GDIMetaFile& rGDIMetaFile);
+
+ void PassEMFPlus(void* pBuffer, sal_uInt32 nLength);
+ void PassEMFPlusHeaderInfo();
+
+ explicit MtfToolsWriter(GDIMetaFile& rGDIMetaFile);
+ ~MtfToolsWriter();
+ };
+
+ class MtfTools
+ {
+ protected:
+ std::unique_ptr<MtfToolsWriter> pOut;
+ SvStream* pWMF; // the WMF/EMF file to be read
+
+ sal_uInt32 nStartPos, nEndPos;
+ std::vector<std::unique_ptr<BSaveStruct>> aBmpSaveList;
+
+ FilterConfigItem* pFilterConfigItem;
+
+ css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator;
+
+ // assures aSampledBrush is the actual brush of the GDIMetaFile
+
+ Color ReadColor();
+ void Callback(sal_uInt16 nPercent);
+
+ MtfTools(
+ GDIMetaFile& rGDIMetaFile,
+ SvStream& rStreamWMF,
+ FilterConfigItem* pConfigItem
+ );
+ ~MtfTools();
+ };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/inc/wmfreader.hxx b/emfio/inc/wmfreader.hxx
new file mode 100644
index 000000000000..734becbb5886
--- /dev/null
+++ b/emfio/inc/wmfreader.hxx
@@ -0,0 +1,106 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_WMFREADER_HXX
+#define INCLUDED_EMFIO_INC_WMFREADER_HXX
+
+#include <mtftools.hxx>
+#include <tools/stream.hxx>
+
+namespace emfio
+{
+ struct WMF_EXTERNALHEADER
+ {
+ sal_uInt16 xExt;
+ sal_uInt16 yExt;
+
+ /** One of the following values:
+ <ul>
+ <li>MM_TEXT</li>
+ <li>MM_LOMETRIC</li>
+ <li>MM_HIMETRIC</li>
+ <li>MM_LOENGLISH</li>
+ <li>MM_HIENGLISH</li>
+ <li>MM_TWIPS</li>
+ <li>MM_ISOTROPIC</li>
+ <li>MM_ANISOTROPIC</li>
+ </ul>
+ If this value is 0, then no external mapmode has been defined,
+ the internal one should then be used.
+ */
+ sal_uInt16 mapMode;
+
+ WMF_EXTERNALHEADER() :
+ xExt(0),
+ yExt(0),
+ mapMode(0)
+ {
+ }
+ };
+
+ class WmfReader : public MtfTools
+ {
+ private:
+
+ sal_uInt16 nUnitsPerInch;
+ sal_uInt32 nRecSize;
+
+ // embedded EMF data
+ std::unique_ptr<SvMemoryStream> pEMFStream;
+
+ // total number of comment records containing EMF data
+ sal_uInt32 nEMFRecCount;
+
+ // number of EMF records read
+ sal_uInt32 nEMFRec;
+
+ // total size of embedded EMF data
+ sal_uInt32 nEMFSize;
+
+ sal_uInt32 nSkipActions;
+ sal_uInt32 nCurrentAction;
+
+ WMF_EXTERNALHEADER* pExternalHeader;
+
+ // reads header of the WMF-Datei
+ bool ReadHeader();
+
+ // reads parameters of the record with the functionnumber nFunction.
+ void ReadRecordParams(sal_uInt16 nFunction);
+
+ Point ReadPoint(); // reads and converts a point (first X then Y)
+ Point ReadYX(); // reads and converts a point (first Y then X)
+ tools::Rectangle ReadRectangle(); // reads and converts a rectangle
+ Size ReadYXExt();
+ void GetPlaceableBound(tools::Rectangle& rSize, SvStream* pStrm);
+
+ public:
+
+ WmfReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile,
+ FilterConfigItem* pConfigItem,
+ WMF_EXTERNALHEADER* pExtHeader = nullptr);
+
+ // read WMF file from stream and fill the GDIMetaFile
+ void ReadWMF();
+ };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx
index 3b6e9ad731fa..e532d903e047 100644
--- a/emfio/source/emfuno/xemfparser.cxx
+++ b/emfio/source/emfuno/xemfparser.cxx
@@ -37,6 +37,9 @@
#include <unotools/ucbstreamhelper.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <wmfreader.hxx>
+#include <emfreader.hxx>
+
//#include <com/sun/star/xml/sax/XParser.hpp>
//#include <com/sun/star/xml/sax/Parser.hpp>
//#include <com/sun/star/xml/sax/InputSource.hpp>
@@ -116,7 +119,7 @@ namespace emfio
if (xEmfStream.is())
{
- static bool bTestCode(true);
+ static bool bTestCode(false);
if (bTestCode)
{
@@ -168,59 +171,55 @@ namespace emfio
// new parser here
bool bBla = true;
+ // rouch check - import and conv to primitive
+ GDIMetaFile aMtf;
+ std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream(xEmfStream));
+ sal_uInt32 nMetaType(0);
+ sal_uInt32 nOrgPos = pStream->Tell();
+
+ SvStreamEndian nOrigNumberFormat = pStream->GetEndian();
+ pStream->SetEndian(SvStreamEndian::LITTLE);
+
+ pStream->Seek(0x28);
+ pStream->ReadUInt32(nMetaType);
+ pStream->Seek(nOrgPos);
+
+ if (nMetaType == 0x464d4520)
+ {
+ emfio::EmfReader(*pStream, aMtf, nullptr).ReadEnhWMF();
+ }
+ else
+ {
+ emfio::WmfReader(*pStream, aMtf, nullptr).ReadWMF();
+ }
+
+ pStream->SetEndian(nOrigNumberFormat);
+ Size aSize(aMtf.GetPrefSize());
+
+ if (aMtf.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
+ {
+ aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapUnit::Map100thMM);
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic(aSize, aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
+ }
+
+ const basegfx::B2DHomMatrix aMetafileTransform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ aSize.Width(),
+ aSize.Height()));
+
+ // force to use decomposition directly to get rid of the metafile
+ const css::uno::Sequence< css::beans::PropertyValue > aViewParameters;
+ drawinglayer::primitive2d::MetafilePrimitive2D aMetafilePrimitive2D(
+ aMetafileTransform,
+ aMtf);
+ aRetval.append(aMetafilePrimitive2D.getDecomposition(aViewParameters));
+
- // // local document handler
- // SvgDocHdl* pSvgDocHdl = new SvgDocHdl(aAbsolutePath);
- // uno::Reference< xml::sax::XDocumentHandler > xSvgDocHdl(pSvgDocHdl);
- //
- // try
- // {
- // // prepare ParserInputSrouce
- // xml::sax::InputSource myInputSource;
- // myInputSource.aInputStream = xEmfStream;
- //
- // // get parser
- // uno::Reference< xml::sax::XParser > xParser(
- // xml::sax::Parser::create(context_));
- // // fdo#60471 need to enable internal entities because
- // // certain ... popular proprietary products write SVG files
- // // that use entities to define XML namespaces.
- // uno::Reference<lang::XInitialization> const xInit(xParser,
- // uno::UNO_QUERY_THROW);
- // uno::Sequence<uno::Any> args(1);
- // args[0] <<= OUString("DoSmeplease");
- // xInit->initialize(args);
- //
- // // connect parser and filter
- // xParser->setDocumentHandler(xSvgDocHdl);
- //
- // // finally, parse the stream to a hierarchy of
- // // SVGGraphicPrimitive2D which will be embedded to the
- // // primitive sequence. Their decompositions will in the
- // // end create local low-level primitives, thus SVG will
- // // be processable from all our processors
- // xParser->parseStream(myInputSource);
- // }
- // catch(const uno::Exception& e)
- // {
- // SAL_WARN( "svg", "Parse error! : " << e.Message);
- // }
- //
- // // decompose to primitives
- // const SvgNodeVector& rResults = pSvgDocHdl->getSvgDocument().getSvgNodeVector();
- // const sal_uInt32 nCount(rResults.size());
- //
- // for(sal_uInt32 a(0); a < nCount; a++)
- // {
- // SvgNode* pCandidate = rResults[a];
- //
- // if(Display_none != pCandidate->getDisplay())
- // {
- // pCandidate->decomposeSvgNode(aRetval, false);
- // }
- // }
}
}
else
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
new file mode 100644
index 000000000000..48c98db4c5fb
--- /dev/null
+++ b/emfio/source/reader/emfreader.cxx
@@ -0,0 +1,1941 @@
+/* -*- 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 <emfreader.hxx>
+
+#include <osl/endian.h>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <vcl/dibtools.hxx>
+#include <o3tl/make_unique.hxx>
+
+#include <memory>
+
+#ifdef DBG_UTIL
+#include <tools/stream.hxx>
+#include <vcl/pngwrite.hxx>
+#endif
+
+using namespace std;
+
+// GDI-Array
+
+#define EMR_HEADER 1
+#define EMR_POLYBEZIER 2
+#define EMR_POLYGON 3
+#define EMR_POLYLINE 4
+#define EMR_POLYBEZIERTO 5
+#define EMR_POLYLINETO 6
+#define EMR_POLYPOLYLINE 7
+#define EMR_POLYPOLYGON 8
+#define EMR_SETWINDOWEXTEX 9
+#define EMR_SETWINDOWORGEX 10
+#define EMR_SETVIEWPORTEXTEX 11
+#define EMR_SETVIEWPORTORGEX 12
+#define EMR_SETBRUSHORGEX 13
+#define EMR_EOF 14
+#define EMR_SETPIXELV 15
+#define EMR_SETMAPPERFLAGS 16
+#define EMR_SETMAPMODE 17
+#define EMR_SETBKMODE 18
+#define EMR_SETPOLYFILLMODE 19
+#define EMR_SETROP2 20
+#define EMR_SETSTRETCHBLTMODE 21
+#define EMR_SETTEXTALIGN 22
+#define EMR_SETCOLORADJUSTMENT 23
+#define EMR_SETTEXTCOLOR 24
+#define EMR_SETBKCOLOR 25
+#define EMR_OFFSETCLIPRGN 26
+#define EMR_MOVETOEX 27
+#define EMR_SETMETARGN 28
+#define EMR_EXCLUDECLIPRECT 29
+#define EMR_INTERSECTCLIPRECT 30
+#define EMR_SCALEVIEWPORTEXTEX 31
+#define EMR_SCALEWINDOWEXTEX 32
+#define EMR_SAVEDC 33
+#define EMR_RESTOREDC 34
+#define EMR_SETWORLDTRANSFORM 35
+#define EMR_MODIFYWORLDTRANSFORM 36
+#define EMR_SELECTOBJECT 37
+#define EMR_CREATEPEN 38
+#define EMR_CREATEBRUSHINDIRECT 39
+#define EMR_DELETEOBJECT 40
+#define EMR_ANGLEARC 41
+#define EMR_ELLIPSE 42
+#define EMR_RECTANGLE 43
+#define EMR_ROUNDRECT 44
+#define EMR_ARC 45
+#define EMR_CHORD 46
+#define EMR_PIE 47
+#define EMR_SELECTPALETTE 48
+#define EMR_CREATEPALETTE 49
+#define EMR_SETPALETTEENTRIES 50
+#define EMR_RESIZEPALETTE 51
+#define EMR_REALIZEPALETTE 52
+#define EMR_EXTFLOODFILL 53
+#define EMR_LINETO 54
+#define EMR_ARCTO 55
+#define EMR_POLYDRAW 56
+#define EMR_SETARCDIRECTION 57
+#define EMR_SETMITERLIMIT 58
+#define EMR_BEGINPATH 59
+#define EMR_ENDPATH 60
+#define EMR_CLOSEFIGURE 61
+#define EMR_FILLPATH 62
+#define EMR_STROKEANDFILLPATH 63
+#define EMR_STROKEPATH 64
+#define EMR_FLATTENPATH 65
+#define EMR_WIDENPATH 66
+#define EMR_SELECTCLIPPATH 67
+#define EMR_ABORTPATH 68
+
+#define EMR_COMMENT 70 // Contains arbitrary private data.
+// Comment Identifiers:
+#define EMR_COMMENT_EMFPLUS 0x2B464D45 // Contains embedded EMF+ records.
+#define EMR_COMMENT_EMFSPOOL 0x00000000 // Contains embedded EMFSPOOL records.
+#define EMR_COMMENT_PUBLIC 0x43494447 // Specify extensions to EMF processing.
+
+#define EMR_FILLRGN 71
+#define EMR_FRAMERGN 72
+#define EMR_INVERTRGN 73
+#define EMR_PAINTRGN 74
+#define EMR_EXTSELECTCLIPRGN 75
+#define EMR_BITBLT 76
+#define EMR_STRETCHBLT 77
+#define EMR_MASKBLT 78
+#define EMR_PLGBLT 79
+#define EMR_SETDIBITSTODEVICE 80
+#define EMR_STRETCHDIBITS 81
+#define EMR_EXTCREATEFONTINDIRECTW 82
+#define EMR_EXTTEXTOUTA 83
+#define EMR_EXTTEXTOUTW 84
+#define EMR_POLYBEZIER16 85
+#define EMR_POLYGON16 86
+#define EMR_POLYLINE16 87
+#define EMR_POLYBEZIERTO16 88
+#define EMR_POLYLINETO16 89
+#define EMR_POLYPOLYLINE16 90
+#define EMR_POLYPOLYGON16 91
+#define EMR_POLYDRAW16 92
+#define EMR_CREATEMONOBRUSH 93
+#define EMR_CREATEDIBPATTERNBRUSHPT 94
+#define EMR_EXTCREATEPEN 95
+#define EMR_POLYTEXTOUTA 96
+#define EMR_POLYTEXTOUTW 97
+
+// WINDOWS VERSION >= 0x400
+#define EMR_SETICMMODE 98
+#define EMR_CREATECOLORSPACE 99
+#define EMR_SETCOLORSPACE 100
+#define EMR_DELETECOLORSPACE 101
+#define EMR_GLSRECORD 102
+#define EMR_GLSBOUNDEDRECORD 103
+#define EMR_PIXELFORMAT 104
+
+// WINDOWS VERSION >= 0x500
+#define EMR_DRAWESCAPE 105
+#define EMR_EXTESCAPE 106
+#define EMR_STARTDOC 107
+#define EMR_SMALLTEXTOUT 108
+#define EMR_FORCEUFIMAPPING 109
+#define EMR_NAMEDESCAPE 110
+#define EMR_COLORCORRECTPALETTE 111
+#define EMR_SETICMPROFILEA 112
+#define EMR_SETICMPROFILEW 113
+#define EMR_ALPHABLEND 114
+#define EMR_ALPHADIBBLEND 115
+#define EMR_TRANSPARENTBLT 116
+#define EMR_TRANSPARENTDIB 117
+#define EMR_GRADIENTFILL 118
+#define EMR_SETLINKEDUFIS 119
+#define EMR_SETTEXTJUSTIFICATION 120
+
+namespace
+{
+
+const char *
+record_type_name(sal_uInt32 nRecType)
+{
+#ifndef SAL_LOG_INFO
+ (void) nRecType;
+ return "";
+#else
+ switch( nRecType )
+ {
+ case EMR_HEADER: return "HEADER";
+ case EMR_POLYBEZIER: return "POLYBEZIER";
+ case EMR_POLYGON: return "POLYGON";
+ case EMR_POLYLINE: return "POLYLINE";
+ case EMR_POLYBEZIERTO: return "POLYBEZIERTO";
+ case EMR_POLYLINETO: return "POLYLINETO";
+ case EMR_POLYPOLYLINE: return "POLYPOLYLINE";
+ case EMR_POLYPOLYGON: return "POLYPOLYGON";
+ case EMR_SETWINDOWEXTEX: return "SETWINDOWEXTEX";
+ case EMR_SETWINDOWORGEX: return "SETWINDOWORGEX";
+ case EMR_SETVIEWPORTEXTEX: return "SETVIEWPORTEXTEX";
+ case EMR_SETVIEWPORTORGEX: return "SETVIEWPORTORGEX";
+ case EMR_SETBRUSHORGEX: return "SETBRUSHORGEX";
+ case EMR_EOF: return "EOF";
+ case EMR_SETPIXELV: return "SETPIXELV";
+ case EMR_SETMAPPERFLAGS: return "SETMAPPERFLAGS";
+ case EMR_SETMAPMODE: return "SETMAPMODE";
+ case EMR_SETBKMODE: return "SETBKMODE";
+ case EMR_SETPOLYFILLMODE: return "SETPOLYFILLMODE";
+ case EMR_SETROP2: return "SETROP2";
+ case EMR_SETSTRETCHBLTMODE: return "SETSTRETCHBLTMODE";
+ case EMR_SETTEXTALIGN: return "SETTEXTALIGN";
+ case EMR_SETCOLORADJUSTMENT: return "SETCOLORADJUSTMENT";
+ case EMR_SETTEXTCOLOR: return "SETTEXTCOLOR";
+ case EMR_SETBKCOLOR: return "SETBKCOLOR";
+ case EMR_OFFSETCLIPRGN: return "OFFSETCLIPRGN";
+ case EMR_MOVETOEX: return "MOVETOEX";
+ case EMR_SETMETARGN: return "SETMETARGN";
+ case EMR_EXCLUDECLIPRECT: return "EXCLUDECLIPRECT";
+ case EMR_INTERSECTCLIPRECT: return "INTERSECTCLIPRECT";
+ case EMR_SCALEVIEWPORTEXTEX: return "SCALEVIEWPORTEXTEX";
+ case EMR_SCALEWINDOWEXTEX: return "SCALEWINDOWEXTEX";
+ case EMR_SAVEDC: return "SAVEDC";
+ case EMR_RESTOREDC: return "RESTOREDC";
+ case EMR_SETWORLDTRANSFORM: return "SETWORLDTRANSFORM";
+ case EMR_MODIFYWORLDTRANSFORM: return "MODIFYWORLDTRANSFORM";
+ case EMR_SELECTOBJECT: return "SELECTOBJECT";
+ case EMR_CREATEPEN: return "CREATEPEN";
+ case EMR_CREATEBRUSHINDIRECT: return "CREATEBRUSHINDIRECT";
+ case EMR_DELETEOBJECT: return "DELETEOBJECT";
+ case EMR_ANGLEARC: return "ANGLEARC";
+ case EMR_ELLIPSE: return "ELLIPSE";
+ case EMR_RECTANGLE: return "RECTANGLE";
+ case EMR_ROUNDRECT: return "ROUNDRECT";
+ case EMR_ARC: return "ARC";
+ case EMR_CHORD: return "CHORD";
+ case EMR_PIE: return "PIE";
+ case EMR_SELECTPALETTE: return "SELECTPALETTE";
+ case EMR_CREATEPALETTE: return "CREATEPALETTE";
+ case EMR_SETPALETTEENTRIES: return "SETPALETTEENTRIES";
+ case EMR_RESIZEPALETTE: return "RESIZEPALETTE";
+ case EMR_REALIZEPALETTE: return "REALIZEPALETTE";
+ case EMR_EXTFLOODFILL: return "EXTFLOODFILL";
+ case EMR_LINETO: return "LINETO";
+ case EMR_ARCTO: return "ARCTO";
+ case EMR_POLYDRAW: return "POLYDRAW";
+ case EMR_SETARCDIRECTION: return "SETARCDIRECTION";
+ case EMR_SETMITERLIMIT: return "SETMITERLIMIT";
+ case EMR_BEGINPATH: return "BEGINPATH";
+ case EMR_ENDPATH: return "ENDPATH";
+ case EMR_CLOSEFIGURE: return "CLOSEFIGURE";
+ case EMR_FILLPATH: return "FILLPATH";
+ case EMR_STROKEANDFILLPATH: return "STROKEANDFILLPATH";
+ case EMR_STROKEPATH: return "STROKEPATH";
+ case EMR_FLATTENPATH: return "FLATTENPATH";
+ case EMR_WIDENPATH: return "WIDENPATH";
+ case EMR_SELECTCLIPPATH: return "SELECTCLIPPATH";
+ case EMR_ABORTPATH: return "ABORTPATH";
+ case EMR_COMMENT: return "COMMENT";
+ case EMR_FILLRGN: return "FILLRGN";
+ case EMR_FRAMERGN: return "FRAMERGN";
+ case EMR_INVERTRGN: return "INVERTRGN";
+ case EMR_PAINTRGN: return "PAINTRGN";
+ case EMR_EXTSELECTCLIPRGN: return "EXTSELECTCLIPRGN";
+ case EMR_BITBLT: return "BITBLT";
+ case EMR_STRETCHBLT: return "STRETCHBLT";
+ case EMR_MASKBLT: return "MASKBLT";
+ case EMR_PLGBLT: return "PLGBLT";
+ case EMR_SETDIBITSTODEVICE: return "SETDIBITSTODEVICE";
+ case EMR_STRETCHDIBITS: return "STRETCHDIBITS";
+ case EMR_EXTCREATEFONTINDIRECTW: return "EXTCREATEFONTINDIRECTW";
+ case EMR_EXTTEXTOUTA: return "EXTTEXTOUTA";
+ case EMR_EXTTEXTOUTW: return "EXTTEXTOUTW";
+ case EMR_POLYBEZIER16: return "POLYBEZIER16";
+ case EMR_POLYGON16: return "POLYGON16";
+ case EMR_POLYLINE16: return "POLYLINE16";
+ case EMR_POLYBEZIERTO16: return "POLYBEZIERTO16";
+ case EMR_POLYLINETO16: return "POLYLINETO16";
+ case EMR_POLYPOLYLINE16: return "POLYPOLYLINE16";
+ case EMR_POLYPOLYGON16: return "POLYPOLYGON16";
+ case EMR_POLYDRAW16: return "POLYDRAW16";
+ case EMR_CREATEMONOBRUSH: return "CREATEMONOBRUSH";
+ case EMR_CREATEDIBPATTERNBRUSHPT: return "CREATEDIBPATTERNBRUSHPT";
+ case EMR_EXTCREATEPEN: return "EXTCREATEPEN";
+ case EMR_POLYTEXTOUTA: return "POLYTEXTOUTA";
+ case EMR_POLYTEXTOUTW: return "POLYTEXTOUTW";
+ case EMR_SETICMMODE: return "SETICMMODE";
+ case EMR_CREATECOLORSPACE: return "CREATECOLORSPACE";
+ case EMR_SETCOLORSPACE: return "SETCOLORSPACE";
+ case EMR_DELETECOLORSPACE: return "DELETECOLORSPACE";
+ case EMR_GLSRECORD: return "GLSRECORD";
+ case EMR_GLSBOUNDEDRECORD: return "GLSBOUNDEDRECORD";
+ case EMR_PIXELFORMAT: return "PIXELFORMAT";
+ case EMR_DRAWESCAPE: return "DRAWESCAPE";
+ case EMR_EXTESCAPE: return "EXTESCAPE";
+ case EMR_STARTDOC: return "STARTDOC";
+ case EMR_SMALLTEXTOUT: return "SMALLTEXTOUT";
+ case EMR_FORCEUFIMAPPING: return "FORCEUFIMAPPING";
+ case EMR_NAMEDESCAPE: return "NAMEDESCAPE";
+ case EMR_COLORCORRECTPALETTE: return "COLORCORRECTPALETTE";
+ case EMR_SETICMPROFILEA: return "SETICMPROFILEA";
+ case EMR_SETICMPROFILEW: return "SETICMPROFILEW";
+ case EMR_ALPHABLEND: return "ALPHABLEND";
+ case EMR_ALPHADIBBLEND: return "ALPHADIBBLEND";
+ case EMR_TRANSPARENTBLT: return "TRANSPARENTBLT";
+ case EMR_TRANSPARENTDIB: return "TRANSPARENTDIB";
+ case EMR_GRADIENTFILL: return "GRADIENTFILL";
+ case EMR_SETLINKEDUFIS: return "SETLINKEDUFIS";
+ case EMR_SETTEXTJUSTIFICATION: return "SETTEXTJUSTIFICATION";
+ default:
+ // Yes, return a pointer to a static buffer. This is a very
+ // local debugging output function, so no big deal.
+ static char buffer[11];
+ sprintf(buffer, "0x%08" SAL_PRIxUINT32, nRecType);
+ return buffer;
+ }
+#endif
+}
+
+#ifdef OSL_BIGENDIAN
+// little endian <-> big endian switch
+static float GetSwapFloat(SvStream& rStream)
+{
+ float fTmp;
+ sal_Int8* pPtr = (sal_Int8*)&fTmp;
+ rStream.ReadSChar(pPtr[3]);
+ rStream.ReadSChar(pPtr[2]);
+ rStream.ReadSChar(pPtr[1]);
+ rStream.ReadSChar(pPtr[0]);
+ return fTmp;
+}
+#endif
+
+struct BLENDFUNCTION
+{
+ unsigned char aBlendOperation;
+ unsigned char aBlendFlags;
+ unsigned char aSrcConstantAlpha;
+ unsigned char aAlphaFormat;
+
+ friend SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun);
+};
+
+SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun)
+{
+ rInStream.ReadUChar(rBlendFun.aBlendOperation);
+ rInStream.ReadUChar(rBlendFun.aBlendFlags);
+ rInStream.ReadUChar(rBlendFun.aSrcConstantAlpha);
+ rInStream.ReadUChar(rBlendFun.aAlphaFormat);
+ return rInStream;
+}
+
+bool ImplReadRegion( tools::PolyPolygon& rPolyPoly, SvStream& rStream, sal_uInt32 nLen )
+{
+ if (nLen == 0)
+ return false;
+
+ sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
+ rStream.ReadUInt32(nHdSize);
+ rStream.ReadUInt32(nType);
+ rStream.ReadUInt32(nCount);
+ rStream.ReadUInt32(nRgnSize);
+
+ if ( nCount > 0
+ && nType == RDH_RECTANGLES
+ && nLen >= ((nCount << 4) + (nHdSize - 16)))
+ {
+ sal_Int32 nx1, ny1, nx2, ny2;
+
+ for (i = 0; i < nCount; i++)
+ {
+ rStream.ReadInt32(nx1);
+ rStream.ReadInt32(ny1);
+ rStream.ReadInt32(nx2);
+ rStream.ReadInt32(ny2);
+
+ tools::Rectangle aRectangle(Point(nx1, ny1), Point(nx2, ny2));
+
+ tools::Polygon aPolygon(aRectangle);
+ tools::PolyPolygon aPolyPolyOr1(aPolygon);
+ tools::PolyPolygon aPolyPolyOr2(rPolyPoly);
+ rPolyPoly.GetUnion(aPolyPolyOr1, aPolyPolyOr2);
+ rPolyPoly = aPolyPolyOr2;
+ }
+ return true;
+ }
+ return false;
+}
+
+} // anonymous namespace
+
+namespace emfio
+{
+ EmfReader::EmfReader(SvStream& rStream,GDIMetaFile& rGDIMetaFile,FilterConfigItem* pConfigItem)
+ : MtfTools(rGDIMetaFile, rStream , pConfigItem)
+ , bRecordPath(false)
+ , nRecordCount(0)
+ , bEMFPlus(false)
+ {}
+
+ EmfReader::~EmfReader()
+ {}
+
+ void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
+ {
+ if (!bEMFPlus) {
+ pOut->PassEMFPlusHeaderInfo();
+
+ #if OSL_DEBUG_LEVEL > 1
+ // debug code - write the stream to debug file /tmp/emf-stream.emf
+ sal_uInt64 const pos = pWMF->Tell();
+ pWMF->Seek(0);
+ SvFileStream file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE | StreamMode::TRUNC );
+
+ pWMF->WriteStream(file);
+ file.Flush();
+ file.Close();
+
+ pWMF->Seek( pos );
+ #endif
+
+ }
+ bEMFPlus = true;
+
+ sal_uInt64 const pos = pWMF->Tell();
+ void *buffer = malloc( length );
+ pOut->PassEMFPlus( buffer, pWMF->ReadBytes(buffer, length) );
+ free( buffer );
+ pWMF->Seek( pos );
+
+ bHaveDC = false;
+
+ // skip in SeekRel if impossibly unavailable
+ sal_uInt32 nRemainder = length;
+
+ const size_t nRequiredHeaderSize = 12;
+ while (nRemainder >= nRequiredHeaderSize)
+ {
+ sal_uInt16 type(0), flags(0);
+ sal_uInt32 size(0), dataSize(0);
+
+ pWMF->ReadUInt16( type ).ReadUInt16( flags ).ReadUInt32( size ).ReadUInt32( dataSize );
+ nRemainder -= nRequiredHeaderSize;
+
+ SAL_INFO ("vcl.emf", "\t\tEMF+ record type: " << std::hex << type << std::dec);
+
+ // Get Device Context
+ // TODO We should use EmfPlusRecordType::GetDC instead
+ if( type == 0x4004 )
+ {
+ bHaveDC = true;
+ SAL_INFO ("vcl.emf", "\t\tEMF+ lock DC (device context)");
+ }
+
+ // Get the length of the remaining data of this record based
+ // on the alleged size
+ sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
+ size-nRequiredHeaderSize : 0;
+ // clip to available size
+ nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
+ pWMF->SeekRel(nRemainingRecordData);
+ nRemainder -= nRemainingRecordData;
+ }
+ pWMF->SeekRel(nRemainder);
+ }
+
+ /**
+ * Reads polygons from the stream.
+ * The \<class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
+ * The \<class Drawer> parameter is a c++11 lambda for the method that will draw the polygon.
+ * skipFirst: if the first point read is the 0th point or the 1st point in the array.
+ * */
+ template <class T, class Drawer>
+ void EmfReader::ReadAndDrawPolygon(Drawer drawer, const bool skipFirst)
+ {
+ sal_uInt32 nPoints(0), nStartIndex(0);
+ pWMF->SeekRel( 16 );
+ pWMF->ReadUInt32( nPoints );
+ if (skipFirst)
+ {
+ nPoints ++;
+ nStartIndex ++;
+ }
+
+ tools::Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
+ drawer(pOut, aPolygon, skipFirst, bRecordPath);
+ }
+
+ /**
+ * Reads polygons from the stream.
+ * The \<class T> parameter is for the type of the points
+ * nStartIndex: which is the starting index in the polygon of the first point read
+ * nPoints: number of points
+ * pWMF: the stream containing the polygons
+ * */
+ template <class T>
+ tools::Polygon EmfReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
+ {
+ bool bRecordOk = nPoints <= SAL_MAX_UINT16;
+ SAL_WARN_IF(!bRecordOk, "vcl.emf", "polygon record has more polygons than we can handle");
+ if (!bRecordOk)
+ return tools::Polygon();
+
+ tools::Polygon aPolygon(nPoints);
+ for (sal_uInt32 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
+ {
+ T nX, nY;
+ *pWMF >> nX >> nY;
+ if (!pWMF->good())
+ {
+ SAL_WARN("vcl.emf", "short read on polygon, truncating");
+ aPolygon.SetSize(i);
+ break;
+ }
+ aPolygon[ i ] = Point( nX, nY );
+ }
+
+ return aPolygon;
+ }
+
+ /**
+ * Reads a polyline from the WMF file and draws it
+ * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+ template <class T>
+ void EmfReader::ReadAndDrawPolyLine()
+ {
+ sal_uInt32 nPoints;
+ sal_uInt32 i, nNumberOfPolylines( 0 ), nCount( 0 );
+ pWMF->SeekRel( 0x10 ); // TODO Skipping Bounds. A 128-bit WMF RectL object (specifies the bounding rectangle in device units.)
+ pWMF->ReadUInt32( nNumberOfPolylines );
+ pWMF->ReadUInt32( nCount ); // total number of points in all polylines
+ if (pWMF->Tell() >= nEndPos)
+ return;
+
+ // taking the amount of points of each polygon, retrieving the total number of points
+ if ( pWMF->good() &&
+ ( nNumberOfPolylines < SAL_MAX_UINT32 / sizeof( sal_uInt16 ) ) &&
+ ( nNumberOfPolylines * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() )
+ )
+ {
+ std::unique_ptr< sal_uInt32[] > pnPolylinePointCount( new sal_uInt32[ nNumberOfPolylines ] );
+ for ( i = 0; i < nNumberOfPolylines && pWMF->good(); i++ )
+ {
+ pWMF->ReadUInt32( nPoints );
+ pnPolylinePointCount[ i ] = nPoints;
+ }
+ // Get polyline points:
+ for ( i = 0; ( i < nNumberOfPolylines ) && pWMF->good(); i++ )
+ {
+ tools::Polygon aPolygon = ReadPolygon< T >( 0, pnPolylinePointCount[ i ] );
+ pOut->DrawPolyLine( aPolygon, false, bRecordPath );
+ }
+ }
+ }
+
+ // these are referenced from inside the templates
+
+ SvStream& operator>>(SvStream& rStream, sal_Int16 &n)
+ {
+ return rStream.ReadInt16(n);
+ }
+
+ SvStream& operator>>(SvStream& rStream, sal_Int32 &n)
+ {
+ return rStream.ReadInt32(n);
+ }
+
+ /**
+ * Reads a poly polygon from the WMF file and draws it.
+ * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+ template <class T>
+ void EmfReader::ReadAndDrawPolyPolygon()
+ {
+ sal_uInt32 nPoly(0), nGesPoints(0), nReadPoints(0);
+ pWMF->SeekRel( 0x10 );
+ // Number of polygons
+ pWMF->ReadUInt32( nPoly ).ReadUInt32( nGesPoints );
+ if (pWMF->Tell() >= nEndPos)
+ return;
+ if (!pWMF->good())
+ return;
+ //check against numeric overflowing
+ if (nGesPoints >= SAL_MAX_UINT32 / sizeof(Point))
+ return;
+ if (nPoly >= SAL_MAX_UINT32 / sizeof(sal_uInt16))
+ return;
+ if (nPoly * sizeof(sal_uInt16) > nEndPos - pWMF->Tell())
+ return;
+
+ // Get number of points in each polygon
+ std::vector<sal_uInt16> aPoints(nPoly);
+ for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
+ {
+ sal_uInt32 nPoints(0);
+ pWMF->ReadUInt32( nPoints );
+ aPoints[i] = (sal_uInt16)nPoints;
+ }
+ if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ // Get polygon points
+ tools::PolyPolygon aPolyPoly(nPoly, nPoly);
+ for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
+ {
+ const sal_uInt16 nPointCount(aPoints[i]);
+ std::vector<Point> aPtAry(nPointCount);
+ for (sal_uInt16 j = 0; j < nPointCount && pWMF->good(); ++j)
+ {
+ T nX(0), nY(0);
+ *pWMF >> nX >> nY;
+ aPtAry[j] = Point( nX, nY );
+ ++nReadPoints;
+ }
+
+ aPolyPoly.Insert(tools::Polygon(aPtAry.size(), aPtAry.data()));
+ }
+
+ pOut->DrawPolyPolygon(aPolyPoly, bRecordPath);
+ }
+
+ OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
+ }
+
+ bool EmfReader::ReadEnhWMF()
+ {
+ sal_uInt32 nStretchBltMode = 0;
+ sal_uInt32 nNextPos(0),
+ nW(0), nH(0), nColor(0), nIndex(0),
+ nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
+ sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
+
+ bool bStatus = ReadHeader();
+ bool bHaveDC = false;
+
+ static bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == nullptr );
+
+ while( bStatus && nRecordCount-- && pWMF->good())
+ {
+ sal_uInt32 nRecType(0), nRecSize(0);
+ pWMF->ReadUInt32(nRecType).ReadUInt32(nRecSize);
+
+ if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
+ {
+ bStatus = false;
+ break;
+ }
+
+ auto nCurPos = pWMF->Tell();
+
+ if (nEndPos < nCurPos - 8)
+ {
+ bStatus = false;
+ break;
+ }
+
+ const sal_uInt32 nMaxPossibleRecSize = nEndPos - (nCurPos - 8);
+ if (nRecSize > nMaxPossibleRecSize)
+ {
+ bStatus = false;
+ break;
+ }
+
+ nNextPos = nCurPos + (nRecSize - 8);
+
+ if( !aBmpSaveList.empty()
+ && ( nRecType != EMR_STRETCHBLT )
+ && ( nRecType != EMR_STRETCHDIBITS )
+ ) {
+ pOut->ResolveBitmapActions( aBmpSaveList );
+ }
+
+ bool bFlag = false;
+
+ SAL_INFO ("vcl.emf", "0x" << std::hex << (nNextPos - nRecSize) << "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: " << nRecSize << std::dec);
+
+ if( bEnableEMFPlus && nRecType == EMR_COMMENT ) {
+ sal_uInt32 length;
+
+ pWMF->ReadUInt32( length );
+
+ SAL_INFO("vcl.emf", "\tGDI comment, length: " << length);
+
+ if( pWMF->good() && length >= 4 && length <= pWMF->remainingSize() ) {
+ sal_uInt32 nCommentId;
+
+ pWMF->ReadUInt32( nCommentId );
+
+ SAL_INFO ("vcl.emf", "\t\tbegin " << (char)(nCommentId & 0xff) << (char)((nCommentId & 0xff00) >> 8) << (char)((nCommentId & 0xff0000) >> 16) << (char)((nCommentId & 0xff000000) >> 24) << " id: 0x" << std::hex << nCommentId << std::dec);
+
+ if( nCommentId == EMR_COMMENT_EMFPLUS && nRecSize >= 12 )
+ {
+ // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields.
+ // We have already read 4-byte CommentIdentifier, so reduce length appropriately
+ ReadEMFPlusComment( length-4, bHaveDC );
+ }
+ else if( nCommentId == EMR_COMMENT_PUBLIC && nRecSize >= 12 )
+ {
+ // TODO: ReadGDIComment()
+ }
+ else if( nCommentId == EMR_COMMENT_EMFSPOOL && nRecSize >= 12 )
+ {
+ // TODO Implement reading EMFSPOOL comment
+
+ }
+ else
+ {
+ SAL_INFO ("vcl.emf", "\t\tunknown id: 0x" << std::hex << nCommentId << std::dec);
+ }
+ }
+ }
+ else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
+ {
+ switch( nRecType )
+ {
+ case EMR_POLYBEZIERTO :
+ ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+ { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, true );
+ break;
+ case EMR_POLYBEZIER :
+ ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+ { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, false );
+ break;
+
+ case EMR_POLYGON :
+ ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool /*aTo*/, bool aRecordPath )
+ { pWinMtfOutput->DrawPolygon( rPolygon, aRecordPath ); }, false );
+ break;
+
+ case EMR_POLYLINETO :
+ ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+ { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, true );
+ break;
+
+ case EMR_POLYLINE :
+ ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+ { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, false );
+ break;
+
+ case EMR_POLYPOLYLINE :
+ ReadAndDrawPolyLine<sal_Int32>();
+ break;
+
+ case EMR_POLYPOLYGON :
+ ReadAndDrawPolyPolygon<sal_Int32>();
+ break;
+
+ case EMR_SETWINDOWEXTEX :
+ {
+ pWMF->ReadUInt32( nW ).ReadUInt32( nH );
+ pOut->SetWinExt( Size( nW, nH ), true);
+ }
+ break;
+
+ case EMR_SETWINDOWORGEX :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->SetWinOrg( Point( nX32, nY32 ), true);
+ }
+ break;
+
+ case EMR_SCALEWINDOWEXTEX :
+ {
+ pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+ pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTORGEX :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->SetDevOrg( Point( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_SCALEVIEWPORTEXTEX :
+ {
+ pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+ pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTEXTEX :
+ {
+ pWMF->ReadUInt32( nW ).ReadUInt32( nH );
+ pOut->SetDevExt( Size( nW, nH ) );
+ }
+ break;
+
+ case EMR_EOF :
+ nRecordCount = 0;
+ break;
+
+ case EMR_SETPIXELV :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
+ }
+ break;
+
+ case EMR_SETMAPMODE :
+ {
+ sal_uInt32 nMapMode;
+ pWMF->ReadUInt32( nMapMode );
+ pOut->SetMapMode( nMapMode );
+ }
+ break;
+
+ case EMR_SETBKMODE :
+ {
+ pWMF->ReadUInt32( nDat32 );
+ pOut->SetBkMode( static_cast<BkMode>(nDat32) );
+ }
+ break;
+
+ case EMR_SETPOLYFILLMODE :
+ break;
+
+ case EMR_SETROP2 :
+ {
+ pWMF->ReadUInt32( nDat32 );
+ pOut->SetRasterOp( (WMFRasterOp)nDat32 );
+ }
+ break;
+
+ case EMR_SETSTRETCHBLTMODE :
+ {
+ pWMF->ReadUInt32( nStretchBltMode );
+ }
+ break;
+
+ case EMR_SETTEXTALIGN :
+ {
+ pWMF->ReadUInt32( nDat32 );
+ pOut->SetTextAlign( nDat32 );
+ }
+ break;
+
+ case EMR_SETTEXTCOLOR :
+ {
+ pOut->SetTextColor( ReadColor() );
+ }
+ break;
+
+ case EMR_SETBKCOLOR :
+ {
+ pOut->SetBkColor( ReadColor() );
+ }
+ break;
+
+ case EMR_OFFSETCLIPRGN :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->MoveClipRegion( Size( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_MOVETOEX :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_INTERSECTCLIPRECT :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+ pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_SAVEDC :
+ {
+ pOut->Push();
+ }
+ break;
+
+ case EMR_RESTOREDC :
+ {
+ pOut->Pop();
+ }
+ break;
+
+ case EMR_SETWORLDTRANSFORM :
+ {
+ XForm aTempXForm;
+ *pWMF >> aTempXForm;
+ pOut->SetWorldTransform( aTempXForm );
+ }
+ break;
+
+ case EMR_MODIFYWORLDTRANSFORM :
+ {
+ sal_uInt32 nMode;
+ XForm aTempXForm;
+ *pWMF >> aTempXForm;
+ pWMF->ReadUInt32( nMode );
+ pOut->ModifyWorldTransform( aTempXForm, nMode );
+ }
+ break;
+
+ case EMR_SELECTOBJECT :
+ {
+ pWMF->ReadUInt32( nIndex );
+ pOut->SelectObject( nIndex );
+ }
+ break;
+
+ case EMR_CREATEPEN :
+ {
+ pWMF->ReadUInt32( nIndex );
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+
+ LineInfo aLineInfo;
+ sal_uInt32 nStyle;
+ Size aSize;
+ // #fdo39428 Remove SvStream operator>>(long&)
+ sal_Int32 nTmpW(0), nTmpH(0);
+
+ pWMF->ReadUInt32( nStyle ).ReadInt32( nTmpW ).ReadInt32( nTmpH );
+ aSize.Width() = nTmpW;
+ aSize.Height() = nTmpH;
+
+ if ( aSize.Width() )
+ aLineInfo.SetWidth( aSize.Width() );
+
+ bool bTransparent = false;
+ switch( nStyle & PS_STYLE_MASK )
+ {
+ case PS_DASHDOTDOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 2 );
+ break;
+ case PS_DASHDOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 1 );
+ break;
+ case PS_DOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 0 );
+ aLineInfo.SetDotCount( 1 );
+ break;
+ case PS_DASH :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 0 );
+ break;
+ case PS_NULL :
+ bTransparent = true;
+ aLineInfo.SetStyle( LineStyle::NONE );
+ break;
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ default :
+ aLineInfo.SetStyle( LineStyle::Solid );
+ }
+ switch( nStyle & PS_ENDCAP_STYLE_MASK )
+ {
+ case PS_ENDCAP_ROUND :
+ if ( aSize.Width() )
+ {
+ aLineInfo.SetLineCap( css::drawing::LineCap_ROUND );
+ break;
+ }
+ SAL_FALLTHROUGH;
+ case PS_ENDCAP_SQUARE :
+ if ( aSize.Width() )
+ {
+ aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE );
+ break;
+ }
+ SAL_FALLTHROUGH;
+ case PS_ENDCAP_FLAT :
+ default :
+ aLineInfo.SetLineCap( css::drawing::LineCap_BUTT );
+ }
+ switch( nStyle & PS_JOIN_STYLE_MASK )
+ {
+ case PS_JOIN_ROUND :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
+ break;
+ case PS_JOIN_MITER :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
+ break;
+ case PS_JOIN_BEVEL :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
+ break;
+ default :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
+ }
+ pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfLineStyle>( ReadColor(), aLineInfo, bTransparent ));
+ }
+ }
+ break;
+
+ case EMR_EXTCREATEPEN :
+ {
+ sal_Int32 elpHatch;
+ sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
+ Color aColorRef;
+
+ pWMF->ReadUInt32( nIndex );
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ pWMF->ReadUInt32( offBmi ).ReadUInt32( cbBmi ).ReadUInt32( offBits ).ReadUInt32( cbBits ). ReadUInt32( nStyle ).ReadUInt32( nWidth ).ReadUInt32( nBrushStyle );
+ aColorRef = ReadColor();
+ pWMF->ReadInt32( elpHatch ).ReadUInt32( elpNumEntries );
+
+ LineInfo aLineInfo;
+ if ( nWidth )
+ aLineInfo.SetWidth( nWidth );
+
+ bool bTransparent = false;
+
+ switch( nStyle & PS_STYLE_MASK )
+ {
+ case PS_DASHDOTDOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 2 );
+ break;
+ case PS_DASHDOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 1 );
+ break;
+ case PS_DOT :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 0 );
+ aLineInfo.SetDotCount( 1 );
+ break;
+ case PS_DASH :
+ aLineInfo.SetStyle( LineStyle::Dash );
+ aLineInfo.SetDashCount( 1 );
+ aLineInfo.SetDotCount( 0 );
+ break;
+ case PS_NULL :
+ bTransparent = true;
+ aLineInfo.SetStyle( LineStyle::NONE );
+ break;
+
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ default :
+ aLineInfo.SetStyle( LineStyle::Solid );
+ }
+ switch( nStyle & PS_ENDCAP_STYLE_MASK )
+ {
+ case PS_ENDCAP_ROUND :
+ if ( aLineInfo.GetWidth() )
+ {
+ aLineInfo.SetLineCap( css::drawing::LineCap_ROUND );
+ break;
+ }
+ SAL_FALLTHROUGH;
+ case PS_ENDCAP_SQUARE :
+ if ( aLineInfo.GetWidth() )
+ {
+ aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE );
+ break;
+ }
+ SAL_FALLTHROUGH;
+ case PS_ENDCAP_FLAT :
+ default :
+ aLineInfo.SetLineCap( css::drawing::LineCap_BUTT );
+ }
+ switch( nStyle & PS_JOIN_STYLE_MASK )
+ {
+ case PS_JOIN_ROUND :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
+ break;
+ case PS_JOIN_MITER :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
+ break;
+ case PS_JOIN_BEVEL :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
+ break;
+ default :
+ aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
+ }
+ pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfLineStyle>( aColorRef, aLineInfo, bTransparent ));
+ }
+ }
+ break;
+
+ case EMR_CREATEBRUSHINDIRECT :
+ {
+ sal_uInt32 nStyle;
+ pWMF->ReadUInt32( nIndex );
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ pWMF->ReadUInt32( nStyle );
+ pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfFillStyle>( ReadColor(), ( nStyle == BS_HOLLOW ) ));
+ }
+ }
+ break;
+
+ case EMR_DELETEOBJECT :
+ {
+ pWMF->ReadUInt32( nIndex );
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ pOut->DeleteObject( nIndex );
+ }
+ break;
+
+ case EMR_ELLIPSE :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+ pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_RECTANGLE :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+ pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_ROUNDRECT :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nW ).ReadUInt32( nH );
+ Size aSize( Size( nW, nH ) );
+ pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
+ }
+ break;
+
+ case EMR_ARC :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_CHORD :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+ pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_PIE :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+ const tools::Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
+
+ // #i73608# OutputDevice deviates from WMF
+ // semantics. start==end means full ellipse here.
+ if( nStartX == nEndX && nStartY == nEndY )
+ pOut->DrawEllipse( aRect );
+ else
+ pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_LINETO :
+ {
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+ pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_ARCTO :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), true );
+ }
+ break;
+
+ case EMR_BEGINPATH :
+ {
+ pOut->ClearPath();
+ bRecordPath = true;
+ }
+ break;
+
+ case EMR_ABORTPATH :
+ pOut->ClearPath();
+ SAL_FALLTHROUGH;
+ case EMR_ENDPATH :
+ bRecordPath = false;
+ break;
+
+ case EMR_CLOSEFIGURE :
+ pOut->ClosePath();
+ break;
+
+ case EMR_FILLPATH :
+ pOut->StrokeAndFillPath( false, true );
+ break;
+
+ case EMR_STROKEANDFILLPATH :
+ pOut->StrokeAndFillPath( true, true );
+ break;
+
+ case EMR_STROKEPATH :
+ pOut->StrokeAndFillPath( true, false );
+ break;
+
+ case EMR_SELECTCLIPPATH :
+ {
+ sal_Int32 nClippingMode;
+ pWMF->ReadInt32(nClippingMode);
+ pOut->SetClipPath(pOut->GetPathObj(), nClippingMode, true);
+ }
+ break;
+
+ case EMR_EXTSELECTCLIPRGN :
+ {
+ sal_Int32 nClippingMode, cbRgnData;
+ pWMF->ReadInt32(cbRgnData);
+ pWMF->ReadInt32(nClippingMode);
+
+ // This record's region data should be ignored if mode
+ // is RGN_COPY - see EMF spec section 2.3.2.2
+ if (nClippingMode == RGN_COPY)
+ {
+ pOut->SetDefaultClipPath();
+ }
+ else
+ {
+ tools::PolyPolygon aPolyPoly;
+ if (cbRgnData)
+ ImplReadRegion(aPolyPoly, *pWMF, nRecSize);
+ pOut->SetClipPath(aPolyPoly, nClippingMode, false);
+ }
+
+ }
+ break;
+
+ case EMR_ALPHABLEND:
+ {
+ sal_Int32 xDest(0), yDest(0), cxDest(0), cyDest(0);
+
+ BLENDFUNCTION aFunc;
+ sal_Int32 xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
+ XForm xformSrc;
+ sal_uInt32 BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
+ sal_uInt32 cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
+
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+ pWMF->SeekRel( 0x10 );
+
+ pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest );
+ *pWMF >> aFunc;
+ pWMF->ReadInt32( xSrc ).ReadInt32( ySrc );
+ *pWMF >> xformSrc;
+ pWMF->ReadUInt32( BkColorSrc ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
+ .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ;
+
+ sal_uInt32 dwRop = SRCAND|SRCINVERT;
+ tools::Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
+
+ if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+ bStatus = false;
+ else
+ {
+ const sal_uInt32 nSourceSize = cbBmiSrc + cbBitsSrc + 14;
+ bool bSafeRead = nSourceSize <= (nEndPos - nStartPos);
+ sal_uInt32 nDeltaToDIB5HeaderSize(0);
+ const bool bReadAlpha(0x01 == aFunc.aAlphaFormat);
+ if (bSafeRead && bReadAlpha)
+ {
+ // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is
+ // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready
+ // for DIB-5 format
+ const sal_uInt32 nHeaderSize = getDIBV5HeaderSize();
+ if (cbBmiSrc > nHeaderSize)
+ bSafeRead = false;
+ else
+ nDeltaToDIB5HeaderSize = nHeaderSize - cbBmiSrc;
+ }
+ if (bSafeRead)
+ {
+ const sal_uInt32 nTargetSize(cbBmiSrc + nDeltaToDIB5HeaderSize + cbBitsSrc + 14);
+ char* pBuf = new char[ nTargetSize ];
+ SvMemoryStream aTmp( pBuf, nTargetSize, StreamMode::READ | StreamMode::WRITE );
+
+ aTmp.ObjectOwnsMemory( true );
+
+ // write BM-Header (14 bytes)
+ aTmp.WriteUChar( 'B' )
+ .WriteUChar( 'M' )
+ .WriteUInt32( cbBitsSrc )
+ .WriteUInt16( 0 )
+ .WriteUInt16( 0 )
+ .WriteUInt32( cbBmiSrc + nDeltaToDIB5HeaderSize + 14 );
+
+ // copy DIBInfoHeader from source (cbBmiSrc bytes)
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->ReadBytes(pBuf + 14, cbBmiSrc);
+
+ if (bReadAlpha)
+ {
+ // need to add values for all stuff that DIBV5Header is bigger
+ // than DIBInfoHeader, all values are correctly initialized to zero,
+ // so we can use memset here
+ memset(pBuf + cbBmiSrc + 14, 0, nDeltaToDIB5HeaderSize);
+ }
+
+ // copy bitmap data from source (offBitsSrc bytes)
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->ReadBytes(pBuf + 14 + nDeltaToDIB5HeaderSize + cbBmiSrc, cbBitsSrc);
+ aTmp.Seek( 0 );
+
+ // prepare to read and fill BitmapEx
+ BitmapEx aBitmapEx;
+
+ if(bReadAlpha)
+ {
+ Bitmap aBitmap;
+ AlphaMask aAlpha;
+
+ if(ReadDIBV5(aBitmap, aAlpha, aTmp))
+ {
+ aBitmapEx = BitmapEx(aBitmap, aAlpha);
+ }
+ }
+ else
+ {
+ Bitmap aBitmap;
+
+ if(ReadDIB(aBitmap, aTmp, true))
+ {
+ if(0xff != aFunc.aSrcConstantAlpha)
+ {
+ // add const alpha channel
+ aBitmapEx = BitmapEx(
+ aBitmap,
+ AlphaMask(aBitmap.GetSizePixel(), &aFunc.aSrcConstantAlpha));
+ }
+ else
+ {
+ // just use Bitmap
+ aBitmapEx = BitmapEx(aBitmap);
+ }
+ }
+ }
+
+ if(!aBitmapEx.IsEmpty())
+ {
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc < aBitmapEx.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc < aBitmapEx.GetSizePixel().Height() ) )
+ {
+ const tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+
+ aBitmapEx.Crop( aCropRect );
+ }
+
+ #ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false);
+
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew("c:\\metafile_content.png", StreamMode::WRITE|StreamMode::TRUNC);
+ vcl::PNGWriter aPNGWriter(aBitmapEx);
+ aPNGWriter.Write(aNew);
+ }
+ #endif
+ aBmpSaveList.emplace_back(new BSaveStruct(aBitmapEx, aRect, dwRop));
+ }
+ }
+ }
+ }
+ break;
+
+ case EMR_BITBLT : // PASSTHROUGH INTENDED
+ case EMR_STRETCHBLT :
+ {
+ sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
+ sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
+ XForm xformSrc;
+
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+
+ pWMF->SeekRel( 0x10 );
+ pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest ).ReadUInt32( dwRop ).ReadInt32( xSrc ).ReadInt32( ySrc )
+ >> xformSrc;
+ pWMF->ReadUInt32( nColor ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
+ .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc );
+
+ if ( nRecType == EMR_STRETCHBLT )
+ pWMF->ReadInt32( cxSrc ).ReadInt32( cySrc );
+ else
+ cxSrc = cySrc = 0;
+
+ Bitmap aBitmap;
+ tools::Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+ if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+ bStatus = false;
+ else
+ {
+ sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+ SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
+ aTmp.ObjectOwnsMemory( true );
+ aTmp.WriteUChar( 'B' )
+ .WriteUChar( 'M' )
+ .WriteUInt32( cbBitsSrc )
+ .WriteUInt16( 0 )
+ .WriteUInt16( 0 )
+ .WriteUInt32( cbBmiSrc + 14 );
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->ReadBytes(pBuf + 14, cbBmiSrc);
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->ReadBytes(pBuf + 14 + cbBmiSrc, cbBitsSrc);
+ aTmp.Seek( 0 );
+ ReadDIB(aBitmap, aTmp, true);
+
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+ {
+ tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+ aBitmap.Crop( aCropRect );
+ }
+ aBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aRect, dwRop));
+ }
+ }
+ }
+ break;
+
+ case EMR_STRETCHDIBITS :
+ {
+ sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
+ sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list