Windows2003-3790/windows/advcore/gdiplus/test/emfdcode/wmfmeta.cpp
2020-09-30 16:53:55 +02:00

5979 lines
207 KiB
C++

/***********************************************************************
MODULE : WMFMETA.CPP
FUNCTIONS : MetaEnumProc
GetMetaFileAndEnum
LoadParameterLB
PlayMetaFileToDest
RenderClipMeta
RenderPlaceableMeta
SetPlaceableExts
SetClipMetaExts
ProcessFile
COMMENTS :
************************************************************************/
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <objbase.h>
extern "C" {
#include "mfdcod32.h"
}
extern "C" {
extern BOOL bConvertToGdiPlus;
extern BOOL bUseGdiPlusToPlay;
}
#include "GdiPlus.h"
#include "MyData.hpp"
#include "dibstream.hpp"
#include "../gpinit.inc"
#ifndef ASSERT
#ifdef _DEBUG // poor man's assert
#define ASSERT(cond) if (!(cond)) { int b = 0; b = 1 / b; }
#else
#define ASSERT(cond)
#endif
#endif
// Check if a source is needed in a 3-way bitblt operation.
// This works on both rop and rop3. We assume that a rop contains zero
// in the high byte.
//
// This is tested by comparing the rop result bits with source (column A
// below) vs. those without source (column B). If the two cases are
// identical, then the effect of the rop does not depend on the source
// and we don't need a source device. Recall the rop construction from
// input (pattern, source, target --> result):
//
// P S T | R A B mask for A = 0CCh
// ------+-------- mask for B = 33h
// 0 0 0 | x 0 x
// 0 0 1 | x 0 x
// 0 1 0 | x x 0
// 0 1 1 | x x 0
// 1 0 0 | x 0 x
// 1 0 1 | x 0 x
// 1 1 0 | x x 0
// 1 1 1 | x x 0
#define ISSOURCEINROP3(rop3) \
(((rop3) & 0xCCCC0000) != (((rop3) << 2) & 0xCCCC0000))
#ifndef EMR_SETICMMODE
#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
#endif
#ifndef EMR_DRAWESCAPE
#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_SETLAYOUT 115
#define EMR_TRANSPARENTBLT 116
#define EMR_GRADIENTFILL 118
#define EMR_SETLINKEDUFIS 119
#define EMR_SETTEXTJUSTIFICATION 120
#define EMR_COLORMATCHTOTARGETW 121
#define EMR_CREATECOLORSPACEW 122
#endif
#define TOREAL(i) (static_cast<float>(i))
//
// Wrap a GDI+ TextureBrush object around DIB data
//
class DibBrush
{
public:
DibBrush(const BITMAPINFO* bmi, const BYTE* bits) :
dibStream(bmi, bits),
bitmap(&dibStream),
brush(&bitmap)
{
}
operator Gdiplus::TextureBrush*()
{
return &brush;
}
private:
DibStream dibStream;
Gdiplus::Bitmap bitmap;
Gdiplus::TextureBrush brush;
};
//
//lookup table for EMF and WMF metafile records
//
EMFMETARECORDS emfMetaRecords[] = {
"WmfSetBkColor" , Gdiplus::WmfRecordTypeSetBkColor ,
"WmfSetBkMode" , Gdiplus::WmfRecordTypeSetBkMode ,
"WmfSetMapMode" , Gdiplus::WmfRecordTypeSetMapMode ,
"WmfSetROP2" , Gdiplus::WmfRecordTypeSetROP2 ,
"WmfSetRelAbs" , Gdiplus::WmfRecordTypeSetRelAbs ,
"WmfSetPolyFillMode" , Gdiplus::WmfRecordTypeSetPolyFillMode ,
"WmfSetStretchBltMode" , Gdiplus::WmfRecordTypeSetStretchBltMode ,
"WmfSetTextCharExtra" , Gdiplus::WmfRecordTypeSetTextCharExtra ,
"WmfSetTextColor" , Gdiplus::WmfRecordTypeSetTextColor ,
"WmfSetTextJustification" , Gdiplus::WmfRecordTypeSetTextJustification ,
"WmfSetWindowOrg" , Gdiplus::WmfRecordTypeSetWindowOrg ,
"WmfSetWindowExt" , Gdiplus::WmfRecordTypeSetWindowExt ,
"WmfSetViewportOrg" , Gdiplus::WmfRecordTypeSetViewportOrg ,
"WmfSetViewportExt" , Gdiplus::WmfRecordTypeSetViewportExt ,
"WmfOffsetWindowOrg" , Gdiplus::WmfRecordTypeOffsetWindowOrg ,
"WmfScaleWindowExt" , Gdiplus::WmfRecordTypeScaleWindowExt ,
"WmfOffsetViewportOrg" , Gdiplus::WmfRecordTypeOffsetViewportOrg ,
"WmfScaleViewportExt" , Gdiplus::WmfRecordTypeScaleViewportExt ,
"WmfLineTo" , Gdiplus::WmfRecordTypeLineTo ,
"WmfMoveTo" , Gdiplus::WmfRecordTypeMoveTo ,
"WmfExcludeClipRect" , Gdiplus::WmfRecordTypeExcludeClipRect ,
"WmfIntersectClipRect" , Gdiplus::WmfRecordTypeIntersectClipRect ,
"WmfArc" , Gdiplus::WmfRecordTypeArc ,
"WmfEllipse" , Gdiplus::WmfRecordTypeEllipse ,
"WmfFloodFill" , Gdiplus::WmfRecordTypeFloodFill ,
"WmfPie" , Gdiplus::WmfRecordTypePie ,
"WmfRectangle" , Gdiplus::WmfRecordTypeRectangle ,
"WmfRoundRect" , Gdiplus::WmfRecordTypeRoundRect ,
"WmfPatBlt" , Gdiplus::WmfRecordTypePatBlt ,
"WmfSaveDC" , Gdiplus::WmfRecordTypeSaveDC ,
"WmfSetPixel" , Gdiplus::WmfRecordTypeSetPixel ,
"WmfOffsetClipRgn" , Gdiplus::WmfRecordTypeOffsetClipRgn ,
"WmfTextOut" , Gdiplus::WmfRecordTypeTextOut ,
"WmfBitBlt" , Gdiplus::WmfRecordTypeBitBlt ,
"WmfStretchBlt" , Gdiplus::WmfRecordTypeStretchBlt ,
"WmfPolygon" , Gdiplus::WmfRecordTypePolygon ,
"WmfPolyline" , Gdiplus::WmfRecordTypePolyline ,
"WmfEscape" , Gdiplus::WmfRecordTypeEscape ,
"WmfRestoreDC" , Gdiplus::WmfRecordTypeRestoreDC ,
"WmfFillRegion" , Gdiplus::WmfRecordTypeFillRegion ,
"WmfFrameRegion" , Gdiplus::WmfRecordTypeFrameRegion ,
"WmfInvertRegion" , Gdiplus::WmfRecordTypeInvertRegion ,
"WmfPaintRegion" , Gdiplus::WmfRecordTypePaintRegion ,
"WmfSelectClipRegion" , Gdiplus::WmfRecordTypeSelectClipRegion ,
"WmfSelectObject" , Gdiplus::WmfRecordTypeSelectObject ,
"WmfSetTextAlign" , Gdiplus::WmfRecordTypeSetTextAlign ,
"WmfDrawText" , Gdiplus::WmfRecordTypeDrawText ,
"WmfChord" , Gdiplus::WmfRecordTypeChord ,
"WmfSetMapperFlags" , Gdiplus::WmfRecordTypeSetMapperFlags ,
"WmfExtTextOut" , Gdiplus::WmfRecordTypeExtTextOut ,
"WmfSetDIBToDev" , Gdiplus::WmfRecordTypeSetDIBToDev ,
"WmfSelectPalette" , Gdiplus::WmfRecordTypeSelectPalette ,
"WmfRealizePalette" , Gdiplus::WmfRecordTypeRealizePalette ,
"WmfAnimatePalette" , Gdiplus::WmfRecordTypeAnimatePalette ,
"WmfSetPalEntries" , Gdiplus::WmfRecordTypeSetPalEntries ,
"WmfPolyPolygon" , Gdiplus::WmfRecordTypePolyPolygon ,
"WmfResizePalette" , Gdiplus::WmfRecordTypeResizePalette ,
"WmfDIBBitBlt" , Gdiplus::WmfRecordTypeDIBBitBlt ,
"WmfDIBStretchBlt" , Gdiplus::WmfRecordTypeDIBStretchBlt ,
"WmfDIBCreatePatternBrush" , Gdiplus::WmfRecordTypeDIBCreatePatternBrush ,
"WmfStretchDIB" , Gdiplus::WmfRecordTypeStretchDIB ,
"WmfExtFloodFill" , Gdiplus::WmfRecordTypeExtFloodFill ,
"WmfSetLayout" , Gdiplus::WmfRecordTypeSetLayout ,
"WmfResetDC" , Gdiplus::WmfRecordTypeResetDC ,
"WmfStartDoc" , Gdiplus::WmfRecordTypeStartDoc ,
"WmfStartPage" , Gdiplus::WmfRecordTypeStartPage ,
"WmfEndPage" , Gdiplus::WmfRecordTypeEndPage ,
"WmfAbortDoc" , Gdiplus::WmfRecordTypeAbortDoc ,
"WmfEndDoc" , Gdiplus::WmfRecordTypeEndDoc ,
"WmfDeleteObject" , Gdiplus::WmfRecordTypeDeleteObject ,
"WmfCreatePalette" , Gdiplus::WmfRecordTypeCreatePalette ,
"WmfCreateBrush" , Gdiplus::WmfRecordTypeCreateBrush ,
"WmfCreatePatternBrush" , Gdiplus::WmfRecordTypeCreatePatternBrush ,
"WmfCreatePenIndirect" , Gdiplus::WmfRecordTypeCreatePenIndirect ,
"WmfCreateFontIndirect" , Gdiplus::WmfRecordTypeCreateFontIndirect ,
"WmfCreateBrushIndirect" , Gdiplus::WmfRecordTypeCreateBrushIndirect ,
"WmfCreateBitmapIndirect" , Gdiplus::WmfRecordTypeCreateBitmapIndirect ,
"WmfCreateBitmap" , Gdiplus::WmfRecordTypeCreateBitmap ,
"WmfCreateRegion" , Gdiplus::WmfRecordTypeCreateRegion ,
"EmfHeader" , Gdiplus::EmfRecordTypeHeader ,
"EmfPolyBezier" , Gdiplus::EmfRecordTypePolyBezier ,
"EmfPolygon" , Gdiplus::EmfRecordTypePolygon ,
"EmfPolyline" , Gdiplus::EmfRecordTypePolyline ,
"EmfPolyBezierTo" , Gdiplus::EmfRecordTypePolyBezierTo ,
"EmfPolyLineTo" , Gdiplus::EmfRecordTypePolyLineTo ,
"EmfPolyPolyline" , Gdiplus::EmfRecordTypePolyPolyline ,
"EmfPolyPolygon" , Gdiplus::EmfRecordTypePolyPolygon ,
"EmfSetWindowExtEx" , Gdiplus::EmfRecordTypeSetWindowExtEx ,
"EmfSetWindowOrgEx" , Gdiplus::EmfRecordTypeSetWindowOrgEx ,
"EmfSetViewportExtEx" , Gdiplus::EmfRecordTypeSetViewportExtEx ,
"EmfSetViewportOrgEx" , Gdiplus::EmfRecordTypeSetViewportOrgEx ,
"EmfSetBrushOrgEx" , Gdiplus::EmfRecordTypeSetBrushOrgEx ,
"EmfEOF" , Gdiplus::EmfRecordTypeEOF ,
"EmfSetPixelV" , Gdiplus::EmfRecordTypeSetPixelV ,
"EmfSetMapperFlags" , Gdiplus::EmfRecordTypeSetMapperFlags ,
"EmfSetMapMode" , Gdiplus::EmfRecordTypeSetMapMode ,
"EmfSetBkMode" , Gdiplus::EmfRecordTypeSetBkMode ,
"EmfSetPolyFillMode" , Gdiplus::EmfRecordTypeSetPolyFillMode ,
"EmfSetROP2" , Gdiplus::EmfRecordTypeSetROP2 ,
"EmfSetStretchBltMode" , Gdiplus::EmfRecordTypeSetStretchBltMode ,
"EmfSetTextAlign" , Gdiplus::EmfRecordTypeSetTextAlign ,
"EmfSetColorAdjustment" , Gdiplus::EmfRecordTypeSetColorAdjustment ,
"EmfSetTextColor" , Gdiplus::EmfRecordTypeSetTextColor ,
"EmfSetBkColor" , Gdiplus::EmfRecordTypeSetBkColor ,
"EmfOffsetClipRgn" , Gdiplus::EmfRecordTypeOffsetClipRgn ,
"EmfMoveToEx" , Gdiplus::EmfRecordTypeMoveToEx ,
"EmfSetMetaRgn" , Gdiplus::EmfRecordTypeSetMetaRgn ,
"EmfExcludeClipRect" , Gdiplus::EmfRecordTypeExcludeClipRect ,
"EmfIntersectClipRect" , Gdiplus::EmfRecordTypeIntersectClipRect ,
"EmfScaleViewportExtEx" , Gdiplus::EmfRecordTypeScaleViewportExtEx ,
"EmfScaleWindowExtEx" , Gdiplus::EmfRecordTypeScaleWindowExtEx ,
"EmfSaveDC" , Gdiplus::EmfRecordTypeSaveDC ,
"EmfRestoreDC" , Gdiplus::EmfRecordTypeRestoreDC ,
"EmfSetWorldTransform" , Gdiplus::EmfRecordTypeSetWorldTransform ,
"EmfModifyWorldTransform" , Gdiplus::EmfRecordTypeModifyWorldTransform ,
"EmfSelectObject" , Gdiplus::EmfRecordTypeSelectObject ,
"EmfCreatePen" , Gdiplus::EmfRecordTypeCreatePen ,
"EmfCreateBrushIndirect" , Gdiplus::EmfRecordTypeCreateBrushIndirect ,
"EmfDeleteObject" , Gdiplus::EmfRecordTypeDeleteObject ,
"EmfAngleArc" , Gdiplus::EmfRecordTypeAngleArc ,
"EmfEllipse" , Gdiplus::EmfRecordTypeEllipse ,
"EmfRectangle" , Gdiplus::EmfRecordTypeRectangle ,
"EmfRoundRect" , Gdiplus::EmfRecordTypeRoundRect ,
"EmfArc" , Gdiplus::EmfRecordTypeArc ,
"EmfChord" , Gdiplus::EmfRecordTypeChord ,
"EmfPie" , Gdiplus::EmfRecordTypePie ,
"EmfSelectPalette" , Gdiplus::EmfRecordTypeSelectPalette ,
"EmfCreatePalette" , Gdiplus::EmfRecordTypeCreatePalette ,
"EmfSetPaletteEntries" , Gdiplus::EmfRecordTypeSetPaletteEntries ,
"EmfResizePalette" , Gdiplus::EmfRecordTypeResizePalette ,
"EmfRealizePalette" , Gdiplus::EmfRecordTypeRealizePalette ,
"EmfExtFloodFill" , Gdiplus::EmfRecordTypeExtFloodFill ,
"EmfLineTo" , Gdiplus::EmfRecordTypeLineTo ,
"EmfArcTo" , Gdiplus::EmfRecordTypeArcTo ,
"EmfPolyDraw" , Gdiplus::EmfRecordTypePolyDraw ,
"EmfSetArcDirection" , Gdiplus::EmfRecordTypeSetArcDirection ,
"EmfSetMiterLimit" , Gdiplus::EmfRecordTypeSetMiterLimit ,
"EmfBeginPath" , Gdiplus::EmfRecordTypeBeginPath ,
"EmfEndPath" , Gdiplus::EmfRecordTypeEndPath ,
"EmfCloseFigure" , Gdiplus::EmfRecordTypeCloseFigure ,
"EmfFillPath" , Gdiplus::EmfRecordTypeFillPath ,
"EmfStrokeAndFillPath" , Gdiplus::EmfRecordTypeStrokeAndFillPath ,
"EmfStrokePath" , Gdiplus::EmfRecordTypeStrokePath ,
"EmfFlattenPath" , Gdiplus::EmfRecordTypeFlattenPath ,
"EmfWidenPath" , Gdiplus::EmfRecordTypeWidenPath ,
"EmfSelectClipPath" , Gdiplus::EmfRecordTypeSelectClipPath ,
"EmfAbortPath" , Gdiplus::EmfRecordTypeAbortPath ,
"EmfReserved_069" , Gdiplus::EmfRecordTypeReserved_069 ,
"EmfGdiComment" , Gdiplus::EmfRecordTypeGdiComment ,
"EmfFillRgn" , Gdiplus::EmfRecordTypeFillRgn ,
"EmfFrameRgn" , Gdiplus::EmfRecordTypeFrameRgn ,
"EmfInvertRgn" , Gdiplus::EmfRecordTypeInvertRgn ,
"EmfPaintRgn" , Gdiplus::EmfRecordTypePaintRgn ,
"EmfExtSelectClipRgn" , Gdiplus::EmfRecordTypeExtSelectClipRgn ,
"EmfBitBlt" , Gdiplus::EmfRecordTypeBitBlt ,
"EmfStretchBlt" , Gdiplus::EmfRecordTypeStretchBlt ,
"EmfMaskBlt" , Gdiplus::EmfRecordTypeMaskBlt ,
"EmfPlgBlt" , Gdiplus::EmfRecordTypePlgBlt ,
"EmfSetDIBitsToDevice" , Gdiplus::EmfRecordTypeSetDIBitsToDevice ,
"EmfStretchDIBits" , Gdiplus::EmfRecordTypeStretchDIBits ,
"EmfExtCreateFontIndirect" , Gdiplus::EmfRecordTypeExtCreateFontIndirect ,
"EmfExtTextOutA" , Gdiplus::EmfRecordTypeExtTextOutA ,
"EmfExtTextOutW" , Gdiplus::EmfRecordTypeExtTextOutW ,
"EmfPolyBezier16" , Gdiplus::EmfRecordTypePolyBezier16 ,
"EmfPolygon16" , Gdiplus::EmfRecordTypePolygon16 ,
"EmfPolyline16" , Gdiplus::EmfRecordTypePolyline16 ,
"EmfPolyBezierTo16" , Gdiplus::EmfRecordTypePolyBezierTo16 ,
"EmfPolylineTo16" , Gdiplus::EmfRecordTypePolylineTo16 ,
"EmfPolyPolyline16" , Gdiplus::EmfRecordTypePolyPolyline16 ,
"EmfPolyPolygon16" , Gdiplus::EmfRecordTypePolyPolygon16 ,
"EmfPolyDraw16" , Gdiplus::EmfRecordTypePolyDraw16 ,
"EmfCreateMonoBrush" , Gdiplus::EmfRecordTypeCreateMonoBrush ,
"EmfCreateDIBPatternBrushPt" , Gdiplus::EmfRecordTypeCreateDIBPatternBrushPt ,
"EmfExtCreatePen" , Gdiplus::EmfRecordTypeExtCreatePen ,
"EmfPolyTextOutA" , Gdiplus::EmfRecordTypePolyTextOutA ,
"EmfPolyTextOutW" , Gdiplus::EmfRecordTypePolyTextOutW ,
"EmfSetICMMode" , Gdiplus::EmfRecordTypeSetICMMode ,
"EmfCreateColorSpace" , Gdiplus::EmfRecordTypeCreateColorSpace ,
"EmfSetColorSpace" , Gdiplus::EmfRecordTypeSetColorSpace ,
"EmfDeleteColorSpace" , Gdiplus::EmfRecordTypeDeleteColorSpace ,
"EmfGLSRecord" , Gdiplus::EmfRecordTypeGLSRecord ,
"EmfGLSBoundedRecord" , Gdiplus::EmfRecordTypeGLSBoundedRecord ,
"EmfPixelFormat" , Gdiplus::EmfRecordTypePixelFormat ,
"EmfDrawEscape" , Gdiplus::EmfRecordTypeDrawEscape ,
"EmfExtEscape" , Gdiplus::EmfRecordTypeExtEscape ,
"EmfStartDoc" , Gdiplus::EmfRecordTypeStartDoc ,
"EmfSmallTextOut" , Gdiplus::EmfRecordTypeSmallTextOut ,
"EmfForceUFIMapping" , Gdiplus::EmfRecordTypeForceUFIMapping ,
"EmfNamedEscape" , Gdiplus::EmfRecordTypeNamedEscape ,
"EmfColorCorrectPalette" , Gdiplus::EmfRecordTypeColorCorrectPalette ,
"EmfSetICMProfileA" , Gdiplus::EmfRecordTypeSetICMProfileA ,
"EmfSetICMProfileW" , Gdiplus::EmfRecordTypeSetICMProfileW ,
"EmfAlphaBlend" , Gdiplus::EmfRecordTypeAlphaBlend ,
"EmfSetLayout" , Gdiplus::EmfRecordTypeSetLayout ,
"EmfTransparentBlt" , Gdiplus::EmfRecordTypeTransparentBlt ,
"EmfReserved_117" , Gdiplus::EmfRecordTypeReserved_117 ,
"EmfGradientFill" , Gdiplus::EmfRecordTypeGradientFill ,
"EmfSetLinkedUFIs" , Gdiplus::EmfRecordTypeSetLinkedUFIs ,
"EmfSetTextJustification" , Gdiplus::EmfRecordTypeSetTextJustification ,
"EmfColorMatchToTargetW" , Gdiplus::EmfRecordTypeColorMatchToTargetW ,
"EmfCreateColorSpaceW" , Gdiplus::EmfRecordTypeCreateColorSpaceW ,
"EmfPlusHeader" , Gdiplus::EmfPlusRecordTypeHeader ,
"EmfPlusEndOfFile" , Gdiplus::EmfPlusRecordTypeEndOfFile ,
"EmfPlusComment" , Gdiplus::EmfPlusRecordTypeComment ,
"EmfPlusGetDC" , Gdiplus::EmfPlusRecordTypeGetDC ,
"EmfPlusMultiFormatStart" , Gdiplus::EmfPlusRecordTypeMultiFormatStart ,
"EmfPlusMultiFormatSection" , Gdiplus::EmfPlusRecordTypeMultiFormatSection ,
"EmfPlusMultiFormatEnd" , Gdiplus::EmfPlusRecordTypeMultiFormatEnd ,
"EmfPlusObject" , Gdiplus::EmfPlusRecordTypeObject ,
"EmfPlusClear" , Gdiplus::EmfPlusRecordTypeClear ,
"EmfPlusFillRects" , Gdiplus::EmfPlusRecordTypeFillRects ,
"EmfPlusDrawRects" , Gdiplus::EmfPlusRecordTypeDrawRects ,
"EmfPlusFillPolygon" , Gdiplus::EmfPlusRecordTypeFillPolygon ,
"EmfPlusDrawLines" , Gdiplus::EmfPlusRecordTypeDrawLines ,
"EmfPlusFillEllipse" , Gdiplus::EmfPlusRecordTypeFillEllipse ,
"EmfPlusDrawEllipse" , Gdiplus::EmfPlusRecordTypeDrawEllipse ,
"EmfPlusFillPie" , Gdiplus::EmfPlusRecordTypeFillPie ,
"EmfPlusDrawPie" , Gdiplus::EmfPlusRecordTypeDrawPie ,
"EmfPlusDrawArc" , Gdiplus::EmfPlusRecordTypeDrawArc ,
"EmfPlusFillRegion" , Gdiplus::EmfPlusRecordTypeFillRegion ,
"EmfPlusFillPath" , Gdiplus::EmfPlusRecordTypeFillPath ,
"EmfPlusDrawPath" , Gdiplus::EmfPlusRecordTypeDrawPath ,
"EmfPlusFillClosedCurve" , Gdiplus::EmfPlusRecordTypeFillClosedCurve ,
"EmfPlusDrawClosedCurve" , Gdiplus::EmfPlusRecordTypeDrawClosedCurve ,
"EmfPlusDrawCurve" , Gdiplus::EmfPlusRecordTypeDrawCurve ,
"EmfPlusDrawBeziers" , Gdiplus::EmfPlusRecordTypeDrawBeziers ,
"EmfPlusDrawImage" , Gdiplus::EmfPlusRecordTypeDrawImage ,
"EmfPlusDrawImagePoints" , Gdiplus::EmfPlusRecordTypeDrawImagePoints ,
"EmfPlusDrawString" , Gdiplus::EmfPlusRecordTypeDrawString ,
"EmfPlusSetRenderingOrigin" , Gdiplus::EmfPlusRecordTypeSetRenderingOrigin ,
"EmfPlusSetAntiAliasMode" , Gdiplus::EmfPlusRecordTypeSetAntiAliasMode ,
"EmfPlusSetTextRenderingHint" , Gdiplus::EmfPlusRecordTypeSetTextRenderingHint ,
"EmfPlusSetTextContrast" , Gdiplus::EmfPlusRecordTypeSetTextContrast ,
"EmfPlusSetInterpolationMode" , Gdiplus::EmfPlusRecordTypeSetInterpolationMode ,
"EmfPlusSetPixelOffsetMode" , Gdiplus::EmfPlusRecordTypeSetPixelOffsetMode ,
"EmfPlusSetCompositingMode" , Gdiplus::EmfPlusRecordTypeSetCompositingMode ,
"EmfPlusSetCompositingQuality" , Gdiplus::EmfPlusRecordTypeSetCompositingQuality ,
"EmfPlusSave" , Gdiplus::EmfPlusRecordTypeSave ,
"EmfPlusRestore" , Gdiplus::EmfPlusRecordTypeRestore ,
"EmfPlusBeginContainer" , Gdiplus::EmfPlusRecordTypeBeginContainer ,
"EmfPlusBeginContainerNoParams" , Gdiplus::EmfPlusRecordTypeBeginContainerNoParams ,
"EmfPlusEndContainer" , Gdiplus::EmfPlusRecordTypeEndContainer ,
"EmfPlusSetWorldTransform" , Gdiplus::EmfPlusRecordTypeSetWorldTransform ,
"EmfPlusResetWorldTransform" , Gdiplus::EmfPlusRecordTypeResetWorldTransform ,
"EmfPlusMultiplyWorldTransform" , Gdiplus::EmfPlusRecordTypeMultiplyWorldTransform ,
"EmfPlusTranslateWorldTransform" , Gdiplus::EmfPlusRecordTypeTranslateWorldTransform,
"EmfPlusScaleWorldTransform" , Gdiplus::EmfPlusRecordTypeScaleWorldTransform ,
"EmfPlusRotateWorldTransform" , Gdiplus::EmfPlusRecordTypeRotateWorldTransform ,
"EmfPlusSetPageTransform" , Gdiplus::EmfPlusRecordTypeSetPageTransform ,
"EmfPlusResetClip" , Gdiplus::EmfPlusRecordTypeResetClip ,
"EmfPlusSetClipRect" , Gdiplus::EmfPlusRecordTypeSetClipRect ,
"EmfPlusSetClipPath" , Gdiplus::EmfPlusRecordTypeSetClipPath ,
"EmfPlusSetClipRegion" , Gdiplus::EmfPlusRecordTypeSetClipRegion ,
"EmfPlusOffsetClip" , Gdiplus::EmfPlusRecordTypeOffsetClip ,
"EmfPlusDrawDriverString" , Gdiplus::EmfPlusRecordTypeDrawDriverString ,
};
/*
METAFUNCTIONS MetaFunctions[] = {
"SETBKCOLOR", 0x0201,
"SETBKMODE", 0x0102,
"SETMAPMODE", 0x0103,
"SETROP2", 0x0104,
"SETRELABS", 0x0105,
"SETPOLYFILLMODE", 0x0106,
"SETSTRETCHBLTMODE", 0x0107,
"SETTEXTCHAREXTRA", 0x0108,
"SETTEXTCOLOR", 0x0209,
"SETTEXTJUSTIFICATION", 0x020A,
"SETWINDOWORG", 0x020B,
"SETWINDOWEXT", 0x020C,
"SETVIEWPORTORG", 0x020D,
"SETVIEWPORTEXT", 0x020E,
"OFFSETWINDOWORG", 0x020F,
"SCALEWINDOWEXT", 0x0400,
"OFFSETVIEWPORTORG", 0x0211,
"SCALEVIEWPORTEXT", 0x0412,
"LINETO", 0x0213,
"MOVETO", 0x0214,
"EXCLUDECLIPRECT", 0x0415,
"INTERSECTCLIPRECT", 0x0416,
"ARC", 0x0817,
"ELLIPSE", 0x0418,
"FLOODFILL", 0x0419,
"PIE", 0x081A,
"RECTANGLE", 0x041B,
"ROUNDRECT", 0x061C,
"PATBLT", 0x061D,
"SAVEDC", 0x001E,
"SETPIXEL", 0x041F,
"OFFSETCLIPRGN", 0x0220,
"TEXTOUT", 0x0521,
"BITBLT", 0x0922,
"STRETCHBLT", 0x0B23,
"POLYGON", 0x0324,
"POLYLINE", 0x0325,
"ESCAPE", 0x0626,
"RESTOREDC", 0x0127,
"FILLREGION", 0x0228,
"FRAMEREGION", 0x0429,
"INVERTREGION", 0x012A,
"PAINTREGION", 0x012B,
"SELECTCLIPREGION", 0x012C,
"SELECTOBJECT", 0x012D,
"SETTEXTALIGN", 0x012E,
"DRAWTEXT", 0x062F,
"CHORD", 0x0830,
"SETMAPPERFLAGS", 0x0231,
"EXTTEXTOUT", 0x0a32,
"SETDIBTODEV", 0x0d33,
"SELECTPALETTE", 0x0234,
"REALIZEPALETTE", 0x0035,
"ANIMATEPALETTE", 0x0436,
"SETPALENTRIES", 0x0037,
"POLYPOLYGON", 0x0538,
"RESIZEPALETTE", 0x0139,
"DIBBITBLT", 0x0940,
"DIBSTRETCHBLT", 0x0b41,
"DIBCREATEPATTERNBRUSH",0x0142,
"STRETCHDIB", 0x0f43,
"DELETEOBJECT", 0x01f0,
"CREATEPALETTE", 0x00f7,
"CREATEBRUSH", 0x00F8,
"CREATEPATTERNBRUSH", 0x01F9,
"CREATEPENINDIRECT", 0x02FA,
"CREATEFONTINDIRECT", 0x02FB,
"CREATEBRUSHINDIRECT", 0x02FC,
"CREATEBITMAPINDIRECT", 0x02FD,
"CREATEBITMAP", 0x06FE,
"CREATEREGION", 0x06FF,
};
*/
/***********************************************************************
FUNCTION : MetaEnumProc
PARAMETERS : HDC hDC
LPHANDLETABLE lpHTable
LPMETARECORD lpMFR
int nObj
LPARAM lpClientData
PURPOSE : callback for EnumMetaFile.
CALLS : EnumMFIndirect()
MESSAGES : none
RETURNS : int
COMMENTS :
HISTORY : 1/16/91 - created - drc
5/6/93 - modified for Win32 - denniscr
************************************************************************/
int CALLBACK MetaEnumProc(
HDC hDC,
LPHANDLETABLE lpHTable,
LPMETARECORD lpMFR,
int nObj,
LPARAM lpClientData)
{
return EnumMFIndirect(hDC, lpHTable, lpMFR, NULL, nObj, lpClientData);
}
/***********************************************************************
FUNCTION : LoadParameterLB
PARAMETERS : HWND hDlg
DWORD dwParams
int nRadix - HEX to display contents in base 16
DEC to display contents in base 10
PURPOSE : display the parameters of the metafile record in
the parameter listbox
CALLS : WINDOWS
GlobalLock
GlobalUnlock
SendDlgItemMessage
wsprintf
lstrlen
MESSAGES : WM_SETREDRAW
WM_RESETCONTENT
LB_ADDSTRING
RETURNS : BOOL
COMMENTS :
HISTORY : 1/16/91 - created - drc
************************************************************************/
BOOL LoadParameterLB(
HWND hDlg,
DWORD dwParams,
int nRadix)
{
DWORD i;
BYTE nHiByte, nLoByte;
BYTE nHiByteHi, nLoByteHi;
WORD wHiWord, wLoWord;
char szBuffer[40];
char szDump[100];
int iValue = 0;
DWORD dwValue = 0;
switch (nRadix) /* if nRadix is not a valid value, return FALSE */
{
case IDB_HEX:
case IDB_DEC:
case IDB_CHAR:
case IDB_WORD:
break;
default :
return FALSE;
}
//
//init the strings
//
*szBuffer = '\0';
*szDump = '\0';
//
//turn off redrawing of the listbox
//
SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, FALSE, 0L);
//
//reset the contents of the listbox
//
SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_RESETCONTENT, 0, 0L);
// don't load an entire bitmap or other image into the dialog in hex
if (dwParams > 1024)
{
dwParams = 1024;
}
if (bEnhMeta)
{
//
//lock the memory where the parameters can be found
//
if (NULL == (lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem)))
return (FALSE);
//
//loop through the metafile record parameters
//
for (i = 0; i < dwParams; i++)
{
/* get the high and low byte of the parameter word */
wHiWord = HIWORD(lpEMFParams[i]);
wLoWord = LOWORD(lpEMFParams[i]);
nLoByteHi = LOBYTE(wHiWord);
nHiByteHi = HIBYTE(wHiWord);
nLoByte = LOBYTE(wLoWord);
nHiByte = HIBYTE(wLoWord);
switch (nRadix)
{
case IDB_HEX: /* if we are to display as hexadecimal */
/* format the bytes for the hex part of dump */
wsprintf((LPSTR)szBuffer, (LPSTR)"%08x ", lpEMFParams[i]);
break;
case IDB_DEC:
/* format the bytes for the decimal part of dump */
dwValue = lpEMFParams[i];
wsprintf((LPSTR)szBuffer, (LPSTR)"%lu ", dwValue );
break;
case IDB_CHAR:
wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c%c%c",
(nLoByte > 0x20) ? nLoByte : 0x2E,
(nHiByte > 0x20) ? nHiByte : 0x2E,
(nLoByteHi > 0x20) ? nLoByteHi : 0x2E,
(nHiByteHi > 0x20) ? nHiByteHi : 0x2E);
break;
case IDB_WORD: /* if we are to display as hexadecimal */
/* format the bytes for the hex part of dump */
wsprintf((LPSTR)szBuffer, (LPSTR)"%04x %04x ", wLoWord, wHiWord );
break;
default :
return FALSE;
}
/* concatenate it onto whatever we have already formatted */
lstrcat((LPSTR)szDump, (LPSTR)szBuffer);
/* use every 8 words for hex/dec dump */
if (!((i + 1) % 4))
{
/*add the string to the listbox */
SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
/* re-init the hex/dec strings in preparation for next 8 words */
*szDump = '\0';
}
}
}
else
{
/* lock the memory where the parameters can be found */
if (NULL == (lpMFParams = (LPPARAMETERS)GlobalLock(hMem)))
return (FALSE);
/* loop through the metafile record parameters */
for (i = 0; i < dwParams; i++)
{
/* get the high and low byte of the parameter word */
nHiByte = HIBYTE(lpMFParams[i]);
nLoByte = LOBYTE(lpMFParams[i]);
switch (nRadix)
{
case IDB_HEX: /* if we are to display as hexadecimal */
/* format the bytes for the hex part of dump */
wsprintf((LPSTR)szBuffer, (LPSTR)"%02x %02x ", nLoByte, nHiByte );
break;
case IDB_DEC:
/* format the bytes for the decimal part of dump */
iValue = lpMFParams[i];
wsprintf((LPSTR)szBuffer, (LPSTR)"%d ", iValue );
break;
case IDB_CHAR:
wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c",
(nLoByte > 0x20) ? nLoByte : 0x2E,
(nHiByte > 0x20) ? nHiByte : 0x2E);
break;
case IDB_WORD: /* if we are to display as hexadecimal */
/* format the bytes for the hex part of dump */
wsprintf((LPSTR)szBuffer, (LPSTR)"%02x%02x ", nHiByte, nLoByte );
break;
default :
return FALSE;
}
/* concatenate it onto whatever we have already formatted */
lstrcat((LPSTR)szDump, (LPSTR)szBuffer);
/* use every 8 words for hex/dec dump */
if (!((i + 1) % 8))
{
/*add the string to the listbox */
SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
/* re-init the hex/dec strings in preparation for next 8 words */
*szDump = '\0';
}
}
} //else
//
//dump any leftover hex/dec dump
//
if (lstrlen((LPSTR)szDump))
SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
//
//enable redraw to the listbox
//
SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, TRUE, 0L);
//
//redraw it
//
InvalidateRect(GetDlgItem(hDlg,IDL_PARAMETERS), NULL, TRUE);
//
//unlock the memory used for the parameters
//
GlobalUnlock(hMem);
return (TRUE);
}
extern "C"
void GetMetaFileAndEnum(
HWND hwnd,
HDC hDC,
int iAction);
/***********************************************************************
FUNCTION : PlayMetaFileToDest
PARAMETERS : HWND hWnd
int nDest - DC to play metafile to
DESTDISPLAY - play to the display
DESTMETA - play into another metafile
PURPOSE : begin the enumeration of the metafile to the user selected
destination. Perform the housekeeping needs appropriate
to that destination.
CALLS : WINDOWS
GetClientRect
InvalidateRect
GetDC
SetMapMode
OpenFileDialog
MessageBox
CreateMetaFile
DeleteMetaFile
CloseMetaFile
APP
WaitCursor
SetClipMetaExts
SetPlaceableExts
GetMetaFileAndEnum
MESSAGES : none
RETURNS : int
COMMENTS :
HISTORY : 1/16/91 - created - drc
************************************************************************/
BOOL PlayMetaFileToDest(
HWND hWnd,
int nDest)
{
HDC hDC;
RECT rect;
int iSaveRet;
//
//if the file opened contained a valid metafile
//
if (bValidFile)
{
//
//init the record count
//
iRecNum = 0;
//
//if we are stepping the metafile then clear the client area
//
if (!bPlayItAll)
{
GetClientRect(hWnd, (LPRECT)&rect);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
}
switch (nDest)
{
//
//playing metafile to the display
//
case DESTDISPLAY:
WaitCursor(TRUE);
hDC = GetDC(hWnd);
if (!bUseGdiPlusToPlay)
{
//
//metafile read in from a clipboard file
//
if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta)
SetClipMetaExts(hDC, lpMFP, lpOldMFP, WMFDISPLAY);
//
//Windows placeable metafile
//
if (bPlaceableMeta && !bEnhMeta)
SetPlaceableExts(hDC, placeableWMFHeader, WMFDISPLAY);
//
//Windows metafile
//
if (!bMetaInRam && !bEnhMeta)
{
SetNonPlaceableExts(hDC, WMFDISPLAY);
}
}
//
//begin the enumeration of the metafile
//
DWORD start, end;
DWORD renderTime;
char tmpBuf[512];
start = GetTickCount();
GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP);
end = GetTickCount();
renderTime = end - start;
wsprintf(tmpBuf, "Time: %d", renderTime);
SetWindowText(hWnd, tmpBuf);
ReleaseDC(hWnd, hDC);
WaitCursor(FALSE);
break;
case DESTMETA:
//
//get a name of a file to play the metafile into
//
iSaveRet = SaveFileDialog((LPSTR)SaveName, (LPSTR)gszSaveEMFFilter);
//
//if the file selected is this metafile then warn user
//
if (!lstrcmp((LPSTR)OpenName, (LPSTR)SaveName))
MessageBox(hWnd, (LPSTR)"Cannot overwrite the opened metafile!",
(LPSTR)"Play to Metafile", MB_OK | MB_ICONEXCLAMATION);
else
//
//the user didn't hit the cancel button
//
if (iSaveRet)
{
WaitCursor(TRUE);
//
//create a disk based metafile
//
hDC = (bEnhMeta) ? CreateEnhMetaFile(NULL, (LPSTR)SaveName, NULL, NULL)
: CreateMetaFile((LPSTR)SaveName);
//
//begin the enumeration of the metafile
//
GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP);
//
//done playing so close the metafile and delete the handle
//
if (bEnhMeta)
DeleteEnhMetaFile(CloseEnhMetaFile(hDC));
else
DeleteMetaFile(CloseMetaFile(hDC));
WaitCursor(FALSE);
}
break;
case DESTDIB:
{
/* extents for the display DC */
GetClientRect(hWndMain, &rect);
INT cx = rect.right - rect.left;
INT cy = rect.bottom - rect.top;
/* SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm));
SetViewportOrgEx(hDC, 0, 0, &lpPT);
*/
WaitCursor(TRUE);
hDC = GetDC(hWnd);
BITMAPINFOHEADER bmi;
memset(&bmi, 0, sizeof(BITMAPINFOHEADER));
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biBitCount = 24;
bmi.biWidth = cx;
bmi.biHeight = -cy;
bmi.biPlanes = 1;
VOID* bits = NULL;
HBITMAP hBmp = CreateDIBSection(hDC, (BITMAPINFO*) &bmi, 0, &bits, NULL, 0);
HDC hDCBmp = CreateCompatibleDC(hDC);
::SelectObject(hDCBmp, hBmp);
FillRect(hDCBmp, &rect, (HBRUSH) ::GetStockObject(GRAY_BRUSH));
if (!bUseGdiPlusToPlay)
{
//
//metafile read in from a clipboard file
//
if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta)
SetClipMetaExts(hDCBmp, lpMFP, lpOldMFP, WMFDISPLAY);
//
//Windows placeable metafile
//
if (bPlaceableMeta && !bEnhMeta)
SetPlaceableExts(hDCBmp, placeableWMFHeader, WMFDISPLAY);
//
//Windows metafile
//
if (!bMetaInRam && !bEnhMeta)
{
SetNonPlaceableExts(hDCBmp, WMFDISPLAY);
}
}
//
//begin the enumeration of the metafile
//
start = GetTickCount();
GetMetaFileAndEnum(hWnd, hDCBmp, ENUMMFSTEP);
end = GetTickCount();
renderTime = end - start;
wsprintf(tmpBuf, "Time: %d", renderTime);
SetWindowText(hWnd, tmpBuf);
StretchDIBits(hDC, 0, 0, cx, cy, 0, 0, cx, cy, bits, (BITMAPINFO*)&bmi, 0, SRCCOPY);
DeleteDC(hDCBmp);
DeleteObject((HGDIOBJ) hBmp);
ReleaseDC(hWnd, hDC);
WaitCursor(FALSE);
break;
}
case DESTPRN:
{
HDC hPr = (HDC)NULL;
PRINTDLG pd;
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_RETURNDC;
pd.hwndOwner = hWndMain;
//
//get a DC for the printer
//
if (PrintDlg(&pd) != 0)
hPr= pd.hDC;
else
break;
//
//if a DC could not be created then report the error and return
//
if (!hPr)
{
WaitCursor(FALSE);
wsprintf((LPSTR)str, "Cannot print %s", (LPSTR)fnameext);
MessageBox(hWndMain, (LPSTR)str, NULL, MB_OK | MB_ICONHAND);
break;
}
//
//define the abort function
//
SetAbortProc(hPr, AbortProc);
//
//Initialize the members of a DOCINFO structure.
//
DOCINFO di;
memset(&di, 0, sizeof(di));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = (bEnhMeta) ? "Print EMF" : "Print WMF";
di.lpszOutput = (LPTSTR) NULL;
//
//Begin a print job by calling the StartDoc
//function.
//
if (SP_ERROR == (StartDoc(hPr, &di)))
{
//if (Escape(hPr, STARTDOC, 4, "Metafile", (LPSTR) NULL) < 0) {
MessageBox(hWndMain, "Unable to start print job",
NULL, MB_OK | MB_ICONHAND);
DeleteDC(hPr);
break;
}
//
//clear the abort flag
//
bAbort = FALSE;
//
//Create the Abort dialog box (modeless)
//
hAbortDlgWnd = CreateDialog((HINSTANCE)hInst, "AbortDlg", hWndMain, AbortDlg);
//
//if the dialog was not created report the error
//
if (!hAbortDlgWnd)
{
WaitCursor(FALSE);
MessageBox(hWndMain, "NULL Abort window handle",
NULL, MB_OK | MB_ICONHAND);
break;
}
//
//show Abort dialog
//
ShowWindow (hAbortDlgWnd, SW_NORMAL);
//
//disable the main window to avoid reentrancy problems
//
EnableWindow(hWndMain, FALSE);
WaitCursor(FALSE);
//
//if we are still committed to printing
//
if (!bUseGdiPlusToPlay)
{
//
//if this is a placeable metafile then set its origins and extents
//
if (bPlaceableMeta)
SetPlaceableExts(hPr, placeableWMFHeader, WMFPRINTER);
//
//if this is a metafile contained within a clipboard file then set
//its origins and extents accordingly
//
if ( (bMetaInRam) && (!bPlaceableMeta) )
SetClipMetaExts(hPr, lpMFP, lpOldMFP, WMFPRINTER);
}
//
//if this is a "traditional" windows metafile
//
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = GetDeviceCaps(hPr, HORZRES);
rc.bottom = GetDeviceCaps(hPr, VERTRES);
POINT lpPT;
SIZE lpSize;
if (TRUE || !bMetaInRam)
{
SetMapMode(hPr, MM_TEXT);
SetViewportOrgEx(hPr, 0, 0, &lpPT);
//
//set the extents to the driver supplied values for horizontal
//and vertical resolution
//
SetViewportExtEx(hPr, rc.right, rc.bottom, &lpSize );
}
//
//play the metafile directly to the printer.
//No enumeration involved here
//
GetMetaFileAndEnum(hWnd, hPr, ENUMMFSTEP);
//
//eject page and end the print job
//
Escape(hPr, NEWFRAME, 0, 0L, 0L);
EndDoc(hPr);
EnableWindow(hWndMain, TRUE);
//
//destroy the Abort dialog box
//
DestroyWindow(hAbortDlgWnd);
DeleteDC(hPr);
}
default:
break;
}
//
//if playing list records then free the memory used for the list of
//selected records
//
if (bPlayList)
{
GlobalUnlock(hSelMem);
GlobalFree(hSelMem);
bPlayList = FALSE;
}
//
//success
//
return (TRUE);
}
else
//
//not a valid metafile
//
return (FALSE);
}
/***********************************************************************
FUNCTION : RenderClipMeta
PARAMETERS : CLIPFILEFORMAT *ClipHeader
int fh
PURPOSE : read metafile bits, metafilepict and metafile header
of the metafile contained within a clipboard file
CALLS : WINDOWS
GlobalAlloc
GlobalLock
GlobalUnlock
GlobalFree
MessageBox
_llseek
_lread
_lclose
SetMetaFileBits
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 1/16/91 - created - drc
5/23/93 - ported to NT. it must handle 3.1 clipboard
as well as NT clipboard files - drc
************************************************************************/
BOOL RenderClipMeta(LPVOID lpvClipHeader, int fh, WORD ClipID)
{
int wBytesRead;
long lBytesRead;
long lSize;
DWORD lOffset;
DWORD dwSizeOfMetaFilePict;
BOOL bEMF = FALSE;
LPNTCLIPFILEFORMAT lpNTClp;
LPCLIPFILEFORMAT lpClp;
//
//cast the void ptr to the clipfile header appropriately
//
if (bEnhMeta)
{
lpNTClp = (LPNTCLIPFILEFORMAT)lpvClipHeader;
bEMF = TRUE;
}
else
lpClp = (LPCLIPFILEFORMAT)lpvClipHeader;
//
//obtain the appropriate size of the metafilepict. win16 vs win32
//
dwSizeOfMetaFilePict = (ClipID == CLP_ID) ?
sizeof(OLDMETAFILEPICT) :
sizeof(METAFILEPICT);
//
//free any memory already allocated for the METAFILEPICT
//
if (lpMFP != NULL || lpOldMFP != NULL)
{
GlobalFreePtr(lpMFP);
lpMFP = NULL;
}
//
//allocate enough memory to read the metafile bits into
//
if (!(lpMFBits = (char*)GlobalAllocPtr(GHND, ((bEMF) ? lpNTClp->DataLen
: lpClp->DataLen - dwSizeOfMetaFilePict))))
return(FALSE);
//
//offset to the metafile bits
//
lOffset = ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset + dwSizeOfMetaFilePict );
//
//size of metafile bits
//
lSize = (long)( ((bEMF) ? lpNTClp->DataLen : lpClp->DataLen - dwSizeOfMetaFilePict));
//
//seek to the beginning of the metafile bits
//
_llseek(fh, lOffset, 0);
//
//read the metafile bits
//
lBytesRead = _hread(fh, lpMFBits, lSize);
//
//if unable to read the metafile bits bail out
//
if( lBytesRead == -1 || lBytesRead < lSize)
{
GlobalFreePtr(lpMFBits);
MessageBox(hWndMain, "Unable to read metafile bits",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//return to beginning to read metafile header
//
_llseek(fh, lOffset, 0);
//
//read the metafile header
//
if (!bEMF)
wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
else
wBytesRead = _lread(fh, (LPSTR)&emfHeader, sizeof(ENHMETAHEADER));
//
//if unable to read the header return
//
if( wBytesRead == -1 || (WORD)wBytesRead < ((bEMF) ? sizeof(ENHMETAHEADER) : sizeof(METAHEADER)) )
{
MessageBox(hWndMain, "Unable to read metafile header",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//set the metafile bits to the memory allocated for that purpose
//
if (bEMF)
//
//win32
//
hemf = SetEnhMetaFileBits(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits);
else
//
//win16
//
hMF = SetMetaFileBitsEx(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits);
if ( NULL == ((bEMF) ? hemf : hMF))
{
MessageBox(hWndMain, "Unable to set metafile bits",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//allocate memory for the metafile pict structure
//
if (!(hMFP = GlobalAlloc(GHND, dwSizeOfMetaFilePict)))
{
MessageBox(hWndMain, "Unable allocate memory for metafile pict",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//lock the memory
//
if (ClipID == CLP_ID)
lpOldMFP = (LPOLDMETAFILEPICT)GlobalLock(hMFP);
else
lpMFP = (LPMETAFILEPICT)GlobalLock(hMFP);
if (!lpMFP && !lpOldMFP)
{
MessageBox(hWndMain, "unable to lock metafile pict memory",
NULL, MB_OK | MB_ICONHAND);
GlobalFree(hMFP);
return(FALSE);
}
//
//reposition to the start of the METAFILEPICT header.
//
_llseek(fh, ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset), 0);
//
//read the metafile pict structure
//
wBytesRead = _lread(fh, ((ClipID == CLP_ID) ? (LPVOID)lpOldMFP : (LPVOID)lpMFP),
dwSizeOfMetaFilePict);
//
//if unable to read, return
//
if( wBytesRead == -1 || wBytesRead < (long)dwSizeOfMetaFilePict) {
MessageBox(hWndMain, "Unable to read metafile pict",
NULL, MB_OK | MB_ICONHAND);
GlobalUnlock(hMFP);
GlobalFree(hMFP);
return(FALSE);
}
if (bEnhMeta)
GetEMFCoolStuff();
//DENNIS - check this out....
/* update metafile handle */
if (ClipID == CLP_ID)
lpOldMFP->hMF = (WORD)hMF;
else
lpMFP->hMF = (HMETAFILE)hemf;
return(TRUE);
}
/***********************************************************************
FUNCTION : RenderPlaceableMeta
PARAMETERS : int fh - filehandle to the placeable metafile
PURPOSE : read the metafile bits, metafile header and placeable
metafile header of a placeable metafile.
CALLS : WINDOWS
GlobalAlloc
GlobalLock
Global
DeleteMetaFile
SetMetaFileBits
_llseek
_lread
_lclose
MessageBox
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 1/16/91 - created - drc
7/1/93 - modified for win32 - denniscr
************************************************************************/
BOOL RenderPlaceableMeta(
int fh)
{
int wBytesRead;
long lBytesRead;
DWORD dwSize;
//
//if there is currently a metafile loaded, get rid of it
//
if (bMetaInRam && hMF && !bEnhMeta)
DeleteMetaFile((HMETAFILE)hMF);
//
//seek to beginning of file and read placeable header
//
_llseek(fh, 0, 0);
//
//read the placeable header
//
wBytesRead = _lread(fh, (LPSTR)&placeableWMFHeader, sizeof(PLACEABLEWMFHEADER));
//
//if there is an error, return
//
if( wBytesRead == -1 || wBytesRead < sizeof(PLACEABLEWMFHEADER) ) {
MessageBox(hWndMain, "Unable to read placeable header",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//return to read metafile header
//
_llseek(fh, sizeof(placeableWMFHeader), 0);
//
//read the metafile header
//
wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
//
//if there is an error return
//
if( wBytesRead == -1 || wBytesRead < sizeof(METAHEADER) ) {
MessageBox(hWndMain, "Unable to read metafile header",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//allocate memory for the metafile bits
//
if (!(lpMFBits = (char *)GlobalAllocPtr(GHND, (mfHeader.mtSize * 2L))))
{
MessageBox(hWndMain, "Unable to allocate memory for metafile bits",
NULL, MB_OK | MB_ICONHAND);
return(FALSE);
}
//
//seek to the metafile bits
//
_llseek(fh, sizeof(placeableWMFHeader), 0);
//
//read metafile bits
//
lBytesRead = _hread(fh, lpMFBits, mfHeader.mtSize * 2);
//
//if there was an error
//
if( lBytesRead == -1 )
{
MessageBox(hWndMain, "Unable to read metafile bits",
NULL, MB_OK | MB_ICONHAND);
GlobalFreePtr(lpMFBits);
return(FALSE);
}
//
//set the metafile bits to the memory that we allocated
//
dwSize = GlobalSizePtr(lpMFBits);
if (!(hMF = SetMetaFileBitsEx(dwSize, (const unsigned char *)lpMFBits)))
return(FALSE);
return(TRUE);
}
/***********************************************************************
FUNCTION : SetPlaceableExts
PARAMETERS : HDC hDC
PLACEABLEWMFHEADER phdr
int nDest
PURPOSE : set the origins and extents on the DC to correspond with
the origins and extents specified within the placeable
metafile header
CALLS : WINDOWS
GetClientRect
SetMapMode
SetWindowOrg
SetWindowExt
SetViewportOrg
SetViewportExt
C runtime
labs
MESSAGES : none
RETURNS : void
COMMENTS :
HISTORY : 1/16/91 - created - drc
************************************************************************/
void SetPlaceableExts(HDC hDC, PLACEABLEWMFHEADER phdr, int nDest)
{
RECT rect;
POINT lpPT;
SIZE lpSize;
/* if setting the extents on the display DC */
if (nDest != WMFPRINTER)
GetClientRect(hWndMain, &rect);
SetMapMode(hDC, MM_ANISOTROPIC);
/* set the windows origin to correspond to the bounding box origin
contained in the placeable header */
SetWindowOrgEx(hDC, phdr.bbox.left, phdr.bbox.top, &lpPT);
/* set the window extents based on the abs value of the bbox coords */
SetWindowExtEx(hDC,phdr.bbox.right -phdr.bbox.left,
phdr.bbox.bottom -phdr.bbox.top,
&lpSize);
/* set the viewport origin and extents */
if (nDest != WMFPRINTER)
{
SetViewportOrgEx(hDC, 0, 0, &lpPT);
SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize);
}
else
{
SetViewportOrgEx(hPr, 0, 0, &lpPT);
SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES),
GetDeviceCaps(hPr, VERTRES),
&lpSize);
}
}
void SetNonPlaceableExts(HDC hDC, int nDest)
{
RECT rect;
POINT lpPT;
SIZE lpSize;
/* if setting the extents on the display DC */
if (nDest != WMFPRINTER)
GetClientRect(hWndMain, &rect);
SetMapMode(hDC, MM_ANISOTROPIC);
/* set the viewport origin and extents */
if (nDest != WMFPRINTER)
{
SetViewportOrgEx(hDC, 0, 0, &lpPT);
SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize);
}
else
{
SetViewportOrgEx(hPr, 0, 0, &lpPT);
SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES),
GetDeviceCaps(hPr, VERTRES),
&lpSize);
}
}
/***********************************************************************
FUNCTION : SetClipMetaExts
PARAMETERS : HDC hDC
METAFILEPICT MFP
int nDest
PURPOSE : set the extents to the client rect for clipboard metafiles
CALLS : WINDOWS
GetClientRect
IntersectClipRect
SetMapMode
SetViewportOrg
SetViewportExt
SetWindowExt
MESSAGES : none
RETURNS : void
COMMENTS : this is not as robust as it could be. A more complete
approach might be something like Petzold discusses in
his Programming Windows book on page 793 in the
function PrepareMetaFile().
HISTORY : 1/16/91 - created - drc
************************************************************************/
void SetClipMetaExts(
HDC hDC,
LPMETAFILEPICT lpMFP,
LPOLDMETAFILEPICT lpOldMFP,
int nDest)
{
int cx, cy;
RECT rect;
POINT lpPT;
SIZE lpSize;
long lmm;
long lxExt;
long lyExt;
/* extents for the display DC */
if (nDest != WMFPRINTER)
{
GetClientRect(hWndMain, &rect);
cx = rect.right - rect.left;
cy = rect.bottom - rect.top;
IntersectClipRect(hDC, rect.left, rect.top, rect.right, rect.bottom);
}
SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm));
/* set physical origin to 0, 0 */
SetViewportOrgEx(hDC, 0, 0, &lpPT);
/* given the mapping mode specified in the metafilepict */
lmm = (lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm;
lxExt = (lpOldMFP != NULL) ? lpOldMFP->xExt : lpMFP->xExt;
lyExt = (lpOldMFP != NULL) ? lpOldMFP->yExt : lpMFP->yExt;
switch (lmm) {
case MM_ISOTROPIC:
if (lxExt && lyExt)
SetWindowExtEx(hDC, lxExt, lyExt, &lpSize);
/* fall through */
case MM_ANISOTROPIC:
if (nDest != WMFPRINTER)
SetViewportExtEx(hDC, cx, cy, &lpSize);
else
SetViewportExtEx(hDC, GetDeviceCaps(hDC, HORZRES),
GetDeviceCaps(hDC, VERTRES), &lpSize );
break;
default:
break;
}
}
/***********************************************************************
FUNCTION : ProcessFile
PARAMETERS : HWND hWnd
LPSTR lpFileName
PURPOSE : open the metafile, determine if it contains a valid
metafile, decide what type of metafile it is (wmf,
clipboard, or placeable) and take care of some menu
housekeeping tasks.
CALLS :
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 1/16/91 - created - drc
************************************************************************/
BOOL ProcessFile(
HWND hWnd,
LPSTR lpFileName)
{
//
//for openfiledialog
//
char drive[3];
char dir[MAX_PATH+1];
char fname[MAX_PATH+1];
char ext[5];
char * pchCorrectSir;
//
//initialize these global handles to metafiles
//
if (hMF && !bMetaInRam)
{
DeleteMetaFile((HMETAFILE)hMF);
hMF = NULL;
}
if (hemf && !bMetaInRam)
{
DeleteEnhMetaFile(hemf);
hemf = NULL;
}
if (lpMFBits)
{
GlobalFreePtr(lpMFBits);
lpMFBits = NULL;
hemf = NULL;
hMF = NULL;
}
bEnhMeta = FALSE;
//
//split the fully qualified filename into its components
//
SplitPath( lpFileName, (LPSTR)drive,
(LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
pchCorrectSir = _strupr( _strdup( ext ) );
//
//if the memory for the emf header, desc string and palette
//is still around then nuke it
//
if (EmfPtr.lpEMFHdr)
{
GlobalFreePtr(EmfPtr.lpEMFHdr);
EmfPtr.lpEMFHdr = NULL ;
}
if (EmfPtr.lpDescStr)
{
GlobalFreePtr(EmfPtr.lpDescStr);
EmfPtr.lpDescStr = NULL ;
}
if (EmfPtr.lpPal)
{
GlobalFreePtr(EmfPtr.lpPal);
EmfPtr.lpPal = NULL ;
}
//
//if the file is an enhanced metafile
//
if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"CLP") == 0)
return ProcessCLP(hWnd, lpFileName);
//
//if the file is a Windows metafile or a Windows or placeable metafile
//as per the normal naming conventions
//
if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"WMF") == 0)
return ProcessWMF(hWnd, lpFileName);
//
//if the file is a clipboard file
//
if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"EMF") == 0)
return ProcessEMF(hWnd, lpFileName);
return FALSE;
}
/***********************************************************************
FUNCTION : ProcessWMF
PARAMETERS : HWND hWnd
LPSTR lpFileName
PURPOSE : open the metafile and determine if it is a Windows metafile or
placeable metafile. Then take care of some menu housekeeping
tasks.
CALLS :
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 6/23/93 - created - drc
************************************************************************/
BOOL ProcessWMF(HWND hWnd, LPSTR lpFileName)
{
int fh;
int wBytesRead;
DWORD dwIsPlaceable;
char szCaption[144];
/* for openfiledialog */
char drive[3];
char dir[MAX_PATH+1];
char fname[MAX_PATH+1];
char ext[5];
char * pchCorrectSir;
//
//split the fully qualified filename into its components
//
SplitPath( lpFileName, (LPSTR)drive,
(LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
pchCorrectSir = _strupr( _strdup( ext ) );
//
//try to open the file. It's existence has already been
//checked by OpenFileDialog
//
fh = _lopen(lpFileName, OF_READ);
//
//if opened successfully
//
if (fh != -1)
{
//
//always disable the clipboard and EMF header menu if we get here
//
EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED);
//
// read the first dword of the file to see if it is a placeable wmf
//
wBytesRead = _lread(fh,(LPSTR)&dwIsPlaceable, sizeof(dwIsPlaceable));
if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable))
{
_lclose(fh);
MessageBox(hWndMain, "unable to read file", NULL,
MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
//
// if this is windows metafile, not a placeable wmf
//
if (dwIsPlaceable != PLACEABLEKEY)
{
// if (!bMetaInRam)
hMF = GetMetaFile((LPSTR)OpenName);
//
//disable placeable header menu item
//
EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
//
//seek to the beginning of the file
//
_llseek(fh, 0, 0);
//
//read the wmf header
//
wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
//
//done with file so close it
//
_lclose(fh);
//
//if read failed
//
if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable))
{
MessageBox(hWndMain, "unable to read metafile header", NULL,
MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
}
//
//this is a placeable metafile
//
else
{
//
//enable the placeable header menu item
//
EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_ENABLED);
//
//convert the placeable format into something that can
//be used with GDI metafile functions
//
RenderPlaceableMeta(fh);
//
//close the file
//
_lclose(fh);
}
//
//at this point we have a metafile header regardless of whether
//the metafile was a windows metafile or a placeable metafile
//so check to see if it is valid. There is really no good
//way to do this so just make sure that the mtType is either
//1 or 2 (memory or disk file)
//
if ( (mfHeader.mtType != 1) && (mfHeader.mtType != 2) )
{
//
//set the program flags appropriately
//
bBadFile = TRUE;
bMetaFileOpen = FALSE;
bValidFile = FALSE;
//
//let the user know that this is an invalid metafile
//
MessageBox(hWndMain, "This file is not a valid metafile",
NULL, MB_OK | MB_ICONEXCLAMATION);
//
//restore the caption text to the default
//
SetWindowText(hWnd, (LPSTR)APPNAME);
//
//disable menu items, indicating that a valid metafile has not been
//loaded
//
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
//
//refresh the menu bar to reflect above changes
//
DrawMenuBar(hWnd);
}
//
//this is a valid metafile...at least based on the above criteria
//
else
{
//
//modify and update the caption text
//
wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
(LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
//
//this could be used by the printing routines if unable to print
//
wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
SetWindowText(hWnd, (LPSTR)szCaption);
//
//enable the appropriate menu items
//
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED);
//
//refresh the menu bar to reflect above changes
//
DrawMenuBar(hWnd);
//
//set global flags appropriately
//
bValidFile = TRUE;
bMetaFileOpen = TRUE;
if (dwIsPlaceable != PLACEABLEKEY)
{
bPlaceableMeta = FALSE;
bMetaInRam = FALSE;
}
else
{
bPlaceableMeta = TRUE;
bMetaInRam = TRUE;
}
}
return (TRUE);
} //if fh != -1
else
return (FALSE);
}
/***********************************************************************
FUNCTION : ProcessCLP
PARAMETERS : HWND hWnd
LPSTR lpFileName
PURPOSE : open the metafile contained in the clipboard file and
take care of some menu housekeeping tasks.
CALLS :
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 6/23/93 - created - drc
************************************************************************/
BOOL ProcessCLP(HWND hWnd, LPSTR lpFileName)
{
WORD i;
int fh;
DWORD HeaderPos;
DWORD nSizeOfClipHeader;
DWORD nSizeOfClipFormat;
NTCLIPFILEHEADER NTFileHeader;
NTCLIPFILEFORMAT NTClipHeader;
CLIPFILEHEADER FileHeader;
CLIPFILEFORMAT ClipHeader;
char szCaption[144];
WORD wFileID;
BOOL bMetaFound = FALSE;
LPVOID lpvAddressOfHdr;
/* for openfiledialog */
char drive[3];
char dir[MAX_PATH+1];
char fname[MAX_PATH+1];
char ext[5];
char * pchCorrectSir;
//
//split the fully qualified filename into its components
//
SplitPath( lpFileName, (LPSTR)drive,
(LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
pchCorrectSir = _strupr( _strdup( ext ) );
//
//try to open the file. It's existence has already been
//checked by OpenFileDialog
fh = _lopen(lpFileName, OF_READ);
//
//if opened successfully
if (fh != -1 )
{
//
// read the clipboard fileidentifier
//
wFileID = 0;
_lread(fh, (LPSTR)&wFileID, sizeof(WORD));
_llseek(fh, 0, 0);
//
//if this is not a valid clipboard file based on the file
//identifier of the file header
//
if (wFileID != CLP_ID && wFileID != CLP_NT_ID && wFileID != CLPBK_NT_ID)
{
_lclose(fh);
MessageBox(hWndMain, "This file is not a valid clipboard file",
NULL, MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
switch (wFileID)
{
case CLP_ID:
_lread(fh, (LPSTR)&FileHeader, sizeof(CLIPFILEHEADER));
nSizeOfClipHeader = sizeof(CLIPFILEHEADER);
nSizeOfClipFormat = sizeof(CLIPFILEFORMAT);
HeaderPos = nSizeOfClipHeader;
break;
case CLP_NT_ID:
case CLPBK_NT_ID:
NTFileHeader.FormatCount = 0;
_lread(fh, (LPSTR)&NTFileHeader, sizeof(NTCLIPFILEHEADER));
nSizeOfClipHeader = sizeof(NTCLIPFILEHEADER);
nSizeOfClipFormat = sizeof(NTCLIPFILEFORMAT);
HeaderPos = nSizeOfClipHeader;
break;
default:
break;
}
//
//search the formats contained within the clipboard file looking
//for a metafile. Break if and when it is found
//
for (i=0;
i < ((wFileID == CLP_ID) ? FileHeader.FormatCount : NTFileHeader.FormatCount);
i++)
{
_llseek(fh, HeaderPos, 0);
//
//read the clipboard header found at current position
//
lpvAddressOfHdr = (wFileID == CLP_ID) ? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader;
if(_lread(fh, (LPSTR)lpvAddressOfHdr, nSizeOfClipFormat) < nSizeOfClipFormat)
//if(_lread(fh, (LPSTR)&ClipHeader, nSizeOfClipHeader) < nSizeOfClipHeader)
{
_lclose(fh);
MessageBox(hWndMain, "read of clipboard header failed",
NULL, MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
//
//increment the file offset to data
//
HeaderPos += nSizeOfClipFormat;
//
//if a metafile was found break...
//this break assumes that CF_METAFILEPICT formats are always written before CF_ENHMETAFILE
//formats.
//
if (wFileID == CLP_ID && ClipHeader.FormatID == CF_METAFILEPICT)
{
bMetaFound = TRUE;
break;
}
if (wFileID == CLP_NT_ID || wFileID == CLPBK_NT_ID)
{
if (NTClipHeader.FormatID == CF_ENHMETAFILE)
// HeaderPos += NTClipHeader.DataLen;
//else
{
bMetaFound = TRUE;
break;
}
}
} //for i < formatcount
if (bMetaFound)
{
//
//if there is currently a metafile loaded delete it.
//
if (wFileID == CLP_ID)
{
if ((bMetaInRam) && (hMF))
{
DeleteMetaFile((HMETAFILE)hMF);
hMF = NULL;
}
}
else
{
if ((bMetaInRam) && (hemf))
{
DeleteEnhMetaFile(hemf);
hemf = NULL;
}
}
//
//modify and update the caption text
//
wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
(LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
//
//this could be used by the printing routines if unable to print
//
wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
SetWindowText(hWnd, (LPSTR)szCaption);
//
//enable the appropriate menu items
//
if (wFileID == CLP_ID)
{
EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED);
}
else
{
EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED);
}
EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
//
//refresh the menu bar
//
DrawMenuBar(hWnd);
//
//set the program flags appropriately
//
bValidFile = TRUE;
bMetaFileOpen = TRUE;
bMetaInRam = TRUE;
bPlaceableMeta = FALSE;
bEnhMeta = (wFileID == CLP_ID) ? FALSE : TRUE;
//
//convert the metafile contained within the clipboard file into
//a format useable with GDI metafile functions
//
if (!RenderClipMeta(((wFileID == CLP_ID)? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader),
fh,
FileHeader.FileIdentifier))
MessageBox(hWndMain, "Unable to render format",
NULL, MB_OK | MB_ICONEXCLAMATION);
_lclose(fh);
}
//
//a metafile was not found within the clipboard file
//
else
{
bBadFile = TRUE;
bMetaFileOpen = FALSE;
bValidFile = FALSE;
bEnhMeta = FALSE;
//
//let the user know
//
MessageBox(hWndMain, "This CLP file doesn't contain a valid metafile",
NULL, MB_OK | MB_ICONEXCLAMATION);
//
//restore the caption text to default
//
SetWindowText(hWnd, (LPSTR)APPNAME);
//
//disable previously enabled menu items
//
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
//
//refresh the menu bar to reflect these changes
//
DrawMenuBar(hWnd);
_lclose(fh);
}
return (TRUE);
}
else
return (FALSE);
}
/***********************************************************************
FUNCTION : ProcessEMF
PARAMETERS : HWND hWnd
LPSTR lpFileName
PURPOSE : open the metafile contained in the clipboard file and
take care of some menu housekeeping tasks.
CALLS :
MESSAGES : none
RETURNS : BOOL
COMMENTS :
HISTORY : 6/23/93 - created - drc
************************************************************************/
BOOL ProcessEMF(HWND hWnd, LPSTR lpFileName)
{
char szCaption[144];
/* for openfiledialog */
char drive[3];
char dir[MAX_PATH+1];
char fname[MAX_PATH+1];
char ext[5];
char * pchCorrectSir;
bEnhMeta = FALSE;
//
//split the fully qualified filename into its components
//
SplitPath( lpFileName, (LPSTR)drive,
(LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
pchCorrectSir = _strupr( _strdup( ext ) );
//
//always disable the clipboard, WMF and Placeable header menu if we get here
//
EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
//
//if emf was successfully opened
//
if (!hemf)
hemf = GetEnhMetaFile(lpFileName);
if (hemf)
{
GetEMFCoolStuff();
//
//modify and update the caption text
//
wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
(LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
//
//this could be used by the printing routines if unable to print
//
wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
SetWindowText(hWnd, (LPSTR)szCaption);
//
//enable the appropriate menu items
//
EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
//
//refresh the menu bar
//
DrawMenuBar(hWnd);
//
//set the program flags appropriately
//
bValidFile = TRUE;
bMetaFileOpen = TRUE;
bEnhMeta = TRUE;
bMetaInRam = FALSE;
bPlaceableMeta = FALSE;
}
// DeleteEnhMetaFile(hemf);
else
{
bEnhMeta = FALSE;
bValidFile = FALSE;
bBadFile = TRUE;
bMetaFileOpen = FALSE;
//
//let the user know
//
MessageBox(hWndMain, "This EMF file doesn't contain a valid metafile",
NULL, MB_OK | MB_ICONEXCLAMATION);
//
//restore the caption text to default
//
SetWindowText(hWnd, (LPSTR)APPNAME);
//
//disable previously enabled menu items
//
EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
//
//refresh the menu bar to reflect these changes
//
DrawMenuBar(hWnd);
}
return TRUE;
}
/***********************************************************************
FUNCTION : GetEMFCoolStuff
PARAMETERS :
PURPOSE :
CALLS :
MESSAGES :
RETURNS :
COMMENTS :
HISTORY : created 7/8/93 - denniscr
************************************************************************/
BOOL GetEMFCoolStuff()
{
//
//init these ptrs
//
EmfPtr.lpEMFHdr = NULL;
EmfPtr.lpDescStr = NULL;
EmfPtr.lpPal = NULL;
if (hemf)
{
//
//obtain the sizes of the emf header, description string and palette
//
UINT uiHdrSize = GetEnhMetaFileHeader(hemf, 0, NULL);
UINT uiDescStrSize = GetEnhMetaFileDescription(hemf, 0, NULL);
UINT uiPalEntries = GetEnhMetaFilePaletteEntries(hemf, 0, NULL);
//
//if these are lengths > 0 then allocate memory to store them
//
if (uiHdrSize)
EmfPtr.lpEMFHdr = (LPENHMETAHEADER)GlobalAllocPtr(GHND, uiHdrSize);
if (uiDescStrSize)
EmfPtr.lpDescStr = (LPTSTR)GlobalAllocPtr(GHND, uiDescStrSize);
if (uiPalEntries)
EmfPtr.lpPal = (LPPALETTEENTRY)GlobalAllocPtr(GHND, uiPalEntries * sizeof(PALETTEENTRY));
//
//so far the emf seems to be valid so continue
//
if (uiHdrSize)
{
//
//get the actual emf header and description string
//
if (!GetEnhMetaFileHeader(hemf, uiHdrSize, EmfPtr.lpEMFHdr))
{
MessageBox(hWndMain, "unable to read enhanced metafile header", NULL,
MB_OK | MB_ICONEXCLAMATION);
bValidFile = FALSE;
return (FALSE);
}
else
{
//
//get the description string if it exists
//
if (uiDescStrSize)
GetEnhMetaFileDescription(hemf, uiDescStrSize, EmfPtr.lpDescStr);
//
//get the palette if it exists
//
if (uiPalEntries)
{
GetEnhMetaFilePaletteEntries(hemf, uiPalEntries, EmfPtr.lpPal);
EmfPtr.palNumEntries = (WORD)uiPalEntries;
}
}
}
}
return (TRUE);
}
float NormalizeAngle (double angle)
{
if (angle >= 0)
{
while (angle >= 360)
{
angle -= 360;
}
}
else
{
while (angle < 0)
{
angle += 360;
}
}
return static_cast<float>(angle);
}
#define PI 3.1415926535897932384626433832795
#define RADIANS_TO_DEGREES (180.0 / PI)
float PointToAngle(float x, float y, float w, float h, float xVector, float yVector)
{
BOOL bScale = TRUE;
if (w == h)
{
if (w == 0)
{
return 0;
}
bScale = FALSE;
}
float horRadius = w / 2;
float verRadius = h / 2;
float xOrigin = x + horRadius;
float yOrigin = y + verRadius;
if (horRadius == 0)
{
double dAngle = asin(((double)(yVector - yOrigin)) / verRadius);
if (xOrigin > xVector)
{
dAngle = PI - dAngle;
}
return NormalizeAngle(dAngle * RADIANS_TO_DEGREES);
}
else if (verRadius == 0)
{
double dAngle = acos(((double)(xVector - xOrigin)) / horRadius);
if (yOrigin > yVector)
{
dAngle = -dAngle;
}
return NormalizeAngle(dAngle * RADIANS_TO_DEGREES);
}
if (yOrigin == yVector)
{
return static_cast<float>((xOrigin <= xVector) ? 0 : 180);
}
if (xOrigin == xVector)
{
return static_cast<float>((yOrigin < yVector) ? 90 : 270);;
}
if (bScale)
{
xVector = (float)(xOrigin + ((xVector - xOrigin) * ((double)verRadius / horRadius)));
}
return NormalizeAngle(atan2(yVector - yOrigin, xVector - xOrigin) * RADIANS_TO_DEGREES);
}
#define HS_DDI_MAX 6
typedef struct {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[2];
} HATCHBRUSHINFO;
HATCHBRUSHINFO hatchBrushInfo = {
{ sizeof(BITMAPINFOHEADER), 8, 8, 1, 1, BI_RGB, 32, 0, 0, 2, 0 },
{ { 255, 255, 255, 0 }, { 0, 0, 0, 0 } }
};
ULONG HatchPatterns[HS_DDI_MAX][8] = {
// Scans have to be DWORD aligned:
{ 0x00, // ........ HS_HORIZONTAL 0
0x00, // ........
0x00, // ........
0xff, // ********
0x00, // ........
0x00, // ........
0x00, // ........
0x00 }, // ........
{ 0x08, // ....*... HS_VERTICAL 1
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08 }, // ....*...
{ 0x80, // *....... HS_FDIAGONAL 2
0x40, // .*......
0x20, // ..*.....
0x10, // ...*....
0x08, // ....*...
0x04, // .....*..
0x02, // ......*.
0x01 }, // .......*
{ 0x01, // .......* HS_BDIAGONAL 3
0x02, // ......*.
0x04, // .....*..
0x08, // ....*...
0x10, // ...*....
0x20, // ..*.....
0x40, // .*......
0x80 }, // *.......
{ 0x08, // ....*... HS_CROSS 4
0x08, // ....*...
0x08, // ....*...
0xff, // ********
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08 }, // ....*...
{ 0x81, // *......* HS_DIAGCROSS 5
0x42, // .*....*.
0x24, // ..*..*..
0x18, // ...**...
0x18, // ...**...
0x24, // ..*..*..
0x42, // .*....*.
0x81 } // *......*
};
/***********************************************************************
FUNCTION : EnhMetaFileEnumProc
PARAMETERS : HDC hDC
LPHANDLETABLE lpHTable
LPMETARECORD lpMFR
int nObj
LPARAM lpData
PURPOSE : callback for EnumEnhMetaFile.
CALLS : EnumMFIndirect()
MESSAGES : none
RETURNS : int
COMMENTS :
HISTORY : created 6/30/93 - denniscr
************************************************************************/
int CALLBACK EnhMetaFileEnumProc(HDC hDC, LPHANDLETABLE lpHTable,
LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData)
{
return EnumMFIndirect(hDC, lpHTable, NULL, lpEMFR, nObj, lpData);
}
void GetPixelSize (Gdiplus::Graphics * g, float * cx, float * cy)
{
Gdiplus::PointF points[2];
points[0].X = points[0].Y = 0;
points[1].X = points[1].Y = 1;
g->TransformPoints(Gdiplus::CoordinateSpaceWorld, Gdiplus::CoordinateSpaceDevice, points, 2);
*cx = points[1].X - points[0].X;
*cy = points[1].Y - points[0].Y;
}
void GpPlayEnhMetaFileRecord(HDC hDC, LPHANDLETABLE lpHTable,
LPENHMETARECORD lpEMFR,
UINT nObj, LPARAM lpData)
{
if (!lpData) return;
MYDATA * myData = (MYDATA *)lpData;
Gdiplus::Graphics * g = myData->g;
myData->recordNum++;
XFORM xForm;
GetWorldTransform(hDC, &xForm);
INT mapMode = GetMapMode(hDC);
POINT org;
SIZE size;
GetViewportOrgEx(hDC, &org);
GetViewportExtEx(hDC, &size);
GetWindowOrgEx(hDC, &org);
GetWindowExtEx(hDC, &size);
switch (lpEMFR->iType)
{
case EMR_HEADER:
{
PENHMETAHEADER pHeader = (PENHMETAHEADER)lpEMFR;
RECT clientRect;
myData->recordNum = 1;
myData->pObjects = new MYOBJECTS[pHeader->nHandles];
myData->numObjects = pHeader->nHandles;
GetClientRect(myData->hwnd, &clientRect);
int clientWidth = clientRect.right - clientRect.left;
int clientHeight = clientRect.bottom - clientRect.top;
myData->windowExtent.cx = clientWidth;
myData->windowExtent.cy = clientHeight;
myData->viewportExtent.cx = clientWidth;
myData->viewportExtent.cy = clientHeight;
float dstX = TOREAL(clientRect.left);
float dstY = TOREAL(clientRect.top);
float dstWidth = TOREAL(clientWidth);
float dstHeight = TOREAL(clientHeight);
float srcWidth = TOREAL(pHeader->rclFrame.right - pHeader->rclFrame.left);
float srcHeight = TOREAL(pHeader->rclFrame.bottom - pHeader->rclFrame.top);
#if 0
if (srcHeight * dstWidth >= dstHeight * srcWidth)
{
float oldDstWidth = dstWidth;
dstWidth = srcWidth * dstHeight / srcHeight;
dstX += (oldDstWidth - dstWidth) / 2;
}
else
{
float oldDstHeight = dstHeight;
dstHeight = srcHeight * dstWidth / srcWidth;
dstY += (oldDstHeight - dstHeight) / 2;
}
#endif
g->SetPageUnit(Gdiplus::UnitPixel);
using Gdiplus::RectF;
RectF dstRect(dstX, dstY, dstWidth, dstHeight);
int deviceLeft = pHeader->rclBounds.left;
int deviceRight = pHeader->rclBounds.right;
int deviceTop = pHeader->rclBounds.top;
int deviceBottom = pHeader->rclBounds.bottom;
// if ((deviceLeft > deviceRight) ||
// (deviceTop > deviceBottom))
{
SIZEL deviceSize = pHeader->szlDevice;
SIZEL mmSize = pHeader->szlMillimeters;
if ((deviceSize.cx <= 0) || (deviceSize.cy <= 0) ||
(mmSize.cx <= 0) || (mmSize.cy <= 0))
{
ASSERT(0);
// Take a wild guess
deviceSize.cx = 1024;
deviceSize.cy = 768;
mmSize.cx = 320;
mmSize.cy = 240;
}
deviceLeft = MulDiv(pHeader->rclFrame.left, deviceSize.cx, (mmSize.cx * 100));
deviceRight = MulDiv(pHeader->rclFrame.right, deviceSize.cx, (mmSize.cx * 100));
deviceTop = MulDiv(pHeader->rclFrame.top, deviceSize.cy, (mmSize.cy * 100));
deviceBottom = MulDiv(pHeader->rclFrame.bottom, deviceSize.cy, (mmSize.cy * 100));
}
RectF srcRect(TOREAL(deviceLeft),
TOREAL(deviceTop),
TOREAL(deviceRight - deviceLeft),
TOREAL(deviceBottom - deviceTop));
myData->containerId = g->BeginContainer(dstRect, srcRect, Gdiplus::UnitPixel);
g->SetPageUnit(Gdiplus::UnitPixel); // Assume MM_TEXT
}
break;
case EMR_POLYBEZIER:
{
PEMRPOLYBEZIER pBezier = (PEMRPOLYBEZIER)lpEMFR;
if (pBezier->cptl > 0)
{
int i = pBezier->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = TOREAL(pBezier->aptl[i].x);
points[i].Y = TOREAL(pBezier->aptl[i].y);
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawBeziers(&pen, points, pBezier->cptl);
}
}
else
{
myData->path->AddBeziers(points, pBezier->cptl);
}
delete [] points;
}
}
break;
case EMR_POLYGON:
{
PEMRPOLYGON pPolygon = (PEMRPOLYGON)lpEMFR;
if (pPolygon->cptl > 0)
{
int i = pPolygon->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = TOREAL(pPolygon->aptl[i].x);
points[i].Y = TOREAL(pPolygon->aptl[i].y);
} while (i > 0);
if (!myData->pathOpen)
{
Gdiplus::GraphicsPath path(myData->fillMode);
path.AddPolygon(points, pPolygon->cptl);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
else
{
myData->path->AddPolygon(points, pPolygon->cptl);
}
delete [] points;
}
}
break;
case EMR_POLYLINE:
{
PEMRPOLYLINE pPolyline = (PEMRPOLYLINE)lpEMFR;
if (pPolyline->cptl > 0)
{
int i = pPolyline->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = TOREAL(pPolyline->aptl[i].x);
points[i].Y = TOREAL(pPolyline->aptl[i].y);
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawLines(&pen, points, pPolyline->cptl);
}
}
else
{
myData->path->AddLines(points, pPolyline->cptl);
}
delete [] points;
}
}
break;
case EMR_POLYBEZIERTO:
{
PEMRPOLYBEZIERTO pBezier = (PEMRPOLYBEZIERTO)lpEMFR;
if (pBezier->cptl > 0)
{
int i = pBezier->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
do
{
points[i].X = TOREAL(pBezier->aptl[i-1].x);
points[i].Y = TOREAL(pBezier->aptl[i-1].y);
i--;
} while (i > 0);
points[0] = myData->curPos;
myData->curPos = points[pBezier->cptl];
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawBeziers(&pen, points, pBezier->cptl+1);
}
}
else
{
myData->path->AddBeziers(points, pBezier->cptl+1);
}
delete [] points;
}
}
break;
case EMR_POLYLINETO:
{
PEMRPOLYLINETO pPolyline = (PEMRPOLYLINETO)lpEMFR;
if (pPolyline->cptl > 0)
{
int i = pPolyline->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
do
{
points[i].X = TOREAL(pPolyline->aptl[i-1].x);
points[i].Y = TOREAL(pPolyline->aptl[i-1].y);
i--;
} while (i > 0);
points[0] = myData->curPos;
myData->curPos = points[pPolyline->cptl];
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawLines(&pen, points, pPolyline->cptl+1);
}
}
else
{
myData->path->AddLines(points, pPolyline->cptl+1);
}
delete [] points;
}
}
break;
case EMR_POLYPOLYLINE:
{
PEMRPOLYPOLYLINE pPolyline = (PEMRPOLYPOLYLINE)lpEMFR;
if ((pPolyline->cptl > 0) && (pPolyline->nPolys > 0))
{
int i = pPolyline->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
POINTL * metaPoints = (POINTL *)(pPolyline->aPolyCounts + pPolyline->nPolys);
do
{
i--;
points[i].X = TOREAL(metaPoints[i].x);
points[i].Y = TOREAL(metaPoints[i].y);
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
i = 0;
Gdiplus::PointF * tmpPoints = points;
DWORD count;
do
{
count = pPolyline->aPolyCounts[i];
g->DrawLines(&pen, tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolyline->nPolys);
}
}
else
{
i = 0;
Gdiplus::PointF * tmpPoints = points;
DWORD count;
do
{
count = pPolyline->aPolyCounts[i];
myData->path->AddLines(tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolyline->nPolys);
}
delete [] points;
}
}
break;
case EMR_POLYPOLYGON:
{
PEMRPOLYPOLYGON pPolygon = (PEMRPOLYPOLYGON)lpEMFR;
if ((pPolygon->cptl > 0) && (pPolygon->nPolys > 0))
{
int i = pPolygon->cptl;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
POINTL * metaPoints = (POINTL *)(pPolygon->aPolyCounts + pPolygon->nPolys);
do
{
i--;
points[i].X = TOREAL(metaPoints[i].x);
points[i].Y = TOREAL(metaPoints[i].y);
} while (i > 0);
Gdiplus::GraphicsPath path(myData->fillMode);
Gdiplus::GraphicsPath * tmpPath = &path;
if (myData->pathOpen)
{
tmpPath = myData->path;
}
Gdiplus::PointF * tmpPoints = points;
DWORD count;
i = 0;
do
{
count = pPolygon->aPolyCounts[i];
tmpPath->StartFigure();
tmpPath->AddPolygon(tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolygon->nPolys);
if (myData->path == NULL)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
delete [] points;
}
}
break;
case EMR_SETWINDOWEXTEX:
{
PEMRSETWINDOWEXTEX pWindowExt = (PEMRSETWINDOWEXTEX)lpEMFR;
if (((myData->mapMode == MM_ANISOTROPIC) ||
(myData->mapMode == MM_ISOTROPIC)) &&
(pWindowExt->szlExtent.cx != 0) && // Note: Can be < 0!!!
(pWindowExt->szlExtent.cy != 0) &&
(pWindowExt->szlExtent.cx != myData->windowExtent.cx) &&
(pWindowExt->szlExtent.cy != myData->windowExtent.cy))
{
myData->windowExtent = pWindowExt->szlExtent;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
if (myData->mapMode == MM_ISOTROPIC)
{
if (sX < sY)
{
sY = sX;
}
else
{
sX = sY;
}
}
myData->scaleX = sX;
myData->scaleY = sY;
myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(sX, sY);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SETWINDOWORGEX:
{
PEMRSETWINDOWORGEX pWindowOrg = (PEMRSETWINDOWORGEX)lpEMFR;
if ((pWindowOrg->ptlOrigin.x != myData->windowOrg.x) &&
(pWindowOrg->ptlOrigin.y != myData->windowOrg.y))
{
myData->windowOrg = pWindowOrg->ptlOrigin;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(oldSx, oldSy);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SETVIEWPORTEXTEX:
{
PEMRSETVIEWPORTEXTEX pViewportExt = (PEMRSETVIEWPORTEXTEX)lpEMFR;
if (((myData->mapMode == MM_ANISOTROPIC) ||
(myData->mapMode == MM_ISOTROPIC)) &&
(pViewportExt->szlExtent.cx > 0) &&
(pViewportExt->szlExtent.cy > 0) &&
(pViewportExt->szlExtent.cx != myData->viewportExtent.cx) &&
(pViewportExt->szlExtent.cy != myData->viewportExtent.cy))
{
myData->viewportExtent = pViewportExt->szlExtent;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
if (myData->mapMode == MM_ISOTROPIC)
{
if (sX < sY)
{
sY = sX;
}
else
{
sX = sY;
}
}
myData->scaleX = sX;
myData->scaleY = sY;
myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(sX, sY);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SETVIEWPORTORGEX:
{
PEMRSETVIEWPORTORGEX pViewportOrg = (PEMRSETVIEWPORTORGEX)lpEMFR;
if ((pViewportOrg->ptlOrigin.x != myData->viewportOrg.x) &&
(pViewportOrg->ptlOrigin.y != myData->viewportOrg.y))
{
myData->viewportOrg = pViewportOrg->ptlOrigin;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(oldSx, oldSy);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SETBRUSHORGEX:
break;
case EMR_EOF:
g->EndContainer(myData->containerId);
break;
case EMR_SETPIXELV:
{
PEMRSETPIXELV pSetPixel = (PEMRSETPIXELV)lpEMFR;
COLORREF cRef = pSetPixel->crColor;
ASSERT((cRef & 0x01000000) == 0);
Gdiplus::SolidBrush brush(Gdiplus::Color(Gdiplus::Color::MakeARGB(0xff,
GetRValue(cRef), GetGValue(cRef), GetBValue(cRef))));
g->FillRectangle(&brush, TOREAL(pSetPixel->ptlPixel.x), TOREAL(pSetPixel->ptlPixel.y), TOREAL(1), TOREAL(1));
}
break;
case EMR_SETMAPPERFLAGS: // for font mapping
break;
case EMR_SETMAPMODE:
{
PEMRSETMAPMODE pMapMode = (PEMRSETMAPMODE)lpEMFR;
if (myData->mapMode != pMapMode->iMode)
{
float sX, sY;
myData->mapMode = pMapMode->iMode;
switch (pMapMode->iMode)
{
case MM_TEXT:
g->SetPageUnit(Gdiplus::UnitPixel);
sX = sY = 1;
break;
case MM_LOMETRIC:
g->SetPageUnit(Gdiplus::UnitMillimeter);
g->SetPageScale(TOREAL(.1));
sX = sY = 1;
break;
case MM_HIMETRIC:
g->SetPageUnit(Gdiplus::UnitMillimeter);
g->SetPageScale(TOREAL(.01));
sX = sY = 1;
break;
case MM_LOENGLISH:
g->SetPageUnit(Gdiplus::UnitInch);
g->SetPageScale(TOREAL(.01));
sX = sY = 1;
break;
case MM_HIENGLISH:
g->SetPageUnit(Gdiplus::UnitInch);
g->SetPageScale(TOREAL(.001));
sX = sY = 1;
break;
case MM_TWIPS:
g->SetPageUnit(Gdiplus::UnitPoint);
g->SetPageScale(TOREAL(.05));
sX = sY = 1;
break;
case MM_ISOTROPIC:
g->SetPageUnit(Gdiplus::UnitPixel);
sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
if (sX < sY)
{
sY = sX;
}
else
{
sX = sY;
}
break;
case MM_ANISOTROPIC:
g->SetPageUnit(Gdiplus::UnitPixel);
sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
break;
}
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
myData->scaleX = sX;
myData->scaleY = sY;
myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(sX, sY);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SETBKMODE:
break;
case EMR_SETPOLYFILLMODE:
{
PEMRSETPOLYFILLMODE pPolyfillMode = (PEMRSETPOLYFILLMODE)lpEMFR;
myData->fillMode = (pPolyfillMode->iMode == ALTERNATE) ? Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding;
}
break;
case EMR_SETROP2:
break;
case EMR_SETSTRETCHBLTMODE:
#ifdef _DEBUG
{
PEMRSETSTRETCHBLTMODE pStretchBltMode = (PEMRSETSTRETCHBLTMODE)lpEMFR;
int mode;
switch (pStretchBltMode->iMode)
{
case BLACKONWHITE:
mode = 1;
break;
case WHITEONBLACK:
mode = 2;
break;
case COLORONCOLOR:
mode = 3;
break;
case HALFTONE:
mode = 4;
break;
}
}
#endif
break;
case EMR_SETTEXTALIGN:
break;
case EMR_SETCOLORADJUSTMENT:
break;
case EMR_SETTEXTCOLOR:
break;
case EMR_SETBKCOLOR:
break;
case EMR_OFFSETCLIPRGN:
{
PEMROFFSETCLIPRGN pOffsetClipRgn = (PEMROFFSETCLIPRGN)lpEMFR;
g->TranslateClip(TOREAL(pOffsetClipRgn->ptlOffset.x), TOREAL(pOffsetClipRgn->ptlOffset.y));
}
break;
case EMR_MOVETOEX:
{
PEMRMOVETOEX pMoveTo = (PEMRMOVETOEX)lpEMFR;
myData->curPos.X = TOREAL(pMoveTo->ptl.x);
myData->curPos.Y = TOREAL(pMoveTo->ptl.y);
}
break;
case EMR_SETMETARGN:
break;
case EMR_EXCLUDECLIPRECT:
{
PEMREXCLUDECLIPRECT pExcludeClipRect = (PEMREXCLUDECLIPRECT)lpEMFR;
Gdiplus::RectF clipRect(TOREAL(pExcludeClipRect->rclClip.left),
TOREAL(pExcludeClipRect->rclClip.top),
TOREAL(pExcludeClipRect->rclClip.right - pExcludeClipRect->rclClip.left),
TOREAL(pExcludeClipRect->rclClip.bottom - pExcludeClipRect->rclClip.top));
g->ExcludeClip(clipRect);
}
break;
case EMR_INTERSECTCLIPRECT:
{
PEMRINTERSECTCLIPRECT pIntersectClipRect = (PEMRINTERSECTCLIPRECT)lpEMFR;
Gdiplus::RectF eRect;
eRect.X = TOREAL(pIntersectClipRect->rclClip.left);
eRect.Y = TOREAL(pIntersectClipRect->rclClip.top);
eRect.Width = TOREAL(pIntersectClipRect->rclClip.right - pIntersectClipRect->rclClip.left);
eRect.Height = TOREAL(pIntersectClipRect->rclClip.bottom - pIntersectClipRect->rclClip.top);
g->IntersectClip(eRect);
}
break;
case EMR_SCALEVIEWPORTEXTEX:
{
PEMRSCALEVIEWPORTEXTEX pViewportExt = (PEMRSCALEVIEWPORTEXTEX)lpEMFR;
if (((myData->mapMode == MM_ANISOTROPIC) ||
(myData->mapMode == MM_ISOTROPIC)) &&
(pViewportExt->xNum != 0) &&
(pViewportExt->yNum != 0) &&
(pViewportExt->xDenom != 0) &&
(pViewportExt->yDenom != 0))
{
myData->viewportExtent.cx = (myData->viewportExtent.cx * pViewportExt->xNum) / pViewportExt->xDenom;
myData->viewportExtent.cy = (myData->viewportExtent.cy * pViewportExt->yNum) / pViewportExt->yDenom;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
if (myData->mapMode == MM_ISOTROPIC)
{
if (sX < sY)
{
sY = sX;
}
else
{
sX = sY;
}
}
myData->scaleX = sX;
myData->scaleY = sY;
myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(sX, sY);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SCALEWINDOWEXTEX:
{
PEMRSCALEWINDOWEXTEX pWindowExt = (PEMRSCALEWINDOWEXTEX)lpEMFR;
if (((myData->mapMode == MM_ANISOTROPIC) ||
(myData->mapMode == MM_ISOTROPIC)) &&
(pWindowExt->xNum != 0) &&
(pWindowExt->yNum != 0) &&
(pWindowExt->xDenom != 0) &&
(pWindowExt->yDenom != 0))
{
myData->windowExtent.cx = (myData->windowExtent.cx * pWindowExt->xNum) / pWindowExt->xDenom;
myData->windowExtent.cy = (myData->windowExtent.cy * pWindowExt->yNum) / pWindowExt->yDenom;
float oldDx = myData->dx;
float oldDy = myData->dy;
float oldSx = myData->scaleX;
float oldSy = myData->scaleY;
float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
if (myData->mapMode == MM_ISOTROPIC)
{
if (sX < sY)
{
sY = sX;
}
else
{
sX = sY;
}
}
myData->scaleX = sX;
myData->scaleY = sY;
myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
Gdiplus::Matrix matrix;
matrix.Scale(sX, sY);
matrix.Translate(myData->dx, myData->dy);
matrix.Translate(-oldDx, -oldDy);
matrix.Scale(1 / oldSx, 1 / oldSy);
g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
}
}
break;
case EMR_SAVEDC:
{
myData->PushId(g->Save());
}
break;
case EMR_RESTOREDC:
{
g->Restore(myData->PopId());
}
break;
case EMR_SETWORLDTRANSFORM:
{
PEMRSETWORLDTRANSFORM pXform = (PEMRSETWORLDTRANSFORM)lpEMFR;
Gdiplus::Matrix newMatrix(pXform->xform.eM11,
pXform->xform.eM12,
pXform->xform.eM21,
pXform->xform.eM22,
pXform->xform.eDx,
pXform->xform.eDy);
if (newMatrix.IsInvertible())
{
myData->matrix.Invert();
myData->matrix.Multiply(&newMatrix);
g->MultiplyTransform(&(myData->matrix));
myData->matrix.SetElements(pXform->xform.eM11,
pXform->xform.eM12,
pXform->xform.eM21,
pXform->xform.eM22,
pXform->xform.eDx,
pXform->xform.eDy);
}
}
break;
case EMR_MODIFYWORLDTRANSFORM:
{
PEMRMODIFYWORLDTRANSFORM pXform = (PEMRMODIFYWORLDTRANSFORM)lpEMFR;
switch (pXform->iMode)
{
case MWT_IDENTITY:
default:
{
myData->matrix.Invert();
g->MultiplyTransform(&(myData->matrix));
myData->matrix.Reset();
}
break;
case MWT_LEFTMULTIPLY:
{
Gdiplus::Matrix newMatrix(pXform->xform.eM11,
pXform->xform.eM12,
pXform->xform.eM21,
pXform->xform.eM22,
pXform->xform.eDx,
pXform->xform.eDy);
if (newMatrix.IsInvertible())
{
myData->matrix.Multiply(&newMatrix);
g->MultiplyTransform(&newMatrix);
}
}
break;
case MWT_RIGHTMULTIPLY:
{
Gdiplus::Matrix newMatrix(pXform->xform.eM11,
pXform->xform.eM12,
pXform->xform.eM21,
pXform->xform.eM22,
pXform->xform.eDx,
pXform->xform.eDy);
if (newMatrix.IsInvertible())
{
Gdiplus::Matrix * inverse = myData->matrix.Clone();
inverse->Invert();
myData->matrix.Multiply(&newMatrix, Gdiplus::MatrixOrderAppend);
inverse->Multiply(&(myData->matrix));
g->MultiplyTransform(inverse);
delete inverse;
}
}
break;
}
}
break;
case EMR_SELECTOBJECT:
{
PEMRSELECTOBJECT pObject = (PEMRSELECTOBJECT)lpEMFR;
int objectIndex = pObject->ihObject;
if ((objectIndex & ENHMETA_STOCK_OBJECT) != 0)
{
switch (objectIndex & (~ENHMETA_STOCK_OBJECT))
{
case WHITE_BRUSH:
myData->curBrush = 0xFFFFFFFF;
break;
case LTGRAY_BRUSH:
myData->curBrush = 0xFFC0C0C0;
break;
case GRAY_BRUSH:
myData->curBrush = 0xFF808080;
break;
case DKGRAY_BRUSH:
myData->curBrush = 0xFF404040;
break;
case BLACK_BRUSH:
myData->curBrush = 0xFF000000;
break;
case NULL_BRUSH:
myData->curBrush = 0x00000000;
break;
case WHITE_PEN:
myData->curPen = 0xFFFFFFFF;
break;
case BLACK_PEN:
myData->curPen = 0xFF000000;
break;
case NULL_PEN:
myData->curPen = 0x00000000;
break;
}
}
else
{
ASSERT(objectIndex < myData->numObjects);
if (myData->pObjects[objectIndex].type == MYOBJECTS::PenObjectType)
{
myData->curPen = myData->pObjects[objectIndex].color;
myData->curPenWidth = myData->pObjects[objectIndex].penWidth;
}
else if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType)
{
myData->curBrush = myData->pObjects[objectIndex].color;
myData->curBrushPattern = myData->pObjects[objectIndex].brushPattern;
#if 1
myData->curPatIndex = myData->pObjects[objectIndex].patIndex;
#else
static dodo = 0;
myData->curPatIndex = dodo++ % 6;
#endif
}
}
}
break;
case EMR_CREATEPEN:
{
PEMRCREATEPEN pPen = (PEMRCREATEPEN)lpEMFR;
COLORREF cRef = pPen->lopn.lopnColor;
ASSERT((cRef & 0x01000000) == 0);
ASSERT(pPen->ihPen < myData->numObjects);
delete myData->pObjects[pPen->ihPen].brushPattern;
myData->pObjects[pPen->ihPen].brushPattern = NULL;
myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType;
myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff,
GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
myData->pObjects[pPen->ihPen].penWidth = pPen->lopn.lopnWidth.x;
}
break;
case EMR_CREATEBRUSHINDIRECT:
{
PEMRCREATEBRUSHINDIRECT pBrush = (PEMRCREATEBRUSHINDIRECT)lpEMFR;
COLORREF cRef = pBrush->lb.lbColor;
ASSERT((cRef & 0x01000000) == 0);
ASSERT(pBrush->ihBrush < myData->numObjects);
myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType;
myData->pObjects[pBrush->ihBrush].patIndex = -1;
delete myData->pObjects[pBrush->ihBrush].brushPattern;
myData->pObjects[pBrush->ihBrush].brushPattern = NULL;
if (pBrush->lb.lbStyle == BS_NULL)
{
myData->pObjects[pBrush->ihBrush].color = 0x00000000;
}
else
{
// Hatch Styles
if (pBrush->lb.lbStyle == BS_HATCHED)
{
switch (pBrush->lb.lbHatch)
{
case HS_HORIZONTAL: /* ----- */
case HS_VERTICAL: /* ||||| */
case HS_FDIAGONAL: /* \\\\\ */
case HS_BDIAGONAL: /* ///// */
case HS_CROSS: /* +++++ */
case HS_DIAGCROSS: /* xxxxx */
myData->pObjects[pBrush->ihBrush].patIndex = pBrush->lb.lbHatch;
break;
}
}
myData->pObjects[pBrush->ihBrush].color = Gdiplus::Color::MakeARGB(0xff,
GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
}
}
break;
case EMR_DELETEOBJECT:
{
#if 0
PEMRDELETEOBJECT pObject = (PEMRDELETEOBJECT)lpEMFR;
int objectIndex = pObject->ihObject;
ASSERT(objectIndex < myData->numObjects);
if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType)
{
if (myData->curBrushPattern != myData->pObjects[objectIndex].brushPattern)
{
delete myData->pObjects[objectIndex].brushPattern;
myData->pObjects[objectIndex].brushPattern = NULL;
}
}
#endif
}
break;
case EMR_ANGLEARC:
break;
case EMR_ELLIPSE:
{
PEMRELLIPSE pEllipse = (PEMRELLIPSE)lpEMFR;
float x = TOREAL(pEllipse->rclBox.left);
float y = TOREAL(pEllipse->rclBox.top);
float w = TOREAL(pEllipse->rclBox.right - x);
float h = TOREAL(pEllipse->rclBox.bottom - y);
if (!myData->pathOpen)
{
Gdiplus::GraphicsPath path(myData->fillMode);
path.AddEllipse(x, y, w, h);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
else
{
myData->path->AddEllipse(x, y, w, h);
}
}
break;
case EMR_RECTANGLE:
{
PEMRRECTANGLE pRect = (PEMRRECTANGLE)lpEMFR;
float x = TOREAL(pRect->rclBox.left);
float y = TOREAL(pRect->rclBox.top);
float w = TOREAL(pRect->rclBox.right - x);
float h = TOREAL(pRect->rclBox.bottom - y);
if (!myData->pathOpen)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillRectangle(&brush, x, y, w, h);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, x, y, w, h);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, x, y, w, h);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawRectangle(&pen, x, y, w, h);
}
}
else
{
myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h));
}
}
break;
case EMR_ROUNDRECT: // for now, ignore the szlCorner param of round corners
{
PEMRROUNDRECT pRect = (PEMRROUNDRECT)lpEMFR;
float x = TOREAL(pRect->rclBox.left);
float y = TOREAL(pRect->rclBox.top);
float w = TOREAL(pRect->rclBox.right - x);
float h = TOREAL(pRect->rclBox.bottom - y);
if (!myData->pathOpen)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillRectangle(&brush, x, y, w, h);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, x, y, w, h);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, x, y, w, h);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawRectangle(&pen, x, y, w, h);
}
}
else
{
myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h));
}
}
break;
case EMR_ARC:
{
PEMRARC pArc = (PEMRARC)lpEMFR;
float x = TOREAL(pArc->rclBox.left);
float y = TOREAL(pArc->rclBox.top);
float w = TOREAL(pArc->rclBox.right - x);
float h = TOREAL(pArc->rclBox.bottom - y);
float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y));
float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y));
if (endAngle <= startAngle)
{
endAngle += 360;
}
float sweepAngle = endAngle - startAngle;
if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
{
sweepAngle = 360 - sweepAngle;
}
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle);
}
}
else
{
myData->path->AddArc(x, y, w, h, startAngle, sweepAngle);
}
}
break;
case EMR_CHORD:
break;
case EMR_PIE:
{
PEMRARC pPie = (PEMRARC)lpEMFR;
float x = TOREAL(pPie->rclBox.left);
float y = TOREAL(pPie->rclBox.top);
float w = TOREAL(pPie->rclBox.right - x);
float h = TOREAL(pPie->rclBox.bottom - y);
float startAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlStart.x), TOREAL(pPie->ptlStart.y));
float endAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlEnd.x), TOREAL(pPie->ptlEnd.y));
if (endAngle <= startAngle)
{
endAngle += 360;
}
float sweepAngle = endAngle - startAngle;
if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
{
sweepAngle = 360 - sweepAngle;
}
if (!myData->pathOpen)
{
Gdiplus::GraphicsPath path(myData->fillMode);
path.AddPie(x, y, w, h, startAngle, sweepAngle);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
else
{
myData->path->AddPie(x, y, w, h, startAngle, sweepAngle);
}
}
break;
case EMR_SELECTPALETTE:
break;
case EMR_CREATEPALETTE:
break;
case EMR_SETPALETTEENTRIES:
break;
case EMR_RESIZEPALETTE:
break;
case EMR_REALIZEPALETTE:
break;
case EMR_EXTFLOODFILL:
break;
case EMR_LINETO:
{
PEMRMOVETOEX pLineTo = (PEMRMOVETOEX)lpEMFR;
float x = TOREAL(pLineTo->ptl.x);
float y = TOREAL(pLineTo->ptl.y);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawLine(&pen, (float)myData->curPos.X, (float)myData->curPos.Y, x, y);
}
}
else
{
myData->path->AddLine((float)myData->curPos.X, (float)myData->curPos.Y, x, y);
}
myData->curPos.X = x;
myData->curPos.Y = y;
}
break;
case EMR_ARCTO:
{
// !!! Set and use current position
PEMRARCTO pArc = (PEMRARCTO)lpEMFR;
float x = TOREAL(pArc->rclBox.left);
float y = TOREAL(pArc->rclBox.top);
float w = TOREAL(pArc->rclBox.right - x);
float h = TOREAL(pArc->rclBox.bottom - y);
float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y));
float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y));
if (endAngle <= startAngle)
{
endAngle += 360;
}
float sweepAngle = endAngle - startAngle;
if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
{
sweepAngle = 360 - sweepAngle;
}
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle);
}
}
else
{
myData->path->AddArc(x, y, w, h, startAngle, sweepAngle);
}
}
break;
case EMR_POLYDRAW:
break;
case EMR_SETARCDIRECTION:
{
PEMRSETARCDIRECTION pArcDirection = (PEMRSETARCDIRECTION)lpEMFR;
myData->arcDirection = pArcDirection->iArcDirection;
}
break;
case EMR_SETMITERLIMIT:
{
PEMRSETMITERLIMIT pMiterLimit = (PEMRSETMITERLIMIT)lpEMFR;
myData->miterLimit = pMiterLimit->eMiterLimit;
}
break;
case EMR_BEGINPATH:
{
delete myData->path;
myData->path = new Gdiplus::GraphicsPath (myData->fillMode);
myData->pathOpen = (myData->path != NULL);
}
break;
case EMR_ENDPATH:
myData->pathOpen = FALSE;
break;
case EMR_CLOSEFIGURE:
{
if (myData->pathOpen)
{
myData->path->CloseFigure();
}
}
break;
case EMR_FILLPATH:
{
if (myData->path != NULL)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, myData->path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, myData->path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, myData->path);
}
}
delete myData->path;
myData->path = NULL;
myData->pathOpen = FALSE;
}
}
break;
case EMR_STROKEANDFILLPATH:
{
if (myData->path != NULL)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, myData->path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, myData->path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, myData->path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, myData->path);
}
delete myData->path;
myData->path = NULL;
myData->pathOpen = FALSE;
}
}
break;
case EMR_STROKEPATH:
{
if (myData->path != NULL)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, myData->path);
}
delete myData->path;
myData->path = NULL;
myData->pathOpen = FALSE;
}
}
break;
case EMR_FLATTENPATH:
{
if (myData->path != NULL)
{
myData->path->Flatten(NULL);
}
}
break;
case EMR_WIDENPATH:
{
if (myData->path != NULL)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
myData->path->Widen(&pen);
}
}
break;
case EMR_SELECTCLIPPATH:
{
if (myData->path != NULL)
{
PEMRSELECTCLIPPATH pSetClipPath = (PEMRSELECTCLIPPATH)lpEMFR;
switch (pSetClipPath->iMode)
{
case RGN_COPY:
default:
g->SetClip(myData->path);
break;
case RGN_AND:
{
Gdiplus::Region region(myData->path);
g->IntersectClip(&region);
}
break;
case RGN_DIFF:
{
Gdiplus::Region region(myData->path);
Gdiplus::Region curClip;
g->GetClip(&curClip);
curClip.Exclude(&region);
g->SetClip(&curClip);
}
break;
case RGN_OR:
{
Gdiplus::Region region(myData->path);
Gdiplus::Region curClip;
g->GetClip(&curClip);
curClip.Union(&region);
g->SetClip(&curClip);
}
break;
case RGN_XOR:
{
Gdiplus::Region region(myData->path);
Gdiplus::Region curClip;
g->GetClip(&curClip);
curClip.Xor(&region);
g->SetClip(&curClip);
}
break;
}
delete myData->path;
myData->path = NULL;
myData->pathOpen = FALSE;
}
}
break;
case EMR_ABORTPATH:
{
if (myData->path != NULL)
{
delete myData->path;
myData->path = NULL;
myData->pathOpen = FALSE;
}
}
break;
case EMR_GDICOMMENT:
break;
case EMR_FILLRGN:
break;
case EMR_FRAMERGN:
break;
case EMR_INVERTRGN:
break;
case EMR_PAINTRGN:
break;
case EMR_EXTSELECTCLIPRGN:
break;
case EMR_BITBLT:
{
PEMRBITBLT pBitBlt = (PEMRBITBLT)lpEMFR;
switch (pBitBlt->dwRop)
{
case BLACKNESS:
{
Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
}
return;
case WHITENESS:
{
Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + 1), TOREAL(pBitBlt->cyDest + 1));
}
return;
default:
if (!ISSOURCEINROP3(pBitBlt->dwRop))
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
}
}
return;
}
break;
}
// Else assume SRCCOPY
BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pBitBlt) + pBitBlt->offBmiSrc);
BYTE *bits = ((BYTE *)pBitBlt) + pBitBlt->offBitsSrc;
DibStream dibStream(bmi, bits);
Gdiplus::Bitmap gpBitmap(&dibStream);
Gdiplus::RectF destRect(TOREAL(pBitBlt->xDest),
TOREAL(pBitBlt->yDest),
TOREAL(pBitBlt->cxDest),
TOREAL(pBitBlt->cyDest));
g->DrawImage(&gpBitmap, destRect,
TOREAL(pBitBlt->xSrc),
TOREAL(pBitBlt->ySrc),
TOREAL(pBitBlt->cxDest),
TOREAL(pBitBlt->cyDest),
Gdiplus::UnitPixel);
}
break;
case EMR_STRETCHBLT:
{
PEMRSTRETCHBLT pStretchBlt = (PEMRSTRETCHBLT)lpEMFR;
switch (pStretchBlt->dwRop)
{
case BLACKNESS:
{
Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
return;
case WHITENESS:
{
Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
float cx, cy;
GetPixelSize (g, &cx, &cy);
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
return;
default:
if (!ISSOURCEINROP3(pStretchBlt->dwRop))
{
float cx, cy;
GetPixelSize (g, &cx, &cy);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
}
return;
}
break;
}
// Else assume SRCCOPY
BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc);
BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc;
DibStream dibStream(bmi, bits);
Gdiplus::Bitmap gpBitmap(&dibStream);
Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest),
TOREAL(pStretchBlt->yDest),
TOREAL(pStretchBlt->cxDest),
TOREAL(pStretchBlt->cyDest));
g->DrawImage(&gpBitmap, destRect,
TOREAL(pStretchBlt->xSrc),
TOREAL(pStretchBlt->ySrc),
TOREAL(pStretchBlt->cxSrc),
TOREAL(pStretchBlt->cySrc),
Gdiplus::UnitPixel);
}
break;
case EMR_MASKBLT:
break;
case EMR_PLGBLT:
break;
case EMR_SETDIBITSTODEVICE:
break;
#if 0
typedef struct tagEMRSETDIBITSTODEVICE
{
EMR emr;
RECTL rclBounds; // Inclusive-inclusive bounds in device units
LONG xDest;
LONG yDest;
LONG xSrc;
LONG ySrc;
LONG cxSrc;
LONG cySrc;
DWORD offBmiSrc; // Offset to the source BITMAPINFO structure
DWORD cbBmiSrc; // Size of the source BITMAPINFO structure
DWORD offBitsSrc; // Offset to the source bitmap bits
DWORD cbBitsSrc; // Size of the source bitmap bits
DWORD iUsageSrc; // Source bitmap info color table usage
DWORD iStartScan;
DWORD cScans;
} EMRSETDIBITSTODEVICE, *PEMRSETDIBITSTODEVICE;
#endif
case EMR_STRETCHDIBITS:
{
PEMRSTRETCHDIBITS pStretchBlt = (PEMRSTRETCHDIBITS)lpEMFR;
switch (pStretchBlt->dwRop)
{
case BLACKNESS:
{
float cx, cy;
GetPixelSize (g, &cx, &cy);
Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
return;
case WHITENESS:
{
float cx, cy;
GetPixelSize (g, &cx, &cy);
Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
return;
default:
if (!ISSOURCEINROP3(pStretchBlt->dwRop))
{
float cx, cy;
GetPixelSize (g, &cx, &cy);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
}
}
return;
}
break;
}
// Else assume SRCCOPY
BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc);
BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc;
DibStream dibStream(bmi, bits);
Gdiplus::Bitmap gpBitmap(&dibStream);
Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest),
TOREAL(pStretchBlt->yDest),
TOREAL(pStretchBlt->cxDest),
TOREAL(pStretchBlt->cyDest));
g->DrawImage(&gpBitmap, destRect,
TOREAL(pStretchBlt->xSrc),
TOREAL(pStretchBlt->ySrc),
TOREAL(pStretchBlt->cxSrc),
TOREAL(pStretchBlt->cySrc),
Gdiplus::UnitPixel);
}
break;
case EMR_EXTCREATEFONTINDIRECTW:
break;
case EMR_EXTTEXTOUTA:
break;
case EMR_EXTTEXTOUTW:
break;
case EMR_POLYBEZIER16:
{
PEMRPOLYBEZIER16 pBezier = (PEMRPOLYBEZIER16)lpEMFR;
if (pBezier->cpts > 0)
{
int i = pBezier->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = pBezier->apts[i].x;
points[i].Y = pBezier->apts[i].y;
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawBeziers(&pen, points, pBezier->cpts);
}
}
else
{
myData->path->AddBeziers(points, pBezier->cpts);
}
delete [] points;
}
}
break;
case EMR_POLYGON16:
{
PEMRPOLYGON16 pPolygon = (PEMRPOLYGON16)lpEMFR;
if (pPolygon->cpts > 0)
{
int i = pPolygon->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = pPolygon->apts[i].x;
points[i].Y = pPolygon->apts[i].y;
} while (i > 0);
if (!myData->pathOpen)
{
Gdiplus::GraphicsPath path(myData->fillMode);
path.AddPolygon(points, pPolygon->cpts);
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
else
{
myData->path->AddPolygon(points, pPolygon->cpts);
}
delete [] points;
}
}
break;
case EMR_POLYLINE16:
{
PEMRPOLYLINE16 pPolyline = (PEMRPOLYLINE16)lpEMFR;
if (pPolyline->cpts > 0)
{
int i = pPolyline->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
do
{
i--;
points[i].X = pPolyline->apts[i].x;
points[i].Y = pPolyline->apts[i].y;
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawLines(&pen, points, pPolyline->cpts);
}
}
else
{
myData->path->AddLines(points, pPolyline->cpts);
}
delete [] points;
}
}
break;
case EMR_POLYBEZIERTO16:
{
PEMRPOLYBEZIERTO16 pBezier = (PEMRPOLYBEZIERTO16)lpEMFR;
if (pBezier->cpts > 0)
{
int i = pBezier->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
do
{
points[i].X = pBezier->apts[i-1].x;
points[i].Y = pBezier->apts[i-1].y;
i--;
} while (i > 0);
points[0] = myData->curPos;
myData->curPos = points[pBezier->cpts];
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawBeziers(&pen, points, pBezier->cpts+1);
}
}
else
{
myData->path->AddBeziers(points, pBezier->cpts+1);
}
delete [] points;
}
}
break;
case EMR_POLYLINETO16:
{
PEMRPOLYLINETO16 pPolyline = (PEMRPOLYLINETO16)lpEMFR;
if (pPolyline->cpts > 0)
{
int i = pPolyline->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
do
{
points[i].X = pPolyline->apts[i-1].x;
points[i].Y = pPolyline->apts[i-1].y;
i--;
} while (i > 0);
points[0] = myData->curPos;
myData->curPos = points[pPolyline->cpts];
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawLines(&pen, points, pPolyline->cpts+1);
}
}
else
{
myData->path->AddLines(points, pPolyline->cpts+1);
}
delete [] points;
}
}
break;
case EMR_POLYPOLYLINE16:
{
PEMRPOLYPOLYLINE16 pPolyline = (PEMRPOLYPOLYLINE16)lpEMFR;
if ((pPolyline->cpts > 0) && (pPolyline->nPolys > 0))
{
int i = pPolyline->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
POINTS * metaPoints = (POINTS *)(pPolyline->aPolyCounts + pPolyline->nPolys);
do
{
i--;
points[i].X = metaPoints[i].x;
points[i].Y = metaPoints[i].y;
} while (i > 0);
if (!myData->pathOpen)
{
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
i = 0;
Gdiplus::PointF * tmpPoints = points;
DWORD count;
do
{
count = pPolyline->aPolyCounts[i];
g->DrawLines(&pen, tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolyline->nPolys);
}
}
else
{
i = 0;
Gdiplus::PointF * tmpPoints = points;
DWORD count;
do
{
count = pPolyline->aPolyCounts[i];
myData->path->AddLines(tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolyline->nPolys);
}
delete [] points;
}
}
break;
case EMR_POLYPOLYGON16:
{
PEMRPOLYPOLYGON16 pPolygon = (PEMRPOLYPOLYGON16)lpEMFR;
if ((pPolygon->cpts > 0) && (pPolygon->nPolys > 0))
{
int i = pPolygon->cpts;
Gdiplus::PointF * points = new Gdiplus::PointF[i];
POINTS * metaPoints = (POINTS *)(pPolygon->aPolyCounts + pPolygon->nPolys);
do
{
i--;
points[i].X = metaPoints[i].x;
points[i].Y = metaPoints[i].y;
} while (i > 0);
Gdiplus::GraphicsPath path(myData->fillMode);
Gdiplus::GraphicsPath * tmpPath = &path;
if (myData->pathOpen)
{
tmpPath = myData->path;
}
Gdiplus::PointF * tmpPoints = points;
DWORD count;
i = 0;
do
{
count = pPolygon->aPolyCounts[i];
tmpPath->StartFigure();
tmpPath->AddPolygon(tmpPoints, count);
tmpPoints += count;
} while ((UINT)++i < pPolygon->nPolys);
if (!myData->pathOpen)
{
if (myData->curBrush != 0)
{
if (myData->curPatIndex < 0)
{
if (myData->curBrushPattern == NULL)
{
Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
g->FillPath(&brush, &path);
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
else
{
BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
DibBrush brush(bmi, bits);
g->FillPath(brush, &path);
}
}
if (myData->curPen != 0)
{
Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
pen.SetMiterLimit(myData->miterLimit);
g->DrawPath(&pen, &path);
}
}
delete [] points;
}
}
break;
case EMR_POLYDRAW16:
break;
case EMR_CREATEMONOBRUSH:
break;
case EMR_CREATEDIBPATTERNBRUSHPT:
{
PEMRCREATEDIBPATTERNBRUSHPT pBrush = (PEMRCREATEDIBPATTERNBRUSHPT)lpEMFR;
ASSERT(pBrush->ihBrush < myData->numObjects);
myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType;
myData->pObjects[pBrush->ihBrush].color = 0xFF808080;
myData->pObjects[pBrush->ihBrush].patIndex = -1;
delete myData->pObjects[pBrush->ihBrush].brushPattern;
myData->pObjects[pBrush->ihBrush].brushPattern = new MYPATTERNBRUSH();
if (myData->pObjects[pBrush->ihBrush].brushPattern != NULL)
{
BYTE * data = new BYTE[pBrush->cbBmi + pBrush->cbBits];
if (data != NULL)
{
memcpy(data, ((BYTE *)pBrush) + pBrush->offBmi, pBrush->cbBmi);
memcpy(data + pBrush->cbBmi, ((BYTE *)pBrush) + pBrush->offBits, pBrush->cbBits);
myData->pObjects[pBrush->ihBrush].brushPattern->bmi = (BITMAPINFO *)data;
myData->pObjects[pBrush->ihBrush].brushPattern->bitsOffset = pBrush->cbBmi;
}
else
{
delete myData->pObjects[pBrush->ihBrush].brushPattern;
myData->pObjects[pBrush->ihBrush].brushPattern = NULL;
}
}
}
break;
case EMR_EXTCREATEPEN:
{
PEMREXTCREATEPEN pPen = (PEMREXTCREATEPEN)lpEMFR;
COLORREF cRef = pPen->elp.elpColor;
ASSERT((cRef & 0x01000000) == 0);
ASSERT(pPen->ihPen < myData->numObjects);
delete myData->pObjects[pPen->ihPen].brushPattern;
myData->pObjects[pPen->ihPen].brushPattern = NULL;
myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType;
myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff,
GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
myData->pObjects[pPen->ihPen].penWidth = pPen->elp.elpWidth;
}
break;
case EMR_POLYTEXTOUTA:
break;
case EMR_POLYTEXTOUTW:
break;
case EMR_SETICMMODE:
case EMR_CREATECOLORSPACE:
case EMR_SETCOLORSPACE:
case EMR_DELETECOLORSPACE:
case EMR_GLSRECORD:
case EMR_GLSBOUNDEDRECORD:
case EMR_PIXELFORMAT:
break;
case EMR_DRAWESCAPE:
case EMR_EXTESCAPE:
case EMR_STARTDOC:
case EMR_SMALLTEXTOUT:
case EMR_FORCEUFIMAPPING:
case EMR_NAMEDESCAPE:
case EMR_COLORCORRECTPALETTE:
case EMR_SETICMPROFILEA:
case EMR_SETICMPROFILEW:
case EMR_ALPHABLEND:
case EMR_SETLAYOUT:
case EMR_TRANSPARENTBLT:
case EMR_GRADIENTFILL:
case EMR_SETLINKEDUFIS:
case EMR_SETTEXTJUSTIFICATION:
case EMR_COLORMATCHTOTARGETW:
case EMR_CREATECOLORSPACEW:
break;
}
}
BOOL StepRecord(
Gdiplus::EmfPlusRecordType recordType,
UINT recordFlags,
UINT recordDataSize,
const BYTE * recordData,
VOID * callbackData,
HDC hDC = NULL,
LPHANDLETABLE lpHTable = NULL,
LPMETARECORD lpMFR = NULL,
LPENHMETARECORD lpEMFR = NULL,
int nObj = 0
);
VOID ListRecord(
Gdiplus::EmfPlusRecordType recordType
);
/***********************************************************************
FUNCTION : EnumMFIndirect
PARAMETERS : HDC hDC
LPHANDLETABLE lpHTable
LPMETARECORD lpMFR
LPENHMETARECORD lpEMFR
int nObj
LPARAM lpData
PURPOSE : called by EnumMetaFile and EnumEnhMetaFile. Handles the stepping of
each metafile record.
MESSAGES : none
RETURNS : int
COMMENTS : ENUMMFSTEP is used whenever records are to be played,
regardless of whether you are playing records from the
list, stepping all, or stepping a range.
ENUMMFLIST is used when you need to add strings to a listbox
that describe the type of reocrd.
HISTORY : created 7/1/93 - denniscr
************************************************************************/
using Gdiplus::EmfPlusRecordType;
int EnumMFIndirect(HDC hDC, LPHANDLETABLE lpHTable,
LPMETARECORD lpMFR,
LPENHMETARECORD lpEMFR,
int nObj, LPARAM lpData)
{
BOOL DlgRet = TRUE;
//
// what is the enumeration action that we are taking?
//
switch (iEnumAction)
{
//
//if the enumeration was entered ala the step metafile menu selection
//
case ENUMMFSTEP:
if (bEnhMeta)
{
return StepRecord((EmfPlusRecordType)(lpEMFR->iType),
0, lpEMFR->nSize - sizeof(EMR),
(BYTE *)lpEMFR->dParm, (VOID *)lpData,
hDC, lpHTable, lpMFR, lpEMFR, nObj);
}
else
{
return StepRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction),
0, ((LONG)lpMFR->rdSize * 2) - 6,
((BYTE *)lpMFR) + 6, (VOID *)lpData,
hDC, lpHTable, lpMFR, lpEMFR, nObj);
}
case ENUMMFLIST:
if (bEnhMeta)
{
ListRecord((Gdiplus::EmfPlusRecordType)lpEMFR->iType);
}
else
{
ListRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction));
}
//
//keep enumerating
//
return(1);
}
return 0;
}
/***********************************************************************
FUNCTION : ConvertEMFtoWMF
PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile
LPSTR lpszFileName - filename of disked based metafile
PURPOSE : Convert an Windows metafile to an enhanced metafile
MESSAGES : none
RETURNS : int
COMMENTS :
HISTORY : created 7/22/93 - denniscr
************************************************************************/
BOOL ConvertWMFtoEMF(HMETAFILE hmf, LPSTR lpszFileName)
{
LPSTR lpWinMFBits;
UINT uiSizeBuf;
HENHMETAFILE hEnhMF;
BOOL bRet = TRUE;
//
//get the size of the Windows metafile associated with hMF
//
if ((uiSizeBuf = GetMetaFileBitsEx((HMETAFILE)hMF, 0, NULL)))
{
//
//allocate enough memory to hold metafile bits
//
lpWinMFBits = (char *)GlobalAllocPtr(GHND, uiSizeBuf);
//
//get the bits of the Windows metafile associated with hMF
//
if (lpWinMFBits && GetMetaFileBitsEx((HMETAFILE)hMF, uiSizeBuf, (LPVOID)lpWinMFBits))
{
//
//copy the bits into a memory based enhanced metafile
//
hEnhMF = SetWinMetaFileBits(uiSizeBuf, (LPBYTE)lpWinMFBits, NULL, NULL);
//
//copy the enhanced metafile to a disk based enhanced metafile
//
CopyEnhMetaFile(hEnhMF, lpszFileName);
//
//done with the memory base enhanced metafile so get rid of it
//
DeleteEnhMetaFile(hEnhMF);
//
//done with the actual memory used to store bits so nuke it
//
GlobalFreePtr(lpWinMFBits);
}
else
bRet = FALSE;
}
else
bRet = FALSE;
return (bRet);
}
/***********************************************************************
FUNCTION : ConvertEMFtoWMF
PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile
LPSTR lpszFileName - filename of disked based metafile
PURPOSE : Convert an enhanced metafile to an Windows metafile
MESSAGES : none
RETURNS : int
COMMENTS :
HISTORY : created 7/22/93 - denniscr
************************************************************************/
BOOL ConvertEMFtoWMF(HDC hrefDC, HENHMETAFILE hEMF, LPSTR lpszFileName)
{
LPSTR lpEMFBits;
UINT uiSizeBuf;
HMETAFILE hWMF;
BOOL bRet = TRUE;
DWORD dwBytesWritten ;
//
//get the size of the Windows metafile associated with hMF
//
if ((uiSizeBuf = Gdiplus::Metafile::EmfToWmfBits(hemf, 0, NULL, MM_ANISOTROPIC,
Gdiplus::EmfToWmfBitsFlagsIncludePlaceable)))
{
//
//allocate enough memory to hold metafile bits
//
lpEMFBits = (LPSTR)GlobalAllocPtr(GHND, uiSizeBuf);
//
//get the bits of the enhanced metafile associated with hEMF
//
if (lpEMFBits && Gdiplus::Metafile::EmfToWmfBits(hEMF, uiSizeBuf,(LPBYTE)lpEMFBits,
MM_ANISOTROPIC, Gdiplus::EmfToWmfBitsFlagsIncludePlaceable))
{
// Create a file and dump the metafile bits into it
HANDLE hFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if(hFile != INVALID_HANDLE_VALUE)
{
WriteFile( hFile, (LPCVOID) lpEMFBits, uiSizeBuf, &dwBytesWritten, NULL ) ;
CloseHandle(hFile);
}
/*
//
//copy the bits into a memory based Windows metafile
//
hWMF = SetMetaFileBitsEx(uiSizeBuf, (LPBYTE)lpEMFBits);
//
//copy the Windows metafile to a disk based Windows metafile
//
CopyMetaFile(hWMF, lpszFileName);
//
//done with the memory base enhanced metafile so get rid of it
//
DeleteMetaFile((HMETAFILE)hMF);
*/
//
//done with the actual memory used to store bits so nuke it
//
GlobalFreePtr(lpEMFBits);
}
else
bRet = FALSE;
}
else
bRet = FALSE;
return (bRet);
}
BOOL StepRecord(
Gdiplus::EmfPlusRecordType recordType,
UINT recordFlags,
UINT recordDataSize,
const BYTE * recordData,
VOID * callbackData,
HDC hDC,
LPHANDLETABLE lpHTable,
LPMETARECORD lpMFR,
LPENHMETARECORD lpEMFR,
int nObj
)
{
//
//keep track of the current metafile record number
//
iRecNum++;
//
//allocate memory for the record. this memory will be used by
//other functions that need to use the contents of the record
//
hMem = GlobalAlloc(GPTR /*GHND*/, (bEnhMeta) ? sizeof(EMR) + recordDataSize :
6 + recordDataSize);
//
//if the memory was successfully allocated
//
if (hMem)
{
BOOL DlgRet = TRUE;
if (bEnhMeta)
{
//
//obtain a long pointer to this memory
//
if ((lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem)) == NULL)
{
//
//we were unable to allocate memory for the record
//
MessageBox(hWndMain, "Memory allocation failed",
NULL, MB_OK | MB_ICONHAND);
}
else
{
//
//copy the contents of the record to the global memory
//
emfMetaRec.nSize = sizeof(EMR) + recordDataSize;
emfMetaRec.iType = recordType;
unsigned long i;
for (i = 0;(DWORD)i < recordDataSize / sizeof(DWORD); i++)
{
*lpEMFParams++ = ((DWORD *)recordData)[i];
}
}
}
else
{
/* obtain a long pointer to this memory */
lpMFParams = (LPPARAMETERS)GlobalLock(hMem);
/* copy the contents of the record to the global memory */
MetaRec.rdSize = (6 + recordDataSize) / 2;
MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType);
DWORD i;
for (i = 0; (DWORD)i < (recordDataSize / 2); i++)
{
*lpMFParams++ = ((WORD *)recordData)[i];
}
}
GlobalUnlock(hMem);
//
//if STEPPING through metafile records that have been selected
//by selecting the menu options Play - Step - All, Play - Step -
//Range, or selecting records from the View - List listbox
//
if ( !bPlayItAll
|| ( bEnumRange && iRecNum >= (WORD)iStartRange && iRecNum <= (WORD)iEndRange )
|| ( bPlayList && !bPlayItAll ) )
{
//
//if playing records selected from the View - List
//listbox of records
if (bPlayList)
{
//
//if playing the selected records
//
if (bPlaySelList)
{
//
//if done playing the selected records then stop the enumeration
//
if (iCount == iNumSel)
{
return(0);
}
//
//if this is a selected record then play it
//
if ((WORD)lpSelMem[iCount] == iRecNum - 1)
{
//
//initialize flag
//
bPlayRec = FALSE;
//
//increment the count
//
iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
//
//call the dialog box that lets you play or ignore this record */
//
DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
}
else
{
//
//initialize flag and do nothing else
//
bPlayRec = FALSE;
}
}
//
//playing the unselected records
//
else
{
//
//if this is one of the selected records then increment
//the record count and init a flag but do nothing else
//
if ((WORD)lpSelMem[iCount] == iRecNum - 1)
{
//
//set count to next selected record in listbox
//
iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
bPlayRec = FALSE;
}
//
//this is not one of the selected records which is what we
//want in this case. So, init a flag give the user the
//opportunity to play the record
//
else
{
bPlayRec = FALSE;
DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
}
}
} //bPlayList
//
//stepping records from the Play - Step menu option
//
else
{
//
//init a flag and show the record contents
//
bPlayRec = FALSE;
iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
}
} //end of STEPPING the metafile
//
//bPlayItAll is TRUE. This is set when the user either
//selects the menu option Play - All or pushes the GO button
//in the view record dialog box
//
else
{
//
//we were stepping records selected from the listbox and
//the user pressed the GO button
//
//Don't bother returning 0 to stop enumeration. We need to
//play to the end of the metafile in this case anyway
//
if (bPlayList)
{
//
//we were playing the selected records
//
if (bPlaySelList)
{
//
//if all of the selected records have been played then
//stop the enumeration
//
if (iCount == iNumSel)
{
return(0);
}
//
//set bPlayRec so the record will be played without user
//interation and then update the record counter
//
if ((WORD)lpSelMem[iCount] == iRecNum - 1)
{
bPlayRec = TRUE;
iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
}
else
//
//it wasn't one of the selected records so don't play
//
{
bPlayRec = FALSE;
}
}
//
//we were playing the unselected records
//
else
{
//
//if it is a selected record then set bPlayRec to FALSE
//so the record is not played
//
if ((WORD)lpSelMem[iCount] == iRecNum - 1)
{
bPlayRec = FALSE;
iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
}
else
{
//
//play the record
//
bPlayRec = TRUE;
}
}
} //bPlayList
} //GO button pushed
//
//Stop the enumeration if you were stepping a range and have
//finished playing that range OR the user selected pushed
//the STOP button in the view record dialog box
//
if ( ((bEnumRange) && (iRecNum > (WORD)iEndRange)) || (!DlgRet) )
{
bPlayRec = FALSE;
//
//stop enumeration
//
return(0);
}
} //if (hMem)
else
//
//we were unable to allocate memory for the record
//
{
MessageBox(hWndMain, "Memory allocation failed",
NULL, MB_OK | MB_ICONHAND);
}
//
//Regardless of the method the user elected to play the
//records, check the flag. If it is set then play the
//record
//
if (bPlayRec)
{
if (bUseGdiPlusToPlay)
{
((MYDATA *)callbackData)->metafile->PlayRecord(recordType, recordFlags, recordDataSize, recordData);
}
else if (bEnhMeta)
{
if (bConvertToGdiPlus)
{
GpPlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj, (LPARAM)callbackData);
}
else
{
PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj);
}
}
else if(!PlayMetaFileRecord(hDC, lpHTable, lpMFR, (UINT)nObj))
{
ASSERT(FALSE);
}
}
//
//done with the record so get rid of it
//
GlobalFree(hMem);
//
//if we made it this far then continue the enumeration
//
return(1);
}
VOID ListRecord(
Gdiplus::EmfPlusRecordType recordType
)
{
char szMetaFunction[100];
iRecNum++;
//
//format the listbox string
//
wsprintf((LPSTR)szMetaFunction, (LPSTR)"%d - ", iRecNum);
//
//get the function number contained in the record
//
if (bEnhMeta)
emfMetaRec.iType = recordType;
else
MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType);
//
//lookup the function number in the structure MetaFunctions
//
int i;
if (bEnhMeta)
{
for (i = NUMMETAFUNCTIONS; i < NUMENHMETARECORDS; i++)
{
if (recordType == (INT)emfMetaRecords[i].iType)
break;
}
}
else // WMF
{
for (i = 0; i < NUMMETAFUNCTIONS; i++)
{
if (recordType == (INT)emfMetaRecords[i].iType)
break;
}
}
//
//if the function number is not found then describe this record
//as an "Unknown" type otherwise use the corresponding name
//found in the lookup
//
if (recordType != (INT)emfMetaRecords[i].iType)
lstrcat((LPSTR)szMetaFunction, (LPSTR)"Unknown");
else
lstrcat((LPSTR)szMetaFunction,(LPSTR)emfMetaRecords[i].szRecordName);
//
//add the string to the listbox
//
SendDlgItemMessage((HWND)CurrenthDlg, IDL_LBREC, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)szMetaFunction);
}
extern "C"
BOOL CALLBACK
PlayGdipMetafileRecordCallback(
Gdiplus::EmfPlusRecordType recordType,
UINT recordFlags,
UINT recordDataSize,
const BYTE * recordData,
VOID * callbackData
)
{
switch (iEnumAction)
{
case ENUMMFSTEP:
return StepRecord(recordType, recordFlags, recordDataSize, recordData, callbackData);
case ENUMMFLIST:
ListRecord(recordType);
break;
}
return TRUE;
}
/***********************************************************************
FUNCTION : GetMetaFileAndEnum
PARAMETERS : HDC hDC
PURPOSE : load the metafile if it has not already been loaded and
begin enumerating it
CALLS : WINDOWS
GetMetaFile
MakeProcInstance
EnumMetaFile
FreeProcInstance
DeleteMetaFile
MessageBox
MESSAGES : none
RETURNS : void
COMMENTS :
HISTORY : 1/16/91 - created - drc
7/1/93 - modified to work with EMFs - denniscr
************************************************************************/
extern "C"
void GetMetaFileAndEnum(
HWND hwnd,
HDC hDC,
int iAction)
{
MYDATA myData(hwnd);
iEnumAction = iAction;
//
//if this is an enhanced metafile (emf)
//
RECT rc;
GetClientRect(hWndMain, &rc);
HPALETTE hpal = NULL;
if (bEnhMeta)
{
if (hemf)
{
LPLOGPALETTE lpLogPal;
HPALETTE hPal;
int i;
//
//allocate memory for the logical palette including the array of
//palette entries
//
lpLogPal = (LPLOGPALETTE) GlobalAllocPtr( GHND, sizeof(LOGPALETTE) +
(sizeof (PALETTEENTRY) * EmfPtr.palNumEntries));
if (lpLogPal)
{
//
//proceed only if there is a valid ptr to logical palette
//and a palette array obtained from the emf
//
if (EmfPtr.lpPal)
{
lpLogPal->palVersion = 0x300;
lpLogPal->palNumEntries = EmfPtr.palNumEntries;
//
//copy palette entries into palentry array
//
for (i = 0; i < EmfPtr.palNumEntries; i++)
lpLogPal->palPalEntry[i] = *EmfPtr.lpPal++;
//
//reposition the ptr back to the beginning should we call this
//code again
//
EmfPtr.lpPal -= EmfPtr.palNumEntries;
//
//create, select and realize the palette
//
if ((hPal = CreatePalette((LPLOGPALETTE)lpLogPal)))
{
SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
}
}
if (bUseGdiPlusToPlay)
{
// Select in the halftone palette for 256-color display mode testing
hpal = Gdiplus::Graphics::GetHalftonePalette();
SelectPalette(hDC, hpal, FALSE);
RealizePalette(hDC);
// Need to delete this before returning;
myData.g = Gdiplus::Graphics::FromHDC(hDC);
myData.g->SetPixelOffsetMode(Gdiplus::PixelOffsetModeHalf);
myData.g->SetInterpolationMode(Gdiplus::InterpolationModeNearestNeighbor);
}
//
//enumerate the EMF. this is a bit odd simply because PlayEnhMetaFile
//really obviates the need for doing this (this cannot be said for WMFs).
//this app does it simply because it may be stepping the metafile records.
//Most apps are generally not concerned about doing this.
//
if (bUseGdiPlusToPlay && (myData.g != NULL))
{
Gdiplus::Metafile m1(hemf);
Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
myData.metafile = &m1;
if(myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok)
MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
myData.metafile = NULL;
}
else
{
// the rect needs to be inclusive-inclusive!!!
rc.right--;
rc.bottom--;
if(!EnumEnhMetaFile(hDC, hemf, (ENHMFENUMPROC)EnhMetaFileEnumProc, (void*)&myData, &rc))
MessageBox(NULL, "Error", "An Error Occured while playing this metafile", MB_OK | MB_ICONERROR);
}
//
//free palette memory
//
GlobalFreePtr(lpLogPal);
}
}
}
else
{
//
//if there is a valid handle to a metafile begin enumerating it
//
if (hMF)
{
if (bUseGdiPlusToPlay)
{
// Select in the halftone palette for 256-color display mode testing
hpal = Gdiplus::Graphics::GetHalftonePalette();
SelectPalette(hDC, hpal, FALSE);
RealizePalette(hDC);
// Need to delete this before returning;
myData.g = Gdiplus::Graphics::FromHDC(hDC);
}
if (bUseGdiPlusToPlay && (myData.g != NULL))
{
Gdiplus::WmfPlaceableFileHeader * wmfPlaceableFileHeader = NULL;
if (bPlaceableMeta)
{
wmfPlaceableFileHeader = (Gdiplus::WmfPlaceableFileHeader *)&placeableWMFHeader;
}
Gdiplus::Metafile m1((HMETAFILE)hMF, wmfPlaceableFileHeader);
Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
myData.metafile = &m1;
if (myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok)
MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
myData.metafile = NULL;
}
else
{
if (!EnumMetaFile(hDC, (HMETAFILE)hMF, (MFENUMPROC) MetaEnumProc, (LPARAM) 0))
MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
}
}
else
MessageBox(hWndMain, "Invalid metafile handle",
NULL, MB_OK | MB_ICONHAND);
}
if (myData.g != NULL )
{
SelectObject(hDC, GetStockObject(DEFAULT_PALETTE));
DeleteObject(hpal);
myData.g->Flush();
delete myData.g;
myData.g = NULL;
}
return;
}