summaryrefslogtreecommitdiff
path: root/vcl/source/filter/wmf
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/filter/wmf')
-rw-r--r--vcl/source/filter/wmf/enhwmf.cxx1967
-rw-r--r--vcl/source/filter/wmf/winmtf.cxx2247
-rw-r--r--vcl/source/filter/wmf/winmtf.hxx718
-rw-r--r--vcl/source/filter/wmf/winwmf.cxx1833
-rw-r--r--vcl/source/filter/wmf/wmf.cxx73
-rw-r--r--vcl/source/filter/wmf/wmfexternal.cxx76
6 files changed, 99 insertions, 6815 deletions
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
deleted file mode 100644
index 12ee4ddb86b6..000000000000
--- a/vcl/source/filter/wmf/enhwmf.cxx
+++ /dev/null
@@ -1,1967 +0,0 @@
-/* -*- 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 <osl/endian.h>
-#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <vcl/dibtools.hxx>
-#include <o3tl/make_unique.hxx>
-
-#include "winmtf.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;
-}
-
-SvStream& operator>>(SvStream& rInStream, XForm& rXForm)
-{
- if (sizeof(float) != 4)
- {
- OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
- rXForm = XForm();
- }
- else
- {
-#ifdef OSL_BIGENDIAN
- rXForm.eM11 = GetSwapFloat(rInStream);
- rXForm.eM12 = GetSwapFloat(rInStream);
- rXForm.eM21 = GetSwapFloat(rInStream);
- rXForm.eM22 = GetSwapFloat(rInStream);
- rXForm.eDx = GetSwapFloat(rInStream);
- rXForm.eDy = GetSwapFloat(rInStream);
-#else
- rInStream.ReadFloat(rXForm.eM11);
- rInStream.ReadFloat(rXForm.eM12);
- rInStream.ReadFloat(rXForm.eM21);
- rInStream.ReadFloat(rXForm.eM22);
- rInStream.ReadFloat(rXForm.eDx);
- rInStream.ReadFloat(rXForm.eDy);
-#endif
- }
- 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
-
-EnhWMFReader::EnhWMFReader(SvStream& rStream,GDIMetaFile& rGDIMetaFile,FilterConfigItem* pConfigItem)
- : WinMtf(rGDIMetaFile, rStream , pConfigItem)
- , bRecordPath(false)
- , nRecordCount(0)
- , bEMFPlus(false)
-{}
-
-EnhWMFReader::~EnhWMFReader()
-{}
-
-void EnhWMFReader::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 EnhWMFReader::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 EnhWMFReader::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 EnhWMFReader::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 EnhWMFReader::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 EnhWMFReader::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<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, true );
- break;
- case EMR_POLYBEZIER :
- ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, false );
- break;
-
- case EMR_POLYGON :
- ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool /*aTo*/, bool aRecordPath )
- { pWinMtfOutput->DrawPolygon( rPolygon, aRecordPath ); }, false );
- break;
-
- case EMR_POLYLINETO :
- ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, true );
- break;
-
- case EMR_POLYLINE :
- ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<WinMtfOutput> &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 ) ;
-
- 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, SRCAND|SRCINVERT));
- }
- }
- }
- }
- 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;
- sal_uInt32 nStart = pWMF->Tell() - 8;
-
- pWMF->SeekRel( 0x10 );
- pWMF->ReadInt32( xDest )
- .ReadInt32( yDest )
- .ReadInt32( xSrc )
- .ReadInt32( ySrc )
- .ReadInt32( cxSrc )
- .ReadInt32( cySrc )
- .ReadUInt32( offBmiSrc )
- .ReadUInt32( cbBmiSrc )
- .ReadUInt32( offBitsSrc )
- .ReadUInt32( cbBitsSrc )
- .ReadUInt32( iUsageSrc )
- .ReadUInt32( dwRop )
- .ReadInt32( cxDest )
- .ReadInt32( cyDest );
-
- Bitmap aBitmap;
- tools::Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
-
- if ( ((SAL_MAX_UINT32 - 14) < cbBitsSrc)
- || ((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_EXTCREATEFONTINDIRECTW :
- {
- pWMF->ReadUInt32( nIndex );
- if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
- {
- LOGFONTW aLogFont;
- sal_Int32 nTmp;
- unsigned char nTmp2;
- pWMF->ReadInt32( aLogFont.lfHeight )
- .ReadInt32( aLogFont.lfWidth )
- .ReadInt32( aLogFont.lfEscapement )
- .ReadInt32( nTmp ) // lfOrientation
- .ReadInt32( aLogFont.lfWeight )
- .ReadUChar( aLogFont.lfItalic )
- .ReadUChar( aLogFont.lfUnderline )
- .ReadUChar( aLogFont.lfStrikeOut )
- .ReadUChar( aLogFont.lfCharSet )
- .ReadUChar( nTmp2 ) // lfOutPrecision
- .ReadUChar( nTmp2 ) // lfClipPrecision
- .ReadUChar( nTmp2 ) // lfQuality
- .ReadUChar( aLogFont.lfPitchAndFamily );
-
- sal_Unicode lfFaceName[LF_FACESIZE+1];
- lfFaceName[LF_FACESIZE] = 0;
- for (int i = 0; i < LF_FACESIZE; ++i)
- {
- sal_uInt16 nChar(0);
- pWMF->ReadUInt16(nChar);
- lfFaceName[i] = nChar;
- }
- aLogFont.alfFaceName = OUString( lfFaceName );
-
- // #i123216# Not used in the test case of #121382# (always identity in XForm), also
- // no hints in ms docu if FontSize should be scaled with WT. Using with the example
- // from #i123216# creates errors, so removing.
-
- // // #i121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
- // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
- // // constraints and dangers
- // const XForm& rXF = pOut->GetWorldTransform();
- // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
- // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
- // aLogFont.lfWidth = aTransVec.getX();
- // aLogFont.lfHeight = aTransVec.getY();
-
- pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfFontStyle>( aLogFont ));
- }
- }
- break;
-
- case EMR_EXTTEXTOUTA :
- bFlag = true;
- SAL_FALLTHROUGH;
- case EMR_EXTTEXTOUTW :
- {
- sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
- sal_uInt32 nOffString, nOptions, offDx;
- sal_Int32 nLen;
-
- nCurPos = pWMF->Tell() - 8;
-
- pWMF->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom ).ReadInt32( nGfxMode ).ReadInt32( nXScale ).ReadInt32( nYScale )
- .ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
-
- pWMF->SeekRel( 0x10 );
- pWMF->ReadUInt32( offDx );
-
- ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
- if ( nOptions & ETO_RTLREADING )
- nTextLayoutMode = ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
- pOut->SetTextLayoutMode( nTextLayoutMode );
- SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "vcl.emf", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
-
- Point aPos( ptlReferenceX, ptlReferenceY );
- bool bLenSane = nLen > 0 && nLen < static_cast<sal_Int32>( SAL_MAX_UINT32 / sizeof(sal_Int32) );
- bool bOffStringSane = nOffString <= nEndPos - nCurPos;
- if (bLenSane && bOffStringSane)
- {
- pWMF->Seek( nCurPos + nOffString );
- OUString aText;
- if ( bFlag )
- {
- if ( nLen <= static_cast<sal_Int32>( nEndPos - pWMF->Tell() ) )
- {
- std::unique_ptr<sal_Char[]> pBuf(new sal_Char[ nLen ]);
- pWMF->ReadBytes(pBuf.get(), nLen);
- aText = OUString(pBuf.get(), nLen, pOut->GetCharSet());
- }
- }
- else
- {
- if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
- {
- std::unique_ptr<sal_Unicode[]> pBuf(new sal_Unicode[ nLen ]);
- pWMF->ReadBytes(pBuf.get(), nLen << 1);
-#ifdef OSL_BIGENDIAN
- sal_Char nTmp, *pTmp = (sal_Char*)( pBuf.get() + nLen );
- while ( pTmp-- != (sal_Char*)pBuf.get() )
- {
- nTmp = *pTmp--;
- pTmp[ 1 ] = *pTmp;
- *pTmp = nTmp;
- }
-#endif
- aText = OUString(pBuf.get(), nLen);
- }
- }
-
- std::unique_ptr<long[]> pDXAry, pDYAry;
- sal_Int32 nDxSize = nLen * ((nOptions & ETO_PDY) ? 8 : 4);
- if ( offDx && (( nCurPos + offDx + nDxSize ) <= nNextPos ) && nNextPos <= nEndPos )
- {
- pWMF->Seek( nCurPos + offDx );
- pDXAry.reset( new long[aText.getLength()] );
- if (nOptions & ETO_PDY)
- {
- pDYAry.reset( new long[aText.getLength()] );
- }
-
- for (sal_Int32 i = 0; i < aText.getLength(); ++i)
- {
- sal_Int32 nDxCount = 1;
- if (aText.getLength() != nLen)
- {
- sal_Unicode cUniChar = aText[i];
- OString aTmp(&cUniChar, 1, pOut->GetCharSet());
- if (aTmp.getLength() > 1)
- {
- nDxCount = aTmp.getLength();
- }
- }
-
- sal_Int32 nDx = 0, nDy = 0;
- while (nDxCount--)
- {
- sal_Int32 nDxTmp = 0;
- pWMF->ReadInt32(nDxTmp);
- nDx += nDxTmp;
- if (nOptions & ETO_PDY)
- {
- sal_Int32 nDyTmp = 0;
- pWMF->ReadInt32(nDyTmp);
- nDy += nDyTmp;
- }
- }
-
- pDXAry[i] = nDx;
- if (nOptions & ETO_PDY)
- {
- pDYAry[i] = nDy;
- }
- }
- }
- pOut->DrawText(aPos, aText, pDXAry.get(), pDYAry.get(), bRecordPath, nGfxMode);
- }
- }
- break;
-
- case EMR_POLYBEZIERTO16 :
- ReadAndDrawPolygon<sal_Int16>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, true );
- break;
-
- case EMR_POLYBEZIER16 :
- ReadAndDrawPolygon<sal_Int16>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, false );
- break;
-
- case EMR_POLYGON16 :
- ReadAndDrawPolygon<sal_Int16>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool /*aTo*/, bool aRecordPath )
- { pWinMtfOutput->DrawPolygon( rPolygon, aRecordPath ); }, false );
- break;
-
- case EMR_POLYLINETO16 :
- ReadAndDrawPolygon<sal_Int16>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, true );
- break;
-
- case EMR_POLYLINE16 :
- ReadAndDrawPolygon<sal_Int16>( [] ( std::unique_ptr<WinMtfOutput> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
- { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, false );
- break;
-
- case EMR_POLYPOLYLINE16 :
- ReadAndDrawPolyLine<sal_Int16>();
- break;
-
- case EMR_POLYPOLYGON16 :
- ReadAndDrawPolyPolygon<sal_Int16>();
- break;
-
- case EMR_FILLRGN :
- {
- sal_uInt32 nLen;
- tools::PolyPolygon aPolyPoly;
- pWMF->SeekRel( 0x10 );
- pWMF->ReadUInt32( nLen ).ReadUInt32( nIndex );
-
- if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
- {
- pOut->Push();
- pOut->SelectObject( nIndex );
- pOut->DrawPolyPolygon( aPolyPoly );
- pOut->Pop();
- }
- }
- break;
-
- case EMR_CREATEDIBPATTERNBRUSHPT :
- {
- sal_uInt32 nStart = pWMF->Tell() - 8;
- Bitmap aBitmap;
-
- pWMF->ReadUInt32( nIndex );
-
- if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
- {
- sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
-
- pWMF->ReadUInt32( usage );
- pWMF->ReadUInt32( offBmi );
- pWMF->ReadUInt32( cbBmi );
- pWMF->ReadUInt32( offBits );
- pWMF->ReadUInt32( cbBits );
-
- if ( (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
- bStatus = false;
- else if ( offBmi )
- {
- sal_uInt32 nSize = cbBmi + cbBits + 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( cbBits )
- .WriteUInt16( 0 )
- .WriteUInt16( 0 )
- .WriteUInt32( cbBmi + 14 );
- pWMF->Seek( nStart + offBmi );
- pWMF->ReadBytes(pBuf + 14, cbBmi);
- pWMF->Seek( nStart + offBits );
- pWMF->ReadBytes(pBuf + 14 + cbBmi, cbBits);
- aTmp.Seek( 0 );
- ReadDIB(aBitmap, aTmp, true);
- }
- }
- }
-
- pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfFillStyle>( aBitmap ));
- }
- break;
-
- case EMR_MASKBLT : SAL_INFO("vcl.emf", "not implemented 'MaskBlt'"); break;
- case EMR_PLGBLT : SAL_INFO("vcl.emf", "not implemented 'PlgBlt'"); break;
- case EMR_SETDIBITSTODEVICE : SAL_INFO("vcl.emf", "not implemented 'SetDIBitsToDevice'"); break;
- case EMR_FRAMERGN : SAL_INFO("vcl.emf", "not implemented 'FrameRgn'"); break;
- case EMR_INVERTRGN : SAL_INFO("vcl.emf", "not implemented 'InvertRgn'"); break;
- case EMR_PAINTRGN : SAL_INFO("vcl.emf", "not implemented 'PaintRgn'"); break;
- case EMR_FLATTENPATH : SAL_INFO("vcl.emf", "not implemented 'FlattenPath'"); break;
- case EMR_WIDENPATH : SAL_INFO("vcl.emf", "not implemented 'WidenPath'"); break;
- case EMR_POLYDRAW : SAL_INFO("vcl.emf", "not implemented 'Polydraw'"); break;
- case EMR_SETARCDIRECTION : SAL_INFO("vcl.emf", "not implemented 'SetArcDirection'"); break;
- case EMR_SETPALETTEENTRIES : SAL_INFO("vcl.emf", "not implemented 'SetPaletteEntries'"); break;
- case EMR_RESIZEPALETTE : SAL_INFO("vcl.emf", "not implemented 'ResizePalette'"); break;
- case EMR_EXTFLOODFILL : SAL_INFO("vcl.emf", "not implemented 'ExtFloodFill'"); break;
- case EMR_ANGLEARC : SAL_INFO("vcl.emf", "not implemented 'AngleArc'"); break;
- case EMR_SETCOLORADJUSTMENT : SAL_INFO("vcl.emf", "not implemented 'SetColorAdjustment'"); break;
- case EMR_POLYDRAW16 : SAL_INFO("vcl.emf", "not implemented 'PolyDraw16'"); break;
- case EMR_POLYTEXTOUTA : SAL_INFO("vcl.emf", "not implemented 'PolyTextOutA'"); break;
- case EMR_POLYTEXTOUTW : SAL_INFO("vcl.emf", "not implemented 'PolyTextOutW'"); break;
- case EMR_CREATECOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'CreateColorSpace'"); break;
- case EMR_SETCOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'SetColorSpace'"); break;
- case EMR_DELETECOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'DeleteColorSpace'"); break;
- case EMR_GLSRECORD : SAL_INFO("vcl.emf", "not implemented 'GlsRecord'"); break;
- case EMR_GLSBOUNDEDRECORD : SAL_INFO("vcl.emf", "not implemented 'GlsBoundRecord'"); break;
- case EMR_PIXELFORMAT : SAL_INFO("vcl.emf", "not implemented 'PixelFormat'"); break;
- case EMR_DRAWESCAPE : SAL_INFO("vcl.emf", "not implemented 'DrawEscape'"); break;
- case EMR_EXTESCAPE : SAL_INFO("vcl.emf", "not implemented 'ExtEscape'"); break;
- case EMR_STARTDOC : SAL_INFO("vcl.emf", "not implemented 'StartDoc'"); break;
- case EMR_SMALLTEXTOUT : SAL_INFO("vcl.emf", "not implemented 'SmallTextOut'"); break;
- case EMR_FORCEUFIMAPPING : SAL_INFO("vcl.emf", "not implemented 'ForceUFIMapping'"); break;
- case EMR_NAMEDESCAPE : SAL_INFO("vcl.emf", "not implemented 'NamedEscape'"); break;
- case EMR_COLORCORRECTPALETTE : SAL_INFO("vcl.emf", "not implemented 'ColorCorrectPalette'"); break;
- case EMR_SETICMPROFILEA : SAL_INFO("vcl.emf", "not implemented 'SetICMProfileA'"); break;
- case EMR_SETICMPROFILEW : SAL_INFO("vcl.emf", "not implemented 'SetICMProfileW'"); break;
- case EMR_TRANSPARENTBLT : SAL_INFO("vcl.emf", "not implemented 'TransparenBlt'"); break;
- case EMR_TRANSPARENTDIB : SAL_INFO("vcl.emf", "not implemented 'TransparenDib'"); break;
- case EMR_GRADIENTFILL : SAL_INFO("vcl.emf", "not implemented 'GradientFill'"); break;
- case EMR_SETLINKEDUFIS : SAL_INFO("vcl.emf", "not implemented 'SetLinkedUFIS'"); break;
-
- case EMR_SETMAPPERFLAGS : SAL_INFO("vcl.emf", "not implemented 'SetMapperFlags'"); break;
- case EMR_SETICMMODE : SAL_INFO("vcl.emf", "not implemented 'SetICMMode'"); break;
- case EMR_CREATEMONOBRUSH : SAL_INFO("vcl.emf", "not implemented 'CreateMonoBrush'"); break;
- case EMR_SETBRUSHORGEX : SAL_INFO("vcl.emf", "not implemented 'SetBrushOrgEx'"); break;
- case EMR_SETMETARGN : SAL_INFO("vcl.emf", "not implemented 'SetMetArgn'"); break;
- case EMR_SETMITERLIMIT : SAL_INFO("vcl.emf", "not implemented 'SetMiterLimit'"); break;
- case EMR_EXCLUDECLIPRECT : SAL_INFO("vcl.emf", "not implemented 'ExcludeClipRect'"); break;
- case EMR_REALIZEPALETTE : SAL_INFO("vcl.emf", "not implemented 'RealizePalette'"); break;
- case EMR_SELECTPALETTE : SAL_INFO("vcl.emf", "not implemented 'SelectPalette'"); break;
- case EMR_CREATEPALETTE : SAL_INFO("vcl.emf", "not implemented 'CreatePalette'"); break;
- case EMR_ALPHADIBBLEND : SAL_INFO("vcl.emf", "not implemented 'AlphaDibBlend'"); break;
- case EMR_SETTEXTJUSTIFICATION : SAL_INFO("vcl.emf", "not implemented 'SetTextJustification'"); break;
-
- case EMR_COMMENT :
- case EMR_HEADER : // has already been read at ReadHeader()
- break;
-
- default : SAL_INFO("vcl.emf", "Unknown Meta Action"); break;
- }
- }
- pWMF->Seek( nNextPos );
- }
- if( !aBmpSaveList.empty() )
- pOut->ResolveBitmapActions( aBmpSaveList );
-
- if ( bStatus )
- pWMF->Seek(nEndPos);
-
- return bStatus;
-};
-
-bool EnhWMFReader::ReadHeader()
-{
- sal_uInt32 nType, nSignature, nVersion;
- sal_uInt32 nHeaderSize, nPalEntries;
-
- // Spare me the METAFILEHEADER here
- // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
- pWMF->ReadUInt32( nType ).ReadUInt32( nHeaderSize );
- if (nType != 0x00000001)
- {
- // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
- SAL_WARN("vcl.emf", "EMF header type is not set to 0x00000001 - possibly corrupted file?");
- return false;
- }
-
- // Start reading the EMR_HEADER Header object
-
- // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
- tools::Rectangle rclBounds = ReadRectangle(); // rectangle in logical units
-
- // picture frame size (RectL object)
- tools::Rectangle rclFrame = ReadRectangle(); // rectangle in device units 1/100th mm
-
- pWMF->ReadUInt32( nSignature );
-
- // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
- // and 2.1.14 FormatSignature Enumeration
- if (nSignature != 0x464d4520)
- {
- SAL_WARN("vcl.emf", "EMF\t\tSignature is not 0x464d4520 (\"FME\") - possibly corrupted file?");
- return false;
- }
-
- pWMF->ReadUInt32(nVersion); // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
- // Microsoft note that not even Windows checks this...
- if (nVersion != 0x00010000)
- {
- SAL_WARN("vcl.emf", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
- }
-
- pWMF->ReadUInt32(nEndPos); // size of metafile
- nEndPos += nStartPos;
-
- sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
- pWMF->Seek(STREAM_SEEK_TO_END);
- sal_uInt32 nActualFileSize = pWMF->Tell();
-
- if ( nActualFileSize < nEndPos )
- {
- SAL_WARN("vcl.emf", "EMF\t\tEMF Header object records number of bytes as " << nEndPos
- << ", however the file size is actually " << nActualFileSize
- << " bytes. Possible file corruption?");
- nEndPos = nActualFileSize;
- }
- pWMF->Seek(nStrmPos);
-
- pWMF->ReadInt32(nRecordCount);
-
- if (nRecordCount <= 0)
- {
- SAL_WARN("vcl.emf", "EMF\t\tEMF Header object shows record counter as <= 0! This shouldn't "
- "be possible... indicator of possible file corruption?");
- return false;
- }
-
- // the number of "handles", or graphics objects used in the metafile
-
- sal_uInt16 nHandlesCount;
- pWMF->ReadUInt16(nHandlesCount);
-
- // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
- // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
- // value is actually pretty useful in checking if there is possible corruption
-
- sal_uInt16 nReserved;
- pWMF->ReadUInt16(nReserved);
-
- if ( nReserved != 0x0000 )
- {
- SAL_WARN("vcl.emf", "EMF\t\tEMF Header object's reserved field is NOT 0x0000... possible "
- "corruption?");
- }
-
- // The next 4 bytes specifies the number of characters in the metafile description.
- // The 4 bytes after that specific the offset from this record that contains the
- // metafile description... zero means no description string.
- // For now, we ignore it.
-
- pWMF->SeekRel(0x8);
-
- sal_Int32 nPixX, nPixY, nMillX, nMillY;
- pWMF->ReadUInt32(nPalEntries);
- pWMF->ReadInt32(nPixX);
- pWMF->ReadInt32(nPixY);
- pWMF->ReadInt32(nMillX);
- pWMF->ReadInt32(nMillY);
-
- pOut->SetrclFrame(rclFrame);
- pOut->SetrclBounds(rclBounds);
- pOut->SetRefPix(Size( nPixX, nPixY ) );
- pOut->SetRefMill(Size( nMillX, nMillY ) );
-
- pWMF->Seek(nStartPos + nHeaderSize);
- return true;
-}
-
-tools::Rectangle EnhWMFReader::ReadRectangle()
-{
- sal_Int32 nLeft, nTop, nRight, nBottom;
- pWMF->ReadInt32(nLeft);
- pWMF->ReadInt32(nTop);
- pWMF->ReadInt32(nRight);
- pWMF->ReadInt32(nBottom);
- return tools::Rectangle(nLeft, nTop, nRight, nBottom);
-}
-
-tools::Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
-{
- Point aTL ( Point( x1, y1 ) );
- Point aBR( Point( --x2, --y2 ) );
- return tools::Rectangle( aTL, aBR );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
deleted file mode 100644
index 5053307069db..000000000000
--- a/vcl/source/filter/wmf/winmtf.cxx
+++ /dev/null
@@ -1,2247 +0,0 @@
-/* -*- 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 <memory>
-#include "winmtf.hxx"
-#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <basegfx/polygon/b2dpolypolygontools.hxx>
-#include <vcl/metaact.hxx>
-#include <vcl/graphictools.hxx>
-#include <vcl/canvastools.hxx>
-#include <vcl/metric.hxx>
-#include <vcl/svapp.hxx>
-#include <tools/fract.hxx>
-#include <rtl/strbuf.hxx>
-#include <rtl/tencinfo.h>
-#include <vcl/virdev.hxx>
-#include <o3tl/make_unique.hxx>
-#include "officecfg/Setup.hxx"
-#include "officecfg/Office/Linguistic.hxx"
-#include "unotools/configmgr.hxx"
-#include "unotools/wincodepage.hxx"
-
-#if OSL_DEBUG_LEVEL > 1
-#define EMFP_DEBUG(x) x
-#else
-#define EMFP_DEBUG(x)
-#endif
-
-void WinMtfClipPath::intersectClipRect( const tools::Rectangle& rRect )
-{
- maClip.intersectRange(
- vcl::unotools::b2DRectangleFromRectangle(rRect));
-}
-
-void WinMtfClipPath::excludeClipRect( const tools::Rectangle& rRect )
-{
- maClip.subtractRange(
- vcl::unotools::b2DRectangleFromRectangle(rRect));
-}
-
-void WinMtfClipPath::setClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
-{
- const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
- switch ( nClippingMode )
- {
- case RGN_OR :
- maClip.unionPolyPolygon(rB2DPoly);
- break;
- case RGN_XOR :
- maClip.xorPolyPolygon(rB2DPoly);
- break;
- case RGN_DIFF :
- maClip.subtractPolyPolygon(rB2DPoly);
- break;
- case RGN_AND :
- maClip.intersectPolyPolygon(rB2DPoly);
- break;
- case RGN_COPY :
- maClip = basegfx::tools::B2DClipState(rB2DPoly);
- break;
- }
-}
-
-void WinMtfClipPath::moveClipRegion( const Size& rSize )
-{
- basegfx::B2DHomMatrix aTranslate;
- aTranslate.translate(rSize.Width(), rSize.Height());
- maClip.transform(aTranslate);
-}
-
-void WinMtfClipPath::setDefaultClipPath()
-{
- // Empty clip region - everything visible
- maClip = basegfx::tools::B2DClipState();
-}
-
-basegfx::B2DPolyPolygon WinMtfClipPath::getClipPath() const
-{
- return maClip.getClipPoly();
-}
-
-void WinMtfPathObj::AddPoint( const Point& rPoint )
-{
- if ( bClosed )
- Insert( tools::Polygon() );
- tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
- rPoly.Insert( rPoly.GetSize(), rPoint );
- bClosed = false;
-}
-
-void WinMtfPathObj::AddPolyLine( const tools::Polygon& rPolyLine )
-{
- if ( bClosed )
- Insert( tools::Polygon() );
- tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
- rPoly.Insert( rPoly.GetSize(), rPolyLine );
- bClosed = false;
-}
-
-void WinMtfPathObj::AddPolygon( const tools::Polygon& rPoly )
-{
- Insert( rPoly );
- bClosed = true;
-}
-
-void WinMtfPathObj::AddPolyPolygon( const tools::PolyPolygon& rPolyPoly )
-{
- sal_uInt16 i, nCount = rPolyPoly.Count();
- for ( i = 0; i < nCount; i++ )
- Insert( rPolyPoly[ i ] );
- bClosed = true;
-}
-
-void WinMtfPathObj::ClosePath()
-{
- if ( Count() )
- {
- tools::Polygon& rPoly = static_cast<tools::PolyPolygon&>(*this)[ Count() - 1 ];
- if ( rPoly.GetSize() > 2 )
- {
- Point aFirst( rPoly[ 0 ] );
- if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
- rPoly.Insert( rPoly.GetSize(), aFirst );
- }
- }
- bClosed = true;
-}
-
-namespace {
-
-OUString getLODefaultLanguage()
-{
- if (utl::ConfigManager::IsAvoidConfig())
- return OUString("en-US");
- OUString result(officecfg::Office::Linguistic::General::DefaultLocale::get());
- if (result.isEmpty())
- result = officecfg::Setup::L10N::ooSetupSystemLocale::get();
- return result;
-}
-
-}
-
-WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
-{
- rtl_TextEncoding eCharSet;
- if ((rFont.alfFaceName == "Symbol")
- || (rFont.alfFaceName == "MT Extra"))
- eCharSet = RTL_TEXTENCODING_SYMBOL;
- else if ((rFont.lfCharSet == DEFAULT_CHARSET) || (rFont.lfCharSet == OEM_CHARSET))
- eCharSet = utl_getWinTextEncodingFromLangStr(getLODefaultLanguage().toUtf8().getStr(),
- rFont.lfCharSet == OEM_CHARSET);
- else
- eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
- if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
- eCharSet = RTL_TEXTENCODING_MS_1252;
- aFont.SetCharSet( eCharSet );
- aFont.SetFamilyName( rFont.alfFaceName );
- FontFamily eFamily;
- switch ( rFont.lfPitchAndFamily & 0xf0 )
- {
- case FF_ROMAN:
- eFamily = FAMILY_ROMAN;
- break;
-
- case FF_SWISS:
- eFamily = FAMILY_SWISS;
- break;
-
- case FF_MODERN:
- eFamily = FAMILY_MODERN;
- break;
-
- case FF_SCRIPT:
- eFamily = FAMILY_SCRIPT;
- break;
-
- case FF_DECORATIVE:
- eFamily = FAMILY_DECORATIVE;
- break;
-
- default:
- eFamily = FAMILY_DONTKNOW;
- break;
- }
- aFont.SetFamily( eFamily );
-
- FontPitch ePitch;
- switch ( rFont.lfPitchAndFamily & 0x0f )
- {
- case FIXED_PITCH:
- ePitch = PITCH_FIXED;
- break;
-
- case DEFAULT_PITCH:
- case VARIABLE_PITCH:
- default:
- ePitch = PITCH_VARIABLE;
- break;
- }
- aFont.SetPitch( ePitch );
-
- FontWeight eWeight;
- if (rFont.lfWeight == 0) // default weight SHOULD be used
- eWeight = WEIGHT_DONTKNOW;
- else if (rFont.lfWeight <= FW_THIN)
- eWeight = WEIGHT_THIN;
- else if( rFont.lfWeight <= FW_ULTRALIGHT )
- eWeight = WEIGHT_ULTRALIGHT;
- else if( rFont.lfWeight <= FW_LIGHT )
- eWeight = WEIGHT_LIGHT;
- else if( rFont.lfWeight < FW_MEDIUM )
- eWeight = WEIGHT_NORMAL;
- else if( rFont.lfWeight == FW_MEDIUM )
- eWeight = WEIGHT_MEDIUM;
- else if( rFont.lfWeight <= FW_SEMIBOLD )
- eWeight = WEIGHT_SEMIBOLD;
- else if( rFont.lfWeight <= FW_BOLD )
- eWeight = WEIGHT_BOLD;
- else if( rFont.lfWeight <= FW_ULTRABOLD )
- eWeight = WEIGHT_ULTRABOLD;
- else
- eWeight = WEIGHT_BLACK;
- aFont.SetWeight( eWeight );
-
- if( rFont.lfItalic )
- aFont.SetItalic( ITALIC_NORMAL );
-
- if( rFont.lfUnderline )
- aFont.SetUnderline( LINESTYLE_SINGLE );
-
- if( rFont.lfStrikeOut )
- aFont.SetStrikeout( STRIKEOUT_SINGLE );
-
- aFont.SetOrientation( (short)rFont.lfEscapement );
-
- Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
- if ( rFont.lfHeight > 0 )
- {
- // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
- SolarMutexGuard aGuard;
- ScopedVclPtrInstance< VirtualDevice > pVDev;
- // converting the cell height into a font height
- aFont.SetFontSize( aFontSize );
- pVDev->SetFont( aFont );
- FontMetric aMetric( pVDev->GetFontMetric() );
- long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
- if (nHeight)
- {
- double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
- aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
- }
- }
-
- // Convert height to positive
- aFontSize.Height() = std::abs(aFontSize.Height());
-
- aFont.SetFontSize(aFontSize);
-};
-
-WinMtf::WinMtf( GDIMetaFile& rGDIMetaFile, SvStream& rStreamWMF, FilterConfigItem* pConfigItem )
- : pOut( o3tl::make_unique<WinMtfOutput>(rGDIMetaFile) )
- , pWMF( &rStreamWMF )
- , nEndPos( 0 )
- , pFilterConfigItem( pConfigItem )
-{
- SvLockBytes *pLB = pWMF->GetLockBytes();
- if ( pLB )
- pLB->SetSynchronMode();
-
- nStartPos = pWMF->Tell();
-
- pOut->SetDevOrg( Point() );
- if ( pFilterConfigItem )
- {
- xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
- if ( xStatusIndicator.is() )
- {
- xStatusIndicator->start( OUString(), 100 );
- }
- }
-}
-
-WinMtf::~WinMtf()
-{
- if ( xStatusIndicator.is() )
- xStatusIndicator->end();
-}
-
-void WinMtf::Callback( sal_uInt16 nPercent )
-{
- if ( xStatusIndicator.is() )
- xStatusIndicator->setValue( nPercent );
-}
-
-Color WinMtf::ReadColor()
-{
- sal_uInt32 nColor;
- pWMF->ReadUInt32( nColor );
- return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) );
-};
-
-Point WinMtfOutput::ImplScale(const Point& rPoint) // Hack to set varying defaults for incompletely defined files.
-{
- if (!mbIsMapDevSet)
- return Point(rPoint.X() * UNDOCUMENTED_WIN_RCL_RELATION - mrclFrame.Left(),
- rPoint.Y() * UNDOCUMENTED_WIN_RCL_RELATION - mrclFrame.Top());
- else
- return rPoint;
-}
-
-Point WinMtfOutput::ImplMap( const Point& rPt )
-{
- if ( mnWinExtX && mnWinExtY )
- {
- double fX = rPt.X();
- double fY = rPt.Y();
-
- double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
- double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
-
- if ( mnGfxMode == GM_COMPATIBLE )
- {
- switch( mnMapMode )
- {
- case MM_LOENGLISH :
- {
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY;
- }
- break;
- case MM_HIENGLISH :
- {
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY;
- }
- break;
- case MM_TWIPS:
- {
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY;
- }
- break;
- case MM_LOMETRIC :
- {
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= 10;
- fY2 *= 10;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY;
- }
- break;
- case MM_HIMETRIC : // in hundredth of a millimeter
- {
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY;
- }
- break;
- default :
- {
- fX2 -= mnWinOrgX;
- fY2 -= mnWinOrgY;
- fX2 /= mnWinExtX;
- fY2 /= mnWinExtY;
- fX2 *= mnDevWidth;
- fY2 *= mnDevHeight;
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY; // fX2, fY2 now in device units
- fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
- fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
- }
- break;
- }
- fX2 -= mrclFrame.Left();
- fY2 -= mrclFrame.Top();
- }
- return Point( FRound( fX2 ), FRound( fY2 ) );
- }
- else
- return Point();
-};
-
-Size WinMtfOutput::ImplMap(const Size& rSz, bool bDoWorldTransform)
-{
- if ( mnWinExtX && mnWinExtY )
- {
- // #i121382# apply the whole WorldTransform, else a rotation will be misinterpreted
- double fWidth, fHeight;
- if (bDoWorldTransform)
- {
- fWidth = rSz.Width() * maXForm.eM11 + rSz.Height() * maXForm.eM21;
- fHeight = rSz.Width() * maXForm.eM12 + rSz.Height() * maXForm.eM22;
- }
- else
- {
- //take the scale, but not the rotation
- basegfx::B2DHomMatrix aMatrix(maXForm.eM11, maXForm.eM12, 0,
- maXForm.eM21, maXForm.eM22, 0);
- basegfx::B2DTuple aScale, aTranslate;
- double fRotate, fShearX;
- if (!aMatrix.decompose(aScale, aTranslate, fRotate, fShearX))
- {
- aScale.setX(1.0);
- aScale.setY(1.0);
- }
- fWidth = rSz.Width() * aScale.getX();
- fHeight = rSz.Height() * aScale.getY();
- }
-
- if ( mnGfxMode == GM_COMPATIBLE )
- {
- switch( mnMapMode )
- {
- case MM_LOENGLISH :
- {
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
- }
- break;
- case MM_HIENGLISH :
- {
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- }
- break;
- case MM_LOMETRIC :
- {
- fWidth *= 10;
- fHeight*=-10;
- }
- break;
- case MM_HIMETRIC : // in hundredth of millimeters
- {
- fHeight *= -1;
- }
- break;
- case MM_TWIPS:
- {
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
- }
- break;
- default :
- {
- fWidth /= mnWinExtX;
- fHeight /= mnWinExtY;
- fWidth *= mnDevWidth;
- fHeight *= mnDevHeight;
- fWidth *= (double)mnMillX * 100 / (double)mnPixX;
- fHeight *= (double)mnMillY * 100 / (double)mnPixY;
- }
- break;
- }
- }
- return Size( FRound( fWidth ), FRound( fHeight ) );
- }
- else
- return Size();
-}
-
-tools::Rectangle WinMtfOutput::ImplMap( const tools::Rectangle& rRect )
-{
- return tools::Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
-}
-
-void WinMtfOutput::ImplMap( vcl::Font& rFont )
-{
- // !!! HACK: we now always set the width to zero because the OS width is interpreted differently;
- // must later be made portable in SV (KA 1996-02-08)
- Size aFontSize = ImplMap (rFont.GetFontSize(), false);
-
- if( aFontSize.Height() < 0 )
- aFontSize.Height() *= -1;
-
- rFont.SetFontSize( aFontSize );
-
- if( ( mnWinExtX * mnWinExtY ) < 0 )
- rFont.SetOrientation( 3600 - rFont.GetOrientation() );
-}
-
-tools::Polygon& WinMtfOutput::ImplMap( tools::Polygon& rPolygon )
-{
- sal_uInt16 nPoints = rPolygon.GetSize();
- for ( sal_uInt16 i = 0; i < nPoints; i++ )
- {
- rPolygon[ i ] = ImplMap( rPolygon[ i ] );
- }
- return rPolygon;
-}
-
-void WinMtfOutput::ImplScale( tools::Polygon& rPolygon )
-{
- sal_uInt16 nPoints = rPolygon.GetSize();
- for ( sal_uInt16 i = 0; i < nPoints; i++ )
- {
- rPolygon[ i ] = ImplScale( rPolygon[ i ] );
- }
-}
-
-tools::PolyPolygon& WinMtfOutput::ImplScale( tools::PolyPolygon& rPolyPolygon )
-{
- sal_uInt16 nPolys = rPolyPolygon.Count();
- for (sal_uInt16 i = 0; i < nPolys; ++i)
- {
- ImplScale(rPolyPolygon[i]);
- }
- return rPolyPolygon;
-}
-
-tools::PolyPolygon& WinMtfOutput::ImplMap( tools::PolyPolygon& rPolyPolygon )
-{
- sal_uInt16 nPolys = rPolyPolygon.Count();
- for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
- return rPolyPolygon;
-}
-
-void WinMtfOutput::SelectObject( sal_Int32 nIndex )
-{
- if ( nIndex & ENHMETA_STOCK_OBJECT )
- {
- sal_uInt16 nStockId = (sal_uInt8)nIndex;
- switch( nStockId )
- {
- case WHITE_BRUSH :
- {
- maFillStyle = WinMtfFillStyle( Color( COL_WHITE ) );
- mbFillStyleSelected = true;
- }
- break;
- case LTGRAY_BRUSH :
- {
- maFillStyle = WinMtfFillStyle( Color( COL_LIGHTGRAY ) );
- mbFillStyleSelected = true;
- }
- break;
- case GRAY_BRUSH :
- case DKGRAY_BRUSH :
- {
- maFillStyle = WinMtfFillStyle( Color( COL_GRAY ) );
- mbFillStyleSelected = true;
- }
- break;
- case BLACK_BRUSH :
- {
- maFillStyle = WinMtfFillStyle( Color( COL_BLACK ) );
- mbFillStyleSelected = true;
- }
- break;
- case NULL_BRUSH :
- {
- maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), true );
- mbFillStyleSelected = true;
- }
- break;
- case WHITE_PEN :
- {
- maLineStyle = WinMtfLineStyle( Color( COL_WHITE ) );
- }
- break;
- case BLACK_PEN :
- {
- maLineStyle = WinMtfLineStyle( Color( COL_BLACK ) );
- }
- break;
- case NULL_PEN :
- {
- maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), true );
- }
- break;
- default:
- break;
- }
- }
- else
- {
- nIndex &= 0xffff; // safety check: don't allow index to be > 65535
-
- GDIObj *pGDIObj = nullptr;
-
- if ( (sal_uInt32)nIndex < vGDIObj.size() )
- pGDIObj = vGDIObj[ nIndex ].get();
-
- if ( pGDIObj )
- {
- const auto pen = dynamic_cast<WinMtfLineStyle*>(pGDIObj);
- if (pen)
- maLineStyle = *pen;
-
- const auto brush = dynamic_cast<WinMtfFillStyle*>(pGDIObj);
- if (brush)
- {
- maFillStyle = *brush;
- mbFillStyleSelected = true;
- }
-
- const auto font = dynamic_cast<WinMtfFontStyle*>(pGDIObj);
- if (font)
- maFont = font->aFont;
- }
- }
-}
-
-void WinMtfOutput::SetTextLayoutMode( ComplexTextLayoutFlags nTextLayoutMode )
-{
- mnTextLayoutMode = nTextLayoutMode;
-}
-
-void WinMtfOutput::SetBkMode( BkMode nMode )
-{
- mnBkMode = nMode;
-}
-
-void WinMtfOutput::SetBkColor( const Color& rColor )
-{
- maBkColor = rColor;
-}
-
-void WinMtfOutput::SetTextColor( const Color& rColor )
-{
- maTextColor = rColor;
-}
-
-void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign )
-{
- mnTextAlign = nAlign;
-}
-
-void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
-{
- vGDIObj.resize(nNewEntrys);
-}
-
-void WinMtfOutput::ImplDrawClippedPolyPolygon( const tools::PolyPolygon& rPolyPoly )
-{
- if ( rPolyPoly.Count() )
- {
- ImplSetNonPersistentLineColorTransparenz();
- if ( rPolyPoly.Count() == 1 )
- {
- if ( rPolyPoly.IsRect() )
- mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
- else
- {
- tools::Polygon aPoly( rPolyPoly[ 0 ] );
- sal_uInt16 nCount = aPoly.GetSize();
- if ( nCount )
- {
- if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
- {
- Point aPoint( aPoly[ 0 ] );
- aPoly.Insert( nCount, aPoint );
- }
- mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
- }
- }
- }
- else
- mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
- }
-}
-
-void WinMtfOutput::CreateObject( std::unique_ptr<GDIObj> pObject )
-{
- if ( pObject )
- {
- const auto pLineStyle = dynamic_cast<WinMtfLineStyle*>(pObject.get());
- const auto pFontStyle = dynamic_cast<WinMtfFontStyle*>(pObject.get());
-
- if ( pFontStyle )
- {
- if (pFontStyle->aFont.GetFontHeight() == 0)
- pFontStyle->aFont.SetFontHeight(423);
- ImplMap(pFontStyle->aFont); // defaulting to 12pt
- }
- else if ( pLineStyle )
- {
- Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
- aSize = ImplMap(aSize);
- pLineStyle->aLineInfo.SetWidth(aSize.Width());
- }
- }
- std::vector<std::unique_ptr<GDIObj>>::size_type nIndex;
- for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
- {
- if ( !vGDIObj[ nIndex ] )
- break;
- }
- if ( nIndex == vGDIObj.size() )
- ImplResizeObjectArry( vGDIObj.size() + 16 );
-
- vGDIObj[ nIndex ] = std::move(pObject);
-}
-
-void WinMtfOutput::CreateObjectIndexed( sal_Int32 nIndex, std::unique_ptr<GDIObj> pObject )
-{
- if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
- {
- nIndex &= 0xffff; // safety check: do not allow index to be > 65535
- if ( pObject )
- {
- const auto pLineStyle = dynamic_cast<WinMtfLineStyle*>(pObject.get());
- const auto pFontStyle = dynamic_cast<WinMtfFontStyle*>(pObject.get());
- if ( pFontStyle )
- {
- if (pFontStyle->aFont.GetFontHeight() == 0)
- pFontStyle->aFont.SetFontHeight(423);
- ImplMap(pFontStyle->aFont);
- }
- else if ( pLineStyle )
- {
- Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
- pLineStyle->aLineInfo.SetWidth( ImplMap(aSize).Width() );
-
- if ( pLineStyle->aLineInfo.GetStyle() == LineStyle::Dash )
- {
- aSize.Width() += 1;
- long nDotLen = ImplMap( aSize ).Width();
- pLineStyle->aLineInfo.SetDistance( nDotLen );
- pLineStyle->aLineInfo.SetDotLen( nDotLen );
- pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 );
- }
- }
- }
- if ( (sal_uInt32)nIndex >= vGDIObj.size() )
- ImplResizeObjectArry( nIndex + 16 );
-
- vGDIObj[ nIndex ] = std::move(pObject);
- }
-}
-
-void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
-{
- if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
- {
- if ( (sal_uInt32)nIndex < vGDIObj.size() )
- {
- vGDIObj[ nIndex ].reset();
- }
- }
-}
-
-void WinMtfOutput::IntersectClipRect( const tools::Rectangle& rRect )
-{
- mbClipNeedsUpdate=true;
- if ((rRect.Left()-rRect.Right()==0) && (rRect.Top()-rRect.Bottom()==0))
- {
- return; // empty rectangles cause trouble
- }
- aClipPath.intersectClipRect( ImplMap( rRect ) );
-}
-
-void WinMtfOutput::ExcludeClipRect( const tools::Rectangle& rRect )
-{
- mbClipNeedsUpdate=true;
- aClipPath.excludeClipRect( ImplMap( rRect ) );
-}
-
-void WinMtfOutput::MoveClipRegion( const Size& rSize )
-{
- mbClipNeedsUpdate=true;
- aClipPath.moveClipRegion( ImplMap( rSize ) );
-}
-
-void WinMtfOutput::SetClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, bool bIsMapped )
-{
- mbClipNeedsUpdate = true;
- tools::PolyPolygon aPolyPolygon(rPolyPolygon);
-
- if (!bIsMapped)
- {
- if (!mbIsMapDevSet && (mnMapMode == MM_ISOTROPIC || mnMapMode == MM_ANISOTROPIC))
- aPolyPolygon = ImplScale(aPolyPolygon);
- else
- aPolyPolygon = ImplMap(aPolyPolygon);
- }
- aClipPath.setClipPath(aPolyPolygon, nClippingMode);
-}
-
-void WinMtfOutput::SetDefaultClipPath()
-{
- mbClipNeedsUpdate = true;
- aClipPath.setDefaultClipPath();
-}
-
-WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
- mnLatestTextAlign ( 0 ),
- mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
- maLatestBkColor ( 0x12345678 ),
- maBkColor ( COL_WHITE ),
- mnLatestTextLayoutMode( ComplexTextLayoutFlags::Default ),
- mnTextLayoutMode ( ComplexTextLayoutFlags::Default ),
- mnLatestBkMode ( BkMode::NONE ),
- mnBkMode ( BkMode::OPAQUE ),
- meLatestRasterOp ( RasterOp::Invert ),
- meRasterOp ( RasterOp::OverPaint ),
- maActPos ( Point() ),
- mbNopMode ( false ),
- mbFillStyleSelected ( false ),
- mbClipNeedsUpdate ( true ),
- mbComplexClip ( false ),
- mnGfxMode ( GM_COMPATIBLE ),
- mnMapMode ( MM_TEXT ),
- mnDevOrgX ( 0 ),
- mnDevOrgY ( 0 ),
- mnDevWidth ( 1 ),
- mnDevHeight ( 1 ),
- mnWinOrgX ( 0 ),
- mnWinOrgY ( 0 ),
- mnWinExtX ( 1 ),
- mnWinExtY ( 1 ),
- mnPixX ( 100 ),
- mnPixY ( 100 ),
- mnMillX ( 1 ),
- mnMillY ( 1 ),
- mpGDIMetaFile ( &rGDIMetaFile )
-{
- mbIsMapWinSet = false;
- mbIsMapDevSet = false;
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) ); // The original clipregion has to be on top
- // of the stack so it can always be restored
- // this is necessary to be able to support
- // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
-
- maFont.SetFamilyName( "Arial" ); // sj: #i57205#, we do have some scaling problems if using
- maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 ); // the default font then most times a x11 font is used, we
- maFont.SetFontHeight( 423 ); // will prevent this defining a font
-
- maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
- maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
-
- mnRop = WMFRasterOp::Black;
- meRasterOp = RasterOp::OverPaint;
- mpGDIMetaFile->AddAction( new MetaRasterOpAction( RasterOp::OverPaint ) );
-}
-
-WinMtfOutput::~WinMtfOutput()
-{
- mpGDIMetaFile->AddAction( new MetaPopAction() );
- mpGDIMetaFile->SetPrefMapMode( MapUnit::Map100thMM );
- if ( mrclFrame.IsEmpty() )
- mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
- else
- mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
-}
-
-void WinMtfOutput::UpdateClipRegion()
-{
- if ( mbClipNeedsUpdate )
- {
- mbClipNeedsUpdate = false;
- mbComplexClip = false;
-
- mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the original clipregion
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) );
-
- // skip for 'no clipping at all' case
- if( !aClipPath.isEmpty() )
- {
- const basegfx::B2DPolyPolygon& rClipPoly( aClipPath.getClipPath() );
-
- mbComplexClip = rClipPoly.count() > 1
- || !basegfx::tools::isRectangle(rClipPoly);
-
- static bool bEnableComplexClipViaRegion = getenv("SAL_WMF_COMPLEXCLIP_VIA_REGION") != nullptr;
-
- if (bEnableComplexClipViaRegion)
- {
- //this makes cases like tdf#45820 work in reasonable time, and I feel in theory should
- //be just fine. In practice I see the output is different so needs work before its the
- //default, but for file fuzzing it should be good enough
- if (mbComplexClip)
- {
- mpGDIMetaFile->AddAction(
- new MetaISectRegionClipRegionAction(
- vcl::Region(rClipPoly)));
- mbComplexClip = false;
- }
- else
- {
- mpGDIMetaFile->AddAction(
- new MetaISectRectClipRegionAction(
- vcl::unotools::rectangleFromB2DRectangle(
- rClipPoly.getB2DRange())));
- }
- }
- else
- {
- //normal case
- mpGDIMetaFile->AddAction(
- new MetaISectRectClipRegionAction(
- vcl::unotools::rectangleFromB2DRectangle(
- rClipPoly.getB2DRange())));
- }
- }
- }
-}
-
-void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
-{
- Color aColor( COL_TRANSPARENT);
- WinMtfLineStyle aTransparentLine( aColor, true );
- if ( ! ( maLatestLineStyle == aTransparentLine ) )
- {
- maLatestLineStyle = aTransparentLine;
- mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
- }
-}
-
-void WinMtfOutput::UpdateLineStyle()
-{
- if (!( maLatestLineStyle == maLineStyle ) )
- {
- maLatestLineStyle = maLineStyle;
- mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
- }
-}
-
-void WinMtfOutput::UpdateFillStyle()
-{
- if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
- maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == BkMode::Transparent );
- if (!( maLatestFillStyle == maFillStyle ) )
- {
- maLatestFillStyle = maFillStyle;
- if (maFillStyle.aType == WinMtfFillStyleType::Solid)
- mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
- }
-}
-
-WMFRasterOp WinMtfOutput::SetRasterOp( WMFRasterOp nRasterOp )
-{
- WMFRasterOp nRetROP = mnRop;
- if ( nRasterOp != mnRop )
- {
- mnRop = nRasterOp;
-
- if ( mbNopMode && ( nRasterOp != WMFRasterOp::Nop ) )
- { // changing modes from WMFRasterOp::Nop so set pen and brush
- maFillStyle = m_NopFillStyle;
- maLineStyle = m_NopLineStyle;
- mbNopMode = false;
- }
- switch( nRasterOp )
- {
- case WMFRasterOp::Not:
- meRasterOp = RasterOp::Invert;
- break;
-
- case WMFRasterOp::XorPen:
- meRasterOp = RasterOp::Xor;
- break;
-
- case WMFRasterOp::Nop:
- {
- meRasterOp = RasterOp::OverPaint;
- if( !mbNopMode )
- {
- m_NopFillStyle = maFillStyle;
- m_NopLineStyle = maLineStyle;
- maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), true );
- maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), true );
- mbNopMode = true;
- }
- }
- break;
-
- default:
- meRasterOp = RasterOp::OverPaint;
- break;
- }
- }
- if ( nRetROP != nRasterOp )
- mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
- return nRetROP;
-};
-
-void WinMtfOutput::StrokeAndFillPath( bool bStroke, bool bFill )
-{
- if ( aPathObj.Count() )
- {
- UpdateClipRegion();
- UpdateLineStyle();
- UpdateFillStyle();
- if ( bFill )
- {
- if ( !bStroke )
- {
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
- mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) );
- }
- if ( aPathObj.Count() == 1 )
- mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
- else
- mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
-
- if ( !bStroke )
- mpGDIMetaFile->AddAction( new MetaPopAction() );
- }
- else
- {
- sal_uInt16 i, nCount = aPathObj.Count();
- for ( i = 0; i < nCount; i++ )
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
- }
- ClearPath();
- }
-}
-
-void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
-{
- mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
-}
-
-void WinMtfOutput::MoveTo( const Point& rPoint, bool bRecordPath )
-{
- Point aDest( ImplMap( rPoint ) );
- if ( bRecordPath )
- {
- // fdo#57353 create new subpath for subsequent moves
- if ( aPathObj.Count() )
- if ( aPathObj[ aPathObj.Count() - 1 ].GetSize() )
- aPathObj.Insert( tools::Polygon() );
- aPathObj.AddPoint( aDest );
- }
- maActPos = aDest;
-}
-
-void WinMtfOutput::LineTo( const Point& rPoint, bool bRecordPath )
-{
- UpdateClipRegion();
- Point aDest( ImplMap( rPoint ) );
- if ( bRecordPath )
- aPathObj.AddPoint( aDest );
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
- }
- maActPos = aDest;
-}
-
-void WinMtfOutput::DrawRect( const tools::Rectangle& rRect, bool bEdge )
-{
- UpdateClipRegion();
- UpdateFillStyle();
-
- if ( mbComplexClip )
- {
- tools::Polygon aPoly( ImplMap( rRect ) );
- tools::PolyPolygon aPolyPolyRect( aPoly );
- tools::PolyPolygon aDest;
- tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
- ImplDrawClippedPolyPolygon( aDest );
- }
- else
- {
- if ( bEdge )
- {
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
- }
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
- }
- }
- else
- {
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
- }
- }
-}
-
-void WinMtfOutput::DrawRoundRect( const tools::Rectangle& rRect, const Size& rSize )
-{
- UpdateClipRegion();
- UpdateLineStyle();
- UpdateFillStyle();
- mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
-}
-
-void WinMtfOutput::DrawEllipse( const tools::Rectangle& rRect )
-{
- UpdateClipRegion();
- UpdateFillStyle();
-
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- Point aCenter( ImplMap( rRect.Center() ) );
- Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
-
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
- }
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
- }
-}
-
-void WinMtfOutput::DrawArc( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd, bool bTo )
-{
- UpdateClipRegion();
- UpdateLineStyle();
- UpdateFillStyle();
-
- tools::Rectangle aRect( ImplMap( rRect ) );
- Point aStart( ImplMap( rStart ) );
- Point aEnd( ImplMap( rEnd ) );
-
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- if ( aStart == aEnd )
- { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
- Point aCenter( aRect.Center() );
- Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
-
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
- }
- else
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Arc ), maLineStyle.aLineInfo ) );
- }
- else
- mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
-
- if ( bTo )
- maActPos = aEnd;
-}
-
-void WinMtfOutput::DrawPie( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd )
-{
- UpdateClipRegion();
- UpdateFillStyle();
-
- tools::Rectangle aRect( ImplMap( rRect ) );
- Point aStart( ImplMap( rStart ) );
- Point aEnd( ImplMap( rEnd ) );
-
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Pie ), maLineStyle.aLineInfo ) );
- }
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
- }
-}
-
-void WinMtfOutput::DrawChord( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd )
-{
- UpdateClipRegion();
- UpdateFillStyle();
-
- tools::Rectangle aRect( ImplMap( rRect ) );
- Point aStart( ImplMap( rStart ) );
- Point aEnd( ImplMap( rEnd ) );
-
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Chord ), maLineStyle.aLineInfo ) );
- }
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
- }
-}
-
-void WinMtfOutput::DrawPolygon( tools::Polygon& rPolygon, bool bRecordPath )
-{
- UpdateClipRegion();
- ImplMap( rPolygon );
- if ( bRecordPath )
- aPathObj.AddPolygon( rPolygon );
- else
- {
- UpdateFillStyle();
-
- if ( mbComplexClip )
- {
- tools::PolyPolygon aPolyPoly( rPolygon );
- tools::PolyPolygon aDest;
- tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPoly, aDest );
- ImplDrawClippedPolyPolygon( aDest );
- }
- else
- {
- if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
- {
- sal_uInt16 nCount = rPolygon.GetSize();
- if ( nCount )
- {
- if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
- {
- Point aPoint( rPolygon[ 0 ] );
- rPolygon.Insert( nCount, aPoint );
- }
- }
- ImplSetNonPersistentLineColorTransparenz();
- mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
- }
- else
- {
- UpdateLineStyle();
-
- if (maLatestFillStyle.aType != WinMtfFillStyleType::Pattern)
- mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
- else {
- SvtGraphicFill aFill = SvtGraphicFill( tools::PolyPolygon( rPolygon ),
- Color(),
- 0.0,
- SvtGraphicFill::fillNonZero,
- SvtGraphicFill::fillTexture,
- SvtGraphicFill::Transform(),
- true,
- SvtGraphicFill::hatchSingle,
- Color(),
- SvtGraphicFill::GradientType::Linear,
- Color(),
- Color(),
- 0,
- Graphic (maLatestFillStyle.aBmp) );
-
- SvMemoryStream aMemStm;
-
- WriteSvtGraphicFill( aMemStm, aFill );
-
- mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
- static_cast<const sal_uInt8*>(aMemStm.GetData()),
- aMemStm.Seek( STREAM_SEEK_TO_END ) ) );
- mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
- }
-
- }
- }
- }
-}
-
-void WinMtfOutput::DrawPolyPolygon( tools::PolyPolygon& rPolyPolygon, bool bRecordPath )
-{
- UpdateClipRegion();
-
- ImplMap( rPolyPolygon );
-
- if ( bRecordPath )
- aPathObj.AddPolyPolygon( rPolyPolygon );
- else
- {
- UpdateFillStyle();
-
- if ( mbComplexClip )
- {
- tools::PolyPolygon aDest;
- tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
- ImplDrawClippedPolyPolygon( aDest );
- }
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
- if (maLineStyle.aLineInfo.GetWidth() > 0 || maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash)
- {
- for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.Count(); ++nPoly)
- {
- mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolyPolygon[nPoly], maLineStyle.aLineInfo));
- }
- }
- }
- }
-}
-
-void WinMtfOutput::DrawPolyLine( tools::Polygon& rPolygon, bool bTo, bool bRecordPath )
-{
- UpdateClipRegion();
-
- sal_uInt16 nPoints = rPolygon.GetSize();
- if (nPoints >= 1)
- {
- ImplMap( rPolygon );
- if ( bTo )
- {
- rPolygon[ 0 ] = maActPos;
- maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
- }
- if ( bRecordPath )
- aPathObj.AddPolyLine( rPolygon );
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
- }
- }
-}
-
-void WinMtfOutput::DrawPolyBezier( tools::Polygon& rPolygon, bool bTo, bool bRecordPath )
-{
- sal_uInt16 nPoints = rPolygon.GetSize();
- if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
- {
- UpdateClipRegion();
-
- ImplMap( rPolygon );
- if ( bTo )
- {
- rPolygon[ 0 ] = maActPos;
- maActPos = rPolygon[ nPoints - 1 ];
- }
- sal_uInt16 i;
- for ( i = 0; ( i + 2 ) < nPoints; )
- {
- rPolygon.SetFlags( i++, PolyFlags::Normal );
- rPolygon.SetFlags( i++, PolyFlags::Control );
- rPolygon.SetFlags( i++, PolyFlags::Control );
- }
- if ( bRecordPath )
- aPathObj.AddPolyLine( rPolygon );
- else
- {
- UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
- }
- }
-}
-
-void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, long* pDYArry, bool bRecordPath, sal_Int32 nGfxMode )
-{
- UpdateClipRegion();
- rPosition = ImplMap( rPosition );
- sal_Int32 nOldGfxMode = GetGfxMode();
- SetGfxMode( GM_COMPATIBLE );
-
- if (pDXArry)
- {
- sal_Int32 nSumX = 0, nSumY = 0;
- for (sal_Int32 i = 0; i < rText.getLength(); i++ )
- {
- nSumX += pDXArry[i];
-
- // #i121382# Map DXArray using WorldTransform
- const Size aSizeX(ImplMap(Size(nSumX, 0)));
- const basegfx::B2DVector aVectorX(aSizeX.Width(), aSizeX.Height());
- pDXArry[i] = basegfx::fround(aVectorX.getLength()) * (nSumX >= 0 ? 1 : -1);
-
- if (pDYArry)
- {
- nSumY += pDYArry[i];
-
- const Size aSizeY(ImplMap(Size(0, nSumY)));
- const basegfx::B2DVector aVectorY(aSizeY.Width(), aSizeY.Height());
- // Reverse Y
- pDYArry[i] = basegfx::fround(aVectorY.getLength()) * (nSumY >= 0 ? -1 : 1);
- }
- }
- }
- if ( mnLatestTextLayoutMode != mnTextLayoutMode )
- {
- mnLatestTextLayoutMode = mnTextLayoutMode;
- mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
- }
- SetGfxMode( nGfxMode );
- TextAlign eTextAlign;
- if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
- eTextAlign = ALIGN_BASELINE;
- else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
- eTextAlign = ALIGN_BOTTOM;
- else
- eTextAlign = ALIGN_TOP;
- bool bChangeFont = false;
- if ( mnLatestTextAlign != mnTextAlign )
- {
- bChangeFont = true;
- mnLatestTextAlign = mnTextAlign;
- mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
- }
- if ( maLatestTextColor != maTextColor )
- {
- bChangeFont = true;
- maLatestTextColor = maTextColor;
- mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
- }
- bool bChangeFillColor = false;
- if ( maLatestBkColor != maBkColor )
- {
- bChangeFillColor = true;
- maLatestBkColor = maBkColor;
- }
- if ( mnLatestBkMode != mnBkMode )
- {
- bChangeFillColor = true;
- mnLatestBkMode = mnBkMode;
- }
- if ( bChangeFillColor )
- {
- bChangeFont = true;
- mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
- }
- vcl::Font aTmp( maFont );
- aTmp.SetColor( maTextColor );
- aTmp.SetFillColor( maBkColor );
-
- if( mnBkMode == BkMode::Transparent )
- aTmp.SetTransparent( true );
- else
- aTmp.SetTransparent( false );
-
- aTmp.SetAlignment( eTextAlign );
-
- if ( nGfxMode == GM_ADVANCED )
- {
- // check whether there is a font rotation applied via transformation
- Point aP1( ImplMap( Point() ) );
- Point aP2( ImplMap( Point( 0, 100 ) ) );
- aP2.X() -= aP1.X();
- aP2.Y() -= aP1.Y();
- double fX = aP2.X();
- double fY = aP2.Y();
- if ( fX )
- {
- double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
- if ( fY > 0 )
- fOrientation = 360 - fOrientation;
- fOrientation += 90;
- fOrientation *= 10;
- fOrientation += aTmp.GetOrientation();
- aTmp.SetOrientation( sal_Int16( fOrientation ) );
- }
- }
-
- if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
- {
- // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
- SolarMutexGuard aGuard;
- ScopedVclPtrInstance< VirtualDevice > pVDev;
- sal_Int32 nTextWidth;
- Point aActPosDelta;
- pVDev->SetMapMode( MapMode( MapUnit::Map100thMM ) );
- pVDev->SetFont( maFont );
- const sal_uInt32 nLen = pDXArry ? rText.getLength() : 0;
- if (nLen)
- {
- nTextWidth = pVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
- if( nLen > 1 )
- nTextWidth += pDXArry[ nLen - 2 ];
- // tdf#39894: We should consider the distance to next character cell origin
- aActPosDelta.X() = pDXArry[ nLen - 1 ];
- if ( pDYArry )
- {
- aActPosDelta.Y() = pDYArry[ nLen - 1 ];
- }
- }
- else
- {
- nTextWidth = pVDev->GetTextWidth( rText );
- aActPosDelta.X() = nTextWidth;
- }
-
- if( mnTextAlign & TA_UPDATECP )
- rPosition = maActPos;
-
- if ( mnTextAlign & TA_RIGHT_CENTER )
- {
- Point aDisplacement( ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1, 0 );
- Point().RotateAround(aDisplacement.X(), aDisplacement.Y(), maFont.GetOrientation());
- rPosition -= aDisplacement;
- }
-
- if( mnTextAlign & TA_UPDATECP )
- {
- Point().RotateAround(aActPosDelta.X(), aActPosDelta.Y(), maFont.GetOrientation());
- maActPos = rPosition + aActPosDelta;
- }
- }
- if ( bChangeFont || ( maLatestFont != aTmp ) )
- {
- maLatestFont = aTmp;
- mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
- mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlignment() ) );
- mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
- mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
- }
- if ( bRecordPath )
- {
- // TODO
- }
- else
- {
- if ( pDXArry && pDYArry )
- {
- for (sal_Int32 i = 0; i < rText.getLength(); ++i)
- {
- Point aCharDisplacement( i ? pDXArry[i-1] : 0, i ? pDYArry[i-1] : 0 );
- Point().RotateAround(aCharDisplacement.X(), aCharDisplacement.Y(), maFont.GetOrientation());
- mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition + aCharDisplacement, OUString( rText[i] ), nullptr, 0, 1 ) );
- }
- }
- else
- {
- /* because text without dx array is badly scaled, we
- will create such an array if necessary */
- long* pDX = pDXArry;
- if (!pDXArry)
- {
- // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
- SolarMutexGuard aGuard;
- ScopedVclPtrInstance< VirtualDevice > pVDev;
- pDX = new long[ rText.getLength() ];
- pVDev->SetMapMode( MapUnit::Map100thMM );
- pVDev->SetFont( maLatestFont );
- pVDev->GetTextArray( rText, pDX, 0, rText.getLength());
- }
- mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, rText.getLength() ) );
- if ( !pDXArry ) // this means we have created our own array
- delete[] pDX; // which must be deleted
- }
- }
- SetGfxMode( nOldGfxMode );
-}
-
-void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx& rBitmap )
-{
- BitmapEx aBmpEx( rBitmap );
- if ( mbComplexClip )
- {
- VclPtrInstance< VirtualDevice > pVDev;
- MapMode aMapMode( MapUnit::Map100thMM );
- aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
- const Size aOutputSizePixel( pVDev->LogicToPixel( rSize, aMapMode ) );
- const Size aSizePixel( rBitmap.GetSizePixel() );
- if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
- {
- aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
- aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
- }
- pVDev->SetMapMode( aMapMode );
- pVDev->SetOutputSizePixel( aSizePixel );
- pVDev->SetFillColor( Color( COL_BLACK ) );
- const tools::PolyPolygon aClip( aClipPath.getClipPath() );
- pVDev->DrawPolyPolygon( aClip );
- const Point aEmptyPoint;
-
- // #i50672# Extract whole VDev content (to match size of rBitmap)
- pVDev->EnableMapMode( false );
- const Bitmap aVDevMask(pVDev->GetBitmap(aEmptyPoint, aSizePixel));
-
- if(aBmpEx.IsTransparent())
- {
- // bitmap already uses a Mask or Alpha, we need to blend that with
- // the new masking in pVDev
- if(aBmpEx.IsAlpha())
- {
- // need to blend in AlphaMask quality (8Bit)
- AlphaMask fromVDev(aVDevMask);
- AlphaMask fromBmpEx(aBmpEx.GetAlpha());
- AlphaMask::ScopedReadAccess pR(fromVDev);
- AlphaMask::ScopedWriteAccess pW(fromBmpEx);
-
- if(pR && pW)
- {
- const long nWidth(std::min(pR->Width(), pW->Width()));
- const long nHeight(std::min(pR->Height(), pW->Height()));
-
- for(long nY(0); nY < nHeight; nY++) for(long nX(0); nX < nWidth; nX++)
- {
- const sal_uInt8 nIndR(pR->GetPixelIndex(nY, nX));
- const sal_uInt8 nIndW(pW->GetPixelIndex(nY, nX));
-
- // these values represent transparency (0 == no, 255 == fully transparent),
- // so to blend these we have to multiply the inverse (opacity)
- // and re-invert the result to transparence
- const sal_uInt8 nCombined(0x00ff - (((0x00ff - nIndR) * (0x00ff - nIndW)) >> 8));
-
- pW->SetPixelIndex(nY, nX, nCombined);
- }
- }
-
- pR.reset();
- pW.reset();
- aBmpEx = BitmapEx(aBmpEx.GetBitmap(), fromBmpEx);
- }
- else
- {
- // need to blend in Mask quality (1Bit)
- Bitmap aMask(aVDevMask.CreateMask(Color(COL_WHITE)));
-
- if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
- {
- aMask.CombineSimple( rBitmap.GetMask(), BmpCombine::Or );
- }
- else
- {
- aMask.CombineSimple( rBitmap.GetMask(), BmpCombine::And );
- }
-
- aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
- }
- }
- else
- {
- // no mask yet, create and add new mask. For better quality, use Alpha,
- // this allows the drawn mask being processed with AntiAliasing (AAed)
- aBmpEx = BitmapEx(rBitmap.GetBitmap(), aVDevMask);
- }
- }
-
- if ( aBmpEx.IsTransparent() )
- mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
- else
- mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
-}
-
-void WinMtfOutput::ResolveBitmapActions( std::vector<std::unique_ptr<BSaveStruct>>& rSaveList )
-{
- UpdateClipRegion();
-
- size_t nObjects = rSaveList.size();
- size_t nObjectsLeft = nObjects;
-
- while ( nObjectsLeft )
- {
- size_t i;
- size_t nObjectsOfSameSize = 0;
- size_t nObjectStartIndex = nObjects - nObjectsLeft;
-
- BSaveStruct* pSave = rSaveList[nObjectStartIndex].get();
- tools::Rectangle aRect( pSave->aOutRect );
-
- for ( i = nObjectStartIndex; i < nObjects; )
- {
- nObjectsOfSameSize++;
- if ( ++i < nObjects )
- {
- pSave = rSaveList[i].get();
- if ( pSave->aOutRect != aRect )
- break;
- }
- }
- Point aPos( ImplMap( aRect.TopLeft() ) );
- Size aSize( ImplMap( aRect.GetSize() ) );
-
- for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
- {
- pSave = rSaveList[i].get();
-
- sal_uInt32 nWinRop = pSave->nWinRop;
- sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
-
- sal_uInt32 nUsed = 0;
- if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
- nUsed |= 1; // pattern is used
- if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
- nUsed |= 2; // source is used
- if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
- nUsed |= 4; // destination is used
-
- if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
- { // patterns aren't well supported yet
- WMFRasterOp nOldRop = SetRasterOp( WMFRasterOp::NONE ); // in this case nRasterOperation is either 0 or 0xff
- UpdateFillStyle();
- DrawRect( aRect, false );
- SetRasterOp( nOldRop );
- }
- else
- {
- bool bDrawn = false;
-
- if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
- {
- if ( nObjectsOfSameSize == 2 )
- {
- BSaveStruct* pSave2 = rSaveList[i + 1].get();
- if ( ( pSave->aBmpEx.GetPrefSize() == pSave2->aBmpEx.GetPrefSize() ) &&
- ( pSave->aBmpEx.GetPrefMapMode() == pSave2->aBmpEx.GetPrefMapMode() ) )
- {
- // TODO: Strictly speaking, we should
- // check whether mask is monochrome, and
- // whether image is black (upper branch)
- // or white (lower branch). Otherwise, the
- // effect is not the same as a masked
- // bitmap.
- if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
- {
- Bitmap aMask( pSave->aBmpEx.GetBitmap() ); aMask.Invert();
- BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- bDrawn = true;
- i++;
- }
- // #i20085# This is just the other way
- // around as above. Only difference: mask
- // is inverted
- else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
- {
- Bitmap aMask( pSave->aBmpEx.GetBitmap() );
- BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- bDrawn = true;
- i++;
- }
- // tdf#90539
- else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCINVERT ) )
- {
- Bitmap aMask( pSave->aBmpEx.GetBitmap() );
- BitmapEx aBmpEx( pSave2->aBmpEx.GetBitmap(), aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- bDrawn = true;
- i++;
- }
- }
- }
- }
-
- if ( !bDrawn )
- {
- Push();
- WMFRasterOp nOldRop = SetRasterOp( WMFRasterOp::CopyPen );
- Bitmap aBitmap( pSave->aBmpEx.GetBitmap() );
- sal_uInt32 nOperation = ( nRasterOperation & 0xf );
- switch( nOperation )
- {
- case 0x1 :
- case 0xe :
- {
- if(pSave->aBmpEx.IsAlpha())
- {
- ImplDrawBitmap( aPos, aSize, pSave->aBmpEx );
- }
- else
- {
- SetRasterOp( WMFRasterOp::XorPen );
- ImplDrawBitmap( aPos, aSize, aBitmap );
- SetRasterOp( WMFRasterOp::CopyPen );
- Bitmap aMask( aBitmap );
- aMask.Invert();
- BitmapEx aBmpEx( aBitmap, aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- if ( nOperation == 0x1 )
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- }
- }
- break;
- case 0x7 :
- case 0x8 :
- {
- Bitmap aMask( aBitmap );
- if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
- {
- aBitmap.Convert( BmpConversion::N24Bit );
- aBitmap.Erase( maFillStyle.aFillColor );
- }
- BitmapEx aBmpEx( aBitmap, aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- if ( nOperation == 0x7 )
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- }
- break;
-
- case 0x4 :
- case 0xb :
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- SetRasterOp( WMFRasterOp::CopyPen );
- Bitmap aMask( aBitmap );
- aBitmap.Invert();
- BitmapEx aBmpEx( aBitmap, aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- SetRasterOp( WMFRasterOp::XorPen );
- ImplDrawBitmap( aPos, aSize, aBitmap );
- if ( nOperation == 0xb )
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- }
- break;
-
- case 0x2 :
- case 0xd :
- {
- Bitmap aMask( aBitmap );
- aMask.Invert();
- BitmapEx aBmpEx( aBitmap, aMask );
- ImplDrawBitmap( aPos, aSize, aBmpEx );
- SetRasterOp( WMFRasterOp::XorPen );
- ImplDrawBitmap( aPos, aSize, aBitmap );
- if ( nOperation == 0xd )
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- }
- break;
- case 0x6 :
- case 0x9 :
- {
- SetRasterOp( WMFRasterOp::XorPen );
- ImplDrawBitmap( aPos, aSize, aBitmap );
- if ( nOperation == 0x9 )
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- }
- break;
-
- case 0x0 : // WHITENESS
- case 0xf : // BLACKNESS
- { // in this case nRasterOperation is either 0 or 0xff
- maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
- UpdateFillStyle();
- DrawRect( aRect, false );
- }
- break;
-
- case 0x3 : // only source is used
- case 0xc :
- {
- if ( nRasterOperation == 0x33 )
- aBitmap.Invert();
- ImplDrawBitmap( aPos, aSize, aBitmap );
- }
- break;
-
- case 0x5 : // only destination is used
- {
- SetRasterOp( WMFRasterOp::Not );
- DrawRect( aRect, false );
- }
- break;
-
- case 0xa : // no operation
- break;
- }
- SetRasterOp( nOldRop );
- Pop();
- }
- }
- }
- nObjectsLeft -= nObjectsOfSameSize;
- }
-
- rSaveList.clear();
-}
-
-void WinMtfOutput::SetDevOrg( const Point& rPoint )
-{
- mnDevOrgX = rPoint.X();
- mnDevOrgY = rPoint.Y();
-}
-
-void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
-{
- mnDevOrgX += nXAdd;
- mnDevOrgY += nYAdd;
-}
-
-void WinMtfOutput::SetDevExt( const Size& rSize ,bool regular)
-{
- if ( rSize.Width() && rSize.Height() )
- {
- switch( mnMapMode )
- {
- case MM_ISOTROPIC :
- case MM_ANISOTROPIC :
- {
- mnDevWidth = rSize.Width();
- mnDevHeight = rSize.Height();
- }
- }
- if (regular)
- {
- mbIsMapDevSet=true;
- }
- }
-}
-
-void WinMtfOutput::ScaleDevExt( double fX, double fY )
-{
- mnDevWidth = FRound( mnDevWidth * fX );
- mnDevHeight = FRound( mnDevHeight * fY );
-}
-
-void WinMtfOutput::SetWinOrg( const Point& rPoint , bool bIsEMF)
-{
- mnWinOrgX = rPoint.X();
- mnWinOrgY = rPoint.Y();
- if (bIsEMF)
- {
- SetDevByWin();
- }
- mbIsMapWinSet=true;
-}
-
-void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
-{
- mnWinOrgX += nXAdd;
- mnWinOrgY += nYAdd;
-}
-
-void WinMtfOutput::SetDevByWin() //mnWinExt...-stuff has to be assigned before.
-{
- if (!mbIsMapDevSet)
- {
- if ( mnMapMode == MM_ISOTROPIC ) //TODO: WHAT ABOUT ANISOTROPIC???
- {
- Size aSize( (mnWinExtX + mnWinOrgX) >> MS_FIXPOINT_BITCOUNT_28_4,
- -((mnWinExtY - mnWinOrgY) >> MS_FIXPOINT_BITCOUNT_28_4));
-
- SetDevExt(aSize, false);
- }
- }
-}
-
-void WinMtfOutput::SetWinExt(const Size& rSize, bool bIsEMF)
-{
- if (rSize.Width() && rSize.Height())
- {
- switch( mnMapMode )
- {
- case MM_ISOTROPIC :
- case MM_ANISOTROPIC :
- {
- mnWinExtX = rSize.Width();
- mnWinExtY = rSize.Height();
- if (bIsEMF)
- {
- SetDevByWin();
- }
- mbIsMapWinSet = true;
- }
- }
- }
-}
-
-void WinMtfOutput::ScaleWinExt( double fX, double fY )
-{
- mnWinExtX = FRound( mnWinExtX * fX );
- mnWinExtY = FRound( mnWinExtY * fY );
-}
-
-void WinMtfOutput::SetrclBounds( const tools::Rectangle& rRect )
-{
- mrclBounds = rRect;
-}
-
-void WinMtfOutput::SetrclFrame( const tools::Rectangle& rRect )
-{
- mrclFrame = rRect;
-}
-
-void WinMtfOutput::SetRefPix( const Size& rSize )
-{
- mnPixX = rSize.Width();
- mnPixY = rSize.Height();
-}
-
-void WinMtfOutput::SetRefMill( const Size& rSize )
-{
- mnMillX = rSize.Width();
- mnMillY = rSize.Height();
-}
-
-void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
-{
- mnMapMode = nMapMode;
- if ( nMapMode == MM_TEXT && !mbIsMapWinSet )
- {
- mnWinExtX = mnDevWidth;
- mnWinExtY = mnDevHeight;
- }
- else if ( mnMapMode == MM_HIMETRIC )
- {
- mnWinExtX = mnMillX * 100;
- mnWinExtY = mnMillY * 100;
- }
-}
-
-void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
-{
- maXForm.eM11 = rXForm.eM11;
- maXForm.eM12 = rXForm.eM12;
- maXForm.eM21 = rXForm.eM21;
- maXForm.eM22 = rXForm.eM22;
- maXForm.eDx = rXForm.eDx;
- maXForm.eDy = rXForm.eDy;
-}
-
-void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
-{
- switch( nMode )
- {
- case MWT_IDENTITY :
- {
- maXForm.eM11 = maXForm.eM22 = 1.0f;
- maXForm.eM12 = maXForm.eM21 = maXForm.eDx = maXForm.eDy = 0.0f;
- break;
- }
-
- case MWT_RIGHTMULTIPLY :
- case MWT_LEFTMULTIPLY :
- {
- const XForm* pLeft;
- const XForm* pRight;
-
- if ( nMode == MWT_LEFTMULTIPLY )
- {
- pLeft = &rXForm;
- pRight = &maXForm;
- }
- else
- {
- pLeft = &maXForm;
- pRight = &rXForm;
- }
-
- float aF[3][3];
- float bF[3][3];
- float cF[3][3];
-
- aF[0][0] = pLeft->eM11;
- aF[0][1] = pLeft->eM12;
- aF[0][2] = 0;
- aF[1][0] = pLeft->eM21;
- aF[1][1] = pLeft->eM22;
- aF[1][2] = 0;
- aF[2][0] = pLeft->eDx;
- aF[2][1] = pLeft->eDy;
- aF[2][2] = 1;
-
- bF[0][0] = pRight->eM11;
- bF[0][1] = pRight->eM12;
- bF[0][2] = 0;
- bF[1][0] = pRight->eM21;
- bF[1][1] = pRight->eM22;
- bF[1][2] = 0;
- bF[2][0] = pRight->eDx;
- bF[2][1] = pRight->eDy;
- bF[2][2] = 1;
-
- int i, j, k;
- for ( i = 0; i < 3; i++ )
- {
- for ( j = 0; j < 3; j++ )
- {
- cF[i][j] = 0;
- for ( k = 0; k < 3; k++ )
- cF[i][j] += aF[i][k] * bF[k][j];
- }
- }
- maXForm.eM11 = cF[0][0];
- maXForm.eM12 = cF[0][1];
- maXForm.eM21 = cF[1][0];
- maXForm.eM22 = cF[1][1];
- maXForm.eDx = cF[2][0];
- maXForm.eDy = cF[2][1];
- break;
- }
- case MWT_SET:
- {
- SetWorldTransform(rXForm);
- break;
- }
- }
-}
-
-void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it
-{ // is not allowed to use the MetaPushAction()
- UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
- std::shared_ptr<SaveStruct> pSave( new SaveStruct );
-
- pSave->aLineStyle = maLineStyle;
- pSave->aFillStyle = maFillStyle;
-
- pSave->aFont = maFont;
- pSave->aTextColor = maTextColor;
- pSave->nTextAlign = mnTextAlign;
- pSave->nTextLayoutMode = mnTextLayoutMode;
- pSave->nMapMode = mnMapMode;
- pSave->nGfxMode = mnGfxMode;
- pSave->nBkMode = mnBkMode;
- pSave->aBkColor = maBkColor;
- pSave->bFillStyleSelected = mbFillStyleSelected;
-
- pSave->aActPos = maActPos;
- pSave->aXForm = maXForm;
- pSave->eRasterOp = meRasterOp;
-
- pSave->nWinOrgX = mnWinOrgX;
- pSave->nWinOrgY = mnWinOrgY;
- pSave->nWinExtX = mnWinExtX;
- pSave->nWinExtY = mnWinExtY;
- pSave->nDevOrgX = mnDevOrgX;
- pSave->nDevOrgY = mnDevOrgY;
- pSave->nDevWidth = mnDevWidth;
- pSave->nDevHeight = mnDevHeight;
-
- pSave->aPathObj = aPathObj;
- pSave->aClipPath = aClipPath;
-
- vSaveStack.push_back( pSave );
-}
-
-void WinMtfOutput::Pop()
-{
- // Get the latest data from the stack
- if( !vSaveStack.empty() )
- {
- // Backup the current data on the stack
- std::shared_ptr<SaveStruct> pSave( vSaveStack.back() );
-
- maLineStyle = pSave->aLineStyle;
- maFillStyle = pSave->aFillStyle;
-
- maFont = pSave->aFont;
- maTextColor = pSave->aTextColor;
- mnTextAlign = pSave->nTextAlign;
- mnTextLayoutMode = pSave->nTextLayoutMode;
- mnBkMode = pSave->nBkMode;
- mnGfxMode = pSave->nGfxMode;
- mnMapMode = pSave->nMapMode;
- maBkColor = pSave->aBkColor;
- mbFillStyleSelected = pSave->bFillStyleSelected;
-
- maActPos = pSave->aActPos;
- maXForm = pSave->aXForm;
- meRasterOp = pSave->eRasterOp;
-
- mnWinOrgX = pSave->nWinOrgX;
- mnWinOrgY = pSave->nWinOrgY;
- mnWinExtX = pSave->nWinExtX;
- mnWinExtY = pSave->nWinExtY;
- mnDevOrgX = pSave->nDevOrgX;
- mnDevOrgY = pSave->nDevOrgY;
- mnDevWidth = pSave->nDevWidth;
- mnDevHeight = pSave->nDevHeight;
-
- aPathObj = pSave->aPathObj;
- if ( ! ( aClipPath == pSave->aClipPath ) )
- {
- aClipPath = pSave->aClipPath;
- mbClipNeedsUpdate = true;
- }
- if ( meLatestRasterOp != meRasterOp )
- mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
- vSaveStack.pop_back();
- }
-}
-
-void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile )
-{
- rGDIMetaFile.Play( *mpGDIMetaFile );
-}
-
-void WinMtfOutput::PassEMFPlusHeaderInfo()
-{
- EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
-
- SvMemoryStream mem;
- sal_Int32 nLeft, nRight, nTop, nBottom;
-
- nLeft = mrclFrame.Left();
- nTop = mrclFrame.Top();
- nRight = mrclFrame.Right();
- nBottom = mrclFrame.Bottom();
-
- // emf header info
- mem.WriteInt32( nLeft ).WriteInt32( nTop ).WriteInt32( nRight ).WriteInt32( nBottom );
- mem.WriteInt32( mnPixX ).WriteInt32( mnPixY ).WriteInt32( mnMillX ).WriteInt32( mnMillY );
-
- float one, zero;
-
- one = 1;
- zero = 0;
-
- // add transformation matrix to be used in vcl's metaact.cxx for
- // rotate and scale operations
- mem.WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero ).WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero );
-
- // need to flush the stream, otherwise GetEndOfData will return 0
- // on windows where the function parameters are probably resolved in reverse order
- mem.Flush();
-
- mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, static_cast<const sal_uInt8*>(mem.GetData()), mem.GetEndOfData() ) );
- mpGDIMetaFile->UseCanvas( true );
-}
-
-void WinMtfOutput::PassEMFPlus( void* pBuffer, sal_uInt32 nLength )
-{
- EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
- mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx
deleted file mode 100644
index ff7d3d5307e9..000000000000
--- a/vcl/source/filter/wmf/winmtf.hxx
+++ /dev/null
@@ -1,718 +0,0 @@
-/* -*- 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_VCL_SOURCE_FILTER_WMF_WINMTF_HXX
-#define INCLUDED_VCL_SOURCE_FILTER_WMF_WINMTF_HXX
-
-#include <memory>
-#include <sal/config.h>
-
-#include <vcl/graph.hxx>
-#include <basegfx/tools/b2dclipstate.hxx>
-#include <vcl/font.hxx>
-#include <vcl/bitmapaccess.hxx>
-#include <vcl/lineinfo.hxx>
-#include <vcl/fltcall.hxx>
-#include <o3tl/make_unique.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
-
-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
-
-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
-
-struct LOGFONTW
-{
- sal_Int32 lfHeight;
- sal_Int32 lfWidth;
- sal_Int32 lfEscapement;
- sal_Int32 lfWeight;
- sal_uInt8 lfItalic;
- sal_uInt8 lfUnderline;
- sal_uInt8 lfStrikeOut;
- sal_uInt8 lfCharSet;
- 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 ==================================
-
-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)
- {}
-};
-
-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 WinMtfOutput 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 WinMtfOutput( GDIMetaFile& rGDIMetaFile );
- ~WinMtfOutput();
-};
-
-class WinMtf
-{
-protected:
-
- std::unique_ptr<WinMtfOutput> 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 );
-
- WinMtf(
- GDIMetaFile& rGDIMetaFile,
- SvStream& rStreamWMF,
- FilterConfigItem* pConfigItem
- );
- ~WinMtf();
-};
-
-class EnhWMFReader : public WinMtf
-{
- 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:
- EnhWMFReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile, FilterConfigItem* pConfigItem = nullptr);
- ~EnhWMFReader();
-
- 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);
-};
-
-class WMFReader : public WinMtf
-{
-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;
-
- 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/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx
deleted file mode 100644
index 501f36eabfe9..000000000000
--- a/vcl/source/filter/wmf/winwmf.cxx
+++ /dev/null
@@ -1,1833 +0,0 @@
-/* -*- 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 "winmtf.hxx"
-
-#include <memory>
-#include <boost/optional.hpp>
-#include <vcl/gdimtf.hxx>
-#include <vcl/wmf.hxx>
-#include <rtl/crc.h>
-#include <rtl/tencinfo.h>
-#include <osl/endian.h>
-#include <vcl/svapp.hxx>
-#include <vcl/dibtools.hxx>
-#include <tools/fract.hxx>
-#include <o3tl/make_unique.hxx>
-
-// MS Windows defines
-
-#define W_META_SETBKCOLOR 0x0201
-#define W_META_SETBKMODE 0x0102
-#define W_META_SETMAPMODE 0x0103
-#define W_META_SETROP2 0x0104
-#define W_META_SETRELABS 0x0105
-#define W_META_SETPOLYFILLMODE 0x0106
-#define W_META_SETSTRETCHBLTMODE 0x0107
-#define W_META_SETTEXTCHAREXTRA 0x0108
-#define W_META_SETTEXTCOLOR 0x0209
-#define W_META_SETTEXTJUSTIFICATION 0x020A
-#define W_META_SETWINDOWORG 0x020B
-#define W_META_SETWINDOWEXT 0x020C
-#define W_META_SETVIEWPORTORG 0x020D
-#define W_META_SETVIEWPORTEXT 0x020E
-#define W_META_OFFSETWINDOWORG 0x020F
-#define W_META_SCALEWINDOWEXT 0x0410
-#define W_META_OFFSETVIEWPORTORG 0x0211
-#define W_META_SCALEVIEWPORTEXT 0x0412
-#define W_META_LINETO 0x0213
-#define W_META_MOVETO 0x0214
-#define W_META_EXCLUDECLIPRECT 0x0415
-#define W_META_INTERSECTCLIPRECT 0x0416
-#define W_META_ARC 0x0817
-#define W_META_ELLIPSE 0x0418
-#define W_META_FLOODFILL 0x0419
-#define W_META_PIE 0x081A
-#define W_META_RECTANGLE 0x041B
-#define W_META_ROUNDRECT 0x061C
-#define W_META_PATBLT 0x061D
-#define W_META_SAVEDC 0x001E
-#define W_META_SETPIXEL 0x041F
-#define W_META_OFFSETCLIPRGN 0x0220
-#define W_META_TEXTOUT 0x0521
-#define W_META_BITBLT 0x0922
-#define W_META_STRETCHBLT 0x0B23
-#define W_META_POLYGON 0x0324
-#define W_META_POLYLINE 0x0325
-#define W_META_ESCAPE 0x0626
-#define W_META_RESTOREDC 0x0127
-#define W_META_FILLREGION 0x0228
-#define W_META_FRAMEREGION 0x0429
-#define W_META_INVERTREGION 0x012A
-#define W_META_PAINTREGION 0x012B
-#define W_META_SELECTCLIPREGION 0x012C
-#define W_META_SELECTOBJECT 0x012D
-#define W_META_SETTEXTALIGN 0x012E
-#define W_META_DRAWTEXT 0x062F
-#define W_META_CHORD 0x0830
-#define W_META_SETMAPPERFLAGS 0x0231
-#define W_META_EXTTEXTOUT 0x0a32
-#define W_META_SETDIBTODEV 0x0d33
-#define W_META_SELECTPALETTE 0x0234
-#define W_META_REALIZEPALETTE 0x0035
-#define W_META_ANIMATEPALETTE 0x0436
-#define W_META_SETPALENTRIES 0x0037
-#define W_META_POLYPOLYGON 0x0538
-#define W_META_RESIZEPALETTE 0x0139
-#define W_META_DIBBITBLT 0x0940
-#define W_META_DIBSTRETCHBLT 0x0b41
-#define W_META_DIBCREATEPATTERNBRUSH 0x0142
-#define W_META_STRETCHDIB 0x0f43
-#define W_META_EXTFLOODFILL 0x0548
-#define W_META_RESETDC 0x014C
-#define W_META_STARTDOC 0x014D
-#define W_META_STARTPAGE 0x004F
-#define W_META_ENDPAGE 0x0050
-#define W_META_ABORTDOC 0x0052
-#define W_META_ENDDOC 0x005E
-#define W_META_DELETEOBJECT 0x01f0
-#define W_META_CREATEPALETTE 0x00f7
-#define W_META_CREATEBRUSH 0x00F8
-#define W_META_CREATEPATTERNBRUSH 0x01F9
-#define W_META_CREATEPENINDIRECT 0x02FA
-#define W_META_CREATEFONTINDIRECT 0x02FB
-#define W_META_CREATEBRUSHINDIRECT 0x02FC
-#define W_META_CREATEBITMAPINDIRECT 0x02FD
-#define W_META_CREATEBITMAP 0x06FE
-#define W_META_CREATEREGION 0x06FF
-
-static void GetWinExtMax( const Point& rSource, tools::Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
-{
- Point aSource( rSource );
- if ( nMapMode == MM_HIMETRIC )
- aSource.Y() = -rSource.Y();
- if ( aSource.X() < rPlaceableBound.Left() )
- rPlaceableBound.Left() = aSource.X();
- if ( aSource.X() > rPlaceableBound.Right() )
- rPlaceableBound.Right() = aSource.X();
- if ( aSource.Y() < rPlaceableBound.Top() )
- rPlaceableBound.Top() = aSource.Y();
- if ( aSource.Y() > rPlaceableBound.Bottom() )
- rPlaceableBound.Bottom() = aSource.Y();
-}
-
-static void GetWinExtMax( const tools::Rectangle& rSource, tools::Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
-{
- GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
- GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
-}
-
-inline Point WMFReader::ReadPoint()
-{
- short nX = 0, nY = 0;
- pWMF->ReadInt16( nX ).ReadInt16( nY );
- return Point( nX, nY );
-}
-
-inline Point WMFReader::ReadYX()
-{
- short nX = 0, nY = 0;
- pWMF->ReadInt16( nY ).ReadInt16( nX );
- return Point( nX, nY );
-}
-
-tools::Rectangle WMFReader::ReadRectangle()
-{
- Point aBR, aTL;
- aBR = ReadYX();
- aTL = ReadYX();
- aBR.X()--;
- aBR.Y()--;
- return tools::Rectangle( aTL, aBR );
-}
-
-Size WMFReader::ReadYXExt()
-{
- short nW=0, nH=0;
- pWMF->ReadInt16( nH ).ReadInt16( nW );
- return Size( nW, nH );
-}
-
-void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
-{
- switch( nFunc )
- {
- case W_META_SETBKCOLOR:
- {
- pOut->SetBkColor( ReadColor() );
- }
- break;
-
- case W_META_SETBKMODE:
- {
- sal_uInt16 nDat = 0;
- pWMF->ReadUInt16( nDat );
- pOut->SetBkMode( static_cast<BkMode>(nDat) );
- }
- break;
-
- // !!!
- case W_META_SETMAPMODE:
- {
- sal_Int16 nMapMode = 0;
- pWMF->ReadInt16( nMapMode );
- pOut->SetMapMode( nMapMode );
- }
- break;
-
- case W_META_SETROP2:
- {
- sal_uInt16 nROP2 = 0;
- pWMF->ReadUInt16( nROP2 );
- pOut->SetRasterOp( (WMFRasterOp)nROP2 );
- }
- break;
-
- case W_META_SETTEXTCOLOR:
- {
- pOut->SetTextColor( ReadColor() );
- }
- break;
-
- case W_META_SETWINDOWORG:
- {
- pOut->SetWinOrg( ReadYX() );
- }
- break;
-
- case W_META_SETWINDOWEXT:
- {
- short nWidth = 0, nHeight = 0;
- pWMF->ReadInt16( nHeight ).ReadInt16( nWidth );
- pOut->SetWinExt( Size( nWidth, nHeight ) );
- }
- break;
-
- case W_META_OFFSETWINDOWORG:
- {
- short nXAdd = 0, nYAdd = 0;
- pWMF->ReadInt16( nYAdd ).ReadInt16( nXAdd );
- pOut->SetWinOrgOffset( nXAdd, nYAdd );
- }
- break;
-
- case W_META_SCALEWINDOWEXT:
- {
- short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
- pWMF->ReadInt16( nYDenom ).ReadInt16( nYNum ).ReadInt16( nXDenom ).ReadInt16( nXNum );
- if (!nYDenom || !nXDenom)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
- }
- break;
-
- case W_META_SETVIEWPORTORG:
- case W_META_SETVIEWPORTEXT:
- break;
-
- case W_META_OFFSETVIEWPORTORG:
- {
- short nXAdd = 0, nYAdd = 0;
- pWMF->ReadInt16( nYAdd ).ReadInt16( nXAdd );
- pOut->SetDevOrgOffset( nXAdd, nYAdd );
- }
- break;
-
- case W_META_SCALEVIEWPORTEXT:
- {
- short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
- pWMF->ReadInt16( nYDenom ).ReadInt16( nYNum ).ReadInt16( nXDenom ).ReadInt16( nXNum );
- if (!nYDenom || !nXDenom)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
- }
- break;
-
- case W_META_LINETO:
- {
- pOut->LineTo( ReadYX() );
- }
- break;
-
- case W_META_MOVETO:
- {
- pOut->MoveTo( ReadYX() );
- }
- break;
-
- case W_META_INTERSECTCLIPRECT:
- {
- pOut->IntersectClipRect( ReadRectangle() );
- }
- break;
-
- case W_META_RECTANGLE:
- {
- pOut->DrawRect( ReadRectangle() );
- }
- break;
-
- case W_META_ROUNDRECT:
- {
- Size aSize( ReadYXExt() );
- pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
- }
- break;
-
- case W_META_ELLIPSE:
- {
- pOut->DrawEllipse( ReadRectangle() );
- }
- break;
-
- case W_META_ARC:
- {
- Point aEnd( ReadYX() );
- Point aStart( ReadYX() );
- tools::Rectangle aRect( ReadRectangle() );
- aRect.Justify();
- pOut->DrawArc( aRect, aStart, aEnd );
- }
- break;
-
- case W_META_PIE:
- {
- Point aEnd( ReadYX() );
- Point aStart( ReadYX() );
- tools::Rectangle aRect( ReadRectangle() );
- aRect.Justify();
-
- // #i73608# OutputDevice deviates from WMF
- // semantics. start==end means full ellipse here.
- if( aStart == aEnd )
- pOut->DrawEllipse( aRect );
- else
- pOut->DrawPie( aRect, aStart, aEnd );
- }
- break;
-
- case W_META_CHORD:
- {
- Point aEnd( ReadYX() );
- Point aStart( ReadYX() );
- tools::Rectangle aRect( ReadRectangle() );
- aRect.Justify();
- pOut->DrawChord( aRect, aStart, aEnd );
- }
- break;
-
- case W_META_POLYGON:
- {
- bool bRecordOk = true;
-
- sal_uInt16 nPoints(0);
- pWMF->ReadUInt16(nPoints);
-
- if (nPoints > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- }
- else
- {
- tools::Polygon aPoly(nPoints);
- for (sal_uInt16 i(0); i < nPoints && pWMF->good(); ++i)
- aPoly[ i ] = ReadPoint();
- pOut->DrawPolygon(aPoly, false/*bRecordPath*/);
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polygon record has more points than we can handle");
-
- bRecordOk &= pWMF->good();
-
- if (!bRecordOk)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- }
- break;
-
- case W_META_POLYPOLYGON:
- {
- sal_uInt16 nPolyCount(0);
- // Number of polygons:
- pWMF->ReadUInt16( nPolyCount );
- if (nPolyCount && pWMF->good())
- {
- bool bRecordOk = true;
- if (nPolyCount > pWMF->remainingSize() / sizeof(sal_uInt16))
- {
- break;
- }
-
- // Number of points of each polygon. Determine total number of points
- std::unique_ptr<sal_uInt16[]> xPolygonPointCounts(new sal_uInt16[nPolyCount]);
- sal_uInt16* pnPoints = xPolygonPointCounts.get();
- tools::PolyPolygon aPolyPoly(nPolyCount, nPolyCount);
- sal_uInt16 nPoints = 0;
- for (sal_uInt16 a = 0; a < nPolyCount && pWMF->good(); ++a)
- {
- pWMF->ReadUInt16( pnPoints[a] );
-
- if (pnPoints[a] > SAL_MAX_UINT16 - nPoints)
- {
- bRecordOk = false;
- break;
- }
-
- nPoints += pnPoints[a];
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polypolygon record has more polygons than we can handle");
-
- bRecordOk &= pWMF->good();
-
- if (!bRecordOk)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
-
- // Polygon points are:
- for (sal_uInt16 a = 0; a < nPolyCount && pWMF->good(); ++a)
- {
- const sal_uInt16 nPointCount(pnPoints[a]);
-
- if (nPointCount > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- break;
- }
-
- std::unique_ptr<Point[]> xPolygonPoints(new Point[nPointCount]);
- Point* pPtAry = xPolygonPoints.get();
-
- for(sal_uInt16 b(0); b < nPointCount && pWMF->good(); ++b)
- {
- pPtAry[b] = ReadPoint();
- }
-
- aPolyPoly.Insert( tools::Polygon(nPointCount, pPtAry) );
- }
-
- bRecordOk &= pWMF->good();
-
- if (!bRecordOk)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
-
- pOut->DrawPolyPolygon( aPolyPoly );
- }
- }
- break;
-
- case W_META_POLYLINE:
- {
- bool bRecordOk = true;
-
- sal_uInt16 nPoints(0);
- pWMF->ReadUInt16(nPoints);
-
- if (nPoints > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- }
- else
- {
- tools::Polygon aPoly(nPoints);
- for (sal_uInt16 i(0); i < nPoints && pWMF->good(); ++i)
- aPoly[ i ] = ReadPoint();
- pOut->DrawPolyLine( aPoly );
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polyline record has more points than we can handle");
-
- bRecordOk &= pWMF->good();
-
- if (!bRecordOk)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- }
- break;
-
- case W_META_SAVEDC:
- {
- pOut->Push();
- }
- break;
-
- case W_META_RESTOREDC:
- {
- pOut->Pop();
- }
- break;
-
- case W_META_SETPIXEL:
- {
- const Color aColor = ReadColor();
- pOut->DrawPixel( ReadYX(), aColor );
- }
- break;
-
- case W_META_OFFSETCLIPRGN:
- {
- pOut->MoveClipRegion( ReadYXExt() );
- }
- break;
-
- case W_META_TEXTOUT:
- {
- sal_uInt16 nLength = 0;
- pWMF->ReadUInt16( nLength );
- if ( nLength )
- {
- std::unique_ptr<char[]> pChar(new char[ ( nLength + 1 ) &~ 1 ]);
- pWMF->ReadBytes(pChar.get(), (nLength + 1) &~ 1);
- OUString aText( pChar.get(), nLength, pOut->GetCharSet() );
- pChar.reset();
- Point aPosition( ReadYX() );
- pOut->DrawText( aPosition, aText );
- }
- }
- break;
-
- case W_META_EXTTEXTOUT:
- {
- pWMF->SeekRel(-6);
- sal_Int32 nRecordPos = pWMF->Tell(), nRecordSize = 0;
- pWMF->ReadInt32( nRecordSize );
- pWMF->SeekRel(2);
- Point aPosition = ReadYX();
- sal_uInt16 nLen = 0, nOptions = 0;
- pWMF->ReadUInt16( nLen ).ReadUInt16( nOptions );
-
- ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
- if ( nOptions & ETO_RTLREADING )
- nTextLayoutMode = ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
- pOut->SetTextLayoutMode( nTextLayoutMode );
- SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "vcl.wmf", "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
-
- // output only makes sense if the text contains characters
- if( nLen )
- {
- sal_Int32 nOriginalTextLen = nLen;
- sal_Int32 nOriginalBlockLen = ( nOriginalTextLen + 1 ) &~ 1;
- tools::Rectangle aRect;
- if( nOptions & ETO_CLIPPED )
- {
- const Point aPt1( ReadPoint() );
- const Point aPt2( ReadPoint() );
- aRect = tools::Rectangle( aPt1, aPt2 );
- }
-
- auto nRemainingSize = pWMF->remainingSize();
- if (nRemainingSize < static_cast<sal_uInt32>(nOriginalBlockLen))
- {
- SAL_WARN("vcl.wmf", "exttextout record claimed more data than the stream can provide");
- nOriginalTextLen = nOriginalBlockLen = nRemainingSize;
- }
-
- std::unique_ptr<char[]> pChar(new char[nOriginalBlockLen]);
- pWMF->ReadBytes(pChar.get(), nOriginalBlockLen);
- OUString aText(pChar.get(), nOriginalTextLen, pOut->GetCharSet()); // after this conversion the text may contain
- sal_Int32 nNewTextLen = aText.getLength(); // less character (japanese version), so the
- // dxAry will not fit
- if ( nNewTextLen )
- {
- std::unique_ptr<long[]> pDXAry, pDYAry;
- sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
- sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
- sal_Int32 nDxAryEntries = nDxArySize >> 1;
- bool bUseDXAry = false;
-
- if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
- {
- sal_Int32 i; // needed just outside the for
- pDXAry.reset(new long[ nNewTextLen ]);
- if ( nOptions & ETO_PDY )
- {
- pDYAry.reset(new long[ nNewTextLen ]);
- }
- for (i = 0; i < nNewTextLen; i++ )
- {
- if ( pWMF->Tell() >= nMaxStreamPos )
- break;
- sal_Int32 nDxCount = 1;
- if ( nNewTextLen != nOriginalTextLen )
- {
- sal_Unicode cUniChar = aText[i];
- OString aTmp(&cUniChar, 1, pOut->GetCharSet());
- if ( aTmp.getLength() > 1 )
- {
- nDxCount = aTmp.getLength();
- }
- }
-
- sal_Int16 nDx = 0, nDy = 0;
- while ( nDxCount-- )
- {
- if ( ( pWMF->Tell() + 2 ) > nMaxStreamPos )
- break;
- sal_Int16 nDxTmp = 0;
- pWMF->ReadInt16(nDxTmp);
- nDx += nDxTmp;
- if ( nOptions & ETO_PDY )
- {
- if ( ( pWMF->Tell() + 2 ) > nMaxStreamPos )
- break;
- sal_Int16 nDyTmp = 0;
- pWMF->ReadInt16(nDyTmp);
- nDy += nDyTmp;
- }
- }
-
- pDXAry[ i ] = nDx;
- if ( nOptions & ETO_PDY )
- {
- pDYAry[i] = nDy;
- }
- }
- if ( i == nNewTextLen )
- bUseDXAry = true;
- }
- if ( pDXAry && bUseDXAry )
- pOut->DrawText( aPosition, aText, pDXAry.get(), pDYAry.get() );
- else
- pOut->DrawText( aPosition, aText );
- }
- }
- }
- break;
-
- case W_META_SELECTOBJECT:
- {
- sal_Int16 nObjIndex = 0;
- pWMF->ReadInt16( nObjIndex );
- pOut->SelectObject( nObjIndex );
- }
- break;
-
- case W_META_SETTEXTALIGN:
- {
- sal_uInt16 nAlign = 0;
- pWMF->ReadUInt16( nAlign );
- pOut->SetTextAlign( nAlign );
- }
- break;
-
- case W_META_BITBLT:
- {
- // 0-3 : nWinROP #93454#
- // 4-5 : y offset of source bitmap
- // 6-7 : x offset of source bitmap
- // 8-9 : used height of source bitmap
- // 10-11 : used width of source bitmap
- // 12-13 : destination position y (in pixel)
- // 14-15 : destination position x (in pixel)
- // 16-17 : don't know
- // 18-19 : Width Bitmap in Pixel
- // 20-21 : Height Bitmap in Pixel
- // 22-23 : bytes per scanline
- // 24 : planes
- // 25 : bitcount
-
- sal_Int32 nWinROP = 0;
- sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nDontKnow = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
- sal_uInt8 nPlanes, nBitCount;
-
- pWMF->ReadInt32( nWinROP )
- .ReadUInt16( nSy ).ReadUInt16( nSx ).ReadUInt16( nSye ).ReadUInt16( nSxe );
- Point aPoint( ReadYX() );
- pWMF->ReadUInt16( nDontKnow ).ReadUInt16( nWidth ).ReadUInt16( nHeight ).ReadUInt16( nBytesPerScan ).ReadUChar( nPlanes ).ReadUChar( nBitCount );
-
- bool bOk = nWidth && nHeight && nPlanes == 1 && nBitCount == 1;
- if (bOk)
- {
- bOk = nBytesPerScan <= pWMF->remainingSize() / nHeight;
- }
- if (bOk)
- {
- Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
- Bitmap::ScopedWriteAccess pAcc(aBmp);
- if ( pAcc )
- {
- for (sal_uInt16 y = 0; y < nHeight && pWMF->good(); ++y)
- {
- sal_uInt16 x = 0;
- for (sal_uInt16 scan = 0; scan < nBytesPerScan; scan++ )
- {
- sal_Int8 nEightPixels = 0;
- pWMF->ReadSChar( nEightPixels );
- for (sal_Int8 i = 7; i >= 0; i-- )
- {
- if ( x < nWidth )
- {
- pAcc->SetPixelIndex( y, x, (nEightPixels>>i)&1 );
- }
- x++;
- }
- }
- }
- pAcc.reset();
- if ( nSye && nSxe &&
- ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
- ( ( nSy + nSye ) <= aBmp.GetSizePixel().Height() ) )
- {
- tools::Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
- aBmp.Crop( aCropRect );
- }
- tools::Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
- aBmpSaveList.emplace_back(new BSaveStruct(aBmp, aDestRect, nWinROP));
- }
- }
- }
- break;
-
- case W_META_STRETCHBLT:
- case W_META_DIBBITBLT:
- case W_META_DIBSTRETCHBLT:
- case W_META_STRETCHDIB:
- {
- sal_Int32 nWinROP = 0;
- sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nUsage = 0;
- Bitmap aBmp;
-
- pWMF->ReadInt32( nWinROP );
-
- if( nFunc == W_META_STRETCHDIB )
- pWMF->ReadUInt16( nUsage );
-
- // nSye and nSxe is the number of pixels that has to been used
- // If they are set to zero, it is as indicator not to scale the bitmap later
-
- if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
- pWMF->ReadUInt16( nSye ).ReadUInt16( nSxe );
-
- // nSy and nx is the offset of the first pixel
- pWMF->ReadUInt16( nSy ).ReadUInt16( nSx );
-
- if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
- {
- if ( nWinROP == PATCOPY )
- pWMF->ReadUInt16( nUsage ); // i don't know anything of this parameter, so its called nUsage
- // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), false );
-
- Size aDestSize( ReadYXExt() );
- if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
- {
- tools::Rectangle aDestRect( ReadYX(), aDestSize );
- if ( nWinROP != PATCOPY )
- ReadDIB(aBmp, *pWMF, false);
-
- // test if it is sensible to crop
- if ( nSye && nSxe &&
- ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
- ( ( nSy + nSye ) <= aBmp.GetSizePixel().Height() ) )
- {
- tools::Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
- aBmp.Crop( aCropRect );
- }
- aBmpSaveList.emplace_back(new BSaveStruct(aBmp, aDestRect, nWinROP));
- }
- }
- }
- break;
-
- case W_META_DIBCREATEPATTERNBRUSH:
- {
- Bitmap aBmp;
- sal_uInt32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
- sal_uInt16 nFunction = 0;
-
- pWMF->ReadUInt16( nFunction ).ReadUInt16( nFunction );
-
- ReadDIB(aBmp, *pWMF, false);
- Bitmap::ScopedReadAccess pBmp(aBmp);
- if ( pBmp )
- {
- for ( long y = 0; y < pBmp->Height(); y++ )
- {
- for ( long x = 0; x < pBmp->Width(); x++ )
- {
- const BitmapColor aColor( pBmp->GetColor( y, x ) );
-
- nRed += aColor.GetRed();
- nGreen += aColor.GetGreen();
- nBlue += aColor.GetBlue();
- }
- }
- nCount = pBmp->Height() * pBmp->Width();
- if ( !nCount )
- nCount++;
- pBmp.reset();
- }
- Color aColor( (sal_uInt8)( nRed / nCount ), (sal_uInt8)( nGreen / nCount ), (sal_uInt8)( nBlue / nCount ) );
- pOut->CreateObject(o3tl::make_unique<WinMtfFillStyle>( aColor, false ));
- }
- break;
-
- case W_META_DELETEOBJECT:
- {
- sal_Int16 nIndex = 0;
- pWMF->ReadInt16( nIndex );
- pOut->DeleteObject( nIndex );
- }
- break;
-
- case W_META_CREATEPALETTE:
- {
- pOut->CreateObject();
- }
- break;
-
- case W_META_CREATEBRUSH:
- {
- pOut->CreateObject(o3tl::make_unique<WinMtfFillStyle>( Color( COL_WHITE ), false ));
- }
- break;
-
- case W_META_CREATEPATTERNBRUSH:
- {
- pOut->CreateObject(o3tl::make_unique<WinMtfFillStyle>( Color( COL_WHITE ), false ));
- }
- break;
-
- case W_META_CREATEPENINDIRECT:
- {
- LineInfo aLineInfo;
- sal_uInt16 nStyle = 0;
- sal_uInt16 nWidth = 0;
- sal_uInt16 nHeight = 0;
-
- pWMF->ReadUInt16(nStyle);
- pWMF->ReadUInt16(nWidth);
- pWMF->ReadUInt16(nHeight);
-
- if (nWidth > 0)
- aLineInfo.SetWidth(nWidth);
-
- bool bTransparent = false;
-
- switch( nStyle & 0xFF )
- {
- 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;
- default :
- case PS_INSIDEFRAME :
- case PS_SOLID :
- aLineInfo.SetStyle( LineStyle::Solid );
- }
- switch( nStyle & 0xF00 )
- {
- case PS_ENDCAP_ROUND :
- aLineInfo.SetLineCap( css::drawing::LineCap_ROUND );
- break;
- case PS_ENDCAP_SQUARE :
- aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE );
- break;
- case PS_ENDCAP_FLAT :
- default :
- aLineInfo.SetLineCap( css::drawing::LineCap_BUTT );
- }
- switch( nStyle & 0xF000 )
- {
- 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->CreateObject(o3tl::make_unique<WinMtfLineStyle>( ReadColor(), aLineInfo, bTransparent ));
- }
- break;
-
- case W_META_CREATEBRUSHINDIRECT:
- {
- sal_uInt16 nStyle = 0;
- pWMF->ReadUInt16( nStyle );
- pOut->CreateObject(o3tl::make_unique<WinMtfFillStyle>( ReadColor(), ( nStyle == BS_HOLLOW ) ));
- }
- break;
-
- case W_META_CREATEFONTINDIRECT:
- {
- Size aFontSize;
- char lfFaceName[LF_FACESIZE+1];
- sal_Int16 lfEscapement = 0;
- sal_Int16 lfOrientation = 0;
- sal_Int16 lfWeight = 0;
-
- LOGFONTW aLogFont;
- unsigned char nTmp;
- aFontSize = ReadYXExt();
- pWMF->ReadInt16( lfEscapement );
- pWMF->ReadInt16( lfOrientation );
- pWMF->ReadInt16( lfWeight );
- pWMF->ReadUChar( aLogFont.lfItalic );
- pWMF->ReadUChar( aLogFont.lfUnderline );
- pWMF->ReadUChar( aLogFont.lfStrikeOut );
- pWMF->ReadUChar( aLogFont.lfCharSet );
- pWMF->ReadUChar( nTmp ); // lfOutPrecision
- pWMF->ReadUChar( nTmp ); // lfClipPrecision
- pWMF->ReadUChar( nTmp ); // lfQuality
- pWMF->ReadUChar( aLogFont.lfPitchAndFamily );
- size_t nRet = pWMF->ReadBytes( lfFaceName, LF_FACESIZE );
- lfFaceName[nRet] = 0;
- aLogFont.lfWidth = aFontSize.Width();
- aLogFont.lfHeight = aFontSize.Height();
- aLogFont.lfEscapement = lfEscapement;
- aLogFont.lfWeight = lfWeight;
-
- rtl_TextEncoding eCharSet;
- if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
- eCharSet = osl_getThreadTextEncoding();
- else
- eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
- if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
- eCharSet = osl_getThreadTextEncoding();
- if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
- eCharSet = RTL_TEXTENCODING_MS_1252;
- aLogFont.alfFaceName = OUString( lfFaceName, strlen(lfFaceName), eCharSet );
-
- pOut->CreateObject(o3tl::make_unique<WinMtfFontStyle>( aLogFont ));
- }
- break;
-
- case W_META_CREATEBITMAPINDIRECT:
- {
- pOut->CreateObject();
- }
- break;
-
- case W_META_CREATEBITMAP:
- {
- pOut->CreateObject();
- }
- break;
-
- case W_META_CREATEREGION:
- {
- pOut->CreateObject();
- }
- break;
-
- case W_META_EXCLUDECLIPRECT :
- {
- pOut->ExcludeClipRect( ReadRectangle() );
- }
- break;
-
- case W_META_PATBLT:
- {
- sal_uInt32 nROP = 0;
- WMFRasterOp nOldROP = WMFRasterOp::NONE;
- pWMF->ReadUInt32( nROP );
- Size aSize = ReadYXExt();
- nOldROP = pOut->SetRasterOp( (WMFRasterOp)nROP );
- pOut->DrawRect( tools::Rectangle( ReadYX(), aSize ), false );
- pOut->SetRasterOp( nOldROP );
- }
- break;
-
- case W_META_SELECTCLIPREGION:
- {
- sal_Int16 nObjIndex = 0;
- pWMF->ReadInt16( nObjIndex );
- if ( !nObjIndex )
- {
- tools::PolyPolygon aEmptyPolyPoly;
- pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, true );
- }
- }
- break;
-
- case W_META_ESCAPE :
- {
- // nRecSize has been checked previously to be greater than 3
- sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
- sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
-
- // taking care that nRecSize does not exceed the maximal stream position
- if ( nMetaRecEndPos > nEndPos )
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- if ( nRecSize >= 4 ) // minimal escape length
- {
- sal_uInt16 nMode = 0, nLen = 0;
- pWMF->ReadUInt16( nMode )
- .ReadUInt16( nLen );
- if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 4 ) )
- {
- sal_uInt32 nNewMagic = 0; // we have to read int32 for
- pWMF->ReadUInt32( nNewMagic ); // META_ESCAPE_ENHANCED_METAFILE CommentIdentifier
-
- if( nNewMagic == 0x2c2a4f4f && nLen >= 14 )
- {
- sal_uInt16 nMagic2 = 0;
- pWMF->ReadUInt16( nMagic2 );
- if( nMagic2 == 0x0a ) // 2nd half of magic
- { // continue with private escape
- sal_uInt32 nCheck = 0, nEsc = 0;
- pWMF->ReadUInt32( nCheck )
- .ReadUInt32( nEsc );
-
- sal_uInt32 nEscLen = nLen - 14;
- if ( nEscLen <= ( nRecSize * 2 ) )
- {
-#ifdef OSL_BIGENDIAN
- sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
- sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
-#else
- sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
-#endif
- std::unique_ptr<sal_Int8[]> pData;
-
- if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- break;
- }
- if ( nEscLen > 0 )
- {
- pData.reset(new sal_Int8[ nEscLen ]);
- pWMF->ReadBytes(pData.get(), nEscLen);
- nCheckSum = rtl_crc32( nCheckSum, pData.get(), nEscLen );
- }
- if ( nCheck == nCheckSum )
- {
- switch( nEsc )
- {
- case PRIVATE_ESCAPE_UNICODE :
- {
- // we will use text instead of polygons only if we have the correct font
- if ( Application::GetDefaultDevice()->IsFontAvailable( pOut->GetFont().GetFamilyName() ) )
- {
- Point aPt;
- OUString aString;
- sal_uInt32 nStringLen, nDXCount;
- std::unique_ptr<long[]> pDXAry;
- SvMemoryStream aMemoryStream( nEscLen );
- aMemoryStream.WriteBytes(pData.get(), nEscLen);
- aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
- sal_Int32 nTmpX(0), nTmpY(0);
- aMemoryStream.ReadInt32( nTmpX )
- .ReadInt32( nTmpY )
- .ReadUInt32( nStringLen );
- aPt.X() = nTmpX;
- aPt.Y() = nTmpY;
-
- if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
- {
-
- aString = read_uInt16s_ToOUString(aMemoryStream, nStringLen);
- aMemoryStream.ReadUInt32( nDXCount );
- if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
- nDXCount = 0;
- if ( nDXCount )
- pDXAry.reset(new long[ nDXCount ]);
- for (sal_uInt32 i = 0; i < nDXCount; i++ )
- {
- sal_Int32 val;
- aMemoryStream.ReadInt32( val);
- pDXAry[ i ] = val;
- }
- aMemoryStream.ReadUInt32( nSkipActions );
- pOut->DrawText( aPt, aString, pDXAry.get() );
- }
- }
- }
- break;
- }
- }
- }
- }
- }
- else if ( (nNewMagic == static_cast< sal_uInt32 >(0x43464D57)) && (nLen >= 34) && ( (sal_Int32)(nLen + 10) <= (sal_Int32)(nRecSize * 2) ))
- {
- sal_uInt32 nComType = 0, nVersion = 0, nFlags = 0, nComRecCount = 0,
- nCurRecSize = 0, nRemainingSize = 0, nEMFTotalSize = 0;
- sal_uInt16 nCheck = 0;
-
- pWMF->ReadUInt32( nComType ).ReadUInt32( nVersion ).ReadUInt16( nCheck ).ReadUInt32( nFlags )
- .ReadUInt32( nComRecCount ).ReadUInt32( nCurRecSize )
- .ReadUInt32( nRemainingSize ).ReadUInt32( nEMFTotalSize ); // the nRemainingSize is not mentioned in MSDN documentation
- // but it seems to be required to read in data produced by OLE
-
- if( nComType == 0x01 && nVersion == 0x10000 && nComRecCount )
- {
- if( !nEMFRec )
- { // first EMF comment
- nEMFRecCount = nComRecCount;
- nEMFSize = nEMFTotalSize;
- if (nEMFSize > pWMF->remainingSize())
- {
- SAL_WARN("vcl.wmf", "emf size claims to be larger than remaining data");
- pEMFStream.reset();
- }
- else
- pEMFStream = o3tl::make_unique<SvMemoryStream>(nEMFSize, 0);
- }
- else if( ( nEMFRecCount != nComRecCount ) || ( nEMFSize != nEMFTotalSize ) ) // add additional checks here
- {
- // total records should be the same as in previous comments
- nEMFRecCount = 0xFFFFFFFF;
- pEMFStream.reset();
- }
- nEMFRec++;
-
- if (pEMFStream && nCurRecSize + 34 > nLen)
- {
- nEMFRecCount = 0xFFFFFFFF;
- pEMFStream.reset();
- }
-
- if (pEMFStream && nCurRecSize > pWMF->remainingSize())
- {
- SAL_WARN("vcl.wmf", "emf record size claims to be larger than remaining data");
- nEMFRecCount = 0xFFFFFFFF;
- pEMFStream.reset();
- }
-
- if (pEMFStream)
- {
- std::vector<sal_Int8> aBuf(nCurRecSize);
- sal_uInt32 nCount = pWMF->ReadBytes(aBuf.data(), nCurRecSize);
- if( nCount == nCurRecSize )
- pEMFStream->WriteBytes(aBuf.data(), nCount);
- }
- }
- }
- }
- }
- }
- break;
-
- case W_META_SETRELABS:
- case W_META_SETPOLYFILLMODE:
- case W_META_SETSTRETCHBLTMODE:
- case W_META_SETTEXTCHAREXTRA:
- case W_META_SETTEXTJUSTIFICATION:
- case W_META_FLOODFILL :
- case W_META_FILLREGION:
- case W_META_FRAMEREGION:
- case W_META_INVERTREGION:
- case W_META_PAINTREGION:
- case W_META_DRAWTEXT:
- case W_META_SETMAPPERFLAGS:
- case W_META_SETDIBTODEV:
- case W_META_SELECTPALETTE:
- case W_META_REALIZEPALETTE:
- case W_META_ANIMATEPALETTE:
- case W_META_SETPALENTRIES:
- case W_META_RESIZEPALETTE:
- case W_META_EXTFLOODFILL:
- case W_META_RESETDC:
- case W_META_STARTDOC:
- case W_META_STARTPAGE:
- case W_META_ENDPAGE:
- case W_META_ABORTDOC:
- case W_META_ENDDOC:
- break;
- }
-}
-
-static const long aMaxWidth = 1024;
-
-bool WMFReader::ReadHeader()
-{
- sal_uInt64 const nStrmPos = pWMF->Tell();
-
- sal_uInt32 nPlaceableMetaKey(0);
- // if available read the METAFILEHEADER
- pWMF->ReadUInt32( nPlaceableMetaKey );
- if (!pWMF->good())
- return false;
-
- tools::Rectangle aPlaceableBound;
-
- bool bPlaceable = nPlaceableMetaKey == 0x9ac6cdd7L;
-
- SAL_INFO("vcl.wmf", "Placeable: \"" << (bPlaceable ? "yes" : "no") << "\"");
-
- if (bPlaceable)
- {
- //TODO do some real error handling here
- sal_Int16 nVal;
-
- // Skip reserved bytes
- pWMF->SeekRel(2);
-
- // BoundRect
- pWMF->ReadInt16( nVal );
- aPlaceableBound.Left() = nVal;
- pWMF->ReadInt16( nVal );
- aPlaceableBound.Top() = nVal;
- pWMF->ReadInt16( nVal );
- aPlaceableBound.Right() = nVal;
- pWMF->ReadInt16( nVal );
- aPlaceableBound.Bottom() = nVal;
-
- // inch
- pWMF->ReadUInt16( nUnitsPerInch );
-
- // reserved
- pWMF->SeekRel( 4 );
-
- // Skip and don't check the checksum
- pWMF->SeekRel( 2 );
- }
- else
- {
- nUnitsPerInch = 96;
-
-
- if ( pExternalHeader != nullptr
- && pExternalHeader->xExt > 0
- && pExternalHeader->yExt > 0
- && (pExternalHeader->mapMode == MM_ISOTROPIC || pExternalHeader->mapMode == MM_ANISOTROPIC))
- {
- // #n417818#: If we have an external header then overwrite the bounds!
- tools::Rectangle aExtRect(0, 0,
- (double) pExternalHeader->xExt * 567 * nUnitsPerInch / 1440000,
- (double) pExternalHeader->yExt * 567 * nUnitsPerInch / 1440000);
- aPlaceableBound = aExtRect;
-
- SAL_INFO("vcl.wmf", "External header size "
- " t: " << aPlaceableBound.Left() << " l: " << aPlaceableBound.Top()
- << " b: " << aPlaceableBound.Right() << " r: " << aPlaceableBound.Bottom());
-
- pOut->SetMapMode( pExternalHeader->mapMode );
- }
- else
- {
- pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the metaactions
- GetPlaceableBound( aPlaceableBound, pWMF );
-
- // The image size is not known so normalize the calculated bounds so that the
- // resulting image is not too big
- const double fMaxWidth = static_cast<double>(aMaxWidth);
- if (aPlaceableBound.GetWidth() > aMaxWidth)
- {
- double fRatio = aPlaceableBound.GetWidth() / fMaxWidth;
-
- aPlaceableBound = tools::Rectangle(
- aPlaceableBound.Left() / fRatio,
- aPlaceableBound.Top() / fRatio,
- aPlaceableBound.Right() / fRatio,
- aPlaceableBound.Bottom() / fRatio);
-
- SAL_INFO("vcl.wmf", "Placeable bounds "
- " t: " << aPlaceableBound.Left() << " l: " << aPlaceableBound.Top()
- << " b: " << aPlaceableBound.Right() << " r: " << aPlaceableBound.Bottom());
- }
- }
-
- pWMF->Seek( nStrmPos );
- }
-
- pOut->SetWinOrg( aPlaceableBound.TopLeft() );
- Size aWMFSize( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
- pOut->SetWinExt( aWMFSize );
-
- SAL_INFO("vcl.wmf", "WMF size w: " << aWMFSize.Width() << " h: " << aWMFSize.Height());
-
- Size aDevExt( 10000, 10000 );
- if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
- {
- const Fraction aFrac( 1, nUnitsPerInch );
- MapMode aWMFMap( MapUnit::MapInch, Point(), aFrac, aFrac );
- Size aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MapUnit::Map100thMM ) );
- aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
- }
- pOut->SetDevExt( aDevExt );
-
- SAL_INFO("vcl.wmf", "Dev size w: " << aDevExt.Width() << " h: " << aDevExt.Height());
-
- // read the METAHEADER
- sal_uInt32 nMetaKey(0);
- pWMF->ReadUInt32( nMetaKey ); // type and headersize
- if (!pWMF->good())
- return false;
- if (nMetaKey != 0x00090001)
- {
- sal_uInt16 aNextWord(0);
- pWMF->ReadUInt16( aNextWord );
- if (nMetaKey != 0x10000 || aNextWord != 0x09)
- {
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- return false;
- }
- }
-
- pWMF->SeekRel( 2 ); // Version (of Windows)
- pWMF->SeekRel( 4 ); // Size (of file in words)
- pWMF->SeekRel( 2 ); // NoObjects (maximum number of simultaneous objects)
- pWMF->SeekRel( 4 ); // MaxRecord (size of largest record in words)
- pWMF->SeekRel( 2 ); // NoParameters (Unused
-
- return pWMF->good();
-}
-
-void WMFReader::ReadWMF()
-{
- sal_uInt16 nFunction;
- sal_uLong nPos, nPercent, nLastPercent;
-
- nSkipActions = 0;
-
- pEMFStream.reset();
- nEMFRecCount = 0;
- nEMFRec = 0;
- nEMFSize = 0;
-
- pOut->SetMapMode( MM_ANISOTROPIC );
- pOut->SetWinOrg( Point() );
- pOut->SetWinExt( Size( 1, 1 ) );
- pOut->SetDevExt( Size( 10000, 10000 ) );
-
- nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
- pWMF->Seek( nStartPos );
- Callback( (sal_uInt16) ( nLastPercent = 0 ) );
-
- if ( ReadHeader( ) )
- {
- nPos = pWMF->Tell();
-
- if( nEndPos - nStartPos )
- {
- bool bEMFAvailable = false;
- while( true )
- {
- nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
-
- if( nLastPercent + 4 <= nPercent )
- {
- Callback( (sal_uInt16) nPercent );
- nLastPercent = nPercent;
- }
- pWMF->ReadUInt32( nRecSize ).ReadUInt16( nFunction );
-
- if( pWMF->GetError()
- || ( nRecSize < 3 )
- || ( nRecSize == 3
- && nFunction == 0
- )
- || pWMF->IsEof()
- )
- {
- if( pWMF->IsEof() )
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
-
- break;
- }
- if ( !bEMFAvailable )
- {
- if( !aBmpSaveList.empty()
- && ( nFunction != W_META_STRETCHDIB )
- && ( nFunction != W_META_DIBBITBLT )
- && ( nFunction != W_META_DIBSTRETCHBLT )
- )
- {
- pOut->ResolveBitmapActions( aBmpSaveList );
- }
-
- if ( !nSkipActions )
- ReadRecordParams( nFunction );
- else
- nSkipActions--;
-
- if( pEMFStream && nEMFRecCount == nEMFRec )
- {
- GDIMetaFile aMeta;
- pEMFStream->Seek( 0 );
- std::unique_ptr<EnhWMFReader> pEMFReader(o3tl::make_unique<EnhWMFReader>( *pEMFStream, aMeta ));
- bEMFAvailable = pEMFReader->ReadEnhWMF();
- pEMFReader.reset(); // destroy first!!!
-
- if( bEMFAvailable )
- {
- pOut->AddFromGDIMetaFile( aMeta );
- pOut->SetrclFrame( tools::Rectangle( Point(0, 0), aMeta.GetPrefSize()));
-
- // the stream needs to be set to the wmf end position,
- // otherwise the GfxLink that is created will be incorrect
- // (leading to graphic loss after swapout/swapin).
- // so we will proceed normally, but are ignoring further wmf
- // records
- }
- else
- {
- // something went wrong
- // continue with WMF, don't try this again
- pEMFStream.reset();
- }
- }
- }
- const sal_uInt32 nAvailableBytes = nEndPos - nPos;
- const sal_uInt32 nMaxPossibleRecordSize = nAvailableBytes/2;
- if (nRecSize <= nMaxPossibleRecordSize)
- {
- nPos += nRecSize * 2;
- pWMF->Seek(nPos);
- }
- else
- pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
- }
- }
- else
- pWMF->SetError( SVSTREAM_GENERALERROR );
-
- if( !pWMF->GetError() && !aBmpSaveList.empty() )
- pOut->ResolveBitmapActions( aBmpSaveList );
- }
- if ( pWMF->GetError() )
- pWMF->Seek( nStartPos );
-}
-
-void WMFReader::GetPlaceableBound( tools::Rectangle& rPlaceableBound, SvStream* pStm )
-{
- bool bRet = true;
-
- tools::Rectangle aBound;
- aBound.Left() = RECT_MAX;
- aBound.Top() = RECT_MAX;
- aBound.Right() = RECT_MIN;
- aBound.Bottom() = RECT_MIN;
- bool bBoundsDetermined = false;
-
- sal_uInt32 nPos = pStm->Tell();
- sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
-
- pStm->Seek( nPos );
-
- Point aWinOrg(0,0);
- boost::optional<Size> aWinExt;
-
- Point aViewportOrg(0,0);
- boost::optional<Size> aViewportExt;
-
- if( nEnd - nPos )
- {
- sal_Int16 nMapMode = MM_ANISOTROPIC;
- sal_uInt16 nFunction;
- sal_uInt32 nRSize;
-
- while( bRet )
- {
- pStm->ReadUInt32( nRSize ).ReadUInt16( nFunction );
-
- if( pStm->GetError() )
- {
- bRet = false;
- break;
- }
- else if ( nRSize==3 && nFunction==0 )
- {
- break;
- }
- else if ( nRSize < 3 || pStm->IsEof() )
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- break;
- }
- switch( nFunction )
- {
- case W_META_SETWINDOWORG:
- {
- aWinOrg = ReadYX();
- }
- break;
-
- case W_META_SETWINDOWEXT:
- {
- sal_Int16 nWidth(0), nHeight(0);
- pStm->ReadInt16(nHeight);
- pStm->ReadInt16(nWidth);
- aWinExt = Size(nWidth, nHeight);
- }
- break;
-
- case W_META_SETVIEWPORTORG:
- {
- aViewportOrg = ReadYX();
- }
- break;
-
- case W_META_SETVIEWPORTEXT:
- {
- sal_Int16 nWidth(0), nHeight(0);
- pStm->ReadInt16(nHeight);
- pStm->ReadInt16(nWidth);
- aViewportExt = Size(nWidth, nHeight);
- }
- break;
-
- case W_META_SETMAPMODE :
- pStm->ReadInt16( nMapMode );
- break;
-
- case W_META_MOVETO:
- case W_META_LINETO:
- GetWinExtMax( ReadYX(), aBound, nMapMode );
- bBoundsDetermined = true;
- break;
-
- case W_META_RECTANGLE:
- case W_META_INTERSECTCLIPRECT:
- case W_META_EXCLUDECLIPRECT :
- case W_META_ELLIPSE:
- GetWinExtMax( ReadRectangle(), aBound, nMapMode );
- bBoundsDetermined = true;
- break;
-
- case W_META_ROUNDRECT:
- ReadYXExt(); // size
- GetWinExtMax( ReadRectangle(), aBound, nMapMode );
- bBoundsDetermined = true;
- break;
-
- case W_META_ARC:
- case W_META_PIE:
- case W_META_CHORD:
- ReadYX(); // end
- ReadYX(); // start
- GetWinExtMax( ReadRectangle(), aBound, nMapMode );
- bBoundsDetermined = true;
- break;
-
- case W_META_POLYGON:
- {
- bool bRecordOk = true;
-
- sal_uInt16 nPoints(0);
- pStm->ReadUInt16( nPoints );
-
- if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- }
- else
- {
- for(sal_uInt16 i = 0; i < nPoints; i++ )
- {
- GetWinExtMax( ReadPoint(), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polyline record claimed more points than the stream can provide");
-
- if (!bRecordOk)
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- break;
- }
- }
- break;
-
- case W_META_POLYPOLYGON:
- {
- bool bRecordOk = true;
- sal_uInt16 nPoly(0), nPoints(0);
- pStm->ReadUInt16(nPoly);
- if (nPoly > pStm->remainingSize() / sizeof(sal_uInt16))
- {
- bRecordOk = false;
- }
- else
- {
- for(sal_uInt16 i = 0; i < nPoly; i++ )
- {
- sal_uInt16 nP = 0;
- pStm->ReadUInt16( nP );
- if (nP > SAL_MAX_UINT16 - nPoints)
- {
- bRecordOk = false;
- break;
- }
- nPoints += nP;
- }
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polypolygon record has more polygons than we can handle");
-
- bRecordOk = bRecordOk && pStm->good();
-
- if (!bRecordOk)
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- break;
- }
-
- if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- }
- else
- {
- for (sal_uInt16 i = 0; i < nPoints; i++ )
- {
- GetWinExtMax( ReadPoint(), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polypolygon record claimed more points than the stream can provide");
-
- bRecordOk &= pStm->good();
-
- if (!bRecordOk)
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- break;
- }
- }
- break;
-
- case W_META_POLYLINE:
- {
- bool bRecordOk = true;
-
- sal_uInt16 nPoints(0);
- pStm->ReadUInt16(nPoints);
- if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
- {
- bRecordOk = false;
- }
- else
- {
- for (sal_uInt16 i = 0; i < nPoints; ++i)
- {
- GetWinExtMax( ReadPoint(), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
-
- SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polyline record claimed more points than the stream can provide");
-
- if (!bRecordOk)
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- break;
- }
- }
- break;
-
- case W_META_SETPIXEL:
- {
- ReadColor();
- GetWinExtMax( ReadYX(), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- break;
-
- case W_META_TEXTOUT:
- {
- sal_uInt16 nLength;
- pStm->ReadUInt16( nLength );
- // todo: we also have to take care of the text width
- if ( nLength )
- {
- pStm->SeekRel( ( nLength + 1 ) &~ 1 );
- GetWinExtMax( ReadYX(), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
- break;
-
- case W_META_EXTTEXTOUT:
- {
- sal_uInt16 nLen, nOptions;
- Point aPosition;
-
- aPosition = ReadYX();
- pStm->ReadUInt16( nLen ).ReadUInt16( nOptions );
- // todo: we also have to take care of the text width
- if( nLen )
- {
- GetWinExtMax( aPosition, aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
- break;
- case W_META_BITBLT:
- case W_META_STRETCHBLT:
- case W_META_DIBBITBLT:
- case W_META_DIBSTRETCHBLT:
- case W_META_STRETCHDIB:
- {
- sal_Int32 nWinROP;
- sal_uInt16 nSx, nSy, nUsage;
- pStm->ReadInt32( nWinROP );
-
- if( nFunction == W_META_STRETCHDIB )
- pStm->ReadUInt16( nUsage );
-
- // nSye and nSxe is the number of pixels that has to been used
- if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
- {
- sal_uInt16 nSxe, nSye;
- pStm->ReadUInt16( nSye ).ReadUInt16( nSxe );
- }
-
- // nSy and nx is the offset of the first pixel
- pStm->ReadUInt16( nSy ).ReadUInt16( nSx );
-
- if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
- {
- if ( nWinROP == PATCOPY )
- pStm->ReadUInt16( nUsage ); // i don't know anything of this parameter, so its called nUsage
- // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), false );
-
- Size aDestSize( ReadYXExt() );
- if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
- {
- tools::Rectangle aDestRect( ReadYX(), aDestSize );
- GetWinExtMax( aDestRect, aBound, nMapMode );
- bBoundsDetermined = true;
- }
- }
- }
- break;
-
- case W_META_PATBLT:
- {
- sal_uInt32 nROP;
- pStm->ReadUInt32( nROP );
- Size aSize = ReadYXExt();
- GetWinExtMax( tools::Rectangle( ReadYX(), aSize ), aBound, nMapMode );
- bBoundsDetermined = true;
- }
- break;
- }
-
- const sal_uInt32 nAvailableBytes = nEnd - nPos;
- const sal_uInt32 nMaxPossibleRecordSize = nAvailableBytes/2;
- if (nRSize <= nMaxPossibleRecordSize)
- {
- nPos += nRSize * 2;
- pStm->Seek( nPos );
- }
- else
- {
- pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
- bRet = false;
- }
- }
- }
- else
- {
- pStm->SetError( SVSTREAM_GENERALERROR );
- bRet = false;
- }
-
- if (bRet)
- {
- if (aWinExt)
- {
- rPlaceableBound = tools::Rectangle(aWinOrg, *aWinExt);
- SAL_INFO("vcl.wmf", "Window dimension "
- " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
- << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
- }
- else if (aViewportExt)
- {
- rPlaceableBound = tools::Rectangle(aViewportOrg, *aViewportExt);
- SAL_INFO("vcl.wmf", "Viewport dimension "
- " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
- << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
- }
- else if (bBoundsDetermined)
- {
- rPlaceableBound = aBound;
- SAL_INFO("vcl.wmf", "Determined dimension "
- " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
- << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
- }
- else
- {
- rPlaceableBound.Left() = 0;
- rPlaceableBound.Top() = 0;
- rPlaceableBound.Right() = aMaxWidth;
- rPlaceableBound.Bottom() = aMaxWidth;
- SAL_INFO("vcl.wmf", "Default dimension "
- " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
- << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
- }
- }
-}
-
-WMFReader::WMFReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile,
- FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER* pExtHeader)
- : WinMtf(rGDIMetaFile, rStreamWMF, pConfigItem)
- , nUnitsPerInch(96)
- , nRecSize(0)
- , nEMFRecCount(0)
- , nEMFRec(0)
- , nEMFSize(0)
- , nSkipActions(0)
- , pExternalHeader(pExtHeader)
-{}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx
index ad9d1536d1d5..f620a8e00303 100644
--- a/vcl/source/filter/wmf/wmf.cxx
+++ b/vcl/source/filter/wmf/wmf.cxx
@@ -17,65 +17,38 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include "winmtf.hxx"
#include "emfwr.hxx"
#include "wmfwr.hxx"
#include <vcl/wmf.hxx>
#include <vcl/gdimetafiletools.hxx>
#include <comphelper/scopeguard.hxx>
-bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER *pExtHeader )
-{
- sal_uInt32 nMetaType;
- sal_uInt32 nOrgPos = rStreamWMF.Tell();
- SvStreamEndian nOrigNumberFormat = rStreamWMF.GetEndian();
- rStreamWMF.SetEndian( SvStreamEndian::LITTLE );
- rStreamWMF.Seek( 0x28 );
- rStreamWMF.ReadUInt32( nMetaType );
- rStreamWMF.Seek( nOrgPos );
- if ( nMetaType == 0x464d4520 )
- {
- if ( !EnhWMFReader( rStreamWMF, rGDIMetaFile, pConfigItem ).ReadEnhWMF() )
- rStreamWMF.SetError( SVSTREAM_FILEFORMAT_ERROR );
- }
- else
- {
- WMFReader( rStreamWMF, rGDIMetaFile, pConfigItem, pExtHeader ).ReadWMF( );
- }
-
- // #i123216# allow a look at CheckSum and ByteSize for debugging
- SAL_INFO("vcl.emf", "\t\t\tchecksum: 0x" << std::hex << rGDIMetaFile.GetChecksum() << std::dec);
- SAL_INFO("vcl.emf", "\t\t\tsize: " << rGDIMetaFile.GetSizeBytes());
-
- rStreamWMF.SetEndian( nOrigNumberFormat );
- return !rStreamWMF.GetError();
-}
-
bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF )
{
- sal_uInt32 nMetaType(0);
- sal_uInt32 nOrgPos = rStream.Tell();
-
- SvStreamEndian nOrigNumberFormat = rStream.GetEndian();
- rStream.SetEndian( SvStreamEndian::LITTLE );
- //exception-safe reset nOrigNumberFormat at end of scope
- const ::comphelper::ScopeGuard aScopeGuard( [&rStream, nOrigNumberFormat] () { rStream.SetEndian( nOrigNumberFormat ); } );
-
- rStream.Seek( 0x28 );
- rStream.ReadUInt32( nMetaType );
- rStream.Seek( nOrgPos );
-
- if (!rStream.good())
- return false;
-
- if ( nMetaType == 0x464d4520 )
- {
- if ( !EnhWMFReader( rStream, rMTF, nullptr ).ReadEnhWMF() )
- rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
- }
- else
+ // Use new method to import Metafile. First, read binary data to mem array
+ const sal_uInt32 nStreamLength(rStream.Seek(STREAM_SEEK_TO_END));
+ VectorGraphicDataArray aNewData(nStreamLength);
+ rStream.Seek(0);
+ rStream.ReadBytes(aNewData.begin(), nStreamLength);
+ rStream.Seek(0);
+
+ if (rStream.good())
{
- WMFReader( rStream, rMTF, nullptr ).ReadWMF();
+ // Throw into VectorGraphicData to get the import. Do not care
+ // too much for type, this will be checked there. Also no path
+ // needed, it is a temporary object
+ VectorGraphicDataPtr aVectorGraphicDataPtr(
+ new VectorGraphicData(
+ aNewData,
+ OUString(),
+ VectorGraphicDataType::Emf));
+
+ // create a Graphic and grep Metafile from it
+ const Graphic aGraphic(aVectorGraphicDataPtr);
+
+ // get the Metafile from it, done
+ rMTF = aGraphic.GetGDIMetaFile();
+ return true;
}
return rStream.good();
diff --git a/vcl/source/filter/wmf/wmfexternal.cxx b/vcl/source/filter/wmf/wmfexternal.cxx
new file mode 100644
index 000000000000..eda806a3d113
--- /dev/null
+++ b/vcl/source/filter/wmf/wmfexternal.cxx
@@ -0,0 +1,76 @@
+/* -*- 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 <vcl/wmfexternal.hxx>
+
+// formally known as WMF_EXTERNALHEADER
+WmfExternal::WmfExternal() :
+ xExt(0),
+ yExt(0),
+ mapMode(0)
+{
+}
+
+css::uno::Sequence< css::beans::PropertyValue > WmfExternal::getSequence() const
+{
+ css::uno::Sequence< css::beans::PropertyValue > aSequence;
+
+ if (0 != xExt || 0 != yExt || 0 != mapMode)
+ {
+ aSequence.realloc(3);
+ aSequence[0].Name = "Width";
+ aSequence[0].Value <<= (sal_Int16)xExt;
+ aSequence[1].Name = "Height";
+ aSequence[1].Value <<= (sal_Int16)yExt;
+ aSequence[2].Name = "MapMode";
+ aSequence[2].Value <<= (sal_Int16)mapMode;
+ }
+
+ return aSequence;
+}
+
+bool WmfExternal::setSequence(const css::uno::Sequence< css::beans::PropertyValue >& rSequence)
+{
+ bool bRetval(false);
+
+ for (sal_Int32 i = 0; i < rSequence.getLength(); ++i)
+ {
+ const OUString aName(rSequence[i].Name);
+
+ if (aName == "Width")
+ {
+ rSequence[i].Value >>= xExt;
+ bRetval = true;
+ }
+ else if (aName == "Height")
+ {
+ rSequence[i].Value >>= yExt;
+ bRetval = true;
+ }
+ else if (aName == "MapMode")
+ {
+ rSequence[i].Value >>= mapMode;
+ bRetval = true;
+ }
+ }
+
+ return bRetval;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */