Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5978 lines
207 KiB

  1. /***********************************************************************
  2. MODULE : WMFMETA.CPP
  3. FUNCTIONS : MetaEnumProc
  4. GetMetaFileAndEnum
  5. LoadParameterLB
  6. PlayMetaFileToDest
  7. RenderClipMeta
  8. RenderPlaceableMeta
  9. SetPlaceableExts
  10. SetClipMetaExts
  11. ProcessFile
  12. COMMENTS :
  13. ************************************************************************/
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include <objbase.h>
  20. extern "C" {
  21. #include "mfdcod32.h"
  22. }
  23. extern "C" {
  24. extern BOOL bConvertToGdiPlus;
  25. extern BOOL bUseGdiPlusToPlay;
  26. }
  27. #include "GdiPlus.h"
  28. #include "MyData.hpp"
  29. #include "dibstream.hpp"
  30. #include "../gpinit.inc"
  31. #ifndef ASSERT
  32. #ifdef _DEBUG // poor man's assert
  33. #define ASSERT(cond) if (!(cond)) { int b = 0; b = 1 / b; }
  34. #else
  35. #define ASSERT(cond)
  36. #endif
  37. #endif
  38. // Check if a source is needed in a 3-way bitblt operation.
  39. // This works on both rop and rop3. We assume that a rop contains zero
  40. // in the high byte.
  41. //
  42. // This is tested by comparing the rop result bits with source (column A
  43. // below) vs. those without source (column B). If the two cases are
  44. // identical, then the effect of the rop does not depend on the source
  45. // and we don't need a source device. Recall the rop construction from
  46. // input (pattern, source, target --> result):
  47. //
  48. // P S T | R A B mask for A = 0CCh
  49. // ------+-------- mask for B = 33h
  50. // 0 0 0 | x 0 x
  51. // 0 0 1 | x 0 x
  52. // 0 1 0 | x x 0
  53. // 0 1 1 | x x 0
  54. // 1 0 0 | x 0 x
  55. // 1 0 1 | x 0 x
  56. // 1 1 0 | x x 0
  57. // 1 1 1 | x x 0
  58. #define ISSOURCEINROP3(rop3) \
  59. (((rop3) & 0xCCCC0000) != (((rop3) << 2) & 0xCCCC0000))
  60. #ifndef EMR_SETICMMODE
  61. #define EMR_SETICMMODE 98
  62. #define EMR_CREATECOLORSPACE 99
  63. #define EMR_SETCOLORSPACE 100
  64. #define EMR_DELETECOLORSPACE 101
  65. #define EMR_GLSRECORD 102
  66. #define EMR_GLSBOUNDEDRECORD 103
  67. #define EMR_PIXELFORMAT 104
  68. #endif
  69. #ifndef EMR_DRAWESCAPE
  70. #define EMR_DRAWESCAPE 105
  71. #define EMR_EXTESCAPE 106
  72. #define EMR_STARTDOC 107
  73. #define EMR_SMALLTEXTOUT 108
  74. #define EMR_FORCEUFIMAPPING 109
  75. #define EMR_NAMEDESCAPE 110
  76. #define EMR_COLORCORRECTPALETTE 111
  77. #define EMR_SETICMPROFILEA 112
  78. #define EMR_SETICMPROFILEW 113
  79. #define EMR_ALPHABLEND 114
  80. #define EMR_SETLAYOUT 115
  81. #define EMR_TRANSPARENTBLT 116
  82. #define EMR_GRADIENTFILL 118
  83. #define EMR_SETLINKEDUFIS 119
  84. #define EMR_SETTEXTJUSTIFICATION 120
  85. #define EMR_COLORMATCHTOTARGETW 121
  86. #define EMR_CREATECOLORSPACEW 122
  87. #endif
  88. #define TOREAL(i) (static_cast<float>(i))
  89. //
  90. // Wrap a GDI+ TextureBrush object around DIB data
  91. //
  92. class DibBrush
  93. {
  94. public:
  95. DibBrush(const BITMAPINFO* bmi, const BYTE* bits) :
  96. dibStream(bmi, bits),
  97. bitmap(&dibStream),
  98. brush(&bitmap)
  99. {
  100. }
  101. operator Gdiplus::TextureBrush*()
  102. {
  103. return &brush;
  104. }
  105. private:
  106. DibStream dibStream;
  107. Gdiplus::Bitmap bitmap;
  108. Gdiplus::TextureBrush brush;
  109. };
  110. //
  111. //lookup table for EMF and WMF metafile records
  112. //
  113. EMFMETARECORDS emfMetaRecords[] = {
  114. "WmfSetBkColor" , Gdiplus::WmfRecordTypeSetBkColor ,
  115. "WmfSetBkMode" , Gdiplus::WmfRecordTypeSetBkMode ,
  116. "WmfSetMapMode" , Gdiplus::WmfRecordTypeSetMapMode ,
  117. "WmfSetROP2" , Gdiplus::WmfRecordTypeSetROP2 ,
  118. "WmfSetRelAbs" , Gdiplus::WmfRecordTypeSetRelAbs ,
  119. "WmfSetPolyFillMode" , Gdiplus::WmfRecordTypeSetPolyFillMode ,
  120. "WmfSetStretchBltMode" , Gdiplus::WmfRecordTypeSetStretchBltMode ,
  121. "WmfSetTextCharExtra" , Gdiplus::WmfRecordTypeSetTextCharExtra ,
  122. "WmfSetTextColor" , Gdiplus::WmfRecordTypeSetTextColor ,
  123. "WmfSetTextJustification" , Gdiplus::WmfRecordTypeSetTextJustification ,
  124. "WmfSetWindowOrg" , Gdiplus::WmfRecordTypeSetWindowOrg ,
  125. "WmfSetWindowExt" , Gdiplus::WmfRecordTypeSetWindowExt ,
  126. "WmfSetViewportOrg" , Gdiplus::WmfRecordTypeSetViewportOrg ,
  127. "WmfSetViewportExt" , Gdiplus::WmfRecordTypeSetViewportExt ,
  128. "WmfOffsetWindowOrg" , Gdiplus::WmfRecordTypeOffsetWindowOrg ,
  129. "WmfScaleWindowExt" , Gdiplus::WmfRecordTypeScaleWindowExt ,
  130. "WmfOffsetViewportOrg" , Gdiplus::WmfRecordTypeOffsetViewportOrg ,
  131. "WmfScaleViewportExt" , Gdiplus::WmfRecordTypeScaleViewportExt ,
  132. "WmfLineTo" , Gdiplus::WmfRecordTypeLineTo ,
  133. "WmfMoveTo" , Gdiplus::WmfRecordTypeMoveTo ,
  134. "WmfExcludeClipRect" , Gdiplus::WmfRecordTypeExcludeClipRect ,
  135. "WmfIntersectClipRect" , Gdiplus::WmfRecordTypeIntersectClipRect ,
  136. "WmfArc" , Gdiplus::WmfRecordTypeArc ,
  137. "WmfEllipse" , Gdiplus::WmfRecordTypeEllipse ,
  138. "WmfFloodFill" , Gdiplus::WmfRecordTypeFloodFill ,
  139. "WmfPie" , Gdiplus::WmfRecordTypePie ,
  140. "WmfRectangle" , Gdiplus::WmfRecordTypeRectangle ,
  141. "WmfRoundRect" , Gdiplus::WmfRecordTypeRoundRect ,
  142. "WmfPatBlt" , Gdiplus::WmfRecordTypePatBlt ,
  143. "WmfSaveDC" , Gdiplus::WmfRecordTypeSaveDC ,
  144. "WmfSetPixel" , Gdiplus::WmfRecordTypeSetPixel ,
  145. "WmfOffsetClipRgn" , Gdiplus::WmfRecordTypeOffsetClipRgn ,
  146. "WmfTextOut" , Gdiplus::WmfRecordTypeTextOut ,
  147. "WmfBitBlt" , Gdiplus::WmfRecordTypeBitBlt ,
  148. "WmfStretchBlt" , Gdiplus::WmfRecordTypeStretchBlt ,
  149. "WmfPolygon" , Gdiplus::WmfRecordTypePolygon ,
  150. "WmfPolyline" , Gdiplus::WmfRecordTypePolyline ,
  151. "WmfEscape" , Gdiplus::WmfRecordTypeEscape ,
  152. "WmfRestoreDC" , Gdiplus::WmfRecordTypeRestoreDC ,
  153. "WmfFillRegion" , Gdiplus::WmfRecordTypeFillRegion ,
  154. "WmfFrameRegion" , Gdiplus::WmfRecordTypeFrameRegion ,
  155. "WmfInvertRegion" , Gdiplus::WmfRecordTypeInvertRegion ,
  156. "WmfPaintRegion" , Gdiplus::WmfRecordTypePaintRegion ,
  157. "WmfSelectClipRegion" , Gdiplus::WmfRecordTypeSelectClipRegion ,
  158. "WmfSelectObject" , Gdiplus::WmfRecordTypeSelectObject ,
  159. "WmfSetTextAlign" , Gdiplus::WmfRecordTypeSetTextAlign ,
  160. "WmfDrawText" , Gdiplus::WmfRecordTypeDrawText ,
  161. "WmfChord" , Gdiplus::WmfRecordTypeChord ,
  162. "WmfSetMapperFlags" , Gdiplus::WmfRecordTypeSetMapperFlags ,
  163. "WmfExtTextOut" , Gdiplus::WmfRecordTypeExtTextOut ,
  164. "WmfSetDIBToDev" , Gdiplus::WmfRecordTypeSetDIBToDev ,
  165. "WmfSelectPalette" , Gdiplus::WmfRecordTypeSelectPalette ,
  166. "WmfRealizePalette" , Gdiplus::WmfRecordTypeRealizePalette ,
  167. "WmfAnimatePalette" , Gdiplus::WmfRecordTypeAnimatePalette ,
  168. "WmfSetPalEntries" , Gdiplus::WmfRecordTypeSetPalEntries ,
  169. "WmfPolyPolygon" , Gdiplus::WmfRecordTypePolyPolygon ,
  170. "WmfResizePalette" , Gdiplus::WmfRecordTypeResizePalette ,
  171. "WmfDIBBitBlt" , Gdiplus::WmfRecordTypeDIBBitBlt ,
  172. "WmfDIBStretchBlt" , Gdiplus::WmfRecordTypeDIBStretchBlt ,
  173. "WmfDIBCreatePatternBrush" , Gdiplus::WmfRecordTypeDIBCreatePatternBrush ,
  174. "WmfStretchDIB" , Gdiplus::WmfRecordTypeStretchDIB ,
  175. "WmfExtFloodFill" , Gdiplus::WmfRecordTypeExtFloodFill ,
  176. "WmfSetLayout" , Gdiplus::WmfRecordTypeSetLayout ,
  177. "WmfResetDC" , Gdiplus::WmfRecordTypeResetDC ,
  178. "WmfStartDoc" , Gdiplus::WmfRecordTypeStartDoc ,
  179. "WmfStartPage" , Gdiplus::WmfRecordTypeStartPage ,
  180. "WmfEndPage" , Gdiplus::WmfRecordTypeEndPage ,
  181. "WmfAbortDoc" , Gdiplus::WmfRecordTypeAbortDoc ,
  182. "WmfEndDoc" , Gdiplus::WmfRecordTypeEndDoc ,
  183. "WmfDeleteObject" , Gdiplus::WmfRecordTypeDeleteObject ,
  184. "WmfCreatePalette" , Gdiplus::WmfRecordTypeCreatePalette ,
  185. "WmfCreateBrush" , Gdiplus::WmfRecordTypeCreateBrush ,
  186. "WmfCreatePatternBrush" , Gdiplus::WmfRecordTypeCreatePatternBrush ,
  187. "WmfCreatePenIndirect" , Gdiplus::WmfRecordTypeCreatePenIndirect ,
  188. "WmfCreateFontIndirect" , Gdiplus::WmfRecordTypeCreateFontIndirect ,
  189. "WmfCreateBrushIndirect" , Gdiplus::WmfRecordTypeCreateBrushIndirect ,
  190. "WmfCreateBitmapIndirect" , Gdiplus::WmfRecordTypeCreateBitmapIndirect ,
  191. "WmfCreateBitmap" , Gdiplus::WmfRecordTypeCreateBitmap ,
  192. "WmfCreateRegion" , Gdiplus::WmfRecordTypeCreateRegion ,
  193. "EmfHeader" , Gdiplus::EmfRecordTypeHeader ,
  194. "EmfPolyBezier" , Gdiplus::EmfRecordTypePolyBezier ,
  195. "EmfPolygon" , Gdiplus::EmfRecordTypePolygon ,
  196. "EmfPolyline" , Gdiplus::EmfRecordTypePolyline ,
  197. "EmfPolyBezierTo" , Gdiplus::EmfRecordTypePolyBezierTo ,
  198. "EmfPolyLineTo" , Gdiplus::EmfRecordTypePolyLineTo ,
  199. "EmfPolyPolyline" , Gdiplus::EmfRecordTypePolyPolyline ,
  200. "EmfPolyPolygon" , Gdiplus::EmfRecordTypePolyPolygon ,
  201. "EmfSetWindowExtEx" , Gdiplus::EmfRecordTypeSetWindowExtEx ,
  202. "EmfSetWindowOrgEx" , Gdiplus::EmfRecordTypeSetWindowOrgEx ,
  203. "EmfSetViewportExtEx" , Gdiplus::EmfRecordTypeSetViewportExtEx ,
  204. "EmfSetViewportOrgEx" , Gdiplus::EmfRecordTypeSetViewportOrgEx ,
  205. "EmfSetBrushOrgEx" , Gdiplus::EmfRecordTypeSetBrushOrgEx ,
  206. "EmfEOF" , Gdiplus::EmfRecordTypeEOF ,
  207. "EmfSetPixelV" , Gdiplus::EmfRecordTypeSetPixelV ,
  208. "EmfSetMapperFlags" , Gdiplus::EmfRecordTypeSetMapperFlags ,
  209. "EmfSetMapMode" , Gdiplus::EmfRecordTypeSetMapMode ,
  210. "EmfSetBkMode" , Gdiplus::EmfRecordTypeSetBkMode ,
  211. "EmfSetPolyFillMode" , Gdiplus::EmfRecordTypeSetPolyFillMode ,
  212. "EmfSetROP2" , Gdiplus::EmfRecordTypeSetROP2 ,
  213. "EmfSetStretchBltMode" , Gdiplus::EmfRecordTypeSetStretchBltMode ,
  214. "EmfSetTextAlign" , Gdiplus::EmfRecordTypeSetTextAlign ,
  215. "EmfSetColorAdjustment" , Gdiplus::EmfRecordTypeSetColorAdjustment ,
  216. "EmfSetTextColor" , Gdiplus::EmfRecordTypeSetTextColor ,
  217. "EmfSetBkColor" , Gdiplus::EmfRecordTypeSetBkColor ,
  218. "EmfOffsetClipRgn" , Gdiplus::EmfRecordTypeOffsetClipRgn ,
  219. "EmfMoveToEx" , Gdiplus::EmfRecordTypeMoveToEx ,
  220. "EmfSetMetaRgn" , Gdiplus::EmfRecordTypeSetMetaRgn ,
  221. "EmfExcludeClipRect" , Gdiplus::EmfRecordTypeExcludeClipRect ,
  222. "EmfIntersectClipRect" , Gdiplus::EmfRecordTypeIntersectClipRect ,
  223. "EmfScaleViewportExtEx" , Gdiplus::EmfRecordTypeScaleViewportExtEx ,
  224. "EmfScaleWindowExtEx" , Gdiplus::EmfRecordTypeScaleWindowExtEx ,
  225. "EmfSaveDC" , Gdiplus::EmfRecordTypeSaveDC ,
  226. "EmfRestoreDC" , Gdiplus::EmfRecordTypeRestoreDC ,
  227. "EmfSetWorldTransform" , Gdiplus::EmfRecordTypeSetWorldTransform ,
  228. "EmfModifyWorldTransform" , Gdiplus::EmfRecordTypeModifyWorldTransform ,
  229. "EmfSelectObject" , Gdiplus::EmfRecordTypeSelectObject ,
  230. "EmfCreatePen" , Gdiplus::EmfRecordTypeCreatePen ,
  231. "EmfCreateBrushIndirect" , Gdiplus::EmfRecordTypeCreateBrushIndirect ,
  232. "EmfDeleteObject" , Gdiplus::EmfRecordTypeDeleteObject ,
  233. "EmfAngleArc" , Gdiplus::EmfRecordTypeAngleArc ,
  234. "EmfEllipse" , Gdiplus::EmfRecordTypeEllipse ,
  235. "EmfRectangle" , Gdiplus::EmfRecordTypeRectangle ,
  236. "EmfRoundRect" , Gdiplus::EmfRecordTypeRoundRect ,
  237. "EmfArc" , Gdiplus::EmfRecordTypeArc ,
  238. "EmfChord" , Gdiplus::EmfRecordTypeChord ,
  239. "EmfPie" , Gdiplus::EmfRecordTypePie ,
  240. "EmfSelectPalette" , Gdiplus::EmfRecordTypeSelectPalette ,
  241. "EmfCreatePalette" , Gdiplus::EmfRecordTypeCreatePalette ,
  242. "EmfSetPaletteEntries" , Gdiplus::EmfRecordTypeSetPaletteEntries ,
  243. "EmfResizePalette" , Gdiplus::EmfRecordTypeResizePalette ,
  244. "EmfRealizePalette" , Gdiplus::EmfRecordTypeRealizePalette ,
  245. "EmfExtFloodFill" , Gdiplus::EmfRecordTypeExtFloodFill ,
  246. "EmfLineTo" , Gdiplus::EmfRecordTypeLineTo ,
  247. "EmfArcTo" , Gdiplus::EmfRecordTypeArcTo ,
  248. "EmfPolyDraw" , Gdiplus::EmfRecordTypePolyDraw ,
  249. "EmfSetArcDirection" , Gdiplus::EmfRecordTypeSetArcDirection ,
  250. "EmfSetMiterLimit" , Gdiplus::EmfRecordTypeSetMiterLimit ,
  251. "EmfBeginPath" , Gdiplus::EmfRecordTypeBeginPath ,
  252. "EmfEndPath" , Gdiplus::EmfRecordTypeEndPath ,
  253. "EmfCloseFigure" , Gdiplus::EmfRecordTypeCloseFigure ,
  254. "EmfFillPath" , Gdiplus::EmfRecordTypeFillPath ,
  255. "EmfStrokeAndFillPath" , Gdiplus::EmfRecordTypeStrokeAndFillPath ,
  256. "EmfStrokePath" , Gdiplus::EmfRecordTypeStrokePath ,
  257. "EmfFlattenPath" , Gdiplus::EmfRecordTypeFlattenPath ,
  258. "EmfWidenPath" , Gdiplus::EmfRecordTypeWidenPath ,
  259. "EmfSelectClipPath" , Gdiplus::EmfRecordTypeSelectClipPath ,
  260. "EmfAbortPath" , Gdiplus::EmfRecordTypeAbortPath ,
  261. "EmfReserved_069" , Gdiplus::EmfRecordTypeReserved_069 ,
  262. "EmfGdiComment" , Gdiplus::EmfRecordTypeGdiComment ,
  263. "EmfFillRgn" , Gdiplus::EmfRecordTypeFillRgn ,
  264. "EmfFrameRgn" , Gdiplus::EmfRecordTypeFrameRgn ,
  265. "EmfInvertRgn" , Gdiplus::EmfRecordTypeInvertRgn ,
  266. "EmfPaintRgn" , Gdiplus::EmfRecordTypePaintRgn ,
  267. "EmfExtSelectClipRgn" , Gdiplus::EmfRecordTypeExtSelectClipRgn ,
  268. "EmfBitBlt" , Gdiplus::EmfRecordTypeBitBlt ,
  269. "EmfStretchBlt" , Gdiplus::EmfRecordTypeStretchBlt ,
  270. "EmfMaskBlt" , Gdiplus::EmfRecordTypeMaskBlt ,
  271. "EmfPlgBlt" , Gdiplus::EmfRecordTypePlgBlt ,
  272. "EmfSetDIBitsToDevice" , Gdiplus::EmfRecordTypeSetDIBitsToDevice ,
  273. "EmfStretchDIBits" , Gdiplus::EmfRecordTypeStretchDIBits ,
  274. "EmfExtCreateFontIndirect" , Gdiplus::EmfRecordTypeExtCreateFontIndirect ,
  275. "EmfExtTextOutA" , Gdiplus::EmfRecordTypeExtTextOutA ,
  276. "EmfExtTextOutW" , Gdiplus::EmfRecordTypeExtTextOutW ,
  277. "EmfPolyBezier16" , Gdiplus::EmfRecordTypePolyBezier16 ,
  278. "EmfPolygon16" , Gdiplus::EmfRecordTypePolygon16 ,
  279. "EmfPolyline16" , Gdiplus::EmfRecordTypePolyline16 ,
  280. "EmfPolyBezierTo16" , Gdiplus::EmfRecordTypePolyBezierTo16 ,
  281. "EmfPolylineTo16" , Gdiplus::EmfRecordTypePolylineTo16 ,
  282. "EmfPolyPolyline16" , Gdiplus::EmfRecordTypePolyPolyline16 ,
  283. "EmfPolyPolygon16" , Gdiplus::EmfRecordTypePolyPolygon16 ,
  284. "EmfPolyDraw16" , Gdiplus::EmfRecordTypePolyDraw16 ,
  285. "EmfCreateMonoBrush" , Gdiplus::EmfRecordTypeCreateMonoBrush ,
  286. "EmfCreateDIBPatternBrushPt" , Gdiplus::EmfRecordTypeCreateDIBPatternBrushPt ,
  287. "EmfExtCreatePen" , Gdiplus::EmfRecordTypeExtCreatePen ,
  288. "EmfPolyTextOutA" , Gdiplus::EmfRecordTypePolyTextOutA ,
  289. "EmfPolyTextOutW" , Gdiplus::EmfRecordTypePolyTextOutW ,
  290. "EmfSetICMMode" , Gdiplus::EmfRecordTypeSetICMMode ,
  291. "EmfCreateColorSpace" , Gdiplus::EmfRecordTypeCreateColorSpace ,
  292. "EmfSetColorSpace" , Gdiplus::EmfRecordTypeSetColorSpace ,
  293. "EmfDeleteColorSpace" , Gdiplus::EmfRecordTypeDeleteColorSpace ,
  294. "EmfGLSRecord" , Gdiplus::EmfRecordTypeGLSRecord ,
  295. "EmfGLSBoundedRecord" , Gdiplus::EmfRecordTypeGLSBoundedRecord ,
  296. "EmfPixelFormat" , Gdiplus::EmfRecordTypePixelFormat ,
  297. "EmfDrawEscape" , Gdiplus::EmfRecordTypeDrawEscape ,
  298. "EmfExtEscape" , Gdiplus::EmfRecordTypeExtEscape ,
  299. "EmfStartDoc" , Gdiplus::EmfRecordTypeStartDoc ,
  300. "EmfSmallTextOut" , Gdiplus::EmfRecordTypeSmallTextOut ,
  301. "EmfForceUFIMapping" , Gdiplus::EmfRecordTypeForceUFIMapping ,
  302. "EmfNamedEscape" , Gdiplus::EmfRecordTypeNamedEscape ,
  303. "EmfColorCorrectPalette" , Gdiplus::EmfRecordTypeColorCorrectPalette ,
  304. "EmfSetICMProfileA" , Gdiplus::EmfRecordTypeSetICMProfileA ,
  305. "EmfSetICMProfileW" , Gdiplus::EmfRecordTypeSetICMProfileW ,
  306. "EmfAlphaBlend" , Gdiplus::EmfRecordTypeAlphaBlend ,
  307. "EmfSetLayout" , Gdiplus::EmfRecordTypeSetLayout ,
  308. "EmfTransparentBlt" , Gdiplus::EmfRecordTypeTransparentBlt ,
  309. "EmfReserved_117" , Gdiplus::EmfRecordTypeReserved_117 ,
  310. "EmfGradientFill" , Gdiplus::EmfRecordTypeGradientFill ,
  311. "EmfSetLinkedUFIs" , Gdiplus::EmfRecordTypeSetLinkedUFIs ,
  312. "EmfSetTextJustification" , Gdiplus::EmfRecordTypeSetTextJustification ,
  313. "EmfColorMatchToTargetW" , Gdiplus::EmfRecordTypeColorMatchToTargetW ,
  314. "EmfCreateColorSpaceW" , Gdiplus::EmfRecordTypeCreateColorSpaceW ,
  315. "EmfPlusHeader" , Gdiplus::EmfPlusRecordTypeHeader ,
  316. "EmfPlusEndOfFile" , Gdiplus::EmfPlusRecordTypeEndOfFile ,
  317. "EmfPlusComment" , Gdiplus::EmfPlusRecordTypeComment ,
  318. "EmfPlusGetDC" , Gdiplus::EmfPlusRecordTypeGetDC ,
  319. "EmfPlusMultiFormatStart" , Gdiplus::EmfPlusRecordTypeMultiFormatStart ,
  320. "EmfPlusMultiFormatSection" , Gdiplus::EmfPlusRecordTypeMultiFormatSection ,
  321. "EmfPlusMultiFormatEnd" , Gdiplus::EmfPlusRecordTypeMultiFormatEnd ,
  322. "EmfPlusObject" , Gdiplus::EmfPlusRecordTypeObject ,
  323. "EmfPlusClear" , Gdiplus::EmfPlusRecordTypeClear ,
  324. "EmfPlusFillRects" , Gdiplus::EmfPlusRecordTypeFillRects ,
  325. "EmfPlusDrawRects" , Gdiplus::EmfPlusRecordTypeDrawRects ,
  326. "EmfPlusFillPolygon" , Gdiplus::EmfPlusRecordTypeFillPolygon ,
  327. "EmfPlusDrawLines" , Gdiplus::EmfPlusRecordTypeDrawLines ,
  328. "EmfPlusFillEllipse" , Gdiplus::EmfPlusRecordTypeFillEllipse ,
  329. "EmfPlusDrawEllipse" , Gdiplus::EmfPlusRecordTypeDrawEllipse ,
  330. "EmfPlusFillPie" , Gdiplus::EmfPlusRecordTypeFillPie ,
  331. "EmfPlusDrawPie" , Gdiplus::EmfPlusRecordTypeDrawPie ,
  332. "EmfPlusDrawArc" , Gdiplus::EmfPlusRecordTypeDrawArc ,
  333. "EmfPlusFillRegion" , Gdiplus::EmfPlusRecordTypeFillRegion ,
  334. "EmfPlusFillPath" , Gdiplus::EmfPlusRecordTypeFillPath ,
  335. "EmfPlusDrawPath" , Gdiplus::EmfPlusRecordTypeDrawPath ,
  336. "EmfPlusFillClosedCurve" , Gdiplus::EmfPlusRecordTypeFillClosedCurve ,
  337. "EmfPlusDrawClosedCurve" , Gdiplus::EmfPlusRecordTypeDrawClosedCurve ,
  338. "EmfPlusDrawCurve" , Gdiplus::EmfPlusRecordTypeDrawCurve ,
  339. "EmfPlusDrawBeziers" , Gdiplus::EmfPlusRecordTypeDrawBeziers ,
  340. "EmfPlusDrawImage" , Gdiplus::EmfPlusRecordTypeDrawImage ,
  341. "EmfPlusDrawImagePoints" , Gdiplus::EmfPlusRecordTypeDrawImagePoints ,
  342. "EmfPlusDrawString" , Gdiplus::EmfPlusRecordTypeDrawString ,
  343. "EmfPlusSetRenderingOrigin" , Gdiplus::EmfPlusRecordTypeSetRenderingOrigin ,
  344. "EmfPlusSetAntiAliasMode" , Gdiplus::EmfPlusRecordTypeSetAntiAliasMode ,
  345. "EmfPlusSetTextRenderingHint" , Gdiplus::EmfPlusRecordTypeSetTextRenderingHint ,
  346. "EmfPlusSetTextContrast" , Gdiplus::EmfPlusRecordTypeSetTextContrast ,
  347. "EmfPlusSetInterpolationMode" , Gdiplus::EmfPlusRecordTypeSetInterpolationMode ,
  348. "EmfPlusSetPixelOffsetMode" , Gdiplus::EmfPlusRecordTypeSetPixelOffsetMode ,
  349. "EmfPlusSetCompositingMode" , Gdiplus::EmfPlusRecordTypeSetCompositingMode ,
  350. "EmfPlusSetCompositingQuality" , Gdiplus::EmfPlusRecordTypeSetCompositingQuality ,
  351. "EmfPlusSave" , Gdiplus::EmfPlusRecordTypeSave ,
  352. "EmfPlusRestore" , Gdiplus::EmfPlusRecordTypeRestore ,
  353. "EmfPlusBeginContainer" , Gdiplus::EmfPlusRecordTypeBeginContainer ,
  354. "EmfPlusBeginContainerNoParams" , Gdiplus::EmfPlusRecordTypeBeginContainerNoParams ,
  355. "EmfPlusEndContainer" , Gdiplus::EmfPlusRecordTypeEndContainer ,
  356. "EmfPlusSetWorldTransform" , Gdiplus::EmfPlusRecordTypeSetWorldTransform ,
  357. "EmfPlusResetWorldTransform" , Gdiplus::EmfPlusRecordTypeResetWorldTransform ,
  358. "EmfPlusMultiplyWorldTransform" , Gdiplus::EmfPlusRecordTypeMultiplyWorldTransform ,
  359. "EmfPlusTranslateWorldTransform" , Gdiplus::EmfPlusRecordTypeTranslateWorldTransform,
  360. "EmfPlusScaleWorldTransform" , Gdiplus::EmfPlusRecordTypeScaleWorldTransform ,
  361. "EmfPlusRotateWorldTransform" , Gdiplus::EmfPlusRecordTypeRotateWorldTransform ,
  362. "EmfPlusSetPageTransform" , Gdiplus::EmfPlusRecordTypeSetPageTransform ,
  363. "EmfPlusResetClip" , Gdiplus::EmfPlusRecordTypeResetClip ,
  364. "EmfPlusSetClipRect" , Gdiplus::EmfPlusRecordTypeSetClipRect ,
  365. "EmfPlusSetClipPath" , Gdiplus::EmfPlusRecordTypeSetClipPath ,
  366. "EmfPlusSetClipRegion" , Gdiplus::EmfPlusRecordTypeSetClipRegion ,
  367. "EmfPlusOffsetClip" , Gdiplus::EmfPlusRecordTypeOffsetClip ,
  368. "EmfPlusDrawDriverString" , Gdiplus::EmfPlusRecordTypeDrawDriverString ,
  369. };
  370. /*
  371. METAFUNCTIONS MetaFunctions[] = {
  372. "SETBKCOLOR", 0x0201,
  373. "SETBKMODE", 0x0102,
  374. "SETMAPMODE", 0x0103,
  375. "SETROP2", 0x0104,
  376. "SETRELABS", 0x0105,
  377. "SETPOLYFILLMODE", 0x0106,
  378. "SETSTRETCHBLTMODE", 0x0107,
  379. "SETTEXTCHAREXTRA", 0x0108,
  380. "SETTEXTCOLOR", 0x0209,
  381. "SETTEXTJUSTIFICATION", 0x020A,
  382. "SETWINDOWORG", 0x020B,
  383. "SETWINDOWEXT", 0x020C,
  384. "SETVIEWPORTORG", 0x020D,
  385. "SETVIEWPORTEXT", 0x020E,
  386. "OFFSETWINDOWORG", 0x020F,
  387. "SCALEWINDOWEXT", 0x0400,
  388. "OFFSETVIEWPORTORG", 0x0211,
  389. "SCALEVIEWPORTEXT", 0x0412,
  390. "LINETO", 0x0213,
  391. "MOVETO", 0x0214,
  392. "EXCLUDECLIPRECT", 0x0415,
  393. "INTERSECTCLIPRECT", 0x0416,
  394. "ARC", 0x0817,
  395. "ELLIPSE", 0x0418,
  396. "FLOODFILL", 0x0419,
  397. "PIE", 0x081A,
  398. "RECTANGLE", 0x041B,
  399. "ROUNDRECT", 0x061C,
  400. "PATBLT", 0x061D,
  401. "SAVEDC", 0x001E,
  402. "SETPIXEL", 0x041F,
  403. "OFFSETCLIPRGN", 0x0220,
  404. "TEXTOUT", 0x0521,
  405. "BITBLT", 0x0922,
  406. "STRETCHBLT", 0x0B23,
  407. "POLYGON", 0x0324,
  408. "POLYLINE", 0x0325,
  409. "ESCAPE", 0x0626,
  410. "RESTOREDC", 0x0127,
  411. "FILLREGION", 0x0228,
  412. "FRAMEREGION", 0x0429,
  413. "INVERTREGION", 0x012A,
  414. "PAINTREGION", 0x012B,
  415. "SELECTCLIPREGION", 0x012C,
  416. "SELECTOBJECT", 0x012D,
  417. "SETTEXTALIGN", 0x012E,
  418. "DRAWTEXT", 0x062F,
  419. "CHORD", 0x0830,
  420. "SETMAPPERFLAGS", 0x0231,
  421. "EXTTEXTOUT", 0x0a32,
  422. "SETDIBTODEV", 0x0d33,
  423. "SELECTPALETTE", 0x0234,
  424. "REALIZEPALETTE", 0x0035,
  425. "ANIMATEPALETTE", 0x0436,
  426. "SETPALENTRIES", 0x0037,
  427. "POLYPOLYGON", 0x0538,
  428. "RESIZEPALETTE", 0x0139,
  429. "DIBBITBLT", 0x0940,
  430. "DIBSTRETCHBLT", 0x0b41,
  431. "DIBCREATEPATTERNBRUSH",0x0142,
  432. "STRETCHDIB", 0x0f43,
  433. "DELETEOBJECT", 0x01f0,
  434. "CREATEPALETTE", 0x00f7,
  435. "CREATEBRUSH", 0x00F8,
  436. "CREATEPATTERNBRUSH", 0x01F9,
  437. "CREATEPENINDIRECT", 0x02FA,
  438. "CREATEFONTINDIRECT", 0x02FB,
  439. "CREATEBRUSHINDIRECT", 0x02FC,
  440. "CREATEBITMAPINDIRECT", 0x02FD,
  441. "CREATEBITMAP", 0x06FE,
  442. "CREATEREGION", 0x06FF,
  443. };
  444. */
  445. /***********************************************************************
  446. FUNCTION : MetaEnumProc
  447. PARAMETERS : HDC hDC
  448. LPHANDLETABLE lpHTable
  449. LPMETARECORD lpMFR
  450. int nObj
  451. LPARAM lpClientData
  452. PURPOSE : callback for EnumMetaFile.
  453. CALLS : EnumMFIndirect()
  454. MESSAGES : none
  455. RETURNS : int
  456. COMMENTS :
  457. HISTORY : 1/16/91 - created - drc
  458. 5/6/93 - modified for Win32 - denniscr
  459. ************************************************************************/
  460. int CALLBACK MetaEnumProc(
  461. HDC hDC,
  462. LPHANDLETABLE lpHTable,
  463. LPMETARECORD lpMFR,
  464. int nObj,
  465. LPARAM lpClientData)
  466. {
  467. return EnumMFIndirect(hDC, lpHTable, lpMFR, NULL, nObj, lpClientData);
  468. }
  469. /***********************************************************************
  470. FUNCTION : LoadParameterLB
  471. PARAMETERS : HWND hDlg
  472. DWORD dwParams
  473. int nRadix - HEX to display contents in base 16
  474. DEC to display contents in base 10
  475. PURPOSE : display the parameters of the metafile record in
  476. the parameter listbox
  477. CALLS : WINDOWS
  478. GlobalLock
  479. GlobalUnlock
  480. SendDlgItemMessage
  481. wsprintf
  482. lstrlen
  483. MESSAGES : WM_SETREDRAW
  484. WM_RESETCONTENT
  485. LB_ADDSTRING
  486. RETURNS : BOOL
  487. COMMENTS :
  488. HISTORY : 1/16/91 - created - drc
  489. ************************************************************************/
  490. BOOL LoadParameterLB(
  491. HWND hDlg,
  492. DWORD dwParams,
  493. int nRadix)
  494. {
  495. DWORD i;
  496. BYTE nHiByte, nLoByte;
  497. BYTE nHiByteHi, nLoByteHi;
  498. WORD wHiWord, wLoWord;
  499. char szBuffer[40];
  500. char szDump[100];
  501. int iValue = 0;
  502. DWORD dwValue = 0;
  503. switch (nRadix) /* if nRadix is not a valid value, return FALSE */
  504. {
  505. case IDB_HEX:
  506. case IDB_DEC:
  507. case IDB_CHAR:
  508. case IDB_WORD:
  509. break;
  510. default :
  511. return FALSE;
  512. }
  513. //
  514. //init the strings
  515. //
  516. *szBuffer = '\0';
  517. *szDump = '\0';
  518. //
  519. //turn off redrawing of the listbox
  520. //
  521. SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, FALSE, 0L);
  522. //
  523. //reset the contents of the listbox
  524. //
  525. SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_RESETCONTENT, 0, 0L);
  526. // don't load an entire bitmap or other image into the dialog in hex
  527. if (dwParams > 1024)
  528. {
  529. dwParams = 1024;
  530. }
  531. if (bEnhMeta)
  532. {
  533. //
  534. //lock the memory where the parameters can be found
  535. //
  536. if (NULL == (lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem)))
  537. return (FALSE);
  538. //
  539. //loop through the metafile record parameters
  540. //
  541. for (i = 0; i < dwParams; i++)
  542. {
  543. /* get the high and low byte of the parameter word */
  544. wHiWord = HIWORD(lpEMFParams[i]);
  545. wLoWord = LOWORD(lpEMFParams[i]);
  546. nLoByteHi = LOBYTE(wHiWord);
  547. nHiByteHi = HIBYTE(wHiWord);
  548. nLoByte = LOBYTE(wLoWord);
  549. nHiByte = HIBYTE(wLoWord);
  550. switch (nRadix)
  551. {
  552. case IDB_HEX: /* if we are to display as hexadecimal */
  553. /* format the bytes for the hex part of dump */
  554. wsprintf((LPSTR)szBuffer, (LPSTR)"%08x ", lpEMFParams[i]);
  555. break;
  556. case IDB_DEC:
  557. /* format the bytes for the decimal part of dump */
  558. dwValue = lpEMFParams[i];
  559. wsprintf((LPSTR)szBuffer, (LPSTR)"%lu ", dwValue );
  560. break;
  561. case IDB_CHAR:
  562. wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c%c%c",
  563. (nLoByte > 0x20) ? nLoByte : 0x2E,
  564. (nHiByte > 0x20) ? nHiByte : 0x2E,
  565. (nLoByteHi > 0x20) ? nLoByteHi : 0x2E,
  566. (nHiByteHi > 0x20) ? nHiByteHi : 0x2E);
  567. break;
  568. case IDB_WORD: /* if we are to display as hexadecimal */
  569. /* format the bytes for the hex part of dump */
  570. wsprintf((LPSTR)szBuffer, (LPSTR)"%04x %04x ", wLoWord, wHiWord );
  571. break;
  572. default :
  573. return FALSE;
  574. }
  575. /* concatenate it onto whatever we have already formatted */
  576. lstrcat((LPSTR)szDump, (LPSTR)szBuffer);
  577. /* use every 8 words for hex/dec dump */
  578. if (!((i + 1) % 4))
  579. {
  580. /*add the string to the listbox */
  581. SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
  582. /* re-init the hex/dec strings in preparation for next 8 words */
  583. *szDump = '\0';
  584. }
  585. }
  586. }
  587. else
  588. {
  589. /* lock the memory where the parameters can be found */
  590. if (NULL == (lpMFParams = (LPPARAMETERS)GlobalLock(hMem)))
  591. return (FALSE);
  592. /* loop through the metafile record parameters */
  593. for (i = 0; i < dwParams; i++)
  594. {
  595. /* get the high and low byte of the parameter word */
  596. nHiByte = HIBYTE(lpMFParams[i]);
  597. nLoByte = LOBYTE(lpMFParams[i]);
  598. switch (nRadix)
  599. {
  600. case IDB_HEX: /* if we are to display as hexadecimal */
  601. /* format the bytes for the hex part of dump */
  602. wsprintf((LPSTR)szBuffer, (LPSTR)"%02x %02x ", nLoByte, nHiByte );
  603. break;
  604. case IDB_DEC:
  605. /* format the bytes for the decimal part of dump */
  606. iValue = lpMFParams[i];
  607. wsprintf((LPSTR)szBuffer, (LPSTR)"%d ", iValue );
  608. break;
  609. case IDB_CHAR:
  610. wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c",
  611. (nLoByte > 0x20) ? nLoByte : 0x2E,
  612. (nHiByte > 0x20) ? nHiByte : 0x2E);
  613. break;
  614. case IDB_WORD: /* if we are to display as hexadecimal */
  615. /* format the bytes for the hex part of dump */
  616. wsprintf((LPSTR)szBuffer, (LPSTR)"%02x%02x ", nHiByte, nLoByte );
  617. break;
  618. default :
  619. return FALSE;
  620. }
  621. /* concatenate it onto whatever we have already formatted */
  622. lstrcat((LPSTR)szDump, (LPSTR)szBuffer);
  623. /* use every 8 words for hex/dec dump */
  624. if (!((i + 1) % 8))
  625. {
  626. /*add the string to the listbox */
  627. SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
  628. /* re-init the hex/dec strings in preparation for next 8 words */
  629. *szDump = '\0';
  630. }
  631. }
  632. } //else
  633. //
  634. //dump any leftover hex/dec dump
  635. //
  636. if (lstrlen((LPSTR)szDump))
  637. SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump);
  638. //
  639. //enable redraw to the listbox
  640. //
  641. SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, TRUE, 0L);
  642. //
  643. //redraw it
  644. //
  645. InvalidateRect(GetDlgItem(hDlg,IDL_PARAMETERS), NULL, TRUE);
  646. //
  647. //unlock the memory used for the parameters
  648. //
  649. GlobalUnlock(hMem);
  650. return (TRUE);
  651. }
  652. extern "C"
  653. void GetMetaFileAndEnum(
  654. HWND hwnd,
  655. HDC hDC,
  656. int iAction);
  657. /***********************************************************************
  658. FUNCTION : PlayMetaFileToDest
  659. PARAMETERS : HWND hWnd
  660. int nDest - DC to play metafile to
  661. DESTDISPLAY - play to the display
  662. DESTMETA - play into another metafile
  663. PURPOSE : begin the enumeration of the metafile to the user selected
  664. destination. Perform the housekeeping needs appropriate
  665. to that destination.
  666. CALLS : WINDOWS
  667. GetClientRect
  668. InvalidateRect
  669. GetDC
  670. SetMapMode
  671. OpenFileDialog
  672. MessageBox
  673. CreateMetaFile
  674. DeleteMetaFile
  675. CloseMetaFile
  676. APP
  677. WaitCursor
  678. SetClipMetaExts
  679. SetPlaceableExts
  680. GetMetaFileAndEnum
  681. MESSAGES : none
  682. RETURNS : int
  683. COMMENTS :
  684. HISTORY : 1/16/91 - created - drc
  685. ************************************************************************/
  686. BOOL PlayMetaFileToDest(
  687. HWND hWnd,
  688. int nDest)
  689. {
  690. HDC hDC;
  691. RECT rect;
  692. int iSaveRet;
  693. //
  694. //if the file opened contained a valid metafile
  695. //
  696. if (bValidFile)
  697. {
  698. //
  699. //init the record count
  700. //
  701. iRecNum = 0;
  702. //
  703. //if we are stepping the metafile then clear the client area
  704. //
  705. if (!bPlayItAll)
  706. {
  707. GetClientRect(hWnd, (LPRECT)&rect);
  708. InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
  709. }
  710. switch (nDest)
  711. {
  712. //
  713. //playing metafile to the display
  714. //
  715. case DESTDISPLAY:
  716. WaitCursor(TRUE);
  717. hDC = GetDC(hWnd);
  718. if (!bUseGdiPlusToPlay)
  719. {
  720. //
  721. //metafile read in from a clipboard file
  722. //
  723. if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta)
  724. SetClipMetaExts(hDC, lpMFP, lpOldMFP, WMFDISPLAY);
  725. //
  726. //Windows placeable metafile
  727. //
  728. if (bPlaceableMeta && !bEnhMeta)
  729. SetPlaceableExts(hDC, placeableWMFHeader, WMFDISPLAY);
  730. //
  731. //Windows metafile
  732. //
  733. if (!bMetaInRam && !bEnhMeta)
  734. {
  735. SetNonPlaceableExts(hDC, WMFDISPLAY);
  736. }
  737. }
  738. //
  739. //begin the enumeration of the metafile
  740. //
  741. DWORD start, end;
  742. DWORD renderTime;
  743. char tmpBuf[512];
  744. start = GetTickCount();
  745. GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP);
  746. end = GetTickCount();
  747. renderTime = end - start;
  748. wsprintf(tmpBuf, "Time: %d", renderTime);
  749. SetWindowText(hWnd, tmpBuf);
  750. ReleaseDC(hWnd, hDC);
  751. WaitCursor(FALSE);
  752. break;
  753. case DESTMETA:
  754. //
  755. //get a name of a file to play the metafile into
  756. //
  757. iSaveRet = SaveFileDialog((LPSTR)SaveName, (LPSTR)gszSaveEMFFilter);
  758. //
  759. //if the file selected is this metafile then warn user
  760. //
  761. if (!lstrcmp((LPSTR)OpenName, (LPSTR)SaveName))
  762. MessageBox(hWnd, (LPSTR)"Cannot overwrite the opened metafile!",
  763. (LPSTR)"Play to Metafile", MB_OK | MB_ICONEXCLAMATION);
  764. else
  765. //
  766. //the user didn't hit the cancel button
  767. //
  768. if (iSaveRet)
  769. {
  770. WaitCursor(TRUE);
  771. //
  772. //create a disk based metafile
  773. //
  774. hDC = (bEnhMeta) ? CreateEnhMetaFile(NULL, (LPSTR)SaveName, NULL, NULL)
  775. : CreateMetaFile((LPSTR)SaveName);
  776. //
  777. //begin the enumeration of the metafile
  778. //
  779. GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP);
  780. //
  781. //done playing so close the metafile and delete the handle
  782. //
  783. if (bEnhMeta)
  784. DeleteEnhMetaFile(CloseEnhMetaFile(hDC));
  785. else
  786. DeleteMetaFile(CloseMetaFile(hDC));
  787. WaitCursor(FALSE);
  788. }
  789. break;
  790. case DESTDIB:
  791. {
  792. /* extents for the display DC */
  793. GetClientRect(hWndMain, &rect);
  794. INT cx = rect.right - rect.left;
  795. INT cy = rect.bottom - rect.top;
  796. /* SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm));
  797. SetViewportOrgEx(hDC, 0, 0, &lpPT);
  798. */
  799. WaitCursor(TRUE);
  800. hDC = GetDC(hWnd);
  801. BITMAPINFOHEADER bmi;
  802. memset(&bmi, 0, sizeof(BITMAPINFOHEADER));
  803. bmi.biSize = sizeof(BITMAPINFOHEADER);
  804. bmi.biBitCount = 24;
  805. bmi.biWidth = cx;
  806. bmi.biHeight = -cy;
  807. bmi.biPlanes = 1;
  808. VOID* bits = NULL;
  809. HBITMAP hBmp = CreateDIBSection(hDC, (BITMAPINFO*) &bmi, 0, &bits, NULL, 0);
  810. HDC hDCBmp = CreateCompatibleDC(hDC);
  811. ::SelectObject(hDCBmp, hBmp);
  812. FillRect(hDCBmp, &rect, (HBRUSH) ::GetStockObject(GRAY_BRUSH));
  813. if (!bUseGdiPlusToPlay)
  814. {
  815. //
  816. //metafile read in from a clipboard file
  817. //
  818. if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta)
  819. SetClipMetaExts(hDCBmp, lpMFP, lpOldMFP, WMFDISPLAY);
  820. //
  821. //Windows placeable metafile
  822. //
  823. if (bPlaceableMeta && !bEnhMeta)
  824. SetPlaceableExts(hDCBmp, placeableWMFHeader, WMFDISPLAY);
  825. //
  826. //Windows metafile
  827. //
  828. if (!bMetaInRam && !bEnhMeta)
  829. {
  830. SetNonPlaceableExts(hDCBmp, WMFDISPLAY);
  831. }
  832. }
  833. //
  834. //begin the enumeration of the metafile
  835. //
  836. start = GetTickCount();
  837. GetMetaFileAndEnum(hWnd, hDCBmp, ENUMMFSTEP);
  838. end = GetTickCount();
  839. renderTime = end - start;
  840. wsprintf(tmpBuf, "Time: %d", renderTime);
  841. SetWindowText(hWnd, tmpBuf);
  842. StretchDIBits(hDC, 0, 0, cx, cy, 0, 0, cx, cy, bits, (BITMAPINFO*)&bmi, 0, SRCCOPY);
  843. DeleteDC(hDCBmp);
  844. DeleteObject((HGDIOBJ) hBmp);
  845. ReleaseDC(hWnd, hDC);
  846. WaitCursor(FALSE);
  847. break;
  848. }
  849. case DESTPRN:
  850. {
  851. HDC hPr = (HDC)NULL;
  852. PRINTDLG pd;
  853. memset(&pd, 0, sizeof(PRINTDLG));
  854. pd.lStructSize = sizeof(PRINTDLG);
  855. pd.Flags = PD_RETURNDC;
  856. pd.hwndOwner = hWndMain;
  857. //
  858. //get a DC for the printer
  859. //
  860. if (PrintDlg(&pd) != 0)
  861. hPr= pd.hDC;
  862. else
  863. break;
  864. //
  865. //if a DC could not be created then report the error and return
  866. //
  867. if (!hPr)
  868. {
  869. WaitCursor(FALSE);
  870. wsprintf((LPSTR)str, "Cannot print %s", (LPSTR)fnameext);
  871. MessageBox(hWndMain, (LPSTR)str, NULL, MB_OK | MB_ICONHAND);
  872. break;
  873. }
  874. //
  875. //define the abort function
  876. //
  877. SetAbortProc(hPr, AbortProc);
  878. //
  879. //Initialize the members of a DOCINFO structure.
  880. //
  881. DOCINFO di;
  882. memset(&di, 0, sizeof(di));
  883. di.cbSize = sizeof(DOCINFO);
  884. di.lpszDocName = (bEnhMeta) ? "Print EMF" : "Print WMF";
  885. di.lpszOutput = (LPTSTR) NULL;
  886. //
  887. //Begin a print job by calling the StartDoc
  888. //function.
  889. //
  890. if (SP_ERROR == (StartDoc(hPr, &di)))
  891. {
  892. //if (Escape(hPr, STARTDOC, 4, "Metafile", (LPSTR) NULL) < 0) {
  893. MessageBox(hWndMain, "Unable to start print job",
  894. NULL, MB_OK | MB_ICONHAND);
  895. DeleteDC(hPr);
  896. break;
  897. }
  898. //
  899. //clear the abort flag
  900. //
  901. bAbort = FALSE;
  902. //
  903. //Create the Abort dialog box (modeless)
  904. //
  905. hAbortDlgWnd = CreateDialog((HINSTANCE)hInst, "AbortDlg", hWndMain, AbortDlg);
  906. //
  907. //if the dialog was not created report the error
  908. //
  909. if (!hAbortDlgWnd)
  910. {
  911. WaitCursor(FALSE);
  912. MessageBox(hWndMain, "NULL Abort window handle",
  913. NULL, MB_OK | MB_ICONHAND);
  914. break;
  915. }
  916. //
  917. //show Abort dialog
  918. //
  919. ShowWindow (hAbortDlgWnd, SW_NORMAL);
  920. //
  921. //disable the main window to avoid reentrancy problems
  922. //
  923. EnableWindow(hWndMain, FALSE);
  924. WaitCursor(FALSE);
  925. //
  926. //if we are still committed to printing
  927. //
  928. if (!bUseGdiPlusToPlay)
  929. {
  930. //
  931. //if this is a placeable metafile then set its origins and extents
  932. //
  933. if (bPlaceableMeta)
  934. SetPlaceableExts(hPr, placeableWMFHeader, WMFPRINTER);
  935. //
  936. //if this is a metafile contained within a clipboard file then set
  937. //its origins and extents accordingly
  938. //
  939. if ( (bMetaInRam) && (!bPlaceableMeta) )
  940. SetClipMetaExts(hPr, lpMFP, lpOldMFP, WMFPRINTER);
  941. }
  942. //
  943. //if this is a "traditional" windows metafile
  944. //
  945. RECT rc;
  946. rc.left = 0;
  947. rc.top = 0;
  948. rc.right = GetDeviceCaps(hPr, HORZRES);
  949. rc.bottom = GetDeviceCaps(hPr, VERTRES);
  950. POINT lpPT;
  951. SIZE lpSize;
  952. if (TRUE || !bMetaInRam)
  953. {
  954. SetMapMode(hPr, MM_TEXT);
  955. SetViewportOrgEx(hPr, 0, 0, &lpPT);
  956. //
  957. //set the extents to the driver supplied values for horizontal
  958. //and vertical resolution
  959. //
  960. SetViewportExtEx(hPr, rc.right, rc.bottom, &lpSize );
  961. }
  962. //
  963. //play the metafile directly to the printer.
  964. //No enumeration involved here
  965. //
  966. GetMetaFileAndEnum(hWnd, hPr, ENUMMFSTEP);
  967. //
  968. //eject page and end the print job
  969. //
  970. Escape(hPr, NEWFRAME, 0, 0L, 0L);
  971. EndDoc(hPr);
  972. EnableWindow(hWndMain, TRUE);
  973. //
  974. //destroy the Abort dialog box
  975. //
  976. DestroyWindow(hAbortDlgWnd);
  977. DeleteDC(hPr);
  978. }
  979. default:
  980. break;
  981. }
  982. //
  983. //if playing list records then free the memory used for the list of
  984. //selected records
  985. //
  986. if (bPlayList)
  987. {
  988. GlobalUnlock(hSelMem);
  989. GlobalFree(hSelMem);
  990. bPlayList = FALSE;
  991. }
  992. //
  993. //success
  994. //
  995. return (TRUE);
  996. }
  997. else
  998. //
  999. //not a valid metafile
  1000. //
  1001. return (FALSE);
  1002. }
  1003. /***********************************************************************
  1004. FUNCTION : RenderClipMeta
  1005. PARAMETERS : CLIPFILEFORMAT *ClipHeader
  1006. int fh
  1007. PURPOSE : read metafile bits, metafilepict and metafile header
  1008. of the metafile contained within a clipboard file
  1009. CALLS : WINDOWS
  1010. GlobalAlloc
  1011. GlobalLock
  1012. GlobalUnlock
  1013. GlobalFree
  1014. MessageBox
  1015. _llseek
  1016. _lread
  1017. _lclose
  1018. SetMetaFileBits
  1019. MESSAGES : none
  1020. RETURNS : BOOL
  1021. COMMENTS :
  1022. HISTORY : 1/16/91 - created - drc
  1023. 5/23/93 - ported to NT. it must handle 3.1 clipboard
  1024. as well as NT clipboard files - drc
  1025. ************************************************************************/
  1026. BOOL RenderClipMeta(LPVOID lpvClipHeader, int fh, WORD ClipID)
  1027. {
  1028. int wBytesRead;
  1029. long lBytesRead;
  1030. long lSize;
  1031. DWORD lOffset;
  1032. DWORD dwSizeOfMetaFilePict;
  1033. BOOL bEMF = FALSE;
  1034. LPNTCLIPFILEFORMAT lpNTClp;
  1035. LPCLIPFILEFORMAT lpClp;
  1036. //
  1037. //cast the void ptr to the clipfile header appropriately
  1038. //
  1039. if (bEnhMeta)
  1040. {
  1041. lpNTClp = (LPNTCLIPFILEFORMAT)lpvClipHeader;
  1042. bEMF = TRUE;
  1043. }
  1044. else
  1045. lpClp = (LPCLIPFILEFORMAT)lpvClipHeader;
  1046. //
  1047. //obtain the appropriate size of the metafilepict. win16 vs win32
  1048. //
  1049. dwSizeOfMetaFilePict = (ClipID == CLP_ID) ?
  1050. sizeof(OLDMETAFILEPICT) :
  1051. sizeof(METAFILEPICT);
  1052. //
  1053. //free any memory already allocated for the METAFILEPICT
  1054. //
  1055. if (lpMFP != NULL || lpOldMFP != NULL)
  1056. {
  1057. GlobalFreePtr(lpMFP);
  1058. lpMFP = NULL;
  1059. }
  1060. //
  1061. //allocate enough memory to read the metafile bits into
  1062. //
  1063. if (!(lpMFBits = (char*)GlobalAllocPtr(GHND, ((bEMF) ? lpNTClp->DataLen
  1064. : lpClp->DataLen - dwSizeOfMetaFilePict))))
  1065. return(FALSE);
  1066. //
  1067. //offset to the metafile bits
  1068. //
  1069. lOffset = ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset + dwSizeOfMetaFilePict );
  1070. //
  1071. //size of metafile bits
  1072. //
  1073. lSize = (long)( ((bEMF) ? lpNTClp->DataLen : lpClp->DataLen - dwSizeOfMetaFilePict));
  1074. //
  1075. //seek to the beginning of the metafile bits
  1076. //
  1077. _llseek(fh, lOffset, 0);
  1078. //
  1079. //read the metafile bits
  1080. //
  1081. lBytesRead = _hread(fh, lpMFBits, lSize);
  1082. //
  1083. //if unable to read the metafile bits bail out
  1084. //
  1085. if( lBytesRead == -1 || lBytesRead < lSize)
  1086. {
  1087. GlobalFreePtr(lpMFBits);
  1088. MessageBox(hWndMain, "Unable to read metafile bits",
  1089. NULL, MB_OK | MB_ICONHAND);
  1090. return(FALSE);
  1091. }
  1092. //
  1093. //return to beginning to read metafile header
  1094. //
  1095. _llseek(fh, lOffset, 0);
  1096. //
  1097. //read the metafile header
  1098. //
  1099. if (!bEMF)
  1100. wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
  1101. else
  1102. wBytesRead = _lread(fh, (LPSTR)&emfHeader, sizeof(ENHMETAHEADER));
  1103. //
  1104. //if unable to read the header return
  1105. //
  1106. if( wBytesRead == -1 || (WORD)wBytesRead < ((bEMF) ? sizeof(ENHMETAHEADER) : sizeof(METAHEADER)) )
  1107. {
  1108. MessageBox(hWndMain, "Unable to read metafile header",
  1109. NULL, MB_OK | MB_ICONHAND);
  1110. return(FALSE);
  1111. }
  1112. //
  1113. //set the metafile bits to the memory allocated for that purpose
  1114. //
  1115. if (bEMF)
  1116. //
  1117. //win32
  1118. //
  1119. hemf = SetEnhMetaFileBits(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits);
  1120. else
  1121. //
  1122. //win16
  1123. //
  1124. hMF = SetMetaFileBitsEx(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits);
  1125. if ( NULL == ((bEMF) ? hemf : hMF))
  1126. {
  1127. MessageBox(hWndMain, "Unable to set metafile bits",
  1128. NULL, MB_OK | MB_ICONHAND);
  1129. return(FALSE);
  1130. }
  1131. //
  1132. //allocate memory for the metafile pict structure
  1133. //
  1134. if (!(hMFP = GlobalAlloc(GHND, dwSizeOfMetaFilePict)))
  1135. {
  1136. MessageBox(hWndMain, "Unable allocate memory for metafile pict",
  1137. NULL, MB_OK | MB_ICONHAND);
  1138. return(FALSE);
  1139. }
  1140. //
  1141. //lock the memory
  1142. //
  1143. if (ClipID == CLP_ID)
  1144. lpOldMFP = (LPOLDMETAFILEPICT)GlobalLock(hMFP);
  1145. else
  1146. lpMFP = (LPMETAFILEPICT)GlobalLock(hMFP);
  1147. if (!lpMFP && !lpOldMFP)
  1148. {
  1149. MessageBox(hWndMain, "unable to lock metafile pict memory",
  1150. NULL, MB_OK | MB_ICONHAND);
  1151. GlobalFree(hMFP);
  1152. return(FALSE);
  1153. }
  1154. //
  1155. //reposition to the start of the METAFILEPICT header.
  1156. //
  1157. _llseek(fh, ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset), 0);
  1158. //
  1159. //read the metafile pict structure
  1160. //
  1161. wBytesRead = _lread(fh, ((ClipID == CLP_ID) ? (LPVOID)lpOldMFP : (LPVOID)lpMFP),
  1162. dwSizeOfMetaFilePict);
  1163. //
  1164. //if unable to read, return
  1165. //
  1166. if( wBytesRead == -1 || wBytesRead < (long)dwSizeOfMetaFilePict) {
  1167. MessageBox(hWndMain, "Unable to read metafile pict",
  1168. NULL, MB_OK | MB_ICONHAND);
  1169. GlobalUnlock(hMFP);
  1170. GlobalFree(hMFP);
  1171. return(FALSE);
  1172. }
  1173. if (bEnhMeta)
  1174. GetEMFCoolStuff();
  1175. //DENNIS - check this out....
  1176. /* update metafile handle */
  1177. if (ClipID == CLP_ID)
  1178. lpOldMFP->hMF = (WORD)hMF;
  1179. else
  1180. lpMFP->hMF = (HMETAFILE)hemf;
  1181. return(TRUE);
  1182. }
  1183. /***********************************************************************
  1184. FUNCTION : RenderPlaceableMeta
  1185. PARAMETERS : int fh - filehandle to the placeable metafile
  1186. PURPOSE : read the metafile bits, metafile header and placeable
  1187. metafile header of a placeable metafile.
  1188. CALLS : WINDOWS
  1189. GlobalAlloc
  1190. GlobalLock
  1191. Global
  1192. DeleteMetaFile
  1193. SetMetaFileBits
  1194. _llseek
  1195. _lread
  1196. _lclose
  1197. MessageBox
  1198. MESSAGES : none
  1199. RETURNS : BOOL
  1200. COMMENTS :
  1201. HISTORY : 1/16/91 - created - drc
  1202. 7/1/93 - modified for win32 - denniscr
  1203. ************************************************************************/
  1204. BOOL RenderPlaceableMeta(
  1205. int fh)
  1206. {
  1207. int wBytesRead;
  1208. long lBytesRead;
  1209. DWORD dwSize;
  1210. //
  1211. //if there is currently a metafile loaded, get rid of it
  1212. //
  1213. if (bMetaInRam && hMF && !bEnhMeta)
  1214. DeleteMetaFile((HMETAFILE)hMF);
  1215. //
  1216. //seek to beginning of file and read placeable header
  1217. //
  1218. _llseek(fh, 0, 0);
  1219. //
  1220. //read the placeable header
  1221. //
  1222. wBytesRead = _lread(fh, (LPSTR)&placeableWMFHeader, sizeof(PLACEABLEWMFHEADER));
  1223. //
  1224. //if there is an error, return
  1225. //
  1226. if( wBytesRead == -1 || wBytesRead < sizeof(PLACEABLEWMFHEADER) ) {
  1227. MessageBox(hWndMain, "Unable to read placeable header",
  1228. NULL, MB_OK | MB_ICONHAND);
  1229. return(FALSE);
  1230. }
  1231. //
  1232. //return to read metafile header
  1233. //
  1234. _llseek(fh, sizeof(placeableWMFHeader), 0);
  1235. //
  1236. //read the metafile header
  1237. //
  1238. wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
  1239. //
  1240. //if there is an error return
  1241. //
  1242. if( wBytesRead == -1 || wBytesRead < sizeof(METAHEADER) ) {
  1243. MessageBox(hWndMain, "Unable to read metafile header",
  1244. NULL, MB_OK | MB_ICONHAND);
  1245. return(FALSE);
  1246. }
  1247. //
  1248. //allocate memory for the metafile bits
  1249. //
  1250. if (!(lpMFBits = (char *)GlobalAllocPtr(GHND, (mfHeader.mtSize * 2L))))
  1251. {
  1252. MessageBox(hWndMain, "Unable to allocate memory for metafile bits",
  1253. NULL, MB_OK | MB_ICONHAND);
  1254. return(FALSE);
  1255. }
  1256. //
  1257. //seek to the metafile bits
  1258. //
  1259. _llseek(fh, sizeof(placeableWMFHeader), 0);
  1260. //
  1261. //read metafile bits
  1262. //
  1263. lBytesRead = _hread(fh, lpMFBits, mfHeader.mtSize * 2);
  1264. //
  1265. //if there was an error
  1266. //
  1267. if( lBytesRead == -1 )
  1268. {
  1269. MessageBox(hWndMain, "Unable to read metafile bits",
  1270. NULL, MB_OK | MB_ICONHAND);
  1271. GlobalFreePtr(lpMFBits);
  1272. return(FALSE);
  1273. }
  1274. //
  1275. //set the metafile bits to the memory that we allocated
  1276. //
  1277. dwSize = GlobalSizePtr(lpMFBits);
  1278. if (!(hMF = SetMetaFileBitsEx(dwSize, (const unsigned char *)lpMFBits)))
  1279. return(FALSE);
  1280. return(TRUE);
  1281. }
  1282. /***********************************************************************
  1283. FUNCTION : SetPlaceableExts
  1284. PARAMETERS : HDC hDC
  1285. PLACEABLEWMFHEADER phdr
  1286. int nDest
  1287. PURPOSE : set the origins and extents on the DC to correspond with
  1288. the origins and extents specified within the placeable
  1289. metafile header
  1290. CALLS : WINDOWS
  1291. GetClientRect
  1292. SetMapMode
  1293. SetWindowOrg
  1294. SetWindowExt
  1295. SetViewportOrg
  1296. SetViewportExt
  1297. C runtime
  1298. labs
  1299. MESSAGES : none
  1300. RETURNS : void
  1301. COMMENTS :
  1302. HISTORY : 1/16/91 - created - drc
  1303. ************************************************************************/
  1304. void SetPlaceableExts(HDC hDC, PLACEABLEWMFHEADER phdr, int nDest)
  1305. {
  1306. RECT rect;
  1307. POINT lpPT;
  1308. SIZE lpSize;
  1309. /* if setting the extents on the display DC */
  1310. if (nDest != WMFPRINTER)
  1311. GetClientRect(hWndMain, &rect);
  1312. SetMapMode(hDC, MM_ANISOTROPIC);
  1313. /* set the windows origin to correspond to the bounding box origin
  1314. contained in the placeable header */
  1315. SetWindowOrgEx(hDC, phdr.bbox.left, phdr.bbox.top, &lpPT);
  1316. /* set the window extents based on the abs value of the bbox coords */
  1317. SetWindowExtEx(hDC,phdr.bbox.right -phdr.bbox.left,
  1318. phdr.bbox.bottom -phdr.bbox.top,
  1319. &lpSize);
  1320. /* set the viewport origin and extents */
  1321. if (nDest != WMFPRINTER)
  1322. {
  1323. SetViewportOrgEx(hDC, 0, 0, &lpPT);
  1324. SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize);
  1325. }
  1326. else
  1327. {
  1328. SetViewportOrgEx(hPr, 0, 0, &lpPT);
  1329. SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES),
  1330. GetDeviceCaps(hPr, VERTRES),
  1331. &lpSize);
  1332. }
  1333. }
  1334. void SetNonPlaceableExts(HDC hDC, int nDest)
  1335. {
  1336. RECT rect;
  1337. POINT lpPT;
  1338. SIZE lpSize;
  1339. /* if setting the extents on the display DC */
  1340. if (nDest != WMFPRINTER)
  1341. GetClientRect(hWndMain, &rect);
  1342. SetMapMode(hDC, MM_ANISOTROPIC);
  1343. /* set the viewport origin and extents */
  1344. if (nDest != WMFPRINTER)
  1345. {
  1346. SetViewportOrgEx(hDC, 0, 0, &lpPT);
  1347. SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize);
  1348. }
  1349. else
  1350. {
  1351. SetViewportOrgEx(hPr, 0, 0, &lpPT);
  1352. SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES),
  1353. GetDeviceCaps(hPr, VERTRES),
  1354. &lpSize);
  1355. }
  1356. }
  1357. /***********************************************************************
  1358. FUNCTION : SetClipMetaExts
  1359. PARAMETERS : HDC hDC
  1360. METAFILEPICT MFP
  1361. int nDest
  1362. PURPOSE : set the extents to the client rect for clipboard metafiles
  1363. CALLS : WINDOWS
  1364. GetClientRect
  1365. IntersectClipRect
  1366. SetMapMode
  1367. SetViewportOrg
  1368. SetViewportExt
  1369. SetWindowExt
  1370. MESSAGES : none
  1371. RETURNS : void
  1372. COMMENTS : this is not as robust as it could be. A more complete
  1373. approach might be something like Petzold discusses in
  1374. his Programming Windows book on page 793 in the
  1375. function PrepareMetaFile().
  1376. HISTORY : 1/16/91 - created - drc
  1377. ************************************************************************/
  1378. void SetClipMetaExts(
  1379. HDC hDC,
  1380. LPMETAFILEPICT lpMFP,
  1381. LPOLDMETAFILEPICT lpOldMFP,
  1382. int nDest)
  1383. {
  1384. int cx, cy;
  1385. RECT rect;
  1386. POINT lpPT;
  1387. SIZE lpSize;
  1388. long lmm;
  1389. long lxExt;
  1390. long lyExt;
  1391. /* extents for the display DC */
  1392. if (nDest != WMFPRINTER)
  1393. {
  1394. GetClientRect(hWndMain, &rect);
  1395. cx = rect.right - rect.left;
  1396. cy = rect.bottom - rect.top;
  1397. IntersectClipRect(hDC, rect.left, rect.top, rect.right, rect.bottom);
  1398. }
  1399. SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm));
  1400. /* set physical origin to 0, 0 */
  1401. SetViewportOrgEx(hDC, 0, 0, &lpPT);
  1402. /* given the mapping mode specified in the metafilepict */
  1403. lmm = (lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm;
  1404. lxExt = (lpOldMFP != NULL) ? lpOldMFP->xExt : lpMFP->xExt;
  1405. lyExt = (lpOldMFP != NULL) ? lpOldMFP->yExt : lpMFP->yExt;
  1406. switch (lmm) {
  1407. case MM_ISOTROPIC:
  1408. if (lxExt && lyExt)
  1409. SetWindowExtEx(hDC, lxExt, lyExt, &lpSize);
  1410. /* fall through */
  1411. case MM_ANISOTROPIC:
  1412. if (nDest != WMFPRINTER)
  1413. SetViewportExtEx(hDC, cx, cy, &lpSize);
  1414. else
  1415. SetViewportExtEx(hDC, GetDeviceCaps(hDC, HORZRES),
  1416. GetDeviceCaps(hDC, VERTRES), &lpSize );
  1417. break;
  1418. default:
  1419. break;
  1420. }
  1421. }
  1422. /***********************************************************************
  1423. FUNCTION : ProcessFile
  1424. PARAMETERS : HWND hWnd
  1425. LPSTR lpFileName
  1426. PURPOSE : open the metafile, determine if it contains a valid
  1427. metafile, decide what type of metafile it is (wmf,
  1428. clipboard, or placeable) and take care of some menu
  1429. housekeeping tasks.
  1430. CALLS :
  1431. MESSAGES : none
  1432. RETURNS : BOOL
  1433. COMMENTS :
  1434. HISTORY : 1/16/91 - created - drc
  1435. ************************************************************************/
  1436. BOOL ProcessFile(
  1437. HWND hWnd,
  1438. LPSTR lpFileName)
  1439. {
  1440. //
  1441. //for openfiledialog
  1442. //
  1443. char drive[3];
  1444. char dir[MAX_PATH+1];
  1445. char fname[MAX_PATH+1];
  1446. char ext[5];
  1447. char * pchCorrectSir;
  1448. //
  1449. //initialize these global handles to metafiles
  1450. //
  1451. if (hMF && !bMetaInRam)
  1452. {
  1453. DeleteMetaFile((HMETAFILE)hMF);
  1454. hMF = NULL;
  1455. }
  1456. if (hemf && !bMetaInRam)
  1457. {
  1458. DeleteEnhMetaFile(hemf);
  1459. hemf = NULL;
  1460. }
  1461. if (lpMFBits)
  1462. {
  1463. GlobalFreePtr(lpMFBits);
  1464. lpMFBits = NULL;
  1465. hemf = NULL;
  1466. hMF = NULL;
  1467. }
  1468. bEnhMeta = FALSE;
  1469. //
  1470. //split the fully qualified filename into its components
  1471. //
  1472. SplitPath( lpFileName, (LPSTR)drive,
  1473. (LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
  1474. pchCorrectSir = _strupr( _strdup( ext ) );
  1475. //
  1476. //if the memory for the emf header, desc string and palette
  1477. //is still around then nuke it
  1478. //
  1479. if (EmfPtr.lpEMFHdr)
  1480. {
  1481. GlobalFreePtr(EmfPtr.lpEMFHdr);
  1482. EmfPtr.lpEMFHdr = NULL ;
  1483. }
  1484. if (EmfPtr.lpDescStr)
  1485. {
  1486. GlobalFreePtr(EmfPtr.lpDescStr);
  1487. EmfPtr.lpDescStr = NULL ;
  1488. }
  1489. if (EmfPtr.lpPal)
  1490. {
  1491. GlobalFreePtr(EmfPtr.lpPal);
  1492. EmfPtr.lpPal = NULL ;
  1493. }
  1494. //
  1495. //if the file is an enhanced metafile
  1496. //
  1497. if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"CLP") == 0)
  1498. return ProcessCLP(hWnd, lpFileName);
  1499. //
  1500. //if the file is a Windows metafile or a Windows or placeable metafile
  1501. //as per the normal naming conventions
  1502. //
  1503. if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"WMF") == 0)
  1504. return ProcessWMF(hWnd, lpFileName);
  1505. //
  1506. //if the file is a clipboard file
  1507. //
  1508. if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"EMF") == 0)
  1509. return ProcessEMF(hWnd, lpFileName);
  1510. return FALSE;
  1511. }
  1512. /***********************************************************************
  1513. FUNCTION : ProcessWMF
  1514. PARAMETERS : HWND hWnd
  1515. LPSTR lpFileName
  1516. PURPOSE : open the metafile and determine if it is a Windows metafile or
  1517. placeable metafile. Then take care of some menu housekeeping
  1518. tasks.
  1519. CALLS :
  1520. MESSAGES : none
  1521. RETURNS : BOOL
  1522. COMMENTS :
  1523. HISTORY : 6/23/93 - created - drc
  1524. ************************************************************************/
  1525. BOOL ProcessWMF(HWND hWnd, LPSTR lpFileName)
  1526. {
  1527. int fh;
  1528. int wBytesRead;
  1529. DWORD dwIsPlaceable;
  1530. char szCaption[144];
  1531. /* for openfiledialog */
  1532. char drive[3];
  1533. char dir[MAX_PATH+1];
  1534. char fname[MAX_PATH+1];
  1535. char ext[5];
  1536. char * pchCorrectSir;
  1537. //
  1538. //split the fully qualified filename into its components
  1539. //
  1540. SplitPath( lpFileName, (LPSTR)drive,
  1541. (LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
  1542. pchCorrectSir = _strupr( _strdup( ext ) );
  1543. //
  1544. //try to open the file. It's existence has already been
  1545. //checked by OpenFileDialog
  1546. //
  1547. fh = _lopen(lpFileName, OF_READ);
  1548. //
  1549. //if opened successfully
  1550. //
  1551. if (fh != -1)
  1552. {
  1553. //
  1554. //always disable the clipboard and EMF header menu if we get here
  1555. //
  1556. EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED);
  1557. EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED);
  1558. //
  1559. // read the first dword of the file to see if it is a placeable wmf
  1560. //
  1561. wBytesRead = _lread(fh,(LPSTR)&dwIsPlaceable, sizeof(dwIsPlaceable));
  1562. if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable))
  1563. {
  1564. _lclose(fh);
  1565. MessageBox(hWndMain, "unable to read file", NULL,
  1566. MB_OK | MB_ICONEXCLAMATION);
  1567. return (FALSE);
  1568. }
  1569. //
  1570. // if this is windows metafile, not a placeable wmf
  1571. //
  1572. if (dwIsPlaceable != PLACEABLEKEY)
  1573. {
  1574. // if (!bMetaInRam)
  1575. hMF = GetMetaFile((LPSTR)OpenName);
  1576. //
  1577. //disable placeable header menu item
  1578. //
  1579. EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
  1580. //
  1581. //seek to the beginning of the file
  1582. //
  1583. _llseek(fh, 0, 0);
  1584. //
  1585. //read the wmf header
  1586. //
  1587. wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
  1588. //
  1589. //done with file so close it
  1590. //
  1591. _lclose(fh);
  1592. //
  1593. //if read failed
  1594. //
  1595. if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable))
  1596. {
  1597. MessageBox(hWndMain, "unable to read metafile header", NULL,
  1598. MB_OK | MB_ICONEXCLAMATION);
  1599. return (FALSE);
  1600. }
  1601. }
  1602. //
  1603. //this is a placeable metafile
  1604. //
  1605. else
  1606. {
  1607. //
  1608. //enable the placeable header menu item
  1609. //
  1610. EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_ENABLED);
  1611. //
  1612. //convert the placeable format into something that can
  1613. //be used with GDI metafile functions
  1614. //
  1615. RenderPlaceableMeta(fh);
  1616. //
  1617. //close the file
  1618. //
  1619. _lclose(fh);
  1620. }
  1621. //
  1622. //at this point we have a metafile header regardless of whether
  1623. //the metafile was a windows metafile or a placeable metafile
  1624. //so check to see if it is valid. There is really no good
  1625. //way to do this so just make sure that the mtType is either
  1626. //1 or 2 (memory or disk file)
  1627. //
  1628. if ( (mfHeader.mtType != 1) && (mfHeader.mtType != 2) )
  1629. {
  1630. //
  1631. //set the program flags appropriately
  1632. //
  1633. bBadFile = TRUE;
  1634. bMetaFileOpen = FALSE;
  1635. bValidFile = FALSE;
  1636. //
  1637. //let the user know that this is an invalid metafile
  1638. //
  1639. MessageBox(hWndMain, "This file is not a valid metafile",
  1640. NULL, MB_OK | MB_ICONEXCLAMATION);
  1641. //
  1642. //restore the caption text to the default
  1643. //
  1644. SetWindowText(hWnd, (LPSTR)APPNAME);
  1645. //
  1646. //disable menu items, indicating that a valid metafile has not been
  1647. //loaded
  1648. //
  1649. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  1650. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  1651. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
  1652. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
  1653. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
  1654. //
  1655. //refresh the menu bar to reflect above changes
  1656. //
  1657. DrawMenuBar(hWnd);
  1658. }
  1659. //
  1660. //this is a valid metafile...at least based on the above criteria
  1661. //
  1662. else
  1663. {
  1664. //
  1665. //modify and update the caption text
  1666. //
  1667. wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
  1668. (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
  1669. //
  1670. //this could be used by the printing routines if unable to print
  1671. //
  1672. wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
  1673. SetWindowText(hWnd, (LPSTR)szCaption);
  1674. //
  1675. //enable the appropriate menu items
  1676. //
  1677. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
  1678. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
  1679. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
  1680. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
  1681. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
  1682. EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED);
  1683. //
  1684. //refresh the menu bar to reflect above changes
  1685. //
  1686. DrawMenuBar(hWnd);
  1687. //
  1688. //set global flags appropriately
  1689. //
  1690. bValidFile = TRUE;
  1691. bMetaFileOpen = TRUE;
  1692. if (dwIsPlaceable != PLACEABLEKEY)
  1693. {
  1694. bPlaceableMeta = FALSE;
  1695. bMetaInRam = FALSE;
  1696. }
  1697. else
  1698. {
  1699. bPlaceableMeta = TRUE;
  1700. bMetaInRam = TRUE;
  1701. }
  1702. }
  1703. return (TRUE);
  1704. } //if fh != -1
  1705. else
  1706. return (FALSE);
  1707. }
  1708. /***********************************************************************
  1709. FUNCTION : ProcessCLP
  1710. PARAMETERS : HWND hWnd
  1711. LPSTR lpFileName
  1712. PURPOSE : open the metafile contained in the clipboard file and
  1713. take care of some menu housekeeping tasks.
  1714. CALLS :
  1715. MESSAGES : none
  1716. RETURNS : BOOL
  1717. COMMENTS :
  1718. HISTORY : 6/23/93 - created - drc
  1719. ************************************************************************/
  1720. BOOL ProcessCLP(HWND hWnd, LPSTR lpFileName)
  1721. {
  1722. WORD i;
  1723. int fh;
  1724. DWORD HeaderPos;
  1725. DWORD nSizeOfClipHeader;
  1726. DWORD nSizeOfClipFormat;
  1727. NTCLIPFILEHEADER NTFileHeader;
  1728. NTCLIPFILEFORMAT NTClipHeader;
  1729. CLIPFILEHEADER FileHeader;
  1730. CLIPFILEFORMAT ClipHeader;
  1731. char szCaption[144];
  1732. WORD wFileID;
  1733. BOOL bMetaFound = FALSE;
  1734. LPVOID lpvAddressOfHdr;
  1735. /* for openfiledialog */
  1736. char drive[3];
  1737. char dir[MAX_PATH+1];
  1738. char fname[MAX_PATH+1];
  1739. char ext[5];
  1740. char * pchCorrectSir;
  1741. //
  1742. //split the fully qualified filename into its components
  1743. //
  1744. SplitPath( lpFileName, (LPSTR)drive,
  1745. (LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
  1746. pchCorrectSir = _strupr( _strdup( ext ) );
  1747. //
  1748. //try to open the file. It's existence has already been
  1749. //checked by OpenFileDialog
  1750. fh = _lopen(lpFileName, OF_READ);
  1751. //
  1752. //if opened successfully
  1753. if (fh != -1 )
  1754. {
  1755. //
  1756. // read the clipboard fileidentifier
  1757. //
  1758. wFileID = 0;
  1759. _lread(fh, (LPSTR)&wFileID, sizeof(WORD));
  1760. _llseek(fh, 0, 0);
  1761. //
  1762. //if this is not a valid clipboard file based on the file
  1763. //identifier of the file header
  1764. //
  1765. if (wFileID != CLP_ID && wFileID != CLP_NT_ID && wFileID != CLPBK_NT_ID)
  1766. {
  1767. _lclose(fh);
  1768. MessageBox(hWndMain, "This file is not a valid clipboard file",
  1769. NULL, MB_OK | MB_ICONEXCLAMATION);
  1770. return (FALSE);
  1771. }
  1772. switch (wFileID)
  1773. {
  1774. case CLP_ID:
  1775. _lread(fh, (LPSTR)&FileHeader, sizeof(CLIPFILEHEADER));
  1776. nSizeOfClipHeader = sizeof(CLIPFILEHEADER);
  1777. nSizeOfClipFormat = sizeof(CLIPFILEFORMAT);
  1778. HeaderPos = nSizeOfClipHeader;
  1779. break;
  1780. case CLP_NT_ID:
  1781. case CLPBK_NT_ID:
  1782. NTFileHeader.FormatCount = 0;
  1783. _lread(fh, (LPSTR)&NTFileHeader, sizeof(NTCLIPFILEHEADER));
  1784. nSizeOfClipHeader = sizeof(NTCLIPFILEHEADER);
  1785. nSizeOfClipFormat = sizeof(NTCLIPFILEFORMAT);
  1786. HeaderPos = nSizeOfClipHeader;
  1787. break;
  1788. default:
  1789. break;
  1790. }
  1791. //
  1792. //search the formats contained within the clipboard file looking
  1793. //for a metafile. Break if and when it is found
  1794. //
  1795. for (i=0;
  1796. i < ((wFileID == CLP_ID) ? FileHeader.FormatCount : NTFileHeader.FormatCount);
  1797. i++)
  1798. {
  1799. _llseek(fh, HeaderPos, 0);
  1800. //
  1801. //read the clipboard header found at current position
  1802. //
  1803. lpvAddressOfHdr = (wFileID == CLP_ID) ? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader;
  1804. if(_lread(fh, (LPSTR)lpvAddressOfHdr, nSizeOfClipFormat) < nSizeOfClipFormat)
  1805. //if(_lread(fh, (LPSTR)&ClipHeader, nSizeOfClipHeader) < nSizeOfClipHeader)
  1806. {
  1807. _lclose(fh);
  1808. MessageBox(hWndMain, "read of clipboard header failed",
  1809. NULL, MB_OK | MB_ICONEXCLAMATION);
  1810. return (FALSE);
  1811. }
  1812. //
  1813. //increment the file offset to data
  1814. //
  1815. HeaderPos += nSizeOfClipFormat;
  1816. //
  1817. //if a metafile was found break...
  1818. //this break assumes that CF_METAFILEPICT formats are always written before CF_ENHMETAFILE
  1819. //formats.
  1820. //
  1821. if (wFileID == CLP_ID && ClipHeader.FormatID == CF_METAFILEPICT)
  1822. {
  1823. bMetaFound = TRUE;
  1824. break;
  1825. }
  1826. if (wFileID == CLP_NT_ID || wFileID == CLPBK_NT_ID)
  1827. {
  1828. if (NTClipHeader.FormatID == CF_ENHMETAFILE)
  1829. // HeaderPos += NTClipHeader.DataLen;
  1830. //else
  1831. {
  1832. bMetaFound = TRUE;
  1833. break;
  1834. }
  1835. }
  1836. } //for i < formatcount
  1837. if (bMetaFound)
  1838. {
  1839. //
  1840. //if there is currently a metafile loaded delete it.
  1841. //
  1842. if (wFileID == CLP_ID)
  1843. {
  1844. if ((bMetaInRam) && (hMF))
  1845. {
  1846. DeleteMetaFile((HMETAFILE)hMF);
  1847. hMF = NULL;
  1848. }
  1849. }
  1850. else
  1851. {
  1852. if ((bMetaInRam) && (hemf))
  1853. {
  1854. DeleteEnhMetaFile(hemf);
  1855. hemf = NULL;
  1856. }
  1857. }
  1858. //
  1859. //modify and update the caption text
  1860. //
  1861. wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
  1862. (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
  1863. //
  1864. //this could be used by the printing routines if unable to print
  1865. //
  1866. wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
  1867. SetWindowText(hWnd, (LPSTR)szCaption);
  1868. //
  1869. //enable the appropriate menu items
  1870. //
  1871. if (wFileID == CLP_ID)
  1872. {
  1873. EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED);
  1874. EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED);
  1875. }
  1876. else
  1877. {
  1878. EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED);
  1879. EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED);
  1880. }
  1881. EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
  1882. EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_ENABLED);
  1883. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
  1884. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
  1885. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
  1886. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
  1887. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
  1888. //
  1889. //refresh the menu bar
  1890. //
  1891. DrawMenuBar(hWnd);
  1892. //
  1893. //set the program flags appropriately
  1894. //
  1895. bValidFile = TRUE;
  1896. bMetaFileOpen = TRUE;
  1897. bMetaInRam = TRUE;
  1898. bPlaceableMeta = FALSE;
  1899. bEnhMeta = (wFileID == CLP_ID) ? FALSE : TRUE;
  1900. //
  1901. //convert the metafile contained within the clipboard file into
  1902. //a format useable with GDI metafile functions
  1903. //
  1904. if (!RenderClipMeta(((wFileID == CLP_ID)? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader),
  1905. fh,
  1906. FileHeader.FileIdentifier))
  1907. MessageBox(hWndMain, "Unable to render format",
  1908. NULL, MB_OK | MB_ICONEXCLAMATION);
  1909. _lclose(fh);
  1910. }
  1911. //
  1912. //a metafile was not found within the clipboard file
  1913. //
  1914. else
  1915. {
  1916. bBadFile = TRUE;
  1917. bMetaFileOpen = FALSE;
  1918. bValidFile = FALSE;
  1919. bEnhMeta = FALSE;
  1920. //
  1921. //let the user know
  1922. //
  1923. MessageBox(hWndMain, "This CLP file doesn't contain a valid metafile",
  1924. NULL, MB_OK | MB_ICONEXCLAMATION);
  1925. //
  1926. //restore the caption text to default
  1927. //
  1928. SetWindowText(hWnd, (LPSTR)APPNAME);
  1929. //
  1930. //disable previously enabled menu items
  1931. //
  1932. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  1933. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  1934. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
  1935. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
  1936. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
  1937. //
  1938. //refresh the menu bar to reflect these changes
  1939. //
  1940. DrawMenuBar(hWnd);
  1941. _lclose(fh);
  1942. }
  1943. return (TRUE);
  1944. }
  1945. else
  1946. return (FALSE);
  1947. }
  1948. /***********************************************************************
  1949. FUNCTION : ProcessEMF
  1950. PARAMETERS : HWND hWnd
  1951. LPSTR lpFileName
  1952. PURPOSE : open the metafile contained in the clipboard file and
  1953. take care of some menu housekeeping tasks.
  1954. CALLS :
  1955. MESSAGES : none
  1956. RETURNS : BOOL
  1957. COMMENTS :
  1958. HISTORY : 6/23/93 - created - drc
  1959. ************************************************************************/
  1960. BOOL ProcessEMF(HWND hWnd, LPSTR lpFileName)
  1961. {
  1962. char szCaption[144];
  1963. /* for openfiledialog */
  1964. char drive[3];
  1965. char dir[MAX_PATH+1];
  1966. char fname[MAX_PATH+1];
  1967. char ext[5];
  1968. char * pchCorrectSir;
  1969. bEnhMeta = FALSE;
  1970. //
  1971. //split the fully qualified filename into its components
  1972. //
  1973. SplitPath( lpFileName, (LPSTR)drive,
  1974. (LPSTR)dir, (LPSTR)fname, (LPSTR)ext);
  1975. pchCorrectSir = _strupr( _strdup( ext ) );
  1976. //
  1977. //always disable the clipboard, WMF and Placeable header menu if we get here
  1978. //
  1979. EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED);
  1980. EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED);
  1981. EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED);
  1982. //
  1983. //if emf was successfully opened
  1984. //
  1985. if (!hemf)
  1986. hemf = GetEnhMetaFile(lpFileName);
  1987. if (hemf)
  1988. {
  1989. GetEMFCoolStuff();
  1990. //
  1991. //modify and update the caption text
  1992. //
  1993. wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s",
  1994. (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext);
  1995. //
  1996. //this could be used by the printing routines if unable to print
  1997. //
  1998. wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext);
  1999. SetWindowText(hWnd, (LPSTR)szCaption);
  2000. //
  2001. //enable the appropriate menu items
  2002. //
  2003. EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED);
  2004. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION);
  2005. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION);
  2006. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED);
  2007. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED);
  2008. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED);
  2009. //
  2010. //refresh the menu bar
  2011. //
  2012. DrawMenuBar(hWnd);
  2013. //
  2014. //set the program flags appropriately
  2015. //
  2016. bValidFile = TRUE;
  2017. bMetaFileOpen = TRUE;
  2018. bEnhMeta = TRUE;
  2019. bMetaInRam = FALSE;
  2020. bPlaceableMeta = FALSE;
  2021. }
  2022. // DeleteEnhMetaFile(hemf);
  2023. else
  2024. {
  2025. bEnhMeta = FALSE;
  2026. bValidFile = FALSE;
  2027. bBadFile = TRUE;
  2028. bMetaFileOpen = FALSE;
  2029. //
  2030. //let the user know
  2031. //
  2032. MessageBox(hWndMain, "This EMF file doesn't contain a valid metafile",
  2033. NULL, MB_OK | MB_ICONEXCLAMATION);
  2034. //
  2035. //restore the caption text to default
  2036. //
  2037. SetWindowText(hWnd, (LPSTR)APPNAME);
  2038. //
  2039. //disable previously enabled menu items
  2040. //
  2041. EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  2042. EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
  2043. EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED);
  2044. EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED);
  2045. EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED);
  2046. //
  2047. //refresh the menu bar to reflect these changes
  2048. //
  2049. DrawMenuBar(hWnd);
  2050. }
  2051. return TRUE;
  2052. }
  2053. /***********************************************************************
  2054. FUNCTION : GetEMFCoolStuff
  2055. PARAMETERS :
  2056. PURPOSE :
  2057. CALLS :
  2058. MESSAGES :
  2059. RETURNS :
  2060. COMMENTS :
  2061. HISTORY : created 7/8/93 - denniscr
  2062. ************************************************************************/
  2063. BOOL GetEMFCoolStuff()
  2064. {
  2065. //
  2066. //init these ptrs
  2067. //
  2068. EmfPtr.lpEMFHdr = NULL;
  2069. EmfPtr.lpDescStr = NULL;
  2070. EmfPtr.lpPal = NULL;
  2071. if (hemf)
  2072. {
  2073. //
  2074. //obtain the sizes of the emf header, description string and palette
  2075. //
  2076. UINT uiHdrSize = GetEnhMetaFileHeader(hemf, 0, NULL);
  2077. UINT uiDescStrSize = GetEnhMetaFileDescription(hemf, 0, NULL);
  2078. UINT uiPalEntries = GetEnhMetaFilePaletteEntries(hemf, 0, NULL);
  2079. //
  2080. //if these are lengths > 0 then allocate memory to store them
  2081. //
  2082. if (uiHdrSize)
  2083. EmfPtr.lpEMFHdr = (LPENHMETAHEADER)GlobalAllocPtr(GHND, uiHdrSize);
  2084. if (uiDescStrSize)
  2085. EmfPtr.lpDescStr = (LPTSTR)GlobalAllocPtr(GHND, uiDescStrSize);
  2086. if (uiPalEntries)
  2087. EmfPtr.lpPal = (LPPALETTEENTRY)GlobalAllocPtr(GHND, uiPalEntries * sizeof(PALETTEENTRY));
  2088. //
  2089. //so far the emf seems to be valid so continue
  2090. //
  2091. if (uiHdrSize)
  2092. {
  2093. //
  2094. //get the actual emf header and description string
  2095. //
  2096. if (!GetEnhMetaFileHeader(hemf, uiHdrSize, EmfPtr.lpEMFHdr))
  2097. {
  2098. MessageBox(hWndMain, "unable to read enhanced metafile header", NULL,
  2099. MB_OK | MB_ICONEXCLAMATION);
  2100. bValidFile = FALSE;
  2101. return (FALSE);
  2102. }
  2103. else
  2104. {
  2105. //
  2106. //get the description string if it exists
  2107. //
  2108. if (uiDescStrSize)
  2109. GetEnhMetaFileDescription(hemf, uiDescStrSize, EmfPtr.lpDescStr);
  2110. //
  2111. //get the palette if it exists
  2112. //
  2113. if (uiPalEntries)
  2114. {
  2115. GetEnhMetaFilePaletteEntries(hemf, uiPalEntries, EmfPtr.lpPal);
  2116. EmfPtr.palNumEntries = (WORD)uiPalEntries;
  2117. }
  2118. }
  2119. }
  2120. }
  2121. return (TRUE);
  2122. }
  2123. float NormalizeAngle (double angle)
  2124. {
  2125. if (angle >= 0)
  2126. {
  2127. while (angle >= 360)
  2128. {
  2129. angle -= 360;
  2130. }
  2131. }
  2132. else
  2133. {
  2134. while (angle < 0)
  2135. {
  2136. angle += 360;
  2137. }
  2138. }
  2139. return static_cast<float>(angle);
  2140. }
  2141. #define PI 3.1415926535897932384626433832795
  2142. #define RADIANS_TO_DEGREES (180.0 / PI)
  2143. float PointToAngle(float x, float y, float w, float h, float xVector, float yVector)
  2144. {
  2145. BOOL bScale = TRUE;
  2146. if (w == h)
  2147. {
  2148. if (w == 0)
  2149. {
  2150. return 0;
  2151. }
  2152. bScale = FALSE;
  2153. }
  2154. float horRadius = w / 2;
  2155. float verRadius = h / 2;
  2156. float xOrigin = x + horRadius;
  2157. float yOrigin = y + verRadius;
  2158. if (horRadius == 0)
  2159. {
  2160. double dAngle = asin(((double)(yVector - yOrigin)) / verRadius);
  2161. if (xOrigin > xVector)
  2162. {
  2163. dAngle = PI - dAngle;
  2164. }
  2165. return NormalizeAngle(dAngle * RADIANS_TO_DEGREES);
  2166. }
  2167. else if (verRadius == 0)
  2168. {
  2169. double dAngle = acos(((double)(xVector - xOrigin)) / horRadius);
  2170. if (yOrigin > yVector)
  2171. {
  2172. dAngle = -dAngle;
  2173. }
  2174. return NormalizeAngle(dAngle * RADIANS_TO_DEGREES);
  2175. }
  2176. if (yOrigin == yVector)
  2177. {
  2178. return static_cast<float>((xOrigin <= xVector) ? 0 : 180);
  2179. }
  2180. if (xOrigin == xVector)
  2181. {
  2182. return static_cast<float>((yOrigin < yVector) ? 90 : 270);;
  2183. }
  2184. if (bScale)
  2185. {
  2186. xVector = (float)(xOrigin + ((xVector - xOrigin) * ((double)verRadius / horRadius)));
  2187. }
  2188. return NormalizeAngle(atan2(yVector - yOrigin, xVector - xOrigin) * RADIANS_TO_DEGREES);
  2189. }
  2190. #define HS_DDI_MAX 6
  2191. typedef struct {
  2192. BITMAPINFOHEADER bmiHeader;
  2193. RGBQUAD bmiColors[2];
  2194. } HATCHBRUSHINFO;
  2195. HATCHBRUSHINFO hatchBrushInfo = {
  2196. { sizeof(BITMAPINFOHEADER), 8, 8, 1, 1, BI_RGB, 32, 0, 0, 2, 0 },
  2197. { { 255, 255, 255, 0 }, { 0, 0, 0, 0 } }
  2198. };
  2199. ULONG HatchPatterns[HS_DDI_MAX][8] = {
  2200. // Scans have to be DWORD aligned:
  2201. { 0x00, // ........ HS_HORIZONTAL 0
  2202. 0x00, // ........
  2203. 0x00, // ........
  2204. 0xff, // ********
  2205. 0x00, // ........
  2206. 0x00, // ........
  2207. 0x00, // ........
  2208. 0x00 }, // ........
  2209. { 0x08, // ....*... HS_VERTICAL 1
  2210. 0x08, // ....*...
  2211. 0x08, // ....*...
  2212. 0x08, // ....*...
  2213. 0x08, // ....*...
  2214. 0x08, // ....*...
  2215. 0x08, // ....*...
  2216. 0x08 }, // ....*...
  2217. { 0x80, // *....... HS_FDIAGONAL 2
  2218. 0x40, // .*......
  2219. 0x20, // ..*.....
  2220. 0x10, // ...*....
  2221. 0x08, // ....*...
  2222. 0x04, // .....*..
  2223. 0x02, // ......*.
  2224. 0x01 }, // .......*
  2225. { 0x01, // .......* HS_BDIAGONAL 3
  2226. 0x02, // ......*.
  2227. 0x04, // .....*..
  2228. 0x08, // ....*...
  2229. 0x10, // ...*....
  2230. 0x20, // ..*.....
  2231. 0x40, // .*......
  2232. 0x80 }, // *.......
  2233. { 0x08, // ....*... HS_CROSS 4
  2234. 0x08, // ....*...
  2235. 0x08, // ....*...
  2236. 0xff, // ********
  2237. 0x08, // ....*...
  2238. 0x08, // ....*...
  2239. 0x08, // ....*...
  2240. 0x08 }, // ....*...
  2241. { 0x81, // *......* HS_DIAGCROSS 5
  2242. 0x42, // .*....*.
  2243. 0x24, // ..*..*..
  2244. 0x18, // ...**...
  2245. 0x18, // ...**...
  2246. 0x24, // ..*..*..
  2247. 0x42, // .*....*.
  2248. 0x81 } // *......*
  2249. };
  2250. /***********************************************************************
  2251. FUNCTION : EnhMetaFileEnumProc
  2252. PARAMETERS : HDC hDC
  2253. LPHANDLETABLE lpHTable
  2254. LPMETARECORD lpMFR
  2255. int nObj
  2256. LPARAM lpData
  2257. PURPOSE : callback for EnumEnhMetaFile.
  2258. CALLS : EnumMFIndirect()
  2259. MESSAGES : none
  2260. RETURNS : int
  2261. COMMENTS :
  2262. HISTORY : created 6/30/93 - denniscr
  2263. ************************************************************************/
  2264. int CALLBACK EnhMetaFileEnumProc(HDC hDC, LPHANDLETABLE lpHTable,
  2265. LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData)
  2266. {
  2267. return EnumMFIndirect(hDC, lpHTable, NULL, lpEMFR, nObj, lpData);
  2268. }
  2269. void GetPixelSize (Gdiplus::Graphics * g, float * cx, float * cy)
  2270. {
  2271. Gdiplus::PointF points[2];
  2272. points[0].X = points[0].Y = 0;
  2273. points[1].X = points[1].Y = 1;
  2274. g->TransformPoints(Gdiplus::CoordinateSpaceWorld, Gdiplus::CoordinateSpaceDevice, points, 2);
  2275. *cx = points[1].X - points[0].X;
  2276. *cy = points[1].Y - points[0].Y;
  2277. }
  2278. void GpPlayEnhMetaFileRecord(HDC hDC, LPHANDLETABLE lpHTable,
  2279. LPENHMETARECORD lpEMFR,
  2280. UINT nObj, LPARAM lpData)
  2281. {
  2282. if (!lpData) return;
  2283. MYDATA * myData = (MYDATA *)lpData;
  2284. Gdiplus::Graphics * g = myData->g;
  2285. myData->recordNum++;
  2286. XFORM xForm;
  2287. GetWorldTransform(hDC, &xForm);
  2288. INT mapMode = GetMapMode(hDC);
  2289. POINT org;
  2290. SIZE size;
  2291. GetViewportOrgEx(hDC, &org);
  2292. GetViewportExtEx(hDC, &size);
  2293. GetWindowOrgEx(hDC, &org);
  2294. GetWindowExtEx(hDC, &size);
  2295. switch (lpEMFR->iType)
  2296. {
  2297. case EMR_HEADER:
  2298. {
  2299. PENHMETAHEADER pHeader = (PENHMETAHEADER)lpEMFR;
  2300. RECT clientRect;
  2301. myData->recordNum = 1;
  2302. myData->pObjects = new MYOBJECTS[pHeader->nHandles];
  2303. myData->numObjects = pHeader->nHandles;
  2304. GetClientRect(myData->hwnd, &clientRect);
  2305. int clientWidth = clientRect.right - clientRect.left;
  2306. int clientHeight = clientRect.bottom - clientRect.top;
  2307. myData->windowExtent.cx = clientWidth;
  2308. myData->windowExtent.cy = clientHeight;
  2309. myData->viewportExtent.cx = clientWidth;
  2310. myData->viewportExtent.cy = clientHeight;
  2311. float dstX = TOREAL(clientRect.left);
  2312. float dstY = TOREAL(clientRect.top);
  2313. float dstWidth = TOREAL(clientWidth);
  2314. float dstHeight = TOREAL(clientHeight);
  2315. float srcWidth = TOREAL(pHeader->rclFrame.right - pHeader->rclFrame.left);
  2316. float srcHeight = TOREAL(pHeader->rclFrame.bottom - pHeader->rclFrame.top);
  2317. #if 0
  2318. if (srcHeight * dstWidth >= dstHeight * srcWidth)
  2319. {
  2320. float oldDstWidth = dstWidth;
  2321. dstWidth = srcWidth * dstHeight / srcHeight;
  2322. dstX += (oldDstWidth - dstWidth) / 2;
  2323. }
  2324. else
  2325. {
  2326. float oldDstHeight = dstHeight;
  2327. dstHeight = srcHeight * dstWidth / srcWidth;
  2328. dstY += (oldDstHeight - dstHeight) / 2;
  2329. }
  2330. #endif
  2331. g->SetPageUnit(Gdiplus::UnitPixel);
  2332. using Gdiplus::RectF;
  2333. RectF dstRect(dstX, dstY, dstWidth, dstHeight);
  2334. int deviceLeft = pHeader->rclBounds.left;
  2335. int deviceRight = pHeader->rclBounds.right;
  2336. int deviceTop = pHeader->rclBounds.top;
  2337. int deviceBottom = pHeader->rclBounds.bottom;
  2338. // if ((deviceLeft > deviceRight) ||
  2339. // (deviceTop > deviceBottom))
  2340. {
  2341. SIZEL deviceSize = pHeader->szlDevice;
  2342. SIZEL mmSize = pHeader->szlMillimeters;
  2343. if ((deviceSize.cx <= 0) || (deviceSize.cy <= 0) ||
  2344. (mmSize.cx <= 0) || (mmSize.cy <= 0))
  2345. {
  2346. ASSERT(0);
  2347. // Take a wild guess
  2348. deviceSize.cx = 1024;
  2349. deviceSize.cy = 768;
  2350. mmSize.cx = 320;
  2351. mmSize.cy = 240;
  2352. }
  2353. deviceLeft = MulDiv(pHeader->rclFrame.left, deviceSize.cx, (mmSize.cx * 100));
  2354. deviceRight = MulDiv(pHeader->rclFrame.right, deviceSize.cx, (mmSize.cx * 100));
  2355. deviceTop = MulDiv(pHeader->rclFrame.top, deviceSize.cy, (mmSize.cy * 100));
  2356. deviceBottom = MulDiv(pHeader->rclFrame.bottom, deviceSize.cy, (mmSize.cy * 100));
  2357. }
  2358. RectF srcRect(TOREAL(deviceLeft),
  2359. TOREAL(deviceTop),
  2360. TOREAL(deviceRight - deviceLeft),
  2361. TOREAL(deviceBottom - deviceTop));
  2362. myData->containerId = g->BeginContainer(dstRect, srcRect, Gdiplus::UnitPixel);
  2363. g->SetPageUnit(Gdiplus::UnitPixel); // Assume MM_TEXT
  2364. }
  2365. break;
  2366. case EMR_POLYBEZIER:
  2367. {
  2368. PEMRPOLYBEZIER pBezier = (PEMRPOLYBEZIER)lpEMFR;
  2369. if (pBezier->cptl > 0)
  2370. {
  2371. int i = pBezier->cptl;
  2372. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  2373. do
  2374. {
  2375. i--;
  2376. points[i].X = TOREAL(pBezier->aptl[i].x);
  2377. points[i].Y = TOREAL(pBezier->aptl[i].y);
  2378. } while (i > 0);
  2379. if (!myData->pathOpen)
  2380. {
  2381. if (myData->curPen != 0)
  2382. {
  2383. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2384. pen.SetMiterLimit(myData->miterLimit);
  2385. g->DrawBeziers(&pen, points, pBezier->cptl);
  2386. }
  2387. }
  2388. else
  2389. {
  2390. myData->path->AddBeziers(points, pBezier->cptl);
  2391. }
  2392. delete [] points;
  2393. }
  2394. }
  2395. break;
  2396. case EMR_POLYGON:
  2397. {
  2398. PEMRPOLYGON pPolygon = (PEMRPOLYGON)lpEMFR;
  2399. if (pPolygon->cptl > 0)
  2400. {
  2401. int i = pPolygon->cptl;
  2402. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  2403. do
  2404. {
  2405. i--;
  2406. points[i].X = TOREAL(pPolygon->aptl[i].x);
  2407. points[i].Y = TOREAL(pPolygon->aptl[i].y);
  2408. } while (i > 0);
  2409. if (!myData->pathOpen)
  2410. {
  2411. Gdiplus::GraphicsPath path(myData->fillMode);
  2412. path.AddPolygon(points, pPolygon->cptl);
  2413. if (myData->curBrush != 0)
  2414. {
  2415. if (myData->curPatIndex < 0)
  2416. {
  2417. if (myData->curBrushPattern == NULL)
  2418. {
  2419. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  2420. g->FillPath(&brush, &path);
  2421. }
  2422. else
  2423. {
  2424. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  2425. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  2426. DibBrush brush(bmi, bits);
  2427. g->FillPath(brush, &path);
  2428. }
  2429. }
  2430. else
  2431. {
  2432. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  2433. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  2434. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  2435. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  2436. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  2437. DibBrush brush(bmi, bits);
  2438. g->FillPath(brush, &path);
  2439. }
  2440. }
  2441. if (myData->curPen != 0)
  2442. {
  2443. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2444. pen.SetMiterLimit(myData->miterLimit);
  2445. g->DrawPath(&pen, &path);
  2446. }
  2447. }
  2448. else
  2449. {
  2450. myData->path->AddPolygon(points, pPolygon->cptl);
  2451. }
  2452. delete [] points;
  2453. }
  2454. }
  2455. break;
  2456. case EMR_POLYLINE:
  2457. {
  2458. PEMRPOLYLINE pPolyline = (PEMRPOLYLINE)lpEMFR;
  2459. if (pPolyline->cptl > 0)
  2460. {
  2461. int i = pPolyline->cptl;
  2462. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  2463. do
  2464. {
  2465. i--;
  2466. points[i].X = TOREAL(pPolyline->aptl[i].x);
  2467. points[i].Y = TOREAL(pPolyline->aptl[i].y);
  2468. } while (i > 0);
  2469. if (!myData->pathOpen)
  2470. {
  2471. if (myData->curPen != 0)
  2472. {
  2473. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2474. pen.SetMiterLimit(myData->miterLimit);
  2475. g->DrawLines(&pen, points, pPolyline->cptl);
  2476. }
  2477. }
  2478. else
  2479. {
  2480. myData->path->AddLines(points, pPolyline->cptl);
  2481. }
  2482. delete [] points;
  2483. }
  2484. }
  2485. break;
  2486. case EMR_POLYBEZIERTO:
  2487. {
  2488. PEMRPOLYBEZIERTO pBezier = (PEMRPOLYBEZIERTO)lpEMFR;
  2489. if (pBezier->cptl > 0)
  2490. {
  2491. int i = pBezier->cptl;
  2492. Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
  2493. do
  2494. {
  2495. points[i].X = TOREAL(pBezier->aptl[i-1].x);
  2496. points[i].Y = TOREAL(pBezier->aptl[i-1].y);
  2497. i--;
  2498. } while (i > 0);
  2499. points[0] = myData->curPos;
  2500. myData->curPos = points[pBezier->cptl];
  2501. if (!myData->pathOpen)
  2502. {
  2503. if (myData->curPen != 0)
  2504. {
  2505. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2506. pen.SetMiterLimit(myData->miterLimit);
  2507. g->DrawBeziers(&pen, points, pBezier->cptl+1);
  2508. }
  2509. }
  2510. else
  2511. {
  2512. myData->path->AddBeziers(points, pBezier->cptl+1);
  2513. }
  2514. delete [] points;
  2515. }
  2516. }
  2517. break;
  2518. case EMR_POLYLINETO:
  2519. {
  2520. PEMRPOLYLINETO pPolyline = (PEMRPOLYLINETO)lpEMFR;
  2521. if (pPolyline->cptl > 0)
  2522. {
  2523. int i = pPolyline->cptl;
  2524. Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
  2525. do
  2526. {
  2527. points[i].X = TOREAL(pPolyline->aptl[i-1].x);
  2528. points[i].Y = TOREAL(pPolyline->aptl[i-1].y);
  2529. i--;
  2530. } while (i > 0);
  2531. points[0] = myData->curPos;
  2532. myData->curPos = points[pPolyline->cptl];
  2533. if (!myData->pathOpen)
  2534. {
  2535. if (myData->curPen != 0)
  2536. {
  2537. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2538. pen.SetMiterLimit(myData->miterLimit);
  2539. g->DrawLines(&pen, points, pPolyline->cptl+1);
  2540. }
  2541. }
  2542. else
  2543. {
  2544. myData->path->AddLines(points, pPolyline->cptl+1);
  2545. }
  2546. delete [] points;
  2547. }
  2548. }
  2549. break;
  2550. case EMR_POLYPOLYLINE:
  2551. {
  2552. PEMRPOLYPOLYLINE pPolyline = (PEMRPOLYPOLYLINE)lpEMFR;
  2553. if ((pPolyline->cptl > 0) && (pPolyline->nPolys > 0))
  2554. {
  2555. int i = pPolyline->cptl;
  2556. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  2557. POINTL * metaPoints = (POINTL *)(pPolyline->aPolyCounts + pPolyline->nPolys);
  2558. do
  2559. {
  2560. i--;
  2561. points[i].X = TOREAL(metaPoints[i].x);
  2562. points[i].Y = TOREAL(metaPoints[i].y);
  2563. } while (i > 0);
  2564. if (!myData->pathOpen)
  2565. {
  2566. if (myData->curPen != 0)
  2567. {
  2568. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2569. pen.SetMiterLimit(myData->miterLimit);
  2570. i = 0;
  2571. Gdiplus::PointF * tmpPoints = points;
  2572. DWORD count;
  2573. do
  2574. {
  2575. count = pPolyline->aPolyCounts[i];
  2576. g->DrawLines(&pen, tmpPoints, count);
  2577. tmpPoints += count;
  2578. } while ((UINT)++i < pPolyline->nPolys);
  2579. }
  2580. }
  2581. else
  2582. {
  2583. i = 0;
  2584. Gdiplus::PointF * tmpPoints = points;
  2585. DWORD count;
  2586. do
  2587. {
  2588. count = pPolyline->aPolyCounts[i];
  2589. myData->path->AddLines(tmpPoints, count);
  2590. tmpPoints += count;
  2591. } while ((UINT)++i < pPolyline->nPolys);
  2592. }
  2593. delete [] points;
  2594. }
  2595. }
  2596. break;
  2597. case EMR_POLYPOLYGON:
  2598. {
  2599. PEMRPOLYPOLYGON pPolygon = (PEMRPOLYPOLYGON)lpEMFR;
  2600. if ((pPolygon->cptl > 0) && (pPolygon->nPolys > 0))
  2601. {
  2602. int i = pPolygon->cptl;
  2603. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  2604. POINTL * metaPoints = (POINTL *)(pPolygon->aPolyCounts + pPolygon->nPolys);
  2605. do
  2606. {
  2607. i--;
  2608. points[i].X = TOREAL(metaPoints[i].x);
  2609. points[i].Y = TOREAL(metaPoints[i].y);
  2610. } while (i > 0);
  2611. Gdiplus::GraphicsPath path(myData->fillMode);
  2612. Gdiplus::GraphicsPath * tmpPath = &path;
  2613. if (myData->pathOpen)
  2614. {
  2615. tmpPath = myData->path;
  2616. }
  2617. Gdiplus::PointF * tmpPoints = points;
  2618. DWORD count;
  2619. i = 0;
  2620. do
  2621. {
  2622. count = pPolygon->aPolyCounts[i];
  2623. tmpPath->StartFigure();
  2624. tmpPath->AddPolygon(tmpPoints, count);
  2625. tmpPoints += count;
  2626. } while ((UINT)++i < pPolygon->nPolys);
  2627. if (myData->path == NULL)
  2628. {
  2629. if (myData->curBrush != 0)
  2630. {
  2631. if (myData->curPatIndex < 0)
  2632. {
  2633. if (myData->curBrushPattern == NULL)
  2634. {
  2635. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  2636. g->FillPath(&brush, &path);
  2637. }
  2638. else
  2639. {
  2640. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  2641. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  2642. DibBrush brush(bmi, bits);
  2643. g->FillPath(brush, &path);
  2644. }
  2645. }
  2646. else
  2647. {
  2648. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  2649. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  2650. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  2651. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  2652. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  2653. DibBrush brush(bmi, bits);
  2654. g->FillPath(brush, &path);
  2655. }
  2656. }
  2657. if (myData->curPen != 0)
  2658. {
  2659. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  2660. pen.SetMiterLimit(myData->miterLimit);
  2661. g->DrawPath(&pen, &path);
  2662. }
  2663. }
  2664. delete [] points;
  2665. }
  2666. }
  2667. break;
  2668. case EMR_SETWINDOWEXTEX:
  2669. {
  2670. PEMRSETWINDOWEXTEX pWindowExt = (PEMRSETWINDOWEXTEX)lpEMFR;
  2671. if (((myData->mapMode == MM_ANISOTROPIC) ||
  2672. (myData->mapMode == MM_ISOTROPIC)) &&
  2673. (pWindowExt->szlExtent.cx != 0) && // Note: Can be < 0!!!
  2674. (pWindowExt->szlExtent.cy != 0) &&
  2675. (pWindowExt->szlExtent.cx != myData->windowExtent.cx) &&
  2676. (pWindowExt->szlExtent.cy != myData->windowExtent.cy))
  2677. {
  2678. myData->windowExtent = pWindowExt->szlExtent;
  2679. float oldDx = myData->dx;
  2680. float oldDy = myData->dy;
  2681. float oldSx = myData->scaleX;
  2682. float oldSy = myData->scaleY;
  2683. float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  2684. float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  2685. if (myData->mapMode == MM_ISOTROPIC)
  2686. {
  2687. if (sX < sY)
  2688. {
  2689. sY = sX;
  2690. }
  2691. else
  2692. {
  2693. sX = sY;
  2694. }
  2695. }
  2696. myData->scaleX = sX;
  2697. myData->scaleY = sY;
  2698. myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
  2699. myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
  2700. Gdiplus::Matrix matrix;
  2701. matrix.Scale(sX, sY);
  2702. matrix.Translate(myData->dx, myData->dy);
  2703. matrix.Translate(-oldDx, -oldDy);
  2704. matrix.Scale(1 / oldSx, 1 / oldSy);
  2705. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  2706. }
  2707. }
  2708. break;
  2709. case EMR_SETWINDOWORGEX:
  2710. {
  2711. PEMRSETWINDOWORGEX pWindowOrg = (PEMRSETWINDOWORGEX)lpEMFR;
  2712. if ((pWindowOrg->ptlOrigin.x != myData->windowOrg.x) &&
  2713. (pWindowOrg->ptlOrigin.y != myData->windowOrg.y))
  2714. {
  2715. myData->windowOrg = pWindowOrg->ptlOrigin;
  2716. float oldDx = myData->dx;
  2717. float oldDy = myData->dy;
  2718. float oldSx = myData->scaleX;
  2719. float oldSy = myData->scaleY;
  2720. myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x;
  2721. myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y;
  2722. Gdiplus::Matrix matrix;
  2723. matrix.Scale(oldSx, oldSy);
  2724. matrix.Translate(myData->dx, myData->dy);
  2725. matrix.Translate(-oldDx, -oldDy);
  2726. matrix.Scale(1 / oldSx, 1 / oldSy);
  2727. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  2728. }
  2729. }
  2730. break;
  2731. case EMR_SETVIEWPORTEXTEX:
  2732. {
  2733. PEMRSETVIEWPORTEXTEX pViewportExt = (PEMRSETVIEWPORTEXTEX)lpEMFR;
  2734. if (((myData->mapMode == MM_ANISOTROPIC) ||
  2735. (myData->mapMode == MM_ISOTROPIC)) &&
  2736. (pViewportExt->szlExtent.cx > 0) &&
  2737. (pViewportExt->szlExtent.cy > 0) &&
  2738. (pViewportExt->szlExtent.cx != myData->viewportExtent.cx) &&
  2739. (pViewportExt->szlExtent.cy != myData->viewportExtent.cy))
  2740. {
  2741. myData->viewportExtent = pViewportExt->szlExtent;
  2742. float oldDx = myData->dx;
  2743. float oldDy = myData->dy;
  2744. float oldSx = myData->scaleX;
  2745. float oldSy = myData->scaleY;
  2746. float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  2747. float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  2748. if (myData->mapMode == MM_ISOTROPIC)
  2749. {
  2750. if (sX < sY)
  2751. {
  2752. sY = sX;
  2753. }
  2754. else
  2755. {
  2756. sX = sY;
  2757. }
  2758. }
  2759. myData->scaleX = sX;
  2760. myData->scaleY = sY;
  2761. myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
  2762. myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
  2763. Gdiplus::Matrix matrix;
  2764. matrix.Scale(sX, sY);
  2765. matrix.Translate(myData->dx, myData->dy);
  2766. matrix.Translate(-oldDx, -oldDy);
  2767. matrix.Scale(1 / oldSx, 1 / oldSy);
  2768. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  2769. }
  2770. }
  2771. break;
  2772. case EMR_SETVIEWPORTORGEX:
  2773. {
  2774. PEMRSETVIEWPORTORGEX pViewportOrg = (PEMRSETVIEWPORTORGEX)lpEMFR;
  2775. if ((pViewportOrg->ptlOrigin.x != myData->viewportOrg.x) &&
  2776. (pViewportOrg->ptlOrigin.y != myData->viewportOrg.y))
  2777. {
  2778. myData->viewportOrg = pViewportOrg->ptlOrigin;
  2779. float oldDx = myData->dx;
  2780. float oldDy = myData->dy;
  2781. float oldSx = myData->scaleX;
  2782. float oldSy = myData->scaleY;
  2783. myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x;
  2784. myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y;
  2785. Gdiplus::Matrix matrix;
  2786. matrix.Scale(oldSx, oldSy);
  2787. matrix.Translate(myData->dx, myData->dy);
  2788. matrix.Translate(-oldDx, -oldDy);
  2789. matrix.Scale(1 / oldSx, 1 / oldSy);
  2790. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  2791. }
  2792. }
  2793. break;
  2794. case EMR_SETBRUSHORGEX:
  2795. break;
  2796. case EMR_EOF:
  2797. g->EndContainer(myData->containerId);
  2798. break;
  2799. case EMR_SETPIXELV:
  2800. {
  2801. PEMRSETPIXELV pSetPixel = (PEMRSETPIXELV)lpEMFR;
  2802. COLORREF cRef = pSetPixel->crColor;
  2803. ASSERT((cRef & 0x01000000) == 0);
  2804. Gdiplus::SolidBrush brush(Gdiplus::Color(Gdiplus::Color::MakeARGB(0xff,
  2805. GetRValue(cRef), GetGValue(cRef), GetBValue(cRef))));
  2806. g->FillRectangle(&brush, TOREAL(pSetPixel->ptlPixel.x), TOREAL(pSetPixel->ptlPixel.y), TOREAL(1), TOREAL(1));
  2807. }
  2808. break;
  2809. case EMR_SETMAPPERFLAGS: // for font mapping
  2810. break;
  2811. case EMR_SETMAPMODE:
  2812. {
  2813. PEMRSETMAPMODE pMapMode = (PEMRSETMAPMODE)lpEMFR;
  2814. if (myData->mapMode != pMapMode->iMode)
  2815. {
  2816. float sX, sY;
  2817. myData->mapMode = pMapMode->iMode;
  2818. switch (pMapMode->iMode)
  2819. {
  2820. case MM_TEXT:
  2821. g->SetPageUnit(Gdiplus::UnitPixel);
  2822. sX = sY = 1;
  2823. break;
  2824. case MM_LOMETRIC:
  2825. g->SetPageUnit(Gdiplus::UnitMillimeter);
  2826. g->SetPageScale(TOREAL(.1));
  2827. sX = sY = 1;
  2828. break;
  2829. case MM_HIMETRIC:
  2830. g->SetPageUnit(Gdiplus::UnitMillimeter);
  2831. g->SetPageScale(TOREAL(.01));
  2832. sX = sY = 1;
  2833. break;
  2834. case MM_LOENGLISH:
  2835. g->SetPageUnit(Gdiplus::UnitInch);
  2836. g->SetPageScale(TOREAL(.01));
  2837. sX = sY = 1;
  2838. break;
  2839. case MM_HIENGLISH:
  2840. g->SetPageUnit(Gdiplus::UnitInch);
  2841. g->SetPageScale(TOREAL(.001));
  2842. sX = sY = 1;
  2843. break;
  2844. case MM_TWIPS:
  2845. g->SetPageUnit(Gdiplus::UnitPoint);
  2846. g->SetPageScale(TOREAL(.05));
  2847. sX = sY = 1;
  2848. break;
  2849. case MM_ISOTROPIC:
  2850. g->SetPageUnit(Gdiplus::UnitPixel);
  2851. sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  2852. sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  2853. if (sX < sY)
  2854. {
  2855. sY = sX;
  2856. }
  2857. else
  2858. {
  2859. sX = sY;
  2860. }
  2861. break;
  2862. case MM_ANISOTROPIC:
  2863. g->SetPageUnit(Gdiplus::UnitPixel);
  2864. sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  2865. sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  2866. break;
  2867. }
  2868. float oldDx = myData->dx;
  2869. float oldDy = myData->dy;
  2870. float oldSx = myData->scaleX;
  2871. float oldSy = myData->scaleY;
  2872. myData->scaleX = sX;
  2873. myData->scaleY = sY;
  2874. myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
  2875. myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
  2876. Gdiplus::Matrix matrix;
  2877. matrix.Scale(sX, sY);
  2878. matrix.Translate(myData->dx, myData->dy);
  2879. matrix.Translate(-oldDx, -oldDy);
  2880. matrix.Scale(1 / oldSx, 1 / oldSy);
  2881. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  2882. }
  2883. }
  2884. break;
  2885. case EMR_SETBKMODE:
  2886. break;
  2887. case EMR_SETPOLYFILLMODE:
  2888. {
  2889. PEMRSETPOLYFILLMODE pPolyfillMode = (PEMRSETPOLYFILLMODE)lpEMFR;
  2890. myData->fillMode = (pPolyfillMode->iMode == ALTERNATE) ? Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding;
  2891. }
  2892. break;
  2893. case EMR_SETROP2:
  2894. break;
  2895. case EMR_SETSTRETCHBLTMODE:
  2896. #ifdef _DEBUG
  2897. {
  2898. PEMRSETSTRETCHBLTMODE pStretchBltMode = (PEMRSETSTRETCHBLTMODE)lpEMFR;
  2899. int mode;
  2900. switch (pStretchBltMode->iMode)
  2901. {
  2902. case BLACKONWHITE:
  2903. mode = 1;
  2904. break;
  2905. case WHITEONBLACK:
  2906. mode = 2;
  2907. break;
  2908. case COLORONCOLOR:
  2909. mode = 3;
  2910. break;
  2911. case HALFTONE:
  2912. mode = 4;
  2913. break;
  2914. }
  2915. }
  2916. #endif
  2917. break;
  2918. case EMR_SETTEXTALIGN:
  2919. break;
  2920. case EMR_SETCOLORADJUSTMENT:
  2921. break;
  2922. case EMR_SETTEXTCOLOR:
  2923. break;
  2924. case EMR_SETBKCOLOR:
  2925. break;
  2926. case EMR_OFFSETCLIPRGN:
  2927. {
  2928. PEMROFFSETCLIPRGN pOffsetClipRgn = (PEMROFFSETCLIPRGN)lpEMFR;
  2929. g->TranslateClip(TOREAL(pOffsetClipRgn->ptlOffset.x), TOREAL(pOffsetClipRgn->ptlOffset.y));
  2930. }
  2931. break;
  2932. case EMR_MOVETOEX:
  2933. {
  2934. PEMRMOVETOEX pMoveTo = (PEMRMOVETOEX)lpEMFR;
  2935. myData->curPos.X = TOREAL(pMoveTo->ptl.x);
  2936. myData->curPos.Y = TOREAL(pMoveTo->ptl.y);
  2937. }
  2938. break;
  2939. case EMR_SETMETARGN:
  2940. break;
  2941. case EMR_EXCLUDECLIPRECT:
  2942. {
  2943. PEMREXCLUDECLIPRECT pExcludeClipRect = (PEMREXCLUDECLIPRECT)lpEMFR;
  2944. Gdiplus::RectF clipRect(TOREAL(pExcludeClipRect->rclClip.left),
  2945. TOREAL(pExcludeClipRect->rclClip.top),
  2946. TOREAL(pExcludeClipRect->rclClip.right - pExcludeClipRect->rclClip.left),
  2947. TOREAL(pExcludeClipRect->rclClip.bottom - pExcludeClipRect->rclClip.top));
  2948. g->ExcludeClip(clipRect);
  2949. }
  2950. break;
  2951. case EMR_INTERSECTCLIPRECT:
  2952. {
  2953. PEMRINTERSECTCLIPRECT pIntersectClipRect = (PEMRINTERSECTCLIPRECT)lpEMFR;
  2954. Gdiplus::RectF eRect;
  2955. eRect.X = TOREAL(pIntersectClipRect->rclClip.left);
  2956. eRect.Y = TOREAL(pIntersectClipRect->rclClip.top);
  2957. eRect.Width = TOREAL(pIntersectClipRect->rclClip.right - pIntersectClipRect->rclClip.left);
  2958. eRect.Height = TOREAL(pIntersectClipRect->rclClip.bottom - pIntersectClipRect->rclClip.top);
  2959. g->IntersectClip(eRect);
  2960. }
  2961. break;
  2962. case EMR_SCALEVIEWPORTEXTEX:
  2963. {
  2964. PEMRSCALEVIEWPORTEXTEX pViewportExt = (PEMRSCALEVIEWPORTEXTEX)lpEMFR;
  2965. if (((myData->mapMode == MM_ANISOTROPIC) ||
  2966. (myData->mapMode == MM_ISOTROPIC)) &&
  2967. (pViewportExt->xNum != 0) &&
  2968. (pViewportExt->yNum != 0) &&
  2969. (pViewportExt->xDenom != 0) &&
  2970. (pViewportExt->yDenom != 0))
  2971. {
  2972. myData->viewportExtent.cx = (myData->viewportExtent.cx * pViewportExt->xNum) / pViewportExt->xDenom;
  2973. myData->viewportExtent.cy = (myData->viewportExtent.cy * pViewportExt->yNum) / pViewportExt->yDenom;
  2974. float oldDx = myData->dx;
  2975. float oldDy = myData->dy;
  2976. float oldSx = myData->scaleX;
  2977. float oldSy = myData->scaleY;
  2978. float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  2979. float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  2980. if (myData->mapMode == MM_ISOTROPIC)
  2981. {
  2982. if (sX < sY)
  2983. {
  2984. sY = sX;
  2985. }
  2986. else
  2987. {
  2988. sX = sY;
  2989. }
  2990. }
  2991. myData->scaleX = sX;
  2992. myData->scaleY = sY;
  2993. myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
  2994. myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
  2995. Gdiplus::Matrix matrix;
  2996. matrix.Scale(sX, sY);
  2997. matrix.Translate(myData->dx, myData->dy);
  2998. matrix.Translate(-oldDx, -oldDy);
  2999. matrix.Scale(1 / oldSx, 1 / oldSy);
  3000. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  3001. }
  3002. }
  3003. break;
  3004. case EMR_SCALEWINDOWEXTEX:
  3005. {
  3006. PEMRSCALEWINDOWEXTEX pWindowExt = (PEMRSCALEWINDOWEXTEX)lpEMFR;
  3007. if (((myData->mapMode == MM_ANISOTROPIC) ||
  3008. (myData->mapMode == MM_ISOTROPIC)) &&
  3009. (pWindowExt->xNum != 0) &&
  3010. (pWindowExt->yNum != 0) &&
  3011. (pWindowExt->xDenom != 0) &&
  3012. (pWindowExt->yDenom != 0))
  3013. {
  3014. myData->windowExtent.cx = (myData->windowExtent.cx * pWindowExt->xNum) / pWindowExt->xDenom;
  3015. myData->windowExtent.cy = (myData->windowExtent.cy * pWindowExt->yNum) / pWindowExt->yDenom;
  3016. float oldDx = myData->dx;
  3017. float oldDy = myData->dy;
  3018. float oldSx = myData->scaleX;
  3019. float oldSy = myData->scaleY;
  3020. float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx;
  3021. float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy;
  3022. if (myData->mapMode == MM_ISOTROPIC)
  3023. {
  3024. if (sX < sY)
  3025. {
  3026. sY = sX;
  3027. }
  3028. else
  3029. {
  3030. sX = sY;
  3031. }
  3032. }
  3033. myData->scaleX = sX;
  3034. myData->scaleY = sY;
  3035. myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x;
  3036. myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y;
  3037. Gdiplus::Matrix matrix;
  3038. matrix.Scale(sX, sY);
  3039. matrix.Translate(myData->dx, myData->dy);
  3040. matrix.Translate(-oldDx, -oldDy);
  3041. matrix.Scale(1 / oldSx, 1 / oldSy);
  3042. g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend);
  3043. }
  3044. }
  3045. break;
  3046. case EMR_SAVEDC:
  3047. {
  3048. myData->PushId(g->Save());
  3049. }
  3050. break;
  3051. case EMR_RESTOREDC:
  3052. {
  3053. g->Restore(myData->PopId());
  3054. }
  3055. break;
  3056. case EMR_SETWORLDTRANSFORM:
  3057. {
  3058. PEMRSETWORLDTRANSFORM pXform = (PEMRSETWORLDTRANSFORM)lpEMFR;
  3059. Gdiplus::Matrix newMatrix(pXform->xform.eM11,
  3060. pXform->xform.eM12,
  3061. pXform->xform.eM21,
  3062. pXform->xform.eM22,
  3063. pXform->xform.eDx,
  3064. pXform->xform.eDy);
  3065. if (newMatrix.IsInvertible())
  3066. {
  3067. myData->matrix.Invert();
  3068. myData->matrix.Multiply(&newMatrix);
  3069. g->MultiplyTransform(&(myData->matrix));
  3070. myData->matrix.SetElements(pXform->xform.eM11,
  3071. pXform->xform.eM12,
  3072. pXform->xform.eM21,
  3073. pXform->xform.eM22,
  3074. pXform->xform.eDx,
  3075. pXform->xform.eDy);
  3076. }
  3077. }
  3078. break;
  3079. case EMR_MODIFYWORLDTRANSFORM:
  3080. {
  3081. PEMRMODIFYWORLDTRANSFORM pXform = (PEMRMODIFYWORLDTRANSFORM)lpEMFR;
  3082. switch (pXform->iMode)
  3083. {
  3084. case MWT_IDENTITY:
  3085. default:
  3086. {
  3087. myData->matrix.Invert();
  3088. g->MultiplyTransform(&(myData->matrix));
  3089. myData->matrix.Reset();
  3090. }
  3091. break;
  3092. case MWT_LEFTMULTIPLY:
  3093. {
  3094. Gdiplus::Matrix newMatrix(pXform->xform.eM11,
  3095. pXform->xform.eM12,
  3096. pXform->xform.eM21,
  3097. pXform->xform.eM22,
  3098. pXform->xform.eDx,
  3099. pXform->xform.eDy);
  3100. if (newMatrix.IsInvertible())
  3101. {
  3102. myData->matrix.Multiply(&newMatrix);
  3103. g->MultiplyTransform(&newMatrix);
  3104. }
  3105. }
  3106. break;
  3107. case MWT_RIGHTMULTIPLY:
  3108. {
  3109. Gdiplus::Matrix newMatrix(pXform->xform.eM11,
  3110. pXform->xform.eM12,
  3111. pXform->xform.eM21,
  3112. pXform->xform.eM22,
  3113. pXform->xform.eDx,
  3114. pXform->xform.eDy);
  3115. if (newMatrix.IsInvertible())
  3116. {
  3117. Gdiplus::Matrix * inverse = myData->matrix.Clone();
  3118. inverse->Invert();
  3119. myData->matrix.Multiply(&newMatrix, Gdiplus::MatrixOrderAppend);
  3120. inverse->Multiply(&(myData->matrix));
  3121. g->MultiplyTransform(inverse);
  3122. delete inverse;
  3123. }
  3124. }
  3125. break;
  3126. }
  3127. }
  3128. break;
  3129. case EMR_SELECTOBJECT:
  3130. {
  3131. PEMRSELECTOBJECT pObject = (PEMRSELECTOBJECT)lpEMFR;
  3132. int objectIndex = pObject->ihObject;
  3133. if ((objectIndex & ENHMETA_STOCK_OBJECT) != 0)
  3134. {
  3135. switch (objectIndex & (~ENHMETA_STOCK_OBJECT))
  3136. {
  3137. case WHITE_BRUSH:
  3138. myData->curBrush = 0xFFFFFFFF;
  3139. break;
  3140. case LTGRAY_BRUSH:
  3141. myData->curBrush = 0xFFC0C0C0;
  3142. break;
  3143. case GRAY_BRUSH:
  3144. myData->curBrush = 0xFF808080;
  3145. break;
  3146. case DKGRAY_BRUSH:
  3147. myData->curBrush = 0xFF404040;
  3148. break;
  3149. case BLACK_BRUSH:
  3150. myData->curBrush = 0xFF000000;
  3151. break;
  3152. case NULL_BRUSH:
  3153. myData->curBrush = 0x00000000;
  3154. break;
  3155. case WHITE_PEN:
  3156. myData->curPen = 0xFFFFFFFF;
  3157. break;
  3158. case BLACK_PEN:
  3159. myData->curPen = 0xFF000000;
  3160. break;
  3161. case NULL_PEN:
  3162. myData->curPen = 0x00000000;
  3163. break;
  3164. }
  3165. }
  3166. else
  3167. {
  3168. ASSERT(objectIndex < myData->numObjects);
  3169. if (myData->pObjects[objectIndex].type == MYOBJECTS::PenObjectType)
  3170. {
  3171. myData->curPen = myData->pObjects[objectIndex].color;
  3172. myData->curPenWidth = myData->pObjects[objectIndex].penWidth;
  3173. }
  3174. else if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType)
  3175. {
  3176. myData->curBrush = myData->pObjects[objectIndex].color;
  3177. myData->curBrushPattern = myData->pObjects[objectIndex].brushPattern;
  3178. #if 1
  3179. myData->curPatIndex = myData->pObjects[objectIndex].patIndex;
  3180. #else
  3181. static dodo = 0;
  3182. myData->curPatIndex = dodo++ % 6;
  3183. #endif
  3184. }
  3185. }
  3186. }
  3187. break;
  3188. case EMR_CREATEPEN:
  3189. {
  3190. PEMRCREATEPEN pPen = (PEMRCREATEPEN)lpEMFR;
  3191. COLORREF cRef = pPen->lopn.lopnColor;
  3192. ASSERT((cRef & 0x01000000) == 0);
  3193. ASSERT(pPen->ihPen < myData->numObjects);
  3194. delete myData->pObjects[pPen->ihPen].brushPattern;
  3195. myData->pObjects[pPen->ihPen].brushPattern = NULL;
  3196. myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType;
  3197. myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff,
  3198. GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
  3199. myData->pObjects[pPen->ihPen].penWidth = pPen->lopn.lopnWidth.x;
  3200. }
  3201. break;
  3202. case EMR_CREATEBRUSHINDIRECT:
  3203. {
  3204. PEMRCREATEBRUSHINDIRECT pBrush = (PEMRCREATEBRUSHINDIRECT)lpEMFR;
  3205. COLORREF cRef = pBrush->lb.lbColor;
  3206. ASSERT((cRef & 0x01000000) == 0);
  3207. ASSERT(pBrush->ihBrush < myData->numObjects);
  3208. myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType;
  3209. myData->pObjects[pBrush->ihBrush].patIndex = -1;
  3210. delete myData->pObjects[pBrush->ihBrush].brushPattern;
  3211. myData->pObjects[pBrush->ihBrush].brushPattern = NULL;
  3212. if (pBrush->lb.lbStyle == BS_NULL)
  3213. {
  3214. myData->pObjects[pBrush->ihBrush].color = 0x00000000;
  3215. }
  3216. else
  3217. {
  3218. // Hatch Styles
  3219. if (pBrush->lb.lbStyle == BS_HATCHED)
  3220. {
  3221. switch (pBrush->lb.lbHatch)
  3222. {
  3223. case HS_HORIZONTAL: /* ----- */
  3224. case HS_VERTICAL: /* ||||| */
  3225. case HS_FDIAGONAL: /* \\\\\ */
  3226. case HS_BDIAGONAL: /* ///// */
  3227. case HS_CROSS: /* +++++ */
  3228. case HS_DIAGCROSS: /* xxxxx */
  3229. myData->pObjects[pBrush->ihBrush].patIndex = pBrush->lb.lbHatch;
  3230. break;
  3231. }
  3232. }
  3233. myData->pObjects[pBrush->ihBrush].color = Gdiplus::Color::MakeARGB(0xff,
  3234. GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
  3235. }
  3236. }
  3237. break;
  3238. case EMR_DELETEOBJECT:
  3239. {
  3240. #if 0
  3241. PEMRDELETEOBJECT pObject = (PEMRDELETEOBJECT)lpEMFR;
  3242. int objectIndex = pObject->ihObject;
  3243. ASSERT(objectIndex < myData->numObjects);
  3244. if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType)
  3245. {
  3246. if (myData->curBrushPattern != myData->pObjects[objectIndex].brushPattern)
  3247. {
  3248. delete myData->pObjects[objectIndex].brushPattern;
  3249. myData->pObjects[objectIndex].brushPattern = NULL;
  3250. }
  3251. }
  3252. #endif
  3253. }
  3254. break;
  3255. case EMR_ANGLEARC:
  3256. break;
  3257. case EMR_ELLIPSE:
  3258. {
  3259. PEMRELLIPSE pEllipse = (PEMRELLIPSE)lpEMFR;
  3260. float x = TOREAL(pEllipse->rclBox.left);
  3261. float y = TOREAL(pEllipse->rclBox.top);
  3262. float w = TOREAL(pEllipse->rclBox.right - x);
  3263. float h = TOREAL(pEllipse->rclBox.bottom - y);
  3264. if (!myData->pathOpen)
  3265. {
  3266. Gdiplus::GraphicsPath path(myData->fillMode);
  3267. path.AddEllipse(x, y, w, h);
  3268. if (myData->curBrush != 0)
  3269. {
  3270. if (myData->curPatIndex < 0)
  3271. {
  3272. if (myData->curBrushPattern == NULL)
  3273. {
  3274. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3275. g->FillPath(&brush, &path);
  3276. }
  3277. else
  3278. {
  3279. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3280. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3281. DibBrush brush(bmi, bits);
  3282. g->FillPath(brush, &path);
  3283. }
  3284. }
  3285. else
  3286. {
  3287. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3288. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3289. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3290. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3291. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3292. DibBrush brush(bmi, bits);
  3293. g->FillPath(brush, &path);
  3294. }
  3295. }
  3296. if (myData->curPen != 0)
  3297. {
  3298. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3299. pen.SetMiterLimit(myData->miterLimit);
  3300. g->DrawPath(&pen, &path);
  3301. }
  3302. }
  3303. else
  3304. {
  3305. myData->path->AddEllipse(x, y, w, h);
  3306. }
  3307. }
  3308. break;
  3309. case EMR_RECTANGLE:
  3310. {
  3311. PEMRRECTANGLE pRect = (PEMRRECTANGLE)lpEMFR;
  3312. float x = TOREAL(pRect->rclBox.left);
  3313. float y = TOREAL(pRect->rclBox.top);
  3314. float w = TOREAL(pRect->rclBox.right - x);
  3315. float h = TOREAL(pRect->rclBox.bottom - y);
  3316. if (!myData->pathOpen)
  3317. {
  3318. if (myData->curBrush != 0)
  3319. {
  3320. if (myData->curPatIndex < 0)
  3321. {
  3322. if (myData->curBrushPattern == NULL)
  3323. {
  3324. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3325. g->FillRectangle(&brush, x, y, w, h);
  3326. }
  3327. else
  3328. {
  3329. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3330. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3331. DibBrush brush(bmi, bits);
  3332. g->FillRectangle(brush, x, y, w, h);
  3333. }
  3334. }
  3335. else
  3336. {
  3337. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3338. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3339. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3340. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3341. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3342. DibBrush brush(bmi, bits);
  3343. g->FillRectangle(brush, x, y, w, h);
  3344. }
  3345. }
  3346. if (myData->curPen != 0)
  3347. {
  3348. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3349. pen.SetMiterLimit(myData->miterLimit);
  3350. g->DrawRectangle(&pen, x, y, w, h);
  3351. }
  3352. }
  3353. else
  3354. {
  3355. myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h));
  3356. }
  3357. }
  3358. break;
  3359. case EMR_ROUNDRECT: // for now, ignore the szlCorner param of round corners
  3360. {
  3361. PEMRROUNDRECT pRect = (PEMRROUNDRECT)lpEMFR;
  3362. float x = TOREAL(pRect->rclBox.left);
  3363. float y = TOREAL(pRect->rclBox.top);
  3364. float w = TOREAL(pRect->rclBox.right - x);
  3365. float h = TOREAL(pRect->rclBox.bottom - y);
  3366. if (!myData->pathOpen)
  3367. {
  3368. if (myData->curBrush != 0)
  3369. {
  3370. if (myData->curPatIndex < 0)
  3371. {
  3372. if (myData->curBrushPattern == NULL)
  3373. {
  3374. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3375. g->FillRectangle(&brush, x, y, w, h);
  3376. }
  3377. else
  3378. {
  3379. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3380. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3381. DibBrush brush(bmi, bits);
  3382. g->FillRectangle(brush, x, y, w, h);
  3383. }
  3384. }
  3385. else
  3386. {
  3387. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3388. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3389. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3390. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3391. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3392. DibBrush brush(bmi, bits);
  3393. g->FillRectangle(brush, x, y, w, h);
  3394. }
  3395. }
  3396. if (myData->curPen != 0)
  3397. {
  3398. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3399. pen.SetMiterLimit(myData->miterLimit);
  3400. g->DrawRectangle(&pen, x, y, w, h);
  3401. }
  3402. }
  3403. else
  3404. {
  3405. myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h));
  3406. }
  3407. }
  3408. break;
  3409. case EMR_ARC:
  3410. {
  3411. PEMRARC pArc = (PEMRARC)lpEMFR;
  3412. float x = TOREAL(pArc->rclBox.left);
  3413. float y = TOREAL(pArc->rclBox.top);
  3414. float w = TOREAL(pArc->rclBox.right - x);
  3415. float h = TOREAL(pArc->rclBox.bottom - y);
  3416. float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y));
  3417. float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y));
  3418. if (endAngle <= startAngle)
  3419. {
  3420. endAngle += 360;
  3421. }
  3422. float sweepAngle = endAngle - startAngle;
  3423. if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
  3424. {
  3425. sweepAngle = 360 - sweepAngle;
  3426. }
  3427. if (!myData->pathOpen)
  3428. {
  3429. if (myData->curPen != 0)
  3430. {
  3431. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3432. pen.SetMiterLimit(myData->miterLimit);
  3433. g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle);
  3434. }
  3435. }
  3436. else
  3437. {
  3438. myData->path->AddArc(x, y, w, h, startAngle, sweepAngle);
  3439. }
  3440. }
  3441. break;
  3442. case EMR_CHORD:
  3443. break;
  3444. case EMR_PIE:
  3445. {
  3446. PEMRARC pPie = (PEMRARC)lpEMFR;
  3447. float x = TOREAL(pPie->rclBox.left);
  3448. float y = TOREAL(pPie->rclBox.top);
  3449. float w = TOREAL(pPie->rclBox.right - x);
  3450. float h = TOREAL(pPie->rclBox.bottom - y);
  3451. float startAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlStart.x), TOREAL(pPie->ptlStart.y));
  3452. float endAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlEnd.x), TOREAL(pPie->ptlEnd.y));
  3453. if (endAngle <= startAngle)
  3454. {
  3455. endAngle += 360;
  3456. }
  3457. float sweepAngle = endAngle - startAngle;
  3458. if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
  3459. {
  3460. sweepAngle = 360 - sweepAngle;
  3461. }
  3462. if (!myData->pathOpen)
  3463. {
  3464. Gdiplus::GraphicsPath path(myData->fillMode);
  3465. path.AddPie(x, y, w, h, startAngle, sweepAngle);
  3466. if (myData->curBrush != 0)
  3467. {
  3468. if (myData->curPatIndex < 0)
  3469. {
  3470. if (myData->curBrushPattern == NULL)
  3471. {
  3472. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3473. g->FillPath(&brush, &path);
  3474. }
  3475. else
  3476. {
  3477. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3478. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3479. DibBrush brush(bmi, bits);
  3480. g->FillPath(brush, &path);
  3481. }
  3482. }
  3483. else
  3484. {
  3485. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3486. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3487. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3488. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3489. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3490. DibBrush brush(bmi, bits);
  3491. g->FillPath(brush, &path);
  3492. }
  3493. }
  3494. if (myData->curPen != 0)
  3495. {
  3496. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3497. pen.SetMiterLimit(myData->miterLimit);
  3498. g->DrawPath(&pen, &path);
  3499. }
  3500. }
  3501. else
  3502. {
  3503. myData->path->AddPie(x, y, w, h, startAngle, sweepAngle);
  3504. }
  3505. }
  3506. break;
  3507. case EMR_SELECTPALETTE:
  3508. break;
  3509. case EMR_CREATEPALETTE:
  3510. break;
  3511. case EMR_SETPALETTEENTRIES:
  3512. break;
  3513. case EMR_RESIZEPALETTE:
  3514. break;
  3515. case EMR_REALIZEPALETTE:
  3516. break;
  3517. case EMR_EXTFLOODFILL:
  3518. break;
  3519. case EMR_LINETO:
  3520. {
  3521. PEMRMOVETOEX pLineTo = (PEMRMOVETOEX)lpEMFR;
  3522. float x = TOREAL(pLineTo->ptl.x);
  3523. float y = TOREAL(pLineTo->ptl.y);
  3524. if (!myData->pathOpen)
  3525. {
  3526. if (myData->curPen != 0)
  3527. {
  3528. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3529. pen.SetMiterLimit(myData->miterLimit);
  3530. g->DrawLine(&pen, (float)myData->curPos.X, (float)myData->curPos.Y, x, y);
  3531. }
  3532. }
  3533. else
  3534. {
  3535. myData->path->AddLine((float)myData->curPos.X, (float)myData->curPos.Y, x, y);
  3536. }
  3537. myData->curPos.X = x;
  3538. myData->curPos.Y = y;
  3539. }
  3540. break;
  3541. case EMR_ARCTO:
  3542. {
  3543. // !!! Set and use current position
  3544. PEMRARCTO pArc = (PEMRARCTO)lpEMFR;
  3545. float x = TOREAL(pArc->rclBox.left);
  3546. float y = TOREAL(pArc->rclBox.top);
  3547. float w = TOREAL(pArc->rclBox.right - x);
  3548. float h = TOREAL(pArc->rclBox.bottom - y);
  3549. float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y));
  3550. float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y));
  3551. if (endAngle <= startAngle)
  3552. {
  3553. endAngle += 360;
  3554. }
  3555. float sweepAngle = endAngle - startAngle;
  3556. if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360))
  3557. {
  3558. sweepAngle = 360 - sweepAngle;
  3559. }
  3560. if (!myData->pathOpen)
  3561. {
  3562. if (myData->curPen != 0)
  3563. {
  3564. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3565. pen.SetMiterLimit(myData->miterLimit);
  3566. g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle);
  3567. }
  3568. }
  3569. else
  3570. {
  3571. myData->path->AddArc(x, y, w, h, startAngle, sweepAngle);
  3572. }
  3573. }
  3574. break;
  3575. case EMR_POLYDRAW:
  3576. break;
  3577. case EMR_SETARCDIRECTION:
  3578. {
  3579. PEMRSETARCDIRECTION pArcDirection = (PEMRSETARCDIRECTION)lpEMFR;
  3580. myData->arcDirection = pArcDirection->iArcDirection;
  3581. }
  3582. break;
  3583. case EMR_SETMITERLIMIT:
  3584. {
  3585. PEMRSETMITERLIMIT pMiterLimit = (PEMRSETMITERLIMIT)lpEMFR;
  3586. myData->miterLimit = pMiterLimit->eMiterLimit;
  3587. }
  3588. break;
  3589. case EMR_BEGINPATH:
  3590. {
  3591. delete myData->path;
  3592. myData->path = new Gdiplus::GraphicsPath (myData->fillMode);
  3593. myData->pathOpen = (myData->path != NULL);
  3594. }
  3595. break;
  3596. case EMR_ENDPATH:
  3597. myData->pathOpen = FALSE;
  3598. break;
  3599. case EMR_CLOSEFIGURE:
  3600. {
  3601. if (myData->pathOpen)
  3602. {
  3603. myData->path->CloseFigure();
  3604. }
  3605. }
  3606. break;
  3607. case EMR_FILLPATH:
  3608. {
  3609. if (myData->path != NULL)
  3610. {
  3611. if (myData->curBrush != 0)
  3612. {
  3613. if (myData->curPatIndex < 0)
  3614. {
  3615. if (myData->curBrushPattern == NULL)
  3616. {
  3617. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3618. g->FillPath(&brush, myData->path);
  3619. }
  3620. else
  3621. {
  3622. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3623. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3624. DibBrush brush(bmi, bits);
  3625. g->FillPath(brush, myData->path);
  3626. }
  3627. }
  3628. else
  3629. {
  3630. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3631. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3632. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3633. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3634. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3635. DibBrush brush(bmi, bits);
  3636. g->FillPath(brush, myData->path);
  3637. }
  3638. }
  3639. delete myData->path;
  3640. myData->path = NULL;
  3641. myData->pathOpen = FALSE;
  3642. }
  3643. }
  3644. break;
  3645. case EMR_STROKEANDFILLPATH:
  3646. {
  3647. if (myData->path != NULL)
  3648. {
  3649. if (myData->curBrush != 0)
  3650. {
  3651. if (myData->curPatIndex < 0)
  3652. {
  3653. if (myData->curBrushPattern == NULL)
  3654. {
  3655. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3656. g->FillPath(&brush, myData->path);
  3657. }
  3658. else
  3659. {
  3660. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3661. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3662. DibBrush brush(bmi, bits);
  3663. g->FillPath(brush, myData->path);
  3664. }
  3665. }
  3666. else
  3667. {
  3668. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3669. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3670. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3671. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3672. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3673. DibBrush brush(bmi, bits);
  3674. g->FillPath(brush, myData->path);
  3675. }
  3676. }
  3677. if (myData->curPen != 0)
  3678. {
  3679. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3680. pen.SetMiterLimit(myData->miterLimit);
  3681. g->DrawPath(&pen, myData->path);
  3682. }
  3683. delete myData->path;
  3684. myData->path = NULL;
  3685. myData->pathOpen = FALSE;
  3686. }
  3687. }
  3688. break;
  3689. case EMR_STROKEPATH:
  3690. {
  3691. if (myData->path != NULL)
  3692. {
  3693. if (myData->curPen != 0)
  3694. {
  3695. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3696. pen.SetMiterLimit(myData->miterLimit);
  3697. g->DrawPath(&pen, myData->path);
  3698. }
  3699. delete myData->path;
  3700. myData->path = NULL;
  3701. myData->pathOpen = FALSE;
  3702. }
  3703. }
  3704. break;
  3705. case EMR_FLATTENPATH:
  3706. {
  3707. if (myData->path != NULL)
  3708. {
  3709. myData->path->Flatten(NULL);
  3710. }
  3711. }
  3712. break;
  3713. case EMR_WIDENPATH:
  3714. {
  3715. if (myData->path != NULL)
  3716. {
  3717. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  3718. pen.SetMiterLimit(myData->miterLimit);
  3719. myData->path->Widen(&pen);
  3720. }
  3721. }
  3722. break;
  3723. case EMR_SELECTCLIPPATH:
  3724. {
  3725. if (myData->path != NULL)
  3726. {
  3727. PEMRSELECTCLIPPATH pSetClipPath = (PEMRSELECTCLIPPATH)lpEMFR;
  3728. switch (pSetClipPath->iMode)
  3729. {
  3730. case RGN_COPY:
  3731. default:
  3732. g->SetClip(myData->path);
  3733. break;
  3734. case RGN_AND:
  3735. {
  3736. Gdiplus::Region region(myData->path);
  3737. g->IntersectClip(&region);
  3738. }
  3739. break;
  3740. case RGN_DIFF:
  3741. {
  3742. Gdiplus::Region region(myData->path);
  3743. Gdiplus::Region curClip;
  3744. g->GetClip(&curClip);
  3745. curClip.Exclude(&region);
  3746. g->SetClip(&curClip);
  3747. }
  3748. break;
  3749. case RGN_OR:
  3750. {
  3751. Gdiplus::Region region(myData->path);
  3752. Gdiplus::Region curClip;
  3753. g->GetClip(&curClip);
  3754. curClip.Union(&region);
  3755. g->SetClip(&curClip);
  3756. }
  3757. break;
  3758. case RGN_XOR:
  3759. {
  3760. Gdiplus::Region region(myData->path);
  3761. Gdiplus::Region curClip;
  3762. g->GetClip(&curClip);
  3763. curClip.Xor(&region);
  3764. g->SetClip(&curClip);
  3765. }
  3766. break;
  3767. }
  3768. delete myData->path;
  3769. myData->path = NULL;
  3770. myData->pathOpen = FALSE;
  3771. }
  3772. }
  3773. break;
  3774. case EMR_ABORTPATH:
  3775. {
  3776. if (myData->path != NULL)
  3777. {
  3778. delete myData->path;
  3779. myData->path = NULL;
  3780. myData->pathOpen = FALSE;
  3781. }
  3782. }
  3783. break;
  3784. case EMR_GDICOMMENT:
  3785. break;
  3786. case EMR_FILLRGN:
  3787. break;
  3788. case EMR_FRAMERGN:
  3789. break;
  3790. case EMR_INVERTRGN:
  3791. break;
  3792. case EMR_PAINTRGN:
  3793. break;
  3794. case EMR_EXTSELECTCLIPRGN:
  3795. break;
  3796. case EMR_BITBLT:
  3797. {
  3798. PEMRBITBLT pBitBlt = (PEMRBITBLT)lpEMFR;
  3799. switch (pBitBlt->dwRop)
  3800. {
  3801. case BLACKNESS:
  3802. {
  3803. Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
  3804. float cx, cy;
  3805. GetPixelSize (g, &cx, &cy);
  3806. g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
  3807. }
  3808. return;
  3809. case WHITENESS:
  3810. {
  3811. Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
  3812. float cx, cy;
  3813. GetPixelSize (g, &cx, &cy);
  3814. g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + 1), TOREAL(pBitBlt->cyDest + 1));
  3815. }
  3816. return;
  3817. default:
  3818. if (!ISSOURCEINROP3(pBitBlt->dwRop))
  3819. {
  3820. if (myData->curBrush != 0)
  3821. {
  3822. if (myData->curPatIndex < 0)
  3823. {
  3824. if (myData->curBrushPattern == NULL)
  3825. {
  3826. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3827. float cx, cy;
  3828. GetPixelSize (g, &cx, &cy);
  3829. g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
  3830. }
  3831. else
  3832. {
  3833. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3834. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3835. DibBrush brush(bmi, bits);
  3836. float cx, cy;
  3837. GetPixelSize (g, &cx, &cy);
  3838. g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
  3839. }
  3840. }
  3841. else
  3842. {
  3843. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3844. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3845. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3846. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3847. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3848. DibBrush brush(bmi, bits);
  3849. float cx, cy;
  3850. GetPixelSize (g, &cx, &cy);
  3851. g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy));
  3852. }
  3853. }
  3854. return;
  3855. }
  3856. break;
  3857. }
  3858. // Else assume SRCCOPY
  3859. BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pBitBlt) + pBitBlt->offBmiSrc);
  3860. BYTE *bits = ((BYTE *)pBitBlt) + pBitBlt->offBitsSrc;
  3861. DibStream dibStream(bmi, bits);
  3862. Gdiplus::Bitmap gpBitmap(&dibStream);
  3863. Gdiplus::RectF destRect(TOREAL(pBitBlt->xDest),
  3864. TOREAL(pBitBlt->yDest),
  3865. TOREAL(pBitBlt->cxDest),
  3866. TOREAL(pBitBlt->cyDest));
  3867. g->DrawImage(&gpBitmap, destRect,
  3868. TOREAL(pBitBlt->xSrc),
  3869. TOREAL(pBitBlt->ySrc),
  3870. TOREAL(pBitBlt->cxDest),
  3871. TOREAL(pBitBlt->cyDest),
  3872. Gdiplus::UnitPixel);
  3873. }
  3874. break;
  3875. case EMR_STRETCHBLT:
  3876. {
  3877. PEMRSTRETCHBLT pStretchBlt = (PEMRSTRETCHBLT)lpEMFR;
  3878. switch (pStretchBlt->dwRop)
  3879. {
  3880. case BLACKNESS:
  3881. {
  3882. Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
  3883. float cx, cy;
  3884. GetPixelSize (g, &cx, &cy);
  3885. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3886. }
  3887. return;
  3888. case WHITENESS:
  3889. {
  3890. Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
  3891. float cx, cy;
  3892. GetPixelSize (g, &cx, &cy);
  3893. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3894. }
  3895. return;
  3896. default:
  3897. if (!ISSOURCEINROP3(pStretchBlt->dwRop))
  3898. {
  3899. float cx, cy;
  3900. GetPixelSize (g, &cx, &cy);
  3901. if (myData->curBrush != 0)
  3902. {
  3903. if (myData->curPatIndex < 0)
  3904. {
  3905. if (myData->curBrushPattern == NULL)
  3906. {
  3907. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  3908. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3909. }
  3910. else
  3911. {
  3912. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  3913. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  3914. DibBrush brush(bmi, bits);
  3915. g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3916. }
  3917. }
  3918. else
  3919. {
  3920. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  3921. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  3922. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  3923. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  3924. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  3925. DibBrush brush(bmi, bits);
  3926. g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3927. }
  3928. }
  3929. return;
  3930. }
  3931. break;
  3932. }
  3933. // Else assume SRCCOPY
  3934. BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc);
  3935. BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc;
  3936. DibStream dibStream(bmi, bits);
  3937. Gdiplus::Bitmap gpBitmap(&dibStream);
  3938. Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest),
  3939. TOREAL(pStretchBlt->yDest),
  3940. TOREAL(pStretchBlt->cxDest),
  3941. TOREAL(pStretchBlt->cyDest));
  3942. g->DrawImage(&gpBitmap, destRect,
  3943. TOREAL(pStretchBlt->xSrc),
  3944. TOREAL(pStretchBlt->ySrc),
  3945. TOREAL(pStretchBlt->cxSrc),
  3946. TOREAL(pStretchBlt->cySrc),
  3947. Gdiplus::UnitPixel);
  3948. }
  3949. break;
  3950. case EMR_MASKBLT:
  3951. break;
  3952. case EMR_PLGBLT:
  3953. break;
  3954. case EMR_SETDIBITSTODEVICE:
  3955. break;
  3956. #if 0
  3957. typedef struct tagEMRSETDIBITSTODEVICE
  3958. {
  3959. EMR emr;
  3960. RECTL rclBounds; // Inclusive-inclusive bounds in device units
  3961. LONG xDest;
  3962. LONG yDest;
  3963. LONG xSrc;
  3964. LONG ySrc;
  3965. LONG cxSrc;
  3966. LONG cySrc;
  3967. DWORD offBmiSrc; // Offset to the source BITMAPINFO structure
  3968. DWORD cbBmiSrc; // Size of the source BITMAPINFO structure
  3969. DWORD offBitsSrc; // Offset to the source bitmap bits
  3970. DWORD cbBitsSrc; // Size of the source bitmap bits
  3971. DWORD iUsageSrc; // Source bitmap info color table usage
  3972. DWORD iStartScan;
  3973. DWORD cScans;
  3974. } EMRSETDIBITSTODEVICE, *PEMRSETDIBITSTODEVICE;
  3975. #endif
  3976. case EMR_STRETCHDIBITS:
  3977. {
  3978. PEMRSTRETCHDIBITS pStretchBlt = (PEMRSTRETCHDIBITS)lpEMFR;
  3979. switch (pStretchBlt->dwRop)
  3980. {
  3981. case BLACKNESS:
  3982. {
  3983. float cx, cy;
  3984. GetPixelSize (g, &cx, &cy);
  3985. Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000));
  3986. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3987. }
  3988. return;
  3989. case WHITENESS:
  3990. {
  3991. float cx, cy;
  3992. GetPixelSize (g, &cx, &cy);
  3993. Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff));
  3994. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  3995. }
  3996. return;
  3997. default:
  3998. if (!ISSOURCEINROP3(pStretchBlt->dwRop))
  3999. {
  4000. float cx, cy;
  4001. GetPixelSize (g, &cx, &cy);
  4002. if (myData->curBrush != 0)
  4003. {
  4004. if (myData->curPatIndex < 0)
  4005. {
  4006. if (myData->curBrushPattern == NULL)
  4007. {
  4008. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  4009. g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  4010. }
  4011. else
  4012. {
  4013. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  4014. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  4015. DibBrush brush(bmi, bits);
  4016. g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  4017. }
  4018. }
  4019. else
  4020. {
  4021. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  4022. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  4023. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  4024. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  4025. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  4026. DibBrush brush(bmi, bits);
  4027. g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy));
  4028. }
  4029. }
  4030. return;
  4031. }
  4032. break;
  4033. }
  4034. // Else assume SRCCOPY
  4035. BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc);
  4036. BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc;
  4037. DibStream dibStream(bmi, bits);
  4038. Gdiplus::Bitmap gpBitmap(&dibStream);
  4039. Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest),
  4040. TOREAL(pStretchBlt->yDest),
  4041. TOREAL(pStretchBlt->cxDest),
  4042. TOREAL(pStretchBlt->cyDest));
  4043. g->DrawImage(&gpBitmap, destRect,
  4044. TOREAL(pStretchBlt->xSrc),
  4045. TOREAL(pStretchBlt->ySrc),
  4046. TOREAL(pStretchBlt->cxSrc),
  4047. TOREAL(pStretchBlt->cySrc),
  4048. Gdiplus::UnitPixel);
  4049. }
  4050. break;
  4051. case EMR_EXTCREATEFONTINDIRECTW:
  4052. break;
  4053. case EMR_EXTTEXTOUTA:
  4054. break;
  4055. case EMR_EXTTEXTOUTW:
  4056. break;
  4057. case EMR_POLYBEZIER16:
  4058. {
  4059. PEMRPOLYBEZIER16 pBezier = (PEMRPOLYBEZIER16)lpEMFR;
  4060. if (pBezier->cpts > 0)
  4061. {
  4062. int i = pBezier->cpts;
  4063. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  4064. do
  4065. {
  4066. i--;
  4067. points[i].X = pBezier->apts[i].x;
  4068. points[i].Y = pBezier->apts[i].y;
  4069. } while (i > 0);
  4070. if (!myData->pathOpen)
  4071. {
  4072. if (myData->curPen != 0)
  4073. {
  4074. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4075. pen.SetMiterLimit(myData->miterLimit);
  4076. g->DrawBeziers(&pen, points, pBezier->cpts);
  4077. }
  4078. }
  4079. else
  4080. {
  4081. myData->path->AddBeziers(points, pBezier->cpts);
  4082. }
  4083. delete [] points;
  4084. }
  4085. }
  4086. break;
  4087. case EMR_POLYGON16:
  4088. {
  4089. PEMRPOLYGON16 pPolygon = (PEMRPOLYGON16)lpEMFR;
  4090. if (pPolygon->cpts > 0)
  4091. {
  4092. int i = pPolygon->cpts;
  4093. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  4094. do
  4095. {
  4096. i--;
  4097. points[i].X = pPolygon->apts[i].x;
  4098. points[i].Y = pPolygon->apts[i].y;
  4099. } while (i > 0);
  4100. if (!myData->pathOpen)
  4101. {
  4102. Gdiplus::GraphicsPath path(myData->fillMode);
  4103. path.AddPolygon(points, pPolygon->cpts);
  4104. if (myData->curBrush != 0)
  4105. {
  4106. if (myData->curPatIndex < 0)
  4107. {
  4108. if (myData->curBrushPattern == NULL)
  4109. {
  4110. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  4111. g->FillPath(&brush, &path);
  4112. }
  4113. else
  4114. {
  4115. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  4116. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  4117. DibBrush brush(bmi, bits);
  4118. g->FillPath(brush, &path);
  4119. }
  4120. }
  4121. else
  4122. {
  4123. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  4124. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  4125. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  4126. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  4127. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  4128. DibBrush brush(bmi, bits);
  4129. g->FillPath(brush, &path);
  4130. }
  4131. }
  4132. if (myData->curPen != 0)
  4133. {
  4134. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4135. pen.SetMiterLimit(myData->miterLimit);
  4136. g->DrawPath(&pen, &path);
  4137. }
  4138. }
  4139. else
  4140. {
  4141. myData->path->AddPolygon(points, pPolygon->cpts);
  4142. }
  4143. delete [] points;
  4144. }
  4145. }
  4146. break;
  4147. case EMR_POLYLINE16:
  4148. {
  4149. PEMRPOLYLINE16 pPolyline = (PEMRPOLYLINE16)lpEMFR;
  4150. if (pPolyline->cpts > 0)
  4151. {
  4152. int i = pPolyline->cpts;
  4153. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  4154. do
  4155. {
  4156. i--;
  4157. points[i].X = pPolyline->apts[i].x;
  4158. points[i].Y = pPolyline->apts[i].y;
  4159. } while (i > 0);
  4160. if (!myData->pathOpen)
  4161. {
  4162. if (myData->curPen != 0)
  4163. {
  4164. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4165. pen.SetMiterLimit(myData->miterLimit);
  4166. g->DrawLines(&pen, points, pPolyline->cpts);
  4167. }
  4168. }
  4169. else
  4170. {
  4171. myData->path->AddLines(points, pPolyline->cpts);
  4172. }
  4173. delete [] points;
  4174. }
  4175. }
  4176. break;
  4177. case EMR_POLYBEZIERTO16:
  4178. {
  4179. PEMRPOLYBEZIERTO16 pBezier = (PEMRPOLYBEZIERTO16)lpEMFR;
  4180. if (pBezier->cpts > 0)
  4181. {
  4182. int i = pBezier->cpts;
  4183. Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
  4184. do
  4185. {
  4186. points[i].X = pBezier->apts[i-1].x;
  4187. points[i].Y = pBezier->apts[i-1].y;
  4188. i--;
  4189. } while (i > 0);
  4190. points[0] = myData->curPos;
  4191. myData->curPos = points[pBezier->cpts];
  4192. if (!myData->pathOpen)
  4193. {
  4194. if (myData->curPen != 0)
  4195. {
  4196. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4197. pen.SetMiterLimit(myData->miterLimit);
  4198. g->DrawBeziers(&pen, points, pBezier->cpts+1);
  4199. }
  4200. }
  4201. else
  4202. {
  4203. myData->path->AddBeziers(points, pBezier->cpts+1);
  4204. }
  4205. delete [] points;
  4206. }
  4207. }
  4208. break;
  4209. case EMR_POLYLINETO16:
  4210. {
  4211. PEMRPOLYLINETO16 pPolyline = (PEMRPOLYLINETO16)lpEMFR;
  4212. if (pPolyline->cpts > 0)
  4213. {
  4214. int i = pPolyline->cpts;
  4215. Gdiplus::PointF * points = new Gdiplus::PointF[i+1];
  4216. do
  4217. {
  4218. points[i].X = pPolyline->apts[i-1].x;
  4219. points[i].Y = pPolyline->apts[i-1].y;
  4220. i--;
  4221. } while (i > 0);
  4222. points[0] = myData->curPos;
  4223. myData->curPos = points[pPolyline->cpts];
  4224. if (!myData->pathOpen)
  4225. {
  4226. if (myData->curPen != 0)
  4227. {
  4228. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4229. pen.SetMiterLimit(myData->miterLimit);
  4230. g->DrawLines(&pen, points, pPolyline->cpts+1);
  4231. }
  4232. }
  4233. else
  4234. {
  4235. myData->path->AddLines(points, pPolyline->cpts+1);
  4236. }
  4237. delete [] points;
  4238. }
  4239. }
  4240. break;
  4241. case EMR_POLYPOLYLINE16:
  4242. {
  4243. PEMRPOLYPOLYLINE16 pPolyline = (PEMRPOLYPOLYLINE16)lpEMFR;
  4244. if ((pPolyline->cpts > 0) && (pPolyline->nPolys > 0))
  4245. {
  4246. int i = pPolyline->cpts;
  4247. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  4248. POINTS * metaPoints = (POINTS *)(pPolyline->aPolyCounts + pPolyline->nPolys);
  4249. do
  4250. {
  4251. i--;
  4252. points[i].X = metaPoints[i].x;
  4253. points[i].Y = metaPoints[i].y;
  4254. } while (i > 0);
  4255. if (!myData->pathOpen)
  4256. {
  4257. if (myData->curPen != 0)
  4258. {
  4259. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4260. pen.SetMiterLimit(myData->miterLimit);
  4261. i = 0;
  4262. Gdiplus::PointF * tmpPoints = points;
  4263. DWORD count;
  4264. do
  4265. {
  4266. count = pPolyline->aPolyCounts[i];
  4267. g->DrawLines(&pen, tmpPoints, count);
  4268. tmpPoints += count;
  4269. } while ((UINT)++i < pPolyline->nPolys);
  4270. }
  4271. }
  4272. else
  4273. {
  4274. i = 0;
  4275. Gdiplus::PointF * tmpPoints = points;
  4276. DWORD count;
  4277. do
  4278. {
  4279. count = pPolyline->aPolyCounts[i];
  4280. myData->path->AddLines(tmpPoints, count);
  4281. tmpPoints += count;
  4282. } while ((UINT)++i < pPolyline->nPolys);
  4283. }
  4284. delete [] points;
  4285. }
  4286. }
  4287. break;
  4288. case EMR_POLYPOLYGON16:
  4289. {
  4290. PEMRPOLYPOLYGON16 pPolygon = (PEMRPOLYPOLYGON16)lpEMFR;
  4291. if ((pPolygon->cpts > 0) && (pPolygon->nPolys > 0))
  4292. {
  4293. int i = pPolygon->cpts;
  4294. Gdiplus::PointF * points = new Gdiplus::PointF[i];
  4295. POINTS * metaPoints = (POINTS *)(pPolygon->aPolyCounts + pPolygon->nPolys);
  4296. do
  4297. {
  4298. i--;
  4299. points[i].X = metaPoints[i].x;
  4300. points[i].Y = metaPoints[i].y;
  4301. } while (i > 0);
  4302. Gdiplus::GraphicsPath path(myData->fillMode);
  4303. Gdiplus::GraphicsPath * tmpPath = &path;
  4304. if (myData->pathOpen)
  4305. {
  4306. tmpPath = myData->path;
  4307. }
  4308. Gdiplus::PointF * tmpPoints = points;
  4309. DWORD count;
  4310. i = 0;
  4311. do
  4312. {
  4313. count = pPolygon->aPolyCounts[i];
  4314. tmpPath->StartFigure();
  4315. tmpPath->AddPolygon(tmpPoints, count);
  4316. tmpPoints += count;
  4317. } while ((UINT)++i < pPolygon->nPolys);
  4318. if (!myData->pathOpen)
  4319. {
  4320. if (myData->curBrush != 0)
  4321. {
  4322. if (myData->curPatIndex < 0)
  4323. {
  4324. if (myData->curBrushPattern == NULL)
  4325. {
  4326. Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush));
  4327. g->FillPath(&brush, &path);
  4328. }
  4329. else
  4330. {
  4331. BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi;
  4332. BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset;
  4333. DibBrush brush(bmi, bits);
  4334. g->FillPath(brush, &path);
  4335. }
  4336. }
  4337. else
  4338. {
  4339. BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo;
  4340. BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex];
  4341. bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift;
  4342. bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift;
  4343. bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift;
  4344. DibBrush brush(bmi, bits);
  4345. g->FillPath(brush, &path);
  4346. }
  4347. }
  4348. if (myData->curPen != 0)
  4349. {
  4350. Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth));
  4351. pen.SetMiterLimit(myData->miterLimit);
  4352. g->DrawPath(&pen, &path);
  4353. }
  4354. }
  4355. delete [] points;
  4356. }
  4357. }
  4358. break;
  4359. case EMR_POLYDRAW16:
  4360. break;
  4361. case EMR_CREATEMONOBRUSH:
  4362. break;
  4363. case EMR_CREATEDIBPATTERNBRUSHPT:
  4364. {
  4365. PEMRCREATEDIBPATTERNBRUSHPT pBrush = (PEMRCREATEDIBPATTERNBRUSHPT)lpEMFR;
  4366. ASSERT(pBrush->ihBrush < myData->numObjects);
  4367. myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType;
  4368. myData->pObjects[pBrush->ihBrush].color = 0xFF808080;
  4369. myData->pObjects[pBrush->ihBrush].patIndex = -1;
  4370. delete myData->pObjects[pBrush->ihBrush].brushPattern;
  4371. myData->pObjects[pBrush->ihBrush].brushPattern = new MYPATTERNBRUSH();
  4372. if (myData->pObjects[pBrush->ihBrush].brushPattern != NULL)
  4373. {
  4374. BYTE * data = new BYTE[pBrush->cbBmi + pBrush->cbBits];
  4375. if (data != NULL)
  4376. {
  4377. memcpy(data, ((BYTE *)pBrush) + pBrush->offBmi, pBrush->cbBmi);
  4378. memcpy(data + pBrush->cbBmi, ((BYTE *)pBrush) + pBrush->offBits, pBrush->cbBits);
  4379. myData->pObjects[pBrush->ihBrush].brushPattern->bmi = (BITMAPINFO *)data;
  4380. myData->pObjects[pBrush->ihBrush].brushPattern->bitsOffset = pBrush->cbBmi;
  4381. }
  4382. else
  4383. {
  4384. delete myData->pObjects[pBrush->ihBrush].brushPattern;
  4385. myData->pObjects[pBrush->ihBrush].brushPattern = NULL;
  4386. }
  4387. }
  4388. }
  4389. break;
  4390. case EMR_EXTCREATEPEN:
  4391. {
  4392. PEMREXTCREATEPEN pPen = (PEMREXTCREATEPEN)lpEMFR;
  4393. COLORREF cRef = pPen->elp.elpColor;
  4394. ASSERT((cRef & 0x01000000) == 0);
  4395. ASSERT(pPen->ihPen < myData->numObjects);
  4396. delete myData->pObjects[pPen->ihPen].brushPattern;
  4397. myData->pObjects[pPen->ihPen].brushPattern = NULL;
  4398. myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType;
  4399. myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff,
  4400. GetRValue(cRef), GetGValue(cRef), GetBValue(cRef));
  4401. myData->pObjects[pPen->ihPen].penWidth = pPen->elp.elpWidth;
  4402. }
  4403. break;
  4404. case EMR_POLYTEXTOUTA:
  4405. break;
  4406. case EMR_POLYTEXTOUTW:
  4407. break;
  4408. case EMR_SETICMMODE:
  4409. case EMR_CREATECOLORSPACE:
  4410. case EMR_SETCOLORSPACE:
  4411. case EMR_DELETECOLORSPACE:
  4412. case EMR_GLSRECORD:
  4413. case EMR_GLSBOUNDEDRECORD:
  4414. case EMR_PIXELFORMAT:
  4415. break;
  4416. case EMR_DRAWESCAPE:
  4417. case EMR_EXTESCAPE:
  4418. case EMR_STARTDOC:
  4419. case EMR_SMALLTEXTOUT:
  4420. case EMR_FORCEUFIMAPPING:
  4421. case EMR_NAMEDESCAPE:
  4422. case EMR_COLORCORRECTPALETTE:
  4423. case EMR_SETICMPROFILEA:
  4424. case EMR_SETICMPROFILEW:
  4425. case EMR_ALPHABLEND:
  4426. case EMR_SETLAYOUT:
  4427. case EMR_TRANSPARENTBLT:
  4428. case EMR_GRADIENTFILL:
  4429. case EMR_SETLINKEDUFIS:
  4430. case EMR_SETTEXTJUSTIFICATION:
  4431. case EMR_COLORMATCHTOTARGETW:
  4432. case EMR_CREATECOLORSPACEW:
  4433. break;
  4434. }
  4435. }
  4436. BOOL StepRecord(
  4437. Gdiplus::EmfPlusRecordType recordType,
  4438. UINT recordFlags,
  4439. UINT recordDataSize,
  4440. const BYTE * recordData,
  4441. VOID * callbackData,
  4442. HDC hDC = NULL,
  4443. LPHANDLETABLE lpHTable = NULL,
  4444. LPMETARECORD lpMFR = NULL,
  4445. LPENHMETARECORD lpEMFR = NULL,
  4446. int nObj = 0
  4447. );
  4448. VOID ListRecord(
  4449. Gdiplus::EmfPlusRecordType recordType
  4450. );
  4451. /***********************************************************************
  4452. FUNCTION : EnumMFIndirect
  4453. PARAMETERS : HDC hDC
  4454. LPHANDLETABLE lpHTable
  4455. LPMETARECORD lpMFR
  4456. LPENHMETARECORD lpEMFR
  4457. int nObj
  4458. LPARAM lpData
  4459. PURPOSE : called by EnumMetaFile and EnumEnhMetaFile. Handles the stepping of
  4460. each metafile record.
  4461. MESSAGES : none
  4462. RETURNS : int
  4463. COMMENTS : ENUMMFSTEP is used whenever records are to be played,
  4464. regardless of whether you are playing records from the
  4465. list, stepping all, or stepping a range.
  4466. ENUMMFLIST is used when you need to add strings to a listbox
  4467. that describe the type of reocrd.
  4468. HISTORY : created 7/1/93 - denniscr
  4469. ************************************************************************/
  4470. using Gdiplus::EmfPlusRecordType;
  4471. int EnumMFIndirect(HDC hDC, LPHANDLETABLE lpHTable,
  4472. LPMETARECORD lpMFR,
  4473. LPENHMETARECORD lpEMFR,
  4474. int nObj, LPARAM lpData)
  4475. {
  4476. BOOL DlgRet = TRUE;
  4477. //
  4478. // what is the enumeration action that we are taking?
  4479. //
  4480. switch (iEnumAction)
  4481. {
  4482. //
  4483. //if the enumeration was entered ala the step metafile menu selection
  4484. //
  4485. case ENUMMFSTEP:
  4486. if (bEnhMeta)
  4487. {
  4488. return StepRecord((EmfPlusRecordType)(lpEMFR->iType),
  4489. 0, lpEMFR->nSize - sizeof(EMR),
  4490. (BYTE *)lpEMFR->dParm, (VOID *)lpData,
  4491. hDC, lpHTable, lpMFR, lpEMFR, nObj);
  4492. }
  4493. else
  4494. {
  4495. return StepRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction),
  4496. 0, ((LONG)lpMFR->rdSize * 2) - 6,
  4497. ((BYTE *)lpMFR) + 6, (VOID *)lpData,
  4498. hDC, lpHTable, lpMFR, lpEMFR, nObj);
  4499. }
  4500. case ENUMMFLIST:
  4501. if (bEnhMeta)
  4502. {
  4503. ListRecord((Gdiplus::EmfPlusRecordType)lpEMFR->iType);
  4504. }
  4505. else
  4506. {
  4507. ListRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction));
  4508. }
  4509. //
  4510. //keep enumerating
  4511. //
  4512. return(1);
  4513. }
  4514. return 0;
  4515. }
  4516. /***********************************************************************
  4517. FUNCTION : ConvertEMFtoWMF
  4518. PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile
  4519. LPSTR lpszFileName - filename of disked based metafile
  4520. PURPOSE : Convert an Windows metafile to an enhanced metafile
  4521. MESSAGES : none
  4522. RETURNS : int
  4523. COMMENTS :
  4524. HISTORY : created 7/22/93 - denniscr
  4525. ************************************************************************/
  4526. BOOL ConvertWMFtoEMF(HMETAFILE hmf, LPSTR lpszFileName)
  4527. {
  4528. LPSTR lpWinMFBits;
  4529. UINT uiSizeBuf;
  4530. HENHMETAFILE hEnhMF;
  4531. BOOL bRet = TRUE;
  4532. //
  4533. //get the size of the Windows metafile associated with hMF
  4534. //
  4535. if ((uiSizeBuf = GetMetaFileBitsEx((HMETAFILE)hMF, 0, NULL)))
  4536. {
  4537. //
  4538. //allocate enough memory to hold metafile bits
  4539. //
  4540. lpWinMFBits = (char *)GlobalAllocPtr(GHND, uiSizeBuf);
  4541. //
  4542. //get the bits of the Windows metafile associated with hMF
  4543. //
  4544. if (lpWinMFBits && GetMetaFileBitsEx((HMETAFILE)hMF, uiSizeBuf, (LPVOID)lpWinMFBits))
  4545. {
  4546. //
  4547. //copy the bits into a memory based enhanced metafile
  4548. //
  4549. hEnhMF = SetWinMetaFileBits(uiSizeBuf, (LPBYTE)lpWinMFBits, NULL, NULL);
  4550. //
  4551. //copy the enhanced metafile to a disk based enhanced metafile
  4552. //
  4553. CopyEnhMetaFile(hEnhMF, lpszFileName);
  4554. //
  4555. //done with the memory base enhanced metafile so get rid of it
  4556. //
  4557. DeleteEnhMetaFile(hEnhMF);
  4558. //
  4559. //done with the actual memory used to store bits so nuke it
  4560. //
  4561. GlobalFreePtr(lpWinMFBits);
  4562. }
  4563. else
  4564. bRet = FALSE;
  4565. }
  4566. else
  4567. bRet = FALSE;
  4568. return (bRet);
  4569. }
  4570. /***********************************************************************
  4571. FUNCTION : ConvertEMFtoWMF
  4572. PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile
  4573. LPSTR lpszFileName - filename of disked based metafile
  4574. PURPOSE : Convert an enhanced metafile to an Windows metafile
  4575. MESSAGES : none
  4576. RETURNS : int
  4577. COMMENTS :
  4578. HISTORY : created 7/22/93 - denniscr
  4579. ************************************************************************/
  4580. BOOL ConvertEMFtoWMF(HDC hrefDC, HENHMETAFILE hEMF, LPSTR lpszFileName)
  4581. {
  4582. LPSTR lpEMFBits;
  4583. UINT uiSizeBuf;
  4584. HMETAFILE hWMF;
  4585. BOOL bRet = TRUE;
  4586. DWORD dwBytesWritten ;
  4587. //
  4588. //get the size of the Windows metafile associated with hMF
  4589. //
  4590. if ((uiSizeBuf = Gdiplus::Metafile::EmfToWmfBits(hemf, 0, NULL, MM_ANISOTROPIC,
  4591. Gdiplus::EmfToWmfBitsFlagsIncludePlaceable)))
  4592. {
  4593. //
  4594. //allocate enough memory to hold metafile bits
  4595. //
  4596. lpEMFBits = (LPSTR)GlobalAllocPtr(GHND, uiSizeBuf);
  4597. //
  4598. //get the bits of the enhanced metafile associated with hEMF
  4599. //
  4600. if (lpEMFBits && Gdiplus::Metafile::EmfToWmfBits(hEMF, uiSizeBuf,(LPBYTE)lpEMFBits,
  4601. MM_ANISOTROPIC, Gdiplus::EmfToWmfBitsFlagsIncludePlaceable))
  4602. {
  4603. // Create a file and dump the metafile bits into it
  4604. HANDLE hFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  4605. if(hFile != INVALID_HANDLE_VALUE)
  4606. {
  4607. WriteFile( hFile, (LPCVOID) lpEMFBits, uiSizeBuf, &dwBytesWritten, NULL ) ;
  4608. CloseHandle(hFile);
  4609. }
  4610. /*
  4611. //
  4612. //copy the bits into a memory based Windows metafile
  4613. //
  4614. hWMF = SetMetaFileBitsEx(uiSizeBuf, (LPBYTE)lpEMFBits);
  4615. //
  4616. //copy the Windows metafile to a disk based Windows metafile
  4617. //
  4618. CopyMetaFile(hWMF, lpszFileName);
  4619. //
  4620. //done with the memory base enhanced metafile so get rid of it
  4621. //
  4622. DeleteMetaFile((HMETAFILE)hMF);
  4623. */
  4624. //
  4625. //done with the actual memory used to store bits so nuke it
  4626. //
  4627. GlobalFreePtr(lpEMFBits);
  4628. }
  4629. else
  4630. bRet = FALSE;
  4631. }
  4632. else
  4633. bRet = FALSE;
  4634. return (bRet);
  4635. }
  4636. BOOL StepRecord(
  4637. Gdiplus::EmfPlusRecordType recordType,
  4638. UINT recordFlags,
  4639. UINT recordDataSize,
  4640. const BYTE * recordData,
  4641. VOID * callbackData,
  4642. HDC hDC,
  4643. LPHANDLETABLE lpHTable,
  4644. LPMETARECORD lpMFR,
  4645. LPENHMETARECORD lpEMFR,
  4646. int nObj
  4647. )
  4648. {
  4649. //
  4650. //keep track of the current metafile record number
  4651. //
  4652. iRecNum++;
  4653. //
  4654. //allocate memory for the record. this memory will be used by
  4655. //other functions that need to use the contents of the record
  4656. //
  4657. hMem = GlobalAlloc(GPTR /*GHND*/, (bEnhMeta) ? sizeof(EMR) + recordDataSize :
  4658. 6 + recordDataSize);
  4659. //
  4660. //if the memory was successfully allocated
  4661. //
  4662. if (hMem)
  4663. {
  4664. BOOL DlgRet = TRUE;
  4665. if (bEnhMeta)
  4666. {
  4667. //
  4668. //obtain a long pointer to this memory
  4669. //
  4670. if ((lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem)) == NULL)
  4671. {
  4672. //
  4673. //we were unable to allocate memory for the record
  4674. //
  4675. MessageBox(hWndMain, "Memory allocation failed",
  4676. NULL, MB_OK | MB_ICONHAND);
  4677. }
  4678. else
  4679. {
  4680. //
  4681. //copy the contents of the record to the global memory
  4682. //
  4683. emfMetaRec.nSize = sizeof(EMR) + recordDataSize;
  4684. emfMetaRec.iType = recordType;
  4685. unsigned long i;
  4686. for (i = 0;(DWORD)i < recordDataSize / sizeof(DWORD); i++)
  4687. {
  4688. *lpEMFParams++ = ((DWORD *)recordData)[i];
  4689. }
  4690. }
  4691. }
  4692. else
  4693. {
  4694. /* obtain a long pointer to this memory */
  4695. lpMFParams = (LPPARAMETERS)GlobalLock(hMem);
  4696. /* copy the contents of the record to the global memory */
  4697. MetaRec.rdSize = (6 + recordDataSize) / 2;
  4698. MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType);
  4699. DWORD i;
  4700. for (i = 0; (DWORD)i < (recordDataSize / 2); i++)
  4701. {
  4702. *lpMFParams++ = ((WORD *)recordData)[i];
  4703. }
  4704. }
  4705. GlobalUnlock(hMem);
  4706. //
  4707. //if STEPPING through metafile records that have been selected
  4708. //by selecting the menu options Play - Step - All, Play - Step -
  4709. //Range, or selecting records from the View - List listbox
  4710. //
  4711. if ( !bPlayItAll
  4712. || ( bEnumRange && iRecNum >= (WORD)iStartRange && iRecNum <= (WORD)iEndRange )
  4713. || ( bPlayList && !bPlayItAll ) )
  4714. {
  4715. //
  4716. //if playing records selected from the View - List
  4717. //listbox of records
  4718. if (bPlayList)
  4719. {
  4720. //
  4721. //if playing the selected records
  4722. //
  4723. if (bPlaySelList)
  4724. {
  4725. //
  4726. //if done playing the selected records then stop the enumeration
  4727. //
  4728. if (iCount == iNumSel)
  4729. {
  4730. return(0);
  4731. }
  4732. //
  4733. //if this is a selected record then play it
  4734. //
  4735. if ((WORD)lpSelMem[iCount] == iRecNum - 1)
  4736. {
  4737. //
  4738. //initialize flag
  4739. //
  4740. bPlayRec = FALSE;
  4741. //
  4742. //increment the count
  4743. //
  4744. iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
  4745. //
  4746. //call the dialog box that lets you play or ignore this record */
  4747. //
  4748. DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
  4749. }
  4750. else
  4751. {
  4752. //
  4753. //initialize flag and do nothing else
  4754. //
  4755. bPlayRec = FALSE;
  4756. }
  4757. }
  4758. //
  4759. //playing the unselected records
  4760. //
  4761. else
  4762. {
  4763. //
  4764. //if this is one of the selected records then increment
  4765. //the record count and init a flag but do nothing else
  4766. //
  4767. if ((WORD)lpSelMem[iCount] == iRecNum - 1)
  4768. {
  4769. //
  4770. //set count to next selected record in listbox
  4771. //
  4772. iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
  4773. bPlayRec = FALSE;
  4774. }
  4775. //
  4776. //this is not one of the selected records which is what we
  4777. //want in this case. So, init a flag give the user the
  4778. //opportunity to play the record
  4779. //
  4780. else
  4781. {
  4782. bPlayRec = FALSE;
  4783. DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
  4784. }
  4785. }
  4786. } //bPlayList
  4787. //
  4788. //stepping records from the Play - Step menu option
  4789. //
  4790. else
  4791. {
  4792. //
  4793. //init a flag and show the record contents
  4794. //
  4795. bPlayRec = FALSE;
  4796. iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
  4797. DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc);
  4798. }
  4799. } //end of STEPPING the metafile
  4800. //
  4801. //bPlayItAll is TRUE. This is set when the user either
  4802. //selects the menu option Play - All or pushes the GO button
  4803. //in the view record dialog box
  4804. //
  4805. else
  4806. {
  4807. //
  4808. //we were stepping records selected from the listbox and
  4809. //the user pressed the GO button
  4810. //
  4811. //Don't bother returning 0 to stop enumeration. We need to
  4812. //play to the end of the metafile in this case anyway
  4813. //
  4814. if (bPlayList)
  4815. {
  4816. //
  4817. //we were playing the selected records
  4818. //
  4819. if (bPlaySelList)
  4820. {
  4821. //
  4822. //if all of the selected records have been played then
  4823. //stop the enumeration
  4824. //
  4825. if (iCount == iNumSel)
  4826. {
  4827. return(0);
  4828. }
  4829. //
  4830. //set bPlayRec so the record will be played without user
  4831. //interation and then update the record counter
  4832. //
  4833. if ((WORD)lpSelMem[iCount] == iRecNum - 1)
  4834. {
  4835. bPlayRec = TRUE;
  4836. iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
  4837. }
  4838. else
  4839. //
  4840. //it wasn't one of the selected records so don't play
  4841. //
  4842. {
  4843. bPlayRec = FALSE;
  4844. }
  4845. }
  4846. //
  4847. //we were playing the unselected records
  4848. //
  4849. else
  4850. {
  4851. //
  4852. //if it is a selected record then set bPlayRec to FALSE
  4853. //so the record is not played
  4854. //
  4855. if ((WORD)lpSelMem[iCount] == iRecNum - 1)
  4856. {
  4857. bPlayRec = FALSE;
  4858. iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount;
  4859. }
  4860. else
  4861. {
  4862. //
  4863. //play the record
  4864. //
  4865. bPlayRec = TRUE;
  4866. }
  4867. }
  4868. } //bPlayList
  4869. } //GO button pushed
  4870. //
  4871. //Stop the enumeration if you were stepping a range and have
  4872. //finished playing that range OR the user selected pushed
  4873. //the STOP button in the view record dialog box
  4874. //
  4875. if ( ((bEnumRange) && (iRecNum > (WORD)iEndRange)) || (!DlgRet) )
  4876. {
  4877. bPlayRec = FALSE;
  4878. //
  4879. //stop enumeration
  4880. //
  4881. return(0);
  4882. }
  4883. } //if (hMem)
  4884. else
  4885. //
  4886. //we were unable to allocate memory for the record
  4887. //
  4888. {
  4889. MessageBox(hWndMain, "Memory allocation failed",
  4890. NULL, MB_OK | MB_ICONHAND);
  4891. }
  4892. //
  4893. //Regardless of the method the user elected to play the
  4894. //records, check the flag. If it is set then play the
  4895. //record
  4896. //
  4897. if (bPlayRec)
  4898. {
  4899. if (bUseGdiPlusToPlay)
  4900. {
  4901. ((MYDATA *)callbackData)->metafile->PlayRecord(recordType, recordFlags, recordDataSize, recordData);
  4902. }
  4903. else if (bEnhMeta)
  4904. {
  4905. if (bConvertToGdiPlus)
  4906. {
  4907. GpPlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj, (LPARAM)callbackData);
  4908. }
  4909. else
  4910. {
  4911. PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj);
  4912. }
  4913. }
  4914. else if(!PlayMetaFileRecord(hDC, lpHTable, lpMFR, (UINT)nObj))
  4915. {
  4916. ASSERT(FALSE);
  4917. }
  4918. }
  4919. //
  4920. //done with the record so get rid of it
  4921. //
  4922. GlobalFree(hMem);
  4923. //
  4924. //if we made it this far then continue the enumeration
  4925. //
  4926. return(1);
  4927. }
  4928. VOID ListRecord(
  4929. Gdiplus::EmfPlusRecordType recordType
  4930. )
  4931. {
  4932. char szMetaFunction[100];
  4933. iRecNum++;
  4934. //
  4935. //format the listbox string
  4936. //
  4937. wsprintf((LPSTR)szMetaFunction, (LPSTR)"%d - ", iRecNum);
  4938. //
  4939. //get the function number contained in the record
  4940. //
  4941. if (bEnhMeta)
  4942. emfMetaRec.iType = recordType;
  4943. else
  4944. MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType);
  4945. //
  4946. //lookup the function number in the structure MetaFunctions
  4947. //
  4948. int i;
  4949. if (bEnhMeta)
  4950. {
  4951. for (i = NUMMETAFUNCTIONS; i < NUMENHMETARECORDS; i++)
  4952. {
  4953. if (recordType == (INT)emfMetaRecords[i].iType)
  4954. break;
  4955. }
  4956. }
  4957. else // WMF
  4958. {
  4959. for (i = 0; i < NUMMETAFUNCTIONS; i++)
  4960. {
  4961. if (recordType == (INT)emfMetaRecords[i].iType)
  4962. break;
  4963. }
  4964. }
  4965. //
  4966. //if the function number is not found then describe this record
  4967. //as an "Unknown" type otherwise use the corresponding name
  4968. //found in the lookup
  4969. //
  4970. if (recordType != (INT)emfMetaRecords[i].iType)
  4971. lstrcat((LPSTR)szMetaFunction, (LPSTR)"Unknown");
  4972. else
  4973. lstrcat((LPSTR)szMetaFunction,(LPSTR)emfMetaRecords[i].szRecordName);
  4974. //
  4975. //add the string to the listbox
  4976. //
  4977. SendDlgItemMessage((HWND)CurrenthDlg, IDL_LBREC, LB_ADDSTRING, 0,
  4978. (LPARAM)(LPSTR)szMetaFunction);
  4979. }
  4980. extern "C"
  4981. BOOL CALLBACK
  4982. PlayGdipMetafileRecordCallback(
  4983. Gdiplus::EmfPlusRecordType recordType,
  4984. UINT recordFlags,
  4985. UINT recordDataSize,
  4986. const BYTE * recordData,
  4987. VOID * callbackData
  4988. )
  4989. {
  4990. switch (iEnumAction)
  4991. {
  4992. case ENUMMFSTEP:
  4993. return StepRecord(recordType, recordFlags, recordDataSize, recordData, callbackData);
  4994. case ENUMMFLIST:
  4995. ListRecord(recordType);
  4996. break;
  4997. }
  4998. return TRUE;
  4999. }
  5000. /***********************************************************************
  5001. FUNCTION : GetMetaFileAndEnum
  5002. PARAMETERS : HDC hDC
  5003. PURPOSE : load the metafile if it has not already been loaded and
  5004. begin enumerating it
  5005. CALLS : WINDOWS
  5006. GetMetaFile
  5007. MakeProcInstance
  5008. EnumMetaFile
  5009. FreeProcInstance
  5010. DeleteMetaFile
  5011. MessageBox
  5012. MESSAGES : none
  5013. RETURNS : void
  5014. COMMENTS :
  5015. HISTORY : 1/16/91 - created - drc
  5016. 7/1/93 - modified to work with EMFs - denniscr
  5017. ************************************************************************/
  5018. extern "C"
  5019. void GetMetaFileAndEnum(
  5020. HWND hwnd,
  5021. HDC hDC,
  5022. int iAction)
  5023. {
  5024. MYDATA myData(hwnd);
  5025. iEnumAction = iAction;
  5026. //
  5027. //if this is an enhanced metafile (emf)
  5028. //
  5029. RECT rc;
  5030. GetClientRect(hWndMain, &rc);
  5031. HPALETTE hpal = NULL;
  5032. if (bEnhMeta)
  5033. {
  5034. if (hemf)
  5035. {
  5036. LPLOGPALETTE lpLogPal;
  5037. HPALETTE hPal;
  5038. int i;
  5039. //
  5040. //allocate memory for the logical palette including the array of
  5041. //palette entries
  5042. //
  5043. lpLogPal = (LPLOGPALETTE) GlobalAllocPtr( GHND, sizeof(LOGPALETTE) +
  5044. (sizeof (PALETTEENTRY) * EmfPtr.palNumEntries));
  5045. if (lpLogPal)
  5046. {
  5047. //
  5048. //proceed only if there is a valid ptr to logical palette
  5049. //and a palette array obtained from the emf
  5050. //
  5051. if (EmfPtr.lpPal)
  5052. {
  5053. lpLogPal->palVersion = 0x300;
  5054. lpLogPal->palNumEntries = EmfPtr.palNumEntries;
  5055. //
  5056. //copy palette entries into palentry array
  5057. //
  5058. for (i = 0; i < EmfPtr.palNumEntries; i++)
  5059. lpLogPal->palPalEntry[i] = *EmfPtr.lpPal++;
  5060. //
  5061. //reposition the ptr back to the beginning should we call this
  5062. //code again
  5063. //
  5064. EmfPtr.lpPal -= EmfPtr.palNumEntries;
  5065. //
  5066. //create, select and realize the palette
  5067. //
  5068. if ((hPal = CreatePalette((LPLOGPALETTE)lpLogPal)))
  5069. {
  5070. SelectPalette(hDC, hPal, FALSE);
  5071. RealizePalette(hDC);
  5072. }
  5073. }
  5074. if (bUseGdiPlusToPlay)
  5075. {
  5076. // Select in the halftone palette for 256-color display mode testing
  5077. hpal = Gdiplus::Graphics::GetHalftonePalette();
  5078. SelectPalette(hDC, hpal, FALSE);
  5079. RealizePalette(hDC);
  5080. // Need to delete this before returning;
  5081. myData.g = Gdiplus::Graphics::FromHDC(hDC);
  5082. myData.g->SetPixelOffsetMode(Gdiplus::PixelOffsetModeHalf);
  5083. myData.g->SetInterpolationMode(Gdiplus::InterpolationModeNearestNeighbor);
  5084. }
  5085. //
  5086. //enumerate the EMF. this is a bit odd simply because PlayEnhMetaFile
  5087. //really obviates the need for doing this (this cannot be said for WMFs).
  5088. //this app does it simply because it may be stepping the metafile records.
  5089. //Most apps are generally not concerned about doing this.
  5090. //
  5091. if (bUseGdiPlusToPlay && (myData.g != NULL))
  5092. {
  5093. Gdiplus::Metafile m1(hemf);
  5094. Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
  5095. myData.metafile = &m1;
  5096. if(myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok)
  5097. MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
  5098. myData.metafile = NULL;
  5099. }
  5100. else
  5101. {
  5102. // the rect needs to be inclusive-inclusive!!!
  5103. rc.right--;
  5104. rc.bottom--;
  5105. if(!EnumEnhMetaFile(hDC, hemf, (ENHMFENUMPROC)EnhMetaFileEnumProc, (void*)&myData, &rc))
  5106. MessageBox(NULL, "Error", "An Error Occured while playing this metafile", MB_OK | MB_ICONERROR);
  5107. }
  5108. //
  5109. //free palette memory
  5110. //
  5111. GlobalFreePtr(lpLogPal);
  5112. }
  5113. }
  5114. }
  5115. else
  5116. {
  5117. //
  5118. //if there is a valid handle to a metafile begin enumerating it
  5119. //
  5120. if (hMF)
  5121. {
  5122. if (bUseGdiPlusToPlay)
  5123. {
  5124. // Select in the halftone palette for 256-color display mode testing
  5125. hpal = Gdiplus::Graphics::GetHalftonePalette();
  5126. SelectPalette(hDC, hpal, FALSE);
  5127. RealizePalette(hDC);
  5128. // Need to delete this before returning;
  5129. myData.g = Gdiplus::Graphics::FromHDC(hDC);
  5130. }
  5131. if (bUseGdiPlusToPlay && (myData.g != NULL))
  5132. {
  5133. Gdiplus::WmfPlaceableFileHeader * wmfPlaceableFileHeader = NULL;
  5134. if (bPlaceableMeta)
  5135. {
  5136. wmfPlaceableFileHeader = (Gdiplus::WmfPlaceableFileHeader *)&placeableWMFHeader;
  5137. }
  5138. Gdiplus::Metafile m1((HMETAFILE)hMF, wmfPlaceableFileHeader);
  5139. Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
  5140. myData.metafile = &m1;
  5141. if (myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok)
  5142. MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
  5143. myData.metafile = NULL;
  5144. }
  5145. else
  5146. {
  5147. if (!EnumMetaFile(hDC, (HMETAFILE)hMF, (MFENUMPROC) MetaEnumProc, (LPARAM) 0))
  5148. MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR);
  5149. }
  5150. }
  5151. else
  5152. MessageBox(hWndMain, "Invalid metafile handle",
  5153. NULL, MB_OK | MB_ICONHAND);
  5154. }
  5155. if (myData.g != NULL )
  5156. {
  5157. SelectObject(hDC, GetStockObject(DEFAULT_PALETTE));
  5158. DeleteObject(hpal);
  5159. myData.g->Flush();
  5160. delete myData.g;
  5161. myData.g = NULL;
  5162. }
  5163. return;
  5164. }