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.

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