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.

4694 lines
129 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: metarec.cxx
  3. *
  4. * Metafile recording functions.
  5. *
  6. * Created: 12-June-1991 13:46:00
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #define NO_STRICT
  12. extern "C" {
  13. #if defined(_GDIPLUS_)
  14. #include <gpprefix.h>
  15. #endif
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <stddef.h>
  20. #include <windows.h> // GDI function declarations.
  21. #include <winerror.h>
  22. #include "firewall.h"
  23. #define __CPLUSPLUS
  24. #include <winspool.h>
  25. #include <w32gdip.h>
  26. #include "ntgdistr.h"
  27. #include "winddi.h"
  28. #include "icm.h"
  29. #include "hmgshare.h"
  30. #include "local.h" // Local object support.
  31. #include "gdiicm.h"
  32. #include "font.h"
  33. #include "metadef.h" // Metafile record type constants.
  34. #include "metarec.h" // Metafile recording functions.
  35. #include "mf16.h"
  36. #include "nlsconv.h"
  37. #include "ntgdi.h"
  38. #include "xfflags.h"
  39. #include "..\inc\mapfile.h"
  40. }
  41. #include "rectl.hxx"
  42. #include "mfdc.hxx" // Metafile DC class declarations.
  43. #include "mfrec.hxx" // Metafile record class declarations.
  44. extern "C" {
  45. #include "mfrec16.h" // 3.x Metafile recording functions
  46. }
  47. extern "C" BOOL bDoFontChange(HDC hdc, WCHAR *pwsz, int c, UINT fl);
  48. extern "C" BOOL bRecordEmbedFonts(HDC hdc);
  49. XFORM xformIdentity = { 1.00000000f, 0.00000000f, 0.00000000f, 1.00000000f,
  50. 0.00000000f, 0.00000000f };
  51. #ifdef LANGPACK
  52. extern LONG gdwDisableMetafileRec ;
  53. #endif
  54. // SaveDC
  55. // BeginPath
  56. // EndPath
  57. // CloseFigure
  58. // FlattenPath
  59. // WidenPath
  60. // AbortPath
  61. // SetMetaRgn
  62. // RealizePalette
  63. extern "C" BOOL MF_Record(HDC hdc,DWORD mrType)
  64. {
  65. PMR pmr;
  66. PLDC pldc;
  67. DC_PLDC(hdc,pldc,FALSE);
  68. PMDC pmdc = (PMDC)pldc->pvPMDC;
  69. ASSERTGDI(pmdc,"no pmdc\n");
  70. PUTS("MF_Record\n");
  71. if (!(pmr = (PMR) pmdc->pvNewRecord(SIZEOF_MR)))
  72. return(FALSE);
  73. pmr->vInit(mrType);
  74. pmr->vCommit(pmdc);
  75. return(TRUE);
  76. }
  77. // FillPath
  78. // StrokeAndFillPath
  79. // StrokePath
  80. extern "C" BOOL MF_BoundRecord(HDC hdc,DWORD mrType)
  81. {
  82. PMRB pmrb;
  83. PLDC pldc;
  84. DC_PLDC(hdc,pldc,FALSE);
  85. PMDC pmdc = (PMDC)pldc->pvPMDC;
  86. ASSERTGDI(pmdc,"no pmdc\n");
  87. PUTS("MF_BoundRecord\n");
  88. if (!(pmrb = (PMRB) pmdc->pvNewRecord(SIZEOF_MRB)))
  89. return(FALSE);
  90. pmrb->vInit(mrType, pmdc);
  91. pmrb->vCommit(pmdc);
  92. return(TRUE);
  93. }
  94. // SetMapperFlags
  95. // SetMapMode
  96. // SetBkMode
  97. // SetPolyFillMode
  98. // SetROP2
  99. // SetStretchBltMode
  100. // SetTextAlign
  101. // SetTextColor
  102. // SetBkColor
  103. // RestoreDC
  104. // SetArcDirection
  105. // SetMiterLimit
  106. // SelectClipPath
  107. // SetLayout
  108. extern "C" BOOL MF_SetD(HDC hdc,DWORD d1,DWORD mrType)
  109. {
  110. PMRD pmrd;
  111. PLDC pldc;
  112. DC_PLDC(hdc,pldc,FALSE);
  113. PMDC pmdc = (PMDC)pldc->pvPMDC;
  114. ASSERTGDI(pmdc,"no pmdc\n");
  115. PUTS("MF_SetD\n");
  116. if( ( mrType == EMR_SETMAPMODE ) ||
  117. ( mrType == EMR_SETMAPPERFLAGS ) ||
  118. ( mrType == EMR_SETLAYOUT ) ||
  119. ( mrType == EMR_RESTOREDC ) )
  120. {
  121. pldc->fl |= LDC_FONT_CHANGE;
  122. }
  123. if (!(pmrd = (PMRD) pmdc->pvNewRecord(SIZEOF_MRD)))
  124. return(FALSE);
  125. pmrd->vInit(mrType, d1);
  126. pmrd->vCommit(pmdc);
  127. return(TRUE);
  128. }
  129. // OffsetWindowOrgEx
  130. // OffsetViewportOrgEx
  131. // SetWindowExtEx
  132. // SetWindowOrgEx
  133. // SetViewportExtEx
  134. // SetViewportOrgEx
  135. // SetBrushOrgEx
  136. // OffsetClipRgn
  137. // MoveToEx
  138. // LineTo
  139. // SetTextJustification
  140. extern "C" BOOL MF_SetDD(HDC hdc,DWORD d1,DWORD d2,DWORD mrType)
  141. {
  142. PMRDD pmrdd;
  143. PLDC pldc;
  144. DC_PLDC(hdc,pldc,FALSE);
  145. PMDC pmdc = (PMDC)pldc->pvPMDC;
  146. ASSERTGDI(pmdc,"no pmdc\n");
  147. PUTS("MF_SetDD\n");
  148. if( ( mrType == EMR_SETVIEWPORTEXTEX ) || ( mrType == EMR_SETWINDOWEXTEX ) )
  149. {
  150. pldc->fl |= LDC_FONT_CHANGE;
  151. }
  152. if (!(pmrdd = (PMRDD) pmdc->pvNewRecord(SIZEOF_MRDD)))
  153. return(FALSE);
  154. pmrdd->vInit(mrType, d1, d2);
  155. pmrdd->vCommit(pmdc);
  156. return(TRUE);
  157. }
  158. // ExcludeClipRect
  159. // IntersectClipRect
  160. // ScaleViewportExtEx
  161. // ScaleWindowExtEx
  162. extern "C" BOOL MF_SetDDDD(HDC hdc,DWORD d1,DWORD d2,DWORD d3,DWORD d4,DWORD mrType)
  163. {
  164. PMRDDDD pmrdddd;
  165. PLDC pldc;
  166. DC_PLDC(hdc,pldc,FALSE);
  167. PMDC pmdc = (PMDC)pldc->pvPMDC;
  168. ASSERTGDI(pmdc,"no pmdc\n");
  169. PUTS("MF_SetDDDD\n");
  170. if( ( mrType == EMR_SCALEVIEWPORTEXTEX ) || ( mrType == EMR_SCALEWINDOWEXTEX ) )
  171. {
  172. pldc->fl |= LDC_FONT_CHANGE;
  173. }
  174. if (!(pmrdddd = (PMRDDDD) pmdc->pvNewRecord(SIZEOF_MRDDDD)))
  175. return(FALSE);
  176. pmrdddd->vInit(mrType, d1, d2, d3, d4);
  177. pmrdddd->vCommit(pmdc);
  178. return(TRUE);
  179. }
  180. // SetMetaRgn
  181. extern "C" BOOL MF_SetMetaRgn(HDC hdc)
  182. {
  183. PLDC pldc;
  184. DC_PLDC(hdc,pldc,FALSE);
  185. PMDC pmdc = (PMDC)pldc->pvPMDC;
  186. ASSERTGDI(pmdc,"no pmdc\n");
  187. PUTS("MF_SetMetaRgn\n");
  188. // Record it first.
  189. if (!MF_Record(hdc,EMR_SETMETARGN))
  190. return(FALSE);
  191. // We have to flush the bounds before we change the clipping region
  192. // because the bounds are clipped to the current clipping region bounds.
  193. pmdc->vFlushBounds();
  194. // Now update the clipping bounds to prepare for the next flush.
  195. pmdc->vSetMetaBounds();
  196. return(TRUE);
  197. }
  198. // SelectClipPath
  199. extern "C" BOOL MF_SelectClipPath(HDC hdc,int iMode)
  200. {
  201. PLDC pldc;
  202. DC_PLDC(hdc,pldc,FALSE);
  203. PMDC pmdc = (PMDC)pldc->pvPMDC;
  204. ASSERTGDI(pmdc,"no pmdc\n");
  205. PUTS("MF_SelectClipPath\n");
  206. // Record it first.
  207. if (!MF_SetD(hdc, (DWORD) iMode, EMR_SELECTCLIPPATH))
  208. return(FALSE);
  209. // We have to flush the bounds before we change the clipping region
  210. // because the bounds are clipped to the current clipping region bounds.
  211. pmdc->vFlushBounds();
  212. // Now mark the clipping bounds dirty. The clipping bounds is updated
  213. // when it is needed.
  214. pmdc->vMarkClipBoundsDirty();
  215. return(TRUE);
  216. }
  217. // OffsetClipRgn
  218. extern "C" BOOL MF_OffsetClipRgn(HDC hdc,int x1,int y1)
  219. {
  220. PLDC pldc;
  221. DC_PLDC(hdc,pldc,FALSE);
  222. PMDC pmdc = (PMDC)pldc->pvPMDC;
  223. ASSERTGDI(pmdc,"no pmdc\n");
  224. PUTS("MF_OffsetClipRgn\n");
  225. // Record it first.
  226. if (!MF_SetDD(hdc, (DWORD) x1, (DWORD) y1, EMR_OFFSETCLIPRGN))
  227. return(FALSE);
  228. // We have to flush the bounds before we change the clipping region
  229. // because the bounds are clipped to the current clipping region bounds.
  230. pmdc->vFlushBounds();
  231. // Now mark the clipping bounds dirty. The clipping bounds is updated
  232. // when it is needed.
  233. pmdc->vMarkClipBoundsDirty();
  234. return(TRUE);
  235. }
  236. // ExcludeClipRect
  237. // IntersectClipRect
  238. extern "C" BOOL MF_AnyClipRect(HDC hdc,int x1,int y1,int x2,int y2,DWORD mrType)
  239. {
  240. BOOL bRet = FALSE;
  241. HRGN hrgnTmp;
  242. PLDC pldc;
  243. DC_PLDC(hdc,pldc,FALSE);
  244. PMDC pmdc = (PMDC)pldc->pvPMDC;
  245. ASSERTGDI(pmdc,"no pmdc\n");
  246. PUTS("MF_AnyClipRect\n");
  247. // Record it first.
  248. if (!MF_SetDDDD(hdc, (DWORD) x1, (DWORD) y1, (DWORD) x2, (DWORD) y2, mrType))
  249. return(bRet);
  250. // We have to flush the bounds before we change the clipping region
  251. // because the bounds are clipped to the current clipping region bounds.
  252. pmdc->vFlushBounds();
  253. // Now mark the clipping bounds dirty. The clipping bounds is updated
  254. // when it is needed.
  255. pmdc->vMarkClipBoundsDirty();
  256. // For ExcludeClipRect and InteresectClipRect, this is a little tricky.
  257. // If there is no initial clip region, we have to create a default clipping
  258. // region. Otherwise, GDI will create some random default clipping region
  259. // for us!
  260. // Find out if we have a clip region.
  261. if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0)))
  262. return(bRet);
  263. switch (GetClipRgn(hdc, hrgnTmp))
  264. {
  265. case -1: // error
  266. ASSERTGDI(FALSE, "GetClipRgn failed");
  267. break;
  268. case 0: // no initial clip region
  269. // We need to select in our default clipping region.
  270. // First, make our default clipping region.
  271. if (!SetRectRgn(hrgnTmp,
  272. (int) (SHORT) MINSHORT,
  273. (int) (SHORT) MINSHORT,
  274. (int) (SHORT) MAXSHORT,
  275. (int) (SHORT) MAXSHORT))
  276. {
  277. ASSERTGDI(FALSE, "SetRectRgn failed");
  278. break;
  279. }
  280. // Now select our default region but don't metafile the call.
  281. {
  282. INT iRet;
  283. iRet = NtGdiExtSelectClipRgn(hdc, hrgnTmp, RGN_COPY);
  284. bRet = (iRet != RGN_ERROR);
  285. }
  286. break;
  287. case 1: // has initial clip region
  288. bRet = TRUE;
  289. break;
  290. }
  291. if (!DeleteObject(hrgnTmp))
  292. {
  293. ASSERTGDI(FALSE, "DeleteObject failed");
  294. }
  295. return(bRet);
  296. }
  297. // Always store the relative level.
  298. extern "C" BOOL MF_RestoreDC(HDC hdc,int iLevel)
  299. {
  300. int cLevel = (int) GetDCDWord(hdc,DDW_SAVEDEPTH,0);
  301. PLDC pldc;
  302. DC_PLDC(hdc,pldc,FALSE);
  303. PMDC pmdc = (PMDC)pldc->pvPMDC;
  304. ASSERTGDI(pmdc,"no pmdc\n");
  305. // Compute the relative level.
  306. if (iLevel > 0)
  307. {
  308. iLevel = iLevel - cLevel;
  309. }
  310. // Check bad levels.
  311. if ((iLevel >= 0) || (iLevel + cLevel <= 0))
  312. return(FALSE);
  313. if (!MF_SetD(hdc,(DWORD)iLevel,EMR_RESTOREDC))
  314. return(FALSE);
  315. // We have to flush the bounds before we change the clipping region
  316. // because the bounds are clipped to the current clipping region bounds.
  317. pmdc->vFlushBounds();
  318. // Now mark the clipping bounds dirty. The clipping bounds is updated
  319. // when it is needed.
  320. pmdc->vMarkClipBoundsDirty();
  321. pmdc->vMarkMetaBoundsDirty();
  322. return(TRUE);
  323. }
  324. extern "C" BOOL MF_SetViewportExtEx(HDC hdc,int x,int y)
  325. {
  326. return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETVIEWPORTEXTEX));
  327. }
  328. extern "C" BOOL MF_SetViewportOrgEx(HDC hdc,int x,int y)
  329. {
  330. return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETVIEWPORTORGEX));
  331. }
  332. extern "C" BOOL MF_SetWindowExtEx(HDC hdc,int x,int y)
  333. {
  334. return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETWINDOWEXTEX));
  335. }
  336. extern "C" BOOL MF_SetWindowOrgEx(HDC hdc,int x,int y)
  337. {
  338. return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETWINDOWORGEX));
  339. }
  340. // Map it to SetViewportOrgEx record.
  341. extern "C" BOOL MF_OffsetViewportOrgEx(HDC hdc,int x,int y)
  342. {
  343. POINTL ptl;
  344. if (!GetViewportOrgEx(hdc, (LPPOINT) &ptl))
  345. return(FALSE);
  346. return
  347. (
  348. MF_SetDD
  349. (
  350. hdc,
  351. (DWORD)(ptl.x + (LONG) x),
  352. (DWORD)(ptl.y + (LONG) y),
  353. EMR_SETVIEWPORTORGEX
  354. )
  355. );
  356. }
  357. // Map it to SetWindowOrgEx record.
  358. extern "C" BOOL MF_OffsetWindowOrgEx(HDC hdc,int x,int y)
  359. {
  360. POINTL ptl;
  361. if (!GetWindowOrgEx(hdc, (LPPOINT) &ptl))
  362. return(FALSE);
  363. return
  364. (
  365. MF_SetDD
  366. (
  367. hdc,
  368. (DWORD) (ptl.x + (LONG) x),
  369. (DWORD) (ptl.y + (LONG) y),
  370. EMR_SETWINDOWORGEX
  371. )
  372. );
  373. }
  374. extern "C" BOOL MF_SetBrushOrgEx(HDC hdc,int x,int y)
  375. {
  376. return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETBRUSHORGEX));
  377. }
  378. // PolyBezier
  379. // Polygon
  380. // Polyline
  381. // PolyBezierTo
  382. // PolylineTo
  383. extern "C" BOOL MF_Poly(HDC hdc, CONST POINT *pptl,DWORD cptl,DWORD mrType)
  384. {
  385. PLDC pldc;
  386. DC_PLDC(hdc,pldc,FALSE);
  387. PMDC pmdc = (PMDC)pldc->pvPMDC;
  388. ASSERTGDI(pmdc,"no pmdc\n");
  389. PUTS("MF_Poly\n");
  390. // Check input assumptions.
  391. ASSERTGDI
  392. (
  393. mrType == EMR_POLYBEZIER
  394. || mrType == EMR_POLYGON
  395. || mrType == EMR_POLYLINE
  396. || mrType == EMR_POLYBEZIERTO
  397. || mrType == EMR_POLYLINETO,
  398. "MF_Poly: Bad record type"
  399. );
  400. ASSERTGDI
  401. (
  402. EMR_POLYGON - EMR_POLYBEZIER == EMR_POLYGON16 - EMR_POLYBEZIER16
  403. && EMR_POLYLINE - EMR_POLYBEZIER == EMR_POLYLINE16 - EMR_POLYBEZIER16
  404. && EMR_POLYBEZIERTO - EMR_POLYBEZIER == EMR_POLYBEZIERTO16 - EMR_POLYBEZIER16
  405. && EMR_POLYLINETO - EMR_POLYBEZIER == EMR_POLYLINETO16 - EMR_POLYBEZIER16,
  406. "MF_Poly: Bad record type"
  407. );
  408. // Store 16-bit record if possible.
  409. if (bIsPoly16((PPOINTL) pptl, cptl))
  410. {
  411. PMRBP16 pmrbp16;
  412. if (!(pmrbp16 = (PMRBP16) pmdc->pvNewRecord(SIZEOF_MRBP16(cptl))))
  413. return(FALSE);
  414. pmrbp16->vInit
  415. (
  416. mrType - EMR_POLYBEZIER + EMR_POLYBEZIER16,
  417. cptl,
  418. (PPOINTL) pptl,
  419. pmdc
  420. );
  421. pmrbp16->vCommit(pmdc);
  422. }
  423. else
  424. {
  425. PMRBP pmrbp;
  426. if (!(pmrbp = (PMRBP) pmdc->pvNewRecord(SIZEOF_MRBP(cptl))))
  427. return(FALSE);
  428. pmrbp->vInit(mrType, cptl, (PPOINTL) pptl, pmdc);
  429. pmrbp->vCommit(pmdc);
  430. }
  431. return(TRUE);
  432. }
  433. // PolyPolygon
  434. // PolyPolyline
  435. extern "C" BOOL MF_PolyPoly(HDC hdc, CONST POINT *pptl, CONST DWORD *pc,DWORD cPoly,DWORD mrType)
  436. {
  437. PLDC pldc;
  438. DC_PLDC(hdc,pldc,FALSE);
  439. PMDC pmdc = (PMDC)pldc->pvPMDC;
  440. ASSERTGDI(pmdc,"no pmdc\n");
  441. PUTS("MF_PolyPoly\n");
  442. // Check input assumptions.
  443. ASSERTGDI
  444. (
  445. mrType == EMR_POLYPOLYGON
  446. || mrType == EMR_POLYPOLYLINE,
  447. "MF_PolyPoly: Bad record type"
  448. );
  449. ASSERTGDI
  450. (
  451. EMR_POLYPOLYLINE - EMR_POLYPOLYGON == EMR_POLYPOLYLINE16 - EMR_POLYPOLYGON16,
  452. "MF_Poly: Bad record type"
  453. );
  454. // Compute the size of the PolyPoly record.
  455. DWORD cptl = 0;
  456. for (DWORD i = 0; i < cPoly; i++)
  457. cptl += pc[i];
  458. // Store 16-bit record if possible.
  459. if (bIsPoly16((PPOINTL) pptl, cptl))
  460. {
  461. PMRBPP16 pmrbpp16;
  462. if (!(pmrbpp16 = (PMRBPP16) pmdc->pvNewRecord(SIZEOF_MRBPP16(cptl,cPoly))))
  463. return(FALSE);
  464. pmrbpp16->vInit
  465. (
  466. mrType - EMR_POLYPOLYGON + EMR_POLYPOLYGON16,
  467. cPoly,
  468. cptl,
  469. (LPDWORD) pc,
  470. (PPOINTL) pptl,
  471. pmdc
  472. );
  473. pmrbpp16->vCommit(pmdc);
  474. }
  475. else
  476. {
  477. PMRBPP pmrbpp;
  478. if (!(pmrbpp = (PMRBPP) pmdc->pvNewRecord(SIZEOF_MRBPP(cptl,cPoly))))
  479. return(FALSE);
  480. pmrbpp->vInit(mrType, cPoly, cptl, (LPDWORD) pc, (PPOINTL) pptl, pmdc);
  481. pmrbpp->vCommit(pmdc);
  482. }
  483. return(TRUE);
  484. }
  485. /******************************Public*Routine******************************\
  486. * MF_TriangleMesh
  487. *
  488. *
  489. * Arguments:
  490. *
  491. *
  492. *
  493. * Return Value:
  494. *
  495. *
  496. *
  497. * History:
  498. *
  499. * 12/3/1996 Mark Enstrom [marke]
  500. *
  501. \**************************************************************************/
  502. extern "C" BOOL
  503. MF_GradientFill(
  504. HDC hdc,
  505. CONST PTRIVERTEX pVertex,
  506. ULONG nVertex,
  507. CONST PVOID pMesh,
  508. ULONG nMesh,
  509. ULONG ulMode
  510. )
  511. {
  512. PLDC pldc;
  513. DC_PLDC(hdc,pldc,FALSE);
  514. PMDC pmdc = (PMDC)pldc->pvPMDC;
  515. ASSERTGDI(pmdc,"no pmdc\n");
  516. PUTS("MF_TriangleMesh\n");
  517. PMRGRADIENTFILL pmrtr;
  518. if (!(pmrtr = (PMRGRADIENTFILL) pmdc->pvNewRecord(SIZEOF_MRGRADIENTFILL(nVertex,nMesh))))
  519. {
  520. return(FALSE);
  521. }
  522. pmrtr->vInit(nVertex,pVertex,nMesh,pMesh,ulMode,pmdc);
  523. pmrtr->vCommit(pmdc);
  524. SET_COLOR_PAGE(pldc);
  525. return(TRUE);
  526. }
  527. // PolyDraw
  528. extern "C" BOOL MF_PolyDraw(HDC hdc, CONST POINT *pptl, CONST BYTE *pb, DWORD cptl)
  529. {
  530. PLDC pldc;
  531. DC_PLDC(hdc,pldc,FALSE);
  532. PMDC pmdc = (PMDC)pldc->pvPMDC;
  533. ASSERTGDI(pmdc,"no pmdc\n");
  534. PUTS("MF_PolyDraw\n");
  535. // Store 16-bit record if possible.
  536. if (bIsPoly16((PPOINTL) pptl, cptl))
  537. {
  538. PMRPOLYDRAW16 pmrpd16;
  539. if (!(pmrpd16 = (PMRPOLYDRAW16) pmdc->pvNewRecord(SIZEOF_MRPOLYDRAW16(cptl))))
  540. return(FALSE);
  541. pmrpd16->vInit(pmdc, (PPOINTL) pptl, pb, cptl);
  542. pmrpd16->vCommit(pmdc);
  543. }
  544. else
  545. {
  546. PMRPOLYDRAW pmrpd;
  547. if (!(pmrpd = (PMRPOLYDRAW) pmdc->pvNewRecord(SIZEOF_MRPOLYDRAW(cptl))))
  548. return(FALSE);
  549. pmrpd->vInit(pmdc, (PPOINTL) pptl, pb, cptl);
  550. pmrpd->vCommit(pmdc);
  551. }
  552. return(TRUE);
  553. }
  554. // InvertRgn
  555. // PaintRgn
  556. extern "C" BOOL MF_InvertPaintRgn(HDC hdc,HRGN hrgn,DWORD mrType)
  557. {
  558. PMRBR pmrbr;
  559. DWORD cRgnData;
  560. PLDC pldc;
  561. DC_PLDC(hdc,pldc,FALSE);
  562. PMDC pmdc = (PMDC)pldc->pvPMDC;
  563. ASSERTGDI(pmdc,"no pmdc\n");
  564. PUTS("MF_InvertPaintRgn\n");
  565. // Get the size of the region data.
  566. if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
  567. return(FALSE);
  568. // Allocate dword aligned structure.
  569. if (!(pmrbr = (PMRBR) pmdc->pvNewRecord(SIZEOF_MRBR(cRgnData))))
  570. return(FALSE);
  571. if (!pmrbr->bInit(mrType, pmdc, hrgn, cRgnData, sizeof(MRBR)))
  572. return(FALSE);
  573. pmrbr->vCommit(pmdc);
  574. return(TRUE);
  575. }
  576. // FillRgn
  577. extern "C" BOOL MF_FillRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush)
  578. {
  579. PMRFILLRGN pmrfr;
  580. DWORD cRgnData;
  581. DWORD imheBrush;
  582. PLDC pldc;
  583. DC_PLDC(hdc,pldc,FALSE);
  584. PMDC pmdc = (PMDC)pldc->pvPMDC;
  585. ASSERTGDI(pmdc,"no pmdc\n");
  586. PUTS("MF_FillRgn\n");
  587. // Create the brush first.
  588. if (!(imheBrush = MF_InternalCreateObject(hdc, hbrush)))
  589. return(FALSE);
  590. // Get the size of the region data.
  591. if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
  592. return(FALSE);
  593. // Allocate dword aligned structure.
  594. if (!(pmrfr = (PMRFILLRGN) pmdc->pvNewRecord(SIZEOF_MRFILLRGN(cRgnData))))
  595. return(FALSE);
  596. if (!pmrfr->bInit(pmdc, hrgn, cRgnData, imheBrush))
  597. return(FALSE);
  598. pmrfr->vCommit(pmdc);
  599. return(TRUE);
  600. }
  601. // FrameRgn
  602. extern "C" BOOL MF_FrameRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush,int cx,int cy)
  603. {
  604. PMRFRAMERGN pmrfr;
  605. DWORD cRgnData;
  606. DWORD imheBrush;
  607. PLDC pldc;
  608. DC_PLDC(hdc,pldc,FALSE);
  609. PMDC pmdc = (PMDC)pldc->pvPMDC;
  610. ASSERTGDI(pmdc,"no pmdc\n");
  611. PUTS("MF_FrameRgn\n");
  612. // Create the brush first.
  613. if (!(imheBrush = MF_InternalCreateObject(hdc, hbrush)))
  614. return(FALSE);
  615. // Get the size of the region data.
  616. if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
  617. return(FALSE);
  618. // Allocate dword aligned structure.
  619. if (!(pmrfr = (PMRFRAMERGN) pmdc->pvNewRecord(SIZEOF_MRFRAMERGN(cRgnData))))
  620. return(FALSE);
  621. if (!pmrfr->bInit(pmdc, hrgn, cRgnData, imheBrush, (LONG) cx, (LONG) cy))
  622. return(FALSE);
  623. pmrfr->vCommit(pmdc);
  624. return(TRUE);
  625. }
  626. // SelectClipRgn
  627. // ExtSelectClipRgn
  628. // SelectObject(hdc,hrgn)
  629. extern "C" BOOL MF_ExtSelectClipRgn(HDC hdc,HRGN hrgn,int iMode)
  630. {
  631. PMREXTSELECTCLIPRGN pmrescr;
  632. DWORD cRgnData;
  633. PLDC pldc;
  634. DC_PLDC(hdc,pldc,FALSE);
  635. PMDC pmdc = (PMDC)pldc->pvPMDC;
  636. ASSERTGDI(pmdc,"no pmdc\n");
  637. PUTS("MF_ExtSelectClipRgn\n");
  638. // Get the size of the region data.
  639. if (iMode == RGN_COPY && hrgn == (HRGN) 0)
  640. cRgnData = 0;
  641. else if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
  642. return(FALSE);
  643. // Allocate dword aligned structure.
  644. if (!(pmrescr = (PMREXTSELECTCLIPRGN) pmdc->pvNewRecord
  645. (SIZEOF_MREXTSELECTCLIPRGN(cRgnData))))
  646. return(FALSE);
  647. if (!pmrescr->bInit(hrgn, cRgnData, (DWORD) iMode))
  648. return(FALSE);
  649. pmrescr->vCommit(pmdc);
  650. // We have to flush the bounds before we change the clipping region
  651. // because the bounds are clipped to the current clipping region bounds.
  652. pmdc->vFlushBounds();
  653. // Now mark the clipping bounds dirty. The clipping bounds is updated
  654. // when it is needed.
  655. pmdc->vMarkClipBoundsDirty();
  656. return(TRUE);
  657. }
  658. // SetPixel
  659. // SetPixelV
  660. extern "C" BOOL MF_SetPixelV(HDC hdc,int x,int y,COLORREF color)
  661. {
  662. PMRSETPIXELV pmrspv;
  663. PLDC pldc;
  664. DC_PLDC(hdc,pldc,FALSE);
  665. PMDC pmdc = (PMDC)pldc->pvPMDC;
  666. ASSERTGDI(pmdc,"no pmdc\n");
  667. PUTS("MF_SetPixelV\n");
  668. if (!(pmrspv = (PMRSETPIXELV) pmdc->pvNewRecord(SIZEOF_MRSETPIXELV)))
  669. return(FALSE);
  670. pmrspv->vInit(x, y, color);
  671. pmrspv->vCommit(pmdc);
  672. CHECK_COLOR_PAGE(pldc,color);
  673. return(TRUE);
  674. }
  675. // AngleArc
  676. extern "C" BOOL MF_AngleArc(HDC hdc,int x,int y,DWORD r,FLOAT eA,FLOAT eB)
  677. {
  678. PMRANGLEARC pmraa;
  679. PLDC pldc;
  680. DC_PLDC(hdc,pldc,FALSE);
  681. PMDC pmdc = (PMDC)pldc->pvPMDC;
  682. ASSERTGDI(pmdc,"no pmdc\n");
  683. PUTS("MF_AngleArc\n");
  684. if (!(pmraa = (PMRANGLEARC) pmdc->pvNewRecord(SIZEOF_MRANGLEARC)))
  685. return(FALSE);
  686. pmraa->vInit(x, y, r, eA, eB);
  687. pmraa->vCommit(pmdc);
  688. return(TRUE);
  689. }
  690. // SetArcDirection - This is recorded only when used.
  691. extern "C" BOOL MF_ValidateArcDirection(HDC hdc)
  692. {
  693. PLDC pldc;
  694. BOOL bClockwiseMeta, bClockwiseAdvanced;
  695. DC_PLDC(hdc,pldc,FALSE);
  696. PUTS("MF_ValidateArcDirection\n");
  697. // Get the current arc direction recorded in the metafile.
  698. // The metafile is recorded in the advanced graphics mode only.
  699. bClockwiseMeta = (pldc->fl & LDC_META_ARCDIR_CLOCKWISE) ? TRUE : FALSE;
  700. // Get the current arc direction in the advanced graphics mode.
  701. bClockwiseAdvanced = (GetArcDirection(hdc) == AD_CLOCKWISE);
  702. if (GetGraphicsMode(hdc) == GM_COMPATIBLE)
  703. {
  704. switch (GetMapMode(hdc))
  705. {
  706. case MM_LOMETRIC:
  707. case MM_HIMETRIC:
  708. case MM_LOENGLISH:
  709. case MM_HIENGLISH:
  710. case MM_TWIPS:
  711. bClockwiseAdvanced = !bClockwiseAdvanced;
  712. break;
  713. //
  714. // If it is MM_ANISOTROPIC and MM_ISOTROPIC
  715. // and negative transform, we flip the arc direction.
  716. // related bugs - 3026, 74010 [lingyunw]
  717. //
  718. case MM_ANISOTROPIC:
  719. case MM_ISOTROPIC:
  720. {
  721. PDC_ATTR pDcAttr;
  722. PVOID pvUser;
  723. PSHARED_GET_VALIDATE(pvUser,hdc,DC_TYPE);
  724. if (pvUser)
  725. {
  726. pDcAttr = (PDC_ATTR)pvUser;
  727. //
  728. // if the xform has changed, we call to the kernel
  729. // to update it
  730. //
  731. if(pDcAttr->flXform &
  732. (PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED | WORLD_XFORM_CHANGED))
  733. {
  734. if (!NtGdiUpdateTransform(hdc))
  735. return(FALSE);
  736. };
  737. if (((pDcAttr->flXform & PTOD_EFM11_NEGATIVE) != 0) ^
  738. ((pDcAttr->flXform & PTOD_EFM22_NEGATIVE) != 0))
  739. {
  740. bClockwiseAdvanced = !bClockwiseAdvanced;
  741. }
  742. }
  743. }
  744. break;
  745. }
  746. }
  747. // Record it only if the new arc direction differs from the recorded one.
  748. if (bClockwiseMeta == bClockwiseAdvanced)
  749. return(TRUE);
  750. pldc->fl ^= LDC_META_ARCDIR_CLOCKWISE;
  751. return
  752. (
  753. MF_SetD
  754. (
  755. hdc,
  756. (DWORD) (bClockwiseAdvanced ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE),
  757. EMR_SETARCDIRECTION
  758. )
  759. );
  760. }
  761. // Ellipse
  762. // Rectangle
  763. extern "C" BOOL MF_EllipseRect(HDC hdc,int x1,int y1,int x2,int y2,DWORD mrType)
  764. {
  765. PMRE pmre;
  766. PLDC pldc;
  767. DC_PLDC(hdc,pldc,FALSE);
  768. PMDC pmdc = (PMDC)pldc->pvPMDC;
  769. ASSERTGDI(pmdc,"no pmdc\n");
  770. PUTS("MF_EllipseRect\n");
  771. // Validate the arc direction in the metafile first.
  772. if (!MF_ValidateArcDirection(hdc))
  773. return(FALSE);
  774. if (!(pmre = (PMRE) pmdc->pvNewRecord(SIZEOF_MRE)))
  775. return(FALSE);
  776. // If the box is empty, don't record it and return success.
  777. switch (pmre->iInit(mrType, hdc, x1, y1, x2, y2))
  778. {
  779. case MRI_ERROR: return(FALSE);
  780. case MRI_NULLBOX: return(TRUE);
  781. case MRI_OK: break;
  782. default: ASSERTGDI(FALSE, "MRE::iInit returned bad value");
  783. break;
  784. }
  785. pmre->vCommit(pmdc);
  786. return(TRUE);
  787. }
  788. // RoundRect
  789. extern "C" BOOL MF_RoundRect(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3)
  790. {
  791. PMRROUNDRECT pmrrr;
  792. PUTS("MF_RoundRect\n");
  793. PLDC pldc;
  794. DC_PLDC(hdc,pldc,FALSE);
  795. PMDC pmdc = (PMDC)pldc->pvPMDC;
  796. ASSERTGDI(pmdc,"no pmdc\n");
  797. // Validate the arc direction in the metafile first.
  798. if (!MF_ValidateArcDirection(hdc))
  799. return(FALSE);
  800. if (!(pmrrr = (PMRROUNDRECT) pmdc->pvNewRecord(SIZEOF_MRROUNDRECT)))
  801. return(FALSE);
  802. // If the box is empty, don't record it and return success.
  803. switch (pmrrr->iInit(hdc, x1, y1, x2, y2, x3, y3))
  804. {
  805. case MRI_ERROR: return(FALSE);
  806. case MRI_NULLBOX: return(TRUE);
  807. case MRI_OK: break;
  808. default: ASSERTGDI(FALSE, "MRROUNDRECT::iInit returned bad value");
  809. break;
  810. }
  811. pmrrr->vCommit(pmdc);
  812. return(TRUE);
  813. }
  814. // Arc
  815. // ArcTo
  816. // Chord
  817. // Pie
  818. extern "C" BOOL MF_ArcChordPie(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,DWORD mrType)
  819. {
  820. PMREPP pmrepp;
  821. PLDC pldc;
  822. DC_PLDC(hdc,pldc,FALSE);
  823. PMDC pmdc = (PMDC)pldc->pvPMDC;
  824. ASSERTGDI(pmdc,"no pmdc\n");
  825. PUTS("MF_ArcChordPie\n");
  826. // Validate the arc direction in the metafile first.
  827. if (!MF_ValidateArcDirection(hdc))
  828. return(FALSE);
  829. if (!(pmrepp = (PMREPP) pmdc->pvNewRecord(SIZEOF_MREPP)))
  830. return(FALSE);
  831. // If the box is empty, don't record it and return success.
  832. switch (pmrepp->iInit(mrType, hdc, x1, y1, x2, y2, x3, y3, x4, y4))
  833. {
  834. case MRI_ERROR: return(FALSE);
  835. case MRI_NULLBOX: return(TRUE);
  836. case MRI_OK: break;
  837. default: ASSERTGDI(FALSE, "MREPP::iInit returned bad value");
  838. break;
  839. }
  840. pmrepp->vCommit(pmdc);
  841. return(TRUE);
  842. }
  843. // SetWorldTransform
  844. extern "C" BOOL MF_SetWorldTransform(HDC hdc, CONST XFORM *pxform)
  845. {
  846. PMRX pmrx;
  847. PLDC pldc;
  848. DC_PLDC(hdc,pldc,FALSE);
  849. PMDC pmdc = (PMDC)pldc->pvPMDC;
  850. ASSERTGDI(pmdc,"no pmdc\n");
  851. PUTS("MF_SetWorldTransform\n");
  852. pldc->fl |= LDC_FONT_CHANGE;
  853. if (!(pmrx = (PMRX) pmdc->pvNewRecord(SIZEOF_MRX)))
  854. return(FALSE);
  855. pmrx->vInit(EMR_SETWORLDTRANSFORM, *pxform);
  856. pmrx->vCommit(pmdc);
  857. return(TRUE);
  858. }
  859. // ModifyWorldTransform
  860. extern "C" BOOL MF_ModifyWorldTransform(HDC hdc, CONST XFORM *pxform, DWORD iMode)
  861. {
  862. PMRXD pmrxd;
  863. PLDC pldc;
  864. DC_PLDC(hdc,pldc,FALSE);
  865. PMDC pmdc = (PMDC)pldc->pvPMDC;
  866. ASSERTGDI(pmdc,"no pmdc\n");
  867. PUTS("MF_ModifyWorldTransform\n");
  868. pldc->fl |= LDC_FONT_CHANGE;
  869. if (!(pmrxd = (PMRXD) pmdc->pvNewRecord(SIZEOF_MRXD)))
  870. return(FALSE);
  871. // If the mode is set to identity transform, use our identity transform
  872. // since there may not be an input transform.
  873. pmrxd->vInit
  874. (
  875. EMR_MODIFYWORLDTRANSFORM,
  876. (iMode == MWT_IDENTITY) ? xformIdentity : *pxform,
  877. iMode
  878. );
  879. pmrxd->vCommit(pmdc);
  880. return(TRUE);
  881. }
  882. // SelectObject
  883. // SelectPalette
  884. extern "C" BOOL MF_SelectAnyObject(HDC hdc,HANDLE h,DWORD mrType)
  885. {
  886. DWORD imhe;
  887. #ifdef LANGPACK
  888. if(gbLpk && gdwDisableMetafileRec) // if there is alangpack, then don't record this (since we are in the middle of an exttextout call)
  889. {
  890. ASSERTGDI(LO_TYPE(h) == LO_FONT_TYPE, "gdwDisableMetafileRec\n");
  891. return TRUE ;
  892. }
  893. #endif
  894. // Do not do regions. Region call goes to ExtSelectClipRgn.
  895. // Do not do bitmap. Metafile DC is not a memory device.
  896. // MF_InternalCreateObject will return an error if given a bitmap handle.
  897. PUTS("MF_SelectAnyObject\n");
  898. // we need to set the DCBrush and DCPen here if they are selected
  899. if ((h == ghbrDCBrush) || (h == ghbrDCPen))
  900. {
  901. PVOID p;
  902. PDC_ATTR pDcAttr;
  903. PSHARED_GET_VALIDATE(p,hdc,DC_TYPE);
  904. pDcAttr = (PDC_ATTR)p;
  905. if (pDcAttr)
  906. {
  907. if (h == ghbrDCBrush)
  908. {
  909. if (pDcAttr->ulDCBrushClr != CLR_INVALID)
  910. {
  911. // Dont know why they were creating a new brush. ghbrDCBrush is a stock object and can be used as such.
  912. // h = (HANDLE) CreateSolidBrush (pDcAttr->ulDCBrushClr);
  913. }
  914. else
  915. {
  916. return (FALSE);
  917. }
  918. }
  919. if (h == ghbrDCPen)
  920. {
  921. if (pDcAttr->ulDCPenClr != CLR_INVALID)
  922. {
  923. // Dont know why they were creating a new brush. ghbrDCPen is a stock object and can be used as such.
  924. // h = (HANDLE) CreatePen (PS_SOLID, 0, pDcAttr->ulDCPenClr);
  925. }
  926. else
  927. {
  928. return (FALSE);
  929. }
  930. }
  931. if (h == NULL)
  932. {
  933. return (FALSE);
  934. }
  935. }
  936. }
  937. if (!(imhe = MF_InternalCreateObject(hdc, h)))
  938. return(FALSE);
  939. return(MF_SetD(hdc, imhe, mrType));
  940. }
  941. // CreatePen
  942. // CreatePenIndirect
  943. // ExtCreatePen
  944. // CreateBrushIndirect
  945. // CreateDIBPatternBrush
  946. // CreateDIBPatternBrushPt
  947. // CreateHatchBrush
  948. // CreatePatternBrush
  949. // CreateSolidBrush
  950. // CreatePalette
  951. // CreateFont
  952. // CreateFontIndirect
  953. // CreateColorSpace
  954. // Create an object if it does not exist. The object must not be a region.
  955. // It also does not create bitmap objects since we keep them in the drawing
  956. // records.
  957. // Return the metafile handle index of the object. For stock objects,
  958. // return the special object index.
  959. // Return 0 on error.
  960. DWORD MF_InternalCreateObject(HDC hdc,HANDLE hobj)
  961. {
  962. DWORD imhe;
  963. UINT ii;
  964. int iType;
  965. int iRet;
  966. LOGBRUSH lb;
  967. PLDC pldc;
  968. DC_PLDC(hdc,pldc,FALSE);
  969. PMDC pmdc = (PMDC)pldc->pvPMDC;
  970. ASSERTGDI(pmdc,"no pmdc\n");
  971. PUTS("MF_InternalCreateObject\n");
  972. if (hobj == NULL)
  973. {
  974. return(0);
  975. }
  976. // Do not do bitmaps. We don't keep bitmap handles in metafiles.
  977. iType = LO_TYPE(hobj);
  978. if ((iType == LO_BITMAP_TYPE) || (iType == LO_DIBSECTION_TYPE))
  979. {
  980. ERROR_ASSERT(FALSE,
  981. "MF_InternalCreateObject: Cannot select bitmap into an enhanced metafile DC");
  982. return(0);
  983. }
  984. // Do not do regions. Regions are stored in the drawing records.
  985. ASSERTGDI(iType != LO_REGION_TYPE,
  986. "MF_InternalCreateObject: Bad object type");
  987. // If this is a stock object, just return a special object index.
  988. if (IS_STOCKOBJ(hobj))
  989. {
  990. for (ii = 0; ii <= STOCK_LAST; ii++)
  991. {
  992. if (GetStockObject(ii) == hobj)
  993. {
  994. if (iType == LO_FONT_TYPE)
  995. {
  996. pldc->fl |= LDC_FONT_CHANGE;
  997. }
  998. break;
  999. }
  1000. }
  1001. return((DWORD) ENHMETA_STOCK_OBJECT + ii);
  1002. }
  1003. // Check if the metafile DC knows this object.
  1004. METALINK metalink(pmetalink16Get(hobj));
  1005. while (metalink.bValid() && (metalink.ihdc != H_INDEX(hdc)))
  1006. metalink.vNext();
  1007. // If the metafile DC knows this object, just return the metafile handle index.
  1008. if (metalink.bValid())
  1009. {
  1010. if( iType == LO_FONT_TYPE )
  1011. {
  1012. pldc->fl |= LDC_FONT_CHANGE;
  1013. }
  1014. return((DWORD) metalink.imhe);
  1015. }
  1016. // Create the object.
  1017. DWORD ulRet = 0; // Assume failure
  1018. // Allocate a metafile handle entry and update the metalink.
  1019. if ((imhe = imheAllocMHE(hdc, hobj)) == INVALID_INDEX)
  1020. return(ulRet);
  1021. switch (iType)
  1022. {
  1023. // Do brush.
  1024. case LO_BRUSH_TYPE:
  1025. iRet = GetObject(hobj,sizeof(lb),&lb);
  1026. // Stock objects is handled above.
  1027. ASSERTGDI(iRet,"MF_InternalCreateObject: Brush error");
  1028. switch (lb.lbStyle)
  1029. {
  1030. case BS_HATCHED:
  1031. case BS_SOLID:
  1032. CHECK_COLOR_PAGE (pldc,lb.lbColor);
  1033. case BS_HOLLOW:
  1034. PMRCREATEBRUSHINDIRECT pmrcbi;
  1035. if (!(pmrcbi = (PMRCREATEBRUSHINDIRECT) pmdc->pvNewRecord
  1036. (SIZEOF_MRCREATEBRUSHINDIRECT)))
  1037. break;
  1038. pmrcbi->vInit(imhe, lb);
  1039. pmrcbi->vCommit(pmdc);
  1040. ulRet = imhe;
  1041. break;
  1042. case BS_PATTERN:
  1043. case BS_DIBPATTERN:
  1044. case BS_DIBPATTERNPT:
  1045. {
  1046. UINT iUsage;
  1047. HBITMAP hbmRemote;
  1048. BMIH bmih;
  1049. DWORD cbBitsInfo;
  1050. DWORD cbBits;
  1051. BOOL bMonoBrush = FALSE;
  1052. if (!(hbmRemote = GetObjectBitmapHandle((HBRUSH)hobj, &iUsage)))
  1053. {
  1054. ASSERTGDI(FALSE,
  1055. "MF_InternalCreateObject: GetObjectBitmapHandle failed");
  1056. break;
  1057. }
  1058. // For a pattern brush, the usage should be set to DIB_PAL_INDICES
  1059. // if it is monochrome. If it is color, it becomes a dib pattern
  1060. // brush with DIB_RGB_COLORS usage.
  1061. if (lb.lbStyle == BS_PATTERN)
  1062. {
  1063. bMonoBrush = MonoBitmap(hbmRemote);
  1064. if (bMonoBrush)
  1065. iUsage = DIB_PAL_INDICES;
  1066. else
  1067. iUsage = DIB_RGB_COLORS;
  1068. }
  1069. // Get the bitmap info header and sizes.
  1070. if (!bMetaGetDIBInfo(hdc, hbmRemote, &bmih,
  1071. &cbBitsInfo, &cbBits, iUsage, 0, FALSE))
  1072. break;
  1073. // Finally create the record and get the bits.
  1074. PMRBRUSH pmrbr;
  1075. if (!(pmrbr = (PMRBRUSH) pmdc->pvNewRecord
  1076. (SIZEOF_MRBRUSH(cbBitsInfo,cbBits))))
  1077. break;
  1078. if (!pmrbr->bInit
  1079. (
  1080. bMonoBrush
  1081. ? EMR_CREATEMONOBRUSH
  1082. : EMR_CREATEDIBPATTERNBRUSHPT,
  1083. hdc,
  1084. imhe,
  1085. hbmRemote,
  1086. bmih,
  1087. iUsage,
  1088. cbBitsInfo, // size of bitmap info
  1089. cbBits // size of bits buffer
  1090. )
  1091. )
  1092. break;
  1093. // Check whether this is a color brush
  1094. if (pmrbr->fColor)
  1095. {
  1096. SET_COLOR_PAGE(pldc);
  1097. }
  1098. pmrbr->vCommit(pmdc);
  1099. ulRet = imhe;
  1100. }
  1101. break;
  1102. default:
  1103. ASSERTGDI(FALSE, "MF_InternalCreateObject: Brush error");
  1104. }
  1105. break;
  1106. // Do pen.
  1107. case LO_PEN_TYPE:
  1108. PMRCREATEPEN pmrcpn;
  1109. // Allocate dword aligned structure.
  1110. if (!(pmrcpn = (PMRCREATEPEN) pmdc->pvNewRecord(SIZEOF_MRCREATEPEN)))
  1111. break;
  1112. if (!pmrcpn->bInit(hobj, imhe))
  1113. break;
  1114. CHECK_COLOR_PAGE (pldc,pmrcpn->GetPenColor());
  1115. pmrcpn->vCommit(pmdc);
  1116. ulRet = imhe;
  1117. break;
  1118. // Do extended pen.
  1119. case LO_EXTPEN_TYPE:
  1120. EXTLOGPEN elp;
  1121. PEXTLOGPEN pelp;
  1122. int cbelp,tcbelp;
  1123. // Get the size of the ExtPen.
  1124. if (!(cbelp = GetObjectA(hobj, 0, (LPVOID) NULL)))
  1125. break;
  1126. ASSERTGDI(cbelp % 4 == 0, "MF_InternalCreateObject: Bad ext pen size");
  1127. if (cbelp <= sizeof(EXTLOGPEN))
  1128. pelp = &elp;
  1129. else if (!(pelp = (PEXTLOGPEN) LocalAlloc(LMEM_FIXED, (UINT) cbelp)))
  1130. break;
  1131. // Get the ExtPen.
  1132. if (GetObjectA(hobj, cbelp, (LPVOID) pelp) == cbelp)
  1133. {
  1134. UINT iUsage;
  1135. HBITMAP hbmRemote = (HBITMAP) 0;
  1136. BMIH bmih;
  1137. DWORD cbBitsInfo = 0;
  1138. DWORD cbBits = 0;
  1139. BOOL bMonoBrush = FALSE;
  1140. // Use switch statement so we can use the break statement on error.
  1141. // The following code is similiar to the brush creation code.
  1142. switch (pelp->elpBrushStyle)
  1143. {
  1144. case BS_DIBPATTERN:
  1145. pelp->elpBrushStyle = BS_DIBPATTERNPT; // fall through
  1146. case BS_PATTERN:
  1147. case BS_DIBPATTERNPT:
  1148. if (!(hbmRemote = GetObjectBitmapHandle((HBRUSH)hobj, &iUsage)))
  1149. {
  1150. ASSERTGDI(FALSE,
  1151. "MF_InternalCreateObject: GetObjectBitmapHandle failed");
  1152. break;
  1153. }
  1154. // For a pattern brush, the usage should be set to
  1155. // DIB_PAL_INDICES if it is monochrome. If it is color,
  1156. // it becomes a dib pattern brush with DIB_RGB_COLORS usage.
  1157. if (pelp->elpBrushStyle == BS_PATTERN)
  1158. {
  1159. bMonoBrush = MonoBitmap(hbmRemote);
  1160. if (bMonoBrush)
  1161. iUsage = DIB_PAL_INDICES;
  1162. else
  1163. iUsage = DIB_RGB_COLORS;
  1164. }
  1165. // Get the bitmap info header and sizes.
  1166. if (!bMetaGetDIBInfo(hdc, hbmRemote, &bmih,
  1167. &cbBitsInfo, &cbBits, (DWORD) iUsage, 0, FALSE))
  1168. break;
  1169. // Record DIB bitmap if possible.
  1170. pelp->elpBrushStyle = bMonoBrush
  1171. ? BS_PATTERN
  1172. : BS_DIBPATTERNPT;
  1173. *(PDWORD) &pelp->elpColor = (DWORD) iUsage;
  1174. pelp->elpHatch = 0;
  1175. // fall through
  1176. default:
  1177. tcbelp = cbelp;
  1178. #if !defined(_X86_)
  1179. // Adjust the elp to be EXTLOGPEN32 for IA64
  1180. // We do this by shifting all DWORDS from
  1181. // &(pelp->elpNumEntries) up by 4 bytes.
  1182. // This is to make sure the disk format is the same
  1183. // as the X86 compatible EXTLOGPEN32 bassed format.
  1184. MoveMemory((PBYTE)(&pelp->elpNumEntries)-4,
  1185. (PBYTE)(&pelp->elpNumEntries),
  1186. tcbelp-FIELD_OFFSET(EXTLOGPEN,elpNumEntries));
  1187. tcbelp -= 4;
  1188. #endif
  1189. // Finally create the record (and get the bits).
  1190. PMREXTCREATEPEN pmrecp;
  1191. // Allocate dword aligned structure.
  1192. if (!(pmrecp = (PMREXTCREATEPEN) pmdc->pvNewRecord
  1193. (SIZEOF_MREXTCREATEPEN(tcbelp,cbBitsInfo,cbBits))))
  1194. break;
  1195. if (!pmrecp->bInit
  1196. (
  1197. hdc,
  1198. imhe,
  1199. tcbelp,
  1200. (PEXTLOGPEN32)pelp,
  1201. hbmRemote,
  1202. bmih,
  1203. cbBitsInfo, // size of bitmap info
  1204. cbBits // size of bits buffer
  1205. )
  1206. )
  1207. break;
  1208. // Check for color page info
  1209. if (pelp->elpBrushStyle == BS_SOLID || pelp->elpBrushStyle == BS_HATCHED)
  1210. {
  1211. CHECK_COLOR_PAGE (pldc,pelp->elpColor);
  1212. }
  1213. else if (hbmRemote && pmrecp->fColor)
  1214. {
  1215. SET_COLOR_PAGE(pldc);
  1216. }
  1217. pmrecp->vCommit(pmdc);
  1218. ulRet = imhe;
  1219. break;
  1220. }
  1221. }
  1222. if (cbelp > sizeof(EXTLOGPEN))
  1223. {
  1224. if (LocalFree(pelp))
  1225. {
  1226. ASSERTGDI(FALSE, "MF_InternalCreateObject: LocalFree failed");
  1227. }
  1228. }
  1229. break;
  1230. // Do palette.
  1231. case LO_PALETTE_TYPE:
  1232. PMRCREATEPALETTE pmrcp;
  1233. USHORT cEntries;
  1234. if (GetObjectA(hobj, sizeof(USHORT), (LPVOID) &cEntries) != 2)
  1235. {
  1236. ASSERTGDI(FALSE, "MF_InternalCreateObject: GetObjectA failed");
  1237. break;
  1238. }
  1239. if (!(pmrcp = (PMRCREATEPALETTE) pmdc->pvNewRecord
  1240. (SIZEOF_MRCREATEPALETTE(cEntries))))
  1241. break;
  1242. // Also clear peFlags.
  1243. if (!pmrcp->bInit((HPALETTE) hobj, imhe, cEntries))
  1244. break;
  1245. // Also update the metafile palette.
  1246. if (!pmrcp->bCommit(pmdc))
  1247. break;
  1248. ulRet = imhe;
  1249. break;
  1250. // Do font.
  1251. case LO_FONT_TYPE:
  1252. PMREXTCREATEFONTINDIRECTW pmecfiw;
  1253. PLDC pldc;
  1254. int iSize;
  1255. ENUMLOGFONTEXDVW elfw;
  1256. pldc = GET_PLDC(hdc);
  1257. iSize = GetObjectW(hobj, (int)sizeof(ENUMLOGFONTEXDVW), (LPVOID)&elfw);
  1258. if (!iSize)
  1259. break;
  1260. ASSERTGDI(
  1261. ((DWORD)iSize) == (offsetof(ENUMLOGFONTEXDVW,elfDesignVector) + SIZEOFDV(elfw.elfDesignVector.dvNumAxes)),
  1262. "sizeof enumlogfontexdvw is broken\n"
  1263. );
  1264. ASSERTGDI(
  1265. sizeof(EXTLOGFONTW) < (offsetof(ENUMLOGFONTEXDVW,elfDesignVector) + SIZEOFDV(0)),
  1266. "sizeof(EXTLOGFONTW) problem\n");
  1267. pldc->fl |= LDC_FONT_CHANGE;
  1268. if (!(pmecfiw = (PMREXTCREATEFONTINDIRECTW) pmdc->pvNewRecord
  1269. (SIZEOF_MRCREATEFONTINDIRECTEXW(iSize))))
  1270. break;
  1271. pmecfiw->vInit((HFONT) hobj, imhe, &elfw);
  1272. pmecfiw->vCommit(pmdc);
  1273. ulRet = imhe;
  1274. break;
  1275. // Do color space.
  1276. case LO_ICMLCS_TYPE:
  1277. if (!MF_InternalCreateColorSpace(hdc,hobj,imhe))
  1278. {
  1279. break;
  1280. }
  1281. ulRet = imhe;
  1282. break;
  1283. case LO_BITMAP_TYPE:
  1284. case LO_DIBSECTION_TYPE:
  1285. default:
  1286. ASSERTGDI(FALSE, "MF_InternalCreateObject: Bad object type\n");
  1287. break;
  1288. }
  1289. // Check for error.
  1290. if (ulRet == 0)
  1291. {
  1292. ERROR_ASSERT(FALSE,
  1293. "MF_InternalCreateObject: unable to record the object");
  1294. vFreeMHE(hdc, imhe);
  1295. return(ulRet);
  1296. }
  1297. ASSERTGDI(ulRet == imhe, "MF_InternalCreateObject: Bad return value");
  1298. // Update number of handles in the metafile header record.
  1299. pmdc->vUpdateNHandles(imhe);
  1300. // Return the metafile handle index of the object.
  1301. return(imhe);
  1302. }
  1303. // DeleteObject
  1304. extern "C" BOOL MF_DeleteObject(HANDLE h)
  1305. {
  1306. // We don't get called if it is a stock object.
  1307. HDC hdc;
  1308. METALINK metalink;
  1309. PUTS("MF_DeleteObject\n");
  1310. ASSERTGDI(pmetalink16Get(h) != NULL,
  1311. "MF_DeleteObject: No object to delete");
  1312. // Delete the object from each metafile DC which references it.
  1313. while (TRUE)
  1314. {
  1315. metalink.vInit(pmetalink16Get(h));
  1316. if (!metalink.bValid())
  1317. break;
  1318. hdc = hdcFromIhdc(metalink.ihdc);
  1319. #if DBG
  1320. ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == h,
  1321. "MF_DeleteObject: Bad metalink");
  1322. ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
  1323. "MF_DeleteObject: Bad metalink");
  1324. #endif
  1325. // Send a delete object record.
  1326. (VOID) MF_SetD(hdc, (DWORD) metalink.imhe, EMR_DELETEOBJECT);
  1327. vFreeMHE(hdc, (ULONG) metalink.imhe);
  1328. }
  1329. return(TRUE);
  1330. }
  1331. // SetPaletteEntries
  1332. extern "C" BOOL MF_SetPaletteEntries
  1333. (
  1334. HPALETTE hpal,
  1335. UINT iStart,
  1336. UINT cEntries,
  1337. CONST PALETTEENTRY *pPalEntries
  1338. )
  1339. {
  1340. // We don't get called if it is a stock object.
  1341. PUTS("MF_SetPaletteEntries\n");
  1342. // Create a record in each metafile DC which references it.
  1343. // Note that if an object has been previously selected in a metafile DC
  1344. // and currently deselected, it is still referenced by the metafile DC.
  1345. for
  1346. (
  1347. METALINK metalink(pmetalink16Get(hpal));
  1348. metalink.bValid();
  1349. metalink.vNext()
  1350. )
  1351. {
  1352. // Get a metafile DC.
  1353. PMDC pmdc = GET_PMDC(hdcFromIhdc(metalink.ihdc));
  1354. PMRSETPALETTEENTRIES pmrspe;
  1355. ASSERTGDI(pmdc->pmhe[metalink.imhe].lhObject == hpal,
  1356. "MF_SetPaletteEntries: Bad metalink");
  1357. ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
  1358. "MF_SetPaletteEntries: Bad metalink");
  1359. // Send a SetPaletteEntries record.
  1360. if (!(pmrspe = (PMRSETPALETTEENTRIES) pmdc->pvNewRecord
  1361. (SIZEOF_MRSETPALETTEENTRIES(cEntries))))
  1362. return(FALSE);
  1363. // Also clear peFlags.
  1364. pmrspe->vInit(metalink.imhe, iStart, cEntries, pPalEntries);
  1365. // Also update the metafile palette.
  1366. if (!pmrspe->bCommit(pmdc))
  1367. return(FALSE);
  1368. }
  1369. return(TRUE);
  1370. }
  1371. /******************************Public*Routine******************************\
  1372. * MF_ColorCorrectPalette
  1373. *
  1374. *
  1375. * Arguments:
  1376. *
  1377. *
  1378. *
  1379. * Return Value:
  1380. *
  1381. *
  1382. *
  1383. * History:
  1384. *
  1385. * 9/23/1996 Mark Enstrom [marke]
  1386. *
  1387. \**************************************************************************/
  1388. extern "C"
  1389. BOOL
  1390. MF_ColorCorrectPalette(
  1391. HDC hdc,
  1392. HPALETTE hpal,
  1393. ULONG FirstEntry,
  1394. ULONG NumberOfEntries)
  1395. {
  1396. PMRDDDD pmrdddd;
  1397. DWORD imhePal;
  1398. PLDC pldc;
  1399. DC_PLDC(hdc,pldc,FALSE);
  1400. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1401. ASSERTGDI(pmdc,"no pmdc\n");
  1402. PUTS("MF_SetDDDD : ColorCorrectPalette\n");
  1403. //
  1404. // get palette
  1405. //
  1406. if (!(imhePal = MF_InternalCreateObject(hdc, hpal)))
  1407. {
  1408. return(FALSE);
  1409. }
  1410. if (!(pmrdddd = (PMRDDDD) pmdc->pvNewRecord(SIZEOF_MRDDDD)))
  1411. {
  1412. return(FALSE);
  1413. }
  1414. pmrdddd->vInit(EMR_COLORCORRECTPALETTE,imhePal,FirstEntry,NumberOfEntries,0);
  1415. pmrdddd->vCommit(pmdc);
  1416. return(TRUE);
  1417. }
  1418. // ResizePalette
  1419. extern "C" BOOL MF_ResizePalette(HPALETTE hpal,UINT c)
  1420. {
  1421. // We don't get called if it is a stock object.
  1422. PUTS("MF_ResizePalette\n");
  1423. // Create a record in each metafile DC which references it.
  1424. // Note that if an object has been previously selected in a metafile DC
  1425. // and currently deselected, it is still referenced by the metafile DC.
  1426. for
  1427. (
  1428. METALINK metalink(pmetalink16Get(hpal));
  1429. metalink.bValid();
  1430. metalink.vNext()
  1431. )
  1432. {
  1433. HDC hdc = hdcFromIhdc(metalink.ihdc);
  1434. ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == hpal,
  1435. "MF_ResizePalette: Bad metalink");
  1436. ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
  1437. "MF_ResizePalette: Bad metalink");
  1438. // Send a ResizePalette record.
  1439. if
  1440. (
  1441. !MF_SetDD
  1442. (
  1443. hdc,
  1444. (DWORD)metalink.imhe,
  1445. (DWORD)c,
  1446. EMR_RESIZEPALETTE
  1447. )
  1448. )
  1449. return(FALSE);
  1450. }
  1451. return(TRUE);
  1452. }
  1453. // RealizePalette
  1454. //
  1455. // This function takes a hpal, not a hdc! We want to metafile RealizePalette
  1456. // calls in other DC which affect the metafile DCs as well. For example,
  1457. // if a palette is selected into a display DC and a metafile DC, a
  1458. // RealizePalette on the display DC will cause a record to be generated in
  1459. // the metafile DC. The reason is applications may expect this behavior
  1460. // in Windows although we do not completely agree with this. In any case,
  1461. // we do the right thing when they realize a palette on metafile DCs.
  1462. //
  1463. // Note that no record is generated if the stock palette is realized. This
  1464. // is compatible with the current design for palette management in metafiles.
  1465. extern "C" BOOL MF_RealizePalette(HPALETTE hpal)
  1466. {
  1467. // We don't get called if it is a stock object.
  1468. PUTS("MF_RealizePalette\n");
  1469. // Create a record in each metafile DC which selects it (NOT references it!).
  1470. // Note that if an object has been previously selected in a metafile DC
  1471. // and currently deselected, it is still referenced by the metafile DC.
  1472. for
  1473. (
  1474. METALINK metalink(pmetalink16Get(hpal));
  1475. metalink.bValid();
  1476. metalink.vNext()
  1477. )
  1478. {
  1479. HDC hdc = hdcFromIhdc(metalink.ihdc);
  1480. ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == hpal,
  1481. "MF_RealizePalette: Bad metalink");
  1482. ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
  1483. "MF_RealizePalette: Bad metalink");
  1484. // Send a RealizePalette record.
  1485. if (GetDCObject(hdc,LO_PALETTE_TYPE) == hpal)
  1486. if (!MF_Record(hdc,EMR_REALIZEPALETTE))
  1487. return(FALSE);
  1488. }
  1489. return(TRUE);
  1490. }
  1491. // EOF - emit an EOF metafile record.
  1492. // This function is called by CloseEnhMetaFile to emit the last metafile record.
  1493. // The EOF record includes the metafile palette if any logical palette is
  1494. // used in the metafile.
  1495. extern "C" BOOL MF_EOF(HDC hdc, ULONG cEntries, PPALETTEENTRY pPalEntries)
  1496. {
  1497. PMREOF pmreof;
  1498. DWORD cbEOF;
  1499. PLDC pldc;
  1500. DC_PLDC(hdc,pldc,FALSE);
  1501. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1502. ASSERTGDI(pmdc,"no pmdc\n");
  1503. PUTS("MF_EOF\n");
  1504. cbEOF = SIZEOF_MREOF(cEntries);
  1505. if (!(pmreof = (PMREOF) pmdc->pvNewRecord(cbEOF)))
  1506. return(FALSE);
  1507. pmreof->vInit(cEntries, pPalEntries, cbEOF);
  1508. pmreof->vCommit(pmdc);
  1509. return(TRUE);
  1510. }
  1511. // GdiComment - emit a metafile comment record.
  1512. extern "C" BOOL MF_GdiComment(HDC hdc, UINT nSize, CONST BYTE *lpData)
  1513. {
  1514. PMRGDICOMMENT pmrc;
  1515. PLDC pldc;
  1516. DC_PLDC(hdc,pldc,FALSE);
  1517. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1518. ASSERTGDI(pmdc,"no pmdc\n");
  1519. PUTS("MF_GdiComment\n");
  1520. // Ignore GDICOMMENT_WINDOWS_METAFILE and other non-embeddable public comments.
  1521. // These comments are now extra baggage.
  1522. if (nSize >= 2 * sizeof(DWORD)
  1523. && ((PDWORD) lpData)[0] == GDICOMMENT_IDENTIFIER
  1524. && ((PDWORD) lpData)[1] & GDICOMMENT_NOEMBED)
  1525. return(TRUE);
  1526. if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT(nSize))))
  1527. return(FALSE);
  1528. // If it is a GDICOMMENT_MULTIFORMATS or other public comments containing
  1529. // logical bounds, we need to accumulate the bounds.
  1530. // We assume that applications set up metafile palette properly before
  1531. // embedding so we do not have to accumulate the metafile palette here.
  1532. // We do the bounds after pvNewRecord so that the previous bounds is
  1533. // accounted for properly.
  1534. if (nSize >= 2 * sizeof(DWORD)
  1535. && ((PDWORD) lpData)[0] == GDICOMMENT_IDENTIFIER
  1536. && ((PDWORD) lpData)[1] & GDICOMMENT_ACCUMBOUNDS)
  1537. {
  1538. POINT aptBounds[4];
  1539. RECT rcBounds;
  1540. // The logical output rectangle follows the ident and iComment fields.
  1541. CONST RECTL *prclOutput = (PRECTL) &lpData[2 * sizeof(DWORD)];
  1542. aptBounds[0].x = prclOutput->left;
  1543. aptBounds[0].y = prclOutput->top;
  1544. aptBounds[1].x = prclOutput->right;
  1545. aptBounds[1].y = prclOutput->top;
  1546. aptBounds[2].x = prclOutput->right;
  1547. aptBounds[2].y = prclOutput->bottom;
  1548. aptBounds[3].x = prclOutput->left;
  1549. aptBounds[3].y = prclOutput->bottom;
  1550. if (!LPtoDP(hdc, aptBounds, 4))
  1551. return(FALSE);
  1552. rcBounds.left = MIN4(aptBounds[0].x,aptBounds[1].x,aptBounds[2].x,aptBounds[3].x);
  1553. rcBounds.right = MAX4(aptBounds[0].x,aptBounds[1].x,aptBounds[2].x,aptBounds[3].x);
  1554. rcBounds.top = MIN4(aptBounds[0].y,aptBounds[1].y,aptBounds[2].y,aptBounds[3].y);
  1555. rcBounds.bottom = MAX4(aptBounds[0].y,aptBounds[1].y,aptBounds[2].y,aptBounds[3].y);
  1556. (void) SetBoundsRectAlt(hdc, &rcBounds, (UINT) (DCB_WINDOWMGR | DCB_ACCUMULATE));
  1557. }
  1558. pmrc->vInit(nSize, lpData);
  1559. pmrc->vCommit(pmdc);
  1560. return(TRUE);
  1561. }
  1562. //
  1563. // Emit a EMF comment record which contains embedded font information
  1564. //
  1565. BOOL
  1566. WriteFontDataAsEMFComment(
  1567. PLDC pldc,
  1568. DWORD ulID,
  1569. PVOID buf1,
  1570. DWORD size1,
  1571. PVOID buf2,
  1572. DWORD size2
  1573. )
  1574. {
  1575. static struct {
  1576. DWORD reserved;
  1577. DWORD signature;
  1578. } FontCommentHeader = { 0, 'TONF' };
  1579. EMFITEMHEADER emfi = { ulID, size1+size2 };
  1580. COMMENTDATABUF databuf[4] = {
  1581. { sizeof(FontCommentHeader), &FontCommentHeader },
  1582. { sizeof(emfi), &emfi },
  1583. { size1, buf1 },
  1584. { size2, buf2 }
  1585. };
  1586. PMRGDICOMMENT pmrc;
  1587. UINT n;
  1588. PMDC pmdc = (PMDC) pldc->pvPMDC;
  1589. BOOL result;
  1590. if (!pmdc || !pmdc->bIsEMFSpool())
  1591. {
  1592. ASSERTGDI(FALSE, "WriteFontDataAsEMFComment: pmdc is NULL\n");
  1593. return FALSE;
  1594. }
  1595. //
  1596. // Record the font data as EMF comment and remember
  1597. // its location in the EMF spool file.
  1598. //
  1599. n = sizeof(FontCommentHeader) + sizeof(emfi) + size1 + size2;
  1600. if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT(n))))
  1601. return FALSE;
  1602. n = SIZEOF_MRGDICOMMENT(0) + sizeof(FontCommentHeader);
  1603. result = pmdc->SaveFontCommentOffset(ulID, n);
  1604. pmrc->vInit(4, databuf);
  1605. pmrc->vCommit(pmdc);
  1606. return result;
  1607. }
  1608. // Emit a metafile comment record for embedded windows metafile.
  1609. extern "C" BOOL MF_GdiCommentWindowsMetaFile(HDC hdc, UINT nSize, CONST BYTE *lpData)
  1610. {
  1611. PMRGDICOMMENT pmrc;
  1612. PLDC pldc;
  1613. DC_PLDC(hdc,pldc,FALSE);
  1614. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1615. ASSERTGDI(pmdc,"no pmdc\n");
  1616. PUTS("MF_GdiCommentWindowsMetaFile\n");
  1617. if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT_WINDOWS_METAFILE(nSize))))
  1618. return(FALSE);
  1619. pmrc->vInitWindowsMetaFile(nSize, lpData);
  1620. pmrc->vCommit(pmdc);
  1621. return(TRUE);
  1622. }
  1623. // Emit a metafile comment record for begin group. This is used to identify
  1624. // the beginning of an embedded enhanced metafile.
  1625. extern "C" BOOL MF_GdiCommentBeginGroupEMF(HDC hdc, PENHMETAHEADER pemfHeader)
  1626. {
  1627. PMRGDICOMMENT pmrc;
  1628. PLDC pldc;
  1629. DC_PLDC(hdc,pldc,FALSE);
  1630. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1631. ASSERTGDI(pmdc,"no pmdc\n");
  1632. PUTS("MF_GdiCommentBeginGroupEMF\n");
  1633. if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT_BEGINGROUP(pemfHeader->nDescription))))
  1634. return(FALSE);
  1635. pmrc->vInitBeginGroupEMF(pemfHeader);
  1636. pmrc->vCommit(pmdc);
  1637. return(TRUE);
  1638. }
  1639. // Emit a metafile comment record for end group. This is used to identify
  1640. // the end of an embedded enhanced metafile.
  1641. extern "C" BOOL MF_GdiCommentEndGroupEMF(HDC hdc)
  1642. {
  1643. DWORD ad[2];
  1644. PUTS("MF_GdiCommentEndGroupEMF\n");
  1645. ad[0] = GDICOMMENT_IDENTIFIER; // ident
  1646. ad[1] = GDICOMMENT_ENDGROUP; // iComment
  1647. return(MF_GdiComment(hdc, (UINT) sizeof(ad), (LPBYTE) &ad));
  1648. }
  1649. // MF_AnyBitBlt helper.
  1650. extern "C" BOOL MF_DoBitBlt
  1651. (
  1652. PMDC pmdcDst,
  1653. int xDst,
  1654. int yDst,
  1655. int cxDst,
  1656. int cyDst,
  1657. DWORD rop,
  1658. int xSrc = 0,
  1659. int ySrc = 0,
  1660. PXFORM pxformSrc = &xformIdentity,
  1661. COLORREF clrBkSrc = 0,
  1662. PBMIH pbmihSrc = (PBMIH) NULL,
  1663. HBITMAP hbmSrc = (HBITMAP) 0,
  1664. DWORD cbBitsInfoSrc = 0,
  1665. DWORD cbBitsSrc = 0
  1666. )
  1667. {
  1668. PMRBB pmrbb;
  1669. if (!(pmrbb = (PMRBB) pmdcDst->pvNewRecord
  1670. (SIZEOF_MRBB(cbBitsInfoSrc,cbBitsSrc))))
  1671. return(FALSE);
  1672. // Use compression option
  1673. if (!pmrbb->bInit
  1674. (
  1675. EMR_BITBLT,
  1676. pmdcDst, // pmdcDst
  1677. xDst, // xDst
  1678. yDst, // yDst
  1679. cxDst, // cxDst
  1680. cyDst, // cyDst
  1681. rop, // rop
  1682. xSrc, // xSrc
  1683. ySrc, // ySrc
  1684. pxformSrc, // source DC transform
  1685. clrBkSrc, // source DC BkColor
  1686. pbmihSrc, // source bitmap info header
  1687. hbmSrc, // source bitmap to save
  1688. hbmSrc ? sizeof(MRBB) : 0, // offset to bitmap info
  1689. cbBitsInfoSrc, // size of bitmap info
  1690. hbmSrc ? sizeof(MRBB) + cbBitsInfoSrc : 0,// offset to bits
  1691. cbBitsSrc // size of bits buffer
  1692. )
  1693. )
  1694. return(FALSE);
  1695. pmrbb->vCommit(pmdcDst);
  1696. return(TRUE);
  1697. }
  1698. /******************************Public*Routine******************************\
  1699. * MF_DoAlphaBlend
  1700. *
  1701. *
  1702. * Arguments:
  1703. *
  1704. *
  1705. *
  1706. * Return Value:
  1707. *
  1708. *
  1709. *
  1710. * History:
  1711. *
  1712. * 12/3/1996 Mark Enstrom [marke]
  1713. *
  1714. \**************************************************************************/
  1715. extern "C" BOOL MF_DoAlphaBlend
  1716. (
  1717. PMDC pmdcDst,
  1718. int xDst,
  1719. int yDst,
  1720. int cxDst,
  1721. int cyDst,
  1722. DWORD Blend,
  1723. int xSrc,
  1724. int ySrc,
  1725. int cxSrc,
  1726. int cySrc,
  1727. PXFORM pxformSrc,
  1728. COLORREF clrBkSrc,
  1729. PBMIH pbmihSrc,
  1730. HBITMAP hbmSrc,
  1731. DWORD cbBitsInfoSrc,
  1732. DWORD cbBitsSrc
  1733. )
  1734. {
  1735. PMRALPHABLEND pmrai;
  1736. // We always have a source bitmap here. AlphaImage without a source is not valid
  1737. ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoAlphaBlend: Bad hbmSrc");
  1738. if (!(pmrai = (PMRALPHABLEND) pmdcDst->pvNewRecord
  1739. (SIZEOF_MRALPHABLEND(cbBitsInfoSrc,cbBitsSrc))))
  1740. return(FALSE);
  1741. // Use compression option
  1742. if (!pmrai->bInit
  1743. (
  1744. pmdcDst, // pmdcDst
  1745. xDst, // xDst
  1746. yDst, // yDst
  1747. cxDst, // cxDst
  1748. cyDst, // cyDst
  1749. Blend, // replaves rop
  1750. xSrc, // xSrc
  1751. ySrc, // ySrc
  1752. cxSrc, // cxSrc
  1753. cySrc, // cySrc
  1754. pxformSrc, // source DC transform
  1755. clrBkSrc, // source DC BkColor
  1756. pbmihSrc, // source bitmap info header
  1757. hbmSrc, // source bitmap to save
  1758. sizeof(MRALPHABLEND),// offset to bitmap info
  1759. cbBitsInfoSrc, // size of bitmap info
  1760. sizeof(MRALPHABLEND) + cbBitsInfoSrc,// offset to bits
  1761. cbBitsSrc // size of bits buffer
  1762. )
  1763. )
  1764. return(FALSE);
  1765. pmrai->vCommit(pmdcDst);
  1766. return(TRUE);
  1767. }
  1768. /******************************Public*Routine******************************\
  1769. * MF_DoTransparentBlt
  1770. *
  1771. *
  1772. * Arguments:
  1773. *
  1774. *
  1775. *
  1776. * Return Value:
  1777. *
  1778. *
  1779. *
  1780. * History:
  1781. *
  1782. * 12/3/1996 Mark Enstrom [marke]
  1783. *
  1784. \**************************************************************************/
  1785. extern "C" BOOL MF_DoTransparentBlt
  1786. (
  1787. PMDC pmdcDst,
  1788. int xDst,
  1789. int yDst,
  1790. int cxDst,
  1791. int cyDst,
  1792. DWORD Blend,
  1793. int xSrc,
  1794. int ySrc,
  1795. int cxSrc,
  1796. int cySrc,
  1797. PXFORM pxformSrc,
  1798. COLORREF clrBkSrc,
  1799. PBMIH pbmihSrc,
  1800. HBITMAP hbmSrc,
  1801. DWORD cbBitsInfoSrc,
  1802. DWORD cbBitsSrc
  1803. )
  1804. {
  1805. PMRTRANSPARENTBLT pmrai;
  1806. // We always have a source bitmap here. TransparentImage without a source is not valid
  1807. ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoTransparentImage: Bad hbmSrc");
  1808. if (!(pmrai = (PMRTRANSPARENTBLT) pmdcDst->pvNewRecord
  1809. (SIZEOF_MRTRANSPARENTBLT(cbBitsInfoSrc,cbBitsSrc))))
  1810. return(FALSE);
  1811. // Use compression option
  1812. if (!pmrai->bInit
  1813. (
  1814. pmdcDst, // pmdcDst
  1815. xDst, // xDst
  1816. yDst, // yDst
  1817. cxDst, // cxDst
  1818. cyDst, // cyDst
  1819. Blend, // color
  1820. xSrc, // xSrc
  1821. ySrc, // ySrc
  1822. cxSrc,
  1823. cySrc,
  1824. pxformSrc, // source DC transform
  1825. clrBkSrc, // source DC BkColor
  1826. pbmihSrc, // source bitmap info header
  1827. hbmSrc, // source bitmap to save
  1828. sizeof(MRTRANSPARENTBLT),// offset to bitmap info
  1829. cbBitsInfoSrc, // size of bitmap info
  1830. sizeof(MRTRANSPARENTBLT) + cbBitsInfoSrc,// offset to bits
  1831. cbBitsSrc // size of bits buffer
  1832. )
  1833. )
  1834. return(FALSE);
  1835. pmrai->vCommit(pmdcDst);
  1836. return(TRUE);
  1837. }
  1838. // MF_AnyBitBlt helper.
  1839. extern "C" BOOL MF_DoStretchBlt
  1840. (
  1841. PMDC pmdcDst,
  1842. int xDst,
  1843. int yDst,
  1844. int cxDst,
  1845. int cyDst,
  1846. DWORD rop,
  1847. int xSrc,
  1848. int ySrc,
  1849. int cxSrc,
  1850. int cySrc,
  1851. PXFORM pxformSrc,
  1852. COLORREF clrBkSrc,
  1853. PBMIH pbmihSrc,
  1854. HBITMAP hbmSrc,
  1855. DWORD cbBitsInfoSrc,
  1856. DWORD cbBitsSrc
  1857. )
  1858. {
  1859. PMRSTRETCHBLT pmrsb;
  1860. // We always have a source bitmap here. StretchBlt without a source is
  1861. // recorded as BitBlt.
  1862. ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoStretchBlt: Bad hbmSrc");
  1863. if (!(pmrsb = (PMRSTRETCHBLT) pmdcDst->pvNewRecord
  1864. (SIZEOF_MRSTRETCHBLT(cbBitsInfoSrc,cbBitsSrc))))
  1865. return(FALSE);
  1866. // Use compression option
  1867. if (!pmrsb->bInit
  1868. (
  1869. pmdcDst, // pmdcDst
  1870. xDst, // xDst
  1871. yDst, // yDst
  1872. cxDst, // cxDst
  1873. cyDst, // cyDst
  1874. rop, // rop
  1875. xSrc, // xSrc
  1876. ySrc, // ySrc
  1877. cxSrc, // cxSrc
  1878. cySrc, // cySrc
  1879. pxformSrc, // source DC transform
  1880. clrBkSrc, // source DC BkColor
  1881. pbmihSrc, // source bitmap info header
  1882. hbmSrc, // source bitmap to save
  1883. sizeof(MRSTRETCHBLT),// offset to bitmap info
  1884. cbBitsInfoSrc, // size of bitmap info
  1885. sizeof(MRSTRETCHBLT) + cbBitsInfoSrc,// offset to bits
  1886. cbBitsSrc // size of bits buffer
  1887. )
  1888. )
  1889. return(FALSE);
  1890. pmrsb->vCommit(pmdcDst);
  1891. return(TRUE);
  1892. }
  1893. // MF_AnyBitBlt helper.
  1894. extern "C" BOOL MF_DoMaskBlt
  1895. (
  1896. PMDC pmdcDst,
  1897. int xDst,
  1898. int yDst,
  1899. int cxDst,
  1900. int cyDst,
  1901. DWORD rop3,
  1902. PBMIH pbmihMask,
  1903. HBITMAP hbmMask,
  1904. DWORD cbBitsInfoMask,
  1905. DWORD cbBitsMask,
  1906. int xMask,
  1907. int yMask,
  1908. int xSrc,
  1909. int ySrc,
  1910. PXFORM pxformSrc,
  1911. COLORREF clrBkSrc = 0,
  1912. PBMIH pbmihSrc = (PBMIH) NULL,
  1913. HBITMAP hbmSrc = (HBITMAP) 0,
  1914. DWORD cbBitsInfoSrc = 0,
  1915. DWORD cbBitsSrc = 0
  1916. )
  1917. {
  1918. PMRMASKBLT pmrmb;
  1919. DWORD offBase = sizeof(MRMASKBLT);
  1920. DWORD offBitsInfoSrc = 0;
  1921. DWORD offBitsSrc = 0;
  1922. DWORD offBitsInfoMask = 0;
  1923. DWORD offBitsMask = 0;
  1924. if (hbmSrc)
  1925. {
  1926. offBitsInfoSrc = offBase;
  1927. offBitsSrc = offBitsInfoSrc + cbBitsInfoSrc;
  1928. offBase = offBitsSrc + cbBitsSrc;
  1929. }
  1930. if (hbmMask)
  1931. {
  1932. offBitsInfoMask = offBase;
  1933. offBitsMask = offBitsInfoMask + cbBitsInfoMask;
  1934. }
  1935. // Now create the record.
  1936. if (!(pmrmb = (PMRMASKBLT) pmdcDst->pvNewRecord
  1937. (SIZEOF_MRMASKBLT(cbBitsInfoSrc,cbBitsSrc,cbBitsInfoMask,cbBitsMask))))
  1938. return(FALSE);
  1939. // Use compression option
  1940. if (!pmrmb->bInit
  1941. (
  1942. pmdcDst, // pmdcDst
  1943. xDst, // xDst
  1944. yDst, // yDst
  1945. cxDst, // cxDst
  1946. cyDst, // cyDst
  1947. rop3, // rop3
  1948. xSrc, // xSrc
  1949. ySrc, // ySrc
  1950. pxformSrc, // source DC transform
  1951. clrBkSrc, // source DC BkColor
  1952. pbmihSrc, // source bitmap info header
  1953. hbmSrc, // source bitmap to save
  1954. offBitsInfoSrc, // offset to bitmap info
  1955. cbBitsInfoSrc, // size of bitmap info
  1956. offBitsSrc, // offset to bits
  1957. cbBitsSrc, // size of bits buffer
  1958. xMask, // xMask
  1959. yMask, // yMask
  1960. pbmihMask, // mask bitmap info header
  1961. hbmMask, // mask bitmap
  1962. offBitsInfoMask, // offset to mask bitmap info
  1963. cbBitsInfoMask, // size of mask bitmap info
  1964. offBitsMask, // offset to mask bits
  1965. cbBitsMask // size of mask bits buffer
  1966. )
  1967. )
  1968. return(FALSE);
  1969. pmrmb->vCommit(pmdcDst);
  1970. return(TRUE);
  1971. }
  1972. // MF_AnyBitBlt helper.
  1973. extern "C" BOOL MF_DoPlgBlt
  1974. (
  1975. PMDC pmdcDst,
  1976. CONST POINT *pptDst,
  1977. PBMIH pbmihMask,
  1978. HBITMAP hbmMask,
  1979. DWORD cbBitsInfoMask,
  1980. DWORD cbBitsMask,
  1981. int xMask,
  1982. int yMask,
  1983. int xSrc,
  1984. int ySrc,
  1985. int cxSrc,
  1986. int cySrc,
  1987. PXFORM pxformSrc,
  1988. COLORREF clrBkSrc,
  1989. PBMIH pbmihSrc,
  1990. HBITMAP hbmSrc,
  1991. DWORD cbBitsInfoSrc,
  1992. DWORD cbBitsSrc
  1993. )
  1994. {
  1995. PMRPLGBLT pmrpb;
  1996. // We always have a source bitmap here. Destination to destination PlgBlt
  1997. // is not allowed.
  1998. ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoPlgBlt: Bad hbmSrc");
  1999. // Now create the record.
  2000. if (!(pmrpb = (PMRPLGBLT) pmdcDst->pvNewRecord
  2001. (SIZEOF_MRPLGBLT(cbBitsInfoSrc,cbBitsSrc,cbBitsInfoMask,cbBitsMask))))
  2002. return(FALSE);
  2003. // Use compression option
  2004. if (!pmrpb->bInit
  2005. (
  2006. pmdcDst, // pmdcDst
  2007. pptDst, // pptDst
  2008. xSrc, // xSrc
  2009. ySrc, // ySrc
  2010. cxSrc, // cxSrc
  2011. cySrc, // cySrc
  2012. pxformSrc, // source DC transform
  2013. clrBkSrc, // source DC BkColor
  2014. pbmihSrc, // source bitmap info header
  2015. hbmSrc, // source bitmap to save
  2016. sizeof(MRPLGBLT), // offset to bitmap info
  2017. cbBitsInfoSrc, // size of bitmap info
  2018. sizeof(MRPLGBLT) + cbBitsInfoSrc,// offset to bits
  2019. cbBitsSrc, // size of bits buffer
  2020. xMask, // xMask
  2021. yMask, // yMask
  2022. pbmihMask, // mask bitmap info header
  2023. hbmMask, // mask bitmap
  2024. hbmMask // offset to mask bitmap info
  2025. ? sizeof(MRPLGBLT) + cbBitsInfoSrc + cbBitsSrc
  2026. : 0,
  2027. cbBitsInfoMask, // size of mask bitmap info
  2028. hbmMask // offset to mask bits
  2029. ? sizeof(MRPLGBLT) + cbBitsInfoSrc + cbBitsSrc + cbBitsInfoMask
  2030. : 0,
  2031. cbBitsMask // size of mask bits buffer
  2032. )
  2033. )
  2034. return(FALSE);
  2035. pmrpb->vCommit(pmdcDst);
  2036. return(TRUE);
  2037. }
  2038. // bMetaGetDIBInfo
  2039. //
  2040. // Gets the bitmap info header and sizes.
  2041. //
  2042. // If hbm or hbmRemote is given, it queries the bitmap info header and
  2043. // fills in the BITMAPINFOHERADER structure at pBmih. A hdc is required
  2044. // if iUsage is DIB_PAL_COLORS.
  2045. //
  2046. // If no hbm or hbmRemote is given, it assumes that it is called by
  2047. // SetDIBitsToDevice or StretchDIBits and pBmih already points to a
  2048. // bitmap info header (BITMAPINFOHEADER) or core header (BITMAPCOREHEADER).
  2049. //
  2050. // In any case, the size for bitmap info (BITMAPINFO) with color table
  2051. // and the size for the bitmap bits is returned in pcbBmi and pcbBits
  2052. // respectively. We do not store BITMAPCOREINFO structure in the metafiles.
  2053. //
  2054. // If cScans is non zero, only the size for the bitmap bits of this many
  2055. // scans is given. The callers in this case are SetDIBitsToDevice or
  2056. // StretchDIBits.
  2057. //
  2058. // This function is called in many places and any modifications have to
  2059. // be verified carefully! It should be kept current with the
  2060. // cjBitmapSize and cjBitmapBitsSize functions.
  2061. //
  2062. // Returns TRUE if successful, FALSE otherwise.
  2063. BOOL bMetaGetDIBInfo
  2064. (
  2065. HDC hdc,
  2066. HBITMAP hbm,
  2067. PBMIH pBmih,
  2068. PDWORD pcbBmi,
  2069. PDWORD pcbBits,
  2070. DWORD iUsage,
  2071. LONG cScans,
  2072. BOOL bMeta16
  2073. )
  2074. {
  2075. DWORD cjClr;
  2076. DWORD cbBmi;
  2077. DWORD cbBits;
  2078. PUTS("bMetaGetDIBInfo\n");
  2079. if (pBmih == NULL)
  2080. return(FALSE);
  2081. // If hbm is given, we need to get the bitmap info header.
  2082. // Otherwise, pBmih already has the bitmap info header.
  2083. if (hbm)
  2084. {
  2085. pBmih->biSize = sizeof(BMIH);
  2086. pBmih->biBitCount = 0; // don't fill in color table
  2087. pBmih->biCompression = BI_RGB;
  2088. if (!GetDIBits(hdc, hbm, 0, 0, (LPBYTE) NULL,
  2089. (LPBITMAPINFO) pBmih, (UINT) iUsage))
  2090. {
  2091. ASSERTGDI(FALSE, "bMetaGetDIBInfo: InternalGetDIBits failed");
  2092. return(FALSE);
  2093. }
  2094. // Windows always zeros the clrUsed and clrImportant fields.
  2095. // 16-bit metafiles also do not support 16/32bpp bitmaps.
  2096. if (bMeta16)
  2097. {
  2098. pBmih->biClrUsed = 0;
  2099. pBmih->biClrImportant = 0;
  2100. if (pBmih->biPlanes != 1
  2101. || pBmih->biBitCount == 16 || pBmih->biBitCount == 32)
  2102. {
  2103. pBmih->biPlanes = 1;
  2104. pBmih->biBitCount = 24;
  2105. pBmih->biCompression = BI_RGB;
  2106. pBmih->biSizeImage = 0;
  2107. iUsage = DIB_RGB_COLORS;
  2108. }
  2109. }
  2110. }
  2111. // Compute size of a color entry.
  2112. switch (iUsage)
  2113. {
  2114. case DIB_RGB_COLORS:
  2115. cjClr = sizeof(RGBQUAD);
  2116. break;
  2117. case DIB_PAL_COLORS:
  2118. cjClr = sizeof(WORD);
  2119. ASSERTGDI(sizeof(WORD) == 2, "bMetaGetDIBInfo: Bad size");
  2120. break;
  2121. case DIB_PAL_INDICES:
  2122. cjClr = 0;
  2123. break;
  2124. default:
  2125. ASSERTGDI(FALSE, "bMetaGetDIBInfo: Bad iUsage");
  2126. return(FALSE);
  2127. }
  2128. // Compute size of the bitmap info (with color table) and bitmap bits buffer.
  2129. // We will store only BITMAPINFO in the record only. The BITMAPCOREINFO
  2130. // structure will be stored as BITMAPINFO in the metafile.
  2131. if (pBmih->biSize > sizeof(BMIH))
  2132. {
  2133. cbBmi = pBmih->biSize;
  2134. }
  2135. else
  2136. {
  2137. cbBmi = sizeof(BMIH);
  2138. }
  2139. if (pBmih->biSize == sizeof(BMCH))
  2140. {
  2141. if (((LPBMCH) pBmih)->bcBitCount == 16 || ((LPBMCH) pBmih)->bcBitCount == 32)
  2142. {
  2143. ASSERTGDI(FALSE, "bMetaGetDIBInfo: 16/32bpp bitmap not allowed in core bitmap info");
  2144. return(FALSE);
  2145. }
  2146. if (((LPBMCH) pBmih)->bcBitCount < 16)
  2147. cbBmi += (1 << ((LPBMCH) pBmih)->bcBitCount) * cjClr;
  2148. cbBits = CJSCAN(((LPBMCH) pBmih)->bcWidth,
  2149. ((LPBMCH) pBmih)->bcPlanes,
  2150. ((LPBMCH) pBmih)->bcBitCount)
  2151. * (cScans ? cScans : (DWORD) ((LPBMCH) pBmih)->bcHeight);
  2152. }
  2153. else
  2154. {
  2155. if (pBmih->biBitCount == 16 || pBmih->biBitCount == 32)
  2156. {
  2157. if (pBmih->biCompression == BI_BITFIELDS)
  2158. cbBmi += 3 * sizeof(DWORD);
  2159. }
  2160. else if (pBmih->biBitCount == 24)
  2161. {
  2162. // BI_BITFIELDS not allowed
  2163. }
  2164. else if ((pBmih->biCompression == BI_JPEG) ||
  2165. (pBmih->biCompression == BI_PNG))
  2166. {
  2167. // No color table for JPEG and PNG images
  2168. }
  2169. else if (pBmih->biClrUsed)
  2170. cbBmi += pBmih->biClrUsed * cjClr;
  2171. else if (pBmih->biBitCount < 16)
  2172. cbBmi += (1 << pBmih->biBitCount) * cjClr;
  2173. // compute cbBits. We first do the computation and then use biSizeImage
  2174. // if it is smaller than cbBits.
  2175. cbBits = CJSCAN(pBmih->biWidth, pBmih->biPlanes, pBmih->biBitCount)
  2176. * (cScans ? cScans : ABS(pBmih->biHeight));
  2177. if (((pBmih->biSizeImage > 0) &&
  2178. (pBmih->biSizeImage < cbBits ||
  2179. pBmih->biCompression == BI_RLE8 ||
  2180. pBmih->biCompression == BI_RLE4)) ||
  2181. (pBmih->biCompression == BI_PNG) ||
  2182. (pBmih->biCompression == BI_JPEG))
  2183. cbBits = pBmih->biSizeImage;
  2184. }
  2185. *pcbBmi = cbBmi;
  2186. *pcbBits = cbBits;
  2187. return(TRUE);
  2188. }
  2189. // BitBlt
  2190. // PatBlt
  2191. // StretchBlt
  2192. // MaskBlt
  2193. // PlgBlt
  2194. extern "C" BOOL MF_AnyBitBlt
  2195. (
  2196. HDC hdcDst,
  2197. int xDst,
  2198. int yDst,
  2199. int cxDst,
  2200. int cyDst,
  2201. CONST POINT *pptDst,
  2202. HDC hdcSrc,
  2203. int xSrc,
  2204. int ySrc,
  2205. int cxSrc,
  2206. int cySrc,
  2207. HBITMAP hbmMask,
  2208. int xMask,
  2209. int yMask,
  2210. DWORD rop, // For MaskBlt, this is rop3!
  2211. // For PlgBlt, this must be 0xCCAA0000!
  2212. DWORD mrType
  2213. )
  2214. {
  2215. DWORD cbBitsInfoMask = 0;
  2216. DWORD cbBitsMask = 0;
  2217. BMIH bmihMask;
  2218. PBMIH pbmihMask = (PBMIH) NULL;
  2219. XFORM xformSrc;
  2220. PLDC pldc;
  2221. DC_PLDC(hdcDst,pldc,FALSE);
  2222. PMDC pmdcDst = (PMDC)pldc->pvPMDC;
  2223. ASSERTGDI(pmdcDst,"no pmdc\n");
  2224. PUTS("MF_AnyBitBlt\n");
  2225. ASSERTGDI(mrType == EMR_BITBLT
  2226. || mrType == EMR_STRETCHBLT
  2227. || mrType == EMR_MASKBLT
  2228. || mrType == EMR_PLGBLT
  2229. || mrType == EMR_ALPHABLEND
  2230. || mrType == EMR_TRANSPARENTBLT,
  2231. "MF_AnyBitBlt: Bad mrType");
  2232. // Do mask first.
  2233. if (hbmMask)
  2234. {
  2235. // Get the mask's bitmap info header and sizes.
  2236. pbmihMask = &bmihMask;
  2237. if (!bMetaGetDIBInfo(hdcDst, hbmMask, &bmihMask,
  2238. &cbBitsInfoMask, &cbBitsMask, DIB_PAL_INDICES, 0, FALSE))
  2239. return(FALSE);
  2240. // Make sure that it is monochrome.
  2241. if (bmihMask.biPlanes != 1 && bmihMask.biBitCount != 1)
  2242. return(FALSE);
  2243. }
  2244. // These two checks are needed to make sure that the following rop test works.
  2245. if ((mrType == EMR_BITBLT || mrType == EMR_STRETCHBLT)
  2246. && (rop & (0xff000000 & ~NOMIRRORBITMAP)) != 0)
  2247. {
  2248. WARNING("MF_AnyBitBlt: Bad BitBlt/StretchBlt rop");
  2249. return(FALSE);
  2250. }
  2251. ASSERTGDI(mrType != EMR_PLGBLT || rop == 0xCCAA0000,
  2252. "MF_AnyBitBlt: Bad PlgBlt rop");
  2253. // Get the source transform if a source is required by the rop.
  2254. // For MaskBlt, we always need the source transform.
  2255. if (
  2256. ISSOURCEINROP3(rop) ||
  2257. (mrType == EMR_MASKBLT) ||
  2258. (mrType == EMR_ALPHABLEND) ||
  2259. (mrType == EMR_TRANSPARENTBLT)
  2260. )
  2261. {
  2262. // Get source transform.
  2263. if (!GetTransform(hdcSrc, XFORM_WORLD_TO_DEVICE, &xformSrc))
  2264. return(FALSE);
  2265. // Make sure that it is a scale.
  2266. if (xformSrc.eM12 != 0.0f || xformSrc.eM21 != 0.0f)
  2267. return(FALSE);
  2268. // Set color page flag
  2269. SET_COLOR_PAGE(pldc);
  2270. }
  2271. // Do blts with a source. The source must allow bit query operation.
  2272. if (
  2273. ISSOURCEINROP3(rop) ||
  2274. (mrType == EMR_TRANSPARENTBLT) ||
  2275. (mrType == EMR_ALPHABLEND)
  2276. )
  2277. {
  2278. COLORREF clrBkSrc;
  2279. BOOL bRet = FALSE; // assume failure
  2280. // We need to record the source bitmap. The source DC must be a memory
  2281. // DC or a direct DC that allows bits to be retrieved. As a result, the
  2282. // source DC cannot be an enhanced metafile DC. That is, destination
  2283. // to destination blts are not allowed in an enhanced metafile!
  2284. if (IS_ALTDC_TYPE(hdcSrc))
  2285. {
  2286. PLDC pldcSrc;
  2287. DC_PLDC(hdcSrc,pldcSrc,FALSE);
  2288. if (pldcSrc->iType == LO_METADC)
  2289. return(FALSE);
  2290. }
  2291. // Get source bk color.
  2292. if ((clrBkSrc = GetNearestColor(hdcSrc, GetBkColor(hdcSrc)))
  2293. == CLR_INVALID)
  2294. {
  2295. return(FALSE);
  2296. }
  2297. // Compute the area of the source bitmap to save in the metafile.
  2298. // First we find the coordinates of the source rectange in the
  2299. // device/bitmap units. Then we expand the rectangle by one pixel
  2300. // unit to account for possible rounding errors. Finally we map
  2301. // the rectangle to the playback bitmap origin by modifying the
  2302. // translation elements in the source transform.
  2303. // Verify pdev
  2304. LONG lWidthSrc, lHeightSrc;
  2305. RECTL rclSrc;
  2306. RECTL rclBitmap;
  2307. DWORD cbBitsInfoCompat;
  2308. DWORD cbBitsCompat;
  2309. HBITMAP hbmTmp = 0;
  2310. HBITMAP hbmCompat = 0;
  2311. HDC hdcCompat = 0;
  2312. int iSaveState = 0;
  2313. BMIH bmihCompat;
  2314. // Get source rectangle in device/bitmap coordinates. Since the
  2315. // source transform is a scale, we can simply convert the endpoints
  2316. // of the source rectangle.
  2317. ASSERTGDI((mrType != EMR_BITBLT && mrType != EMR_MASKBLT)
  2318. || (cxDst == cxSrc && cyDst == cySrc),
  2319. "MF_AnyBitBlt: Bad width and height in BitBlt/MaskBlt");
  2320. ASSERTGDI(sizeof(RECTL) == sizeof(POINT)*2, "MF_AnyBitBlt: Bad size");
  2321. ((PERECTL) &rclSrc)->vInit(xSrc, ySrc, xSrc + cxSrc, ySrc + cySrc);
  2322. if (!LPtoDP(hdcSrc, (LPPOINT) &rclSrc, 2))
  2323. return(FALSE);
  2324. // Order the result. We assume it to be inclusive-inclusive.
  2325. ((PERECTL) &rclSrc)->vOrder();
  2326. // Expand it by one pixel.
  2327. rclSrc.left--;
  2328. rclSrc.top--;
  2329. rclSrc.right++;
  2330. rclSrc.bottom++;
  2331. // Map it to the playback bitmap origin.
  2332. xformSrc.eDx -= (FLOAT) rclSrc.left;
  2333. xformSrc.eDy -= (FLOAT) rclSrc.top;
  2334. // We now have the rectangle which defines the size of the playback
  2335. // bitmap. But we still need to clip it to the source device/bitmap
  2336. // limits. This is done by reducing the size of the rectangle and
  2337. // translating its origin.
  2338. ((PERECTL) &rclBitmap)->vInit
  2339. (0, 0, rclSrc.right - rclSrc.left, rclSrc.bottom - rclSrc.top);
  2340. // Get source width and height
  2341. // WINBUG #82866 2-7-2000 bhouse Investigate possible bug in MfAnyBitBlt
  2342. // Old Comment:
  2343. // - if it is a direct DC, we really want to fall through to the
  2344. // second case. Will either the GetDCObject or GetObject fail?
  2345. HBITMAP hbm = (HBITMAP)GetDCObject(hdcSrc, LO_BITMAP_TYPE);
  2346. BITMAP bmSrc;
  2347. if (hbm && GetObjectA((HANDLE)hbm,sizeof(BITMAP),(LPVOID) &bmSrc))
  2348. {
  2349. lWidthSrc = bmSrc.bmWidth;
  2350. lHeightSrc = bmSrc.bmHeight;
  2351. }
  2352. else
  2353. {
  2354. lWidthSrc = GetDeviceCaps(hdcDst, DESKTOPHORZRES);
  2355. lHeightSrc = GetDeviceCaps(hdcDst, DESKTOPVERTRES);
  2356. }
  2357. // Clip the source rectangle to the source device/bitmap limits.
  2358. // Adjust the playback bitmap size and source transform at the
  2359. // same time.
  2360. if (rclSrc.left < 0) // Shift and clip the left edge.
  2361. {
  2362. rclBitmap.right += rclSrc.left;
  2363. xformSrc.eDx += (FLOAT) rclSrc.left;
  2364. rclSrc.left = 0;
  2365. }
  2366. if (rclSrc.right >= lWidthSrc) // Clip the right edge.
  2367. {
  2368. rclBitmap.right -= (rclSrc.right - lWidthSrc + 1);
  2369. rclSrc.right -= (rclSrc.right - lWidthSrc + 1);
  2370. }
  2371. if (rclSrc.top < 0) // Shift and clip the top edge.
  2372. {
  2373. rclBitmap.bottom += rclSrc.top;
  2374. xformSrc.eDy += (FLOAT) rclSrc.top;
  2375. rclSrc.top = 0;
  2376. }
  2377. if (rclSrc.bottom >= lHeightSrc) // Clip the bottom edge.
  2378. {
  2379. rclBitmap.bottom -= (rclSrc.bottom - lHeightSrc + 1);
  2380. rclSrc.bottom -= (rclSrc.bottom - lHeightSrc + 1);
  2381. }
  2382. // If the rectangle is completely clipped, there is no playback
  2383. // bitmap and nothing to blt.
  2384. if (rclBitmap.right < 0 || rclBitmap.bottom < 0)
  2385. return(TRUE);
  2386. // We now have the size of the playback bitmap. We will create a bitmap
  2387. // compatible to the source, copy the bits to the compatible bitmap
  2388. // and finally retrieve and store the bits in the metafile record.
  2389. // Create a compatible DC.
  2390. if (!(hdcCompat = CreateCompatibleDC(hdcSrc)))
  2391. goto mfbb_src_exit;
  2392. // Create a compatible bitmap.
  2393. if (!(hbmCompat = CreateCompatibleBitmap
  2394. (
  2395. hdcSrc,
  2396. (int) rclBitmap.right + 1,
  2397. (int) rclBitmap.bottom + 1
  2398. )
  2399. )
  2400. )
  2401. goto mfbb_src_exit;
  2402. // Select the bitmap.
  2403. if (!(hbmTmp = (HBITMAP)SelectObject(hdcCompat, (HANDLE)hbmCompat)))
  2404. goto mfbb_src_exit;
  2405. // Set up the source DC to have the same identity transform as the
  2406. // compatible DC so that the following bitblt call will not scale.
  2407. if (!(iSaveState = SaveDC(hdcSrc)))
  2408. goto mfbb_src_exit;
  2409. // Must be in the advanced graphics mode to modify the world transform.
  2410. SetGraphicsMode(hdcSrc, GM_ADVANCED);
  2411. if (!SetMapMode(hdcSrc, MM_TEXT)
  2412. || !ModifyWorldTransform(hdcSrc, (LPXFORM) NULL, MWT_IDENTITY)
  2413. || !SetWindowOrgEx(hdcSrc, 0, 0, (LPPOINT) NULL)
  2414. || !SetViewportOrgEx(hdcSrc, 0, 0, (LPPOINT) NULL))
  2415. goto mfbb_src_exit;
  2416. // Copy the source bits into the compatible bitmap.
  2417. if (!BitBlt(hdcCompat, // Dest dc
  2418. 0, // Dest x
  2419. 0, // Dest y
  2420. (int) rclBitmap.right + 1, // Width
  2421. (int) rclBitmap.bottom + 1, // Height
  2422. hdcSrc, // Src dc
  2423. (int) rclSrc.left, // Src x
  2424. (int) rclSrc.top, // Src y
  2425. SRCCOPY)) // Rop
  2426. goto mfbb_src_exit;
  2427. // Retrieve the bitmap info header.
  2428. SelectObject(hdcCompat, hbmTmp);
  2429. hbmTmp = 0; // don't deselect it again later.
  2430. // Get the bitmap info header and sizes.
  2431. if (!bMetaGetDIBInfo(hdcCompat, hbmCompat, &bmihCompat,
  2432. &cbBitsInfoCompat, &cbBitsCompat, DIB_RGB_COLORS, 0, FALSE))
  2433. goto mfbb_src_exit;
  2434. // Finally create the record and get the bits.
  2435. pmdcDst->hdcSrc = hdcSrc;
  2436. switch (mrType)
  2437. {
  2438. case EMR_BITBLT:
  2439. bRet = MF_DoBitBlt
  2440. (
  2441. pmdcDst, // pmdcDst
  2442. xDst, // xDst
  2443. yDst, // yDst
  2444. cxDst, // cxDst
  2445. cyDst, // cyDst
  2446. rop, // rop
  2447. xSrc, // xSrc
  2448. ySrc, // ySrc
  2449. &xformSrc, // source DC transform
  2450. clrBkSrc, // source DC BkColor
  2451. &bmihCompat, // source bitmap info header
  2452. hbmCompat, // source bitmap to save
  2453. cbBitsInfoCompat, // size of bitmap info
  2454. cbBitsCompat // size of bits buffer
  2455. );
  2456. break;
  2457. case EMR_STRETCHBLT:
  2458. bRet = MF_DoStretchBlt
  2459. (
  2460. pmdcDst, // pmdcDst
  2461. xDst, // xDst
  2462. yDst, // yDst
  2463. cxDst, // cxDst
  2464. cyDst, // cyDst
  2465. rop, // rop
  2466. xSrc, // xSrc
  2467. ySrc, // ySrc
  2468. cxSrc, // cxSrc
  2469. cySrc, // cySrc
  2470. &xformSrc, // source DC transform
  2471. clrBkSrc, // source DC BkColor
  2472. &bmihCompat, // source bitmap info header
  2473. hbmCompat, // source bitmap to save
  2474. cbBitsInfoCompat, // size of bitmap info
  2475. cbBitsCompat // size of bits buffer
  2476. );
  2477. break;
  2478. case EMR_MASKBLT:
  2479. bRet = MF_DoMaskBlt
  2480. (
  2481. pmdcDst, // pmdcDst
  2482. xDst, // xDst
  2483. yDst, // yDst
  2484. cxDst, // cxDst
  2485. cyDst, // cyDst
  2486. rop, // rop
  2487. pbmihMask, // mask bitmap info header
  2488. hbmMask, // hbmMask
  2489. cbBitsInfoMask, // size of mask bitmap info
  2490. cbBitsMask, // size of mask bits buffer
  2491. xMask, // xMask
  2492. yMask, // yMask
  2493. xSrc, // xSrc
  2494. ySrc, // ySrc
  2495. &xformSrc, // source DC transform
  2496. clrBkSrc, // source DC BkColor
  2497. &bmihCompat, // source bitmap info header
  2498. hbmCompat, // source bitmap to save
  2499. cbBitsInfoCompat, // size of bitmap info
  2500. cbBitsCompat // size of bits buffer
  2501. );
  2502. break;
  2503. case EMR_PLGBLT:
  2504. bRet = MF_DoPlgBlt
  2505. (
  2506. pmdcDst, // pmdcDst
  2507. pptDst, // pptDst
  2508. pbmihMask, // mask bitmap info header
  2509. hbmMask, // hbmMask
  2510. cbBitsInfoMask, // size of mask bitmap info
  2511. cbBitsMask, // size of mask bits buffer
  2512. xMask, // xMask
  2513. yMask, // yMask
  2514. xSrc, // xSrc
  2515. ySrc, // ySrc
  2516. cxSrc, // cxSrc
  2517. cySrc, // cySrc
  2518. &xformSrc, // source DC transform
  2519. clrBkSrc, // source DC BkColor
  2520. &bmihCompat, // source bitmap info header
  2521. hbmCompat, // source bitmap to save
  2522. cbBitsInfoCompat, // size of bitmap info
  2523. cbBitsCompat // size of bits buffer
  2524. );
  2525. break;
  2526. case EMR_ALPHABLEND:
  2527. bRet = MF_DoAlphaBlend(
  2528. pmdcDst, // pmdcDst
  2529. xDst, // xDst
  2530. yDst, // yDst
  2531. cxDst, // cxDst
  2532. cyDst, // cyDst
  2533. rop, // rop
  2534. xSrc, // xSrc
  2535. ySrc, // ySrc
  2536. cxSrc, // cxSrc
  2537. cySrc, // cySrc
  2538. &xformSrc, // source DC transform
  2539. clrBkSrc, // source DC BkColor
  2540. &bmihCompat, // source bitmap info header
  2541. hbmCompat, // source bitmap to save
  2542. cbBitsInfoCompat, // size of bitmap info
  2543. cbBitsCompat // size of bits buffer
  2544. );
  2545. break;
  2546. case EMR_TRANSPARENTBLT:
  2547. bRet = MF_DoTransparentBlt(
  2548. pmdcDst, // pmdcDst
  2549. xDst, // xDst
  2550. yDst, // yDst
  2551. cxDst, // cxDst
  2552. cyDst, // cyDst
  2553. rop, // rop
  2554. xSrc, // xSrc
  2555. ySrc, // ySrc
  2556. cxSrc,
  2557. cySrc,
  2558. &xformSrc, // source DC transform
  2559. clrBkSrc, // source DC BkColor
  2560. &bmihCompat, // source bitmap info header
  2561. hbmCompat, // source bitmap to save
  2562. cbBitsInfoCompat, // size of bitmap info
  2563. cbBitsCompat // size of bits buffer
  2564. );
  2565. break;
  2566. }
  2567. mfbb_src_exit:
  2568. // Clean up and go home.
  2569. if (iSaveState)
  2570. {
  2571. if (!RestoreDC(hdcSrc, -1))
  2572. {
  2573. ASSERTGDI(FALSE, "MF_AnyBitBlt: RestoreDC failed");
  2574. }
  2575. }
  2576. if (hbmTmp)
  2577. {
  2578. if (!SelectObject(hdcCompat, hbmTmp))
  2579. {
  2580. ASSERTGDI(FALSE, "MF_AnyBitBlt: SelectObject failed");
  2581. }
  2582. }
  2583. if (hbmCompat)
  2584. {
  2585. if (!DeleteObject(hbmCompat))
  2586. {
  2587. ASSERTGDI(FALSE, "MF_AnyBitBlt: DeleteObject failed");
  2588. }
  2589. }
  2590. if (hdcCompat)
  2591. {
  2592. if (!DeleteDC(hdcCompat))
  2593. {
  2594. ASSERTGDI(FALSE, "MF_AnyBitBlt: DeleteDC failed");
  2595. }
  2596. }
  2597. return(bRet);
  2598. }
  2599. // It requires no source DC.
  2600. switch (mrType)
  2601. {
  2602. // StretchBlt is just a BitBlt here.
  2603. case EMR_BITBLT:
  2604. case EMR_STRETCHBLT:
  2605. return
  2606. (
  2607. MF_DoBitBlt
  2608. (
  2609. pmdcDst,
  2610. xDst,
  2611. yDst,
  2612. cxDst,
  2613. cyDst,
  2614. rop
  2615. )
  2616. );
  2617. case EMR_MASKBLT:
  2618. return
  2619. (
  2620. MF_DoMaskBlt
  2621. (
  2622. pmdcDst,
  2623. xDst,
  2624. yDst,
  2625. cxDst,
  2626. cyDst,
  2627. rop,
  2628. pbmihMask,
  2629. hbmMask,
  2630. cbBitsInfoMask,
  2631. cbBitsMask,
  2632. xMask,
  2633. yMask,
  2634. xSrc,
  2635. ySrc,
  2636. &xformSrc
  2637. )
  2638. );
  2639. // PlgBlt requires a source.
  2640. case EMR_PLGBLT:
  2641. ASSERTGDI(FALSE, "MF_AnyBitBlt: Source needed in PlgBlt");
  2642. return(FALSE);
  2643. }
  2644. return FALSE;
  2645. }
  2646. // SetDIBitsToDevice (for both 16- and 32-bit metafiles)
  2647. // StretchDIBits (for both 16- and 32-bit metafiles)
  2648. extern "C" BOOL MF_AnyDIBits
  2649. (
  2650. HDC hdcDst,
  2651. int xDst,
  2652. int yDst,
  2653. int cxDst,
  2654. int cyDst,
  2655. int xDib,
  2656. int yDib,
  2657. int cxDib,
  2658. int cyDib,
  2659. DWORD iStartScan,
  2660. DWORD cScans,
  2661. CONST VOID * pBitsDib,
  2662. CONST BITMAPINFO *pBitsInfoDib,
  2663. DWORD iUsageDib,
  2664. DWORD rop,
  2665. DWORD mrType
  2666. )
  2667. {
  2668. DWORD cbBitsInfoDib = 0;
  2669. DWORD cbBitsDib = 0;
  2670. DWORD cbProfData = 0;
  2671. VOID *pProfData = NULL;
  2672. PUTS("MF_AnyDIBits\n");
  2673. ASSERTGDI(mrType == EMR_SETDIBITSTODEVICE || mrType == EMR_STRETCHDIBITS
  2674. || mrType == META_SETDIBTODEV || mrType == META_STRETCHDIB,
  2675. "MF_AnyDIBits: Bad mrType");
  2676. ASSERTGDI(mrType == EMR_STRETCHDIBITS || mrType == META_STRETCHDIB
  2677. || rop == SRCCOPY,
  2678. "MF_AnyDIBits: Bad rop");
  2679. if (ISSOURCEINROP3(rop))
  2680. {
  2681. // Get the bitmap sizes.
  2682. // We will store only BITMAPINFO in the record only. The
  2683. // BITMAPCOREINFO structure will be converted and stored as
  2684. // BITMAPINFO in the metafile.
  2685. // If it is a SetDIBitsToDevice, cScans cannot be zero.
  2686. // If it is a StretchDIBits, cScans must be zero.
  2687. if (mrType == EMR_SETDIBITSTODEVICE || mrType == META_SETDIBTODEV)
  2688. if (!cScans)
  2689. return(FALSE);
  2690. if (!bMetaGetDIBInfo(hdcDst, (HBITMAP) 0, (PBMIH) pBitsInfoDib,
  2691. &cbBitsInfoDib, &cbBitsDib, iUsageDib, cScans, FALSE))
  2692. return(FALSE);
  2693. // If there is any attached color space data, get pointer to that.
  2694. // (only for BITMAPV5 headers.
  2695. if (pBitsInfoDib->bmiHeader.biSize == sizeof(BITMAPV5HEADER))
  2696. {
  2697. PBITMAPV5HEADER pBmih5 = (PBITMAPV5HEADER)pBitsInfoDib;
  2698. // if there is any attached profile data, count it on.
  2699. if (((pBmih5->bV5CSType == PROFILE_EMBEDDED) ||
  2700. (pBmih5->bV5CSType == PROFILE_LINKED))
  2701. &&
  2702. (pBmih5->bV5ProfileData != 0))
  2703. {
  2704. ICMMSG(("MF_AnyDIBits(): Metafiling attached color profile data\n"));
  2705. pProfData = (BYTE *)pBmih5 + pBmih5->bV5ProfileData;
  2706. cbProfData = pBmih5->bV5ProfileSize;
  2707. }
  2708. }
  2709. }
  2710. switch (mrType)
  2711. {
  2712. case EMR_SETDIBITSTODEVICE:
  2713. {
  2714. PMRSETDIBITSTODEVICE pmrsdb;
  2715. PLDC pldc;
  2716. DC_PLDC(hdcDst,pldc,FALSE);
  2717. PMDC pmdcDst = (PMDC)pldc->pvPMDC;
  2718. ASSERTGDI(pmdcDst,"no pmdc\n");
  2719. if (!(pmrsdb = (PMRSETDIBITSTODEVICE) pmdcDst->pvNewRecord
  2720. (SIZEOF_MRSETDIBITSTODEVICE(cbBitsInfoDib,cbBitsDib,cbProfData))))
  2721. return(FALSE);
  2722. pmrsdb->vInit
  2723. (
  2724. pmdcDst, // pmdcDst
  2725. (LONG) xDst, // xDst
  2726. (LONG) yDst, // yDst
  2727. (LONG) xDib, // xDib
  2728. (LONG) yDib, // yDib
  2729. (DWORD) cxDib, // cxDib
  2730. (DWORD) cyDib, // cyDib
  2731. iStartScan, // iStartScan
  2732. cScans, // cScans
  2733. cbBitsDib, // size of bits buffer
  2734. pBitsDib, // dib bits
  2735. cbBitsInfoDib, // size of bitmap info
  2736. pBitsInfoDib, // dib info
  2737. cbProfData, // size of color profile data (if BITMAPV5)
  2738. pProfData, // color profile data
  2739. iUsageDib // dib info usage
  2740. );
  2741. pmrsdb->vCommit(pmdcDst);
  2742. SET_COLOR_PAGE(pldc);
  2743. }
  2744. break;
  2745. case EMR_STRETCHDIBITS:
  2746. {
  2747. PMRSTRETCHDIBITS pmrstrdb;
  2748. PLDC pldc;
  2749. DC_PLDC(hdcDst,pldc,FALSE);
  2750. PMDC pmdcDst = (PMDC)pldc->pvPMDC;
  2751. ASSERTGDI(pmdcDst,"no pmdc\n");
  2752. if (!(pmrstrdb = (PMRSTRETCHDIBITS) pmdcDst->pvNewRecord
  2753. (SIZEOF_MRSTRETCHDIBITS(cbBitsInfoDib,cbBitsDib,cbProfData))))
  2754. return(FALSE);
  2755. pmrstrdb->vInit
  2756. (
  2757. pmdcDst, // pmdcDst
  2758. (LONG) xDst, // xDst
  2759. (LONG) yDst, // yDst
  2760. (LONG) cxDst, // cxDst
  2761. (LONG) cyDst, // cyDst
  2762. (LONG) xDib, // xDib
  2763. (LONG) yDib - iStartScan, // yDib
  2764. (LONG) cxDib, // cxDib
  2765. (LONG) cyDib, // cyDib
  2766. cScans, // cScans
  2767. cbBitsDib, // size of bits buffer
  2768. cScans ? ((PBYTE)pBitsDib) +
  2769. CJSCAN(pBitsInfoDib->bmiHeader.biWidth,pBitsInfoDib->bmiHeader.biPlanes,
  2770. pBitsInfoDib->bmiHeader.biBitCount)* iStartScan
  2771. : pBitsDib, // dib bits
  2772. cbBitsInfoDib, // size of bitmap info
  2773. pBitsInfoDib, // dib info
  2774. iUsageDib, // dib info usage
  2775. cbProfData, // size of color profile data (if BITMAPV5)
  2776. pProfData, // color profile data
  2777. rop // rop
  2778. );
  2779. pmrstrdb->vCommit(pmdcDst);
  2780. SET_COLOR_PAGE(pldc);
  2781. }
  2782. break;
  2783. case META_SETDIBTODEV:
  2784. case META_STRETCHDIB:
  2785. {
  2786. // Do not handle DIB_PAL_INDICES because there is no palette
  2787. // information available.
  2788. if (cbBitsInfoDib != 0 && iUsageDib == DIB_PAL_INDICES)
  2789. return(FALSE);
  2790. // Convert new bitmap formats to win3 bitmap formats
  2791. if (cbBitsInfoDib != 0
  2792. && (pBitsInfoDib->bmiHeader.biSize == sizeof(BMIH))
  2793. && (pBitsInfoDib->bmiHeader.biPlanes != 1
  2794. ||pBitsInfoDib->bmiHeader.biBitCount == 16
  2795. ||pBitsInfoDib->bmiHeader.biBitCount == 32))
  2796. {
  2797. BOOL b = FALSE;
  2798. HDC hdc = (HDC) 0;
  2799. HBITMAP hbm = (HBITMAP) 0;
  2800. PBYTE pBits24 = (PBYTE) NULL;
  2801. DWORD cbBits24;
  2802. BMIH bmih;
  2803. if (iUsageDib == DIB_PAL_COLORS)
  2804. return(FALSE); // illegal usage
  2805. hdc = CreateCompatibleDC((HDC) 0);
  2806. if (!(hbm = CreateDIBitmap(hdc,
  2807. (LPBITMAPINFOHEADER) pBitsInfoDib,
  2808. CBM_CREATEDIB, (LPBYTE) NULL, pBitsInfoDib, DIB_RGB_COLORS)))
  2809. goto error_exit;
  2810. if (!SetDIBits(hdc, hbm,
  2811. cScans ? (UINT) iStartScan : 0,
  2812. cScans ? (UINT) cScans : (UINT) pBitsInfoDib->bmiHeader.biHeight,
  2813. (CONST VOID *) pBitsDib, pBitsInfoDib, (UINT) iUsageDib))
  2814. goto error_exit;
  2815. bmih = *(PBITMAPINFOHEADER) pBitsInfoDib;
  2816. bmih.biPlanes = 1;
  2817. bmih.biBitCount = 24;
  2818. bmih.biCompression = BI_RGB;
  2819. bmih.biSizeImage = 0;
  2820. bmih.biClrUsed = 0;
  2821. bmih.biClrImportant = 0;
  2822. cbBits24 = CJSCAN(bmih.biWidth,bmih.biPlanes,bmih.biBitCount)
  2823. * (cScans ? cScans : ABS(bmih.biHeight));
  2824. pBits24 = (LPBYTE) LocalAlloc(LMEM_FIXED, (UINT) cbBits24);
  2825. if (pBits24 == (LPBYTE) NULL)
  2826. goto error_exit;
  2827. // Get bitmap info and bits in 24bpp.
  2828. if (!GetDIBits(hdc,
  2829. hbm,
  2830. cScans ? (UINT) iStartScan : 0,
  2831. cScans ? (UINT) cScans : (UINT) bmih.biHeight,
  2832. (LPVOID) pBits24,
  2833. (LPBITMAPINFO) &bmih,
  2834. DIB_RGB_COLORS))
  2835. goto error_exit;
  2836. b = MF16_RecordDIBits
  2837. (
  2838. hdcDst,
  2839. xDst,
  2840. yDst,
  2841. cxDst,
  2842. cyDst,
  2843. xDib,
  2844. yDib,
  2845. cxDib,
  2846. cyDib,
  2847. iStartScan,
  2848. cScans,
  2849. cbBits24,
  2850. pBits24,
  2851. sizeof(bmih),
  2852. (LPBMI) &bmih,
  2853. DIB_RGB_COLORS,
  2854. rop,
  2855. mrType
  2856. );
  2857. error_exit:
  2858. if (hdc)
  2859. DeleteDC(hdc);
  2860. if (hbm)
  2861. DeleteObject(hbm);
  2862. if (pBits24)
  2863. LocalFree((HANDLE) pBits24);
  2864. return(b);
  2865. }
  2866. else
  2867. {
  2868. return
  2869. (
  2870. MF16_RecordDIBits
  2871. (
  2872. hdcDst,
  2873. xDst,
  2874. yDst,
  2875. cxDst,
  2876. cyDst,
  2877. xDib,
  2878. yDib,
  2879. cxDib,
  2880. cyDib,
  2881. iStartScan,
  2882. cScans,
  2883. cbBitsDib,
  2884. pBitsDib,
  2885. cbBitsInfoDib,
  2886. pBitsInfoDib,
  2887. iUsageDib,
  2888. rop,
  2889. mrType
  2890. )
  2891. );
  2892. }
  2893. }
  2894. }
  2895. return(TRUE);
  2896. }
  2897. // SetFontXform
  2898. // This function is called only by the metafile playback code.
  2899. // If hdc is an enhanced metafile DC, we need to remember the scales
  2900. // so that we can metafile it in the compatible ExtTextOut or PolyTextOut
  2901. // record that follows.
  2902. extern "C" BOOL MF_SetFontXform(HDC hdc,FLOAT exScale,FLOAT eyScale)
  2903. {
  2904. PLDC pldc;
  2905. DC_PLDC(hdc,pldc,FALSE);
  2906. PMDC pmdc = (PMDC)pldc->pvPMDC;
  2907. ASSERTGDI(pmdc,"no pmdc\n");
  2908. pmdc->exFontScale(exScale);
  2909. pmdc->eyFontScale(eyScale);
  2910. return(TRUE);
  2911. }
  2912. // TextOutA
  2913. // TextOutW
  2914. // ExtTextOutA
  2915. // ExtTextOutW
  2916. extern "C" BOOL MF_ExtTextOut(
  2917. HDC hdc
  2918. , int x
  2919. , int y
  2920. , UINT fl
  2921. , CONST RECT *prcl
  2922. , LPCSTR psz
  2923. , int c
  2924. , CONST INT *pdx
  2925. , DWORD mrType
  2926. )
  2927. {
  2928. #define BUFCOUNT 256
  2929. WCHAR awc[BUFCOUNT];
  2930. WCHAR *pwsz;
  2931. PLDC pldc;
  2932. int bAlloc = 0;
  2933. BOOL bRet = TRUE;
  2934. DWORD dwCP;
  2935. INT pDxCaptureBuffer[BUFCOUNT * 2]; // just in case there is pdy
  2936. INT cSave;
  2937. PVOID pDCAttr;
  2938. switch (mrType)
  2939. {
  2940. case EMR_EXTTEXTOUTW:
  2941. pwsz = (WCHAR*) psz;
  2942. break;
  2943. case EMR_EXTTEXTOUTA:
  2944. if (c < BUFCOUNT)
  2945. {
  2946. // if the multi byte string is small enough then use
  2947. // the buffer on the frame
  2948. pwsz = awc;
  2949. }
  2950. else
  2951. {
  2952. if (!(pwsz = (WCHAR*) LOCALALLOC((c+1) * (sizeof(WCHAR)+
  2953. ((fl & ETO_PDY) ? (sizeof(INT) * 2) : sizeof(INT))))))
  2954. {
  2955. WARNING("MF_ExtTextOut: failed memory allocation\n");
  2956. return(FALSE);
  2957. }
  2958. bAlloc = 1;
  2959. }
  2960. dwCP = GetCodePage(hdc);
  2961. if(fFontAssocStatus)
  2962. {
  2963. dwCP = FontAssocHack(dwCP,(char*)psz,c);
  2964. }
  2965. cSave = c;
  2966. c = MultiByteToWideChar(dwCP, 0, psz, c, pwsz, c*sizeof(WCHAR));
  2967. break;
  2968. default:
  2969. WARNING("MF_ExtTextOut: Bad record type");
  2970. return(FALSE);
  2971. }
  2972. DC_PLDC(hdc,pldc,FALSE);
  2973. PMDC pmdc = (PMDC)pldc->pvPMDC;
  2974. ASSERTGDI(pmdc,"no pmdc\n");
  2975. PUTS("MF_ExtTextOut\n");
  2976. pldc = GET_PLDC( hdc );
  2977. if (pldc == NULL)
  2978. {
  2979. WARNING("MF_ExtTextOut: unable to retrieve pldc\n");
  2980. if (bAlloc)
  2981. {
  2982. LOCALFREE((void*) pwsz);
  2983. }
  2984. return(FALSE);
  2985. }
  2986. if( (pldc->fl & (LDC_FONT_CHANGE | LDC_FONT_SUBSET | LDC_LINKED_FONTS)) &&
  2987. (pldc->fl & (LDC_DOWNLOAD_FONTS | LDC_FORCE_MAPPING )) )
  2988. {
  2989. bDoFontChange(hdc, pwsz, c, fl);
  2990. pldc->fl &= ~LDC_FONT_CHANGE;
  2991. }
  2992. else if (!(pldc->fl & (LDC_DOWNLOAD_FONTS | LDC_FORCE_MAPPING)) && // local printing
  2993. (pldc->fl & LDC_EMBED_FONTS)) // current process has embedded fonts
  2994. {
  2995. bRecordEmbedFonts(hdc);
  2996. }
  2997. PSHARED_GET_VALIDATE(pDCAttr,hdc,DC_TYPE);
  2998. // optimization for printing. If there is no pdx array, lTextExtra, lBreakExtra and cBreak, don't record pdx
  2999. if((pldc->fl & LDC_META_PRINT) && (pdx == NULL) && ( ((PDC_ATTR)pDCAttr)->lTextExtra == 0 ) &&
  3000. ( ((PDC_ATTR)pDCAttr)->lBreakExtra == 0 ) && ( ((PDC_ATTR)pDCAttr)->cBreak == 0) )
  3001. {
  3002. PMRSMALLTEXTOUT pmrsto;
  3003. BOOL bSmallGlyphs = TRUE;
  3004. int cGlyphs;
  3005. UINT cSize;
  3006. for( cGlyphs = 0; cGlyphs < c; cGlyphs++ )
  3007. {
  3008. if( pwsz[cGlyphs] & 0xFF00 )
  3009. {
  3010. bSmallGlyphs = FALSE;
  3011. break;
  3012. }
  3013. }
  3014. cSize = sizeof(MRSMALLTEXTOUT);
  3015. cSize += c * ( ( bSmallGlyphs ) ? sizeof(char) : sizeof(WCHAR) );
  3016. cSize += ( prcl == NULL ) ? 0 : sizeof(RECT);
  3017. cSize = ( cSize + 3 ) & ~3;
  3018. if( !(pmrsto = (PMRSMALLTEXTOUT) pmdc->pvNewRecord(cSize)) )
  3019. {
  3020. bRet = FALSE;
  3021. }
  3022. else
  3023. {
  3024. pmrsto->vInit(hdc,
  3025. pmdc,
  3026. EMR_SMALLTEXTOUT,
  3027. x,
  3028. y,
  3029. fl,
  3030. (RECT*) prcl,
  3031. c,
  3032. pwsz,
  3033. bSmallGlyphs );
  3034. pmrsto->vCommit(pmdc);
  3035. }
  3036. }
  3037. else
  3038. {
  3039. PMREXTTEXTOUT pmreto;
  3040. UINT cjCh = sizeof(WCHAR);
  3041. INT *pDxCapt = (INT *)pdx;
  3042. if((mrType == EMR_EXTTEXTOUTA) && (pdx != NULL))
  3043. {
  3044. if (IS_ANY_DBCS_CODEPAGE(dwCP))
  3045. {
  3046. pDxCapt = (bAlloc) ? (INT*) &pwsz[(cSave+1)&~1] : pDxCaptureBuffer;
  3047. ConvertDxArray(dwCP,
  3048. (char*) psz,
  3049. (int*) pdx,
  3050. cSave,
  3051. pDxCapt,
  3052. (BOOL)(fl & ETO_PDY)
  3053. );
  3054. }
  3055. else
  3056. {
  3057. pDxCapt = (INT *)pdx;
  3058. }
  3059. }
  3060. if(!(pmreto=(PMREXTTEXTOUT)pmdc->pvNewRecord(SIZEOF_MREXTTEXTOUT(c,cjCh,(fl & ETO_PDY)))) ||
  3061. !pmreto->bInit(EMR_EXTTEXTOUTW,pmdc,hdc,x,y,fl,prcl,(LPCSTR)pwsz,
  3062. c,(CONST INT *)pDxCapt,cjCh))
  3063. {
  3064. bRet = FALSE;
  3065. }
  3066. else
  3067. {
  3068. pmreto->vCommit(pmdc);
  3069. }
  3070. }
  3071. if (bAlloc)
  3072. LOCALFREE((void*) pwsz);
  3073. return(bRet);
  3074. #undef BUFCOUNT
  3075. }
  3076. // PolyTextOutA
  3077. // PolyTextOutW
  3078. extern "C" BOOL MF_PolyTextOut(HDC hdc, CONST POLYTEXTA *ppta, int c, DWORD mrType)
  3079. {
  3080. DWORD mrTypeT;
  3081. BOOL b;
  3082. CONST POLYTEXTA *pptaT;
  3083. PLDC pldc;
  3084. DC_PLDC(hdc,pldc,FALSE);
  3085. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3086. ASSERTGDI(pmdc,"no pmdc\n");
  3087. PUTS("MF_PolyTextOut\n");
  3088. // [kirko] 19-Apr-94
  3089. //
  3090. // I have changed this routine to call off to MF_ExtTextOut for each member
  3091. // of the POLYTEXT? array. This is a little sleazy in that we are recording
  3092. // a different function than what was sent down by the application. On the
  3093. // other hand, it works and it is not incompatible with Chicago since they
  3094. // don't support a PolyTextOut function. You may be concerned that we are losing
  3095. // speed since we no longer call off to the spiffy fase PolyTextOut routine.
  3096. // But, if you look in GDI you will find that that PolyTextOut just calls off
  3097. // to ExtTextOut in a loop. We have just moved the loop to the Metafile recording.
  3098. // If PolyTextOut is ever made fast again, the Metafile code should then be
  3099. // modified to record those calls directly.
  3100. switch (mrType)
  3101. {
  3102. case EMR_POLYTEXTOUTA:
  3103. mrTypeT = EMR_EXTTEXTOUTA;
  3104. break;
  3105. case EMR_POLYTEXTOUTW:
  3106. mrTypeT = EMR_EXTTEXTOUTW;
  3107. break;
  3108. default:
  3109. WARNING("MF_PolyTextOut -- bad mrType");
  3110. return(FALSE);
  3111. }
  3112. for (b = TRUE, pptaT = ppta + c; ppta < pptaT && b; ppta++)
  3113. {
  3114. b = MF_ExtTextOut(hdc, ppta->x, ppta->y, ppta->uiFlags, &(ppta->rcl)
  3115. , ppta->lpstr, ppta->n, ppta->pdx, mrTypeT);
  3116. }
  3117. return(b);
  3118. }
  3119. extern "C" BOOL MF_ExtFloodFill(HDC hdc,int x,int y,COLORREF color,DWORD iMode)
  3120. {
  3121. PMREXTFLOODFILL pmreff;
  3122. PLDC pldc;
  3123. DC_PLDC(hdc,pldc,FALSE);
  3124. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3125. ASSERTGDI(pmdc,"no pmdc\n");
  3126. PUTS("MF_ExtFloodFill\n");
  3127. if (!(pmreff = (PMREXTFLOODFILL) pmdc->pvNewRecord(SIZEOF_MREXTFLOODFILL)))
  3128. return(FALSE);
  3129. pmreff->vInit(x, y, color, iMode);
  3130. pmreff->vCommit(pmdc);
  3131. return(TRUE);
  3132. }
  3133. // SetColorAdjustment
  3134. extern "C" BOOL MF_SetColorAdjustment(HDC hdc, CONST COLORADJUSTMENT *pca)
  3135. {
  3136. PMRSETCOLORADJUSTMENT pmrsca;
  3137. PLDC pldc;
  3138. DC_PLDC(hdc,pldc,FALSE);
  3139. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3140. ASSERTGDI(pmdc,"no pmdc\n");
  3141. PUTS("MF_SetColorAdjustment\n");
  3142. if (!(pmrsca = (PMRSETCOLORADJUSTMENT) pmdc->pvNewRecord(SIZEOF_MRSETCOLORADJUSTMENT(pca))))
  3143. return(FALSE);
  3144. pmrsca->vInit(pca);
  3145. pmrsca->vCommit(pmdc);
  3146. return(TRUE);
  3147. }
  3148. extern "C" BOOL MF_WriteEscape(HDC hdc, int nEscape, int nCount, LPCSTR lpInData, int type )
  3149. {
  3150. PMRESCAPE pmre;
  3151. PLDC pldc;
  3152. DC_PLDC(hdc,pldc,FALSE);
  3153. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3154. ASSERTGDI(pmdc,"no pmdc\n");
  3155. MFD2("Recording escape %d\n", nEscape );
  3156. // just in case some one (pagemaker) passes in NULL with non 0 count!
  3157. if (lpInData == NULL)
  3158. nCount = 0;
  3159. if (!(pmre = (PMRESCAPE) pmdc->pvNewRecord((sizeof(MRESCAPE)+nCount+3)&~3)))
  3160. {
  3161. WARNING("MF_WriteEscape: failed memory allocation\n");
  3162. return(FALSE);
  3163. }
  3164. pmre->vInit(type, nEscape, nCount, lpInData);
  3165. pmre->vCommit(pmdc);
  3166. if (type == EMR_DRAWESCAPE ||
  3167. nEscape == PASSTHROUGH ||
  3168. nEscape == POSTSCRIPT_DATA ||
  3169. nEscape == POSTSCRIPT_PASSTHROUGH ||
  3170. nEscape == ENCAPSULATED_POSTSCRIPT)
  3171. {
  3172. SET_COLOR_PAGE (pldc);
  3173. }
  3174. return(TRUE);
  3175. }
  3176. extern "C" BOOL MF_WriteNamedEscape(
  3177. HDC hdc,
  3178. LPWSTR pwszDriver,
  3179. int nEscape,
  3180. int nCount,
  3181. LPCSTR lpInData)
  3182. {
  3183. PMRNAMEDESCAPE pmre;
  3184. PLDC pldc;
  3185. DC_PLDC(hdc,pldc,FALSE);
  3186. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3187. ASSERTGDI(pmdc,"no pmdc\n");
  3188. MFD2("Recording named escape %d\n", nEscape );
  3189. INT cjSizeOfRecord = (sizeof(MRNAMEDESCAPE) + nCount +
  3190. ((wcslen(pwszDriver)+1) * sizeof(WCHAR)) +3)&~3;
  3191. if(!(pmre = (PMRNAMEDESCAPE) pmdc->pvNewRecord(cjSizeOfRecord)))
  3192. {
  3193. WARNING("MF_WriteEscape: failed memory allocation\n");
  3194. return(FALSE);
  3195. }
  3196. pmre->vInit(EMR_NAMEDESCAPE, nEscape, pwszDriver, lpInData, nCount);
  3197. pmre->vCommit(pmdc);
  3198. return(TRUE);
  3199. }
  3200. extern "C" BOOL MF_StartDoc(HDC hdc, CONST DOCINFOW *pDocInfo )
  3201. {
  3202. PMRSTARTDOC pmrs;
  3203. DWORD cj;
  3204. PLDC pldc;
  3205. DC_PLDC(hdc,pldc,FALSE);
  3206. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3207. ASSERTGDI(pmdc,"no pmdc\n");
  3208. MFD1( "Recording MF_StartDocW\n" );
  3209. cj = sizeof(MRSTARTDOC);
  3210. if( pDocInfo->lpszDocName != NULL )
  3211. {
  3212. cj += (lstrlenW( pDocInfo->lpszDocName ) + 1) * sizeof(WCHAR);
  3213. cj = (cj+3) & ~(0x3);
  3214. }
  3215. if( pDocInfo->lpszOutput != NULL )
  3216. {
  3217. cj += (lstrlenW( pDocInfo->lpszOutput ) + 1) * sizeof(WCHAR);
  3218. }
  3219. cj = (cj+3) & ~(0x3); // make things DWORD alligned
  3220. if (!(pmrs = (PMRSTARTDOC) pmdc->pvNewRecord( cj+40 )))
  3221. {
  3222. WARNING("MF_StartDoc: failed memory allocation\n");
  3223. return(FALSE);
  3224. }
  3225. pmrs->vInit(EMR_STARTDOC, pDocInfo);
  3226. pmrs->vCommit(pmdc);
  3227. return(TRUE);
  3228. }
  3229. extern "C" BOOL MF_ForceUFIMapping(HDC hdc, PUNIVERSAL_FONT_ID pufi )
  3230. {
  3231. PMRFORCEUFIMAPPING pmre;
  3232. PLDC pldc;
  3233. DC_PLDC(hdc,pldc,FALSE);
  3234. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3235. ASSERTGDI(pmdc,"no pmdc\n");
  3236. MFD1("Recording forced mapping\n");
  3237. if (!(pmre = (PMRFORCEUFIMAPPING) pmdc->pvNewRecord(sizeof(MRFORCEUFIMAPPING))))
  3238. {
  3239. WARNING("MF_ForceUFIMapping: failed memory allocation\n");
  3240. return(FALSE);
  3241. }
  3242. pmre->vInit(EMR_FORCEUFIMAPPING, pufi);
  3243. pmre->vCommit(pmdc);
  3244. return(TRUE);
  3245. }
  3246. extern "C" BOOL MF_SetLinkedUFIs(HDC hdc, PUNIVERSAL_FONT_ID pufi,UINT uNumLinkedUFIs )
  3247. {
  3248. PMRSETLINKEDUFIS pmre;
  3249. PLDC pldc;
  3250. DC_PLDC(hdc,pldc,FALSE);
  3251. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3252. ASSERTGDI(pmdc,"no pmdc\n");
  3253. MFD1("Recording SetLinkedUFIs\n");
  3254. UINT AllocationSize = sizeof(MRSETLINKEDUFIS) + sizeof(UNIVERSAL_FONT_ID) *
  3255. uNumLinkedUFIs;
  3256. if(!(pmre = (PMRSETLINKEDUFIS) pmdc->pvNewRecord(AllocationSize)))
  3257. {
  3258. WARNING("MF_orceUFIMapping: failed memory allocation\n");
  3259. return(FALSE);
  3260. }
  3261. pmre->vInit(uNumLinkedUFIs, pufi);
  3262. pmre->vCommit(pmdc);
  3263. return(TRUE);
  3264. }
  3265. // OpenGL metafile records
  3266. BOOL APIENTRY GdiAddGlsRecord(HDC hdc, DWORD cb, BYTE *pb, LPRECTL prclBounds)
  3267. {
  3268. PMRGLSRECORD pmrgr;
  3269. PMRGLSBOUNDEDRECORD pmrgbr;
  3270. PLDC pldc;
  3271. DC_PLDC(hdc, pldc, FALSE);
  3272. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3273. ASSERTGDI(pmdc, "no pmdc\n");
  3274. if (prclBounds == NULL)
  3275. {
  3276. pmrgr = (PMRGLSRECORD)pmdc->pvNewRecord(SIZEOF_MRGLSRECORD(cb));
  3277. if (pmrgr == NULL)
  3278. {
  3279. return FALSE;
  3280. }
  3281. pmrgr->vInit(cb, pb);
  3282. pmrgr->vCommit(pmdc);
  3283. }
  3284. else
  3285. {
  3286. pmrgbr = (PMRGLSBOUNDEDRECORD)
  3287. pmdc->pvNewRecord(SIZEOF_MRGLSBOUNDEDRECORD(cb));
  3288. if (pmrgbr == NULL)
  3289. {
  3290. return FALSE;
  3291. }
  3292. pmrgbr->vInit(cb, pb, prclBounds);
  3293. pmrgbr->vCommit(pmdc);
  3294. }
  3295. // Mark the metafile as containing OpenGL records
  3296. pmdc->mrmf.bOpenGL = TRUE;
  3297. // NTFIXED #34919(old RaidDB 423900) 02-07-2000 pravins OPENGL PRINT: Prints
  3298. // to many color printers in black an white only.
  3299. // This page can be a color.
  3300. SET_COLOR_PAGE(pldc);
  3301. return TRUE;
  3302. }
  3303. extern "C" BOOL APIENTRY GdiAddGlsBounds(HDC hdc, LPRECTL prclBounds)
  3304. {
  3305. // Bounds are given as a well-ordered rectangle in
  3306. // device coordinates
  3307. return SetBoundsRectAlt(hdc, (RECT *)prclBounds,
  3308. (UINT)(DCB_WINDOWMGR | DCB_ACCUMULATE)) != 0;
  3309. }
  3310. extern "C" BOOL APIENTRY MF_SetPixelFormat(HDC hdc,
  3311. int iPixelFormat,
  3312. CONST PIXELFORMATDESCRIPTOR *ppfd)
  3313. {
  3314. PMRPIXELFORMAT pmrpf;
  3315. PLDC pldc;
  3316. DC_PLDC(hdc, pldc, FALSE);
  3317. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3318. ASSERTGDI(pmdc, "no pmdc\n");
  3319. pmrpf = (PMRPIXELFORMAT)pmdc->pvNewRecord(SIZEOF_MRPIXELFORMAT);
  3320. if (pmrpf == NULL)
  3321. {
  3322. return FALSE;
  3323. }
  3324. pmrpf->vInit(ppfd);
  3325. pmrpf->vCommit(pmdc);
  3326. // Fix up the pixel format offset in the header
  3327. // This only allows one pixel format to be
  3328. // described in the header. This doesn't seem too bad
  3329. // but we don't really need the pixel format offset in the
  3330. // header since there should always be a pixel format record
  3331. // in the metafile (as long as a pixel format is set)
  3332. pmdc->mrmf.cbPixelFormat = sizeof(PIXELFORMATDESCRIPTOR);
  3333. pmdc->mrmf.offPixelFormat = pmdc->iMem-sizeof(MRPIXELFORMAT)+
  3334. FIELD_OFFSET(MRPIXELFORMAT, pfd);
  3335. return TRUE;
  3336. }
  3337. extern "C" BOOL APIENTRY MF_SetICMProfile(HDC hdc, LPBYTE lpFile, PVOID pvColorSpace, DWORD dwRecordType)
  3338. {
  3339. BOOL bRet = TRUE;
  3340. PMRSETICMPROFILE pmsip;
  3341. WCHAR UnicFileName[MAX_PATH];
  3342. WCHAR PathFileName[MAX_PATH+1];
  3343. PCACHED_COLORSPACE pColorSpace = (PCACHED_COLORSPACE) pvColorSpace;
  3344. PLDC pldc;
  3345. DC_PLDC(hdc,pldc,FALSE);
  3346. PUTS("MF_SetICMProfile\n");
  3347. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3348. ASSERTGDI(pmdc, "no pmdc\n");
  3349. ASSERTGDI((dwRecordType == EMR_SETICMPROFILEA) ||
  3350. (dwRecordType == EMR_SETICMPROFILEW), "Invalid Record Type\n");
  3351. CLIENT_SIDE_FILEVIEW MappedProfile;
  3352. DWORD dwFlags = 0;
  3353. DWORD dwNameLength = 0;
  3354. DWORD dwDataLength = 0;
  3355. LPBYTE lpName = NULL;
  3356. LPBYTE lpData = NULL;
  3357. #if DBG
  3358. BOOL bDownload = ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE));
  3359. #else
  3360. BOOL bDownload = (pldc->fl & LDC_DOWNLOAD_PROFILES);
  3361. #endif
  3362. if (pColorSpace)
  3363. {
  3364. ICMMSG(("MF_SetICMProfile[A|W]():Metafiling by color space\n"));
  3365. //
  3366. // Get profile name from CACHED_COLORSPACE.
  3367. //
  3368. lpName = (PBYTE)&(pColorSpace->LogColorSpace.lcsFilename[0]);
  3369. //
  3370. // Unicode record.
  3371. //
  3372. dwRecordType = EMR_SETICMPROFILEW;
  3373. }
  3374. else if (lpFile)
  3375. {
  3376. ICMMSG(("MF_SetICMProfile[A|W]():Metafiling by file name\n"));
  3377. //
  3378. // If ansi API, the lpName is ansi based string, Convert the string to Unicode.
  3379. //
  3380. if (bDownload && (dwRecordType == EMR_SETICMPROFILEA))
  3381. {
  3382. //
  3383. // Convert ANSI to Unicode.
  3384. //
  3385. vToUnicodeN(UnicFileName,MAX_PATH,(char *)lpFile,strlen((char *)lpFile)+1);
  3386. lpName = (LPBYTE) UnicFileName;
  3387. //
  3388. // And this is download, which means only EMF-spooling case comes here.
  3389. // so this record is only play back on NT. thus we are safe to convert
  3390. // record this as Unicode.
  3391. //
  3392. dwRecordType = EMR_SETICMPROFILEW;
  3393. }
  3394. else
  3395. {
  3396. lpName = lpFile;
  3397. }
  3398. }
  3399. else
  3400. {
  3401. return FALSE;
  3402. }
  3403. //
  3404. // We must have color profile (since this is destination color space).
  3405. //
  3406. if (dwRecordType == EMR_SETICMPROFILEW)
  3407. {
  3408. ICMMSG(("MF_SetICMProfileW():Metafiling - %ws\n",lpName));
  3409. if (*(WCHAR *)lpName == UNICODE_NULL)
  3410. {
  3411. ICMMSG(("MF_SetICMProfile() ANSI: no profile name is given\n"));
  3412. return FALSE;
  3413. }
  3414. }
  3415. else
  3416. {
  3417. ICMMSG(("MF_SetICMProfileA():Metafiling - %s\n",lpName));
  3418. if (*(char *)lpName == NULL)
  3419. {
  3420. ICMMSG(("MF_SetICMProfile() UNICODE: no profile name is given\n"));
  3421. return FALSE;
  3422. }
  3423. }
  3424. RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3425. if (bDownload)
  3426. {
  3427. //
  3428. // We are in profile attached mode.
  3429. //
  3430. dwFlags = SETICMPROFILE_EMBEDED;
  3431. //
  3432. // Normalize ICC profile path
  3433. //
  3434. BuildIcmProfilePath((WCHAR *)lpName, PathFileName, MAX_PATH);
  3435. //
  3436. // Check we already attached this or not.
  3437. //
  3438. if (pmdc->bExistColorProfile(PathFileName))
  3439. {
  3440. ICMMSG(("MF_SetICMProfile():Exist in metafile FileImage - %ws\n",PathFileName));
  3441. }
  3442. else
  3443. {
  3444. ICMMSG(("MF_SetICMProfile():Attaching in metafile FileImage - %ws\n",PathFileName));
  3445. if (pColorSpace && (pColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER))
  3446. {
  3447. lpData = (PBYTE)(pColorSpace->ColorProfile.pProfileData);
  3448. dwDataLength = pColorSpace->ColorProfile.cbDataSize;
  3449. }
  3450. else
  3451. {
  3452. if (!bMapFileUNICODEClideSide(PathFileName,&MappedProfile,FALSE))
  3453. {
  3454. return FALSE;
  3455. }
  3456. lpData = (PBYTE) MappedProfile.pvView;
  3457. dwDataLength = MappedProfile.cjView;
  3458. }
  3459. // Mark we attach this profile into metafile
  3460. //
  3461. pmdc->vInsertColorProfile((WCHAR *)PathFileName);
  3462. }
  3463. // WINBUG 365045 4-10-2001 pravins Possible work item in MF_SetICMProfile
  3464. //
  3465. // Old Comment:
  3466. // [THIS PART NEED TO BE RE-CONSIDERRED]
  3467. //
  3468. // Only record filename, not full path. (when we attach profile)
  3469. //
  3470. lpName = (LPBYTE) GetFileNameFromPath((WCHAR *)PathFileName);
  3471. }
  3472. if (dwRecordType == EMR_SETICMPROFILEA)
  3473. {
  3474. //
  3475. // Compute the data length (string is ansi)
  3476. //
  3477. dwNameLength = strlen((CHAR *)lpName) + 1;
  3478. }
  3479. else
  3480. {
  3481. //
  3482. // Compute the data length (string is unicode)
  3483. //
  3484. dwNameLength = (wcslen((WCHAR *)lpName) + 1) * sizeof(WCHAR);
  3485. }
  3486. pmsip = (PMRSETICMPROFILE)pmdc->pvNewRecord(SIZEOF_MRSETICMPROFILE(dwNameLength+dwDataLength));
  3487. if (pmsip == NULL)
  3488. {
  3489. bRet = FALSE;
  3490. }
  3491. else
  3492. {
  3493. pmsip->vInit(dwRecordType,dwFlags,dwNameLength,lpName,dwDataLength,lpData);
  3494. pmsip->vCommit(pmdc);
  3495. }
  3496. if (MappedProfile.hSection)
  3497. {
  3498. vUnmapFileClideSide(&MappedProfile);
  3499. }
  3500. return bRet;
  3501. }
  3502. extern "C" BOOL APIENTRY MF_ColorMatchToTarget(HDC hdc, DWORD dwAction, PVOID pvColorSpace, DWORD dwRecordType)
  3503. {
  3504. BOOL bRet = TRUE;
  3505. PMRCOLORMATCHTOTARGET pmcmt;
  3506. WCHAR PathFileName[MAX_PATH+1];
  3507. PCACHED_COLORSPACE pColorSpace = (PCACHED_COLORSPACE) pvColorSpace;
  3508. PLDC pldc;
  3509. DC_PLDC(hdc,pldc,FALSE);
  3510. PUTS("MF_ColorMatchToTarget\n");
  3511. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3512. ASSERTGDI(pmdc, "no pmdc\n");
  3513. ASSERTGDI(dwRecordType == EMR_COLORMATCHTOTARGETW, "Invalid Record Type\n");
  3514. DWORD dwFlags = 0;
  3515. DWORD dwNameLength = 0;
  3516. DWORD dwDataLength = 0;
  3517. LPBYTE lpName = NULL;
  3518. LPBYTE lpData = NULL;
  3519. CLIENT_SIDE_FILEVIEW MappedProfile;
  3520. RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3521. if (dwAction == CS_ENABLE)
  3522. {
  3523. //
  3524. // Get profile name from CACHED_COLORSPACE.
  3525. //
  3526. lpName = (PBYTE)&(pColorSpace->LogColorSpace.lcsFilename[0]);
  3527. //
  3528. // We must have color profile (since this is target color space).
  3529. //
  3530. if (*(WCHAR *)lpName == UNICODE_NULL)
  3531. {
  3532. ICMMSG(("MF_ColorMatchToTarget():no profile name in LOGCOLORSPACE\n"));
  3533. return FALSE;
  3534. }
  3535. ICMMSG(("MF_ColorMatchToTarget():Metafiling - %ws\n",lpName));
  3536. #if DBG
  3537. if ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE))
  3538. #else
  3539. if (pldc->fl & LDC_DOWNLOAD_PROFILES)
  3540. #endif
  3541. {
  3542. //
  3543. // We are in profile attached mode.
  3544. //
  3545. dwFlags = COLORMATCHTOTARGET_EMBEDED;
  3546. //
  3547. // Normalize ICC profile path
  3548. //
  3549. BuildIcmProfilePath((WCHAR *)lpName, PathFileName, MAX_PATH);
  3550. //
  3551. // Check we already attached this or not.
  3552. //
  3553. if (pmdc->bExistColorProfile((WCHAR *)PathFileName))
  3554. {
  3555. ICMMSG(("MF_ColorMatchToTarget():Exist in metafile FileImage - %ws\n",PathFileName));
  3556. }
  3557. else
  3558. {
  3559. ICMMSG(("MF_ColorMatchToTarget():Attaching in metafile FileImage - %ws\n",PathFileName));
  3560. if (pColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER)
  3561. {
  3562. lpData = (PBYTE)(pColorSpace->ColorProfile.pProfileData);
  3563. dwDataLength = pColorSpace->ColorProfile.cbDataSize;
  3564. }
  3565. else
  3566. {
  3567. if (!bMapFileUNICODEClideSide(PathFileName,&MappedProfile,FALSE))
  3568. {
  3569. return FALSE;
  3570. }
  3571. lpData = (PBYTE) MappedProfile.pvView;
  3572. dwDataLength = MappedProfile.cjView;
  3573. }
  3574. // Mark we attach this profile into metafile
  3575. //
  3576. pmdc->vInsertColorProfile((WCHAR *)PathFileName);
  3577. }
  3578. // WINBUG 365045 4-10-2001 pravins Possible work item in MF_SetICMProfile
  3579. //
  3580. // Old Comment:
  3581. // [THIS PART NEED TO BE RE-CONSIDERRED]
  3582. //
  3583. // Only record filename, not full path. (when we attach profile)
  3584. //
  3585. lpName = (LPBYTE) GetFileNameFromPath((WCHAR *)PathFileName);
  3586. }
  3587. //
  3588. // Compute the data length (string is unicode)
  3589. //
  3590. dwNameLength = (wcslen((WCHAR *)lpName) + 1) * sizeof(WCHAR);
  3591. }
  3592. else
  3593. {
  3594. ICMMSG(("MF_ColorMatchToTarget():Metafiling - %d",dwAction));
  3595. }
  3596. pmcmt = (PMRCOLORMATCHTOTARGET)pmdc->pvNewRecord(SIZEOF_MRCOLORMATCHTOTARGET(dwNameLength+dwDataLength));
  3597. if (pmcmt == NULL)
  3598. {
  3599. bRet = FALSE;
  3600. }
  3601. else
  3602. {
  3603. pmcmt->vInit(dwRecordType,dwAction,dwFlags,dwNameLength,lpName,dwDataLength,lpData);
  3604. pmcmt->vCommit(pmdc);
  3605. }
  3606. if (MappedProfile.hSection)
  3607. {
  3608. vUnmapFileClideSide(&MappedProfile);
  3609. }
  3610. return bRet;
  3611. }
  3612. extern "C" BOOL APIENTRY MF_CreateColorSpaceA(PMDC pmdc, HGDIOBJ hobj, DWORD imhe)
  3613. {
  3614. BOOL bRet = TRUE;
  3615. PMRCREATECOLORSPACE pmColorSpaceA;
  3616. PUTS("MF_CreateColorSpaceA\n");
  3617. LOGCOLORSPACEA LogColorSpaceA;
  3618. if (!GetLogColorSpaceA((HCOLORSPACE)hobj,&LogColorSpaceA,sizeof(LOGCOLORSPACEA)))
  3619. {
  3620. ICMMSG(("MF_CreateColorSpaceA():Failed on GetLogColorSpaceW()\n"));
  3621. return FALSE;
  3622. }
  3623. #if DBG
  3624. if (LogColorSpaceA.lcsFilename[0] != NULL)
  3625. {
  3626. ICMMSG(("MF_CreateColorSpaceA():Metafiling - %s\n",LogColorSpaceA.lcsFilename));
  3627. }
  3628. #endif
  3629. pmColorSpaceA = (PMRCREATECOLORSPACE) pmdc->pvNewRecord(SIZEOF_MRCREATECOLORSPACE);
  3630. if (pmColorSpaceA == NULL)
  3631. {
  3632. bRet = FALSE;
  3633. }
  3634. else
  3635. {
  3636. pmColorSpaceA->vInit((ULONG)imhe,LogColorSpaceA);
  3637. pmColorSpaceA->vCommit(pmdc);
  3638. }
  3639. return bRet;
  3640. }
  3641. extern "C" BOOL APIENTRY MF_CreateColorSpaceW(
  3642. PMDC pmdc, PLOGCOLORSPACEEXW pLogColorSpaceExW, DWORD imhe, BOOL bDownload)
  3643. {
  3644. BOOL bRet = TRUE;
  3645. PMRCREATECOLORSPACEW pmColorSpaceW;
  3646. WCHAR PathFileName[MAX_PATH];
  3647. PUTS("MF_CreateColorSpaceW\n");
  3648. DWORD dwFlags = 0;
  3649. DWORD dwDataLength = 0;
  3650. LPBYTE lpData = NULL;
  3651. CLIENT_SIDE_FILEVIEW MappedProfile;
  3652. RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3653. //
  3654. // Check LOGCOLORSPACE has color profile.
  3655. //
  3656. if (pLogColorSpaceExW->lcsColorSpace.lcsFilename[0] != NULL)
  3657. {
  3658. ICMMSG(("MF_CreateColorSpaceW():Metafiling - %ws\n",
  3659. pLogColorSpaceExW->lcsColorSpace.lcsFilename));
  3660. }
  3661. pmColorSpaceW = (PMRCREATECOLORSPACEW)pmdc->pvNewRecord(SIZEOF_MRCREATECOLORSPACEW(dwDataLength));
  3662. if (pmColorSpaceW == NULL)
  3663. {
  3664. bRet = FALSE;
  3665. }
  3666. else
  3667. {
  3668. pmColorSpaceW->vInit((ULONG)imhe,pLogColorSpaceExW->lcsColorSpace,dwFlags,dwDataLength,lpData);
  3669. pmColorSpaceW->vCommit(pmdc);
  3670. }
  3671. return bRet;
  3672. }
  3673. extern "C" BOOL APIENTRY MF_InternalCreateColorSpace(HDC hdc,HGDIOBJ hobj,DWORD imhe)
  3674. {
  3675. BOOL bRet = TRUE;
  3676. PLDC pldc;
  3677. DC_PLDC(hdc,pldc,FALSE);
  3678. PUTS("MF_InternalCreateColorSpace\n");
  3679. PMDC pmdc = (PMDC)pldc->pvPMDC;
  3680. ASSERTGDI(pmdc, "no pmdc\n");
  3681. LOGCOLORSPACEEXW LogColorSpaceExW;
  3682. //
  3683. // Obtain LOGCOLORSPACEEX from handle.
  3684. //
  3685. if (!NtGdiExtGetObjectW((HCOLORSPACE)hobj,sizeof(LOGCOLORSPACEEXW),&LogColorSpaceExW))
  3686. {
  3687. ICMMSG(("MF_InternalCreateColorSpace():Failed on NtGdiExtGetObject()\n"));
  3688. return (FALSE);
  3689. }
  3690. #if DBG
  3691. BOOL bDownload = ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE));
  3692. #else
  3693. BOOL bDownload = (pldc->fl & LDC_DOWNLOAD_PROFILES);
  3694. #endif
  3695. ICMMSG(("MF_InternalCreateColorSpace():dwFlags = %x, bDownload = %d\n",
  3696. LogColorSpaceExW.dwFlags,bDownload));
  3697. //
  3698. // If we are EMF spooling (profile attach case), or color space is created by CreateColorSpaceW(),
  3699. // use Unicode version of record to keep in metafile.
  3700. //
  3701. if ((LogColorSpaceExW.dwFlags & LCSEX_ANSICREATED) && (!bDownload))
  3702. {
  3703. //
  3704. // Create Win9x compatible ANSI record.
  3705. //
  3706. bRet = MF_CreateColorSpaceA(pmdc,hobj,imhe);
  3707. }
  3708. else
  3709. {
  3710. //
  3711. // Create Unicode record.
  3712. //
  3713. bRet = MF_CreateColorSpaceW(pmdc,&LogColorSpaceExW,imhe,bDownload);
  3714. }
  3715. return bRet;
  3716. }