Source code of Windows XP (NT5)
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.

7176 lines
188 KiB

  1. //
  2. // OE.C
  3. // Order Encoder
  4. //
  5. // Copyright(c) Microsoft 1997-
  6. //
  7. #include <as16.h>
  8. //
  9. // Define entries in the Font Alias table. This table is used to convert
  10. // non-existant fonts (used by certain widely used applications) into
  11. // something we can use as a local font.
  12. //
  13. // The font names that we alias are:
  14. //
  15. // "Helv"
  16. // This is used by Excel. It is mapped directly onto "MS Sans Serif".
  17. //
  18. // "MS Dialog"
  19. // This is used by Word. It is the same as an 8pt bold MS Sans Serif.
  20. // We actually map it to a "MS Sans Serif" font that is one pel narrower
  21. // than the metrics specify (because all matching is done on non-bold
  22. // fonts) - hence the 1 value in the charWidthAdjustment field.
  23. //
  24. // "MS Dialog Light"
  25. // Added as part of the Win95 performance enhancements...Presumably for
  26. // MS-Word...
  27. //
  28. //
  29. #define NUM_ALIAS_FONTS 3
  30. char CODESEG g_szMsSansSerif[] = "MS Sans Serif";
  31. char CODESEG g_szHelv[] = "Helv";
  32. char CODESEG g_szMsDialog[] = "MS Dialog";
  33. char CODESEG g_szMsDialogLight[] = "MS Dialog Light";
  34. FONT_ALIAS_TABLE CODESEG g_oeFontAliasTable[NUM_ALIAS_FONTS] =
  35. {
  36. { g_szHelv, g_szMsSansSerif, 0 },
  37. { g_szMsDialog, g_szMsSansSerif, 1 },
  38. { g_szMsDialogLight, g_szMsSansSerif, 0 }
  39. };
  40. //
  41. // OE_DDProcessRequest()
  42. // Handles OE escapes
  43. //
  44. BOOL OE_DDProcessRequest
  45. (
  46. UINT fnEscape,
  47. LPOSI_ESCAPE_HEADER pResult,
  48. DWORD cbResult
  49. )
  50. {
  51. BOOL rc = TRUE;
  52. DebugEntry(OE_DDProcessRequest);
  53. switch (fnEscape)
  54. {
  55. case OE_ESC_NEW_FONTS:
  56. {
  57. ASSERT(cbResult == sizeof(OE_NEW_FONTS));
  58. OEDDSetNewFonts((LPOE_NEW_FONTS)pResult);
  59. }
  60. break;
  61. case OE_ESC_NEW_CAPABILITIES:
  62. {
  63. ASSERT(cbResult == sizeof(OE_NEW_CAPABILITIES));
  64. OEDDSetNewCapabilities((LPOE_NEW_CAPABILITIES)pResult);
  65. }
  66. break;
  67. default:
  68. {
  69. ERROR_OUT(("Unrecognized OE escape"));
  70. rc = FALSE;
  71. }
  72. break;
  73. }
  74. DebugExitBOOL(OE_DDProcessRequest, rc);
  75. return(rc);
  76. }
  77. //
  78. // OE_DDInit()
  79. // This creates the patches we need.
  80. //
  81. BOOL OE_DDInit(void)
  82. {
  83. BOOL rc = FALSE;
  84. HGLOBAL hMem;
  85. UINT uSel;
  86. DDI_PATCH iPatch;
  87. DebugEntry(OE_DDInit);
  88. //
  89. // lstrcmp(), like strcmp(), works numerically for US/Eng code page.
  90. // But it's lexographic like Win32 lstrcmp() is all the time for non
  91. // US.
  92. //
  93. // So we use MyStrcmp()
  94. //
  95. ASSERT(MyStrcmp("Symbol", "SYmbol") > 0);
  96. //
  97. // Allocate a cached selector. We use it when reading from swapped-out
  98. // DCs. Therefore base it off of GDI's data segement, so it has the
  99. // same access rights and limit.
  100. //
  101. g_oeSelDst = AllocSelector((UINT)g_hInstGdi16);
  102. g_oeSelSrc = AllocSelector((UINT)g_hInstGdi16);
  103. if (!g_oeSelDst || !g_oeSelSrc)
  104. {
  105. ERROR_OUT(("Out of selectors"));
  106. DC_QUIT;
  107. }
  108. //
  109. // Allocate g_poeLocalFonts--it's too big for our DS. We make it
  110. // a very small size since on new fonts, we will realloc it.
  111. //
  112. hMem = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT | GMEM_SHARE,
  113. sizeof(LOCALFONT));
  114. if (!hMem)
  115. {
  116. ERROR_OUT(("OE_DDInit: Couldn't allocate font matching array"));
  117. DC_QUIT;
  118. }
  119. g_poeLocalFonts = MAKELP(hMem, 0);
  120. //
  121. // Create two patches for ChangeDisplaySettings/Ex and ENABLE them right
  122. // away. We don't want you to be able to change your display when
  123. // NetMeeting is running, regardless of whether you are in a share yet.
  124. //
  125. uSel = CreateFnPatch(ChangeDisplaySettings, DrvChangeDisplaySettings,
  126. &g_oeDisplaySettingsPatch, 0);
  127. if (!uSel)
  128. {
  129. ERROR_OUT(("CDS patch failed to create"));
  130. DC_QUIT;
  131. }
  132. EnableFnPatch(&g_oeDisplaySettingsPatch, PATCH_ACTIVATE);
  133. if (SELECTOROF(g_lpfnCDSEx))
  134. {
  135. if (!CreateFnPatch(g_lpfnCDSEx, DrvChangeDisplaySettingsEx,
  136. &g_oeDisplaySettingsExPatch, uSel))
  137. {
  138. ERROR_OUT(("CDSEx patch failed to create"));
  139. DC_QUIT;
  140. }
  141. EnableFnPatch(&g_oeDisplaySettingsExPatch, PATCH_ACTIVATE);
  142. }
  143. //
  144. // Create patches.
  145. // NOTE this code assumes that various groups of functions are in
  146. // the same segment. CreateFnPatch has asserts to verify this.
  147. //
  148. // Rather than check each for failure (low on selectors), we try to
  149. // create all the patches, then loop through looking for any that
  150. // didn't succeed.
  151. //
  152. // Why do we do this? Because allocating 50 different selectors is
  153. // not so hot when 16-bit selectors are the most precious resource on
  154. // Win95 (most out-of-memory conditions that aren't blatant app errors
  155. // are caused by a lack of selectors, not logical memory).
  156. //
  157. // _ARCDDA
  158. uSel = CreateFnPatch(Arc, DrvArc, &g_oeDDPatches[DDI_ARC], 0);
  159. CreateFnPatch(Chord, DrvChord, &g_oeDDPatches[DDI_CHORD], uSel);
  160. CreateFnPatch(Ellipse, DrvEllipse, &g_oeDDPatches[DDI_ELLIPSE], uSel);
  161. CreateFnPatch(Pie, DrvPie, &g_oeDDPatches[DDI_PIE], uSel);
  162. CreateFnPatch(RoundRect, DrvRoundRect, &g_oeDDPatches[DDI_ROUNDRECT], uSel);
  163. // IGROUP
  164. uSel = CreateFnPatch(BitBlt, DrvBitBlt, &g_oeDDPatches[DDI_BITBLT], 0);
  165. CreateFnPatch(ExtTextOut, DrvExtTextOutA, &g_oeDDPatches[DDI_EXTTEXTOUTA], uSel);
  166. CreateFnPatch(InvertRgn, DrvInvertRgn, &g_oeDDPatches[DDI_INVERTRGN], uSel);
  167. CreateFnPatch(DeleteObject, DrvDeleteObject, &g_oeDDPatches[DDI_DELETEOBJECT], uSel);
  168. CreateFnPatch(Death, DrvDeath, &g_oeDDPatches[DDI_DEATH], uSel);
  169. CreateFnPatch(Resurrection, DrvResurrection, &g_oeDDPatches[DDI_RESURRECTION], uSel);
  170. //
  171. // Note: PatBlt and IPatBlt (internal PatBlt) jump to RealPatBlt, which
  172. // is 3 bytes past PatBlt. So patch RealPatBlt, or we'll (1) fault with
  173. // misaligned instructions and (2) miss many PatBlt calls. But our
  174. // function needs to preserve CX since those two routines pass 0 for
  175. // internal calls (EMF) and -1 for external calls.
  176. //
  177. g_lpfnRealPatBlt = (REALPATBLTPROC)((LPBYTE)PatBlt+3);
  178. CreateFnPatch(g_lpfnRealPatBlt, DrvPatBlt, &g_oeDDPatches[DDI_PATBLT], uSel);
  179. CreateFnPatch(StretchBlt, DrvStretchBlt, &g_oeDDPatches[DDI_STRETCHBLT], uSel);
  180. CreateFnPatch(TextOut, DrvTextOutA, &g_oeDDPatches[DDI_TEXTOUTA], uSel);
  181. // _FLOODFILL
  182. uSel = CreateFnPatch(ExtFloodFill, DrvExtFloodFill, &g_oeDDPatches[DDI_EXTFLOODFILL], 0);
  183. CreateFnPatch(FloodFill, DrvFloodFill, &g_oeDDPatches[DDI_FLOODFILL], uSel);
  184. // _FONTLOAD
  185. uSel = CreateFnPatch(g_lpfnExtTextOutW, DrvExtTextOutW, &g_oeDDPatches[DDI_EXTTEXTOUTW], 0);
  186. CreateFnPatch(g_lpfnTextOutW, DrvTextOutW, &g_oeDDPatches[DDI_TEXTOUTW], uSel);
  187. // _PATH
  188. uSel = CreateFnPatch(FillPath, DrvFillPath, &g_oeDDPatches[DDI_FILLPATH], 0);
  189. CreateFnPatch(StrokeAndFillPath, DrvStrokeAndFillPath, &g_oeDDPatches[DDI_STROKEANDFILLPATH], uSel);
  190. CreateFnPatch(StrokePath, DrvStrokePath, &g_oeDDPatches[DDI_STROKEPATH], uSel);
  191. // _RGOUT
  192. uSel = CreateFnPatch(FillRgn, DrvFillRgn, &g_oeDDPatches[DDI_FILLRGN], 0);
  193. CreateFnPatch(FrameRgn, DrvFrameRgn, &g_oeDDPatches[DDI_FRAMERGN], uSel);
  194. CreateFnPatch(PaintRgn, DrvPaintRgn, &g_oeDDPatches[DDI_PAINTRGN], uSel);
  195. // _OUTMAN
  196. uSel = CreateFnPatch(LineTo, DrvLineTo, &g_oeDDPatches[DDI_LINETO], 0);
  197. CreateFnPatch(Polyline, DrvPolyline, &g_oeDDPatches[DDI_POLYLINE], uSel);
  198. CreateFnPatch(g_lpfnPolylineTo, DrvPolylineTo, &g_oeDDPatches[DDI_POLYLINETO], uSel);
  199. // EMF
  200. uSel = CreateFnPatch(PlayEnhMetaFileRecord, DrvPlayEnhMetaFileRecord, &g_oeDDPatches[DDI_PLAYENHMETAFILERECORD], 0);
  201. // METAPLAY
  202. uSel = CreateFnPatch(PlayMetaFile, DrvPlayMetaFile, &g_oeDDPatches[DDI_PLAYMETAFILE], 0);
  203. CreateFnPatch(PlayMetaFileRecord, DrvPlayMetaFileRecord, &g_oeDDPatches[DDI_PLAYMETAFILERECORD], uSel);
  204. // _POLYGON
  205. uSel = CreateFnPatch(Polygon, DrvPolygon, &g_oeDDPatches[DDI_POLYGON], 0);
  206. CreateFnPatch(PolyPolygon, DrvPolyPolygon, &g_oeDDPatches[DDI_POLYPOLYGON], uSel);
  207. // _BEZIER
  208. uSel = CreateFnPatch(PolyBezier, DrvPolyBezier, &g_oeDDPatches[DDI_POLYBEZIER], 0);
  209. CreateFnPatch(PolyBezierTo, DrvPolyBezierTo, &g_oeDDPatches[DDI_POLYBEZIERTO], uSel);
  210. // _WIN32
  211. uSel = CreateFnPatch(g_lpfnPolyPolyline, DrvPolyPolyline, &g_oeDDPatches[DDI_POLYPOLYLINE], 0);
  212. // _RECT
  213. uSel = CreateFnPatch(Rectangle, DrvRectangle, &g_oeDDPatches[DDI_RECTANGLE], 0);
  214. // _DIBITMAP
  215. uSel = CreateFnPatch(SetDIBitsToDevice, DrvSetDIBitsToDevice, &g_oeDDPatches[DDI_SETDIBITSTODEVICE], 0);
  216. CreateFnPatch(StretchDIBits, DrvStretchDIBits, &g_oeDDPatches[DDI_STRETCHDIBITS], uSel);
  217. // _DCSTUFF
  218. uSel = CreateFnPatch(CreateSpb, DrvCreateSpb, &g_oeDDPatches[DDI_CREATESPB], 0);
  219. // _PIXDDA
  220. uSel = CreateFnPatch(SetPixel, DrvSetPixel, &g_oeDDPatches[DDI_SETPIXEL], 0);
  221. // _PALETTE
  222. uSel = CreateFnPatch(UpdateColors, DrvUpdateColors, &g_oeDDPatches[DDI_UPDATECOLORS], 0);
  223. CreateFnPatch(GDIRealizePalette, DrvGDIRealizePalette, &g_oeDDPatches[DDI_GDIREALIZEPALETTE], uSel);
  224. CreateFnPatch(RealizeDefaultPalette, DrvRealizeDefaultPalette, &g_oeDDPatches[DDI_REALIZEDEFAULTPALETTE], uSel);
  225. // (User WINRARE)
  226. uSel = CreateFnPatch(WinOldAppHackoMatic, DrvWinOldAppHackoMatic, &g_oeDDPatches[DDI_WINOLDAPPHACKOMATIC], 0);
  227. //
  228. // Loop through our patches and check for failure
  229. //
  230. for (iPatch = DDI_FIRST; iPatch < DDI_MAX; iPatch++)
  231. {
  232. if (!SELECTOROF(g_oeDDPatches[iPatch].lpCodeAlias))
  233. {
  234. ERROR_OUT(("Patch %u failed to create", iPatch));
  235. DC_QUIT;
  236. }
  237. }
  238. rc = TRUE;
  239. DC_EXIT_POINT:
  240. DebugExitBOOL(OE_DDInit, rc);
  241. return(rc);
  242. }
  243. //
  244. // OE_DDTerm()
  245. // This destroys the patches we created.
  246. //
  247. void OE_DDTerm(void)
  248. {
  249. DDI_PATCH iPatch;
  250. DebugEntry(OE_DDTerm);
  251. //
  252. // Destroying patches will also disable any still active.
  253. //
  254. for (iPatch = DDI_FIRST; iPatch < DDI_MAX; iPatch++)
  255. {
  256. // destroy patches
  257. DestroyFnPatch(&g_oeDDPatches[iPatch]);
  258. }
  259. //
  260. // Destroy ChangeDisplaySettings patches
  261. //
  262. if (SELECTOROF(g_lpfnCDSEx))
  263. DestroyFnPatch(&g_oeDisplaySettingsExPatch);
  264. DestroyFnPatch(&g_oeDisplaySettingsPatch);
  265. //
  266. // Free font memory
  267. //
  268. if (SELECTOROF(g_poeLocalFonts))
  269. {
  270. GlobalFree((HGLOBAL)SELECTOROF(g_poeLocalFonts));
  271. g_poeLocalFonts = NULL;
  272. }
  273. //
  274. // Free cached selectors
  275. //
  276. if (g_oeSelSrc)
  277. {
  278. FreeSelector(g_oeSelSrc);
  279. g_oeSelSrc = 0;
  280. }
  281. if (g_oeSelDst)
  282. {
  283. FreeSelector(g_oeSelDst);
  284. g_oeSelDst = 0;
  285. }
  286. DebugExitVOID(OE_DDTerm);
  287. }
  288. //
  289. // OE_DDViewing()
  290. //
  291. // Turns on/off patches for trapping graphic output.
  292. //
  293. void OE_DDViewing(BOOL fViewers)
  294. {
  295. DDI_PATCH patch;
  296. DebugEntry(OE_DDViewing);
  297. //
  298. // Clear font caches
  299. //
  300. g_oeFhLast.fontIndex = 0xFFFF;
  301. //
  302. // Enable or disable GDI patches
  303. //
  304. for (patch = DDI_FIRST; patch < DDI_MAX; patch++)
  305. {
  306. EnableFnPatch(&g_oeDDPatches[patch], (fViewers ? PATCH_ACTIVATE :
  307. PATCH_DEACTIVATE));
  308. }
  309. //
  310. // Do save bits & cursor patches too
  311. //
  312. SSI_DDViewing(fViewers);
  313. CM_DDViewing(fViewers);
  314. if (fViewers)
  315. {
  316. //
  317. // Our palette color array starts out as all black on each share.
  318. // So force PMUpdateSystemColors() to do something.
  319. //
  320. ASSERT(g_asSharedMemory);
  321. g_asSharedMemory->pmPaletteChanged = TRUE;
  322. }
  323. DebugExitVOID(OE_DDViewing);
  324. }
  325. //
  326. // FUNCTION: OEDDSetNewCapabilities
  327. //
  328. // DESCRIPTION:
  329. //
  330. // Set the new OE related capabilities
  331. //
  332. // RETURNS:
  333. //
  334. // NONE
  335. //
  336. // PARAMETERS:
  337. //
  338. // pDataIn - pointer to the input buffer
  339. //
  340. //
  341. void OEDDSetNewCapabilities(LPOE_NEW_CAPABILITIES pCapabilities)
  342. {
  343. LPBYTE lpos16;
  344. DebugEntry(OEDDSetNewCapabilities);
  345. //
  346. // Copy the data from the Share Core.
  347. //
  348. g_oeBaselineTextEnabled = pCapabilities->baselineTextEnabled;
  349. g_oeSendOrders = pCapabilities->sendOrders;
  350. g_oeTextEnabled = pCapabilities->textEnabled;
  351. //
  352. // The share core has passed down a pointer to it's copy of the order
  353. // support array. We take a copy for the kernel here.
  354. //
  355. lpos16 = MapLS(pCapabilities->orderSupported);
  356. if (SELECTOROF(lpos16))
  357. {
  358. hmemcpy(g_oeOrderSupported, lpos16, sizeof(g_oeOrderSupported));
  359. UnMapLS(lpos16);
  360. }
  361. else
  362. {
  363. UINT i;
  364. ERROR_OUT(("OEDDSetNewCaps: can't save new order array"));
  365. for (i = 0; i < sizeof(g_oeOrderSupported); i++)
  366. g_oeOrderSupported[i] = FALSE;
  367. }
  368. TRACE_OUT(( "OE caps: BLT %c Orders %c Text %c",
  369. g_oeBaselineTextEnabled ? 'Y': 'N',
  370. g_oeSendOrders ? 'Y': 'N',
  371. g_oeTextEnabled ? 'Y': 'N'));
  372. DebugExitVOID(OEDDSetNewCapabilities);
  373. }
  374. //
  375. // FUNCTION: OEDDSetNewFonts
  376. //
  377. // DESCRIPTION:
  378. //
  379. // Set the new font handling information to be used by the display driver.
  380. //
  381. // RETURNS:
  382. //
  383. // NONE
  384. //
  385. //
  386. void OEDDSetNewFonts(LPOE_NEW_FONTS pRequest)
  387. {
  388. HGLOBAL hMem;
  389. UINT cbNewSize;
  390. LPVOID lpFontData;
  391. LPVOID lpFontIndex;
  392. DebugEntry(OEDDSetNewFonts);
  393. TRACE_OUT(( "New fonts %d", pRequest->countFonts));
  394. //
  395. // Initialize new number of fonts to zero in case an error happens.
  396. // We don't want to use stale font info if so. And clear the font
  397. // cache.
  398. //
  399. g_oeNumFonts = 0;
  400. g_oeFhLast.fontIndex = 0xFFFF;
  401. g_oeFontCaps = pRequest->fontCaps;
  402. //
  403. // Can we get 16:16 addresses for font info?
  404. //
  405. lpFontData = MapLS(pRequest->fontData);
  406. lpFontIndex = MapLS(pRequest->fontIndex);
  407. if (!lpFontData || !lpFontIndex)
  408. {
  409. ERROR_OUT(("OEDDSetNewFonts: couldn't map flat addresses to 16-bit"));
  410. DC_QUIT;
  411. }
  412. //
  413. // Realloc our current font block if we need to. Always shrink it
  414. // too, this thing can get large!
  415. //
  416. ASSERT(pRequest->countFonts <= (0xFFFF / sizeof(LOCALFONT)));
  417. cbNewSize = pRequest->countFonts * sizeof(LOCALFONT);
  418. hMem = (HGLOBAL)SELECTOROF(g_poeLocalFonts);
  419. hMem = GlobalReAlloc(hMem, cbNewSize, GMEM_MOVEABLE | GMEM_SHARE);
  420. if (!hMem)
  421. {
  422. ERROR_OUT(("OEDDSetNewFonts: can't allocate space for font info"));
  423. DC_QUIT;
  424. }
  425. else
  426. {
  427. g_poeLocalFonts = MAKELP(hMem, 0);
  428. }
  429. //
  430. // We got here, so everything is OK. Update the font info we have.
  431. //
  432. g_oeNumFonts = pRequest->countFonts;
  433. hmemcpy(g_poeLocalFonts, lpFontData, cbNewSize);
  434. hmemcpy(g_oeLocalFontIndex, lpFontIndex,
  435. sizeof(g_oeLocalFontIndex[0]) * FH_LOCAL_INDEX_SIZE);
  436. DC_EXIT_POINT:
  437. if (lpFontData)
  438. UnMapLS(lpFontData);
  439. if (lpFontIndex)
  440. UnMapLS(lpFontIndex);
  441. DebugExitVOID(OEDDSetNewFonts);
  442. }
  443. //
  444. // UTILITY ROUTINES
  445. //
  446. //
  447. // OEGetPolarity()
  448. // Gets the axes polarity signs.
  449. //
  450. // NOTE that we fill in the ptPolarity field of our OESTATE global, to
  451. // save on stack.
  452. //
  453. void OEGetPolarity(void)
  454. {
  455. SIZE WindowExtent;
  456. SIZE ViewportExtent;
  457. DebugEntry(OEGetPolarity);
  458. switch (GetMapMode(g_oeState.hdc))
  459. {
  460. case MM_ANISOTROPIC:
  461. case MM_ISOTROPIC:
  462. GetWindowExtEx(g_oeState.hdc, &WindowExtent);
  463. GetViewportExtEx(g_oeState.hdc, &ViewportExtent);
  464. if ((ViewportExtent.cx < 0) == (WindowExtent.cx < 0))
  465. g_oeState.ptPolarity.x = 1;
  466. else
  467. g_oeState.ptPolarity.x = -1;
  468. if ((ViewportExtent.cy < 0) == (WindowExtent.cy < 0))
  469. g_oeState.ptPolarity.y = 1;
  470. else
  471. g_oeState.ptPolarity.y = -1;
  472. break;
  473. case MM_HIENGLISH:
  474. case MM_HIMETRIC:
  475. case MM_LOENGLISH:
  476. case MM_LOMETRIC:
  477. case MM_TWIPS:
  478. g_oeState.ptPolarity.x = 1;
  479. g_oeState.ptPolarity.y = -1;
  480. break;
  481. default:
  482. g_oeState.ptPolarity.x = 1;
  483. g_oeState.ptPolarity.y = 1;
  484. break;
  485. }
  486. DebugExitVOID(OEGetPolarity);
  487. }
  488. //
  489. // OEGetState()
  490. // This sets up the fields in the g_oeState global, depending on what
  491. // a particular DDI needs. That is conveyed via the flags.
  492. //
  493. void OEGetState
  494. (
  495. UINT uFlags
  496. )
  497. {
  498. DWORD dwOrg;
  499. DebugEntry(OEGetState);
  500. if (uFlags & OESTATE_COORDS)
  501. {
  502. dwOrg = GetDCOrg(g_oeState.hdc);
  503. g_oeState.ptDCOrg.x = LOWORD(dwOrg);
  504. g_oeState.ptDCOrg.y = HIWORD(dwOrg);
  505. OEGetPolarity();
  506. }
  507. if (uFlags & OESTATE_PEN)
  508. {
  509. // Try to get the pen data
  510. if (!GetObject(g_oeState.lpdc->hPen, sizeof(g_oeState.logPen),
  511. &g_oeState.logPen))
  512. {
  513. ERROR_OUT(("Couldn't get pen info"));
  514. g_oeState.logPen.lopnWidth.x = 1;
  515. g_oeState.logPen.lopnWidth.y = 1;
  516. g_oeState.logPen.lopnStyle = PS_NULL;
  517. uFlags &= ~OESTATE_PEN;
  518. }
  519. }
  520. if (uFlags & OESTATE_BRUSH)
  521. {
  522. // Try to get the brush data
  523. if (!GetObject(g_oeState.lpdc->hBrush, sizeof(g_oeState.logBrush),
  524. &g_oeState.logBrush))
  525. {
  526. ERROR_OUT(("Couldn't get brush info"));
  527. g_oeState.logBrush.lbStyle = BS_NULL;
  528. uFlags &= ~OESTATE_BRUSH;
  529. }
  530. }
  531. if (uFlags & OESTATE_FONT)
  532. {
  533. // Try to get the logfont data
  534. if (!GetObject(g_oeState.lpdc->hFont, sizeof(g_oeState.logFont),
  535. &g_oeState.logFont))
  536. {
  537. ERROR_OUT(("Gouldn't get font info"));
  538. //
  539. // Fill in an empty face name
  540. //
  541. g_oeState.logFont.lfFaceName[0] = 0;
  542. uFlags &= ~OESTATE_FONT;
  543. }
  544. else
  545. {
  546. GetTextMetrics(g_oeState.hdc, &g_oeState.tmFont);
  547. g_oeState.tmAlign = GetTextAlign(g_oeState.hdc);
  548. }
  549. }
  550. if (uFlags & OESTATE_REGION)
  551. {
  552. DWORD cbSize;
  553. cbSize = GetRegionData(g_oeState.lpdc->hRaoClip,
  554. sizeof(g_oeState.rgnData), (LPRGNDATA)&g_oeState.rgnData);
  555. if (cbSize > sizeof(g_oeState.rgnData))
  556. {
  557. WARNING_OUT(("Clip region %04x is too big, unclipped drawing may result"));
  558. }
  559. if (!cbSize || (cbSize > sizeof(g_oeState.rgnData)))
  560. {
  561. // Bound box is best we can do.
  562. RECT rcBound;
  563. if (GetRgnBox(g_oeState.lpdc->hRaoClip, &rcBound) <= NULLREGION)
  564. {
  565. WARNING_OUT(("Couldn't even get bounding box of Clip region"));
  566. SetRectEmpty(&rcBound);
  567. }
  568. g_oeState.rgnData.rdh.iType = SIMPLEREGION;
  569. g_oeState.rgnData.rdh.nRgnSize = sizeof(RDH) + sizeof(RECTL);
  570. g_oeState.rgnData.rdh.nRectL = 1;
  571. RECT_TO_RECTL(&rcBound, &g_oeState.rgnData.rdh.arclBounds);
  572. RECT_TO_RECTL(&rcBound, g_oeState.rgnData.arclPieces);
  573. }
  574. }
  575. g_oeState.uFlags |= uFlags;
  576. DebugExitVOID(OEGetState);
  577. }
  578. //
  579. // OEPolarityAdjust()
  580. // This swaps the coordinates of a rectangle based on the sign polarity.
  581. //
  582. // NOTE: We use the g_oeState polarity field. So this function assumes
  583. // polarity is setup already.
  584. //
  585. void OEPolarityAdjust
  586. (
  587. LPRECT aRects,
  588. UINT cRects
  589. )
  590. {
  591. int tmp;
  592. DebugEntry(OEPolarityAdjust);
  593. ASSERT(g_oeState.uFlags & OESTATE_COORDS);
  594. while (cRects > 0)
  595. {
  596. if (g_oeState.ptPolarity.x < 0)
  597. {
  598. // Swap left & right
  599. tmp = aRects->left;
  600. aRects->left = aRects->right;
  601. aRects->right = tmp;
  602. }
  603. if (g_oeState.ptPolarity.y < 0)
  604. {
  605. // Swap top & bottom
  606. tmp = aRects->top;
  607. aRects->top = aRects->bottom;
  608. aRects->bottom = tmp;
  609. }
  610. cRects--;
  611. aRects++;
  612. }
  613. DebugExitVOID(OEPolarityAdjust);
  614. }
  615. //
  616. // OECheckOrder()
  617. // This checks for the common stuff that all the DDIs do before deciding
  618. // to send an order or accumulate screen data.
  619. //
  620. BOOL OECheckOrder
  621. (
  622. DWORD order,
  623. UINT flags
  624. )
  625. {
  626. if (!OE_SendAsOrder(order))
  627. return(FALSE);
  628. if ((flags & OECHECK_PEN) && !OECheckPenIsSimple())
  629. return(FALSE);
  630. if ((flags & OECHECK_BRUSH) && !OECheckBrushIsSimple())
  631. return(FALSE);
  632. if ((flags & OECHECK_CLIPPING) && OEClippingIsComplex())
  633. return(FALSE);
  634. return(TRUE);
  635. }
  636. //
  637. // OELPtoVirtual()
  638. // Converts coords from logical to device (pixels). This does map mode
  639. // then translation offsets.
  640. //
  641. void OELPtoVirtual
  642. (
  643. HDC hdc,
  644. LPPOINT aPts,
  645. UINT cPts
  646. )
  647. {
  648. LONG l;
  649. int s;
  650. DebugEntry(OELPtoVirtual);
  651. ASSERT(g_oeState.uFlags & OESTATE_COORDS);
  652. ASSERT(hdc == g_oeState.hdc);
  653. //
  654. // Convert to pixels
  655. //
  656. LPtoDP(hdc, aPts, cPts);
  657. //
  658. // Use the device origin, so we can convert from DC-relative to screen
  659. // coords.
  660. //
  661. while (cPts > 0)
  662. {
  663. //
  664. // Prevent overflow
  665. //
  666. l = (LONG)aPts->x + (LONG)g_oeState.ptDCOrg.x;
  667. s = (int)l;
  668. if (l == (LONG)s)
  669. {
  670. aPts->x = s;
  671. }
  672. else
  673. {
  674. //
  675. // HIWORD(l) will be 1 for positive overflow, 0xFFFF for
  676. // negative overflow. Therefore we will get 0x7FFE or 0x8000
  677. // (+32766 or -32768).
  678. //
  679. aPts->x = 0x7FFF - HIWORD(l);
  680. TRACE_OUT(("adjusted X from %ld to %d", l, aPts->x));
  681. }
  682. //
  683. // Look for int overflow in the Y coordinate
  684. //
  685. l = (LONG)aPts->y + (LONG)g_oeState.ptDCOrg.y;
  686. s = (int)l;
  687. if (l == (LONG)s)
  688. {
  689. aPts->y = s;
  690. }
  691. else
  692. {
  693. //
  694. // HIWORD(l) will be 1 for positive overflow, 0xFFFF for
  695. // negative overflow. Therefore we will get 0x7FFE or 0x8000
  696. // (+32766 or -32768).
  697. //
  698. aPts->y = 0x7FFF - HIWORD(l);
  699. TRACE_OUT(("adjusted Y from %ld to %d", l, aPts->y));
  700. }
  701. //
  702. // Move on to the next point
  703. //
  704. --cPts;
  705. ++aPts;
  706. }
  707. DebugExitVOID(OELPtoVirtual);
  708. }
  709. //
  710. // OELRtoVirtual
  711. //
  712. // Adjusts RECT in window coordinates to virtual coordinates. Clips the
  713. // result to [+32766, -32768] which is near enough to [+32767, -32768]
  714. //
  715. // NB. This function takes a Windows rectangle (Exclusive coords) and
  716. // returns a DC-Share rectangle (inclusive coords).
  717. // This means that any calling function can safely convert to inclusive
  718. // without having to worry above overflowing.
  719. //
  720. void OELRtoVirtual
  721. (
  722. HDC hdc,
  723. LPRECT aRects,
  724. UINT cRects
  725. )
  726. {
  727. int temp;
  728. DebugEntry(OELRtoVirtual);
  729. //
  730. // Convert the points to screen coords, clipping to INT16s
  731. //
  732. OELPtoVirtual(hdc, (LPPOINT)aRects, 2 * cRects);
  733. //
  734. // Make each rectangle inclusive
  735. //
  736. while (cRects > 0)
  737. {
  738. //
  739. // LAURABU BOGUS!
  740. // Use OEPolarityAdjust() instead, this is safer.
  741. //
  742. //
  743. // If the rect is bad then flip the edges. This will be the case
  744. // if the LP coordinate system is running in a different direction
  745. // than the device coordinate system.
  746. //
  747. if (aRects->left > aRects->right)
  748. {
  749. TRACE_OUT(("Flipping x coords"));
  750. temp = aRects->left;
  751. aRects->left = aRects->right;
  752. aRects->right = temp;
  753. }
  754. if (aRects->top > aRects->bottom)
  755. {
  756. TRACE_OUT(("Flipping y coords"));
  757. temp = aRects->top;
  758. aRects->top = aRects->bottom;
  759. aRects->bottom = temp;
  760. }
  761. aRects->right--;
  762. aRects->bottom--;
  763. //
  764. // Move on to the next rect
  765. //
  766. cRects--;
  767. aRects++;
  768. }
  769. DebugExitVOID(OELRtoVirtual);
  770. }
  771. //
  772. // OE_SendAsOrder()
  773. //
  774. BOOL OE_SendAsOrder(DWORD order)
  775. {
  776. BOOL rc = FALSE;
  777. DebugEntry(OE_SendAsOrder);
  778. //
  779. // Only check the order if we are allowed to send orders in the first
  780. // place!
  781. //
  782. if (g_oeSendOrders)
  783. {
  784. TRACE_OUT(("Orders enabled"));
  785. //
  786. // We are sending some orders, so check individual flags.
  787. //
  788. rc = (BOOL)g_oeOrderSupported[HIWORD(order)];
  789. TRACE_OUT(("Send order %lx HIWORD %u", order, HIWORD(order)));
  790. }
  791. DebugExitDWORD(OE_SendAsOrder, rc);
  792. return(rc);
  793. }
  794. //
  795. // FUNCTION: OESendRop3AsOrder.
  796. //
  797. // DESCRIPTION:
  798. //
  799. // Checks to see if the rop uses the destination bits. If it does then
  800. // returns FALSE unless the "send all rops" property flag is set.
  801. //
  802. // PARAMETERS: The rop3 to be checked (in protocol format ie a byte).
  803. //
  804. // RETURNS: TRUE if the rop3 should be sent as an order.
  805. //
  806. //
  807. BOOL OESendRop3AsOrder(BYTE rop3)
  808. {
  809. BOOL rc = TRUE;
  810. DebugEntry(OESendRop3AsOrder);
  811. //
  812. // Rop 0x5F is used by MSDN to highlight search keywords. This XORs
  813. // a pattern with the destination, producing markedly different (and
  814. // sometimes unreadable) shadow output. We special-case no-encoding for
  815. // it.
  816. //
  817. if (rop3 == 0x5F)
  818. {
  819. WARNING_OUT(("Rop3 0x5F never encoded"));
  820. rc = FALSE;
  821. }
  822. DebugExitBOOL(OESendRop3AsOrder, rc);
  823. return(rc);
  824. }
  825. //
  826. // OEPenWidthAdjust()
  827. //
  828. // Adjusts a rectangle to allow for the current pen width divided by
  829. // the divisor, rounding up.
  830. //
  831. // NOTE: This routine uses the logPen and ptPolarity fields of g_oeState.
  832. //
  833. void OEPenWidthAdjust
  834. (
  835. LPRECT lprc,
  836. UINT divisor
  837. )
  838. {
  839. UINT width;
  840. UINT roundingFactor = divisor - 1;
  841. DebugEntry(OEPenWidthAdjust);
  842. width = max(g_oeState.logPen.lopnWidth.x, g_oeState.logPen.lopnWidth.y);
  843. InflateRect(lprc,
  844. ((g_oeState.ptPolarity.x * width) +
  845. (g_oeState.ptPolarity.x * roundingFactor)) / divisor,
  846. ((g_oeState.ptPolarity.y * width) +
  847. (g_oeState.ptPolarity.x * roundingFactor)) / divisor);
  848. DebugExitVOID(OEPenWidthAdjust);
  849. }
  850. //
  851. // Function: OEExpandColor
  852. //
  853. // Description: Converts a generic bitwise representation of an RGB color
  854. // index into an 8-bit color index as used by the line
  855. // protocol.
  856. //
  857. void OEExpandColor
  858. (
  859. LPBYTE lpField,
  860. DWORD srcColor,
  861. DWORD mask
  862. )
  863. {
  864. DWORD colorTmp;
  865. DebugEntry(OEExpandColor);
  866. //
  867. // Different example bit masks:
  868. //
  869. // Normal 24-bit:
  870. // 0x000000FF (red)
  871. // 0x0000FF00 (green)
  872. // 0x00FF0000 (blue)
  873. //
  874. // True color 32-bits:
  875. // 0xFF000000 (red)
  876. // 0x00FF0000 (green)
  877. // 0x0000FF00 (blue)
  878. //
  879. // 5-5-5 16-bits
  880. // 0x0000001F (red)
  881. // 0x000003E0 (green)
  882. // 0x00007C00 (blue)
  883. //
  884. // 5-6-5 16-bits
  885. // 0x0000001F (red)
  886. // 0x000007E0 (green)
  887. // 0x0000F800 (blue)
  888. //
  889. //
  890. // Convert the color using the following algorithm.
  891. //
  892. // <new color> = <old color> * <new bpp mask> / <old bpp mask>
  893. //
  894. // where:
  895. //
  896. // new bpp mask = mask for all bits at new setting (0xFF for 8bpp)
  897. //
  898. // This way maximal (eg. 0x1F) and minimal (eg. 0x00) settings are
  899. // converted into the correct 8-bit maximum and minimum.
  900. //
  901. // Rearranging the above equation we get:
  902. //
  903. // <new color> = (<old color> & <old bpp mask>) * 0xFF / <old bpp mask>
  904. //
  905. // where:
  906. //
  907. // <old bpp mask> = mask for the color
  908. //
  909. //
  910. // LAURABU BOGUS:
  911. // We need to avoid overflow caused by the multiply. NOTE: in theory
  912. // we should use a double, but that's painfully slow. So for now hack
  913. // it. If the HIBYTE is set, just right shift 24 bits.
  914. //
  915. colorTmp = srcColor & mask;
  916. if (colorTmp & 0xFF000000)
  917. colorTmp >>= 24;
  918. else
  919. colorTmp = (colorTmp * 0xFF) / mask;
  920. *lpField = (BYTE)colorTmp;
  921. TRACE_OUT(( "0x%lX -> 0x%X", srcColor, (WORD)*lpField));
  922. DebugExitVOID(OEExpandColor);
  923. }
  924. //
  925. // OEConvertColor()
  926. // Converts a PHYSICAL color to a real RGB
  927. //
  928. void OEConvertColor
  929. (
  930. DWORD rgb,
  931. LPTSHR_COLOR lptshrDst,
  932. BOOL fAllowDither
  933. )
  934. {
  935. DWORD rgbConverted;
  936. PALETTEENTRY pe;
  937. int pal;
  938. DWORD numColors;
  939. DebugEntry(OEConvertColor);
  940. rgbConverted = rgb;
  941. //
  942. // Get the current palette size.
  943. //
  944. GetObject(g_oeState.lpdc->hPal, sizeof(pal), &pal);
  945. if (pal == 0)
  946. {
  947. //
  948. // GDI has a bug. It allows a ResizePalette() call to set a new
  949. // size of zero for the palette. If you subsequently make
  950. // certain palette manager calls on such a palette, GDI will fault.
  951. //
  952. // To avoid this problem, as seen in 3D Kitchen by Books that Work,
  953. // we check for this case and simply return the input color.
  954. //
  955. WARNING_OUT(("Zero-sized palette"));
  956. DC_QUIT;
  957. }
  958. if (g_oeState.lpdc->hPal == g_oeStockPalette)
  959. {
  960. //
  961. // Quattro Pro and others put junk in the high bits of their colors.
  962. // We need to mask it out.
  963. //
  964. if (rgb & 0xFC000000)
  965. {
  966. rgb &= 0x00FFFFFF;
  967. }
  968. else
  969. {
  970. if (rgb & PALETTERGB_FLAG)
  971. {
  972. //
  973. // Using PALETTERGB is just like using an RGB, turn it off.
  974. // The color will be dithered, if necessary, using the
  975. // default system colors.
  976. //
  977. rgb &= 0x01FFFFFF;
  978. }
  979. }
  980. }
  981. if (rgb & COLOR_FLAGS)
  982. {
  983. if (rgb & PALETTERGB_FLAG)
  984. {
  985. pal = GetNearestPaletteIndex(g_oeState.lpdc->hPal, rgb);
  986. }
  987. else
  988. {
  989. ASSERT(rgb & PALETTEINDEX_FLAG);
  990. pal = LOWORD(rgb);
  991. }
  992. //
  993. // Look up entry in palette.
  994. //
  995. if (!GetPaletteEntries(g_oeState.lpdc->hPal, pal, 1, &pe))
  996. {
  997. ERROR_OUT(("GetPaletteEntries failed for index %d", pal));
  998. *((LPDWORD)&pe) = 0L;
  999. }
  1000. else if (pe.peFlags & PC_EXPLICIT)
  1001. {
  1002. //
  1003. // If this is PC_EXPLICIT, it's an index into the system
  1004. // palette.
  1005. //
  1006. pal = LOWORD(*((LPDWORD)&pe));
  1007. if (g_osiScreenBPP < 32)
  1008. {
  1009. numColors = 1L << g_osiScreenBPP;
  1010. }
  1011. else
  1012. {
  1013. numColors = 0xFFFFFFFF;
  1014. }
  1015. if (numColors > 256)
  1016. {
  1017. //
  1018. // We are on a direct color device. What does explicit
  1019. // mean in this case? The answer is, use the VGA color
  1020. // palette.
  1021. //
  1022. pe = g_osiVgaPalette[pal % 16];
  1023. }
  1024. else
  1025. {
  1026. pal %= numColors;
  1027. GetSystemPaletteEntries(g_oeState.hdc, pal, 1, &pe);
  1028. }
  1029. }
  1030. rgbConverted = *((LPDWORD)&pe);
  1031. }
  1032. DC_EXIT_POINT:
  1033. //
  1034. // To get the correct results for any RGBs we send to true color systems,
  1035. // we need to normalize the RGB to an exact palette match on the local
  1036. // system. This is because we aren't guaranteed that the RGB on the
  1037. // local will have an exact match to the current system palette. If
  1038. // not, then GDI will convert them locally, but the orders will send
  1039. // to remotes will be displayed exactly, resulting in a mismatch.
  1040. //
  1041. if ((g_osiScreenBPP == 8) &&
  1042. !(rgb & COLOR_FLAGS) &&
  1043. (!fAllowDither || (g_oeState.lpdc->hPal != g_oeStockPalette)))
  1044. {
  1045. TSHR_RGBQUAD rgq;
  1046. rgbConverted &= 0x00FFFFFF;
  1047. //
  1048. // Common cases.
  1049. //
  1050. if ((rgbConverted == RGB(0, 0, 0)) ||
  1051. (rgbConverted == RGB(0xFF, 0xFF, 0xFF)))
  1052. {
  1053. goto ReallyConverted;
  1054. }
  1055. //
  1056. // g_osiScreenBMI.bmiHeader is already filled in.
  1057. //
  1058. //
  1059. // NOTE:
  1060. // We don't need or want to realize any palettes. We want color
  1061. // mapping based on the current screen palette contents.
  1062. //
  1063. // We disable SetPixel() patch, or our trap will trash the
  1064. // variables for this call.
  1065. //
  1066. //
  1067. // g_osiMemoryDC() always has our 1x1 color bitmap g_osiMemoryBMP
  1068. // selected into it.
  1069. //
  1070. EnableFnPatch(&g_oeDDPatches[DDI_SETPIXEL], PATCH_DISABLE);
  1071. SetPixel(g_osiMemoryDC, 0, 0, rgbConverted);
  1072. EnableFnPatch(&g_oeDDPatches[DDI_SETPIXEL], PATCH_ENABLE);
  1073. //
  1074. // Get mapped color index
  1075. //
  1076. GetDIBits(g_osiMemoryDC, g_osiMemoryBMP, 0, 1, &pal,
  1077. (LPBITMAPINFO)&g_osiScreenBMI, DIB_RGB_COLORS);
  1078. rgq = g_osiScreenBMI.bmiColors[LOBYTE(pal)];
  1079. OTRACE(("Mapped color %08lx to %08lx", rgbConverted,
  1080. RGB(rgq.rgbRed, rgq.rgbGreen, rgq.rgbBlue)));
  1081. rgbConverted = RGB(rgq.rgbRed, rgq.rgbGreen, rgq.rgbBlue);
  1082. }
  1083. ReallyConverted:
  1084. lptshrDst->red = GetRValue(rgbConverted);
  1085. lptshrDst->green = GetGValue(rgbConverted);
  1086. lptshrDst->blue = GetBValue(rgbConverted);
  1087. DebugExitVOID(OEConvertColor);
  1088. }
  1089. //
  1090. // OEGetBrushInfo()
  1091. // Standard brush goop
  1092. //
  1093. void OEGetBrushInfo
  1094. (
  1095. LPTSHR_COLOR pBack,
  1096. LPTSHR_COLOR pFore,
  1097. LPTSHR_UINT32 pStyle,
  1098. LPTSHR_UINT32 pHatch,
  1099. LPBYTE pExtra
  1100. )
  1101. {
  1102. int iRow;
  1103. DebugEntry(OEGetBrushInfo);
  1104. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL, pBack, FALSE);
  1105. *pStyle = g_oeState.logBrush.lbStyle;
  1106. if (g_oeState.logBrush.lbStyle == BS_PATTERN)
  1107. {
  1108. //
  1109. // We only track mono patterns, so the foreground color is the
  1110. // brush color.
  1111. //
  1112. OEConvertColor(g_oeState.lpdc->DrawMode.txColorL, pFore, FALSE);
  1113. // For pattern brushes, the hatch stores the 1st pattern byte,
  1114. // the Extra field the remaining 7 pattern bytes
  1115. *pHatch = g_oeState.logBrushExtra[0];
  1116. hmemcpy(pExtra, g_oeState.logBrushExtra+1, TRACKED_BRUSH_SIZE-1);
  1117. }
  1118. else
  1119. {
  1120. ASSERT(g_oeState.logBrush.lbStyle != BS_DIBPATTERN);
  1121. OEConvertColor(g_oeState.logBrush.lbColor, pFore, TRUE);
  1122. // The hatch is the hatch style
  1123. *pHatch = g_oeState.logBrush.lbHatch;
  1124. // Extra info is empty
  1125. for (iRow = 0; iRow < TRACKED_BRUSH_SIZE-1; iRow++)
  1126. {
  1127. pExtra[iRow] = 0;
  1128. }
  1129. }
  1130. DebugExitVOID(OEGetBrushInfo);
  1131. }
  1132. //
  1133. // OEClippingIsSimple()
  1134. //
  1135. BOOL OEClippingIsSimple(void)
  1136. {
  1137. BOOL fSimple;
  1138. RECT rc;
  1139. DebugEntry(OEClippingIsSimple);
  1140. ASSERT(g_oeState.uFlags & OESTATE_REGION);
  1141. fSimple = (g_oeState.rgnData.rdh.nRectL <= 1);
  1142. DebugExitBOOL(OEClippingIsSimple, fSimple);
  1143. return(fSimple);
  1144. }
  1145. //
  1146. // OEClippingIsComplex()
  1147. //
  1148. BOOL OEClippingIsComplex(void)
  1149. {
  1150. BOOL fComplex;
  1151. DebugEntry(OEClippingIsComplex);
  1152. ASSERT(g_oeState.uFlags & OESTATE_REGION);
  1153. fComplex = (g_oeState.rgnData.rdh.nRgnSize >=
  1154. sizeof(RDH) + CRECTS_COMPLEX*sizeof(RECTL));
  1155. DebugExitBOOL(OEClippingIsComplex, fComplex);
  1156. return(fComplex);
  1157. }
  1158. //
  1159. // OECheckPenIsSimple()
  1160. //
  1161. BOOL OECheckPenIsSimple(void)
  1162. {
  1163. POINT ptArr[2];
  1164. BOOL fSimple;
  1165. DebugEntry(OECheckPenIsSimple);
  1166. if (g_oeState.uFlags & OESTATE_PEN)
  1167. {
  1168. ptArr[0].x = ptArr[0].y = 0;
  1169. ptArr[1].x = g_oeState.logPen.lopnWidth.x;
  1170. ptArr[1].y = 0;
  1171. LPtoDP(g_oeState.hdc, ptArr, 2);
  1172. fSimple = ((ptArr[1].x - ptArr[0].x) <= 1);
  1173. }
  1174. else
  1175. {
  1176. // The current pen in the DC is invalid
  1177. WARNING_OUT(("Invalid pen selected into DC"));
  1178. fSimple = FALSE;
  1179. }
  1180. DebugExitBOOL(OECheckPenIsSimple, fSimple);
  1181. return(fSimple);
  1182. }
  1183. //
  1184. // OECheckBrushIsSimple()
  1185. //
  1186. BOOL OECheckBrushIsSimple(void)
  1187. {
  1188. BOOL fSimple;
  1189. DebugEntry(OECheckBrushIsSimple);
  1190. // Assume not simple
  1191. fSimple = FALSE;
  1192. if (g_oeState.uFlags & OESTATE_BRUSH)
  1193. {
  1194. //
  1195. // If the brush is a pattern, it's OK if one of standard pattern
  1196. // brushes. If it comes from a DIB, it's never OK. All other
  1197. // brushes are OK.
  1198. //
  1199. if (g_oeState.logBrush.lbStyle == BS_PATTERN)
  1200. {
  1201. LPGDIHANDLE lpgh;
  1202. LPBRUSH lpBrush;
  1203. LPBITMAP lpPattern;
  1204. //
  1205. // For pattern brushes, the lbHatch field of the ilBrushOverhead
  1206. // item in the GDI local BRUSH object is a global handle to
  1207. // a memory block that is the BITMAP of the thing.
  1208. //
  1209. //
  1210. // BOGUS LAURABU:
  1211. // NM 2.0 Win95 went to a lot more work to check if a color bitmap
  1212. // pattern brush had only 2 colors and therefore was orderable. But
  1213. // I can't find a single that uses such a thing. So for now, we just
  1214. // care if the pattern bitmap is monochrome and the pattern is between 8x8 and
  1215. // 16x8.
  1216. //
  1217. // Get a pointer to the brush data
  1218. lpgh = MAKELP(g_hInstGdi16, g_oeState.lpdc->hBrush);
  1219. ASSERT(!IsBadReadPtr(lpgh, sizeof(DWORD)));
  1220. ASSERT(!(lpgh->objFlags & OBJFLAGS_SWAPPEDOUT));
  1221. lpBrush = MAKELP(g_hInstGdi16, lpgh->pGdiObj);
  1222. ASSERT(!IsBadReadPtr(lpBrush, sizeof(BRUSH)));
  1223. // Get the bitmapinfo handle -- it's the lbHatch field
  1224. lpPattern = MAKELP(lpBrush->ilBrushOverhead.lbHatch, 0);
  1225. //
  1226. // Macromedia Director among others creates pattern brushes
  1227. // with no pattern. We therefore consider these objects to
  1228. // be too complex to send in an order
  1229. //
  1230. //
  1231. // Is this monochrome with a pattern between 8 and 16 pels?
  1232. // We save the left 8 pixel grid if so.
  1233. //
  1234. if (!IsBadReadPtr(lpPattern, sizeof(BITMAP)) &&
  1235. (lpPattern->bmWidth >= MIN_BRUSH_WIDTH) &&
  1236. (lpPattern->bmWidth <= MAX_BRUSH_WIDTH) &&
  1237. (lpPattern->bmHeight == TRACKED_BRUSH_HEIGHT) &&
  1238. (lpPattern->bmPlanes == 1) && (lpPattern->bmBitsPixel == 1))
  1239. {
  1240. LPUINT lpRow;
  1241. int iRow;
  1242. // Save the pattern away in logBrushExtra
  1243. lpRow = lpPattern->bmBits;
  1244. ASSERT(!IsBadReadPtr(lpRow, TRACKED_BRUSH_HEIGHT*sizeof(UINT)));
  1245. //
  1246. // The pattern is always WORD aligned. But only the
  1247. // LOBYTE has meaning.
  1248. //
  1249. // NOTE:
  1250. // We fill the pattern in DIB order, namely bottom to
  1251. // top.
  1252. //
  1253. ASSERT(lpPattern->bmWidthBytes == 2);
  1254. for (iRow = 0; iRow < TRACKED_BRUSH_HEIGHT; iRow++, lpRow++)
  1255. {
  1256. g_oeState.logBrushExtra[TRACKED_BRUSH_HEIGHT - 1 - iRow] =
  1257. (BYTE)*lpRow;
  1258. }
  1259. fSimple = TRUE;
  1260. }
  1261. }
  1262. else if (g_oeState.logBrush.lbStyle != BS_DIBPATTERN)
  1263. {
  1264. fSimple = TRUE;
  1265. }
  1266. }
  1267. else
  1268. {
  1269. WARNING_OUT(("Invalid brush selected into DC"));
  1270. }
  1271. DebugExitBOOL(OECheckBrushIsSimple, fSimple);
  1272. return(fSimple);
  1273. }
  1274. //
  1275. // OEAddLine()
  1276. // This calculates the bounds of a line output call, and either adds an
  1277. // order or gets set for screen data accum.
  1278. //
  1279. void OEAddLine
  1280. (
  1281. POINT ptStart,
  1282. POINT ptEnd
  1283. )
  1284. {
  1285. LPINT_ORDER pOrder;
  1286. LPLINETO_ORDER pLineTo;
  1287. DebugEntry(OEAddLine);
  1288. //
  1289. // Get the bounds
  1290. //
  1291. g_oeState.rc.left = min(ptStart.x, ptEnd.x);
  1292. g_oeState.rc.top = min(ptStart.y, ptEnd.y);
  1293. g_oeState.rc.right = max(ptStart.x, ptEnd.x);
  1294. g_oeState.rc.bottom = max(ptStart.y, ptEnd.y);
  1295. //
  1296. // Adjust for axes polarity and pen dimensions
  1297. //
  1298. ASSERT(g_oeState.uFlags & OESTATE_COORDS);
  1299. OEPolarityAdjust(&g_oeState.rc, 1);
  1300. OEPenWidthAdjust(&g_oeState.rc, 1);
  1301. //
  1302. // OEPenWidthAdjust returns an inclusive rect. But OELRtoVirtual
  1303. // expects an exclusive. After it returns, we need to add back
  1304. // the extra subtraction.
  1305. //
  1306. // NOTE that OELRtoVirtual also adjusts for virtual desktop origin.
  1307. //
  1308. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  1309. g_oeState.rc.right++;
  1310. g_oeState.rc.bottom++;
  1311. //
  1312. // Now we have the true draw bounds. Can we send this as an order?
  1313. //
  1314. pOrder = NULL;
  1315. if (OECheckOrder(ORD_LINETO, OECHECK_PEN | OECHECK_CLIPPING))
  1316. {
  1317. //
  1318. // We can send an order.
  1319. //
  1320. pOrder = OA_DDAllocOrderMem(sizeof(LINETO_ORDER), 0);
  1321. if (!pOrder)
  1322. DC_QUIT;
  1323. pLineTo = (LPLINETO_ORDER)pOrder->abOrderData;
  1324. pLineTo->type = LOWORD(ORD_LINETO);
  1325. //
  1326. // Must do this first: oords in the LINETO order are 32-bit
  1327. //
  1328. OELPtoVirtual(g_oeState.hdc, &ptStart, 1);
  1329. OELPtoVirtual(g_oeState.hdc, &ptEnd, 1);
  1330. pLineTo->nXStart = ptStart.x;
  1331. pLineTo->nYStart = ptStart.y;
  1332. pLineTo->nXEnd = ptEnd.x;
  1333. pLineTo->nYEnd = ptEnd.y;
  1334. //
  1335. // This is a physical color
  1336. //
  1337. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL,
  1338. &pLineTo->BackColor, FALSE);
  1339. pLineTo->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  1340. pLineTo->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  1341. pLineTo->PenStyle = g_oeState.logPen.lopnStyle;
  1342. //
  1343. // Currently only pen withs of 1 are supported. Unfortunately
  1344. // GDI left it up to the driver to decide on how to stroke the
  1345. // line, so we can't predict what pixels will be on or off for
  1346. // pen widths bigger.
  1347. //
  1348. pLineTo->PenWidth = 1;
  1349. //
  1350. // This is a logical color
  1351. //
  1352. OEConvertColor(g_oeState.logPen.lopnColor, &pLineTo->PenColor,
  1353. FALSE);
  1354. //
  1355. // Store the general order data.
  1356. //
  1357. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  1358. //
  1359. // This will add in OESTATE_SENTORDER if it succeeded.
  1360. // Then OEDDPostStopAccum() will ignore screen data, or
  1361. // will add our nicely calculated bounds above in instead.
  1362. //
  1363. OTRACE(("Line: Start {%d, %d}, End {%d, %d}", ptStart.x, ptStart.y,
  1364. ptEnd.x, ptEnd.y));
  1365. OEClipAndAddOrder(pOrder, NULL);
  1366. }
  1367. DC_EXIT_POINT:
  1368. if (!pOrder)
  1369. {
  1370. OTRACE(("Line: Sending as screen data {%d, %d, %d, %d}",
  1371. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  1372. g_oeState.rc.bottom));
  1373. OEClipAndAddScreenData(&g_oeState.rc);
  1374. }
  1375. DebugExitVOID(OEAddLine);
  1376. }
  1377. //
  1378. // OEValidateDC()
  1379. // This makes sure the thing passed in is a valid DC and gets a pointer to
  1380. // the DC data structure in GDI if so. We need to handle the (rare) case
  1381. // of the DC being swapped out to GDI's extended flat memory space as well
  1382. // as the HDC being prsent in GDI's 16-bit dataseg
  1383. //
  1384. // NOTE:
  1385. // It is NOT valid to hang on to a LPDC around a GDI call. Something may
  1386. // be swapped out before the call, then get swapped in after the call.
  1387. // In which case the original based32 ptr gets freed. And vice-versa, the
  1388. // original GDI dc-16 localptr may get realloced small.
  1389. //
  1390. // In normal usage, this is very fast. Only in low memory (or when
  1391. // parameters are invalid) does doing this twice even matter.
  1392. //
  1393. LPDC OEValidateDC
  1394. (
  1395. HDC hdc,
  1396. BOOL fSrc
  1397. )
  1398. {
  1399. LPDC lpdc = NULL;
  1400. LPGDIHANDLE lpgh;
  1401. DWORD dwBase;
  1402. DebugEntry(OEDDValidateDC);
  1403. if (IsGDIObject(hdc) != GDIOBJ_DC)
  1404. {
  1405. //
  1406. // This is a metafile HDC, an IC, or just a plain old bad param.
  1407. //
  1408. DC_QUIT;
  1409. }
  1410. //
  1411. // OK. The HDC is a local handle to two words in GDI's DS:
  1412. // * 1st is actual ptr of DC (or local32 handle if swapped out)
  1413. // * 2nd is flags
  1414. //
  1415. // NOTE:
  1416. // Gdi's data segment is already GlobalFixed(). So we don't have to
  1417. // worry about it moving.
  1418. //
  1419. lpgh = MAKELP(g_hInstGdi16, hdc);
  1420. if (lpgh->objFlags & OBJFLAGS_SWAPPEDOUT)
  1421. {
  1422. UINT uSel;
  1423. //
  1424. // This is an error only so we can actually stop when we hit this
  1425. // rare case and make sure our code is working!
  1426. //
  1427. WARNING_OUT(("DC is swapped out, getting at far heap info"));
  1428. //
  1429. // Need to make our cached selector point at this thing. NOTE that
  1430. // in OEDDStopAccum, we need to reget lpdc since it will have been
  1431. // swapped in during the output call.
  1432. //
  1433. dwBase = GetSelectorBase((UINT)g_hInstGdi16);
  1434. ASSERT(dwBase);
  1435. uSel = (fSrc ? g_oeSelSrc : g_oeSelDst);
  1436. SetSelectorBase(uSel, dwBase + 0x10000);
  1437. //
  1438. // The pGdiObj is the local32 handle. GDI:10000+pGdiObj has a DWORD
  1439. // which is the based32 address, relative to GDI's dataseg, of the DC.
  1440. // We've set the base of our selector 64K higher than GDI, so we can
  1441. // use it as an offset directly.
  1442. //
  1443. ASSERT(!IsBadReadPtr(MAKELP(uSel, lpgh->pGdiObj), sizeof(DWORD)));
  1444. dwBase = *(LPDWORD)MAKELP(uSel, lpgh->pGdiObj);
  1445. //
  1446. // The 16-bit base is the nearest 64K less than this 32-bit pointer,
  1447. // above GDI's ds.
  1448. //
  1449. SetSelectorBase(uSel, GetSelectorBase((UINT)g_hInstGdi16) +
  1450. (dwBase & 0xFFFF0000));
  1451. //
  1452. // Remainder is slop past 64K.
  1453. //
  1454. lpdc = MAKELP(uSel, LOWORD(dwBase));
  1455. }
  1456. else
  1457. {
  1458. lpdc = MAKELP(g_hInstGdi16, lpgh->pGdiObj);
  1459. }
  1460. ASSERT(!IsBadReadPtr(lpdc, sizeof(DC)));
  1461. DC_EXIT_POINT:
  1462. DebugExitDWORD(OEDDValidateDC, (DWORD)lpdc);
  1463. return(lpdc);
  1464. }
  1465. //
  1466. // OEBeforeDDI()
  1467. //
  1468. // This does all the common stuff at the start of an intercepted DDI call:
  1469. // * Increment the reentrancy count
  1470. // * Disable the patch
  1471. // * Get a ptr to the DC structure (if valid)
  1472. // * Get some attributes about the DC (if valid)
  1473. // * Set up to get the drawing bounds calculated in GDI
  1474. //
  1475. BOOL OEBeforeDDI
  1476. (
  1477. DDI_PATCH ddiType,
  1478. HDC hdcDst,
  1479. UINT uFlags
  1480. )
  1481. {
  1482. LPDC lpdc;
  1483. BOOL fWeCare = FALSE;
  1484. DebugEntry(OEBeforeDDI);
  1485. EnableFnPatch(&g_oeDDPatches[ddiType], PATCH_DISABLE);
  1486. if (++g_oeEnterCount > 1)
  1487. {
  1488. TRACE_OUT(("Skipping nested output call"));
  1489. DC_QUIT;
  1490. }
  1491. //
  1492. // Get a pointer to the destination DC. Since we may have an output
  1493. // call where both the source and dest are swapped out, we may need to
  1494. // use both our cached selectors. Thus, we must to tell OEValidateDC()
  1495. // which DC this is to avoid collision.
  1496. //
  1497. lpdc = OEValidateDC(hdcDst, FALSE);
  1498. if (!SELECTOROF(lpdc))
  1499. {
  1500. TRACE_OUT(("Bogus DC"));
  1501. DC_QUIT;
  1502. }
  1503. //
  1504. // Is this a screen DC w/o an active path? When a path is active, the
  1505. // output is being recorded into a path, which is like a region. Then
  1506. // stroking/filling the path can cause output.
  1507. //
  1508. if (!(lpdc->DCFlags & DC_IS_DISPLAY) ||
  1509. (lpdc->fwPath & DCPATH_ACTIVE))
  1510. {
  1511. TRACE_OUT(("Not screen DC"));
  1512. DC_QUIT;
  1513. }
  1514. //
  1515. // Only if this is a screen DC do we care about where the output is
  1516. // going to happen. For memory DCs,
  1517. //
  1518. // If this is a bitmap DC or a path is active, we want to dork with
  1519. // the bitmap cache.
  1520. if (lpdc->DCFlags & DC_IS_MEMORY)
  1521. {
  1522. //
  1523. // No screen data or other goop accumulated for non-output calls
  1524. // We just want to do stuff in OEAfterDDI.
  1525. //
  1526. uFlags &= ~OESTATE_DDISTUFF;
  1527. goto WeCareWeReallyCare;
  1528. }
  1529. else
  1530. {
  1531. //
  1532. // Is this a DC we care about? Our algorithm is:
  1533. // * If sharing the desktop, yes.
  1534. // * If no window associated with DC or window is desktop, maybe.
  1535. // * If window is ancestor of shared window, yes. Else no.
  1536. //
  1537. if (!g_hetDDDesktopIsShared)
  1538. {
  1539. ERROR_OUT(("g_hetDDDesktopIsShared is FALSE!"));
  1540. }
  1541. }
  1542. //
  1543. // Code from here to WeCareWeReallyCare() is only for screen DCs
  1544. //
  1545. //
  1546. // For the *TextOut* apis, we want to accumulate DCBs if the font is too
  1547. // complex.
  1548. //
  1549. if (uFlags & OESTATE_SDA_FONTCOMPLEX)
  1550. {
  1551. BOOL fComplex;
  1552. POINT aptCheck[2];
  1553. fComplex = TRUE;
  1554. // Get the logfont info
  1555. if (!GetObject(lpdc->hFont, sizeof(g_oeState.logFont), &g_oeState.logFont) ||
  1556. (g_oeState.logFont.lfEscapement != 0))
  1557. goto FontCheckDone;
  1558. //
  1559. // The font is too complex if it has escapement or the logical units
  1560. // are bigger than pixels.
  1561. //
  1562. // NOTE that NM 2.0 had a bug--it used one point only for non
  1563. // MM_TEXT mode. They did this because they wouldn't get back
  1564. // the same thing passed in, forgetting that LPtoDP takes into
  1565. // account viewport and window origins in addition to scaling.
  1566. //
  1567. // So we do this the right way, using two points and looking at
  1568. // the difference.
  1569. //
  1570. aptCheck[0].x = 0;
  1571. aptCheck[0].y = 0;
  1572. aptCheck[1].x = 1000;
  1573. aptCheck[1].y = 1000;
  1574. LPtoDP(hdcDst, aptCheck, 2);
  1575. if ((aptCheck[1].x - aptCheck[0].x <= 1000) ||
  1576. (aptCheck[1].y - aptCheck[0].y <= 1000))
  1577. {
  1578. fComplex = FALSE;
  1579. }
  1580. FontCheckDone:
  1581. if (fComplex)
  1582. {
  1583. TRACE_OUT(("Font too complex for text order"));
  1584. uFlags |= OESTATE_SDA_DCB;
  1585. }
  1586. }
  1587. //
  1588. // Some DDIs calculate their own bound rects, which is faster than
  1589. // GDI's BoundsRect() services. But some don't because it's too
  1590. // complicated. In that case, we do it for 'em.
  1591. //
  1592. if (uFlags & OESTATE_SDA_DCB)
  1593. {
  1594. //
  1595. // We don't have to worry about the mapping mode when getting the
  1596. // bounds. The only thing to note is that the return rect is
  1597. // relative to the window org of the DC, and visrgn/clipping occurs
  1598. //
  1599. g_oeState.uGetDCB = GetBoundsRect(hdcDst, &g_oeState.rcDCB, 0);
  1600. g_oeState.uSetDCB = SetBoundsRect(hdcDst, NULL, DCB_ENABLE | DCB_RESET)
  1601. & (DCB_ENABLE | DCB_DISABLE);
  1602. // No curpos needed if going as screen data, not order
  1603. uFlags &= ~OESTATE_CURPOS;
  1604. }
  1605. if (uFlags & OESTATE_CURPOS)
  1606. {
  1607. GetCurrentPositionEx(hdcDst, &g_oeState.ptCurPos);
  1608. }
  1609. WeCareWeReallyCare:
  1610. fWeCare = TRUE;
  1611. g_oeState.uFlags = uFlags;
  1612. g_oeState.hdc = hdcDst;
  1613. DC_EXIT_POINT:
  1614. DebugExitBOOL(OEBeforeDDI, fWeCare);
  1615. return(fWeCare);
  1616. }
  1617. //
  1618. // OEAfterDDI()
  1619. //
  1620. // This does all the common things right after a DDI call. It returns TRUE
  1621. // if output happened into a screen DC that we care about.
  1622. //
  1623. BOOL OEAfterDDI
  1624. (
  1625. DDI_PATCH ddiType,
  1626. BOOL fWeCare,
  1627. BOOL fOutput
  1628. )
  1629. {
  1630. DebugEntry(OEAfterDDI);
  1631. //
  1632. // Reenable patch
  1633. //
  1634. EnableFnPatch(&g_oeDDPatches[ddiType], PATCH_ENABLE);
  1635. --g_oeEnterCount;
  1636. if (!fWeCare)
  1637. {
  1638. //
  1639. // This was reentrant, we don't care about output into this
  1640. // DC, or something went wrong, bail out.
  1641. //
  1642. DC_QUIT;
  1643. }
  1644. g_oeState.lpdc = OEValidateDC(g_oeState.hdc, FALSE);
  1645. if (!SELECTOROF(g_oeState.lpdc))
  1646. {
  1647. ERROR_OUT(("Bogus DC"));
  1648. DC_QUIT;
  1649. }
  1650. ASSERT(g_oeState.lpdc->DCFlags & DC_IS_DISPLAY);
  1651. ASSERT(!(g_oeState.lpdc->fwPath & DCPATH_ACTIVE));
  1652. //
  1653. // If this output happened into a memory bitmap, see if it affects
  1654. // SPBs or our sent bitmap cache
  1655. //
  1656. if (g_oeState.lpdc->DCFlags & DC_IS_MEMORY)
  1657. {
  1658. //
  1659. // Don't set fOutput to FALSE for SPB operations, we want
  1660. // BitBlt to look at it.
  1661. //
  1662. if (fOutput)
  1663. {
  1664. // If this is BitBlt, check for SPB creation
  1665. if ((ddiType != DDI_BITBLT) ||
  1666. (g_oeState.lpdc->hBitmap != g_ssiLastSpbBitmap))
  1667. {
  1668. fOutput = FALSE;
  1669. }
  1670. }
  1671. }
  1672. else
  1673. {
  1674. //
  1675. // Drawing on the screen that isn't going to be handled in the DDI
  1676. // call.
  1677. //
  1678. if (fOutput && (g_oeState.uFlags & OESTATE_SDA_MASK))
  1679. {
  1680. //
  1681. // We do some common tasks that several DDIs would have to do
  1682. // * take the screen bounds and add as SD
  1683. // * take the draw bounds and add as SD
  1684. //
  1685. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  1686. if (g_oeState.uFlags & OESTATE_SDA_DCB)
  1687. {
  1688. //
  1689. // Get the drawing bounds
  1690. //
  1691. int mmMode;
  1692. SIZE ptWindowExt;
  1693. SIZE ptViewportExt;
  1694. int uBoundsNew;
  1695. mmMode = GetMapMode(g_oeState.hdc);
  1696. if (mmMode != MM_TEXT)
  1697. {
  1698. //
  1699. // Changing the map mode whacks the window/view exts
  1700. // So save them so we can replace them when done.
  1701. //
  1702. GetWindowExtEx(g_oeState.hdc, &ptWindowExt);
  1703. GetViewportExtEx(g_oeState.hdc, &ptViewportExt);
  1704. SetMapMode(g_oeState.hdc, MM_TEXT);
  1705. }
  1706. //
  1707. // Get the drawing bounds and update them.
  1708. //
  1709. uBoundsNew = GetBoundsRect(g_oeState.hdc, &g_oeState.rc, DCB_RESET);
  1710. //
  1711. // If no drawing bounds updated, act like no output happened.
  1712. //
  1713. if ((uBoundsNew & DCB_SET) == DCB_RESET)
  1714. {
  1715. fOutput = FALSE;
  1716. }
  1717. else
  1718. {
  1719. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  1720. }
  1721. if (mmMode != MM_TEXT)
  1722. {
  1723. SetMapMode(g_oeState.hdc, mmMode);
  1724. // Put back the window, viewport exts; SetMapMode wipes them out
  1725. SetWindowExt(g_oeState.hdc, ptWindowExt.cx, ptWindowExt.cy);
  1726. SetViewportExt(g_oeState.hdc, ptViewportExt.cx, ptViewportExt.cy);
  1727. }
  1728. }
  1729. else
  1730. {
  1731. ASSERT(g_oeState.uFlags & OESTATE_SDA_SCREEN);
  1732. g_oeState.rc.left = g_osiScreenRect.left;
  1733. g_oeState.rc.top = g_osiScreenRect.top;
  1734. g_oeState.rc.right = g_osiScreenRect.right - 1;
  1735. g_oeState.rc.bottom = g_osiScreenRect.bottom - 1;
  1736. }
  1737. if (fOutput)
  1738. {
  1739. if (g_oeState.uFlags & OESTATE_OFFBYONEHACK)
  1740. g_oeState.rc.bottom++;
  1741. OEClipAndAddScreenData(&g_oeState.rc);
  1742. // This way caller won't do anything else.
  1743. fOutput = FALSE;
  1744. }
  1745. //
  1746. // Put back the draw bounds if we'd turned them on.
  1747. //
  1748. if (g_oeState.uFlags & OESTATE_SDA_DCB)
  1749. {
  1750. if (g_oeState.uGetDCB == DCB_SET)
  1751. {
  1752. SetBoundsRect(g_oeState.hdc, &g_oeState.rcDCB,
  1753. g_oeState.uSetDCB | DCB_ACCUMULATE);
  1754. }
  1755. else
  1756. {
  1757. SetBoundsRect(g_oeState.hdc, NULL,
  1758. g_oeState.uSetDCB | DCB_RESET);
  1759. }
  1760. }
  1761. }
  1762. }
  1763. DC_EXIT_POINT:
  1764. DebugExitBOOL(OEAfterDDI, (fWeCare && fOutput));
  1765. return(fWeCare && fOutput);
  1766. }
  1767. //
  1768. // OEClipAndAddScreenData()
  1769. //
  1770. void OEClipAndAddScreenData
  1771. (
  1772. LPRECT lprcAdd
  1773. )
  1774. {
  1775. RECT rcSDA;
  1776. RECT rcClipped;
  1777. LPRECTL pClip;
  1778. UINT iClip;
  1779. DebugEntry(OEClipAndAddScreenData);
  1780. ASSERT(g_oeState.uFlags & OESTATE_REGION);
  1781. //
  1782. // The rect passed is in virtual desktop inclusive coords. Convert to
  1783. // Windows screen coords
  1784. //
  1785. rcSDA.left = lprcAdd->left;
  1786. rcSDA.top = lprcAdd->top;
  1787. rcSDA.right = lprcAdd->right + 1;
  1788. rcSDA.bottom = lprcAdd->bottom + 1;
  1789. //
  1790. // We've got our region data. In the case of a region that has more
  1791. // than 64 pieces, we just use the bound box (one piece), that's been
  1792. // set up for us already.
  1793. //
  1794. //
  1795. // Intersect each piece with the total bounds to product an SDA rect
  1796. // clipped appropriately.
  1797. //
  1798. for (iClip = 0, pClip = g_oeState.rgnData.arclPieces;
  1799. iClip < g_oeState.rgnData.rdh.nRectL; iClip++, pClip++)
  1800. {
  1801. RECTL_TO_RECT(pClip, &rcClipped);
  1802. if (IntersectRect(&rcClipped, &rcClipped, &rcSDA))
  1803. {
  1804. //
  1805. // Convert to virtual desktop inclusive coords
  1806. //
  1807. rcClipped.right -= 1;
  1808. rcClipped.bottom -= 1;
  1809. BA_AddScreenData(&rcClipped);
  1810. }
  1811. }
  1812. DC_EXIT_POINT:
  1813. DebugExitVOID(OEClipAndAddScreenData);
  1814. }
  1815. //
  1816. // FUNCTION: OEClipAndAddOrder
  1817. //
  1818. // DESCRIPTION:
  1819. //
  1820. // Clips the supplied order to the current clip region in the DC. If this
  1821. // results in more than one clipped rectangle then the order is duplicated
  1822. // and multiple copies are added to the Order List (with the only
  1823. // difference between the orders being the destination rectangle).
  1824. //
  1825. // PARAMETERS: pOrder - a pointer to the order
  1826. //
  1827. // RETURNS: VOID
  1828. //
  1829. //
  1830. void OEClipAndAddOrder
  1831. (
  1832. LPINT_ORDER pOrder,
  1833. void FAR* lpExtraInfo
  1834. )
  1835. {
  1836. RECT rcOrder;
  1837. RECT rcPiece;
  1838. RECT rcClipped;
  1839. LPRECTL pPiece;
  1840. UINT iClip;
  1841. BOOL fOrderClipped;
  1842. LPINT_ORDER pNewOrder;
  1843. LPINT_ORDER pLastOrder;
  1844. DebugEntry(OEClipAndAddOrder);
  1845. ASSERT(g_oeState.uFlags & OESTATE_REGION);
  1846. //
  1847. // If this fails somewhere, we accumulate screen data in the same place
  1848. // to spoil the order(s).
  1849. //
  1850. //
  1851. // NOTE:
  1852. // There are some VERY important things about the way this function
  1853. // works that you should be aware of:
  1854. //
  1855. // (1) Every time an order is allocated, it is added to the end of
  1856. // the order heap linked list
  1857. // (2) Appending an order commits it, that updates some total byte info.
  1858. // If the order is a spoiler, the append code will walk backwards from
  1859. // the order being appended and will wipe out orders whose bounds are
  1860. // completely contained within the rect of the current one.
  1861. //
  1862. // THEREFORE, it is important to append orders in the order they are
  1863. // allocated it. When we come into this function, one order is already
  1864. // allocated. Its rcsDst bound rect is uninitialized. When a second
  1865. // intersection with the visrgn occurs, we must allocate a new order,
  1866. // but append the previously allocated block with the previous rect
  1867. // info.
  1868. //
  1869. // Otherwise you will encounter the bug that took me a while to figure
  1870. // out:
  1871. // * Laura allocates an order in say PatBlt with a spoiler ROP
  1872. // * Laura calls OEClipAndAddOrder and of course the rcsDst field
  1873. // hasn't been initialized yet.
  1874. // * The order intersects two pieces of the visrgn. On the first
  1875. // intersection, we save that info away.
  1876. // * On the second, we allocate a new order block, fill in the NEW
  1877. // order's info by copying from the old, setting up the rect
  1878. // with the first intersection, and call OA_DDAddOrder.
  1879. // * This, as a spoiler, causes the OA_ code to walk backwards in
  1880. // the linked list looking for orders whose bounds are
  1881. // completely enclosed by this one.
  1882. // * It comes to the original order allocated, whose bounds are
  1883. // currently NOT initialized
  1884. // * It may find that these uninitialized values describe a rect
  1885. // contained within the new order's bounds
  1886. // * It frees this order but the order was not yet committed
  1887. // * The heap sizes and heap info no longer match, causing an
  1888. // error about the "List head wrong", the list to get reinited,
  1889. // and orders to be lost.
  1890. //
  1891. rcOrder.left = g_oeState.rc.left;
  1892. rcOrder.top = g_oeState.rc.top;
  1893. rcOrder.right = g_oeState.rc.right + 1;
  1894. rcOrder.bottom = g_oeState.rc.bottom + 1;
  1895. pNewOrder = pOrder;
  1896. fOrderClipped = FALSE;
  1897. g_oaPurgeAllowed = FALSE;
  1898. //
  1899. // Intersect each piece rect with the draw bounds
  1900. //
  1901. for (iClip = 0, pPiece = g_oeState.rgnData.arclPieces;
  1902. iClip < g_oeState.rgnData.rdh.nRectL; iClip++, pPiece++)
  1903. {
  1904. RECTL_TO_RECT(pPiece, &rcPiece);
  1905. if (!IntersectRect(&rcPiece, &rcPiece, &rcOrder))
  1906. continue;
  1907. if (fOrderClipped)
  1908. {
  1909. //
  1910. // This adds a clipped order for the LAST intersection, not
  1911. // the current one. We do this to avoid allocating an extra
  1912. // order when only ONE intersection occurs.
  1913. //
  1914. //
  1915. // The order has already been clipped once, so it actually
  1916. // intersects more than one clip rect. We cope with this
  1917. // by duplicating the order and clipping it again.
  1918. //
  1919. pNewOrder = OA_DDAllocOrderMem(
  1920. pLastOrder->OrderHeader.Common.cbOrderDataLength, 0);
  1921. if (pNewOrder == NULL)
  1922. {
  1923. WARNING_OUT(("OA alloc failed"));
  1924. //
  1925. // BOGUS LAURABU:
  1926. // If some order in the middle fails to be
  1927. // allocated, we need the previous order + the remaining
  1928. // intersections to be added as screen data!
  1929. //
  1930. // NT's code is bogus, it will miss some output.
  1931. //
  1932. //
  1933. // Allocation of memory for a duplicate order failed.
  1934. // Just add the original order as screen data, and free
  1935. // the original's memory. Note that g_oeState.rc has
  1936. // the proper bounds, so we can just call OEClipAndAddScreenData().
  1937. //
  1938. OA_DDFreeOrderMem(pLastOrder);
  1939. OEClipAndAddScreenData(&g_oeState.rc);
  1940. DC_QUIT;
  1941. }
  1942. //
  1943. // Copy the header & data from the original order to this
  1944. // new one. Don't overwrite the list info at the start.
  1945. //
  1946. hmemcpy((LPBYTE)pNewOrder + FIELD_SIZE(INT_ORDER, OrderHeader.list),
  1947. (LPBYTE)pLastOrder + FIELD_SIZE(INT_ORDER, OrderHeader.list),
  1948. pLastOrder->OrderHeader.Common.cbOrderDataLength +
  1949. sizeof(INT_ORDER_HEADER) -
  1950. FIELD_SIZE(INT_ORDER, OrderHeader.list));
  1951. //
  1952. // Set the clip rect. NOTE: This is the clipped rect from
  1953. // LAST time.
  1954. //
  1955. pLastOrder->OrderHeader.Common.rcsDst.left =
  1956. rcClipped.left;
  1957. pLastOrder->OrderHeader.Common.rcsDst.top =
  1958. rcClipped.top;
  1959. pLastOrder->OrderHeader.Common.rcsDst.right =
  1960. rcClipped.right - 1;
  1961. pLastOrder->OrderHeader.Common.rcsDst.bottom =
  1962. rcClipped.bottom - 1;
  1963. OTRACE(("Duplicate clipped order %08lx at {%d, %d, %d, %d}",
  1964. pLastOrder,
  1965. pLastOrder->OrderHeader.Common.rcsDst.left,
  1966. pLastOrder->OrderHeader.Common.rcsDst.top,
  1967. pLastOrder->OrderHeader.Common.rcsDst.right,
  1968. pLastOrder->OrderHeader.Common.rcsDst.bottom));
  1969. OA_DDAddOrder(pLastOrder, lpExtraInfo);
  1970. }
  1971. //
  1972. // Save the clipping rect for the NEXT dude.
  1973. //
  1974. CopyRect(&rcClipped, &rcPiece);
  1975. fOrderClipped = TRUE;
  1976. pLastOrder = pNewOrder;
  1977. }
  1978. //
  1979. // We're out of the loop now.
  1980. //
  1981. if (fOrderClipped)
  1982. {
  1983. pLastOrder->OrderHeader.Common.rcsDst.left =
  1984. rcClipped.left;
  1985. pLastOrder->OrderHeader.Common.rcsDst.top =
  1986. rcClipped.top;
  1987. pLastOrder->OrderHeader.Common.rcsDst.right =
  1988. rcClipped.right - 1;
  1989. pLastOrder->OrderHeader.Common.rcsDst.bottom =
  1990. rcClipped.bottom - 1;
  1991. OTRACE(("Clipped order %08lx at {%d, %d, %d, %d}",
  1992. pLastOrder,
  1993. pLastOrder->OrderHeader.Common.rcsDst.left,
  1994. pLastOrder->OrderHeader.Common.rcsDst.top,
  1995. pLastOrder->OrderHeader.Common.rcsDst.right,
  1996. pLastOrder->OrderHeader.Common.rcsDst.bottom));
  1997. OA_DDAddOrder(pLastOrder, lpExtraInfo);
  1998. }
  1999. else
  2000. {
  2001. OTRACE(("Order clipped completely"));
  2002. OA_DDFreeOrderMem(pOrder);
  2003. }
  2004. DC_EXIT_POINT:
  2005. g_oaPurgeAllowed = TRUE;
  2006. DebugExitVOID(OEClipAndAddOrder);
  2007. }
  2008. //
  2009. // DDI PATCHES
  2010. //
  2011. //
  2012. // DrvArc()
  2013. //
  2014. BOOL WINAPI DrvArc
  2015. (
  2016. HDC hdcDst,
  2017. int xLeft,
  2018. int yTop,
  2019. int xRight,
  2020. int yBottom,
  2021. int xStartArc,
  2022. int yStartArc,
  2023. int xEndArc,
  2024. int yEndArc
  2025. )
  2026. {
  2027. BOOL fWeCare;
  2028. BOOL fOutput;
  2029. LPINT_ORDER pOrder;
  2030. LPARC_ORDER pArc;
  2031. POINT ptStart;
  2032. POINT ptEnd;
  2033. DebugEntry(DrvArc);
  2034. OE_SHM_START_WRITING;
  2035. fWeCare = OEBeforeDDI(DDI_ARC, hdcDst, 0);
  2036. fOutput = Arc(hdcDst, xLeft, yTop, xRight, yBottom, xStartArc,
  2037. yStartArc, xEndArc, yEndArc);
  2038. if (OEAfterDDI(DDI_ARC, fWeCare, fOutput))
  2039. {
  2040. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  2041. //
  2042. // Get the bound rect
  2043. //
  2044. g_oeState.rc.left = xLeft;
  2045. g_oeState.rc.top = yTop;
  2046. g_oeState.rc.right = xRight;
  2047. g_oeState.rc.bottom = yBottom;
  2048. OEPenWidthAdjust(&g_oeState.rc, 1);
  2049. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2050. //
  2051. // Can we send an ARC order?
  2052. //
  2053. pOrder = NULL;
  2054. if (OECheckOrder(ORD_ARC, OECHECK_PEN | OECHECK_CLIPPING))
  2055. {
  2056. pOrder = OA_DDAllocOrderMem(sizeof(ARC_ORDER), 0);
  2057. if (!pOrder)
  2058. goto NoArcOrder;
  2059. pArc = (LPARC_ORDER)pOrder->abOrderData;
  2060. pArc->type = LOWORD(ORD_ARC);
  2061. //
  2062. // Note that order coordinates are 32-bits, but we're 16-bits.
  2063. // So we need intermediate variables to do conversions on.
  2064. //
  2065. pArc->nLeftRect = g_oeState.rc.left;
  2066. pArc->nTopRect = g_oeState.rc.top;
  2067. pArc->nRightRect = g_oeState.rc.right;
  2068. pArc->nBottomRect = g_oeState.rc.bottom;
  2069. ptStart.x = xStartArc;
  2070. ptStart.y = yStartArc;
  2071. OELPtoVirtual(g_oeState.hdc, &ptStart, 1);
  2072. pArc->nXStart = ptStart.x;
  2073. pArc->nYStart = ptStart.y;
  2074. ptEnd.x = xEndArc;
  2075. ptEnd.y = yEndArc;
  2076. OELPtoVirtual(g_oeState.hdc, &ptEnd, 1);
  2077. pArc->nXEnd = ptEnd.x;
  2078. pArc->nYEnd = ptEnd.y;
  2079. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL,
  2080. &pArc->BackColor, FALSE);
  2081. pArc->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  2082. pArc->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  2083. pArc->PenStyle = g_oeState.logPen.lopnStyle;
  2084. pArc->PenWidth = 1;
  2085. OEConvertColor(g_oeState.logPen.lopnColor,
  2086. &pArc->PenColor, FALSE);
  2087. //
  2088. // Get the arc direction (counter-clockwise or clockwise)
  2089. //
  2090. if (g_oeState.lpdc->fwPath & DCPATH_CLOCKWISE)
  2091. pArc->ArcDirection = ORD_ARC_CLOCKWISE;
  2092. else
  2093. pArc->ArcDirection = ORD_ARC_COUNTERCLOCKWISE;
  2094. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2095. OTRACE(("Arc: Order %08lx, Rect {%d, %d, %d, %d}, Start {%d, %d}, End {%d, %d}",
  2096. pOrder,
  2097. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2098. g_oeState.rc.bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y));
  2099. OEClipAndAddOrder(pOrder, NULL);
  2100. }
  2101. NoArcOrder:
  2102. if (!pOrder)
  2103. {
  2104. OTRACE(("Arc: Sending as screen data {%d, %d, %d, %d}",
  2105. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2106. g_oeState.rc.bottom));
  2107. OEClipAndAddScreenData(&g_oeState.rc);
  2108. }
  2109. }
  2110. OE_SHM_STOP_WRITING;
  2111. DebugExitBOOL(DrvArc, fOutput);
  2112. return(fOutput);
  2113. }
  2114. //
  2115. // DrvChord()
  2116. //
  2117. BOOL WINAPI DrvChord
  2118. (
  2119. HDC hdcDst,
  2120. int xLeft,
  2121. int yTop,
  2122. int xRight,
  2123. int yBottom,
  2124. int xStartChord,
  2125. int yStartChord,
  2126. int xEndChord,
  2127. int yEndChord
  2128. )
  2129. {
  2130. BOOL fWeCare;
  2131. BOOL fOutput;
  2132. LPINT_ORDER pOrder;
  2133. LPCHORD_ORDER pChord;
  2134. POINT ptStart;
  2135. POINT ptEnd;
  2136. POINT ptBrushOrg;
  2137. DebugEntry(DrvChord);
  2138. OE_SHM_START_WRITING;
  2139. fWeCare = OEBeforeDDI(DDI_CHORD, hdcDst, 0);
  2140. fOutput = Chord(hdcDst, xLeft, yTop, xRight, yBottom,
  2141. xStartChord, yStartChord, xEndChord, yEndChord);
  2142. if (OEAfterDDI(DDI_CHORD, fWeCare, fOutput))
  2143. {
  2144. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  2145. //
  2146. // Get the bound rect
  2147. //
  2148. g_oeState.rc.left = xLeft;
  2149. g_oeState.rc.top = yTop;
  2150. g_oeState.rc.right = xRight;
  2151. g_oeState.rc.bottom = yBottom;
  2152. OEPenWidthAdjust(&g_oeState.rc, 1);
  2153. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2154. //
  2155. // Can we send a CHORD order?
  2156. //
  2157. pOrder = NULL;
  2158. if (OECheckOrder(ORD_CHORD, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING))
  2159. {
  2160. pOrder = OA_DDAllocOrderMem(sizeof(CHORD_ORDER), 0);
  2161. if (!pOrder)
  2162. goto NoChordOrder;
  2163. pChord = (LPCHORD_ORDER)pOrder->abOrderData;
  2164. pChord->type = LOWORD(ORD_CHORD);
  2165. pChord->nLeftRect = g_oeState.rc.left;
  2166. pChord->nTopRect = g_oeState.rc.top;
  2167. pChord->nRightRect = g_oeState.rc.right;
  2168. pChord->nBottomRect = g_oeState.rc.bottom;
  2169. ptStart.x = xStartChord;
  2170. ptStart.y = yStartChord;
  2171. OELPtoVirtual(g_oeState.hdc, &ptStart, 1);
  2172. pChord->nXStart = ptStart.x;
  2173. pChord->nYStart = ptStart.y;
  2174. ptEnd.x = xEndChord;
  2175. ptEnd.y = yEndChord;
  2176. OELPtoVirtual(g_oeState.hdc, &ptEnd, 1);
  2177. pChord->nXEnd = ptEnd.x;
  2178. pChord->nYEnd = ptEnd.y;
  2179. OEGetBrushInfo(&pChord->BackColor, &pChord->ForeColor,
  2180. &pChord->BrushStyle, &pChord->BrushHatch, pChord->BrushExtra);
  2181. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  2182. pChord->BrushOrgX = (BYTE)ptBrushOrg.x;
  2183. pChord->BrushOrgY = (BYTE)ptBrushOrg.y;
  2184. pChord->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  2185. pChord->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  2186. pChord->PenStyle = g_oeState.logPen.lopnStyle;
  2187. pChord->PenWidth = 1;
  2188. OEConvertColor(g_oeState.logPen.lopnColor,
  2189. &pChord->PenColor, FALSE);
  2190. if (g_oeState.lpdc->fwPath & DCPATH_CLOCKWISE)
  2191. pChord->ArcDirection = ORD_ARC_CLOCKWISE;
  2192. else
  2193. pChord->ArcDirection = ORD_ARC_COUNTERCLOCKWISE;
  2194. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2195. OTRACE(("Chord: Order %08lx, Rect {%d, %d, %d, %d}, Start {%d, %d}, End {%d, %d}",
  2196. pOrder,
  2197. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2198. g_oeState.rc.bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y));
  2199. OEClipAndAddOrder(pOrder, NULL);
  2200. }
  2201. NoChordOrder:
  2202. if (!pOrder)
  2203. {
  2204. OTRACE(("Chord: Sending as screen data {%d, %d, %d, %d}",
  2205. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2206. g_oeState.rc.bottom));
  2207. OEClipAndAddScreenData(&g_oeState.rc);
  2208. }
  2209. }
  2210. OE_SHM_STOP_WRITING;
  2211. DebugExitBOOL(DrvChord, fOutput);
  2212. return(fOutput);
  2213. }
  2214. //
  2215. // DrvEllipse()
  2216. //
  2217. BOOL WINAPI DrvEllipse
  2218. (
  2219. HDC hdcDst,
  2220. int xLeft,
  2221. int yTop,
  2222. int xRight,
  2223. int yBottom
  2224. )
  2225. {
  2226. BOOL fWeCare;
  2227. BOOL fOutput;
  2228. LPINT_ORDER pOrder;
  2229. LPELLIPSE_ORDER pEllipse;
  2230. POINT ptBrushOrg;
  2231. DebugEntry(DrvEllipse);
  2232. OE_SHM_START_WRITING;
  2233. fWeCare = OEBeforeDDI(DDI_ELLIPSE, hdcDst, 0);
  2234. fOutput = Ellipse(hdcDst, xLeft, yTop, xRight, yBottom);
  2235. if (OEAfterDDI(DDI_ELLIPSE, fWeCare, fOutput))
  2236. {
  2237. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  2238. //
  2239. // Calc bound rect
  2240. //
  2241. g_oeState.rc.left = xLeft;
  2242. g_oeState.rc.top = yTop;
  2243. g_oeState.rc.right = xRight;
  2244. g_oeState.rc.bottom = yBottom;
  2245. OEPenWidthAdjust(&g_oeState.rc, 1);
  2246. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2247. //
  2248. // Can we send ELLIPSE order?
  2249. //
  2250. pOrder = NULL;
  2251. if (OECheckOrder(ORD_ELLIPSE, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING))
  2252. {
  2253. pOrder = OA_DDAllocOrderMem(sizeof(ELLIPSE_ORDER), 0);
  2254. if (!pOrder)
  2255. goto NoEllipseOrder;
  2256. pEllipse = (LPELLIPSE_ORDER)pOrder->abOrderData;
  2257. pEllipse->type = LOWORD(ORD_ELLIPSE);
  2258. pEllipse->nLeftRect = g_oeState.rc.left;
  2259. pEllipse->nTopRect = g_oeState.rc.top;
  2260. pEllipse->nRightRect = g_oeState.rc.right;
  2261. pEllipse->nBottomRect = g_oeState.rc.bottom;
  2262. OEGetBrushInfo(&pEllipse->BackColor, &pEllipse->ForeColor,
  2263. &pEllipse->BrushStyle, &pEllipse->BrushHatch,
  2264. pEllipse->BrushExtra);
  2265. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  2266. pEllipse->BrushOrgX = (BYTE)ptBrushOrg.x;
  2267. pEllipse->BrushOrgY = (BYTE)ptBrushOrg.y;
  2268. pEllipse->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  2269. pEllipse->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  2270. pEllipse->PenStyle = g_oeState.logPen.lopnStyle;
  2271. pEllipse->PenWidth = 1;
  2272. OEConvertColor(g_oeState.logPen.lopnColor, &pEllipse->PenColor,
  2273. FALSE);
  2274. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2275. OTRACE(("Ellipse: Order %08lx, Rect {%d, %d, %d, %d}",
  2276. pOrder,
  2277. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2278. g_oeState.rc.bottom));
  2279. OEClipAndAddOrder(pOrder, NULL);
  2280. }
  2281. NoEllipseOrder:
  2282. if (!pOrder)
  2283. {
  2284. OTRACE(("Ellipse: Sending as screen data {%d, %d, %d, %d}",
  2285. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2286. g_oeState.rc.bottom));
  2287. OEClipAndAddScreenData(&g_oeState.rc);
  2288. }
  2289. }
  2290. OE_SHM_STOP_WRITING;
  2291. DebugExitBOOL(DrvEllipse, fOutput);
  2292. return(fOutput);
  2293. }
  2294. //
  2295. // DrvPie()
  2296. //
  2297. BOOL WINAPI DrvPie
  2298. (
  2299. HDC hdcDst,
  2300. int xLeft,
  2301. int yTop,
  2302. int xRight,
  2303. int yBottom,
  2304. int xStartArc,
  2305. int yStartArc,
  2306. int xEndArc,
  2307. int yEndArc
  2308. )
  2309. {
  2310. BOOL fWeCare;
  2311. BOOL fOutput;
  2312. LPINT_ORDER pOrder;
  2313. LPPIE_ORDER pPie;
  2314. POINT ptStart;
  2315. POINT ptEnd;
  2316. POINT ptBrushOrg;
  2317. DebugEntry(DrvPie);
  2318. OE_SHM_START_WRITING;
  2319. fWeCare = OEBeforeDDI(DDI_PIE, hdcDst, 0);
  2320. fOutput = Pie(hdcDst, xLeft, yTop, xRight, yBottom, xStartArc, yStartArc,
  2321. xEndArc, yEndArc);
  2322. if (OEAfterDDI(DDI_PIE, fWeCare, fOutput))
  2323. {
  2324. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  2325. //
  2326. // Get bound rect
  2327. //
  2328. g_oeState.rc.left = xLeft;
  2329. g_oeState.rc.top = yTop;
  2330. g_oeState.rc.right = xRight;
  2331. g_oeState.rc.bottom = yBottom;
  2332. OEPenWidthAdjust(&g_oeState.rc, 1);
  2333. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2334. //
  2335. // Can we send PIE order?
  2336. //
  2337. pOrder = NULL;
  2338. if (OECheckOrder(ORD_PIE, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING))
  2339. {
  2340. pOrder = OA_DDAllocOrderMem(sizeof(PIE_ORDER), 0);
  2341. if (!pOrder)
  2342. goto NoPieOrder;
  2343. pPie = (LPPIE_ORDER)pOrder->abOrderData;
  2344. pPie->type = LOWORD(ORD_PIE);
  2345. pPie->nLeftRect = g_oeState.rc.left;
  2346. pPie->nTopRect = g_oeState.rc.top;
  2347. pPie->nRightRect = g_oeState.rc.right;
  2348. pPie->nBottomRect = g_oeState.rc.bottom;
  2349. ptStart.x = xStartArc;
  2350. ptStart.y = yStartArc;
  2351. OELPtoVirtual(g_oeState.hdc, &ptStart, 1);
  2352. pPie->nXStart = ptStart.x;
  2353. pPie->nYStart = ptStart.y;
  2354. ptEnd.x = xEndArc;
  2355. ptEnd.y = yEndArc;
  2356. OELPtoVirtual(g_oeState.hdc, &ptEnd, 1);
  2357. pPie->nXEnd = ptEnd.x;
  2358. pPie->nYEnd = ptEnd.y;
  2359. OEGetBrushInfo(&pPie->BackColor, &pPie->ForeColor,
  2360. &pPie->BrushStyle, &pPie->BrushHatch, pPie->BrushExtra);
  2361. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  2362. pPie->BrushOrgX = (BYTE)ptBrushOrg.x;
  2363. pPie->BrushOrgY = (BYTE)ptBrushOrg.y;
  2364. pPie->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  2365. pPie->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  2366. pPie->PenStyle = g_oeState.logPen.lopnStyle;
  2367. pPie->PenWidth = 1;
  2368. OEConvertColor(g_oeState.logPen.lopnColor, &pPie->PenColor,
  2369. FALSE);
  2370. if (g_oeState.lpdc->fwPath & DCPATH_CLOCKWISE)
  2371. pPie->ArcDirection = ORD_ARC_CLOCKWISE;
  2372. else
  2373. pPie->ArcDirection = ORD_ARC_COUNTERCLOCKWISE;
  2374. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2375. OTRACE(("Pie: Order %08lx, Rect {%d, %d, %d, %d}, Start {%d, %d}, End {%d, %d}",
  2376. pOrder,
  2377. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2378. g_oeState.rc.bottom));
  2379. OEClipAndAddOrder(pOrder, NULL);
  2380. }
  2381. NoPieOrder:
  2382. if (!pOrder)
  2383. {
  2384. OTRACE(("PieOrder: Sending as screen data {%d, %d, %d, %d}",
  2385. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2386. g_oeState.rc.bottom));
  2387. OEClipAndAddScreenData(&g_oeState.rc);
  2388. }
  2389. }
  2390. OE_SHM_STOP_WRITING;
  2391. DebugExitBOOL(DrvPie, fOutput);
  2392. return(fOutput);
  2393. }
  2394. //
  2395. // DrvRoundRect()
  2396. //
  2397. BOOL WINAPI DrvRoundRect
  2398. (
  2399. HDC hdcDst,
  2400. int xLeft,
  2401. int yTop,
  2402. int xRight,
  2403. int yBottom,
  2404. int cxEllipse,
  2405. int cyEllipse
  2406. )
  2407. {
  2408. BOOL fWeCare;
  2409. BOOL fOutput;
  2410. LPINT_ORDER pOrder;
  2411. LPROUNDRECT_ORDER pRoundRect;
  2412. POINT ptBrushOrg;
  2413. DebugEntry(DrvRoundRect);
  2414. OE_SHM_START_WRITING;
  2415. fWeCare = OEBeforeDDI(DDI_ROUNDRECT, hdcDst, 0);
  2416. fOutput = RoundRect(hdcDst, xLeft, yTop, xRight, yBottom, cxEllipse, cyEllipse);
  2417. if (OEAfterDDI(DDI_ROUNDRECT, fWeCare, fOutput))
  2418. {
  2419. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  2420. //
  2421. // Get bound rect
  2422. //
  2423. g_oeState.rc.left = xLeft;
  2424. g_oeState.rc.top = yTop;
  2425. g_oeState.rc.right = xRight;
  2426. g_oeState.rc.bottom = yBottom;
  2427. OEPenWidthAdjust(&g_oeState.rc, 1);
  2428. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2429. //
  2430. // Can we send ROUNDRECT order?
  2431. //
  2432. pOrder = NULL;
  2433. if (OECheckOrder(ORD_ROUNDRECT, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING) &&
  2434. (GetMapMode(hdcDst) == MM_TEXT))
  2435. {
  2436. pOrder = OA_DDAllocOrderMem(sizeof(ROUNDRECT_ORDER), 0);
  2437. if (!pOrder)
  2438. goto NoRoundRectOrder;
  2439. pRoundRect = (LPROUNDRECT_ORDER)pOrder->abOrderData;
  2440. pRoundRect->type = LOWORD(ORD_ROUNDRECT);
  2441. pRoundRect->nLeftRect = g_oeState.rc.left;
  2442. pRoundRect->nTopRect = g_oeState.rc.top;
  2443. pRoundRect->nRightRect = g_oeState.rc.right;
  2444. pRoundRect->nBottomRect = g_oeState.rc.bottom;
  2445. //
  2446. // It's too difficult to do the mapping of the ellipse
  2447. // dimensions when not MM_TEXT. Therefore we don't. If we
  2448. // are here, we just pass the sizes straight through.
  2449. //
  2450. pRoundRect->nEllipseWidth = cxEllipse;
  2451. pRoundRect->nEllipseHeight = cyEllipse;
  2452. OEGetBrushInfo(&pRoundRect->BackColor, &pRoundRect->ForeColor,
  2453. &pRoundRect->BrushStyle, &pRoundRect->BrushHatch,
  2454. pRoundRect->BrushExtra);
  2455. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  2456. pRoundRect->BrushOrgX = ptBrushOrg.x;
  2457. pRoundRect->BrushOrgY = ptBrushOrg.y;
  2458. pRoundRect->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  2459. pRoundRect->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  2460. pRoundRect->PenStyle = g_oeState.logPen.lopnStyle;
  2461. pRoundRect->PenWidth = 1;
  2462. OEConvertColor(g_oeState.logPen.lopnColor,
  2463. &pRoundRect->PenColor, FALSE);
  2464. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2465. OTRACE(("RoundRect: Order %08lx, Rect {%d, %d, %d, %d}, Curve {%d, %d}",
  2466. pOrder,
  2467. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2468. g_oeState.rc.bottom, cxEllipse, cyEllipse));
  2469. OEClipAndAddOrder(pOrder, NULL);
  2470. }
  2471. NoRoundRectOrder:
  2472. if (!pOrder)
  2473. {
  2474. OTRACE(("RoundRect: Sending as screen data {%d, %d, %d, %d}",
  2475. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2476. g_oeState.rc.bottom));
  2477. OEClipAndAddScreenData(&g_oeState.rc);
  2478. }
  2479. }
  2480. OE_SHM_STOP_WRITING;
  2481. DebugExitBOOL(DrvRoundRect, fOutput);
  2482. return(fOutput);
  2483. }
  2484. //
  2485. // DrvBitBlt
  2486. //
  2487. BOOL WINAPI DrvBitBlt
  2488. (
  2489. HDC hdcDst,
  2490. int xDst,
  2491. int yDst,
  2492. int cxDst,
  2493. int cyDst,
  2494. HDC hdcSrc,
  2495. int xSrc,
  2496. int ySrc,
  2497. DWORD dwRop
  2498. )
  2499. {
  2500. BOOL fWeCare;
  2501. BOOL fOutput;
  2502. BYTE bRop;
  2503. LPDC lpdcSrc;
  2504. LPINT_ORDER pOrder;
  2505. LPSCRBLT_ORDER pScrBlt;
  2506. POINT ptT;
  2507. RECT rcT;
  2508. DebugEntry(DrvBitBlt);
  2509. OE_SHM_START_WRITING;
  2510. fWeCare = OEBeforeDDI(DDI_BITBLT, hdcDst, 0);
  2511. fOutput = BitBlt(hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, dwRop);
  2512. if (OEAfterDDI(DDI_BITBLT, fWeCare, fOutput && cxDst && cyDst))
  2513. {
  2514. //
  2515. // Is this really PatBlt?
  2516. //
  2517. bRop = LOBYTE(HIWORD(dwRop));
  2518. if (((bRop & 0x33) << 2) == (bRop & 0xCC))
  2519. {
  2520. TRACE_OUT(("BitBlt used for PatBlt"));
  2521. OEGetState(OESTATE_COORDS | OESTATE_BRUSH | OESTATE_REGION);
  2522. //
  2523. // Get bound rect
  2524. //
  2525. g_oeState.rc.left = xDst;
  2526. g_oeState.rc.top = yDst;
  2527. g_oeState.rc.right = xDst + cxDst;
  2528. g_oeState.rc.bottom = yDst + cyDst;
  2529. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2530. OEAddBlt(dwRop);
  2531. DC_QUIT;
  2532. }
  2533. //
  2534. // SPB goop
  2535. //
  2536. if (g_oeState.lpdc->hBitmap == g_ssiLastSpbBitmap)
  2537. {
  2538. //
  2539. // This is an SPB operation. The source is in screen coords.
  2540. //
  2541. ASSERT(g_ssiLastSpbBitmap);
  2542. ASSERT(g_oeState.lpdc->DCFlags & DC_IS_MEMORY);
  2543. ASSERT(dwRop == SRCCOPY);
  2544. g_oeState.rc.left = xSrc;
  2545. g_oeState.rc.top = ySrc;
  2546. g_oeState.rc.right = xSrc + cxDst;
  2547. g_oeState.rc.bottom = ySrc + cyDst;
  2548. SSISaveBits(g_ssiLastSpbBitmap, &g_oeState.rc);
  2549. g_ssiLastSpbBitmap = NULL;
  2550. DC_QUIT;
  2551. }
  2552. ASSERT(!(g_oeState.lpdc->DCFlags & DC_IS_MEMORY));
  2553. //
  2554. // Is this a memory to screen blt for SPB restoration?
  2555. //
  2556. lpdcSrc = OEValidateDC(hdcSrc, TRUE);
  2557. if (SELECTOROF(lpdcSrc) &&
  2558. (lpdcSrc->DCFlags & DC_IS_DISPLAY) &&
  2559. (lpdcSrc->DCFlags & DC_IS_MEMORY) &&
  2560. (dwRop == SRCCOPY) &&
  2561. SSIRestoreBits(lpdcSrc->hBitmap))
  2562. {
  2563. OTRACE(("BitBlt: SPB restored"));
  2564. DC_QUIT;
  2565. }
  2566. //
  2567. // Now, we accumulate orders for screen-to-screen blts
  2568. //
  2569. OEGetState(OESTATE_COORDS | OESTATE_BRUSH | OESTATE_REGION);
  2570. g_oeState.rc.left = xDst;
  2571. g_oeState.rc.top = yDst;
  2572. g_oeState.rc.right = xDst + cxDst;
  2573. g_oeState.rc.bottom = yDst + cyDst;
  2574. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2575. pOrder = NULL;
  2576. if (hdcSrc == hdcDst)
  2577. {
  2578. if (!OECheckOrder(ORD_SCRBLT, OECHECK_CLIPPING) ||
  2579. !OESendRop3AsOrder(bRop) ||
  2580. !ROP3_NO_PATTERN(bRop))
  2581. {
  2582. goto NoBitBltOrder;
  2583. }
  2584. //
  2585. // Get source coords
  2586. //
  2587. ptT.x = xSrc;
  2588. ptT.y = ySrc;
  2589. OELPtoVirtual(hdcSrc, &ptT, 1);
  2590. //
  2591. // If the clipping isn't simple and the source overlaps the dest,
  2592. // send as screen data. It's too complicated for an order.
  2593. //
  2594. if (!OEClippingIsSimple())
  2595. {
  2596. //
  2597. // NOTE:
  2598. // The NM 2.0 code was really messed up, the source rect
  2599. // calcs were bogus.
  2600. //
  2601. rcT.left = max(g_oeState.rc.left, ptT.x);
  2602. rcT.right = min(g_oeState.rc.right,
  2603. ptT.x + (g_oeState.rc.right - g_oeState.rc.left));
  2604. rcT.top = max(g_oeState.rc.top, ptT.y);
  2605. rcT.bottom = min(g_oeState.rc.bottom,
  2606. ptT.y + (g_oeState.rc.bottom - g_oeState.rc.top));
  2607. if ((rcT.left <= rcT.right) &&
  2608. (rcT.top <= rcT.bottom))
  2609. {
  2610. TRACE_OUT(("No SCRBLT order; non-rect clipping and Src/Dst intersect"));
  2611. goto NoBitBltOrder;
  2612. }
  2613. }
  2614. pOrder = OA_DDAllocOrderMem(sizeof(SCRBLT_ORDER), 0);
  2615. if (!pOrder)
  2616. goto NoBitBltOrder;
  2617. pScrBlt = (LPSCRBLT_ORDER)pOrder->abOrderData;
  2618. pScrBlt->type = LOWORD(ORD_SCRBLT);
  2619. pScrBlt->nLeftRect = g_oeState.rc.left;
  2620. pScrBlt->nTopRect = g_oeState.rc.top;
  2621. pScrBlt->nWidth = g_oeState.rc.right - g_oeState.rc.left + 1;
  2622. pScrBlt->nHeight = g_oeState.rc.bottom - g_oeState.rc.top + 1;
  2623. pScrBlt->bRop = bRop;
  2624. pScrBlt->nXSrc = ptT.x;
  2625. pScrBlt->nYSrc = ptT.y;
  2626. pOrder->OrderHeader.Common.fOrderFlags = OF_BLOCKER | OF_SPOILABLE;
  2627. OTRACE(("ScrBlt: From {%d, %d}, To {%d, %d}, Size {%d, %d}",
  2628. ptT.x, ptT.y, g_oeState.rc.left, g_oeState.rc.top,
  2629. g_oeState.rc.right - g_oeState.rc.left + 1,
  2630. g_oeState.rc.bottom - g_oeState.rc.top + 1));
  2631. OEClipAndAddOrder(pOrder, NULL);
  2632. }
  2633. NoBitBltOrder:
  2634. if (!pOrder)
  2635. {
  2636. OTRACE(("BitBlt: Sending as screen data {%d, %d, %d, %d}",
  2637. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2638. g_oeState.rc.bottom));
  2639. OEClipAndAddScreenData(&g_oeState.rc);
  2640. }
  2641. }
  2642. DC_EXIT_POINT:
  2643. OE_SHM_STOP_WRITING;
  2644. DebugExitBOOL(DrvBitBlt, fOutput);
  2645. return(fOutput);
  2646. }
  2647. //
  2648. // DrvExtTextOutA()
  2649. //
  2650. BOOL WINAPI DrvExtTextOutA
  2651. (
  2652. HDC hdcDst,
  2653. int xDst,
  2654. int yDst,
  2655. UINT uOptions,
  2656. LPRECT lprcClip,
  2657. LPSTR lpszText,
  2658. UINT cchText,
  2659. LPINT lpdxCharSpacing
  2660. )
  2661. {
  2662. BOOL fWeCare;
  2663. BOOL fOutput;
  2664. UINT uFlags;
  2665. DebugEntry(DrvExtTextOutA);
  2666. OE_SHM_START_WRITING;
  2667. //
  2668. // Is this really just opaquing?
  2669. //
  2670. if ((cchText == 0) &&
  2671. SELECTOROF(lprcClip) &&
  2672. !IsBadReadPtr(lprcClip, sizeof(RECT)) &&
  2673. (uOptions & ETO_OPAQUE))
  2674. {
  2675. uFlags = 0;
  2676. }
  2677. else
  2678. {
  2679. uFlags = OESTATE_SDA_FONTCOMPLEX | OESTATE_CURPOS;
  2680. }
  2681. fWeCare = OEBeforeDDI(DDI_EXTTEXTOUTA, hdcDst, uFlags);
  2682. fOutput = ExtTextOut(hdcDst, xDst, yDst, uOptions, lprcClip, lpszText, cchText, lpdxCharSpacing);
  2683. if (OEAfterDDI(DDI_EXTTEXTOUTA, fWeCare, fOutput))
  2684. {
  2685. //
  2686. // Is this a simple OPAQUE rect, or a textout call?
  2687. // NOTE that OEAfterDDI() returns FALSE if fOutput is TRUE but
  2688. // we used DCBs to add it as screen data.
  2689. //
  2690. if (uFlags & OESTATE_SDA_FONTCOMPLEX)
  2691. {
  2692. if (cchText)
  2693. {
  2694. POINT ptStart = {xDst, yDst};
  2695. OEAddText(ptStart, uOptions, lprcClip, lpszText, cchText, lpdxCharSpacing);
  2696. }
  2697. }
  2698. else
  2699. {
  2700. OEAddOpaqueRect(lprcClip);
  2701. }
  2702. }
  2703. OE_SHM_STOP_WRITING;
  2704. DebugExitBOOL(DrvExtTextOutA, fOutput);
  2705. return(fOutput);
  2706. }
  2707. #pragma optimize("gle", off)
  2708. //
  2709. // DrvPatBlt()
  2710. //
  2711. BOOL WINAPI DrvPatBlt
  2712. (
  2713. HDC hdcDst,
  2714. int xDst,
  2715. int yDst,
  2716. int cxDst,
  2717. int cyDst,
  2718. DWORD rop
  2719. )
  2720. {
  2721. UINT cxSave;
  2722. BOOL fWeCare;
  2723. BOOL fOutput;
  2724. LPINT_ORDER pOrder;
  2725. // Save CX
  2726. _asm mov cxSave, cx
  2727. DebugEntry(DrvPatBlt);
  2728. OE_SHM_START_WRITING;
  2729. fWeCare = OEBeforeDDI(DDI_PATBLT, hdcDst, 0);
  2730. // Restore CX for RealPatBlt
  2731. _asm mov cx, cxSave
  2732. fOutput = g_lpfnRealPatBlt(hdcDst, xDst, yDst, cxDst, cyDst, rop);
  2733. if (OEAfterDDI(DDI_PATBLT, fWeCare, fOutput && (cxSave != 0)))
  2734. {
  2735. OEGetState(OESTATE_COORDS | OESTATE_BRUSH | OESTATE_REGION);
  2736. //
  2737. // Get bound rect
  2738. //
  2739. g_oeState.rc.left = xDst;
  2740. g_oeState.rc.top = yDst;
  2741. g_oeState.rc.right = xDst + cxDst;
  2742. g_oeState.rc.bottom = yDst + cyDst;
  2743. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2744. OEAddBlt(rop);
  2745. }
  2746. OE_SHM_STOP_WRITING;
  2747. DebugExitBOOL(DrvPatBlt, fOutput);
  2748. return(fOutput);
  2749. }
  2750. #pragma optimize("", on)
  2751. //
  2752. // OEAddBlt()
  2753. // Used for simple destination ROP blts
  2754. //
  2755. void OEAddBlt
  2756. (
  2757. DWORD dwRop
  2758. )
  2759. {
  2760. LPINT_ORDER pOrder;
  2761. DWORD type;
  2762. POINT ptBrushOrg;
  2763. BYTE bRop;
  2764. DebugEntry(OEAddBlt);
  2765. pOrder = NULL;
  2766. //
  2767. // Is this a full PATBLT_ORDER or a simple DSTBLT_ORDER? If the top
  2768. // nibble of the ROP is equal to the bottom nibble, no pattern is
  2769. // required. WHITENESS for example.
  2770. //
  2771. bRop = LOBYTE(HIWORD(dwRop));
  2772. if ((bRop >> 4) == (bRop & 0x0F))
  2773. {
  2774. type = ORD_DSTBLT;
  2775. }
  2776. else
  2777. {
  2778. type = ORD_PATBLT;
  2779. if (!OECheckBrushIsSimple())
  2780. {
  2781. DC_QUIT;
  2782. }
  2783. if ((dwRop == PATCOPY) && (g_oeState.logBrush.lbStyle == BS_NULL))
  2784. {
  2785. // No output happens in this scenario at all, no screen data even
  2786. goto NothingAtAll;
  2787. }
  2788. }
  2789. if (OE_SendAsOrder(type) &&
  2790. OESendRop3AsOrder(bRop) &&
  2791. !OEClippingIsComplex())
  2792. {
  2793. if (type == ORD_PATBLT)
  2794. {
  2795. LPPATBLT_ORDER pPatBlt;
  2796. pOrder = OA_DDAllocOrderMem(sizeof(PATBLT_ORDER), 0);
  2797. if (!pOrder)
  2798. DC_QUIT;
  2799. pPatBlt = (LPPATBLT_ORDER)pOrder->abOrderData;
  2800. pPatBlt->type = LOWORD(ORD_PATBLT);
  2801. pPatBlt->nLeftRect = g_oeState.rc.left;
  2802. pPatBlt->nTopRect = g_oeState.rc.top;
  2803. pPatBlt->nWidth = g_oeState.rc.right - g_oeState.rc.left + 1;
  2804. pPatBlt->nHeight = g_oeState.rc.bottom - g_oeState.rc.top + 1;
  2805. pPatBlt->bRop = bRop;
  2806. OEGetBrushInfo(&pPatBlt->BackColor, &pPatBlt->ForeColor,
  2807. &pPatBlt->BrushStyle, &pPatBlt->BrushHatch, pPatBlt->BrushExtra);
  2808. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  2809. pPatBlt->BrushOrgX = (BYTE)ptBrushOrg.x;
  2810. pPatBlt->BrushOrgY = (BYTE)ptBrushOrg.y;
  2811. OTRACE(("PatBlt: Order %08lx, Rect {%d, %d, %d, %d}",
  2812. pOrder,
  2813. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2814. g_oeState.rc.right));
  2815. }
  2816. else
  2817. {
  2818. LPDSTBLT_ORDER pDstBlt;
  2819. ASSERT(type == ORD_DSTBLT);
  2820. pOrder = OA_DDAllocOrderMem(sizeof(DSTBLT_ORDER), 0);
  2821. if (!pOrder)
  2822. DC_QUIT;
  2823. pDstBlt = (LPDSTBLT_ORDER)pOrder->abOrderData;
  2824. pDstBlt->type = LOWORD(ORD_DSTBLT);
  2825. pDstBlt->nLeftRect = g_oeState.rc.left;
  2826. pDstBlt->nTopRect = g_oeState.rc.top;
  2827. pDstBlt->nWidth = g_oeState.rc.right - g_oeState.rc.left + 1;
  2828. pDstBlt->nHeight = g_oeState.rc.bottom - g_oeState.rc.top + 1;
  2829. pDstBlt->bRop = bRop;
  2830. OTRACE(("DstBlt: Order %08lx, Rect {%d, %d, %d, %d}",
  2831. pOrder,
  2832. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2833. g_oeState.rc.bottom));
  2834. }
  2835. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  2836. if (ROP3_IS_OPAQUE(bRop))
  2837. pOrder->OrderHeader.Common.fOrderFlags |= OF_SPOILER;
  2838. OEClipAndAddOrder(pOrder, NULL);
  2839. }
  2840. DC_EXIT_POINT:
  2841. if (!pOrder)
  2842. {
  2843. OTRACE(("PatBlt: Sending as screen data {%d, %d, %d, %d}",
  2844. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2845. g_oeState.rc.bottom));
  2846. OEClipAndAddScreenData(&g_oeState.rc);
  2847. }
  2848. NothingAtAll:
  2849. DebugExitVOID(OEAddBlt);
  2850. }
  2851. //
  2852. // DrvStretchBlt()
  2853. //
  2854. BOOL WINAPI DrvStretchBlt
  2855. (
  2856. HDC hdcDst,
  2857. int xDst,
  2858. int yDst,
  2859. int cxDst,
  2860. int cyDst,
  2861. HDC hdcSrc,
  2862. int xSrc,
  2863. int ySrc,
  2864. int cxSrc,
  2865. int cySrc,
  2866. DWORD rop
  2867. )
  2868. {
  2869. BOOL fWeCare;
  2870. BOOL fOutput;
  2871. DebugEntry(DrvStretchBlt);
  2872. OE_SHM_START_WRITING;
  2873. fWeCare = OEBeforeDDI(DDI_STRETCHBLT, hdcDst, 0);
  2874. fOutput = StretchBlt(hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, rop);
  2875. if (OEAfterDDI(DDI_STRETCHBLT, fWeCare, fOutput))
  2876. {
  2877. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  2878. g_oeState.rc.left = xDst;
  2879. g_oeState.rc.top = yDst;
  2880. g_oeState.rc.right = xDst + cxDst;
  2881. g_oeState.rc.bottom = yDst + cyDst;
  2882. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  2883. OTRACE(("StretchBlt: Sending as screen data {%d, %d, %d, %d}",
  2884. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  2885. g_oeState.rc.bottom));
  2886. OEClipAndAddScreenData(&g_oeState.rc);
  2887. }
  2888. OE_SHM_STOP_WRITING;
  2889. DebugExitBOOL(DrvStretchBlt, fOutput);
  2890. return(fOutput);
  2891. }
  2892. //
  2893. // TextOutA()
  2894. //
  2895. BOOL WINAPI DrvTextOutA
  2896. (
  2897. HDC hdcDst,
  2898. int xDst,
  2899. int yDst,
  2900. LPSTR lpszText,
  2901. int cchText
  2902. )
  2903. {
  2904. BOOL fWeCare;
  2905. BOOL fOutput;
  2906. DebugEntry(DrvTextOutA);
  2907. OE_SHM_START_WRITING;
  2908. fWeCare = OEBeforeDDI(DDI_TEXTOUTA, hdcDst, OESTATE_SDA_FONTCOMPLEX | OESTATE_CURPOS);
  2909. fOutput = TextOut(hdcDst, xDst, yDst, lpszText, cchText);
  2910. if (OEAfterDDI(DDI_TEXTOUTA, fWeCare, fOutput && cchText))
  2911. {
  2912. POINT ptStart = {xDst, yDst};
  2913. OEAddText(ptStart, 0, NULL, lpszText, cchText, NULL);
  2914. }
  2915. OE_SHM_STOP_WRITING;
  2916. DebugExitBOOL(DrvTextOutA, fOutput);
  2917. return(fOutput);
  2918. }
  2919. //
  2920. // DrvExtFloodFill()
  2921. //
  2922. // This just gets added as screen data. Too darned complicated to
  2923. // calculate the result.
  2924. //
  2925. BOOL WINAPI DrvExtFloodFill
  2926. (
  2927. HDC hdcDst,
  2928. int xDst,
  2929. int yDst,
  2930. COLORREF clrFill,
  2931. UINT uFillType
  2932. )
  2933. {
  2934. BOOL fWeCare;
  2935. BOOL fOutput;
  2936. DebugEntry(DrvExtFloodFill);
  2937. OE_SHM_START_WRITING;
  2938. //
  2939. // GDI's draw bounds has an off-by-one bug in ExtFloodFill and FloodFill
  2940. //
  2941. fWeCare = OEBeforeDDI(DDI_EXTFLOODFILL, hdcDst, OESTATE_SDA_DCB |
  2942. OESTATE_OFFBYONEHACK);
  2943. fOutput = ExtFloodFill(hdcDst, xDst, yDst, clrFill, uFillType);
  2944. OEAfterDDI(DDI_EXTFLOODFILL, fWeCare, fOutput);
  2945. OE_SHM_STOP_WRITING;
  2946. DebugExitBOOL(DrvExtFloodFill, fOutput);
  2947. return(fOutput);
  2948. }
  2949. //
  2950. // DrvFloodFill()
  2951. //
  2952. BOOL WINAPI DrvFloodFill
  2953. (
  2954. HDC hdcDst,
  2955. int xDst,
  2956. int yDst,
  2957. COLORREF clrFill
  2958. )
  2959. {
  2960. BOOL fWeCare;
  2961. BOOL fOutput;
  2962. DebugEntry(DrvFloodFill);
  2963. OE_SHM_START_WRITING;
  2964. //
  2965. // GDI's draw bounds has an off-by-one bug in ExtFloodFill and FloodFill
  2966. //
  2967. fWeCare = OEBeforeDDI(DDI_FLOODFILL, hdcDst, OESTATE_SDA_DCB |
  2968. OESTATE_OFFBYONEHACK);
  2969. fOutput = FloodFill(hdcDst, xDst, yDst, clrFill);
  2970. OEAfterDDI(DDI_FLOODFILL, fWeCare, fOutput);
  2971. OE_SHM_STOP_WRITING;
  2972. DebugExitBOOL(DrvFloodFill, fOutput);
  2973. return(fOutput);
  2974. }
  2975. //
  2976. // DrvExtTextOut()
  2977. //
  2978. BOOL WINAPI DrvExtTextOutW
  2979. (
  2980. HDC hdcDst,
  2981. int xDst,
  2982. int yDst,
  2983. UINT uOptions,
  2984. LPRECT lprcClip,
  2985. LPWSTR lpwszText,
  2986. UINT cchText,
  2987. LPINT lpdxCharSpacing
  2988. )
  2989. {
  2990. BOOL fWeCare;
  2991. BOOL fOutput;
  2992. UINT uFlags;
  2993. //
  2994. // NOTE:
  2995. // ExtTextOutW and TextOutW are only called on 32-bit app threads. So
  2996. // chewing up stack space isn't a problem.
  2997. //
  2998. UINT cchAnsi = 0;
  2999. char szAnsi[ORD_MAX_STRING_LEN_WITHOUT_DELTAS+1];
  3000. DebugEntry(DrvExtTextOutW);
  3001. OE_SHM_START_WRITING;
  3002. if ((cchText == 0) &&
  3003. SELECTOROF(lprcClip) &&
  3004. !IsBadReadPtr(lprcClip, sizeof(RECT)) &&
  3005. (uOptions & ETO_OPAQUE))
  3006. {
  3007. uFlags = 0;
  3008. }
  3009. else
  3010. {
  3011. //
  3012. // Is this order-able? It is if we can convert the unicode string
  3013. // to ansi then back to unicode, and end up where we started.
  3014. //
  3015. uFlags = OESTATE_SDA_DCB;
  3016. if (cchText &&
  3017. (cchText <= ORD_MAX_STRING_LEN_WITHOUT_DELTAS) &&
  3018. !IsBadReadPtr(lpwszText, cchText*sizeof(WCHAR)))
  3019. {
  3020. int cchUni;
  3021. //
  3022. // NOTE:
  3023. // UniToAnsi() returns ONE LESS than the # of chars converted
  3024. //
  3025. cchAnsi = UniToAnsi(lpwszText, szAnsi, cchText) + 1;
  3026. cchUni = AnsiToUni(szAnsi, cchAnsi, g_oeTempString, ORD_MAX_STRING_LEN_WITHOUT_DELTAS);
  3027. if (cchUni == cchText)
  3028. {
  3029. //
  3030. // Verify these strings are the same
  3031. //
  3032. UINT ich;
  3033. for (ich = 0; ich < cchText; ich++)
  3034. {
  3035. if (lpwszText[ich] != g_oeTempString[ich])
  3036. break;
  3037. }
  3038. if (ich == cchText)
  3039. {
  3040. //
  3041. // We made it to the end; everything matched.
  3042. //
  3043. uFlags = OESTATE_SDA_FONTCOMPLEX | OESTATE_CURPOS;
  3044. }
  3045. }
  3046. #ifdef DEBUG
  3047. if (uFlags == OESTATE_SDA_DCB)
  3048. {
  3049. WARNING_OUT(("Can't encode ExtTextOutW"));
  3050. }
  3051. #endif // DEBUG
  3052. }
  3053. }
  3054. fWeCare = OEBeforeDDI(DDI_EXTTEXTOUTW, hdcDst, uFlags);
  3055. fOutput = g_lpfnExtTextOutW(hdcDst, xDst, yDst, uOptions, lprcClip,
  3056. lpwszText, cchText, lpdxCharSpacing);
  3057. if (OEAfterDDI(DDI_EXTTEXTOUTW, fWeCare, fOutput))
  3058. {
  3059. //
  3060. // Is this a simple OPAQUE rect, or a textout call we can order?
  3061. // NOTE that OEAfterDDI() returns FALSE even if fOutput but we
  3062. // used DCBs to add as screen data.
  3063. //
  3064. if (uFlags & OESTATE_SDA_FONTCOMPLEX)
  3065. {
  3066. POINT ptStart = {xDst, yDst};
  3067. ASSERT(cchAnsi);
  3068. OEAddText(ptStart, uOptions, lprcClip, szAnsi, cchAnsi, lpdxCharSpacing);
  3069. }
  3070. else
  3071. {
  3072. OEAddOpaqueRect(lprcClip);
  3073. }
  3074. }
  3075. OE_SHM_STOP_WRITING;
  3076. DebugExitBOOL(DrvExtTextOutW, fOutput);
  3077. return(fOutput);
  3078. }
  3079. //
  3080. // DrvTextOutW()
  3081. //
  3082. BOOL WINAPI DrvTextOutW
  3083. (
  3084. HDC hdcDst,
  3085. int xDst,
  3086. int yDst,
  3087. LPWSTR lpwszText,
  3088. int cchText
  3089. )
  3090. {
  3091. BOOL fWeCare;
  3092. BOOL fOutput;
  3093. UINT uFlags;
  3094. //
  3095. // NOTE:
  3096. // ExtTextOutW and TextOutW are only called on 32-bit app threads. So
  3097. // chewing up stack space isn't a problem.
  3098. //
  3099. UINT cchAnsi = 0;
  3100. char szAnsi[ORD_MAX_STRING_LEN_WITHOUT_DELTAS+1];
  3101. DebugEntry(DrvTextOutW);
  3102. OE_SHM_START_WRITING;
  3103. //
  3104. // Is this order-able? It is if we can convert the unicode string to
  3105. // ansi then back to unicode, and end up where we started.
  3106. //
  3107. uFlags = OESTATE_SDA_DCB;
  3108. if (cchText &&
  3109. (cchText <= ORD_MAX_STRING_LEN_WITHOUT_DELTAS) &&
  3110. !IsBadReadPtr(lpwszText, cchText*sizeof(WCHAR)))
  3111. {
  3112. int cchUni;
  3113. //
  3114. // NOTE:
  3115. // UniToAnsi() returns one LESS than the # of chars converted
  3116. //
  3117. cchAnsi = UniToAnsi(lpwszText, szAnsi, cchText) + 1;
  3118. cchUni = AnsiToUni(szAnsi, cchAnsi, g_oeTempString, cchText);
  3119. if (cchUni == cchText)
  3120. {
  3121. //
  3122. // Verify these strings are the same
  3123. //
  3124. UINT ich;
  3125. for (ich = 0; ich < cchText; ich++)
  3126. {
  3127. if (lpwszText[ich] != g_oeTempString[ich])
  3128. break;
  3129. }
  3130. if (ich == cchText)
  3131. {
  3132. //
  3133. // We made it to the end; everything matched.
  3134. //
  3135. uFlags = OESTATE_SDA_FONTCOMPLEX | OESTATE_CURPOS;
  3136. }
  3137. #ifdef DEBUG
  3138. if (uFlags == OESTATE_SDA_DCB)
  3139. {
  3140. WARNING_OUT(("Can't encode TextOutW"));
  3141. }
  3142. #endif // DEBUG
  3143. }
  3144. }
  3145. fWeCare = OEBeforeDDI(DDI_TEXTOUTW, hdcDst, uFlags);
  3146. fOutput = g_lpfnTextOutW(hdcDst, xDst, yDst, lpwszText, cchText);
  3147. if (OEAfterDDI(DDI_TEXTOUTW, fWeCare, fOutput && cchText))
  3148. {
  3149. POINT ptStart = {xDst, yDst};
  3150. OEAddText(ptStart, 0, NULL, szAnsi, cchAnsi, NULL);
  3151. }
  3152. OE_SHM_STOP_WRITING;
  3153. DebugExitBOOL(DrvTextOutW, fOutput);
  3154. return(fOutput);
  3155. }
  3156. //
  3157. // OEAddOpaqueRect()
  3158. // Adds a simple opaque rect order, used for "erasing" ExtTextOutA/W
  3159. // calls. The most common examples are in Office.
  3160. //
  3161. void OEAddOpaqueRect(LPRECT lprcOpaque)
  3162. {
  3163. LPINT_ORDER pOrder;
  3164. LPOPAQUERECT_ORDER pOpaqueRect;
  3165. DebugEntry(OEAddOpaqueRect);
  3166. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  3167. g_oeState.rc = *lprcOpaque;
  3168. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  3169. pOrder = NULL;
  3170. if (OECheckOrder(ORD_OPAQUERECT, OECHECK_CLIPPING))
  3171. {
  3172. pOrder = OA_DDAllocOrderMem(sizeof(OPAQUERECT_ORDER), 0);
  3173. if (!pOrder)
  3174. DC_QUIT;
  3175. pOpaqueRect = (LPOPAQUERECT_ORDER)pOrder->abOrderData;
  3176. pOpaqueRect->type = LOWORD(ORD_OPAQUERECT);
  3177. pOpaqueRect->nLeftRect = g_oeState.rc.left;
  3178. pOpaqueRect->nTopRect = g_oeState.rc.top;
  3179. pOpaqueRect->nWidth = g_oeState.rc.right - g_oeState.rc.left + 1;
  3180. pOpaqueRect->nHeight = g_oeState.rc.bottom - g_oeState.rc.top + 1;
  3181. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL,
  3182. &pOpaqueRect->Color, FALSE);
  3183. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILER | OF_SPOILABLE;
  3184. OTRACE(("OpaqueRect: Order %08lx, Rect {%d, %d, %d, %d}, Color %08lx",
  3185. pOrder,
  3186. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  3187. g_oeState.rc.bottom, pOpaqueRect->Color));
  3188. OEClipAndAddOrder(pOrder, NULL);
  3189. }
  3190. DC_EXIT_POINT:
  3191. if (!pOrder)
  3192. {
  3193. OTRACE(("OpaqueRect: Sending as screen data {%d, %d, %d, %d}",
  3194. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  3195. g_oeState.rc.bottom));
  3196. OEClipAndAddScreenData(&g_oeState.rc);
  3197. }
  3198. DebugExitVOID(OEAddOpaqueRect);
  3199. }
  3200. //
  3201. // OEAddText()
  3202. // Big monster routine that handles TextOutA/ExtTextOutA
  3203. //
  3204. // In general, we care about:
  3205. // * Clip rect--if none, and no text, it's an OpaqueRect instead
  3206. // * The font
  3207. // * Whether it's too complicated to send as an order
  3208. // * If it needs a deltaX array
  3209. //
  3210. void OEAddText
  3211. (
  3212. POINT ptStart,
  3213. UINT uOptions,
  3214. LPRECT lprcClip,
  3215. LPSTR lpszText,
  3216. UINT cchText,
  3217. LPINT lpdxCharSpacing
  3218. )
  3219. {
  3220. RECT rcT;
  3221. int overhang;
  3222. int width;
  3223. UINT fOrderFlags;
  3224. int cchMax;
  3225. DWORD order;
  3226. LPINT_ORDER pOrder;
  3227. LPEXTTEXTOUT_ORDER pExtTextOut;
  3228. LPTEXTOUT_ORDER pTextOut;
  3229. LPCOMMON_TEXTORDER pCommon;
  3230. UINT fontHeight;
  3231. UINT fontWidth;
  3232. UINT fontWeight;
  3233. UINT fontFlags;
  3234. UINT fontIndex;
  3235. BOOL fSendDeltaX;
  3236. POINT ptT;
  3237. DebugEntry(OEAddText);
  3238. //
  3239. // NOTE:
  3240. // Do NOT convert ptStart. It is needed in logical form for several
  3241. // different things.
  3242. //
  3243. OEGetState(OESTATE_COORDS | OESTATE_FONT | OESTATE_REGION);
  3244. //
  3245. // We need to apply the same validation to the flags that GDI does.
  3246. // This bit massaging is for various app compatibility things.
  3247. //
  3248. if (uOptions & ~(ETO_CLIPPED | ETO_OPAQUE | ETO_GLYPH_INDEX | ETO_RTLREADING))
  3249. {
  3250. uOptions &= (ETO_CLIPPED | ETO_OPAQUE);
  3251. }
  3252. if (!(uOptions & (ETO_CLIPPED | ETO_OPAQUE)))
  3253. {
  3254. // No opaquing/clipping, no clip rect
  3255. lprcClip = NULL;
  3256. }
  3257. if (!SELECTOROF(lprcClip))
  3258. {
  3259. // No clip rect, no opaquing/clipping
  3260. uOptions &= ~(ETO_CLIPPED | ETO_OPAQUE);
  3261. }
  3262. pOrder = NULL;
  3263. fOrderFlags = OF_SPOILABLE;
  3264. //
  3265. // Calculate the real starting position of the text
  3266. //
  3267. if (g_oeState.tmAlign & TA_UPDATECP)
  3268. {
  3269. ASSERT(g_oeState.uFlags & OESTATE_CURPOS);
  3270. ptStart = g_oeState.ptCurPos;
  3271. }
  3272. overhang = OEGetStringExtent(lpszText, cchText, lpdxCharSpacing, &rcT);
  3273. width = rcT.right - overhang - rcT.left;
  3274. switch (g_oeState.tmAlign & (TA_CENTER | TA_LEFT | TA_RIGHT))
  3275. {
  3276. case TA_CENTER:
  3277. // The original x coord is the MIDPOINT
  3278. TRACE_OUT(("TextOut HORZ center"));
  3279. ptStart.x -= (width * g_oeState.ptPolarity.x / 2);
  3280. break;
  3281. case TA_RIGHT:
  3282. // The original x coord is the RIGHT SIDE
  3283. TRACE_OUT(("TextOut HORZ right"));
  3284. ptStart.x -= (width * g_oeState.ptPolarity.x);
  3285. break;
  3286. case TA_LEFT:
  3287. break;
  3288. }
  3289. switch (g_oeState.tmAlign & (TA_BASELINE | TA_BOTTOM | TA_TOP))
  3290. {
  3291. case TA_BASELINE:
  3292. // The original y coord is the BASELINE
  3293. TRACE_OUT(("TextOut VERT baseline"));
  3294. ptStart.y -= (g_oeState.tmFont.tmAscent * g_oeState.ptPolarity.y);
  3295. break;
  3296. case TA_BOTTOM:
  3297. // The original y coord is the BOTTOM SIDE
  3298. TRACE_OUT(("TextOut VERT bottom"));
  3299. ptStart.y -= ((rcT.bottom - rcT.top) * g_oeState.ptPolarity.y);
  3300. break;
  3301. case TA_TOP:
  3302. break;
  3303. }
  3304. //
  3305. // Calculate extent rect for order
  3306. //
  3307. if (uOptions & ETO_CLIPPED)
  3308. {
  3309. // Because of CopyRect() validation layer bug, do this directly
  3310. g_oeState.rc = *lprcClip;
  3311. if (uOptions & ETO_OPAQUE)
  3312. fOrderFlags |= OF_SPOILER;
  3313. }
  3314. else
  3315. {
  3316. g_oeState.rc.left = ptStart.x + (g_oeState.ptPolarity.x * rcT.left);
  3317. g_oeState.rc.top = ptStart.y + (g_oeState.ptPolarity.y * rcT.top);
  3318. g_oeState.rc.right = ptStart.x + (g_oeState.ptPolarity.x * rcT.right);
  3319. g_oeState.rc.bottom = ptStart.y + (g_oeState.ptPolarity.y * rcT.bottom);
  3320. if (uOptions & ETO_OPAQUE)
  3321. {
  3322. //
  3323. // Set the SPOILER flag in the order header. However, if the
  3324. // text extends outside the opaque rect, then the order isn't
  3325. // really opaque, and we have to clear this flag.
  3326. //
  3327. fOrderFlags |= OF_SPOILER;
  3328. if (g_oeState.ptPolarity.x == 1)
  3329. {
  3330. if ((g_oeState.rc.left < lprcClip->left) ||
  3331. (g_oeState.rc.right > lprcClip->right))
  3332. {
  3333. fOrderFlags &= ~OF_SPOILER;
  3334. }
  3335. g_oeState.rc.left = min(g_oeState.rc.left, lprcClip->left);
  3336. g_oeState.rc.right = max(g_oeState.rc.right, lprcClip->right);
  3337. }
  3338. else
  3339. {
  3340. if ((g_oeState.rc.left > lprcClip->left) ||
  3341. (g_oeState.rc.right < lprcClip->right))
  3342. {
  3343. fOrderFlags &= ~OF_SPOILER;
  3344. }
  3345. g_oeState.rc.left = max(g_oeState.rc.left, lprcClip->left);
  3346. g_oeState.rc.right = min(g_oeState.rc.right, lprcClip->right);
  3347. }
  3348. if (g_oeState.ptPolarity.y == 1)
  3349. {
  3350. if ((g_oeState.rc.top < lprcClip->top) ||
  3351. (g_oeState.rc.bottom > lprcClip->bottom))
  3352. {
  3353. fOrderFlags &= ~OF_SPOILER;
  3354. }
  3355. g_oeState.rc.top = min(g_oeState.rc.top, lprcClip->top);
  3356. g_oeState.rc.bottom = max(g_oeState.rc.bottom, lprcClip->bottom);
  3357. }
  3358. else
  3359. {
  3360. if ((g_oeState.rc.top > lprcClip->top) ||
  3361. (g_oeState.rc.bottom < lprcClip->bottom))
  3362. {
  3363. fOrderFlags &= ~OF_SPOILER;
  3364. }
  3365. g_oeState.rc.top = max(g_oeState.rc.top, lprcClip->top);
  3366. g_oeState.rc.bottom = min(g_oeState.rc.bottom, lprcClip->bottom);
  3367. }
  3368. //
  3369. // After all this, if the text is OPAQUE, then it is a spoiler
  3370. //
  3371. if (g_oeState.lpdc->DrawMode.bkMode == OPAQUE)
  3372. fOrderFlags |= OF_SPOILER;
  3373. }
  3374. }
  3375. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  3376. //
  3377. // Is the font supported?
  3378. //
  3379. if (!OECheckFontIsSupported(lpszText, cchText, &fontHeight,
  3380. &fontWidth, &fontWeight, &fontFlags, &fontIndex, &fSendDeltaX))
  3381. DC_QUIT;
  3382. //
  3383. // What type of order are we sending? And therefore what is the max
  3384. // # of chars we can encode?
  3385. //
  3386. if (fSendDeltaX || SELECTOROF(lpdxCharSpacing) || uOptions)
  3387. {
  3388. order = ORD_EXTTEXTOUT;
  3389. cchMax = ORD_MAX_STRING_LEN_WITH_DELTAS;
  3390. }
  3391. else
  3392. {
  3393. order = ORD_TEXTOUT;
  3394. cchMax = ORD_MAX_STRING_LEN_WITHOUT_DELTAS;
  3395. }
  3396. if (OECheckOrder(order, OECHECK_CLIPPING) &&
  3397. (cchText <= cchMax))
  3398. {
  3399. if (order == ORD_TEXTOUT)
  3400. {
  3401. pOrder = OA_DDAllocOrderMem((sizeof(TEXTOUT_ORDER)
  3402. - ORD_MAX_STRING_LEN_WITHOUT_DELTAS
  3403. + cchText),
  3404. 0);
  3405. if (!pOrder)
  3406. DC_QUIT;
  3407. pTextOut = (LPTEXTOUT_ORDER)pOrder->abOrderData;
  3408. pTextOut->type = LOWORD(order);
  3409. pCommon = &pTextOut->common;
  3410. }
  3411. else
  3412. {
  3413. //
  3414. // BOGUS LAURABU
  3415. // This allocates space for a deltax array whether or not one is
  3416. // needed.
  3417. //
  3418. pOrder = OA_DDAllocOrderMem((sizeof(EXTTEXTOUT_ORDER)
  3419. - ORD_MAX_STRING_LEN_WITHOUT_DELTAS
  3420. - (ORD_MAX_STRING_LEN_WITH_DELTAS * sizeof(TSHR_INT32))
  3421. + cchText
  3422. + (cchText * sizeof(TSHR_INT32))
  3423. + 4), 0); // 4 is for dword alignment padding
  3424. if (!pOrder)
  3425. DC_QUIT;
  3426. pExtTextOut = (LPEXTTEXTOUT_ORDER)pOrder->abOrderData;
  3427. pExtTextOut->type = LOWORD(order);
  3428. pCommon = &pExtTextOut->common;
  3429. }
  3430. //
  3431. // The order coords are TSHR_INT32s
  3432. //
  3433. ptT = ptStart;
  3434. OELPtoVirtual(g_oeState.hdc, &ptT, 1);
  3435. pCommon->nXStart = ptT.x;
  3436. pCommon->nYStart = ptT.y;
  3437. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL,
  3438. &pCommon->BackColor, FALSE);
  3439. OEConvertColor(g_oeState.lpdc->DrawMode.txColorL,
  3440. &pCommon->ForeColor, FALSE);
  3441. pCommon->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  3442. pCommon->CharExtra = g_oeState.lpdc->DrawMode.CharExtra;
  3443. pCommon->BreakExtra = g_oeState.lpdc->DrawMode.TBreakExtra;
  3444. pCommon->BreakCount = g_oeState.lpdc->DrawMode.BreakCount;
  3445. //
  3446. // Font details
  3447. //
  3448. pCommon->FontHeight = fontHeight;
  3449. pCommon->FontWidth = fontWidth;
  3450. pCommon->FontWeight = fontWeight;
  3451. pCommon->FontFlags = fontFlags;
  3452. pCommon->FontIndex = fontIndex;
  3453. if (order == ORD_TEXTOUT)
  3454. {
  3455. //
  3456. // Copy the string
  3457. //
  3458. pTextOut->variableString.len = cchText;
  3459. hmemcpy(pTextOut->variableString.string, lpszText, cchText);
  3460. }
  3461. else
  3462. {
  3463. pExtTextOut->fuOptions = uOptions & (ETO_OPAQUE | ETO_CLIPPED);
  3464. //
  3465. // If there is a clipping rect, set it up. Otherwise use the
  3466. // last ETO's clip rect. This makes OE2 encoding more efficient.
  3467. //
  3468. // NOTE that this is not the same as the drawing bounds--the
  3469. // text may extend outside the clip area.
  3470. //
  3471. if (SELECTOROF(lprcClip))
  3472. {
  3473. ASSERT(uOptions & (ETO_OPAQUE | ETO_CLIPPED));
  3474. rcT = *lprcClip;
  3475. OELRtoVirtual(g_oeState.hdc, &rcT, 1);
  3476. //
  3477. // This is a TSHR_RECT32, so we can't just copy
  3478. //
  3479. pExtTextOut->rectangle.left = rcT.left;
  3480. pExtTextOut->rectangle.top = rcT.top;
  3481. pExtTextOut->rectangle.right = rcT.right;
  3482. pExtTextOut->rectangle.bottom = rcT.bottom;
  3483. g_oeLastETORect = pExtTextOut->rectangle;
  3484. }
  3485. else
  3486. {
  3487. pExtTextOut->rectangle = g_oeLastETORect;
  3488. }
  3489. //
  3490. // Copy the string
  3491. //
  3492. pExtTextOut->variableString.len = cchText;
  3493. hmemcpy(pExtTextOut->variableString.string, lpszText, cchText);
  3494. //
  3495. // Copy the deltax array
  3496. //
  3497. // Although we have a defined fixed length structure for
  3498. // storing ExtTextOut orders, we don't send the full structure
  3499. // over the network as the text will only be, say, 10 chars while
  3500. // the structure contains room for 127.
  3501. //
  3502. // Hence we pack the structure now to remove all the blank data
  3503. // BUT we must maintain the natural alignment of the variables.
  3504. //
  3505. // So we know the length of the string which we can use to
  3506. // start the new delta structure at the next 4-byte boundary.
  3507. //
  3508. if (!OEAddDeltaX(pExtTextOut, lpszText, cchText, lpdxCharSpacing, fSendDeltaX, ptStart))
  3509. {
  3510. WARNING_OUT(("Couldn't add delta-x array to EXTTEXTOUT order"));
  3511. OA_DDFreeOrderMem(pOrder);
  3512. pOrder = NULL;
  3513. }
  3514. }
  3515. }
  3516. DC_EXIT_POINT:
  3517. if (pOrder)
  3518. {
  3519. //
  3520. // Call OEMaybeSimulateDeltaX to add a deltax array to the order
  3521. // if needed to correctly position the text. This happens when
  3522. // the font in use doesn't exist on other machines.
  3523. //
  3524. pOrder->OrderHeader.Common.fOrderFlags = fOrderFlags;
  3525. OTRACE(("TextOut: Type %08lx, Order %08lx, Rect {%d, %d, %d, %d}, Length %d",
  3526. pOrder, order,
  3527. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  3528. g_oeState.rc.bottom, cchText));
  3529. OEClipAndAddOrder(pOrder, NULL);
  3530. }
  3531. else
  3532. {
  3533. OTRACE(("OEAddText: Sending as screen data {%d, %d, %d, %d}",
  3534. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  3535. g_oeState.rc.bottom));
  3536. OEClipAndAddScreenData(&g_oeState.rc);
  3537. }
  3538. DebugExitVOID(OEAddText);
  3539. }
  3540. //
  3541. // OECheckFontIsSupported()
  3542. //
  3543. // We check if we can send this font. If we haven't received the negotiated
  3544. // packet caps yet, forget it.
  3545. //
  3546. // It returns:
  3547. // font height in points
  3548. // font ascender in points
  3549. // average font width in points
  3550. // font weight
  3551. // font style flags
  3552. // font handle
  3553. // do we need to send delta x
  3554. //
  3555. BOOL OECheckFontIsSupported
  3556. (
  3557. LPSTR lpszText,
  3558. UINT cchText,
  3559. LPUINT pFontHeight,
  3560. LPUINT pFontWidth,
  3561. LPUINT pFontWeight,
  3562. LPUINT pFontFlags,
  3563. LPUINT pFontIndex,
  3564. LPBOOL pSendDeltaX
  3565. )
  3566. {
  3567. BOOL fFontSupported;
  3568. UINT codePage;
  3569. UINT i;
  3570. UINT iLocal;
  3571. TSHR_UINT32 matchQuality;
  3572. UINT charWidthAdjustment;
  3573. int fontNameLen;
  3574. int compareResult;
  3575. POINT xformSize[2];
  3576. DebugEntry(OECheckFontIsSupported);
  3577. ASSERT(g_oeState.uFlags & OESTATE_FONT);
  3578. //
  3579. // Set up defaults
  3580. //
  3581. fFontSupported = FALSE;
  3582. *pSendDeltaX = FALSE;
  3583. //
  3584. // Do we have our list yet?
  3585. //
  3586. if (!g_oeTextEnabled)
  3587. DC_QUIT;
  3588. //
  3589. // Get the font facename
  3590. //
  3591. GetTextFace(g_oeState.hdc, LF_FACESIZE, g_oeState.logFont.lfFaceName);
  3592. //
  3593. // Search our Font Alias Table for the font name. If we find it,
  3594. // replace it with the aliased name.
  3595. //
  3596. charWidthAdjustment = 0;
  3597. for (i = 0; i < NUM_ALIAS_FONTS; i++)
  3598. {
  3599. if (!lstrcmp(g_oeState.logFont.lfFaceName,
  3600. g_oeFontAliasTable[i].pszOriginalFontName))
  3601. {
  3602. TRACE_OUT(("Alias name: %s -> %s", g_oeState.logFont.lfFaceName,
  3603. g_oeFontAliasTable[i].pszAliasFontName));
  3604. lstrcpy(g_oeState.logFont.lfFaceName,
  3605. g_oeFontAliasTable[i].pszAliasFontName);
  3606. charWidthAdjustment = g_oeFontAliasTable[i].charWidthAdjustment;
  3607. break;
  3608. }
  3609. }
  3610. //
  3611. // Get the current font code page
  3612. //
  3613. switch (g_oeState.tmFont.tmCharSet)
  3614. {
  3615. case ANSI_CHARSET:
  3616. codePage = NF_CP_WIN_ANSI;
  3617. break;
  3618. case OEM_CHARSET:
  3619. codePage = NF_CP_WIN_OEM;
  3620. break;
  3621. //
  3622. // LAURABU BUGBUG
  3623. // This wasn't in NM 2.0 -- does this cause problems in int'l?
  3624. //
  3625. case SYMBOL_CHARSET:
  3626. codePage = NF_CP_WIN_SYMBOL;
  3627. break;
  3628. default:
  3629. codePage = NF_CP_UNKNOWN;
  3630. break;
  3631. }
  3632. //
  3633. // We have a font name to match with those we know to be available
  3634. // remotely. Try to jump straight to the first entry in the local font
  3635. // table starting with the same char as this font. If this index slot
  3636. // is empty (has 0xFFFF in it), then bail out immediately.
  3637. //
  3638. for (iLocal = g_oeLocalFontIndex[(BYTE)g_oeState.logFont.lfFaceName[0]];
  3639. iLocal < g_oeNumFonts;
  3640. iLocal++)
  3641. {
  3642. //
  3643. // If this font isn't supported remotely, skip it.
  3644. //
  3645. matchQuality = g_poeLocalFonts[iLocal].SupportCode;
  3646. if (matchQuality == FH_SC_NO_MATCH)
  3647. {
  3648. continue;
  3649. }
  3650. //
  3651. // If this facename is different than ours, skip it. WE MUST
  3652. // CALL STRCMP(), because lstrcmp and strcmp() do different things
  3653. // for case. lstrcmp is lexi, and strcmp is alphi.
  3654. //
  3655. compareResult = MyStrcmp(g_poeLocalFonts[iLocal].Details.nfFaceName,
  3656. g_oeState.logFont.lfFaceName);
  3657. //
  3658. // If this font is alphabetically before the one we're searching for,
  3659. // skip it and continue looking.
  3660. //
  3661. if (compareResult < 0)
  3662. {
  3663. continue;
  3664. }
  3665. //
  3666. // If this font is alphabetically after the one we're searching for,
  3667. // then an entry for ours doesn't exist since the table is sorted
  3668. // alphabetically. Bail out.
  3669. //
  3670. if (compareResult > 0)
  3671. {
  3672. break;
  3673. }
  3674. //
  3675. // This looks promising, a font with the right name is supported on
  3676. // the remote system. Let's look at the metrics.
  3677. //
  3678. *pFontFlags = 0;
  3679. *pFontIndex = iLocal;
  3680. *pFontWeight = g_oeState.tmFont.tmWeight;
  3681. //
  3682. // Check for a fixed pitch font (NOT present means fixed)
  3683. //
  3684. if (!(g_oeState.tmFont.tmPitchAndFamily & FIXED_PITCH))
  3685. {
  3686. *pFontFlags |= NF_FIXED_PITCH;
  3687. }
  3688. //
  3689. // Check for a truetype font
  3690. //
  3691. if (g_oeState.tmFont.tmPitchAndFamily & TMPF_TRUETYPE)
  3692. {
  3693. *pFontFlags |= NF_TRUE_TYPE;
  3694. }
  3695. //
  3696. // Convert the font dimensions into pixel values. We use the
  3697. // average font width and the character height
  3698. //
  3699. xformSize[0].x = 0;
  3700. xformSize[0].y = 0;
  3701. xformSize[1].x = g_oeState.tmFont.tmAveCharWidth;
  3702. xformSize[1].y = g_oeState.tmFont.tmHeight -
  3703. g_oeState.tmFont.tmInternalLeading;
  3704. //
  3705. // For non-truetype simulated bold/italic fonts only:
  3706. //
  3707. // If the font is bold, the overhang field indicates the extra
  3708. // space a char takes up. Since our internal table contains the
  3709. // size of normal (non-bold) chars for simulated bold, we adjust
  3710. // for that here.
  3711. //
  3712. // If the font is italic, the overhang field indicates the number
  3713. // of pixels the char is skewed. We don't want to make adjustments
  3714. // in this case.
  3715. //
  3716. if (!(g_oeState.tmFont.tmPitchAndFamily & TMPF_TRUETYPE) &&
  3717. !g_oeState.tmFont.tmItalic)
  3718. {
  3719. xformSize[1].x -= g_oeState.tmFont.tmOverhang;
  3720. }
  3721. //
  3722. // LAURABU BOGUS
  3723. // For baseline text orders
  3724. //
  3725. // xformSize[2].x = 0;
  3726. // xformSize[2].y = g_oeState.tmFont.tmAscent;
  3727. //
  3728. LPtoDP(g_oeState.hdc, xformSize, 2);
  3729. //
  3730. // Calculate the font width & height
  3731. //
  3732. *pFontHeight = abs(xformSize[1].y - xformSize[0].y);
  3733. *pFontWidth = abs(xformSize[1].x - xformSize[0].x)
  3734. - charWidthAdjustment;
  3735. //
  3736. // LAURABU BOGUS
  3737. // For baseline text orders
  3738. //
  3739. // Get the offset to the start of the text cell
  3740. //
  3741. // *pFontAscender = abs(xformSize[2].y - xformSize[0].y);
  3742. //
  3743. //
  3744. // Check that we have a matching pair -- where we require that the
  3745. // fonts (i.e., the one being used by the app and the one we've
  3746. // matched with the remot system) are the same pitch and use the
  3747. // same technology.
  3748. //
  3749. if ((g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_FIXED_PITCH) !=
  3750. (*pFontFlags & NF_FIXED_PITCH))
  3751. {
  3752. OTRACE(("Fixed pitch mismatch"));
  3753. continue;
  3754. }
  3755. if ((g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_TRUE_TYPE) !=
  3756. (*pFontFlags & NF_TRUE_TYPE))
  3757. {
  3758. OTRACE(("True type mismatch"));
  3759. continue;
  3760. }
  3761. //
  3762. // We have a pair of fonts with the same attributes, both fixed or
  3763. // variable pitch, and using the same font technology.
  3764. //
  3765. // If the font is fixed pitch, then we need to check that the size
  3766. // matches also.
  3767. //
  3768. // If not, assume it's always matchable.
  3769. //
  3770. if (g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_FIXED_SIZE)
  3771. {
  3772. //
  3773. // The font is fixed size, so we must check that this
  3774. // particular size is matchable.
  3775. //
  3776. if ( (*pFontHeight != g_poeLocalFonts[iLocal].Details.nfAveHeight) ||
  3777. (*pFontWidth != g_poeLocalFonts[iLocal].Details.nfAveWidth) )
  3778. {
  3779. //
  3780. // The sizes differ, so we must fail this match.
  3781. //
  3782. TRACE_OUT(("Font size mismatch: want {%d, %d}, found {%d, %d}",
  3783. *pFontHeight, *pFontWidth, g_poeLocalFonts[iLocal].Details.nfAveHeight,
  3784. g_poeLocalFonts[iLocal].Details.nfAveWidth));
  3785. continue;
  3786. }
  3787. }
  3788. //
  3789. // Finally, we've got a matched pair.
  3790. //
  3791. fFontSupported = TRUE;
  3792. break;
  3793. }
  3794. if (!fFontSupported)
  3795. {
  3796. TRACE_OUT(("Couldn't find matching font for %s in table",
  3797. g_oeState.logFont.lfFaceName));
  3798. DC_QUIT;
  3799. }
  3800. //
  3801. // Build up the rest of the font flags. We've got pitch already.
  3802. //
  3803. if (g_oeState.tmFont.tmItalic)
  3804. {
  3805. *pFontFlags |= NF_ITALIC;
  3806. }
  3807. if (g_oeState.tmFont.tmUnderlined)
  3808. {
  3809. *pFontFlags |= NF_UNDERLINE;
  3810. }
  3811. if (g_oeState.tmFont.tmStruckOut)
  3812. {
  3813. *pFontFlags |= NF_STRIKEOUT;
  3814. }
  3815. //
  3816. // LAURABU BOGUS
  3817. // On NT, here's where simulated bold fonts are handled. Note that we,
  3818. // like NM 2.0, handle it above with the overhang.
  3819. //
  3820. #if 0
  3821. //
  3822. // It is possible to have a font made bold by Windows, i.e. the
  3823. // standard font definition is not bold, but windows manipulates the
  3824. // font data to create a bold effect. This is marked by the
  3825. // FO_SIM_BOLD flag.
  3826. //
  3827. // In this case we need to ensure that the font flags are marked as
  3828. // bold according to the weight.
  3829. //
  3830. if ( ((pfo->flFontType & FO_SIM_BOLD) != 0) &&
  3831. ( pFontMetrics->usWinWeight < FW_BOLD) )
  3832. {
  3833. TRACE_OUT(( "Upgrading weight for a bold font"));
  3834. *pFontWeight = FW_BOLD;
  3835. }
  3836. #endif
  3837. //
  3838. // Should we check the chars in the string itself? Use matchQuality
  3839. // to decide.
  3840. //
  3841. // If the font is an exact match, or if it's an approx match for its
  3842. // entire range (0x00 to 0xFF), then send it happily. If not, only
  3843. // send chars within the range 0x20-0x7F (real ASCII)
  3844. //
  3845. if (codePage != g_poeLocalFonts[iLocal].Details.nfCodePage)
  3846. {
  3847. TRACE_OUT(( "Using different CP: downgrade to APPROX_ASC"));
  3848. matchQuality = FH_SC_APPROX_ASCII_MATCH;
  3849. }
  3850. //
  3851. // If we don't have an exact match, check the individual characters.
  3852. //
  3853. if ( (matchQuality != FH_SC_EXACT_MATCH ) &&
  3854. (matchQuality != FH_SC_APPROX_MATCH) )
  3855. {
  3856. //
  3857. // LAURABU BOGUS!
  3858. // NT does approximate matching only if the font supports the
  3859. // ANSI charset. NM 2.0 never did this, so we won't either.
  3860. //
  3861. //
  3862. // This font is not a good match across its entire range. Check
  3863. // that all chars are within the desired range.
  3864. //
  3865. for (i = 0; i < cchText; i++)
  3866. {
  3867. if ( (lpszText[i] == 0) ||
  3868. ( (lpszText[i] >= NF_ASCII_FIRST) &&
  3869. (lpszText[i] <= NF_ASCII_LAST) ) )
  3870. {
  3871. continue;
  3872. }
  3873. //
  3874. // Can only get here by finding a char outside our acceptable
  3875. // range.
  3876. //
  3877. OTRACE(("Found non ASCII char %c", lpszText[i]));
  3878. fFontSupported = FALSE;
  3879. DC_QUIT;
  3880. }
  3881. if (fFontSupported)
  3882. {
  3883. //
  3884. // We still have to check that this is ANSI text. Consider a
  3885. // string written in symbol font where all the chars in
  3886. // the string are in the range 0x20-0x7F, but none of them
  3887. // are ASCII.
  3888. //
  3889. OemToAnsiBuff(lpszText, g_oeAnsiString, cchText);
  3890. //
  3891. // BOGUS LAURABU
  3892. // This is our own inline MEMCMP to avoid pulling in the CRT.
  3893. // If any other place needs it, we should make this a function
  3894. //
  3895. for (i = 0; i < cchText; i++)
  3896. {
  3897. if (lpszText[i] != g_oeAnsiString[i])
  3898. {
  3899. OTRACE(("Found non ANSI char %c", lpszText[i]));
  3900. fFontSupported = FALSE;
  3901. DC_QUIT;
  3902. }
  3903. }
  3904. }
  3905. }
  3906. //
  3907. // We have a valid font. Now sort out deltaX issues
  3908. //
  3909. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_ALWAYS))
  3910. {
  3911. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_SOMETIMES))
  3912. {
  3913. //
  3914. // CAPS_FONT_NEED_X_SOMETIMES and CAPS_FONT_NEED_X_ALWAYS are
  3915. // both not set so we can exit now. (We do not need a delta X
  3916. // array).
  3917. //
  3918. TRACE_OUT(( "Capabilities eliminated delta X"));
  3919. DC_QUIT;
  3920. }
  3921. //
  3922. // CAPS_FONT_NEED_X_SOMETIMES is set and CAPS_FONT_NEED_X_ALWAYS is
  3923. // not set. In this case whether we need a delta X is determined
  3924. // by whether the font is an exact match or an approximate match
  3925. // (because of either approximation of name, signature, or aspect
  3926. // ratio). We can only find this out after we have extracted the
  3927. // font handle from the existing order.
  3928. //
  3929. }
  3930. //
  3931. // If the string is a single character (or less) then we can just
  3932. // return.
  3933. //
  3934. if (cchText <= 1)
  3935. {
  3936. TRACE_OUT(( "String only %u long", cchText));
  3937. DC_QUIT;
  3938. }
  3939. //
  3940. // Capabilities allow us to ignore delta X position if we have an exact
  3941. // match.
  3942. //
  3943. if (matchQuality & FH_SC_EXACT)
  3944. {
  3945. //
  3946. // Exit immediately, providing that there is no override to always
  3947. // send increments.
  3948. //
  3949. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_ALWAYS))
  3950. {
  3951. TRACE_OUT(( "Font has exact match"));
  3952. DC_QUIT;
  3953. }
  3954. }
  3955. //
  3956. // We must send a deltaX array
  3957. //
  3958. *pSendDeltaX = TRUE;
  3959. DC_EXIT_POINT:
  3960. DebugExitDWORD(OECheckFontIsSupported, fFontSupported);
  3961. return(fFontSupported);
  3962. }
  3963. //
  3964. // OEAddDeltaX()
  3965. //
  3966. // This fills in the allocated deltaX array if one is needed, either because
  3967. // the app passed one in ExtTextOut, or we need to simulate a font that
  3968. // isn't available remotely.
  3969. //
  3970. BOOL OEAddDeltaX
  3971. (
  3972. LPEXTTEXTOUT_ORDER pExtTextOut,
  3973. LPSTR lpszText,
  3974. UINT cchText,
  3975. LPINT lpdxCharSpacing,
  3976. BOOL fDeltaX,
  3977. POINT ptStart
  3978. )
  3979. {
  3980. BOOL fSuccess;
  3981. LPBYTE lpVariable;
  3982. LPVARIABLE_DELTAX lpDeltaPos;
  3983. UINT i;
  3984. int charWidth;
  3985. int xLastLP;
  3986. int xLastDP;
  3987. DebugEntry(OEAddDeltaX);
  3988. lpVariable = ((LPBYTE)&pExtTextOut->variableString) +
  3989. sizeof(pExtTextOut->variableString.len) + cchText;
  3990. lpDeltaPos = (LPVARIABLE_DELTAX)DC_ROUND_UP_4((DWORD)lpVariable);
  3991. fSuccess = FALSE;
  3992. if (SELECTOROF(lpdxCharSpacing))
  3993. {
  3994. //
  3995. // We must translate the LPDX increments into device units.
  3996. // We have to do this a single point at a time to preserve
  3997. // accuracy and because the order field isn't the same size.
  3998. //
  3999. // We preserve accuracy by calculating the position of the
  4000. // point in the current coords, and converting this before
  4001. // subtracting the original point to get the delta.
  4002. // Otherwise, we'd hit rounding errors very often. 4 chars
  4003. // is the limit in TWIPs e.g.
  4004. //
  4005. lpDeltaPos->len = cchText * sizeof(TSHR_INT32);
  4006. xLastLP = ptStart.x;
  4007. ptStart.y = 0;
  4008. LPtoDP(g_oeState.hdc, &ptStart, 1);
  4009. xLastDP = ptStart.x;
  4010. for (i = 0; i < cchText; i++)
  4011. {
  4012. xLastLP += lpdxCharSpacing[i];
  4013. ptStart.x = xLastLP;
  4014. ptStart.y = 0;
  4015. LPtoDP(g_oeState.hdc, &ptStart, 1);
  4016. lpDeltaPos->deltaX[i] = ptStart.x - xLastDP;
  4017. xLastDP = ptStart.x;
  4018. }
  4019. //
  4020. // Remember we have a deltax array
  4021. //
  4022. pExtTextOut->fuOptions |= ETO_LPDX;
  4023. fSuccess = TRUE;
  4024. }
  4025. else if (fDeltaX)
  4026. {
  4027. //
  4028. // Simulate deltax.
  4029. //
  4030. lpDeltaPos->len = cchText * sizeof(TSHR_INT32);
  4031. //
  4032. // Is this the same font as last time? If so, we have the
  4033. // generated character width table cached.
  4034. //
  4035. // NOTE that when the capabilities chage, we clear the cache to
  4036. // avoid matching a font based on a stale index. And when starting
  4037. // to share.
  4038. //
  4039. if ((g_oeFhLast.fontIndex != pExtTextOut->common.FontIndex) ||
  4040. (g_oeFhLast.fontHeight != pExtTextOut->common.FontHeight) ||
  4041. (g_oeFhLast.fontWidth != pExtTextOut->common.FontWidth) ||
  4042. (g_oeFhLast.fontWeight != pExtTextOut->common.FontWeight) ||
  4043. (g_oeFhLast.fontFlags != pExtTextOut->common.FontFlags))
  4044. {
  4045. LPLOCALFONT lpFont;
  4046. HFONT hFontSim;
  4047. HFONT hFontOld;
  4048. TEXTMETRIC tmNew;
  4049. int width;
  4050. ABC abc;
  4051. BYTE italic;
  4052. BYTE underline;
  4053. BYTE strikeout;
  4054. BYTE pitch;
  4055. BYTE charset;
  4056. BYTE precis;
  4057. TSHR_UINT32 FontFlags;
  4058. //
  4059. // Generate a new table and cache the info
  4060. //
  4061. // We can not use the ACTUAL font selected in. We must
  4062. // create a new logical font from our table info.
  4063. //
  4064. ASSERT(g_poeLocalFonts);
  4065. lpFont = g_poeLocalFonts + pExtTextOut->common.FontIndex;
  4066. FontFlags = pExtTextOut->common.FontFlags;
  4067. //
  4068. // What are the logical attributes of this desired font?
  4069. //
  4070. italic = (BYTE)(FontFlags & NF_ITALIC);
  4071. underline = (BYTE)(FontFlags & NF_UNDERLINE);
  4072. strikeout = (BYTE)(FontFlags & NF_STRIKEOUT);
  4073. if (FontFlags & NF_FIXED_PITCH)
  4074. {
  4075. pitch = FF_DONTCARE | FIXED_PITCH;
  4076. }
  4077. else
  4078. {
  4079. pitch = FF_DONTCARE | VARIABLE_PITCH;
  4080. }
  4081. //
  4082. // Is this a TrueType font? The windows Font Mapper biases
  4083. // towards non-TrueType fonts.
  4084. //
  4085. if (FontFlags & NF_TRUE_TYPE)
  4086. {
  4087. pitch |= TMPF_TRUETYPE;
  4088. precis = OUT_TT_ONLY_PRECIS;
  4089. }
  4090. else
  4091. {
  4092. precis = OUT_RASTER_PRECIS;
  4093. }
  4094. //
  4095. // The given height is the char height, not the cell height.
  4096. // So pass it as a negative value below...
  4097. //
  4098. //
  4099. // Use the codepage (misleadingly named) to figure out the
  4100. // charset to ask for.
  4101. //
  4102. if (lpFont->Details.nfCodePage == NF_CP_WIN_ANSI)
  4103. {
  4104. charset = ANSI_CHARSET;
  4105. }
  4106. else if (lpFont->Details.nfCodePage == NF_CP_WIN_OEM)
  4107. {
  4108. charset = OEM_CHARSET;
  4109. }
  4110. else if (lpFont->Details.nfCodePage == NF_CP_WIN_SYMBOL)
  4111. {
  4112. charset = SYMBOL_CHARSET;
  4113. }
  4114. else
  4115. {
  4116. charset = DEFAULT_CHARSET;
  4117. }
  4118. hFontSim = CreateFont(-(int)pExtTextOut->common.FontHeight,
  4119. (int)pExtTextOut->common.FontWidth, 0, 0,
  4120. (int)pExtTextOut->common.FontWeight, italic, underline,
  4121. strikeout, charset, precis, CLIP_DEFAULT_PRECIS,
  4122. DEFAULT_QUALITY, pitch, (LPSTR)lpFont->Details.nfFaceName);
  4123. if (!hFontSim)
  4124. {
  4125. ERROR_OUT(("Couldn't create simulated font for metrics"));
  4126. DC_QUIT;
  4127. }
  4128. hFontOld = SelectFont(g_osiScreenDC, hFontSim);
  4129. if (!hFontOld)
  4130. {
  4131. ERROR_OUT(("Couldn't select simulated font for metrics"));
  4132. DeleteFont(hFontSim);
  4133. DC_QUIT;
  4134. }
  4135. //
  4136. // Get the character dimensions
  4137. //
  4138. GetTextMetrics(g_osiScreenDC, &tmNew);
  4139. for (i = 0; i < 256; i++)
  4140. {
  4141. if (tmNew.tmPitchAndFamily & TMPF_TRUETYPE)
  4142. {
  4143. //
  4144. // Use ABC spacing for truetype
  4145. //
  4146. GetCharABCWidths(g_osiScreenDC, i, i, &abc);
  4147. width = abc.abcA + abc.abcB + abc.abcC;
  4148. }
  4149. else if (!(tmNew.tmPitchAndFamily & FIXED_PITCH))
  4150. {
  4151. //
  4152. // Note that the name of FIXED_PITCH is not what you'd
  4153. // expect, its ABSENCE means it's fixed.
  4154. //
  4155. // In any case, for fixed pitch fonts, each char is the
  4156. // same size.
  4157. //
  4158. width = tmNew.tmAveCharWidth - tmNew.tmOverhang;
  4159. }
  4160. else
  4161. {
  4162. //
  4163. // Query the width of the char
  4164. //
  4165. GetCharWidth(g_osiScreenDC, i, i, &width);
  4166. width -= tmNew.tmOverhang;
  4167. }
  4168. g_oeFhLast.charWidths[i] = width;
  4169. }
  4170. //
  4171. // We've successfully generated the width info for this font,
  4172. // update our cache.
  4173. //
  4174. g_oeFhLast.fontIndex = pExtTextOut->common.FontIndex;
  4175. g_oeFhLast.fontHeight = pExtTextOut->common.FontHeight;
  4176. g_oeFhLast.fontWidth = pExtTextOut->common.FontWidth;
  4177. g_oeFhLast.fontWeight = pExtTextOut->common.FontWeight;
  4178. g_oeFhLast.fontFlags = pExtTextOut->common.FontFlags;
  4179. //
  4180. // Select back in old font and delete new one
  4181. //
  4182. SelectFont(g_osiScreenDC, hFontOld);
  4183. DeleteFont(hFontSim);
  4184. }
  4185. //
  4186. // Now calculate the width of each character in the string.
  4187. // This includes the last char because it is needed to correctly
  4188. // define the extent of the string.
  4189. //
  4190. for (i = 0; i < cchText; i++)
  4191. {
  4192. //
  4193. // The width is that in the width table for the current char.
  4194. //
  4195. lpDeltaPos->deltaX[i] = g_oeFhLast.charWidths[lpszText[i]];
  4196. }
  4197. //
  4198. // Remember we have a deltax array
  4199. //
  4200. pExtTextOut->fuOptions |= ETO_LPDX;
  4201. fSuccess = TRUE;
  4202. }
  4203. else
  4204. {
  4205. //
  4206. // No deltax array
  4207. //
  4208. lpDeltaPos->len = 0;
  4209. fSuccess = TRUE;
  4210. }
  4211. DC_EXIT_POINT:
  4212. DebugExitBOOL(OEAddDeltaX, fSuccess);
  4213. return(fSuccess);
  4214. }
  4215. //
  4216. // OEGetStringExtent()
  4217. //
  4218. int OEGetStringExtent
  4219. (
  4220. LPSTR lpszText,
  4221. UINT cchText,
  4222. LPINT lpdxCharSpacing,
  4223. LPRECT lprcExtent
  4224. )
  4225. {
  4226. DWORD textExtent;
  4227. UINT i;
  4228. int thisX;
  4229. int minX;
  4230. int maxX;
  4231. ABC abcSpace;
  4232. int overhang = 0;
  4233. DebugEntry(OEGetStringExtent);
  4234. ASSERT(g_oeState.uFlags & OESTATE_FONT);
  4235. ASSERT(g_oeState.uFlags & OESTATE_COORDS);
  4236. //
  4237. // With no characters, return a NULL rect
  4238. //
  4239. if (cchText == 0)
  4240. {
  4241. lprcExtent->left = 1;
  4242. lprcExtent->top = 0;
  4243. lprcExtent->right = 0;
  4244. lprcExtent->bottom = 0;
  4245. }
  4246. else if (!SELECTOROF(lpdxCharSpacing))
  4247. {
  4248. //
  4249. // Get the simple text extent from GDI
  4250. //
  4251. textExtent = GetTextExtent(g_oeState.hdc, lpszText, cchText);
  4252. lprcExtent->left = 0;
  4253. lprcExtent->top = 0;
  4254. lprcExtent->right = LOWORD(textExtent);
  4255. lprcExtent->bottom = HIWORD(textExtent);
  4256. //
  4257. // We now have the the advance distance for the string. However,
  4258. // some fonts like TrueType with C widths, or Italic, may extend
  4259. // beyond this. Add in extra space here if necessary
  4260. //
  4261. if (g_oeState.tmFont.tmPitchAndFamily & TMPF_TRUETYPE)
  4262. {
  4263. //
  4264. // Get the A-B-C widths of the last character
  4265. //
  4266. GetCharABCWidths(g_oeState.hdc, lpszText[cchText-1],
  4267. lpszText[cchText-1], &abcSpace);
  4268. //
  4269. // Add on the C width (the right side extra) of the last char
  4270. //
  4271. overhang = abcSpace.abcC;
  4272. }
  4273. else
  4274. {
  4275. //
  4276. // Use global overhang, this is an old font (like simulated Italic)
  4277. //
  4278. overhang = g_oeState.tmFont.tmOverhang;
  4279. }
  4280. lprcExtent->right += overhang;
  4281. }
  4282. else
  4283. {
  4284. //
  4285. // Delta positions were given. In this case, the text extent is
  4286. // the sum of the delta values + the width of the last char
  4287. //
  4288. // Get the dimensions of the chars one by one, starting with 1st char
  4289. textExtent = GetTextExtent(g_oeState.hdc, lpszText, 1);
  4290. thisX = 0;
  4291. minX = 0;
  4292. maxX = LOWORD(textExtent);
  4293. for (i = 1; i < cchText; i++)
  4294. {
  4295. thisX += g_oeState.ptPolarity.x * lpdxCharSpacing[i-1];
  4296. textExtent = GetTextExtent(g_oeState.hdc, lpszText+i, 1);
  4297. minX = min(minX, thisX);
  4298. maxX = max(maxX, thisX + (int)LOWORD(textExtent));
  4299. }
  4300. thisX += g_oeState.ptPolarity.x * lpdxCharSpacing[cchText-1];
  4301. maxX = max(maxX, thisX);
  4302. lprcExtent->left = minX;
  4303. lprcExtent->top = 0;
  4304. lprcExtent->right = maxX;
  4305. lprcExtent->bottom = HIWORD(textExtent);
  4306. }
  4307. DebugExitDWORD(OEGetStringExtent, (DWORD)(LONG)overhang);
  4308. return(overhang);
  4309. }
  4310. //
  4311. // DrvFillPath()
  4312. //
  4313. BOOL WINAPI DrvFillPath
  4314. (
  4315. HDC hdcDst
  4316. )
  4317. {
  4318. BOOL fWeCare;
  4319. BOOL fOutput;
  4320. DebugEntry(DrvFillPath);
  4321. OE_SHM_START_WRITING;
  4322. //
  4323. // The Path() apis don't set the drawing bounds. We assume the whole
  4324. // screen (device coords) instead.
  4325. //
  4326. // NOTE that NM 2.0 had a bug--it didn't account for the virtual
  4327. // screen origin when setting up the rect to accum as screen data.
  4328. // It just passed (0, 0, 32765, 32765) in.
  4329. //
  4330. fWeCare = OEBeforeDDI(DDI_FILLPATH, hdcDst, OESTATE_SDA_SCREEN);
  4331. fOutput = FillPath(hdcDst);
  4332. OEAfterDDI(DDI_FILLPATH, fWeCare, fOutput);
  4333. OE_SHM_STOP_WRITING;
  4334. DebugExitBOOL(DrvFillPath, fOutput);
  4335. return(fOutput);
  4336. }
  4337. //
  4338. // DrvStrokeAndFillPath()
  4339. //
  4340. BOOL WINAPI DrvStrokeAndFillPath
  4341. (
  4342. HDC hdcDst
  4343. )
  4344. {
  4345. BOOL fWeCare;
  4346. BOOL fOutput;
  4347. DebugEntry(DrvStrokeAndFillPath);
  4348. OE_SHM_START_WRITING;
  4349. //
  4350. // The Path() apis don't set the drawing bounds. We assume the whole
  4351. // screen (device coords) instead.
  4352. //
  4353. // NOTE that NM 2.0 had a bug--it didn't account for the virtual
  4354. // screen origin when setting up the rect to accum as screen data.
  4355. // It just passed (0, 0, 32765, 32765) in.
  4356. //
  4357. fWeCare = OEBeforeDDI(DDI_STROKEANDFILLPATH, hdcDst, OESTATE_SDA_SCREEN);
  4358. fOutput = StrokeAndFillPath(hdcDst);
  4359. OEAfterDDI(DDI_STROKEANDFILLPATH, fWeCare, fOutput);
  4360. OE_SHM_STOP_WRITING;
  4361. DebugExitBOOL(DrvStrokeAndFillPath, fOutput);
  4362. return(fOutput);
  4363. }
  4364. //
  4365. // DrvStrokePath()
  4366. //
  4367. BOOL WINAPI DrvStrokePath
  4368. (
  4369. HDC hdcDst
  4370. )
  4371. {
  4372. BOOL fWeCare;
  4373. BOOL fOutput;
  4374. DebugEntry(DrvStrokePath);
  4375. OE_SHM_START_WRITING;
  4376. //
  4377. // The Path() apis don't set the drawing bounds. We assume the whole
  4378. // screen (device coords) instead.
  4379. //
  4380. // NOTE that NM 2.0 had a bug--it didn't account for the virtual
  4381. // screen origin when setting up the rect to accum as screen data.
  4382. // It just passed (0, 0, 32765, 32765) in.
  4383. //
  4384. fWeCare = OEBeforeDDI(DDI_STROKEPATH, hdcDst, OESTATE_SDA_SCREEN);
  4385. fOutput = StrokePath(hdcDst);
  4386. OEAfterDDI(DDI_STROKEPATH, fWeCare, fOutput);
  4387. OE_SHM_STOP_WRITING;
  4388. DebugExitBOOL(DrvStrokePath, fOutput);
  4389. return(fOutput);
  4390. }
  4391. //
  4392. // DrvFillRgn()
  4393. //
  4394. BOOL WINAPI DrvFillRgn
  4395. (
  4396. HDC hdcDst,
  4397. HRGN hrgnFill,
  4398. HBRUSH hbrFill
  4399. )
  4400. {
  4401. BOOL fWeCare;
  4402. BOOL fOutput;
  4403. DebugEntry(DrvFillRgn);
  4404. OE_SHM_START_WRITING;
  4405. //
  4406. // We can't use Rgn apis if the map mode isn't MM_TEXT. So we use DCBs
  4407. // instead.
  4408. //
  4409. fWeCare = OEBeforeDDI(DDI_FILLRGN, hdcDst, 0);
  4410. fOutput = FillRgn(hdcDst, hrgnFill, hbrFill);
  4411. if (OEAfterDDI(DDI_FILLRGN, fWeCare, fOutput))
  4412. {
  4413. //
  4414. // NOTE that OEAfterDDI() returns FALSE even if fOutput if we used
  4415. // DCBs to send as screen data. In other words, OEAfterDDI() returns
  4416. // TRUE IFF output happened into a DC we care about and it needs
  4417. // processing still.
  4418. //
  4419. OEAddRgnPaint(hrgnFill, hbrFill, g_oeState.lpdc->DrawMode.Rop2);
  4420. }
  4421. OE_SHM_STOP_WRITING;
  4422. DebugExitBOOL(DrvFillRgn, fOutput);
  4423. return(fOutput);
  4424. }
  4425. //
  4426. // OETwoWayRopToThree()
  4427. // Gets the 3-way ROP equivalent of a 2-way ROP.
  4428. //
  4429. BOOL OETwoWayRopToThree
  4430. (
  4431. int rop2,
  4432. LPDWORD lpdwRop3
  4433. )
  4434. {
  4435. BOOL fConverted = TRUE;
  4436. DebugEntry(OETwoWayRopToThree);
  4437. switch (rop2)
  4438. {
  4439. case R2_BLACK:
  4440. *lpdwRop3 = BLACKNESS;
  4441. break;
  4442. case R2_NOT:
  4443. *lpdwRop3 = DSTINVERT;
  4444. break;
  4445. case R2_XORPEN:
  4446. *lpdwRop3 = PATINVERT;
  4447. break;
  4448. case R2_COPYPEN:
  4449. *lpdwRop3 = PATCOPY;
  4450. break;
  4451. case R2_WHITE:
  4452. *lpdwRop3 = WHITENESS;
  4453. break;
  4454. default:
  4455. fConverted = FALSE;
  4456. break;
  4457. }
  4458. DebugExitBOOL(OETwoWayRopToThree, fConverted);
  4459. return(fConverted);
  4460. }
  4461. //
  4462. // OEAddRgnPaint()
  4463. // This will set up a modified region (vis intersect param) and brush, and
  4464. // if possible will fake a PatBlt. If not, screen data.
  4465. //
  4466. // NOTE:
  4467. // (1) hrgnPaint is in DC coords
  4468. // (2) GetClipRgn() returns a region in screen coords
  4469. // (3) SelectClipRgn() takes a region in DC coords
  4470. //
  4471. void OEAddRgnPaint
  4472. (
  4473. HRGN hrgnPaint,
  4474. HBRUSH hbrPaint,
  4475. UINT rop2
  4476. )
  4477. {
  4478. BOOL fScreenData = TRUE;
  4479. HRGN hrgnClip;
  4480. HRGN hrgnNewClip;
  4481. HRGN hrgnOldClip;
  4482. POINT ptXlation;
  4483. DWORD dwRop3;
  4484. DebugEntry(OEAddRgnPaint);
  4485. //
  4486. // Get the original visrgn.
  4487. //
  4488. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  4489. //
  4490. // Get the bounding box and convert the bounding box to our coords.
  4491. //
  4492. if (GetRgnBox(hrgnPaint, &g_oeState.rc) <= NULLREGION)
  4493. {
  4494. // Nothing to do.
  4495. TRACE_OUT(("OEAddRgnPaint: empty region"));
  4496. goto DC_EMPTY_REGION;
  4497. }
  4498. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  4499. //
  4500. // We can't continue if we aren't MM_TEXT--clip rgn APIs only work
  4501. // in that mode. So send as screen data instead.
  4502. //
  4503. if (GetMapMode(g_oeState.hdc) != MM_TEXT)
  4504. {
  4505. TRACE_OUT(("OEAddRgnPaint: map mode not MM_TEXT, send as screen data"));
  4506. DC_QUIT;
  4507. }
  4508. //
  4509. // Save a copy of the current cliprgn
  4510. //
  4511. hrgnNewClip = CreateRectRgn(0, 0, 0, 0);
  4512. if (!hrgnNewClip)
  4513. DC_QUIT;
  4514. //
  4515. // Get app LP xlation factor; SelectClipRgn() expects DP units
  4516. //
  4517. ptXlation.x = 0;
  4518. ptXlation.y = 0;
  4519. DPtoLP(g_oeState.hdc, &ptXlation, 1);
  4520. hrgnOldClip = NULL;
  4521. if (hrgnClip = GetClipRgn(g_oeState.hdc))
  4522. {
  4523. hrgnOldClip = CreateRectRgn(0, 0, 0, 0);
  4524. if (!hrgnOldClip)
  4525. {
  4526. DeleteRgn(hrgnNewClip);
  4527. DC_QUIT;
  4528. }
  4529. //
  4530. // This is in screen coords. Convert to DC coords
  4531. // * Subtract the DC origin
  4532. // * Get the DP-LP xlation and subtract
  4533. //
  4534. CopyRgn(hrgnOldClip, hrgnClip);
  4535. OffsetRgn(hrgnOldClip,
  4536. -g_oeState.ptDCOrg.x + ptXlation.x,
  4537. -g_oeState.ptDCOrg.y + ptXlation.y);
  4538. //
  4539. // Intersect the current clip with the paint region (already in
  4540. // DC coords)
  4541. //
  4542. IntersectRgn(hrgnNewClip, hrgnOldClip, hrgnPaint);
  4543. //
  4544. // Convert the old LP region back to DP units to select back in
  4545. // when done.
  4546. //
  4547. OffsetRgn(hrgnOldClip, -ptXlation.x, -ptXlation.y);
  4548. }
  4549. else
  4550. {
  4551. CopyRgn(hrgnNewClip, hrgnPaint);
  4552. }
  4553. //
  4554. // Convert LP paint region to DP clip region
  4555. //
  4556. OffsetRgn(hrgnNewClip, -ptXlation.x, -ptXlation.y);
  4557. //
  4558. // Select in new clip region (expected to be in device coords).
  4559. //
  4560. SelectClipRgn(g_oeState.hdc, hrgnNewClip);
  4561. DeleteRgn(hrgnNewClip);
  4562. //
  4563. // Reget the RAO (intersect of vis/clip)
  4564. //
  4565. OEGetState(OESTATE_REGION);
  4566. //
  4567. // Get brush info
  4568. //
  4569. if (hbrPaint)
  4570. {
  4571. if (GetObject(hbrPaint, sizeof(g_oeState.logBrush), &g_oeState.logBrush))
  4572. {
  4573. g_oeState.uFlags |= OESTATE_BRUSH;
  4574. }
  4575. else
  4576. {
  4577. g_oeState.logBrush.lbStyle = BS_NULL;
  4578. }
  4579. }
  4580. //
  4581. // Fake a patblt
  4582. //
  4583. if (OETwoWayRopToThree(rop2, &dwRop3))
  4584. {
  4585. fScreenData = FALSE;
  4586. OEAddBlt(dwRop3);
  4587. }
  4588. //
  4589. // Select back in the previous clip rgn
  4590. //
  4591. SelectClipRgn(g_oeState.hdc, hrgnOldClip);
  4592. if (hrgnOldClip)
  4593. DeleteRgn(hrgnOldClip);
  4594. DC_EXIT_POINT:
  4595. if (fScreenData)
  4596. {
  4597. OTRACE(("OEAddRgnPaint: Sending as screen data {%d, %d, %d, %d}",
  4598. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  4599. g_oeState.rc.bottom));
  4600. OEClipAndAddScreenData(&g_oeState.rc);
  4601. }
  4602. DC_EMPTY_REGION:
  4603. DebugExitVOID(OEAddRgnPaint);
  4604. }
  4605. //
  4606. // DrvFrameRgn()
  4607. //
  4608. BOOL WINAPI DrvFrameRgn
  4609. (
  4610. HDC hdcDst,
  4611. HRGN hrgnFrameArea,
  4612. HBRUSH hbrFramePattern,
  4613. int cxFrame,
  4614. int cyFrame
  4615. )
  4616. {
  4617. BOOL fWeCare;
  4618. BOOL fOutput;
  4619. DebugEntry(DrvFrameRgn);
  4620. OE_SHM_START_WRITING;
  4621. fWeCare = OEBeforeDDI(DDI_FRAMERGN, hdcDst, 0);
  4622. fOutput = FrameRgn(hdcDst, hrgnFrameArea, hbrFramePattern,
  4623. cxFrame, cyFrame);
  4624. if (OEAfterDDI(DDI_FRAMERGN, fWeCare, fOutput))
  4625. {
  4626. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  4627. if (GetRgnBox(hrgnFrameArea, &g_oeState.rc) > NULLREGION)
  4628. {
  4629. InflateRect(&g_oeState.rc,
  4630. g_oeState.ptPolarity.x * cxFrame,
  4631. g_oeState.ptPolarity.y * cyFrame);
  4632. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  4633. OTRACE(("FrameRgn: Sending as screen data {%d, %d, %d, %d}",
  4634. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  4635. g_oeState.rc.bottom));
  4636. OEClipAndAddScreenData(&g_oeState.rc);
  4637. }
  4638. }
  4639. OE_SHM_STOP_WRITING;
  4640. DebugExitBOOL(DrvFrameRgn, fOutput);
  4641. return(fOutput);
  4642. }
  4643. //
  4644. // DrvInvertRgn()
  4645. //
  4646. BOOL WINAPI DrvInvertRgn
  4647. (
  4648. HDC hdcDst,
  4649. HRGN hrgnInvert
  4650. )
  4651. {
  4652. BOOL fWeCare;
  4653. BOOL fOutput;
  4654. DebugEntry(DrvInvertRgn);
  4655. OE_SHM_START_WRITING;
  4656. fWeCare = OEBeforeDDI(DDI_INVERTRGN, hdcDst, 0);
  4657. fOutput = InvertRgn(hdcDst, hrgnInvert);
  4658. if (OEAfterDDI(DDI_INVERTRGN, fWeCare, fOutput))
  4659. {
  4660. OEAddRgnPaint(hrgnInvert, NULL, R2_NOT);
  4661. }
  4662. OE_SHM_STOP_WRITING;
  4663. DebugExitBOOL(DrvInvertRgn, fOutput);
  4664. return(fOutput);
  4665. }
  4666. //
  4667. // DrvPaintRgn()
  4668. //
  4669. BOOL WINAPI DrvPaintRgn
  4670. (
  4671. HDC hdcDst,
  4672. HRGN hrgnPaint
  4673. )
  4674. {
  4675. BOOL fWeCare;
  4676. BOOL fOutput;
  4677. DebugEntry(DrvPaintRgn);
  4678. OE_SHM_START_WRITING;
  4679. fWeCare = OEBeforeDDI(DDI_PAINTRGN, hdcDst, 0);
  4680. fOutput = PaintRgn(hdcDst, hrgnPaint);
  4681. if (OEAfterDDI(DDI_PAINTRGN, fWeCare, fOutput))
  4682. {
  4683. OEAddRgnPaint(hrgnPaint, g_oeState.lpdc->hBrush, g_oeState.lpdc->DrawMode.Rop2);
  4684. }
  4685. OE_SHM_STOP_WRITING;
  4686. DebugExitBOOL(DrvPaintRgn, fOutput);
  4687. return(fOutput);
  4688. }
  4689. //
  4690. // DrvLineTo()
  4691. //
  4692. BOOL WINAPI DrvLineTo
  4693. (
  4694. HDC hdcDst,
  4695. int xTo,
  4696. int yTo
  4697. )
  4698. {
  4699. POINT ptEnd;
  4700. BOOL fWeCare;
  4701. BOOL fOutput;
  4702. DebugEntry(DrvLineTo);
  4703. OE_SHM_START_WRITING;
  4704. fWeCare = OEBeforeDDI(DDI_LINETO, hdcDst, OESTATE_CURPOS);
  4705. fOutput = LineTo(hdcDst, xTo, yTo);
  4706. //
  4707. // OEAfterDDI returns TRUE if the DC is a screen DC and output happened
  4708. // and we aren't skipping due to reentrancy.
  4709. //
  4710. if (OEAfterDDI(DDI_LINETO, fWeCare, fOutput))
  4711. {
  4712. //
  4713. // OEAddLine() will calculate extents, and if an order can't be sent,
  4714. // OEDoneDDI will add the bounds as screen data.
  4715. //
  4716. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  4717. ptEnd.x = xTo;
  4718. ptEnd.y = yTo;
  4719. ASSERT(g_oeState.uFlags & OESTATE_CURPOS);
  4720. OEAddLine(g_oeState.ptCurPos, ptEnd);
  4721. }
  4722. OE_SHM_STOP_WRITING;
  4723. DebugExitBOOL(DrvLineTo, fOutput);
  4724. return(fOutput);
  4725. }
  4726. //
  4727. // DrvPolyline()
  4728. //
  4729. // NOTE:
  4730. // The differences between Polyline() and PolylineTo() are
  4731. // (1) PolylineTo moves the current position to the end coords of the
  4732. // last point; Polyline preserves the current position
  4733. // (2) Polyline uses the first point in the array as the starting coord
  4734. // of the first point; PolylineTo() uses the current position.
  4735. //
  4736. BOOL WINAPI DrvPolyline
  4737. (
  4738. HDC hdcDst,
  4739. LPPOINT aPoints,
  4740. int cPoints
  4741. )
  4742. {
  4743. BOOL fWeCare;
  4744. BOOL fOutput;
  4745. DebugEntry(DrvPolyline);
  4746. OE_SHM_START_WRITING;
  4747. fWeCare = OEBeforeDDI(DDI_POLYLINE, hdcDst, 0);
  4748. fOutput = Polyline(hdcDst, aPoints, cPoints);
  4749. if (OEAfterDDI(DDI_POLYLINE, fWeCare, fOutput && cPoints > 1))
  4750. {
  4751. //
  4752. // GDI should NEVER return success if the aPoints parameter is
  4753. // bogus.
  4754. //
  4755. // NOTE LAURABU:
  4756. // This implementation is better than NM 2.0. That one would turn
  4757. // this GDI call actually into separate MoveTo/LineTo calls, which
  4758. // whacks out metafiles etc. Instead, we call through to the org
  4759. // Polyline, then add LineTo orders.
  4760. //
  4761. ASSERT(!IsBadReadPtr(aPoints, cPoints*sizeof(POINT)));
  4762. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  4763. OEAddPolyline(aPoints[0], aPoints+1, cPoints-1);
  4764. }
  4765. OE_SHM_STOP_WRITING;
  4766. DebugExitBOOL(DrvPolyline, fOutput);
  4767. return(fOutput);
  4768. }
  4769. //
  4770. // DrvPolylineTo()
  4771. //
  4772. BOOL WINAPI DrvPolylineTo
  4773. (
  4774. HDC hdcDst,
  4775. LPPOINT aPoints,
  4776. int cPoints
  4777. )
  4778. {
  4779. BOOL fWeCare;
  4780. BOOL fOutput;
  4781. DebugEntry(DrvPolylineTo);
  4782. OE_SHM_START_WRITING;
  4783. fWeCare = OEBeforeDDI(DDI_POLYLINETO, hdcDst, OESTATE_CURPOS);
  4784. fOutput = g_lpfnPolylineTo(hdcDst, aPoints, cPoints);
  4785. if (OEAfterDDI(DDI_POLYLINETO, fWeCare, fOutput && cPoints))
  4786. {
  4787. //
  4788. // GDI should NEVER return success if the aPoints parameter is
  4789. // bogus.
  4790. //
  4791. // NOTE LAURABU:
  4792. // This implementation is better than NM 2.0. That one would turn
  4793. // this GDI call actually into separate LineTo calls, which whacks
  4794. // out metafiles etc. Instead, we call through to the original
  4795. // PolylineTo, then add LineTo orders.
  4796. //
  4797. ASSERT(!IsBadReadPtr(aPoints, cPoints*sizeof(POINT)));
  4798. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  4799. ASSERT(g_oeState.uFlags & OESTATE_CURPOS);
  4800. OEAddPolyline(g_oeState.ptCurPos, aPoints, cPoints);
  4801. }
  4802. OE_SHM_STOP_WRITING;
  4803. DebugExitBOOL(DrvPolylineTo, fOutput);
  4804. return(fOutput);
  4805. }
  4806. //
  4807. // OEAddPolyline
  4808. // Used by Polyline(), PolylineTo(), and PolyPolyline()
  4809. //
  4810. void OEAddPolyline
  4811. (
  4812. POINT ptStart,
  4813. LPPOINT aPoints,
  4814. UINT cPoints
  4815. )
  4816. {
  4817. DebugEntry(OEAddPolyline);
  4818. ASSERT(g_oeState.uFlags & OESTATE_COORDS);
  4819. ASSERT(g_oeState.uFlags & OESTATE_REGION);
  4820. while (cPoints-- > 0)
  4821. {
  4822. OEAddLine(ptStart, *aPoints);
  4823. //
  4824. // The start point of the next line is the end point of the
  4825. // current one.
  4826. //
  4827. ptStart = *aPoints;
  4828. aPoints++;
  4829. }
  4830. DebugExitVOID(OEAddPolyline);
  4831. }
  4832. //
  4833. // DrvPlayEnhMetaFileRecord()
  4834. //
  4835. BOOL WINAPI DrvPlayEnhMetaFileRecord
  4836. (
  4837. HDC hdcDst,
  4838. LPHANDLETABLE lpEMFHandles,
  4839. LPENHMETARECORD lpEMFRecord,
  4840. DWORD cEMFHandles
  4841. )
  4842. {
  4843. BOOL fWeCare;
  4844. BOOL fOutput;
  4845. DebugEntry(DrvPlayEnhMetaFileRecord);
  4846. OE_SHM_START_WRITING;
  4847. fWeCare = OEBeforeDDI(DDI_PLAYENHMETAFILERECORD, hdcDst, OESTATE_SDA_DCB);
  4848. fOutput = PlayEnhMetaFileRecord(hdcDst, lpEMFHandles, lpEMFRecord, cEMFHandles);
  4849. OEAfterDDI(DDI_PLAYENHMETAFILERECORD, fWeCare, fOutput);
  4850. OE_SHM_STOP_WRITING;
  4851. DebugExitBOOL(DrvPlayEnhMetaFileRecord, fOutput);
  4852. return(fOutput);
  4853. }
  4854. //
  4855. // DrvPlayMetaFile()
  4856. //
  4857. BOOL WINAPI DrvPlayMetaFile
  4858. (
  4859. HDC hdcDst,
  4860. HMETAFILE hmf
  4861. )
  4862. {
  4863. BOOL fWeCare;
  4864. BOOL fOutput;
  4865. DebugEntry(DrvPlayMetaFile);
  4866. OE_SHM_START_WRITING;
  4867. fWeCare = OEBeforeDDI(DDI_PLAYMETAFILE, hdcDst, OESTATE_SDA_DCB);
  4868. fOutput = PlayMetaFile(hdcDst, hmf);
  4869. OEAfterDDI(DDI_PLAYMETAFILE, fWeCare, fOutput);
  4870. OE_SHM_STOP_WRITING;
  4871. DebugExitBOOL(DrvPlayMetaFile, fOutput);
  4872. return(fOutput);
  4873. }
  4874. //
  4875. // DrvPlayMetaFileRecord()
  4876. //
  4877. void WINAPI DrvPlayMetaFileRecord
  4878. (
  4879. HDC hdcDst,
  4880. LPHANDLETABLE lpMFHandles,
  4881. LPMETARECORD lpMFRecord,
  4882. UINT cMFHandles
  4883. )
  4884. {
  4885. BOOL fWeCare;
  4886. DebugEntry(DrvPlayMetaFileRecord);
  4887. OE_SHM_START_WRITING;
  4888. fWeCare = OEBeforeDDI(DDI_PLAYMETAFILERECORD, hdcDst, OESTATE_SDA_DCB);
  4889. PlayMetaFileRecord(hdcDst, lpMFHandles, lpMFRecord, cMFHandles);
  4890. OEAfterDDI(DDI_PLAYMETAFILERECORD, fWeCare, TRUE);
  4891. OE_SHM_STOP_WRITING;
  4892. DebugExitVOID(DrvPlayMetaFileRecord);
  4893. }
  4894. //
  4895. // DrvPolyBezier()
  4896. //
  4897. BOOL WINAPI DrvPolyBezier
  4898. (
  4899. HDC hdcDst,
  4900. LPPOINT aPoints,
  4901. UINT cPoints
  4902. )
  4903. {
  4904. BOOL fWeCare;
  4905. BOOL fOutput;
  4906. DebugEntry(DrvPolyBezier);
  4907. OE_SHM_START_WRITING;
  4908. fWeCare = OEBeforeDDI(DDI_POLYBEZIER, hdcDst, 0);
  4909. fOutput = PolyBezier(hdcDst, aPoints, cPoints);
  4910. if (OEAfterDDI(DDI_POLYBEZIER, fWeCare, fOutput && (cPoints > 1)))
  4911. {
  4912. ASSERT(!IsBadReadPtr(aPoints, cPoints*sizeof(POINT)));
  4913. OEAddPolyBezier(aPoints[0], aPoints+1, cPoints-1);
  4914. }
  4915. OE_SHM_STOP_WRITING;
  4916. DebugExitBOOL(DrvPolyBezier, fOutput);
  4917. return(fOutput);
  4918. }
  4919. //
  4920. // DrvPolyBezierTo()
  4921. //
  4922. BOOL WINAPI DrvPolyBezierTo
  4923. (
  4924. HDC hdcDst,
  4925. LPPOINT aPoints,
  4926. UINT cPoints
  4927. )
  4928. {
  4929. BOOL fWeCare;
  4930. BOOL fOutput;
  4931. DebugEntry(DrvPolyBezierTo);
  4932. OE_SHM_START_WRITING;
  4933. fWeCare = OEBeforeDDI(DDI_POLYBEZIERTO, hdcDst, OESTATE_CURPOS);
  4934. fOutput = PolyBezierTo(hdcDst, aPoints, cPoints);
  4935. if (OEAfterDDI(DDI_POLYBEZIERTO, fWeCare, fOutput && cPoints))
  4936. {
  4937. ASSERT(!IsBadReadPtr(aPoints, cPoints*sizeof(POINT)));
  4938. ASSERT(g_oeState.uFlags & OESTATE_CURPOS);
  4939. OEAddPolyBezier(g_oeState.ptCurPos, aPoints, cPoints);
  4940. }
  4941. OE_SHM_STOP_WRITING;
  4942. DebugExitBOOL(DrvPolyBezierTo, fOutput);
  4943. return(fOutput);
  4944. }
  4945. //
  4946. // OEAddPolyBezier()
  4947. //
  4948. // Adds poly bezier order for both PolyBezier() and PolyBezierTo().
  4949. //
  4950. void OEAddPolyBezier
  4951. (
  4952. POINT ptStart,
  4953. LPPOINT aPoints,
  4954. UINT cPoints
  4955. )
  4956. {
  4957. UINT iPoint;
  4958. LPINT_ORDER pOrder;
  4959. LPPOLYBEZIER_ORDER pPolyBezier;
  4960. DebugEntry(OEAddPolyBezier);
  4961. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  4962. //
  4963. // Calculate the bounds
  4964. //
  4965. g_oeState.rc.left = ptStart.x;
  4966. g_oeState.rc.top = ptStart.y;
  4967. g_oeState.rc.right = ptStart.x;
  4968. g_oeState.rc.bottom = ptStart.y;
  4969. for (iPoint = 0; iPoint < cPoints; iPoint++)
  4970. {
  4971. g_oeState.rc.left = min(g_oeState.rc.left, aPoints[iPoint].x);
  4972. g_oeState.rc.right = max(g_oeState.rc.right, aPoints[iPoint].x);
  4973. g_oeState.rc.top = min(g_oeState.rc.top, aPoints[iPoint].y);
  4974. g_oeState.rc.bottom = max(g_oeState.rc.bottom, aPoints[iPoint].y);
  4975. }
  4976. OEPolarityAdjust(&g_oeState.rc, 1);
  4977. OEPenWidthAdjust(&g_oeState.rc, 1);
  4978. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  4979. //
  4980. // OELRtoVirtual takes an exclusive rect and returns an inclusive one.
  4981. // But we passed it an inclusive already rect, so we need to account
  4982. // for that.
  4983. //
  4984. g_oeState.rc.right++;
  4985. g_oeState.rc.bottom++;
  4986. pOrder = NULL;
  4987. // Account for starting point also
  4988. if (OECheckOrder(ORD_POLYBEZIER, OECHECK_PEN | OECHECK_CLIPPING) &&
  4989. (cPoints < ORD_MAX_POLYBEZIER_POINTS))
  4990. {
  4991. pOrder = OA_DDAllocOrderMem(sizeof(POLYBEZIER_ORDER) -
  4992. ((ORD_MAX_POLYBEZIER_POINTS - cPoints - 1) *
  4993. sizeof(pPolyBezier->variablePoints.aPoints[0])), 0);
  4994. if (!pOrder)
  4995. DC_QUIT;
  4996. pPolyBezier = (LPPOLYBEZIER_ORDER)pOrder->abOrderData;
  4997. pPolyBezier->type = LOWORD(ORD_POLYBEZIER);
  4998. //
  4999. // Copy them into the order array
  5000. //
  5001. pPolyBezier->variablePoints.len =
  5002. ((cPoints+1) * sizeof(pPolyBezier->variablePoints.aPoints[0]));
  5003. pPolyBezier->variablePoints.aPoints[0].x = ptStart.x;
  5004. pPolyBezier->variablePoints.aPoints[0].y = ptStart.y;
  5005. hmemcpy(pPolyBezier->variablePoints.aPoints+1, aPoints,
  5006. cPoints*sizeof(pPolyBezier->variablePoints.aPoints[0]));
  5007. //
  5008. // Convert points to virtual
  5009. //
  5010. // NOTE that this works because aPoints[] holds TSHR_POINT16s, which
  5011. // are natively the same size as POINT structures.
  5012. //
  5013. OELPtoVirtual(g_oeState.hdc, (LPPOINT)pPolyBezier->variablePoints.aPoints,
  5014. cPoints+1);
  5015. OEConvertColor(g_oeState.lpdc->DrawMode.bkColorL,
  5016. &pPolyBezier->BackColor, FALSE);
  5017. OEConvertColor(g_oeState.lpdc->DrawMode.txColorL,
  5018. &pPolyBezier->ForeColor, FALSE);
  5019. pPolyBezier->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  5020. pPolyBezier->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  5021. pPolyBezier->PenStyle = g_oeState.logPen.lopnStyle;
  5022. pPolyBezier->PenWidth = 1;
  5023. OEConvertColor(g_oeState.logPen.lopnColor, &pPolyBezier->PenColor,
  5024. FALSE);
  5025. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  5026. OTRACE(("PolyBezier: Order %08lx, Rect {%d, %d, %d, %d} with %d points",
  5027. pOrder, g_oeState.rc.left, g_oeState.rc.top,
  5028. g_oeState.rc.right, g_oeState.rc.bottom, cPoints+1));
  5029. OEClipAndAddOrder(pOrder, NULL);
  5030. }
  5031. DC_EXIT_POINT:
  5032. if (!pOrder)
  5033. {
  5034. OTRACE(("PolyBezier: Sending as screen data {%d, %d, %d, %d}",
  5035. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  5036. g_oeState.rc.bottom));
  5037. OEClipAndAddScreenData(&g_oeState.rc);
  5038. }
  5039. DebugExitVOID(OEAddPolyBezier);
  5040. }
  5041. //
  5042. // DrvPolygon()
  5043. //
  5044. BOOL WINAPI DrvPolygon
  5045. (
  5046. HDC hdcDst,
  5047. LPPOINT aPoints,
  5048. int cPoints
  5049. )
  5050. {
  5051. BOOL fWeCare;
  5052. BOOL fOutput;
  5053. LPINT_ORDER pOrder;
  5054. LPPOLYGON_ORDER pPolygon;
  5055. int iPoint;
  5056. POINT ptBrushOrg;
  5057. DebugEntry(DrvPolygon);
  5058. OE_SHM_START_WRITING;
  5059. fWeCare = OEBeforeDDI(DDI_POLYGON, hdcDst, 0);
  5060. fOutput = Polygon(hdcDst, aPoints, cPoints);
  5061. if (OEAfterDDI(DDI_POLYGON, fWeCare, fOutput && (cPoints > 1)))
  5062. {
  5063. ASSERT(!IsBadReadPtr(aPoints, cPoints*sizeof(POINT)));
  5064. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  5065. //
  5066. // Compute the bounds
  5067. //
  5068. g_oeState.rc.left = aPoints[0].x;
  5069. g_oeState.rc.top = aPoints[0].y;
  5070. g_oeState.rc.right = aPoints[0].x;
  5071. g_oeState.rc.bottom = aPoints[0].y;
  5072. for (iPoint = 1; iPoint < cPoints; iPoint++)
  5073. {
  5074. g_oeState.rc.left = min(g_oeState.rc.left, aPoints[iPoint].x);
  5075. g_oeState.rc.top = min(g_oeState.rc.top, aPoints[iPoint].y);
  5076. g_oeState.rc.right = max(g_oeState.rc.right, aPoints[iPoint].x);
  5077. g_oeState.rc.bottom = max(g_oeState.rc.bottom, aPoints[iPoint].y);
  5078. }
  5079. OEPolarityAdjust(&g_oeState.rc, 1);
  5080. OEPenWidthAdjust(&g_oeState.rc, 1);
  5081. //
  5082. // The rect is in inclusive coords already, OELRtoVirtual thinks
  5083. // it's exclusive. So we need to add one back on to the right
  5084. // and bottom to end up with the real inclusive rect.
  5085. //
  5086. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  5087. g_oeState.rc.right++;
  5088. g_oeState.rc.bottom++;
  5089. pOrder = NULL;
  5090. if (OECheckOrder(ORD_POLYGON, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING) &&
  5091. (cPoints <= ORD_MAX_POLYGON_POINTS))
  5092. {
  5093. pOrder = OA_DDAllocOrderMem(sizeof(POLYGON_ORDER) -
  5094. ((ORD_MAX_POLYGON_POINTS - cPoints) *
  5095. sizeof(pPolygon->variablePoints.aPoints[0])), 0);
  5096. if (!pOrder)
  5097. goto NoPolygonOrder;
  5098. pPolygon = (LPPOLYGON_ORDER)pOrder->abOrderData;
  5099. pPolygon->type = LOWORD(ORD_POLYGON);
  5100. pPolygon->variablePoints.len =
  5101. cPoints * sizeof(pPolygon->variablePoints.aPoints[0]);
  5102. hmemcpy(pPolygon->variablePoints.aPoints, aPoints,
  5103. pPolygon->variablePoints.len);
  5104. //
  5105. // Convert all the points to virtual
  5106. //
  5107. // NOTE that this works because aPoints[] hols TSHR_POINT16s,
  5108. // which are natively the same size as POINT structures.
  5109. //
  5110. OELPtoVirtual(g_oeState.hdc, (LPPOINT)pPolygon->variablePoints.aPoints,
  5111. cPoints);
  5112. OEGetBrushInfo(&pPolygon->BackColor, &pPolygon->ForeColor,
  5113. &pPolygon->BrushStyle, &pPolygon->BrushHatch,
  5114. pPolygon->BrushExtra);
  5115. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  5116. pPolygon->BrushOrgX = (BYTE)ptBrushOrg.x;
  5117. pPolygon->BrushOrgY = (BYTE)ptBrushOrg.y;
  5118. pPolygon->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  5119. pPolygon->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  5120. //
  5121. // Pen info
  5122. //
  5123. pPolygon->PenStyle = g_oeState.logPen.lopnStyle;
  5124. pPolygon->PenWidth = 1;
  5125. OEConvertColor(g_oeState.logPen.lopnColor, &pPolygon->PenColor,
  5126. FALSE);
  5127. pPolygon->FillMode = GetPolyFillMode(g_oeState.hdc);
  5128. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  5129. OTRACE(("Polygon: Order %08lx, Rect {%d, %d, %d, %d} with %d points",
  5130. pOrder, g_oeState.rc.left, g_oeState.rc.top,
  5131. g_oeState.rc.right, g_oeState.rc.bottom, cPoints));
  5132. OEClipAndAddOrder(pOrder, NULL);
  5133. }
  5134. NoPolygonOrder:
  5135. if (!pOrder)
  5136. {
  5137. OTRACE(("Polygon: Sending %d points as screen data {%d, %d, %d, %d}",
  5138. cPoints, g_oeState.rc.left, g_oeState.rc.top,
  5139. g_oeState.rc.right, g_oeState.rc.bottom));
  5140. OEClipAndAddScreenData(&g_oeState.rc);
  5141. }
  5142. }
  5143. OE_SHM_STOP_WRITING;
  5144. DebugExitBOOL(DrvPolygon, fOutput);
  5145. return(fOutput);
  5146. }
  5147. //
  5148. // DrvPolyPolygon()
  5149. //
  5150. BOOL WINAPI DrvPolyPolygon
  5151. (
  5152. HDC hdcDst,
  5153. LPPOINT aPoints,
  5154. LPINT aPolygonPoints,
  5155. int cPolygons
  5156. )
  5157. {
  5158. BOOL fWeCare;
  5159. BOOL fOutput;
  5160. int iPolygon;
  5161. int iPoint;
  5162. DebugEntry(DrvPolyPolygon);
  5163. OE_SHM_START_WRITING;
  5164. fWeCare = OEBeforeDDI(DDI_POLYPOLYGON, hdcDst, 0);
  5165. fOutput = PolyPolygon(hdcDst, aPoints, aPolygonPoints, cPolygons);
  5166. if (OEAfterDDI(DDI_POLYPOLYGON, fWeCare, fOutput && cPolygons))
  5167. {
  5168. ASSERT(!IsBadReadPtr(aPolygonPoints, cPolygons*sizeof(int)));
  5169. #ifdef DEBUG
  5170. //
  5171. // How many points total are there?
  5172. //
  5173. iPoint = 0;
  5174. for (iPolygon = 0; iPolygon < cPolygons; iPolygon++)
  5175. {
  5176. iPoint += aPolygonPoints[iPolygon];
  5177. }
  5178. ASSERT(!IsBadReadPtr(aPoints, iPoint*sizeof(POINT)));
  5179. #endif
  5180. //
  5181. // Like LineTo, we need to juggle the coords for polarity.
  5182. //
  5183. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  5184. for (iPolygon = 0; iPolygon < cPolygons; iPolygon++, aPolygonPoints++)
  5185. {
  5186. //
  5187. // No points for this polygon, nothing to do.
  5188. //
  5189. if (*aPolygonPoints < 2)
  5190. {
  5191. aPoints += *aPolygonPoints;
  5192. continue;
  5193. }
  5194. g_oeState.rc.left = aPoints[0].x;
  5195. g_oeState.rc.top = aPoints[0].y;
  5196. g_oeState.rc.right = aPoints[0].x;
  5197. g_oeState.rc.bottom = aPoints[0].y;
  5198. aPoints++;
  5199. for (iPoint = 1; iPoint < *aPolygonPoints; iPoint++, aPoints++)
  5200. {
  5201. g_oeState.rc.left = min(g_oeState.rc.left, aPoints[0].x);
  5202. g_oeState.rc.top = min(g_oeState.rc.top, aPoints[0].y);
  5203. g_oeState.rc.right = max(g_oeState.rc.right, aPoints[0].x);
  5204. g_oeState.rc.bottom = max(g_oeState.rc.bottom, aPoints[0].y);
  5205. }
  5206. OEPolarityAdjust(&g_oeState.rc, 1);
  5207. OEPenWidthAdjust(&g_oeState.rc, 1);
  5208. //
  5209. // Our rectangle is already inclusive, and OELRtoVirtual() will
  5210. // treat it like it's exclusive. So after we return add one back
  5211. // to the right & bottom to end up with the real inclusive
  5212. // rectangle.
  5213. //
  5214. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  5215. g_oeState.rc.right++;
  5216. g_oeState.rc.bottom++;
  5217. OTRACE(("PolyPolygon: Sending piece %d as screen data {%d, %d, %d, %d}",
  5218. iPolygon, g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  5219. g_oeState.rc.bottom));
  5220. OEClipAndAddScreenData(&g_oeState.rc);
  5221. }
  5222. }
  5223. OE_SHM_STOP_WRITING;
  5224. DebugExitBOOL(DrvPolyPolygon, fOutput);
  5225. return(fOutput);
  5226. }
  5227. //
  5228. // PolyPolyline()
  5229. //
  5230. BOOL WINAPI DrvPolyPolyline
  5231. (
  5232. DWORD cPtTotal,
  5233. HDC hdcDst,
  5234. LPPOINT aPoints,
  5235. LPINT acPolylinePoints,
  5236. int cPolylines
  5237. )
  5238. {
  5239. BOOL fWeCare;
  5240. BOOL fOutput;
  5241. UINT cPoints;
  5242. DebugEntry(DrvPolyPolyline);
  5243. OE_SHM_START_WRITING;
  5244. //
  5245. // LAURABU NOTE:
  5246. // This code is better than 2.0. 2.0 would simulate the actual GDI
  5247. // call by repeated Polyline calls. We accumulate orders the same way
  5248. // that would have happened, but let GDI do the drawing, which is much
  5249. // more metafile friendly, among other things.
  5250. //
  5251. fWeCare = OEBeforeDDI(DDI_POLYPOLYLINE, hdcDst, 0);
  5252. fOutput = g_lpfnPolyPolyline(cPtTotal, hdcDst, aPoints, acPolylinePoints,
  5253. cPolylines);
  5254. if (OEAfterDDI(DDI_POLYPOLYLINE, fWeCare, fOutput && cPolylines))
  5255. {
  5256. ASSERT(!IsBadReadPtr(acPolylinePoints, cPolylines*sizeof(int)));
  5257. ASSERT(!IsBadReadPtr(aPoints, (UINT)cPtTotal*sizeof(POINT)));
  5258. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_REGION);
  5259. while (cPolylines-- > 0)
  5260. {
  5261. cPoints = *(acPolylinePoints++);
  5262. if (cPoints > 1)
  5263. {
  5264. OEAddPolyline(aPoints[0], aPoints+1, cPoints-1);
  5265. }
  5266. aPoints += cPoints;
  5267. }
  5268. }
  5269. OE_SHM_STOP_WRITING;
  5270. DebugExitBOOL(DrvPolyPolyline, fOutput);
  5271. return(fOutput);
  5272. }
  5273. //
  5274. // DrvRectangle()
  5275. //
  5276. BOOL WINAPI DrvRectangle
  5277. (
  5278. HDC hdcDst,
  5279. int xLeft,
  5280. int yTop,
  5281. int xRight,
  5282. int yBottom
  5283. )
  5284. {
  5285. BOOL fWeCare;
  5286. BOOL fOutput;
  5287. RECT rcAdjusted;
  5288. LPINT_ORDER pOrder;
  5289. LPRECTANGLE_ORDER pRectangle;
  5290. POINT ptBrushOrg;
  5291. LPRECT pRect;
  5292. int sideWidth;
  5293. DebugEntry(DrvRectangle);
  5294. OE_SHM_START_WRITING;
  5295. fWeCare = OEBeforeDDI(DDI_RECTANGLE, hdcDst, 0);
  5296. fOutput = Rectangle(hdcDst, xLeft, yTop, xRight, yBottom);
  5297. if (OEAfterDDI(DDI_RECTANGLE, fWeCare, fOutput && (xLeft != xRight) && (yTop != yBottom)))
  5298. {
  5299. OEGetState(OESTATE_COORDS | OESTATE_PEN | OESTATE_BRUSH | OESTATE_REGION);
  5300. g_oeState.rc.left = xLeft;
  5301. g_oeState.rc.top = yTop;
  5302. g_oeState.rc.right = xRight;
  5303. g_oeState.rc.bottom = yBottom;
  5304. CopyRect(&rcAdjusted, &g_oeState.rc);
  5305. if ((g_oeState.logPen.lopnStyle == PS_SOLID) ||
  5306. (g_oeState.logPen.lopnStyle == PS_INSIDEFRAME))
  5307. {
  5308. OEPenWidthAdjust(&rcAdjusted, 2);
  5309. }
  5310. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  5311. OELRtoVirtual(g_oeState.hdc, &rcAdjusted, 1);
  5312. rcAdjusted.right--;
  5313. rcAdjusted.bottom--;
  5314. pOrder = NULL;
  5315. if (OECheckOrder(ORD_RECTANGLE, OECHECK_PEN | OECHECK_BRUSH | OECHECK_CLIPPING))
  5316. {
  5317. pOrder = OA_DDAllocOrderMem(sizeof(RECTANGLE_ORDER), 0);
  5318. if (!pOrder)
  5319. goto NoRectOrder;
  5320. pRectangle = (LPRECTANGLE_ORDER)pOrder->abOrderData;
  5321. pRectangle->type = LOWORD(ORD_RECTANGLE);
  5322. pRectangle->nLeftRect = g_oeState.rc.left;
  5323. pRectangle->nTopRect = g_oeState.rc.top;
  5324. pRectangle->nRightRect = g_oeState.rc.right;
  5325. pRectangle->nBottomRect = g_oeState.rc.bottom;
  5326. OEGetBrushInfo(&pRectangle->BackColor, &pRectangle->ForeColor,
  5327. &pRectangle->BrushStyle, &pRectangle->BrushHatch,
  5328. pRectangle->BrushExtra);
  5329. GetBrushOrgEx(g_oeState.hdc, &ptBrushOrg);
  5330. pRectangle->BrushOrgX = (BYTE)ptBrushOrg.x;
  5331. pRectangle->BrushOrgY = (BYTE)ptBrushOrg.y;
  5332. pRectangle->BackMode = g_oeState.lpdc->DrawMode.bkMode;
  5333. pRectangle->ROP2 = g_oeState.lpdc->DrawMode.Rop2;
  5334. pRectangle->PenStyle = g_oeState.logPen.lopnStyle;
  5335. pRectangle->PenWidth = 1;
  5336. OEConvertColor(g_oeState.logPen.lopnColor, &pRectangle->PenColor,
  5337. FALSE);
  5338. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  5339. if ((g_oeState.logBrush.lbStyle == BS_SOLID) ||
  5340. ((pRectangle->BackMode == OPAQUE) &&
  5341. (g_oeState.logBrush.lbStyle != BS_NULL)))
  5342. {
  5343. pOrder->OrderHeader.Common.fOrderFlags |= OF_SPOILER;
  5344. }
  5345. //
  5346. // Since we only encode orders of width 1, the bounding rect
  5347. // stuff is simple.
  5348. //
  5349. OTRACE(("Rectangle: Order %08lx, pOrder, Rect {%d, %d, %d, %d}",
  5350. pOrder, g_oeState.rc.left,
  5351. g_oeState.rc.top, g_oeState.rc.right, g_oeState.rc.bottom));
  5352. OEClipAndAddOrder(pOrder, NULL);
  5353. }
  5354. NoRectOrder:
  5355. if (!pOrder)
  5356. {
  5357. //
  5358. // This is more complicated. We accumulate screen data for
  5359. // pens of different sizes.
  5360. //
  5361. //
  5362. // If the interior is drawn, then we need to send all the screen
  5363. // area enclosed by the rect. Otherwise, we can just send the
  5364. // four rectangles describing the border.
  5365. //
  5366. if (g_oeState.logBrush.lbStyle == BS_NULL)
  5367. {
  5368. pRect = NULL;
  5369. //
  5370. // Use the pen width to determine the width of each rect
  5371. // to add as screen data
  5372. //
  5373. switch (g_oeState.logPen.lopnStyle)
  5374. {
  5375. case PS_NULL:
  5376. // Nothing to do.
  5377. break;
  5378. case PS_SOLID:
  5379. //
  5380. // The difference between the adjusted and normal
  5381. // rects is half the pen width, so double this up
  5382. // to get the width of each piece to send.
  5383. //
  5384. pRect = &rcAdjusted;
  5385. sideWidth = 2*(g_oeState.rc.left - rcAdjusted.left)
  5386. - 1;
  5387. break;
  5388. case PS_INSIDEFRAME:
  5389. //
  5390. // The pen is contained entirely within the corner
  5391. // pts passed to this function.
  5392. //
  5393. pRect = &g_oeState.rc;
  5394. sideWidth = 2*(g_oeState.rc.left - rcAdjusted.left)
  5395. - 1;
  5396. break;
  5397. default:
  5398. //
  5399. // All other pens have width of 1 and are inside the
  5400. // frame.
  5401. //
  5402. pRect = &g_oeState.rc;
  5403. sideWidth = 0;
  5404. break;
  5405. }
  5406. if (pRect)
  5407. {
  5408. RECT rcT;
  5409. //
  5410. // Left
  5411. //
  5412. CopyRect(&rcT, pRect);
  5413. rcT.right = rcT.left + sideWidth;
  5414. rcT.bottom -= sideWidth + 1;
  5415. OTRACE(("Rectangle left: Sending screen data {%d, %d, %d, %d}",
  5416. rcT.left, rcT.top, rcT.right, rcT.bottom));
  5417. OEClipAndAddScreenData(&rcT);
  5418. //
  5419. // Top
  5420. //
  5421. CopyRect(&rcT, pRect);
  5422. rcT.left += sideWidth + 1;
  5423. rcT.bottom = rcT.top + sideWidth;
  5424. OTRACE(("Rectangle top: Sending screen data {%d, %d, %d, %d}",
  5425. rcT.left, rcT.top, rcT.right, rcT.bottom));
  5426. OEClipAndAddScreenData(&rcT);
  5427. //
  5428. // Right
  5429. //
  5430. CopyRect(&rcT, pRect);
  5431. rcT.left = rcT.right - sideWidth;
  5432. rcT.top += sideWidth + 1;
  5433. OTRACE(("Rectangle right: Sending screen data {%d, %d, %d, %d}",
  5434. rcT.left, rcT.top, rcT.right, rcT.bottom));
  5435. OEClipAndAddScreenData(&rcT);
  5436. //
  5437. // Bottom
  5438. //
  5439. CopyRect(&rcT, pRect);
  5440. rcT.right -= sideWidth + 1;
  5441. rcT.top = rcT.bottom - sideWidth;
  5442. OTRACE(("Rectangle bottom: Sending screen data {%d, %d, %d, %d}",
  5443. rcT.left, rcT.top, rcT.right, rcT.bottom));
  5444. OEClipAndAddScreenData(&rcT);
  5445. }
  5446. }
  5447. else
  5448. {
  5449. if (g_oeState.logPen.lopnStyle == PS_SOLID)
  5450. pRect = &rcAdjusted;
  5451. else
  5452. pRect = &g_oeState.rc;
  5453. OTRACE(("Rectangle: Sending as screen data {%d, %d, %d, %d}",
  5454. pRect->left, pRect->top, pRect->right, pRect->bottom));
  5455. OEClipAndAddScreenData(pRect);
  5456. }
  5457. }
  5458. }
  5459. OE_SHM_STOP_WRITING;
  5460. DebugExitBOOL(DrvRectangle, fOutput);
  5461. return(fOutput);
  5462. }
  5463. //
  5464. // DrvSetDIBitsToDevice()
  5465. //
  5466. int WINAPI DrvSetDIBitsToDevice
  5467. (
  5468. HDC hdcDst,
  5469. int xDst,
  5470. int yDst,
  5471. int cxDst,
  5472. int cyDst,
  5473. int xSrc,
  5474. int ySrc,
  5475. UINT uStartScan,
  5476. UINT cScanLines,
  5477. LPVOID lpvBits,
  5478. LPBITMAPINFO lpbmi,
  5479. UINT fuColorUse
  5480. )
  5481. {
  5482. BOOL fWeCare;
  5483. BOOL fOutput;
  5484. DebugEntry(DrvSetDIBitsToDevice);
  5485. OE_SHM_START_WRITING;
  5486. fWeCare = OEBeforeDDI(DDI_SETDIBITSTODEVICE, hdcDst, 0);
  5487. fOutput = SetDIBitsToDevice(hdcDst, xDst, yDst, cxDst, cyDst,
  5488. xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse);
  5489. if (OEAfterDDI(DDI_SETDIBITSTODEVICE, fWeCare, fOutput))
  5490. {
  5491. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  5492. g_oeState.rc.left = xDst;
  5493. g_oeState.rc.top = yDst;
  5494. OELPtoVirtual(g_oeState.hdc, (LPPOINT)&g_oeState.rc.left, 1);
  5495. g_oeState.rc.right = g_oeState.rc.left + cxDst;
  5496. g_oeState.rc.bottom = g_oeState.rc.top + cyDst;
  5497. OTRACE(("SetDIBitsToDevice: Sending as screen data {%d, %d, %d, %d}",
  5498. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  5499. g_oeState.rc.bottom));
  5500. OEClipAndAddScreenData(&g_oeState.rc);
  5501. }
  5502. OE_SHM_STOP_WRITING;
  5503. DebugExitBOOL(DrvSetDIBitsToDevice, fOutput);
  5504. return(fOutput);
  5505. }
  5506. //
  5507. // DrvSetPixel()
  5508. //
  5509. COLORREF WINAPI DrvSetPixel
  5510. (
  5511. HDC hdcDst,
  5512. int xDst,
  5513. int yDst,
  5514. COLORREF crPixel
  5515. )
  5516. {
  5517. BOOL fWeCare;
  5518. COLORREF rgbOld;
  5519. DebugEntry(DrvSetPixel);
  5520. OE_SHM_START_WRITING;
  5521. fWeCare = OEBeforeDDI(DDI_SETPIXEL, hdcDst, 0);
  5522. rgbOld = SetPixel(hdcDst, xDst, yDst, crPixel);
  5523. if (OEAfterDDI(DDI_SETPIXEL, fWeCare, (rgbOld != (COLORREF)-1)))
  5524. {
  5525. OEGetState(OESTATE_COORDS | OESTATE_REGION);
  5526. g_oeState.rc.left = xDst;
  5527. g_oeState.rc.top = yDst;
  5528. g_oeState.rc.right = xDst;
  5529. g_oeState.rc.bottom = yDst;
  5530. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  5531. g_oeState.rc.right++;
  5532. g_oeState.rc.bottom++;
  5533. OTRACE(("SetPixel: Sending as screen data {%d, %d, %d, %d}",
  5534. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  5535. g_oeState.rc.bottom));
  5536. OEClipAndAddScreenData(&g_oeState.rc);
  5537. }
  5538. OE_SHM_STOP_WRITING;
  5539. DebugExitDWORD(DrvSetPxel, rgbOld);
  5540. return(rgbOld);
  5541. }
  5542. //
  5543. // DrvStretchDIBits()
  5544. //
  5545. int WINAPI DrvStretchDIBits
  5546. (
  5547. HDC hdcDst,
  5548. int xDst,
  5549. int yDst,
  5550. int cxDst,
  5551. int cyDst,
  5552. int xSrc,
  5553. int ySrc,
  5554. int cxSrc,
  5555. int cySrc,
  5556. LPVOID lpvBits,
  5557. LPBITMAPINFO lpbmi,
  5558. UINT fuColorUse,
  5559. DWORD dwRop
  5560. )
  5561. {
  5562. BOOL fWeCare;
  5563. BOOL fOutput;
  5564. BYTE bRop;
  5565. DebugEntry(DrvStretchDIBits);
  5566. OE_SHM_START_WRITING;
  5567. fWeCare = OEBeforeDDI(DDI_STRETCHDIBITS, hdcDst, 0);
  5568. fOutput = StretchDIBits(hdcDst, xDst, yDst, cxDst, cyDst,
  5569. xSrc, ySrc, cxSrc, cySrc, lpvBits, lpbmi, fuColorUse, dwRop);
  5570. if (OEAfterDDI(DDI_STRETCHDIBITS, fWeCare, fOutput && cxDst && cyDst))
  5571. {
  5572. OEGetState(OESTATE_COORDS | OESTATE_BRUSH | OESTATE_REGION);
  5573. g_oeState.rc.left = xDst;
  5574. g_oeState.rc.top = yDst;
  5575. g_oeState.rc.right = xDst + cxDst;
  5576. g_oeState.rc.bottom = yDst + cyDst;
  5577. OELRtoVirtual(g_oeState.hdc, &g_oeState.rc, 1);
  5578. //
  5579. // If this is a PatBlt really, do that instead.
  5580. //
  5581. bRop = LOBYTE(HIWORD(dwRop));
  5582. if (((bRop & 0x33) << 2) == (bRop & 0xCC))
  5583. {
  5584. OEAddBlt(dwRop);
  5585. DC_QUIT;
  5586. }
  5587. //
  5588. // Do tile bitblt order stuff...
  5589. //
  5590. OTRACE(("StretchDIBits: Sending as screen data {%d, %d, %d, %d}",
  5591. g_oeState.rc.left, g_oeState.rc.top, g_oeState.rc.right,
  5592. g_oeState.rc.bottom));
  5593. OEClipAndAddScreenData(&g_oeState.rc);
  5594. }
  5595. DC_EXIT_POINT:
  5596. OE_SHM_STOP_WRITING;
  5597. DebugExitBOOL(DrvStretchDIBits, fOutput);
  5598. return(fOutput);
  5599. }
  5600. //
  5601. // DrvUpdateColors()
  5602. //
  5603. int WINAPI DrvUpdateColors
  5604. (
  5605. HDC hdcDst
  5606. )
  5607. {
  5608. BOOL fWeCare;
  5609. int ret;
  5610. DebugEntry(DrvUpdateColors);
  5611. OE_SHM_START_WRITING;
  5612. //
  5613. // This doesn't reset the drawing bounds. So we just assume the whole
  5614. // DC changed. And the return value is meaningless. We can't assume
  5615. // that zero means failure.
  5616. //
  5617. fWeCare = OEBeforeDDI(DDI_UPDATECOLORS, hdcDst, OESTATE_SDA_SCREEN);
  5618. ret = UpdateColors(hdcDst);
  5619. OEAfterDDI(DDI_UPDATECOLORS, fWeCare, TRUE);
  5620. OE_SHM_STOP_WRITING;
  5621. DebugExitDWORD(DrvUpdateColors, (DWORD)(UINT)ret);
  5622. return(ret);
  5623. }
  5624. //
  5625. // SETTINGS/MODE FUNCTIONS
  5626. // For full screen dos boxes, resolution/color depth changes
  5627. //
  5628. //
  5629. // DrvGDIRealizePalette()
  5630. //
  5631. // The WM_PALETTE* messages in Win95 are unreliable. So, like NM 2.0, we
  5632. // patch two GDI APIs instead and update a shared variable
  5633. //
  5634. DWORD WINAPI DrvGDIRealizePalette(HDC hdc)
  5635. {
  5636. DWORD dwRet;
  5637. DebugEntry(DrvGDIRealizePalette);
  5638. EnableFnPatch(&g_oeDDPatches[DDI_GDIREALIZEPALETTE], PATCH_DISABLE);
  5639. dwRet = GDIRealizePalette(hdc);
  5640. EnableFnPatch(&g_oeDDPatches[DDI_GDIREALIZEPALETTE], PATCH_ENABLE);
  5641. ASSERT(g_asSharedMemory);
  5642. g_asSharedMemory->pmPaletteChanged = TRUE;
  5643. DebugExitDWORD(DrvGDIRealizePalette, dwRet);
  5644. return(dwRet);
  5645. }
  5646. //
  5647. // DrvRealizeDefaultPalette()
  5648. //
  5649. // The WM_PALETTE* messages in Win95 are unreliable. So, like NM 2.0, we
  5650. // patch two GDI APIs instead and update a shared variable
  5651. //
  5652. void WINAPI DrvRealizeDefaultPalette(HDC hdc)
  5653. {
  5654. DebugEntry(DrvRealizeDefaultPalette);
  5655. EnableFnPatch(&g_oeDDPatches[DDI_REALIZEDEFAULTPALETTE], PATCH_DISABLE);
  5656. RealizeDefaultPalette(hdc);
  5657. EnableFnPatch(&g_oeDDPatches[DDI_REALIZEDEFAULTPALETTE], PATCH_ENABLE);
  5658. ASSERT(g_asSharedMemory);
  5659. g_asSharedMemory->pmPaletteChanged = TRUE;
  5660. DebugExitVOID(DrvRealizeDefaultPalette);
  5661. }
  5662. //
  5663. // This is called when a blue screen fault is coming up, or an app calls
  5664. // Disable() in USER.
  5665. //
  5666. UINT WINAPI DrvDeath
  5667. (
  5668. HDC hdc
  5669. )
  5670. {
  5671. UINT uResult;
  5672. g_asSharedMemory->fullScreen = TRUE;
  5673. EnableFnPatch(&g_oeDDPatches[DDI_DEATH], PATCH_DISABLE);
  5674. uResult = Death(hdc);
  5675. EnableFnPatch(&g_oeDDPatches[DDI_DEATH], PATCH_ENABLE);
  5676. return(uResult);
  5677. }
  5678. //
  5679. // This is called when a blue screen fault is going away, or an app calls
  5680. // Enable() in USER.
  5681. //
  5682. UINT WINAPI DrvResurrection
  5683. (
  5684. HDC hdc,
  5685. DWORD dwParam1,
  5686. DWORD dwParam2,
  5687. DWORD dwParam3
  5688. )
  5689. {
  5690. UINT uResult;
  5691. g_asSharedMemory->fullScreen = FALSE;
  5692. EnableFnPatch(&g_oeDDPatches[DDI_RESURRECTION], PATCH_DISABLE);
  5693. uResult = Resurrection(hdc, dwParam1, dwParam2, dwParam3);
  5694. EnableFnPatch(&g_oeDDPatches[DDI_RESURRECTION], PATCH_ENABLE);
  5695. return(uResult);
  5696. }
  5697. //
  5698. // This is called by a dosbox when going to or coming out of full screen
  5699. // mode. DirectX calls it also.
  5700. //
  5701. LONG WINAPI DrvWinOldAppHackoMatic
  5702. (
  5703. LONG lFlags
  5704. )
  5705. {
  5706. LONG lResult;
  5707. if (lFlags == WOAHACK_LOSINGDISPLAYFOCUS)
  5708. {
  5709. //
  5710. // DOS box is going to full screen from windowed
  5711. //
  5712. g_asSharedMemory->fullScreen = TRUE;
  5713. }
  5714. else if (lFlags == WOAHACK_GAININGDISPLAYFOCUS)
  5715. {
  5716. //
  5717. // DOS box is going from windowed to full screen
  5718. //
  5719. g_asSharedMemory->fullScreen = FALSE;
  5720. }
  5721. EnableFnPatch(&g_oeDDPatches[DDI_WINOLDAPPHACKOMATIC], PATCH_DISABLE);
  5722. lResult = WinOldAppHackoMatic(lFlags);
  5723. EnableFnPatch(&g_oeDDPatches[DDI_WINOLDAPPHACKOMATIC], PATCH_ENABLE);
  5724. return(lResult);
  5725. }
  5726. //
  5727. // ChangeDisplaySettings() WIN95
  5728. // ChangeDisplaySettingsEx() MEMPHIS
  5729. //
  5730. // This is called in 3 circumstances:
  5731. // * By the control to change your screen
  5732. // * By the shell when warm-docking
  5733. // * By 3rd party games to change the settings silently.
  5734. //
  5735. // Easiest thing to do is just to fail this completely.
  5736. //
  5737. LONG WINAPI DrvChangeDisplaySettings
  5738. (
  5739. LPDEVMODE lpDevMode,
  5740. DWORD flags
  5741. )
  5742. {
  5743. return(DISP_CHANGE_FAILED);
  5744. }
  5745. LONG WINAPI DrvChangeDisplaySettingsEx
  5746. (
  5747. LPCSTR lpszDeviceName,
  5748. LPDEVMODE lpDevMode,
  5749. HWND hwnd,
  5750. DWORD flags,
  5751. LPVOID lParam
  5752. )
  5753. {
  5754. return(DISP_CHANGE_FAILED);
  5755. }
  5756. //
  5757. // OBJECT FUNCTIONS
  5758. // For bitmaps (SPBs and cache) and brushes
  5759. //
  5760. //
  5761. // DrvCreateSpb()
  5762. //
  5763. // This watches for SPB bitmaps being created.
  5764. //
  5765. UINT WINAPI DrvCreateSpb
  5766. (
  5767. HDC hdcCompat,
  5768. int cxWidth,
  5769. int cyHeight
  5770. )
  5771. {
  5772. HBITMAP hbmpRet;
  5773. DebugEntry(DrvCreateSpb);
  5774. EnableFnPatch(&g_oeDDPatches[DDI_CREATESPB], PATCH_DISABLE);
  5775. hbmpRet = (HBITMAP)CreateSpb(hdcCompat, cxWidth, cyHeight);
  5776. EnableFnPatch(&g_oeDDPatches[DDI_CREATESPB], PATCH_ENABLE);
  5777. if (hbmpRet)
  5778. {
  5779. //
  5780. // Save in our "next SPB" bitmap list
  5781. //
  5782. g_ssiLastSpbBitmap = hbmpRet;
  5783. }
  5784. DebugExitDWORD(DrvCreateSpb, (DWORD)(UINT)hbmpRet);
  5785. return((UINT)hbmpRet);
  5786. }
  5787. //
  5788. // DrvDeleteObject()
  5789. //
  5790. // This and DrvSysDeleteObject() watch for bitmaps being destroyed.
  5791. //
  5792. BOOL WINAPI DrvDeleteObject
  5793. (
  5794. HGDIOBJ hobj
  5795. )
  5796. {
  5797. BOOL fReturn;
  5798. int gdiType;
  5799. DebugEntry(DrvDeleteObject);
  5800. gdiType = IsGDIObject(hobj);
  5801. if (gdiType == GDIOBJ_BITMAP)
  5802. {
  5803. OE_SHM_START_WRITING;
  5804. //
  5805. // If SPB, toss it. Else if cached bitmap, kill cache entry.
  5806. //
  5807. if ((HBITMAP)hobj == g_ssiLastSpbBitmap)
  5808. {
  5809. g_ssiLastSpbBitmap = NULL;
  5810. }
  5811. else if (!SSIDiscardBits((HBITMAP)hobj))
  5812. {
  5813. }
  5814. OE_SHM_STOP_WRITING;
  5815. }
  5816. EnableFnPatch(&g_oeDDPatches[DDI_DELETEOBJECT], PATCH_DISABLE);
  5817. fReturn = DeleteObject(hobj);
  5818. EnableFnPatch(&g_oeDDPatches[DDI_DELETEOBJECT], PATCH_ENABLE);
  5819. DebugExitBOOL(DrvDeleteObject, fReturn);
  5820. return(fReturn);
  5821. }
  5822. //
  5823. // OE_RectIntersectsSDA()
  5824. //
  5825. // Used by SSI and BLT orders
  5826. //
  5827. BOOL OE_RectIntersectsSDA(LPRECT pRect)
  5828. {
  5829. RECT rectVD;
  5830. BOOL fIntersection = FALSE;
  5831. UINT i;
  5832. DebugEntry(OE_RectIntersectsSDA);
  5833. //
  5834. // Copy the supplied rectangle, converting to inclusive Virtual
  5835. // Desktop coords.
  5836. //
  5837. rectVD.left = pRect->left;
  5838. rectVD.top = pRect->top;
  5839. rectVD.right = pRect->right - 1;
  5840. rectVD.bottom = pRect->bottom - 1;
  5841. //
  5842. // Loop through each of the bounding rectangles checking for
  5843. // an intersection with the supplied rectangle.
  5844. //
  5845. for (i = 0; i <= BA_NUM_RECTS; i++)
  5846. {
  5847. if ( (g_baBounds[i].InUse) &&
  5848. (g_baBounds[i].Coord.left <= rectVD.right) &&
  5849. (g_baBounds[i].Coord.top <= rectVD.bottom) &&
  5850. (g_baBounds[i].Coord.right >= rectVD.left) &&
  5851. (g_baBounds[i].Coord.bottom >= rectVD.top) )
  5852. {
  5853. OTRACE(("Rect {%d, %d, %d, %d} intersects SDA {%d, %d, %d, %d}",
  5854. rectVD.left, rectVD.top, rectVD.right, rectVD.bottom,
  5855. g_baBounds[i].Coord.left, g_baBounds[i].Coord.top,
  5856. g_baBounds[i].Coord.right, g_baBounds[i].Coord.bottom));
  5857. fIntersection = TRUE;
  5858. break;
  5859. }
  5860. }
  5861. DebugExitBOOL(OE_RectIntersectsSDA, fIntersection);
  5862. return(fIntersection);
  5863. }
  5864. //
  5865. // MyStrcmp()
  5866. // Real strcmp() algorithm.
  5867. //
  5868. int MyStrcmp(LPCSTR lp1, LPCSTR lp2)
  5869. {
  5870. ASSERT(lp1);
  5871. ASSERT(lp2);
  5872. while (*lp1 == *lp2)
  5873. {
  5874. //
  5875. // The two strings are identical
  5876. //
  5877. if (!*lp1)
  5878. return(0);
  5879. lp1++;
  5880. lp2++;
  5881. }
  5882. //
  5883. // String1 is numerically > String2, or <
  5884. //
  5885. return((*lp1 > *lp2) ? 1 : -1);
  5886. }