WindowsXP-SP1/windows/advcore/gdiplus/engine/entry/metawmf.hpp
2020-09-30 16:53:49 +02:00

704 lines
22 KiB
C++

/**************************************************************************\
*
* Copyright (c) 1999 Microsoft Corporation
*
* Module Name:
*
* MetaWmf.hpp
*
* Abstract:
*
* Metafile definitions for WMF and EMF playback
*
* Created:
*
* 1/6/2000 DCurtis
*
\**************************************************************************/
#ifndef _METAWMF_HPP
#define _METAWMF_HPP
//#define GDIP_EXCEPTIONS 0
#define GDIP_TRY __try {
#define GDIP_CATCH } __except(EXCEPTION_EXECUTE_HANDLER) {
#define GDIP_ENDCATCH }
#define GDIP_RECORDBUFFER_SIZE 2048 // >= 1138 so pattern brushes work
#define SIZEOF_METARECORDHEADER (sizeof(DWORD) + sizeof(WORD))
#define NUM_STOCK_FONTS (DEFAULT_GUI_FONT - OEM_FIXED_FONT + 1)
#define NUM_STOCK_RECOLOR_OBJS 7
/*****************************************************************************
Commenting.
These interfaces allow comments to be added to a metafile DC which describe
grouping and other information useful for decoding metafiles, the
interfaces which take an MSODC have no effect if the DC is not a picture
(PICT, WMF or EMF) DC.
For PICT files there are two levels of structure, the public comment
"kind" which is a globally defined comment and the "private" comment kind,
which is used for application-specific comments. In a PICT the public
comment kind is the kind argument to PicComment and the private kind is
used if the public value is pictApplicationComment.
In a WMF the signature indicates whether the comment is public or private,
all comments look like the PICT private comment.
In an EMF GdiComment() defines some "public" comments plus a format for
"private" comments - see the Win32 API documentation.
******************************************************************* JohnBo **/
// Definition of the comment codes used in the various metafile formats.
const ULONG msosignaturePublic =0xFFFFFFFF; // WMF public signature.
const ULONG msosignaturePPOld =0x5050FE54; // PowerPoint 2 signature
const ULONG msosignaturePP =0x50504E54; // PowerPoint signature
const ULONG msosignature =0x50504E54; // Office/Escher signature
// The following enumeration defines the ukind values in the above structure,
// note that these duplicate the PICT comment kinds for groups because in
// a WMF (but *NOT* a PICT or EMF) and MSOMFCOMMENT structure must be used,
// this enumeration contains all the valid kinds, including both the public
// and private kinds, these may overlap because they are distinguished by
// the "signature".
typedef enum
{
// Public WMF comments - signature == msosignaturePublic.
msocommentBeginGroup = 0x0000, // Public WMF begin group.
msocommentEndGroup = 0x0001, // Public WMF end group.
msocommentBeginHeader = 0x0002,
msocommentEndHeader = 0x0003,
msocommentCreator = 0x0004,
msocommentWinVersion = 0x0005,
// Private PICT and WMF comments - signature == msosignature.
msocommentVersion = 0x0000,
msocommentBFileBlock = 0x0001, // UNUSED
msocommentBeginPicture = 0x0002,
msocommentEndPicture = 0x0003,
msocommentDevInfo = 0x0004,
msocommentBeginHyperOpaque = 0x0005, // UNUSED
msocommentEndHyperOpaque = 0x0006, // UNUSED
msocommentBeginFade = 0x0007,
msocommentEndFade = 0x0008,
msocommentDitherDetect = 0x0009, // Not used now?
// New values used in Office97.
msocommentPictureDescription = 0x0101, // Description text.
msocommentBeginGelEffect = 0x0102,
msocommentEndGelEffect = 0x0103,
msocommentBeginClipPath = 0x0104,
msocommentEndClipPath = 0x0105,
msocommentBeginSrcCopy = 0x0106,
msocommentEndSrcCopy = 0x0107,
// Reserved comments used internally by Mac PP4.
msocommentPictUnmute = 0x7FFE,
msocommentPictMute = 0x7FFF,
// The following is a flag - what is it for?
msocommentRegistered = 0x8000
} MSOMFCOMMENTKIND;
typedef struct
{
UINT Handle;
COLORREF Color;
BOOL Brush;
}
RecolorStockObject;
extern RecolorStockObject RecolorStockObjectList[NUM_STOCK_RECOLOR_OBJS];
enum GdipHdcType
{
UnknownHdc = 0x00000000,
ScreenHdc = 0x00000001,
BitmapHdc = 0x00000002,
MetafileHdc = 0x00000004,
PrinterHdc = 0x00000008,
PostscriptHdc = 0x00010000,
PostscriptPrinterHdc = PrinterHdc | PostscriptHdc,
EmfHdc = 0x00100000 | MetafileHdc,
WmfHdc = 0x00200000 | MetafileHdc,
};
enum MfFsmState
{
MfFsmStart,
MfFsmPSData,
MfFsmCreateBrushIndirect,
MfFsmSelectBrush,
MfFsmCreatePenIndirect,
MfFsmSelectPen,
MfFsmSetROP,
};
class MfEnumState
{
protected:
GdipHdcType HdcType;
HDC Hdc;
INT SaveDcVal;
INT SaveDcCount;
INT NumObjects; // num objects in handle table
INT SizeAllocedRecord;
INT ModifiedRecordSize;
INT BytesEnumerated;
BOOL ExternalEnumeration;
HPALETTE CurrentPalette;
HFONT DefaultFont;
HFONT StockFonts[NUM_STOCK_FONTS];
HANDLETABLE * HandleTable;
GpRecolor * Recolor;
ColorAdjustType AdjustType;
const BYTE * RecordData;
UINT RecordDataSize;
EmfPlusRecordType RecordType;
InterpolationMode Interpolation;
BOOL Is8Bpp;
BOOL IsHalftonePalette;
COLORREF BkColor;
COLORREF TextColor;
RECT DestRectDevice;
BOOL RopUsed;
DpContext * Context;
union
{
const VOID * CurrentRecord;
const METARECORD * CurrentWmfRecord;
const ENHMETARECORD * CurrentEmfRecord;
};
union
{
VOID * ModifiedRecord;
METARECORD * ModifiedWmfRecord;
ENHMETARECORD * ModifiedEmfRecord;
};
union
{
VOID * AllocedRecord;
METARECORD * AllocedWmfRecord;
ENHMETARECORD * AllocedEmfRecord;
};
BYTE RecordBuffer[GDIP_RECORDBUFFER_SIZE];
MfFsmState FsmState;
BOOL GdiCentricMode;
BOOL SoftekFilter;
HGDIOBJ RecoloredStockHandle[NUM_STOCK_RECOLOR_OBJS];
BOOL SrcCopyOnly;
public:
MfEnumState(
HDC hdc,
BOOL externalEnumeration,
InterpolationMode interpolation,
GpRecolor * recolor,
ColorAdjustType adjustType,
const RECT * dest,
DpContext * context
);
~MfEnumState();
BOOL IsValid() { return (SaveDcVal != 0); }
BOOL IsMetafile() { return ((HdcType & MetafileHdc) == MetafileHdc); }
BOOL IsPostscript() { return ((HdcType & PostscriptHdc) == PostscriptHdc); }
BOOL IsPrinter() { return ((HdcType & PrinterHdc) == PrinterHdc);}
BOOL IsPostscriptPrinter(){ return ((HdcType & PostscriptPrinterHdc) == PostscriptPrinterHdc);}
BOOL IsBitmap() { return ((HdcType & BitmapHdc) == BitmapHdc); }
BOOL IsScreen() { return ((HdcType & ScreenHdc) == ScreenHdc); }
BOOL GetRopUsed() { return RopUsed; }
VOID ResetRopUsed() { RopUsed = FALSE; }
VOID
StartRecord(
HDC hdc,
HANDLETABLE * handleTable,
INT numObjects,
const VOID * currentRecord,
EmfPlusRecordType recordType,
UINT recordDataSize,
const BYTE * recordData
)
{
ASSERT(hdc != NULL);
Hdc = hdc;
ModifiedRecord = NULL;
ModifiedRecordSize = 0;
CurrentRecord = currentRecord;
RecordType = recordType;
RecordDataSize = recordDataSize;
RecordData = recordData;
BytesEnumerated += GetCurrentRecordSize();
if ((handleTable != NULL) && (numObjects > 0))
{
HandleTable = handleTable;
NumObjects = numObjects;
}
else
{
WARNING(("NULL handle table and/or no objects"));
HandleTable = NULL;
NumObjects = 0;
}
}
virtual BOOL
ProcessRecord(
EmfPlusRecordType recordType,
UINT recordDataSize,
const BYTE * recordData
) = 0;
virtual BOOL PlayRecord() = 0;
VOID SaveHdc()
{
SaveDcCount--;
this->PlayRecord();
}
virtual VOID RestoreHdc() = 0;
VOID SelectPalette(INT objectIndex);
protected:
virtual INT GetCurrentRecordSize() const = 0;
BOOL CreateRecordToModify(INT size = 0);
COLORREF ModifyColor(
COLORREF color,
ColorAdjustType adjustType
);
INT
GetModifiedDibSize(
BITMAPINFOHEADER UNALIGNED * dibInfo,
UINT numPalEntries,
UINT dibBitsSize,
UINT & usage
);
VOID
ModifyDib(
UINT usage,
BITMAPINFOHEADER UNALIGNED * srcDibInfo,
BYTE * srcBits,
BITMAPINFOHEADER UNALIGNED * dstDibInfo,
UINT numPalEntries,
UINT srcDibBitsSize,
ColorAdjustType adjustType
);
VOID
Modify16BppDib(
INT width,
INT posHeight,
BYTE * srcPixels,
DWORD UNALIGNED * bitFields,
BYTE * dstPixels,
ColorAdjustType adjustType
);
VOID
Modify24BppDib(
INT width,
INT posHeight,
BYTE * srcPixels,
DWORD UNALIGNED * bitFields,
BYTE * dstPixels,
ColorAdjustType adjustType
);
VOID
Modify32BppDib(
INT width,
INT posHeight,
BYTE * srcPixels,
DWORD UNALIGNED * bitFields,
BYTE * dstPixels,
ColorAdjustType adjustType
);
VOID
OutputDIB(
HDC hdc,
const RECTL * bounds,
INT dstX,
INT dstY,
INT dstWidth,
INT dstHeight,
INT srcX,
INT srcY,
INT srcWidth,
INT srcHeight,
BITMAPINFOHEADER UNALIGNED * dibInfo,
BYTE * bits, // if NULL, this is a packed DIB
UINT usage,
DWORD rop,
BOOL isWmfDib
);
virtual BOOL CreateAndPlayOutputDIBRecord(
HDC hdc,
const RECTL * bounds,
INT dstX,
INT dstY,
INT dstWidth,
INT dstHeight,
INT srcX,
INT srcY,
INT srcWidth,
INT srcHeight,
BITMAPINFOHEADER UNALIGNED * dibInfo,
BYTE * bits, // if NULL, this is a packed DIB
UINT usage,
DWORD rop
)=0;
virtual BOOL CreateAndPlayCommentRecord()
{
return TRUE;
}
virtual VOID IntersectDestRect()=0;
};
class WmfEnumState : public MfEnumState
{
public:
BOOL IgnorePostscript;
protected:
INT MetafileSize;
HPEN HpenSave;
HBRUSH HbrushSave;
HPALETTE HpaletteSave;
HFONT HfontSave;
HBITMAP HbitmapSave;
HRGN HregionSave;
BOOL FirstViewportOrg;
BOOL FirstViewportExt;
GpMatrix ViewportXForm;
POINT ImgViewportOrg;
SIZE ImgViewportExt;
POINT DstViewportOrg;
SIZE DstViewportExt;
BOOL IsFirstRecord;
public:
WmfEnumState(
HDC hdc,
HMETAFILE hWmf,
BOOL externalEnumeration,
InterpolationMode interpolation,
const RECT * dstRect,
const RECT * deviceRect,
DpContext * context,
GpRecolor * recolor = NULL,
ColorAdjustType adjustType = ColorAdjustTypeDefault
);
~WmfEnumState();
virtual BOOL
ProcessRecord(
EmfPlusRecordType recordType,
UINT recordDataSize,
const BYTE * recordData
);
virtual BOOL PlayRecord();
virtual VOID RestoreHdc();
VOID EndRecord();
VOID SetBkColor()
{
BkColor = *((COLORREF UNALIGNED *)&(((WORD UNALIGNED *)RecordData)[0]));
ModifyRecordColor(0, ColorAdjustTypeBrush);
this->PlayRecord();
}
VOID SetTextColor()
{
TextColor = *((COLORREF UNALIGNED *)&(((WORD UNALIGNED *)RecordData)[0]));
ModifyRecordColor(0, ColorAdjustTypeText);
this->PlayRecord();
}
VOID FloodFill()
{
ModifyRecordColor(0, ColorAdjustTypeBrush);
this->PlayRecord();
}
VOID ExtFloodFill()
{
ModifyRecordColor(1, ColorAdjustTypeBrush);
this->PlayRecord();
}
VOID SetPixel()
{
ModifyRecordColor(0, ColorAdjustTypePen);
this->PlayRecord();
}
VOID DibCreatePatternBrush();
VOID CreatePatternBrush();
VOID CreatePenIndirect();
VOID CreateBrushIndirect();
VOID BitBlt();
VOID StretchBlt()
{
this->BitBlt();
}
VOID Escape();
VOID SetDIBitsToDevice();
VOID PolyPolygon();
VOID DIBBitBlt();
VOID DIBStretchBlt()
{
this->DIBBitBlt();
}
VOID StretchDIBits();
VOID SetViewportOrg();
VOID SetViewportExt();
VOID Rectangle();
VOID CreateFontIndirect();
VOID SelectObject();
VOID CreateRegion();
VOID SetROP2();
protected:
virtual INT GetCurrentRecordSize() const { return RecordDataSize + SIZEOF_METARECORDHEADER; }
BOOL CreateCopyOfCurrentRecord();
VOID ModifyRecordColor(
INT paramIndex,
ColorAdjustType adjustType
);
VOID MakeSolidBlackBrush();
VOID CalculateViewportMatrix();
virtual BOOL CreateAndPlayOutputDIBRecord(
HDC hdc,
const RECTL * bounds,
INT dstX,
INT dstY,
INT dstWidth,
INT dstHeight,
INT srcX,
INT srcY,
INT srcWidth,
INT srcHeight,
BITMAPINFOHEADER UNALIGNED * dibInfo,
BYTE * bits, // if NULL, this is a packed DIB
UINT usage,
DWORD rop
);
virtual VOID IntersectDestRect();
};
class EmfEnumState : public MfEnumState
{
protected:
HRGN ClipRgn;
POINT BrushOrg;
HPALETTE Palette;
public:
EmfEnumState(
HDC hdc,
HENHMETAFILE hEmf,
const RECT * dest,
const RECT * deviceRect,
BOOL externalEnumeration,
InterpolationMode interpolation,
DpContext * context,
GpRecolor * recolor = NULL,
ColorAdjustType adjustType = ColorAdjustTypeDefault
);
~EmfEnumState()
{
GpFree(AllocedRecord);
if (IsMetafile())
{
// Bug 106406 from Office: Missing RestoreDC in EMF
// Account for unbalanced SaveDC/RestoreDC pairs and
// restore to the saveDC state
::RestoreDC(Hdc, SaveDcCount - 1);
}
else
{
::RestoreDC(Hdc, SaveDcVal);
}
}
virtual BOOL
ProcessRecord(
EmfPlusRecordType recordType,
UINT recordDataSize,
const BYTE * recordData
);
// returns a pointer to the current record, but the header may
// not actually be there -- just the data of the record.
const ENHMETARECORD * GetPartialRecord()
{
if (CurrentEmfRecord != NULL)
{
return CurrentEmfRecord;
}
ASSERT(RecordData != NULL);
return (const ENHMETARECORD *)(((const BYTE *)RecordData) - sizeof(EMR));
}
virtual BOOL PlayRecord();
virtual VOID RestoreHdc();
VOID Header();
VOID SelectPalette(INT objectIndex);
VOID SetPixelV()
{
ModifyRecordColor(2, ColorAdjustTypePen);
this->PlayRecord();
}
VOID SetTextColor()
{
TextColor = ((COLORREF *)RecordData)[0];
ModifyRecordColor(0, ColorAdjustTypeText);
this->PlayRecord();
}
VOID SetBkColor()
{
BkColor = ((COLORREF *)RecordData)[0];
ModifyRecordColor(0, ColorAdjustTypeBrush);
this->PlayRecord();
}
VOID CreatePen();
VOID CreateBrushIndirect();
VOID ExtFloodFill()
{
ModifyRecordColor(2, ColorAdjustTypeBrush);
this->PlayRecord();
}
VOID GdiComment();
VOID BitBlt();
VOID StretchBlt();
VOID SetDIBitsToDevice();
VOID StretchDIBits();
VOID CreateDibPatternBrushPt();
VOID ExtCreatePen();
VOID MaskBlt()
{
// !!! to do
ResetRecordBounds();
this->PlayRecord();
}
VOID PlgBlt()
{
// !!! to do
ResetRecordBounds();
this->PlayRecord();
}
VOID GradientFill()
{
// !!! to do
this->PlayRecord();
}
VOID TransparentBlt()
{
// !!! to do
ResetRecordBounds();
this->PlayRecord();
}
VOID AlphaBlend()
{
// !!! to do
ResetRecordBounds();
this->PlayRecord();
}
VOID ExtEscape();
VOID ExtCreateFontIndirect();
VOID SelectObject();
VOID SetROP2();
VOID ExtTextOutW();
VOID Rectangle();
protected:
virtual INT GetCurrentRecordSize() const { return RecordDataSize + sizeof(EMR); }
BOOL CreateCopyOfCurrentRecord();
VOID ModifyRecordColor(
INT paramIndex,
ColorAdjustType adjustType
);
BOOL ValidObjectIndex(INT objectIndex)
{
return ((objectIndex > 0) && (objectIndex < NumObjects));
}
BITMAPINFOHEADER *
CreateModifiedDib(
BITMAPINFOHEADER * srcDibInfo,
BYTE * srcBits,
UINT & usage,
DWORD rop
);
virtual BOOL CreateAndPlayOutputDIBRecord(
HDC hdc,
const RECTL * bounds,
INT dstX,
INT dstY,
INT dstWidth,
INT dstHeight,
INT srcX,
INT srcY,
INT srcWidth,
INT srcHeight,
BITMAPINFOHEADER UNALIGNED * dibInfo,
BYTE * bits, // if NULL, this is a packed DIB
UINT usage,
DWORD rop
);
virtual VOID IntersectDestRect();
VOID ResetRecordBounds();
virtual BOOL CreateAndPlayCommentRecord()
{
// This will create an Empty comment record and play it through GDI
// This is necessary to invalidate the Transform cache that Win9x keeps
// while playing metafiles. If we need to query the current transform
// this makes sure that the result is the current one and not the
// previously cached transform
// Allocate a comment buffer that has 1 DWORD in the Data field.
BYTE buffer[(sizeof(EMRGDICOMMENT)+3) & ~3];
EMRGDICOMMENT* comment = (EMRGDICOMMENT*) buffer;
comment->emr.iType = EMR_GDICOMMENT;
comment->emr.nSize = (sizeof(EMRGDICOMMENT)+3) & ~3;
comment->cbData = 4;
*(DWORD*)(comment->Data) = 0;
return PlayEnhMetaFileRecord(Hdc, HandleTable, (ENHMETARECORD*)comment, NumObjects);
}
};
BOOL
GetDibNumPalEntries(
BOOL isWmfDib,
UINT biSize,
UINT biBitCount,
UINT biCompression,
UINT biClrUsed,
UINT * numPalEntries
);
UINT
GetDibBitsSize(
BITMAPINFOHEADER UNALIGNED * dibInfo
);
inline static BOOL
IsSourceInRop3(
DWORD rop3
)
{
return (rop3 & 0xCCCC0000) != ((rop3 << 2) & 0xCCCC0000);
}
#endif // !_METAWMF_HPP