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

2994 lines
112 KiB

  1. /****************************************************************************/
  2. // odint.cpp
  3. //
  4. // Order Decoder internal functions.
  5. //
  6. // Copyright (c) 1997-2000 Microsoft Corp.
  7. // Portions copyright (c) 1992-1997 Microsoft, PictureTel
  8. /****************************************************************************/
  9. #include <adcg.h>
  10. extern "C" {
  11. #define TRC_GROUP TRC_GROUP_CORE
  12. #define TRC_FILE "aodint"
  13. #include <atrcapi.h>
  14. }
  15. #define TSC_HR_FILEID TSC_HR_ODINT_CPP
  16. #include "od.h"
  17. #include "cc.h"
  18. #include "bbar.h"
  19. // WinCE does not define BS_HATCHED for their wingdi.h
  20. #ifdef OS_WINCE
  21. #define BS_HATCHED 2
  22. #endif
  23. #define OD_DECODE_CHECK_READ( p, type, pEnd, hr ) \
  24. CHECK_READ_N_BYTES(p, pEnd, sizeof(type), hr, \
  25. ( TB, _T("Read past data end")))
  26. #define OD_DECODE_CHECK_READ_MULT( p, type, mult, pEnd, hr ) \
  27. CHECK_READ_N_BYTES(p, pEnd, (mult) * sizeof(type), hr, \
  28. ( TB, _T("Read past data end")))
  29. #define OD_DECODE_CHECK_VARIABLE_DATALEN( have, required ) \
  30. if( have < required ) { \
  31. TRC_ABORT((TB,_T("Slowpath decode varaible data len ") \
  32. _T("[required=%u got=%u]"), required, have )); \
  33. hr = E_TSC_CORE_LENGTH; \
  34. DC_QUIT; \
  35. }
  36. /****************************************************************************/
  37. // ODDecodeOpaqueRect
  38. //
  39. // Fast-path decode function for OpaqueRect (most common order [57%] in
  40. // WinBench99).
  41. /****************************************************************************/
  42. HRESULT DCINTERNAL COD::ODDecodeOpaqueRect(
  43. BYTE ControlFlags,
  44. BYTE FAR * FAR *ppFieldDecode,
  45. DCUINT dataLen,
  46. UINT32 FieldFlags)
  47. {
  48. HRESULT hr = S_OK;
  49. PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastOpaqueRect;
  50. OPAQUERECT_ORDER FAR *pOR = (OPAQUERECT_ORDER FAR *)
  51. (_OD.lastOpaqueRect + UH_ORDER_HEADER_SIZE);
  52. BYTE FAR *pFieldDecode = *ppFieldDecode;
  53. BYTE FAR *pEnd = pFieldDecode + dataLen;
  54. DC_BEGIN_FN("ODDecodeOpaqueRect");
  55. if (ControlFlags & TS_DELTA_COORDINATES) {
  56. // All coord fields are 1-byte signed deltas from the last values.
  57. if (FieldFlags & 0x01) {
  58. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  59. pOR->nLeftRect += *((char FAR *)pFieldDecode);
  60. pFieldDecode++;
  61. }
  62. if (FieldFlags & 0x02) {
  63. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  64. pOR->nTopRect += *((char FAR *)pFieldDecode);
  65. pFieldDecode++;
  66. }
  67. if (FieldFlags & 0x04) {
  68. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  69. pOR->nWidth += *((char FAR *)pFieldDecode);
  70. pFieldDecode++;
  71. }
  72. if (FieldFlags & 0x08) {
  73. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  74. pOR->nHeight += *((char FAR *)pFieldDecode);
  75. pFieldDecode++;
  76. }
  77. }
  78. else {
  79. // All coord fields are 2-byte values.sign-extended from the output.
  80. if (FieldFlags & 0x01) {
  81. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  82. pOR->nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  83. pFieldDecode += 2;
  84. }
  85. if (FieldFlags & 0x02) {
  86. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  87. pOR->nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  88. pFieldDecode += 2;
  89. }
  90. if (FieldFlags & 0x04) {
  91. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  92. pOR->nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode);
  93. pFieldDecode += 2;
  94. }
  95. if (FieldFlags & 0x08) {
  96. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  97. pOR->nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode);
  98. pFieldDecode += 2;
  99. }
  100. }
  101. // If we've not already set the bounds (the order didn't contain
  102. // any), set the bounds to the blt rect and reset the clip region.
  103. // This rect might be needed later to add to the clip region for
  104. // updating the shadow buffer to the screen.
  105. if (!(ControlFlags & TS_BOUNDS)) {
  106. pUHHdr->dstRect.left = (int)pOR->nLeftRect;
  107. pUHHdr->dstRect.top = (int)pOR->nTopRect;
  108. pUHHdr->dstRect.right = (int)(pOR->nLeftRect + pOR->nWidth - 1);
  109. pUHHdr->dstRect.bottom = (int)(pOR->nTopRect + pOR->nHeight - 1);
  110. _pUh->UH_ResetClipRegion();
  111. }
  112. else {
  113. _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top,
  114. pUHHdr->dstRect.right, pUHHdr->dstRect.bottom);
  115. }
  116. // Copy non-coordinate fields if present.
  117. if (FieldFlags & 0x10) {
  118. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  119. pOR->Color.u.rgb.red = *pFieldDecode++;
  120. }
  121. if (FieldFlags & 0x20) {
  122. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  123. pOR->Color.u.rgb.green = *pFieldDecode++;
  124. }
  125. if (FieldFlags & 0x40) {
  126. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  127. pOR->Color.u.rgb.blue = *pFieldDecode++;
  128. }
  129. // Return the incremented pointer to the main routine.
  130. *ppFieldDecode = pFieldDecode;
  131. #ifdef DC_HICOLOR
  132. TRC_NRM((TB,_T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#06lx)"),
  133. (int)pOR->nLeftRect,
  134. (int)pOR->nTopRect,
  135. (int)pOR->nWidth,
  136. (int)pOR->nHeight,
  137. *((PDCUINT32)&pOR->Color) ));
  138. #else
  139. TRC_NRM((TB,_T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#02x)"),
  140. (int)pOR->nLeftRect,
  141. (int)pOR->nTopRect,
  142. (int)pOR->nWidth,
  143. (int)pOR->nHeight,
  144. (int)pOR->Color.u.index));
  145. #endif
  146. // Create a solid brush of the required color. Hard-coded to use
  147. // palette brushes for now because we don't support anything more.
  148. _pUh->UHUseSolidPaletteBrush(pOR->Color);
  149. // Do the blt.
  150. TIMERSTART;
  151. PatBlt(_pUh->_UH.hdcDraw, (int)pOR->nLeftRect, (int)pOR->nTopRect,
  152. (int)pOR->nWidth, (int)pOR->nHeight, PATCOPY);
  153. TIMERSTOP;
  154. UPDATECOUNTER(FC_OPAQUERECT_TYPE);
  155. DC_EXIT_POINT:
  156. DC_END_FN();
  157. return hr;
  158. }
  159. /****************************************************************************/
  160. // ODDecodeMemBlt
  161. //
  162. // Fast-path decode function for MemBlt (3rd most common order in WinBench99).
  163. /****************************************************************************/
  164. HRESULT DCINTERNAL COD::ODDecodeMemBlt(
  165. BYTE ControlFlags,
  166. BYTE FAR * FAR *ppFieldDecode,
  167. DCUINT dataLen,
  168. UINT32 FieldFlags)
  169. {
  170. HRESULT hr = S_OK;
  171. PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastMembltR2;
  172. MEMBLT_R2_ORDER FAR *pMB = (MEMBLT_R2_ORDER FAR *)
  173. (_OD.lastMembltR2 + UH_ORDER_HEADER_SIZE);
  174. BYTE FAR *pFieldDecode = *ppFieldDecode;
  175. BYTE FAR *pEnd = pFieldDecode + dataLen;
  176. DC_BEGIN_FN("ODDecodeMemBlt");
  177. // CacheID is a fixed 2-byte field.
  178. if (FieldFlags & 0x0001) {
  179. OD_DECODE_CHECK_READ( pFieldDecode, UINT16, pEnd, hr );
  180. pMB->Common.cacheId = *((UINT16 UNALIGNED FAR *)pFieldDecode);
  181. pFieldDecode += 2;
  182. }
  183. if (ControlFlags & TS_DELTA_COORDINATES) {
  184. // All coord fields are 1-byte signed deltas from the last values.
  185. if (FieldFlags & 0x0002) {
  186. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  187. pMB->Common.nLeftRect += *((char FAR *)pFieldDecode);
  188. pFieldDecode++;
  189. }
  190. if (FieldFlags & 0x0004) {
  191. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  192. pMB->Common.nTopRect += *((char FAR *)pFieldDecode);
  193. pFieldDecode++;
  194. }
  195. if (FieldFlags & 0x0008) {
  196. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  197. pMB->Common.nWidth += *((char FAR *)pFieldDecode);
  198. pFieldDecode++;
  199. }
  200. if (FieldFlags & 0x0010) {
  201. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  202. pMB->Common.nHeight += *((char FAR *)pFieldDecode);
  203. pFieldDecode++;
  204. }
  205. // bRop is just 1 byte.
  206. if (FieldFlags & 0x0020) {
  207. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  208. pMB->Common.bRop = *pFieldDecode++;
  209. }
  210. if (FieldFlags & 0x0040) {
  211. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  212. pMB->Common.nXSrc += *((char FAR *)pFieldDecode);
  213. pFieldDecode++;
  214. }
  215. if (FieldFlags & 0x0080) {
  216. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  217. pMB->Common.nYSrc += *((char FAR *)pFieldDecode);
  218. pFieldDecode++;
  219. }
  220. }
  221. else {
  222. // All coord fields are 2-byte values.sign-extended from the output.
  223. if (FieldFlags & 0x0002) {
  224. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  225. pMB->Common.nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  226. pFieldDecode += 2;
  227. }
  228. if (FieldFlags & 0x0004) {
  229. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  230. pMB->Common.nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  231. pFieldDecode += 2;
  232. }
  233. if (FieldFlags & 0x0008) {
  234. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  235. pMB->Common.nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode);
  236. pFieldDecode += 2;
  237. }
  238. if (FieldFlags & 0x0010) {
  239. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  240. pMB->Common.nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode);
  241. pFieldDecode += 2;
  242. }
  243. // bRop is just 1 byte.
  244. if (FieldFlags & 0x0020) {
  245. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  246. pMB->Common.bRop = *pFieldDecode++;
  247. }
  248. if (FieldFlags & 0x0040) {
  249. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  250. pMB->Common.nXSrc = *((INT16 UNALIGNED FAR *)pFieldDecode);
  251. pFieldDecode += 2;
  252. }
  253. if (FieldFlags & 0x0080) {
  254. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  255. pMB->Common.nYSrc = *((INT16 UNALIGNED FAR *)pFieldDecode);
  256. pFieldDecode += 2;
  257. }
  258. }
  259. // CacheIndex is always a 2-byte field.
  260. if (FieldFlags & 0x0100) {
  261. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  262. pMB->Common.cacheIndex = *((UINT16 UNALIGNED FAR *)pFieldDecode);
  263. pFieldDecode += 2;
  264. }
  265. // If we've not already set the bounds (the order didn't contain
  266. // any), set the bounds to the blt rect and reset the clip region.
  267. // This rect might be needed later to add to the clip region for
  268. // updating the shadow buffer to the screen.
  269. if (!(ControlFlags & TS_BOUNDS)) {
  270. pUHHdr->dstRect.left = (int)pMB->Common.nLeftRect;
  271. pUHHdr->dstRect.top = (int)pMB->Common.nTopRect;
  272. pUHHdr->dstRect.right = (int)(pMB->Common.nLeftRect +
  273. pMB->Common.nWidth - 1);
  274. pUHHdr->dstRect.bottom = (int)(pMB->Common.nTopRect +
  275. pMB->Common.nHeight - 1);
  276. _pUh->UH_ResetClipRegion();
  277. }
  278. else {
  279. _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top,
  280. pUHHdr->dstRect.right, pUHHdr->dstRect.bottom);
  281. }
  282. // Return the incremented pointer to the main routine.
  283. *ppFieldDecode = pFieldDecode;
  284. TRC_NRM((TB, _T("ORDER: MemBlt")));
  285. hr = _pUh->UHDrawMemBltOrder(_pUh->_UH.hdcDraw, &pMB->Common);
  286. DC_QUIT_ON_FAIL(hr);
  287. #ifdef DC_DEBUG
  288. if (_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap ||
  289. _pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow) {
  290. // Draw hatching over the memblt data if the option is enabled.
  291. if (_pUh->_UH.hatchMemBltOrderData) {
  292. unsigned cacheId;
  293. unsigned cacheEntry;
  294. cacheId = DCLO8(pMB->Common.cacheId);
  295. cacheEntry = pMB->Common.cacheIndex;
  296. if (cacheId < _pUh->_UH.NumBitmapCaches &&
  297. cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX) {
  298. if (_pUh->_UH.MonitorEntries[0] != NULL) {
  299. _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect,
  300. (int)(pMB->Common.nLeftRect + pMB->Common.nWidth),
  301. (int)(pMB->Common.nTopRect + pMB->Common.nHeight),
  302. (_pUh->_UH.MonitorEntries[cacheId][cacheEntry].UsageCount == 1) ?
  303. UH_RGB_MAGENTA : UH_RGB_BLUE,
  304. UH_BRUSHTYPE_FDIAGONAL);
  305. } else {
  306. _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect,
  307. (int)(pMB->Common.nLeftRect + pMB->Common.nWidth),
  308. (int)(pMB->Common.nTopRect + pMB->Common.nHeight),
  309. UH_RGB_MAGENTA,
  310. UH_BRUSHTYPE_FDIAGONAL);
  311. }
  312. }
  313. }
  314. // Label the memblt if the option is enabled.
  315. if (_pUh->_UH.labelMemBltOrders) {
  316. unsigned cacheId;
  317. unsigned cacheEntry;
  318. cacheId = DCLO8(pMB->Common.cacheId);
  319. cacheEntry = pMB->Common.cacheIndex;
  320. if (cacheId < _pUh->_UH.NumBitmapCaches &&
  321. cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX) {
  322. _pUh->UHLabelMemBltOrder((int)pMB->Common.nLeftRect,
  323. (int)pMB->Common.nTopRect,
  324. pMB->Common.cacheId, pMB->Common.cacheIndex);
  325. }
  326. }
  327. }
  328. #endif /* DC_DEBUG */
  329. DC_EXIT_POINT:
  330. DC_END_FN();
  331. return hr;
  332. }
  333. /****************************************************************************/
  334. // ODDecodeLineTo
  335. //
  336. // Fast-path decode function for LineTo (5th most common order in WinBench99).
  337. /****************************************************************************/
  338. HRESULT DCINTERNAL COD::ODDecodeLineTo(
  339. BYTE ControlFlags,
  340. BYTE FAR * FAR *ppFieldDecode,
  341. DCUINT dataLen,
  342. UINT32 FieldFlags)
  343. {
  344. HRESULT hr = S_OK;
  345. PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastLineTo;
  346. LINETO_ORDER FAR *pLT = (LINETO_ORDER FAR *)
  347. (_OD.lastLineTo + UH_ORDER_HEADER_SIZE);
  348. BYTE FAR *pFieldDecode = *ppFieldDecode;
  349. BYTE FAR *pEnd = pFieldDecode + dataLen;
  350. DC_BEGIN_FN("ODDecodeLineTo");
  351. // BackMode is always a 2-byte field.
  352. if (FieldFlags & 0x0001) {
  353. OD_DECODE_CHECK_READ( pFieldDecode, UINT16, pEnd, hr );
  354. pLT->BackMode = *((UINT16 UNALIGNED FAR *)pFieldDecode);
  355. pFieldDecode += 2;
  356. }
  357. if (ControlFlags & TS_DELTA_COORDINATES) {
  358. // All coord fields are 1-byte signed deltas from the last values.
  359. if (FieldFlags & 0x0002) {
  360. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  361. pLT->nXStart += *((char FAR *)pFieldDecode);
  362. pFieldDecode++;
  363. }
  364. if (FieldFlags & 0x0004) {
  365. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  366. pLT->nYStart += *((char FAR *)pFieldDecode);
  367. pFieldDecode++;
  368. }
  369. if (FieldFlags & 0x0008) {
  370. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  371. pLT->nXEnd += *((char FAR *)pFieldDecode);
  372. pFieldDecode++;
  373. }
  374. if (FieldFlags & 0x0010) {
  375. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  376. pLT->nYEnd += *((char FAR *)pFieldDecode);
  377. pFieldDecode++;
  378. }
  379. }
  380. else {
  381. // All coord fields are 2-byte values.sign-extended from the output.
  382. if (FieldFlags & 0x0002) {
  383. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  384. pLT->nXStart = *((INT16 UNALIGNED FAR *)pFieldDecode);
  385. pFieldDecode += 2;
  386. }
  387. if (FieldFlags & 0x0004) {
  388. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  389. pLT->nYStart = *((INT16 UNALIGNED FAR *)pFieldDecode);
  390. pFieldDecode += 2;
  391. }
  392. if (FieldFlags & 0x0008) {
  393. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  394. pLT->nXEnd = *((INT16 UNALIGNED FAR *)pFieldDecode);
  395. pFieldDecode += 2;
  396. }
  397. if (FieldFlags & 0x0010) {
  398. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  399. pLT->nYEnd = *((INT16 UNALIGNED FAR *)pFieldDecode);
  400. pFieldDecode += 2;
  401. }
  402. }
  403. // If we've not already set the bounds (the order didn't contain
  404. // any), set the bounds to the blt rect and reset the clip region.
  405. // This rect might be needed later to add to the clip region for
  406. // updating the shadow buffer to the screen.
  407. if (!(ControlFlags & TS_BOUNDS)) {
  408. if (pLT->nXStart < pLT->nXEnd) {
  409. pUHHdr->dstRect.left = (int)pLT->nXStart;
  410. pUHHdr->dstRect.right = (int)pLT->nXEnd;
  411. }
  412. else {
  413. pUHHdr->dstRect.right = (int)pLT->nXStart;
  414. pUHHdr->dstRect.left = (int)pLT->nXEnd;
  415. }
  416. if (pLT->nYStart < pLT->nYEnd) {
  417. pUHHdr->dstRect.top = (int)pLT->nYStart;
  418. pUHHdr->dstRect.bottom = (int)pLT->nYEnd;
  419. }
  420. else {
  421. pUHHdr->dstRect.bottom = (int)pLT->nYStart;
  422. pUHHdr->dstRect.top = (int)pLT->nYEnd;
  423. }
  424. _pUh->UH_ResetClipRegion();
  425. }
  426. else {
  427. _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top,
  428. pUHHdr->dstRect.right, pUHHdr->dstRect.bottom);
  429. }
  430. // Copy non-coordinate fields if present.
  431. if (FieldFlags & 0x0020) {
  432. OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr );
  433. pLT->BackColor.u.rgb.red = *pFieldDecode++;
  434. pLT->BackColor.u.rgb.green = *pFieldDecode++;
  435. pLT->BackColor.u.rgb.blue = *pFieldDecode++;
  436. }
  437. if (FieldFlags & 0x0040) {
  438. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  439. pLT->ROP2 = *pFieldDecode++;
  440. }
  441. if (FieldFlags & 0x0080) {
  442. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  443. pLT->PenStyle = *pFieldDecode++;
  444. }
  445. if (FieldFlags & 0x0100) {
  446. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  447. pLT->PenWidth = *pFieldDecode++;
  448. }
  449. if (FieldFlags & 0x0200) {
  450. OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr );
  451. pLT->PenColor.u.rgb.red = *pFieldDecode++;
  452. pLT->PenColor.u.rgb.green = *pFieldDecode++;
  453. pLT->PenColor.u.rgb.blue = *pFieldDecode++;
  454. }
  455. // Return the incremented pointer to the main routine.
  456. *ppFieldDecode = pFieldDecode;
  457. TRC_NRM((TB,_T("ORDER: LineTo BC %08lX BM %04X rop2 %04X pen ")
  458. _T("%04X %04X %08lX x1 %d y1 %d x2 %d y2 %d"),
  459. pLT->BackColor,
  460. pLT->BackMode,
  461. pLT->ROP2,
  462. pLT->PenStyle,
  463. pLT->PenWidth,
  464. pLT->PenColor,
  465. pLT->nXStart,
  466. pLT->nYStart,
  467. pLT->nXEnd,
  468. pLT->nYEnd));
  469. UHUseBkColor(pLT->BackColor, UH_COLOR_PALETTE, _pUh);
  470. UHUseBkMode((int)pLT->BackMode, _pUh);
  471. UHUseROP2((int)pLT->ROP2, _pUh);
  472. _pUh->UHUsePen((unsigned)pLT->PenStyle, (unsigned)pLT->PenWidth, pLT->PenColor,
  473. UH_COLOR_PALETTE);
  474. TIMERSTART;
  475. #ifdef OS_WINCE
  476. {
  477. POINT pts[2];
  478. pts[0].x = pLT->nXStart;
  479. pts[0].y = pLT->nYStart;
  480. pts[1].x = pLT->nXEnd;
  481. pts[1].y = pLT->nYEnd;
  482. Polyline(_pUh->_UH.hdcDraw, pts, 2);
  483. }
  484. #else
  485. MoveToEx(_pUh->_UH.hdcDraw, (int)pLT->nXStart, (int)pLT->nYStart, NULL);
  486. LineTo(_pUh->_UH.hdcDraw, (int)pLT->nXEnd, (int)pLT->nYEnd);
  487. #endif // OS_WINCE
  488. TIMERSTOP;
  489. UPDATECOUNTER(FC_LINETO_TYPE);
  490. #ifdef DC_ROTTER
  491. #pragma message("ROTTER keystroke return code compiled in")
  492. /****************************************************************/
  493. /* For use with ROund Trip TimER application */
  494. /* */
  495. /* ROTTER runs on the server and initiates a series of drawing */
  496. /* commands to the screen, ending with a specific unusual line */
  497. /* drawing command (from (1,1) and (51,51) with MERGEPENNOT ROP)*/
  498. /* */
  499. /* It then waits until it receives a 't' or 'T' keystroke after */
  500. /* which it calculates the elapsed time between the start of */
  501. /* the drawing and the receipt of the keystroke. This is the */
  502. /* round trip time. */
  503. /* */
  504. /* The following code checks to see whether ROTTER has finished */
  505. /* drawing, by testing all LineTo commands to see if any are 50 */
  506. /* across by 50 down with MERGEPENNOT ROP. We are not able to */
  507. /* simply test that the line's start and endpoints are at (1,1) */
  508. /* and (51,51) because the coordinates that are received by */
  509. /* Ducati depend on the position of ROTTER's window on the */
  510. /* terminal. */
  511. /* */
  512. /* When the special case is detected we post a "T", by */
  513. /* synthesizing a press of the T key and injecting it into the */
  514. /* IH input handler window, which causes IH to send a key-down */
  515. /* key-up sequence for the T key to the server. */
  516. /****************************************************************/
  517. if ((R2_MERGEPENNOT == (pLineTo->ROP2)) &&
  518. (50 == ((pLineTo->nXEnd) - (pLineTo->nXStart))) &&
  519. (50 == ((pLineTo->nYEnd) - (pLineTo->nYStart))))
  520. {
  521. TRC_ALT((TB,_T("MERGEPENNOT ROP2 detected. Sending 'T'")));
  522. PostMessage(IH_GetInputHandlerWindow(),
  523. WM_KEYDOWN,
  524. 0x00000054,
  525. 0x00140001);
  526. PostMessage(IH_GetInputHandlerWindow(),
  527. WM_KEYUP,
  528. 0x00000054,
  529. 0xC0140001);
  530. }
  531. #endif /* DC_ROTTER */
  532. DC_EXIT_POINT:
  533. DC_END_FN();
  534. return hr;
  535. }
  536. /****************************************************************************/
  537. // ODDecodePatBlt
  538. //
  539. // Fast-path decode function for PatBlt.
  540. /****************************************************************************/
  541. HRESULT DCINTERNAL COD::ODDecodePatBlt(
  542. BYTE ControlFlags,
  543. BYTE FAR * FAR *ppFieldDecode,
  544. DCUINT dataLen,
  545. UINT32 FieldFlags)
  546. {
  547. HRESULT hr = S_OK;
  548. UINT32 WindowsROP;
  549. PUH_ORDER pUHHdr = (PUH_ORDER)_OD.lastPatblt;
  550. PATBLT_ORDER FAR *pPB = (PATBLT_ORDER FAR *)
  551. (_OD.lastPatblt + UH_ORDER_HEADER_SIZE);
  552. BYTE FAR *pFieldDecode = *ppFieldDecode;
  553. BYTE FAR *pEnd = pFieldDecode + dataLen;
  554. DC_BEGIN_FN("ODDecodePatBlt");
  555. if (ControlFlags & TS_DELTA_COORDINATES) {
  556. // All coord fields are 1-byte signed deltas from the last values.
  557. if (FieldFlags & 0x0001) {
  558. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  559. pPB->nLeftRect += *((char FAR *)pFieldDecode);
  560. pFieldDecode++;
  561. }
  562. if (FieldFlags & 0x0002) {
  563. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  564. pPB->nTopRect += *((char FAR *)pFieldDecode);
  565. pFieldDecode++;
  566. }
  567. if (FieldFlags & 0x0004) {
  568. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  569. pPB->nWidth += *((char FAR *)pFieldDecode);
  570. pFieldDecode++;
  571. }
  572. if (FieldFlags & 0x0008) {
  573. OD_DECODE_CHECK_READ( pFieldDecode, char, pEnd, hr );
  574. pPB->nHeight += *((char FAR *)pFieldDecode);
  575. pFieldDecode++;
  576. }
  577. }
  578. else {
  579. // All coord fields are 2-byte values.sign-extended from the output.
  580. if (FieldFlags & 0x0001) {
  581. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  582. pPB->nLeftRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  583. pFieldDecode += 2;
  584. }
  585. if (FieldFlags & 0x0002) {
  586. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  587. pPB->nTopRect = *((INT16 UNALIGNED FAR *)pFieldDecode);
  588. pFieldDecode += 2;
  589. }
  590. if (FieldFlags & 0x0004) {
  591. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  592. pPB->nWidth = *((INT16 UNALIGNED FAR *)pFieldDecode);
  593. pFieldDecode += 2;
  594. }
  595. if (FieldFlags & 0x0008) {
  596. OD_DECODE_CHECK_READ( pFieldDecode, INT16, pEnd, hr );
  597. pPB->nHeight = *((INT16 UNALIGNED FAR *)pFieldDecode);
  598. pFieldDecode += 2;
  599. }
  600. }
  601. // If we've not already set the bounds (the order didn't contain
  602. // any), set the bounds to the blt rect and reset the clip region.
  603. // This rect might be needed later to add to the clip region for
  604. // updating the shadow buffer to the screen.
  605. if (!(ControlFlags & TS_BOUNDS)) {
  606. pUHHdr->dstRect.left = (int)pPB->nLeftRect;
  607. pUHHdr->dstRect.top = (int)pPB->nTopRect;
  608. pUHHdr->dstRect.right = (int)(pPB->nLeftRect + pPB->nWidth - 1);
  609. pUHHdr->dstRect.bottom = (int)(pPB->nTopRect + pPB->nHeight - 1);
  610. _pUh->UH_ResetClipRegion();
  611. }
  612. else {
  613. _pUh->UH_SetClipRegion(pUHHdr->dstRect.left, pUHHdr->dstRect.top,
  614. pUHHdr->dstRect.right, pUHHdr->dstRect.bottom);
  615. }
  616. // Copy non-coordinate fields if present.
  617. if (FieldFlags & 0x0010) {
  618. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  619. pPB->bRop = *pFieldDecode++;
  620. }
  621. if (FieldFlags & 0x0020) {
  622. OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr );
  623. pPB->BackColor.u.rgb.red = *pFieldDecode++;
  624. pPB->BackColor.u.rgb.green = *pFieldDecode++;
  625. pPB->BackColor.u.rgb.blue = *pFieldDecode++;
  626. }
  627. if (FieldFlags & 0x0040) {
  628. OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 3, pEnd, hr );
  629. pPB->ForeColor.u.rgb.red = *pFieldDecode++;
  630. pPB->ForeColor.u.rgb.green = *pFieldDecode++;
  631. pPB->ForeColor.u.rgb.blue = *pFieldDecode++;
  632. }
  633. if (FieldFlags & 0x0080) {
  634. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  635. pPB->BrushOrgX = *pFieldDecode++;
  636. }
  637. if (FieldFlags & 0x0100) {
  638. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  639. pPB->BrushOrgY = *pFieldDecode++;
  640. }
  641. if (FieldFlags & 0x0200) {
  642. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  643. pPB->BrushStyle = *pFieldDecode++;
  644. }
  645. if (FieldFlags & 0x0400) {
  646. OD_DECODE_CHECK_READ( pFieldDecode, BYTE, pEnd, hr );
  647. pPB->BrushHatch = *pFieldDecode++;
  648. }
  649. if (FieldFlags & 0x0800) {
  650. OD_DECODE_CHECK_READ_MULT( pFieldDecode, BYTE, 7, pEnd, hr );
  651. memcpy(&pPB->BrushExtra, pFieldDecode, 7);
  652. pFieldDecode += 7;
  653. }
  654. // Return the incremented pointer to the main routine.
  655. *ppFieldDecode = pFieldDecode;
  656. TRC_NRM((TB, _T("ORDER: PatBlt Brush %02X %02X BC %02x FC %02x ")
  657. _T("X %d Y %d w %d h %d rop %08lX"),
  658. (int)pPB->BrushStyle,
  659. (int)pPB->BrushHatch,
  660. (int)pPB->BackColor.u.index,
  661. (int)pPB->ForeColor.u.index,
  662. (int)pPB->nLeftRect,
  663. (int)pPB->nTopRect,
  664. (int)pPB->nWidth,
  665. (int)pPB->nHeight,
  666. _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop)));
  667. // Explicitly use palette entries; we don't support more than that now.
  668. UHUseBkColor(pPB->BackColor, UH_COLOR_PALETTE, _pUh);
  669. UHUseTextColor(pPB->ForeColor, UH_COLOR_PALETTE, _pUh);
  670. UHUseBrushOrg((int)pPB->BrushOrgX, (int)pPB->BrushOrgY,_pUh);
  671. hr = _pUh->UHUseBrush((unsigned)pPB->BrushStyle, (unsigned)pPB->BrushHatch,
  672. pPB->ForeColor, UH_COLOR_PALETTE, pPB->BrushExtra);
  673. DC_QUIT_ON_FAIL(hr);
  674. WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop);
  675. TIMERSTART;
  676. PatBlt(_pUh->_UH.hdcDraw, (int)pPB->nLeftRect, (int)pPB->nTopRect,
  677. (int)pPB->nWidth, (int)pPB->nHeight, WindowsROP);
  678. TIMERSTOP;
  679. UPDATECOUNTER(FC_PATBLT_TYPE);
  680. DC_EXIT_POINT:
  681. DC_END_FN();
  682. return hr;
  683. }
  684. /****************************************************************************/
  685. // ODHandleMultiPatBlt
  686. //
  687. // Handler for MultiPatBlt orders.
  688. /****************************************************************************/
  689. HRESULT DCINTERNAL COD::ODHandleMultiPatBlt(PUH_ORDER pOrder,
  690. UINT16 uiVarDataLen, BOOL bBoundsSet)
  691. {
  692. HRESULT hr = S_OK;
  693. unsigned i;
  694. UINT32 WindowsROP;
  695. RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1];
  696. MULTI_PATBLT_ORDER FAR *pPB = (MULTI_PATBLT_ORDER FAR *)pOrder->orderData;
  697. DC_BEGIN_FN("ODHandleMultiPatBlt");
  698. // If there are no rects, we have nothing to draw. The server in error, or
  699. // a bad server, can send 0 rects. In this case we should simply defend our
  700. // selves
  701. if (0 == pPB->nDeltaEntries) {
  702. TRC_ERR((TB,_T("Multipatblt with no rects; uiVarDataLen=%u"),
  703. uiVarDataLen));
  704. hr = S_OK;
  705. DC_QUIT;
  706. }
  707. // If we've not already set the bounds (the order didn't contain
  708. // any), set the bounds to the blt rect and reset the clip region.
  709. // This rect might be needed later to add to the clip region for
  710. // updating the shadow buffer to the screen.
  711. if (!bBoundsSet) {
  712. pOrder->dstRect.left = (int)pPB->nLeftRect;
  713. pOrder->dstRect.top = (int)pPB->nTopRect;
  714. pOrder->dstRect.right = (int)(pPB->nLeftRect + pPB->nWidth - 1);
  715. pOrder->dstRect.bottom = (int)(pPB->nTopRect + pPB->nHeight - 1);
  716. _pUh->UH_ResetClipRegion();
  717. }
  718. else {
  719. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  720. pOrder->dstRect.right, pOrder->dstRect.bottom);
  721. }
  722. TRC_NRM((TB, _T("ORDER: PatBlt Brush %02X %02X BC %02x FC %02x ")
  723. _T("X %d Y %d w %d h %d rop %08lX"),
  724. (int)pPB->BrushStyle,
  725. (int)pPB->BrushHatch,
  726. (int)pPB->BackColor.u.index,
  727. (int)pPB->ForeColor.u.index,
  728. (int)pPB->nLeftRect,
  729. (int)pPB->nTopRect,
  730. (int)pPB->nWidth,
  731. (int)pPB->nHeight,
  732. _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop)));
  733. // Explicitly use palette entries; we don't support more than that now.
  734. UHUseBkColor(pPB->BackColor, UH_COLOR_PALETTE, _pUh);
  735. UHUseTextColor(pPB->ForeColor, UH_COLOR_PALETTE, _pUh);
  736. UHUseBrushOrg((int)pPB->BrushOrgX, (int)pPB->BrushOrgY, _pUh);
  737. hr = _pUh->UHUseBrush((unsigned)pPB->BrushStyle, (unsigned)pPB->BrushHatch,
  738. pPB->ForeColor, UH_COLOR_PALETTE, pPB->BrushExtra);
  739. DC_QUIT_ON_FAIL(hr);
  740. hr = ODDecodeMultipleRects(Rects, pPB->nDeltaEntries, &pPB->codedDeltaList,
  741. uiVarDataLen);
  742. DC_QUIT_ON_FAIL(hr);
  743. WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pPB->bRop);
  744. TIMERSTART;
  745. for (i = 0; i < pPB->nDeltaEntries; i++ )
  746. PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top,
  747. (int)(Rects[i].right - Rects[i].left),
  748. (int)(Rects[i].bottom - Rects[i].top),
  749. WindowsROP);
  750. TIMERSTOP;
  751. UPDATECOUNTER(FC_PATBLT_TYPE);
  752. DC_EXIT_POINT:
  753. DC_END_FN();
  754. return hr;
  755. }
  756. /****************************************************************************/
  757. // ODHandleDstBlts
  758. //
  759. // Order handler for both DstBlt and MultiDstBlt.
  760. /****************************************************************************/
  761. HRESULT DCINTERNAL COD::ODHandleDstBlts(PUH_ORDER pOrder, UINT16 uiVarDataLen,
  762. BOOL bBoundsSet)
  763. {
  764. HRESULT hr = S_OK;
  765. RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1];
  766. UINT32 WindowsROP;
  767. unsigned i;
  768. LPDSTBLT_ORDER pDB = (LPDSTBLT_ORDER)pOrder->orderData;
  769. DC_BEGIN_FN("ODHandleDstBlts");
  770. // If we've not already set the bounds (the order didn't contain
  771. // any), set the bounds to the blt rect and reset the clip region.
  772. // This rect might be needed later to add to the clip region for
  773. // updating the shadow buffer to the screen.
  774. if (!bBoundsSet) {
  775. pOrder->dstRect.left = (int)pDB->nLeftRect;
  776. pOrder->dstRect.top = (int)pDB->nTopRect;
  777. pOrder->dstRect.right = (int)(pDB->nLeftRect + pDB->nWidth - 1);
  778. pOrder->dstRect.bottom = (int)(pDB->nTopRect + pDB->nHeight - 1);
  779. _pUh->UH_ResetClipRegion();
  780. }
  781. else {
  782. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  783. pOrder->dstRect.right, pOrder->dstRect.bottom);
  784. }
  785. WindowsROP = _pUh->UHConvertToWindowsROP(pDB->bRop);
  786. if (pDB->type == TS_ENC_DSTBLT_ORDER) {
  787. TRC_NRM((TB, _T("ORDER: DstBlt X %d Y %d w %d h %d rop %08lX"),
  788. (int)pDB->nLeftRect, (int)pDB->nTopRect,
  789. (int)pDB->nWidth, (int)pDB->nHeight,
  790. WindowsROP));
  791. TRC_NRM((TB, _T("Single")));
  792. TRC_ASSERT((0==uiVarDataLen),
  793. (TB,_T("Recieved varaible length data in fixed length order")));
  794. TIMERSTART;
  795. PatBlt(_pUh->_UH.hdcDraw, (int)pDB->nLeftRect, (int)pDB->nTopRect,
  796. (int)pDB->nWidth, (int)pDB->nHeight, WindowsROP);
  797. TIMERSTOP;
  798. UPDATECOUNTER(FC_DSTBLT_TYPE);
  799. }
  800. else {
  801. LPMULTI_DSTBLT_ORDER pMDB = (LPMULTI_DSTBLT_ORDER)pDB;
  802. TRC_NRM((TB, _T("ORDER: MultiDstBlt X %d Y %d w %d h %d rop %08lX ")
  803. _T("nDeltas %d"), (int)pMDB->nLeftRect, (int)pMDB->nTopRect,
  804. (int)pMDB->nWidth, (int)pMDB->nHeight, WindowsROP,
  805. pMDB->nDeltaEntries));
  806. if (0 == pMDB->nDeltaEntries) {
  807. TRC_ERR((TB,_T("MultiDstBlt with no rects; uiVarDataLen=%u"),
  808. uiVarDataLen));
  809. hr = S_OK;
  810. DC_QUIT;
  811. }
  812. hr = ODDecodeMultipleRects(Rects, pMDB->nDeltaEntries,
  813. &pMDB->codedDeltaList, uiVarDataLen);
  814. DC_QUIT_ON_FAIL(hr);
  815. TIMERSTART;
  816. for (i = 0; i < pMDB->nDeltaEntries; i++)
  817. PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top,
  818. (int)(Rects[i].right - Rects[i].left),
  819. (int)(Rects[i].bottom - Rects[i].top),
  820. WindowsROP);
  821. TIMERSTOP;
  822. UPDATECOUNTER(FC_DSTBLT_TYPE);
  823. }
  824. DC_EXIT_POINT:
  825. DC_END_FN();
  826. return hr;
  827. }
  828. /****************************************************************************/
  829. // ODHandleScrBlts
  830. //
  831. // Order handler for ScrBlt and MultiScrBlt.
  832. /****************************************************************************/
  833. HRESULT DCINTERNAL COD::ODHandleScrBlts(PUH_ORDER pOrder, UINT16 uiVarDataLen,
  834. BOOL bBoundsSet)
  835. {
  836. HRESULT hr = S_OK;
  837. RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1];
  838. UINT32 WindowsROP;
  839. unsigned i;
  840. LPSCRBLT_ORDER pSB = (LPSCRBLT_ORDER)pOrder->orderData;
  841. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  842. RECT rectTemp, rectIntersect;
  843. int nX, nY;
  844. int nWidth;
  845. #endif
  846. DC_BEGIN_FN("ODHandleScrBlts");
  847. // If we've not already set the bounds (the order didn't contain
  848. // any), set the bounds to the blt rect and reset the clip region.
  849. // This rect might be needed later to add to the clip region for
  850. // updating the shadow buffer to the screen.
  851. if (!bBoundsSet) {
  852. pOrder->dstRect.left = (int)pSB->nLeftRect;
  853. pOrder->dstRect.top = (int)pSB->nTopRect;
  854. pOrder->dstRect.right = (int)(pSB->nLeftRect + pSB->nWidth - 1);
  855. pOrder->dstRect.bottom = (int)(pSB->nTopRect + pSB->nHeight - 1);
  856. _pUh->UH_ResetClipRegion();
  857. }
  858. else {
  859. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  860. pOrder->dstRect.right, pOrder->dstRect.bottom);
  861. }
  862. WindowsROP = _pUh->UHConvertToWindowsROP((unsigned)pSB->bRop);
  863. if (pSB->type == TS_ENC_SCRBLT_ORDER) {
  864. TRC_NRM((TB, _T("ORDER: ScrBlt dx %d dy %d w %d h %d sx %d sy %d rop %08lX"),
  865. (int)pSB->nLeftRect, (int)pSB->nTopRect,
  866. (int)pSB->nWidth, (int)pSB->nHeight,
  867. (int)pSB->nXSrc, (int)pSB->nYSrc, WindowsROP));
  868. TIMERSTART;
  869. // If we turned off screenblt support due to shadowing a
  870. // large session from WinCE, the server will not currently
  871. // register that and will still send us ScrBlts. We won't
  872. // have a shadow bitmap in this scenario, but we can deal
  873. // with this by invalidating the affected output area.
  874. if (_pCc->_ccCombinedCapabilities.orderCapabilitySet.
  875. orderSupport[TS_NEG_SCRBLT_INDEX]) {
  876. TRC_DBG((TB, _T("Real ScrBlt")));
  877. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  878. if (!_pUh->_UH.DontUseShadowBitmap && _pUh->_UH.hdcShadowBitmap ) {
  879. #else
  880. if (_pUh->_UH.hdcShadowBitmap) {
  881. #endif
  882. if (!BitBlt(_pUh->_UH.hdcDraw, (int)pSB->nLeftRect, (int)pSB->nTopRect,
  883. (int)pSB->nWidth, (int)pSB->nHeight, _pUh->_UH.hdcShadowBitmap,
  884. (int)pSB->nXSrc, (int)pSB->nYSrc,
  885. WindowsROP)) {
  886. TRC_ERR((TB, _T("BitBlt failed")));
  887. }
  888. }
  889. else {
  890. #ifdef OS_WINCE
  891. if (!ODHandleAlwaysOnTopRects(pSB))
  892. {
  893. #endif
  894. if (!BitBlt(_pUh->_UH.hdcDraw, (int)pSB->nLeftRect, (int)pSB->nTopRect,
  895. (int)pSB->nWidth, (int)pSB->nHeight, _pUh->_UH.hdcOutputWindow,
  896. (int)pSB->nXSrc, (int)pSB->nYSrc,
  897. WindowsROP)) {
  898. TRC_ERR((TB, _T("BitBlt failed")));
  899. }
  900. #ifdef OS_WINCE
  901. }
  902. #endif
  903. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  904. if ((_pUh->_UH.fIsBBarVisible) && (_pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow))
  905. {
  906. rectTemp.left = (int)(pSB->nXSrc);
  907. rectTemp.top = (int)(pSB->nYSrc);
  908. rectTemp.right = (int)(pSB->nXSrc + pSB->nWidth);
  909. rectTemp.bottom = (int)(pSB->nYSrc + pSB->nHeight);
  910. if (IntersectRect(&rectIntersect, &rectTemp, &(_pUh->_UH.rectBBar))) {
  911. nX = pSB->nLeftRect - pSB->nXSrc;
  912. nY = pSB->nTopRect - pSB->nYSrc;
  913. rectIntersect.left += nX;
  914. rectIntersect.right += nX;
  915. rectIntersect.top += nY;
  916. rectIntersect.bottom += nY;
  917. // In fullscreen, when moving a window quickly inside and outside the bbar
  918. // part of window intersected by bbar is not drawn correctly
  919. // here we invalidate larger rectangle to solve this problem
  920. nWidth = rectIntersect.right - rectIntersect.left;
  921. rectIntersect.left -= nWidth;
  922. rectIntersect.right += nWidth;
  923. rectIntersect.bottom += _pUh->_UH.rectBBar.bottom * 2;
  924. InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectIntersect, FALSE);
  925. }
  926. }
  927. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  928. }
  929. }
  930. else {
  931. // Alternative processing for when we get a ScrBlt
  932. // without having advertised support for it.
  933. TRC_DBG((TB, _T("Simulated ScrBlt")));
  934. Rects[0].left = (int)(pSB->nLeftRect);
  935. Rects[0].top = (int)(pSB->nTopRect);
  936. Rects[0].right = (int)(pSB->nLeftRect + pSB->nWidth);
  937. Rects[0].bottom = (int)(pSB->nTopRect + pSB->nHeight);
  938. InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &Rects[0], FALSE);
  939. }
  940. TIMERSTOP;
  941. UPDATECOUNTER(FC_SCRBLT_TYPE);
  942. }
  943. else {
  944. int deltaX, deltaY;
  945. LPMULTI_SCRBLT_ORDER pMSB = (LPMULTI_SCRBLT_ORDER)pSB;
  946. TRC_NRM((TB, _T("ORDER: MultiScrBlt dx %d dy %d w %d h %d sx %d sy %d ")
  947. _T("rop %08lX nDeltas=%d"),
  948. (int)pMSB->nLeftRect, (int)pMSB->nTopRect,
  949. (int)pMSB->nWidth, (int)pMSB->nHeight,
  950. (int)pMSB->nXSrc, (int)pMSB->nYSrc, WindowsROP,
  951. (int)pMSB->nDeltaEntries));
  952. TRC_ASSERT((pMSB->codedDeltaList.len <=
  953. (ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN +
  954. ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES)),
  955. (TB,_T("Received MultiScrBlt with too-large internal length")));
  956. if (0 == pMSB->nDeltaEntries) {
  957. TRC_ERR((TB,_T("MultiScrBlt with no rects; uiVarDataLen=%u"),
  958. uiVarDataLen));
  959. hr = S_OK;
  960. DC_QUIT;
  961. }
  962. hr = ODDecodeMultipleRects(Rects, pMSB->nDeltaEntries,
  963. &pMSB->codedDeltaList, uiVarDataLen);
  964. DC_QUIT_ON_FAIL(hr);
  965. // Do a ScrBlt for each of the clip rects as a subrect of the
  966. // original ScrBlt rect.
  967. TIMERSTART;
  968. if (_pCc->_ccCombinedCapabilities.orderCapabilitySet.
  969. orderSupport[TS_NEG_MULTISCRBLT_INDEX]) {
  970. TRC_DBG((TB, _T("Real MultiScrBlt")));
  971. for (i = 0; i < pMSB->nDeltaEntries; i++ ) {
  972. // Clip rects in Rects[] are specified within the dest
  973. // rect (pSB->nLeftRect, nTopRect, nRightRect,
  974. // nBottomRect) so we need to calc the offset from the
  975. // source point (pSB->nXSrc, nYSrc) by calculating
  976. // the delta from the dest rect top-left to the clip rect
  977. // top-left, then adding the delta to the source point.
  978. deltaX = (int)(Rects[i].left - pSB->nLeftRect);
  979. deltaY = (int)(Rects[i].top - pSB->nTopRect);
  980. // Do the ScrBlt. Note that rects are in exclusive coords.
  981. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  982. if (!_pUh->_UH.DontUseShadowBitmap && _pUh->_UH.hdcShadowBitmap) {
  983. #else
  984. if (_pUh->_UH.hdcShadowBitmap) {
  985. #endif
  986. if (!BitBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top,
  987. (int)(Rects[i].right - Rects[i].left),
  988. (int)(Rects[i].bottom - Rects[i].top),
  989. _pUh->_UH.hdcShadowBitmap, (int)pMSB->nXSrc + deltaX,
  990. (int)pMSB->nYSrc + deltaY,
  991. WindowsROP)) {
  992. TRC_ERR((TB, _T("BitBlt failed")));
  993. }
  994. }
  995. else {
  996. #ifdef OS_WINCE
  997. if (!ODHandleAlwaysOnTopRects(pSB))
  998. {
  999. #endif
  1000. if (!BitBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top,
  1001. (int)(Rects[i].right - Rects[i].left),
  1002. (int)(Rects[i].bottom - Rects[i].top),
  1003. _pUh->_UH.hdcOutputWindow, (int)pMSB->nXSrc + deltaX,
  1004. (int)pMSB->nYSrc + deltaY,
  1005. WindowsROP)) {
  1006. TRC_ERR((TB, _T("BitBlt failed")));
  1007. }
  1008. #ifdef OS_WINCE
  1009. }
  1010. #endif
  1011. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1012. if ((_pUh->_UH.fIsBBarVisible) && (_pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow))
  1013. {
  1014. rectTemp.left = (int)(pSB->nXSrc + deltaX);
  1015. rectTemp.top = (int)(pSB->nYSrc + deltaY);
  1016. rectTemp.right = (int)(pSB->nXSrc + deltaX + Rects[i].right - Rects[i].left);
  1017. rectTemp.bottom = (int)(pSB->nYSrc + deltaY + Rects[i].bottom - Rects[i].top);
  1018. if (IntersectRect(&rectIntersect, &rectTemp, &(_pUh->_UH.rectBBar))) {
  1019. nX = pMSB->nLeftRect - pMSB->nXSrc;
  1020. nY = pMSB->nTopRect - pMSB->nYSrc;
  1021. rectIntersect.left += nX;
  1022. rectIntersect.right += nX;
  1023. rectIntersect.top += nY;
  1024. rectIntersect.bottom += nY;
  1025. // In fullscreen, when moving a window quickly inside and outside the bbar
  1026. // part of window intersected by bbar is not drawn correctly
  1027. // here we invalidate larger rectangle to solve this problem
  1028. nWidth = rectIntersect.right - rectIntersect.left;
  1029. rectIntersect.left -= nWidth;
  1030. rectIntersect.right += nWidth;
  1031. rectIntersect.bottom += _pUh->_UH.rectBBar.bottom * 2;
  1032. InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectIntersect, FALSE);
  1033. }
  1034. }
  1035. #endif //DISABLE_SHADOW_IN_FULLSCREEN
  1036. }
  1037. }
  1038. }
  1039. else {
  1040. // Alternative processing for when we get a MultiScrBlt
  1041. // without having advertised support for it.
  1042. TRC_DBG((TB, _T("Simulated MultiScrBlt")));
  1043. Rects[0].left = (int)(pMSB->nLeftRect);
  1044. Rects[0].top = (int)(pMSB->nTopRect);
  1045. Rects[0].right = (int)(pMSB->nLeftRect + pMSB->nWidth);
  1046. Rects[0].bottom = (int)(pMSB->nTopRect + pMSB->nHeight);
  1047. InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &Rects[0], FALSE);
  1048. }
  1049. TIMERSTOP;
  1050. UPDATECOUNTER(FC_SCRBLT_TYPE);
  1051. }
  1052. DC_EXIT_POINT:
  1053. DC_END_FN();
  1054. return hr;
  1055. }
  1056. /****************************************************************************/
  1057. // ODHandleMultiOpaqueRect
  1058. //
  1059. // Order handler for MultiOpaqueRect.
  1060. /****************************************************************************/
  1061. HRESULT DCINTERNAL COD::ODHandleMultiOpaqueRect(PUH_ORDER pOrder,
  1062. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1063. {
  1064. HRESULT hr;
  1065. RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1];
  1066. unsigned i;
  1067. LPMULTI_OPAQUERECT_ORDER pOR =
  1068. (LPMULTI_OPAQUERECT_ORDER)pOrder->orderData;
  1069. DC_BEGIN_FN("ODHandleMultiOpaqueRect");
  1070. if (0 == pOR->nDeltaEntries) {
  1071. TRC_ERR((TB,_T("MultiOpaqueRect with no rects; uiVarDataLen=%u"),
  1072. uiVarDataLen));
  1073. hr = S_OK;
  1074. DC_QUIT;
  1075. }
  1076. // If we've not already set the bounds (the order didn't contain
  1077. // any), set the bounds to the blt rect and reset the clip region.
  1078. // This rect might be needed later to add to the clip region for
  1079. // updating the shadow buffer to the screen.
  1080. if (!bBoundsSet) {
  1081. pOrder->dstRect.left = (int)pOR->nLeftRect;
  1082. pOrder->dstRect.top = (int)pOR->nTopRect;
  1083. pOrder->dstRect.right = (int)(pOR->nLeftRect + pOR->nWidth - 1);
  1084. pOrder->dstRect.bottom = (int)(pOR->nTopRect + pOR->nHeight - 1);
  1085. _pUh->UH_ResetClipRegion();
  1086. }
  1087. else {
  1088. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1089. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1090. }
  1091. TRC_NRM((TB, _T("ORDER: OpaqueRect x(%d) y(%d) w(%d) h(%d) c(%#02x)"),
  1092. (int)pOR->nLeftRect, (int)pOR->nTopRect,
  1093. (int)pOR->nWidth,
  1094. (int)pOR->nHeight,
  1095. (int)pOR->Color.u.index));
  1096. _pUh->UHUseSolidPaletteBrush(pOR->Color);
  1097. hr = ODDecodeMultipleRects(Rects, pOR->nDeltaEntries, &pOR->codedDeltaList,
  1098. uiVarDataLen);
  1099. DC_QUIT_ON_FAIL(hr);
  1100. TIMERSTART;
  1101. for (i = 0; i < pOR ->nDeltaEntries; i++)
  1102. PatBlt(_pUh->_UH.hdcDraw, (int)Rects[i].left, (int)Rects[i].top,
  1103. (int)(Rects[i].right - Rects[i].left),
  1104. (int)(Rects[i].bottom - Rects[i].top), PATCOPY);
  1105. TIMERSTOP;
  1106. UPDATECOUNTER(FC_OPAQUERECT_TYPE);
  1107. DC_EXIT_POINT:
  1108. DC_END_FN();
  1109. return hr;
  1110. }
  1111. #ifdef DRAW_NINEGRID
  1112. /****************************************************************************/
  1113. // ODHandleDrawNineGrid
  1114. //
  1115. // Order handler for DrawNineGrid.
  1116. /****************************************************************************/
  1117. HRESULT DCINTERNAL COD::ODHandleDrawNineGrid(PUH_ORDER pOrder,
  1118. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1119. {
  1120. HRESULT hr = S_OK;
  1121. LPDRAWNINEGRID_ORDER pDNG =
  1122. (LPDRAWNINEGRID_ORDER)pOrder->orderData;
  1123. DC_BEGIN_FN("ODHandleDrawNineGrid");
  1124. TRC_ASSERT((bBoundsSet != 0), (TB, _T("Bounds is not set for DrawNineGrid")));
  1125. TRC_ASSERT((0==uiVarDataLen),
  1126. (TB, _T("Varaible length data in fixed length packet")));
  1127. hr = _pUh->UHIsValidNineGridCacheIndex(pDNG->bitmapId);
  1128. DC_QUIT_ON_FAIL(hr);
  1129. // The bounds is for the destination bounding rect, not clip region
  1130. // needs to be set
  1131. _pUh->UH_ResetClipRegion();
  1132. TRC_NRM((TB, _T("ORDER: DrawNineGrid x(%d) y(%d) w(%d) h(%d) id(%d)"),
  1133. (int)pOrder->dstRect.left, (int)pOrder->dstRect.top,
  1134. (int)pOrder->dstRect.right,
  1135. (int)pOrder->dstRect.bottom,
  1136. (int)pDNG->bitmapId));
  1137. TIMERSTART;
  1138. hr = _pUh->UH_DrawNineGrid(pOrder, pDNG->bitmapId, (RECT *)&(pDNG->srcLeft));
  1139. TIMERSTOP;
  1140. DC_QUIT_ON_FAIL(hr);
  1141. //UPDATECOUNTER(FC_OPAQUERECT_TYPE);
  1142. DC_EXIT_POINT:
  1143. DC_END_FN();
  1144. return hr;
  1145. }
  1146. /****************************************************************************/
  1147. // ODHandleMultiOpaqueRect
  1148. //
  1149. // Order handler for MultiOpaqueRect.
  1150. /****************************************************************************/
  1151. HRESULT DCINTERNAL COD::ODHandleMultiDrawNineGrid(PUH_ORDER pOrder,
  1152. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1153. {
  1154. HRESULT hr = S_OK;
  1155. RECT Rects[ORD_MAX_ENCODED_CLIP_RECTS + 1];
  1156. unsigned i;
  1157. LPMULTI_DRAWNINEGRID_ORDER pDNG =
  1158. (LPMULTI_DRAWNINEGRID_ORDER)pOrder->orderData;
  1159. DC_BEGIN_FN("ODHandleMultiDrawNineGrid");
  1160. TRC_ASSERT((bBoundsSet != 0), (TB, _T("Bounds is not set for MultiDrawNineGrid")));
  1161. if (0 == pDNG->nDeltaEntries) {
  1162. TRC_ERR((TB,_T("MultiDrawNineGrid with no rects; uiVarDataLen=%u"),
  1163. uiVarDataLen));
  1164. hr = S_OK;
  1165. DC_QUIT;
  1166. }
  1167. hr = _pUh->UHIsValidNineGridCacheIndex(pDNG->bitmapId);
  1168. DC_QUIT_ON_FAIL(hr);
  1169. // Need to setup the clip region
  1170. hr = ODDecodeMultipleRects(Rects, pDNG->nDeltaEntries,
  1171. &pDNG->codedDeltaList, uiVarDataLen);
  1172. DC_QUIT_ON_FAIL(hr);
  1173. #if defined (OS_WINCE)
  1174. _UH.validClipDC = NULL;
  1175. #endif
  1176. SelectClipRgn(_pUh->_UH.hdcDraw, NULL);
  1177. SetRectRgn(_pUh->_UH.hDrawNineGridClipRegion, 0, 0, 0, 0);
  1178. for (i = 0; i < pDNG->nDeltaEntries; i++) {
  1179. UH_ORDER OrderRect;
  1180. OrderRect.dstRect.left = Rects[i].left;
  1181. OrderRect.dstRect.top = Rects[i].top;
  1182. OrderRect.dstRect.right = Rects[i].right -1;
  1183. OrderRect.dstRect.bottom = Rects[i].bottom -1;
  1184. _pUh->UHAddUpdateRegion(&OrderRect, _pUh->_UH.hDrawNineGridClipRegion);
  1185. }
  1186. #if defined (OS_WINCE)
  1187. _UH.validClipDC = NULL;
  1188. #endif
  1189. SelectClipRgn(_pUh->_UH.hdcDraw, _pUh->_UH.hDrawNineGridClipRegion);
  1190. TRC_NRM((TB, _T("ORDER: MultiDrawNineGrid x(%d) y(%d) w(%d) h(%d) id(%d)"),
  1191. (int)pOrder->dstRect.left, (int)pOrder->dstRect.top,
  1192. (int)pOrder->dstRect.right,
  1193. (int)pOrder->dstRect.bottom,
  1194. (int)pDNG->bitmapId));
  1195. TIMERSTART;
  1196. hr = _pUh->UH_DrawNineGrid(pOrder, pDNG->bitmapId, (RECT *)&(pDNG->srcLeft));
  1197. TIMERSTOP;
  1198. //UPDATECOUNTER(FC_OPAQUERECT_TYPE);
  1199. DC_QUIT_ON_FAIL(hr);
  1200. #if defined (OS_WINCE)
  1201. _UH.validClipDC = NULL;
  1202. #endif
  1203. SelectClipRgn(_pUh->_UH.hdcDraw, NULL);
  1204. DC_EXIT_POINT:
  1205. DC_END_FN();
  1206. return hr;
  1207. }
  1208. #endif
  1209. /****************************************************************************/
  1210. // ODHandleMem3Blt
  1211. //
  1212. // Order handler for Mem3Blt.
  1213. /****************************************************************************/
  1214. HRESULT DCINTERNAL COD::ODHandleMem3Blt(PUH_ORDER pOrder,
  1215. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1216. {
  1217. HRESULT hr = S_OK;
  1218. LPMEM3BLT_R2_ORDER pMB = (LPMEM3BLT_R2_ORDER)pOrder->orderData;
  1219. DC_BEGIN_FN("ODHandleMem3Blt");
  1220. TRC_ASSERT((0==uiVarDataLen),
  1221. (TB, _T("Varaible length data in fixed length packet")));
  1222. // If we've not already set the bounds (the order didn't contain
  1223. // any), set the bounds to the blt rect and reset the clip region.
  1224. // This rect might be needed later to add to the clip region for
  1225. // updating the shadow buffer to the screen.
  1226. if (!bBoundsSet) {
  1227. pOrder->dstRect.left = (int)pMB->Common.nLeftRect;
  1228. pOrder->dstRect.top = (int)pMB->Common.nTopRect;
  1229. pOrder->dstRect.right = (int)(pMB->Common.nLeftRect +
  1230. pMB->Common.nWidth - 1);
  1231. pOrder->dstRect.bottom = (int)(pMB->Common.nTopRect +
  1232. pMB->Common.nHeight - 1);
  1233. _pUh->UH_ResetClipRegion();
  1234. }
  1235. else {
  1236. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1237. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1238. }
  1239. TRC_NRM((TB, _T("ORDER: Mem3Blt")));
  1240. UHUseBkColor(pMB->BackColor, UH_COLOR_PALETTE, _pUh);
  1241. UHUseTextColor(pMB->ForeColor, UH_COLOR_PALETTE, _pUh);
  1242. UHUseBrushOrg((int)pMB->BrushOrgX, (int)pMB->BrushOrgY, _pUh);
  1243. hr = _pUh->UHUseBrush((int)pMB->BrushStyle, (int)pMB->BrushHatch,
  1244. pMB->ForeColor, UH_COLOR_PALETTE, pMB->BrushExtra);
  1245. DC_QUIT_ON_FAIL(hr);
  1246. hr = _pUh->UHDrawMemBltOrder(_pUh->_UH.hdcDraw, &pMB->Common);
  1247. DC_QUIT_ON_FAIL(hr);
  1248. #ifdef DC_DEBUG
  1249. // Draw hatching over the memblt data if the option is enabled.
  1250. if (_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap ||
  1251. _pUh->_UH.hdcDraw == _pUh->_UH.hdcOutputWindow) {
  1252. if (_pUh->_UH.hatchMemBltOrderData) {
  1253. unsigned cacheId;
  1254. unsigned cacheEntry;
  1255. cacheId = DCLO8(pMB->Common.cacheId);
  1256. cacheEntry = pMB->Common.cacheIndex;
  1257. if (cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX &&
  1258. SUCCEEDED(_pUh->UHIsValidBitmapCacheIndex(cacheId, cacheEntry))) {
  1259. if (_pUh->_UH.MonitorEntries[0] != NULL)
  1260. _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect,
  1261. (int)(pMB->Common.nLeftRect + pMB->Common.nWidth),
  1262. (int)(pMB->Common.nTopRect + pMB->Common.nHeight),
  1263. (_pUh->_UH.MonitorEntries[cacheId][cacheEntry].UsageCount == 1) ?
  1264. UH_RGB_MAGENTA : UH_RGB_GREEN,
  1265. UH_BRUSHTYPE_FDIAGONAL);
  1266. else
  1267. _pUh->UH_HatchRect((int)pMB->Common.nLeftRect, (int)pMB->Common.nTopRect,
  1268. (int)(pMB->Common.nLeftRect + pMB->Common.nWidth),
  1269. (int)(pMB->Common.nTopRect + pMB->Common.nHeight),
  1270. UH_RGB_MAGENTA, UH_BRUSHTYPE_FDIAGONAL);
  1271. }
  1272. }
  1273. // Label the memblt if the option is enabled.
  1274. if (_pUh->_UH.labelMemBltOrders) {
  1275. unsigned cacheId;
  1276. unsigned cacheEntry;
  1277. cacheId = DCLO8(pMB->Common.cacheId);
  1278. cacheEntry = pMB->Common.cacheIndex;
  1279. if (cacheEntry != BITMAPCACHE_WAITING_LIST_INDEX &&
  1280. SUCCEEDED(_pUh->UHIsValidBitmapCacheIndex(cacheId, cacheEntry))) {
  1281. _pUh->UHLabelMemBltOrder((int)pMB->Common.nLeftRect,
  1282. (int)pMB->Common.nTopRect, pMB->Common.cacheId,
  1283. pMB->Common.cacheIndex);
  1284. }
  1285. }
  1286. }
  1287. #endif /* DC_DEBUG */
  1288. DC_EXIT_POINT:
  1289. DC_END_FN();
  1290. return hr;
  1291. }
  1292. /****************************************************************************/
  1293. // ODHandleSaveBitmap
  1294. //
  1295. // Order handler for SaveBitmap.
  1296. /****************************************************************************/
  1297. HRESULT DCINTERNAL COD::ODHandleSaveBitmap(PUH_ORDER pOrder,
  1298. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1299. {
  1300. HRESULT hr = S_OK;
  1301. int xSaveBitmap;
  1302. int ySaveBitmap;
  1303. int xScreenBitmap;
  1304. int yScreenBitmap;
  1305. int cxTile;
  1306. int cyTile;
  1307. int ScreenLeft, ScreenTop, ScreenRight, ScreenBottom;
  1308. LPSAVEBITMAP_ORDER pSB = (LPSAVEBITMAP_ORDER)pOrder->orderData;
  1309. DC_BEGIN_FN("ODHandleSaveBitmap");
  1310. TRC_ASSERT((0==uiVarDataLen),
  1311. (TB, _T("Varaible length data in fixed length packet")));
  1312. // If we've not already set the bounds (the order didn't contain
  1313. // any), set the bounds to the blt rect and reset the clip region.
  1314. // This rect might be needed later to add to the clip region for
  1315. // updating the shadow buffer to the screen.
  1316. if (!bBoundsSet) {
  1317. pOrder->dstRect.left = (int)pSB->nLeftRect;
  1318. pOrder->dstRect.top = (int)pSB->nTopRect;
  1319. pOrder->dstRect.right = (int)pSB->nRightRect;
  1320. pOrder->dstRect.bottom = (int)pSB->nBottomRect;
  1321. _pUh->UH_ResetClipRegion();
  1322. }
  1323. else {
  1324. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1325. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1326. }
  1327. TRC_NRM((TB, _T("ORDER: SaveBitmap op %d rect %d %d %d %d"),
  1328. (int)pSB->Operation, (int)pSB->nLeftRect,
  1329. (int)pSB->nTopRect, (int)pSB->nRightRect,
  1330. (int)pSB->nBottomRect));
  1331. if (_pUh->_UH.hSaveScreenBitmap != NULL) {
  1332. // Check that we have selected a DC to draw to.
  1333. TRC_ASSERT((NULL != _pUh->_UH.hdcDraw), (TB,_T("No drawing hdc!")));
  1334. // Calculate the (x,y) offset into the Save Desktop Bitmap from the
  1335. // start position as encoded in the order. (The server knows the
  1336. // dimensions of our bitmap and is reponsible for telling us where to
  1337. // store/retrieve rectangles in the bitmap.)
  1338. // See T.128 8.16.17 for a justification of this algorithm.
  1339. ySaveBitmap = (int)((pSB->SavedBitmapPosition /
  1340. (UH_SAVE_BITMAP_WIDTH *
  1341. (UINT32)UH_SAVE_BITMAP_Y_GRANULARITY)) *
  1342. UH_SAVE_BITMAP_Y_GRANULARITY);
  1343. xSaveBitmap = (int)((pSB->SavedBitmapPosition -
  1344. (ySaveBitmap * (UINT32)UH_SAVE_BITMAP_WIDTH)) /
  1345. UH_SAVE_BITMAP_Y_GRANULARITY);
  1346. TRC_DBG((TB, _T("start pos %lu = (%d,%d)"),
  1347. pSB->SavedBitmapPosition, xSaveBitmap, ySaveBitmap));
  1348. // Split the bitmap rectangle into tiles that fit neatly into the
  1349. // save bitmap. Each tile's dimensions are a multiple of the
  1350. // xGranularity and yGranularity. Tiling is used so that a screen
  1351. // bitmap rectangle can be saved even if it is taller than the
  1352. // save bitmap. e.g.:
  1353. // Screen Bitmap Save Bitmap
  1354. // 111111 1111112222
  1355. // 222222 -> 2233333344
  1356. // 333333 4444------
  1357. // 444444
  1358. // The protocol uses inclusive co-ordinates, whereas Windows
  1359. // has an exclusive co-ordinate system. Therefore, doctor
  1360. // these co-ords to make sure the lower-right edges are included.
  1361. ScreenLeft = (int)pSB->nLeftRect;
  1362. ScreenTop = (int)pSB->nTopRect;
  1363. ScreenRight = (int)pSB->nRightRect + 1;
  1364. ScreenBottom = (int)pSB->nBottomRect + 1;
  1365. // Start tiling in the top left corner of the Screen Bitmap rectangle.
  1366. xScreenBitmap = ScreenLeft;
  1367. yScreenBitmap = ScreenTop;
  1368. // The height of the tile is the vertical granularity (or less - if
  1369. // the Screen Bitmap rect is thinner than the granularity).
  1370. cyTile = DC_MIN(ScreenBottom - yScreenBitmap,
  1371. UH_SAVE_BITMAP_Y_GRANULARITY);
  1372. // Repeat while there are more tiles in the Screen Bitmap rect to
  1373. // process.
  1374. while (yScreenBitmap < ScreenBottom) {
  1375. // The width of the tile is the minimum of:
  1376. // - the width of the remaining rectangle in the current strip of
  1377. // the Screen Bitmap rectangle
  1378. // - the width of the remaining empty space in the Save Bitmap
  1379. cxTile = DC_MIN(UH_SAVE_BITMAP_WIDTH - xSaveBitmap,
  1380. ScreenRight - xScreenBitmap);
  1381. TRC_DBG((TB, _T("screen(%d,%d) save(%d,%d) cx(%d) cy(%d)"),
  1382. xScreenBitmap, yScreenBitmap, xSaveBitmap, ySaveBitmap,
  1383. cxTile, cyTile));
  1384. // Copy this tile.
  1385. if (pSB->Operation == SV_SAVEBITS) {
  1386. TRC_NRM((TB, _T("Save a desktop bitmap")));
  1387. if (!BitBlt(_pUh->_UH.hdcSaveScreenBitmap, xSaveBitmap, ySaveBitmap,
  1388. cxTile, cyTile, _pUh->_UH.hdcDraw, xScreenBitmap,
  1389. yScreenBitmap, SRCCOPY)) {
  1390. TRC_SYSTEM_ERROR("BitBlt");
  1391. TRC_ERR((TB, _T("Screen(%u,%u) Tile(%u,%u) Save(%u,%u)"),
  1392. xScreenBitmap, yScreenBitmap, cxTile, cyTile,
  1393. xSaveBitmap, ySaveBitmap));
  1394. }
  1395. }
  1396. else {
  1397. TRC_NRM((TB, _T("Restore a desktop bitmap")));
  1398. if (!BitBlt(_pUh->_UH.hdcDraw, xScreenBitmap, yScreenBitmap, cxTile,
  1399. cyTile, _pUh->_UH.hdcSaveScreenBitmap, xSaveBitmap,
  1400. ySaveBitmap, SRCCOPY)) {
  1401. TRC_SYSTEM_ERROR("BitBlt");
  1402. TRC_ERR((TB, _T("Screen(%u,%u) Tile(%u,%u) Save(%u,%u)"),
  1403. xScreenBitmap, yScreenBitmap, cxTile, cyTile,
  1404. xSaveBitmap, ySaveBitmap));
  1405. }
  1406. }
  1407. // Move to the next tile in the Screen Bitmap rectangle.
  1408. xScreenBitmap += cxTile;
  1409. if (xScreenBitmap >= ScreenRight) {
  1410. xScreenBitmap = ScreenLeft;
  1411. yScreenBitmap += cyTile;
  1412. cyTile = DC_MIN(ScreenBottom - yScreenBitmap,
  1413. UH_SAVE_BITMAP_Y_GRANULARITY);
  1414. }
  1415. // Move to the next free space in the Save Bitmap.
  1416. xSaveBitmap += UHROUNDUP(cxTile, UH_SAVE_BITMAP_X_GRANULARITY);
  1417. if (xSaveBitmap >= UH_SAVE_BITMAP_WIDTH) {
  1418. // Move to the next horizontal strip.
  1419. TRC_DBG((TB,_T("Next strip")));
  1420. xSaveBitmap = 0;
  1421. ySaveBitmap += UHROUNDUP(cyTile, UH_SAVE_BITMAP_Y_GRANULARITY);
  1422. }
  1423. if (ySaveBitmap >= UH_SAVE_BITMAP_HEIGHT) {
  1424. // Assert that we haven't been sent too much stuff. Quietly
  1425. // stop saving data in the retail build.
  1426. TRC_ABORT((TB, _T("Server out of bounds!")));
  1427. break;
  1428. }
  1429. }
  1430. #ifdef DC_DEBUG
  1431. // Draw hatching over the SSB data if the option is enabled.
  1432. if (_pUh->_UH.hatchSSBOrderData)
  1433. _pUh->UH_HatchRect((int)pSB->nLeftRect, (int)pSB->nTopRect,
  1434. (int)pSB->nRightRect, (int)pSB->nBottomRect,
  1435. UH_RGB_CYAN, UH_BRUSHTYPE_FDIAGONAL);
  1436. #endif
  1437. }
  1438. else {
  1439. // This should never happen. We only advertise SSB support
  1440. // if UH has successfully created this bitmap.
  1441. // Fail to process the order in the retail build - the
  1442. // server is probably being evil.
  1443. TRC_ABORT((TB, _T("SSB bitmap null!")));
  1444. }
  1445. return hr;
  1446. DC_END_FN();
  1447. }
  1448. /****************************************************************************/
  1449. // ODHandlePolyLine
  1450. //
  1451. // Order handler for PolyLine.
  1452. /****************************************************************************/
  1453. HRESULT DCINTERNAL COD::ODHandlePolyLine(PUH_ORDER pOrder,
  1454. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1455. {
  1456. HRESULT hr = S_OK;
  1457. POINT Points[ORD_MAX_POLYLINE_ENCODED_POINTS + 1];
  1458. RECT BoundRect;
  1459. DCCOLOR ZeroColor;
  1460. PPOLYLINE_ORDER pPL = (PPOLYLINE_ORDER)pOrder->orderData;
  1461. DC_BEGIN_FN("ODHandlePolyLine");
  1462. TRC_NRM((TB, _T("ORDER: PolyLine xs=%d ys=%d rop2=%04X brc=0x%X ")
  1463. _T("penc=%08lX #entr=%d"),
  1464. pPL->XStart, pPL->YStart, pPL->ROP2, pPL->BrushCacheEntry,
  1465. pPL->PenColor, pPL->NumDeltaEntries));
  1466. ZeroColor.u.rgb.red = 0;
  1467. ZeroColor.u.rgb.green = 0;
  1468. ZeroColor.u.rgb.blue = 0;
  1469. UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh);
  1470. UHUseBkMode(TRANSPARENT, _pUh);
  1471. UHUseROP2((int)pPL->ROP2, _pUh);
  1472. _pUh->UHUsePen(PS_SOLID, 1, pPL->PenColor, UH_COLOR_PALETTE);
  1473. Points[0].x = (int)pPL->XStart;
  1474. Points[0].y = (int)pPL->YStart;
  1475. BoundRect.left = BoundRect.right = Points[0].x;
  1476. BoundRect.top = BoundRect.bottom = Points[0].y;
  1477. hr = ODDecodePathPoints(Points, &BoundRect,
  1478. pPL->CodedDeltaList.Deltas,
  1479. (unsigned)pPL->NumDeltaEntries, ORD_MAX_POLYLINE_ENCODED_POINTS,
  1480. pPL->CodedDeltaList.len, ORD_MAX_POLYLINE_CODEDDELTAS_LEN +
  1481. ORD_MAX_POLYLINE_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet);
  1482. DC_QUIT_ON_FAIL(hr);
  1483. // If we didn't get a rect across the net, use the one we calculated.
  1484. // This rect might be needed later to add to the clip region for
  1485. // updating the shadow buffer to the screen.
  1486. if (!bBoundsSet) {
  1487. pOrder->dstRect.left = BoundRect.left;
  1488. pOrder->dstRect.top = BoundRect.top;
  1489. pOrder->dstRect.right = BoundRect.right;
  1490. pOrder->dstRect.bottom = BoundRect.bottom;
  1491. _pUh->UH_ResetClipRegion();
  1492. }
  1493. else {
  1494. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1495. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1496. }
  1497. TIMERSTART;
  1498. Polyline(_pUh->_UH.hdcDraw, Points, (UINT16)pPL->NumDeltaEntries + 1);
  1499. TIMERSTOP;
  1500. UPDATECOUNTER(FC_POLYLINE_TYPE);
  1501. DC_EXIT_POINT:
  1502. DC_END_FN();
  1503. return hr;
  1504. }
  1505. /****************************************************************************/
  1506. // ODHandlePolygonSC
  1507. //
  1508. // Order handler for Polygon with solic color brush.
  1509. /****************************************************************************/
  1510. HRESULT DCINTERNAL COD::ODHandlePolygonSC(PUH_ORDER pOrder,
  1511. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1512. {
  1513. HRESULT hr = S_OK;
  1514. POINT Points[ORD_MAX_POLYGON_ENCODED_POINTS + 1];
  1515. RECT BoundRect;
  1516. DCCOLOR ZeroColor;
  1517. POLYGON_SC_ORDER FAR *pPG = (POLYGON_SC_ORDER FAR *)pOrder->orderData;
  1518. DC_BEGIN_FN("ODHandlePolygonSC");
  1519. TRC_NRM((TB, _T("ORDER: PolyGonSC xs=%d ys=%d rop2=%04X fill=%d ")
  1520. _T("brushc=%08lX #entr=%d"),
  1521. pPG->XStart, pPG->YStart, pPG->ROP2, pPG->FillMode,
  1522. pPG->BrushColor, pPG->NumDeltaEntries));
  1523. ZeroColor.u.rgb.red = 0;
  1524. ZeroColor.u.rgb.green = 0;
  1525. ZeroColor.u.rgb.blue = 0;
  1526. UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh);
  1527. UHUseBkMode(TRANSPARENT, _pUh);
  1528. UHUseROP2((int)pPG->ROP2, _pUh);
  1529. _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE);
  1530. _pUh->UHUseSolidPaletteBrush(pPG->BrushColor);
  1531. UHUseFillMode(pPG->FillMode,_pUh);
  1532. Points[0].x = (int)pPG->XStart;
  1533. Points[0].y = (int)pPG->YStart;
  1534. BoundRect.left = BoundRect.right = Points[0].x;
  1535. BoundRect.top = BoundRect.bottom = Points[0].y;
  1536. hr = ODDecodePathPoints(Points, &BoundRect,
  1537. pPG->CodedDeltaList.Deltas,
  1538. (unsigned)pPG->NumDeltaEntries, ORD_MAX_POLYGON_ENCODED_POINTS,
  1539. pPG->CodedDeltaList.len, ORD_MAX_POLYGON_CODEDDELTAS_LEN +
  1540. ORD_MAX_POLYGON_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet);
  1541. DC_QUIT_ON_FAIL(hr);
  1542. // If we didn't get a rect across the net, use the one we calculated.
  1543. // This rect might be needed later to add to the clip region for
  1544. // updating the shadow buffer to the screen.
  1545. if (!bBoundsSet) {
  1546. pOrder->dstRect.left = BoundRect.left;
  1547. pOrder->dstRect.top = BoundRect.top;
  1548. pOrder->dstRect.right = BoundRect.right;
  1549. pOrder->dstRect.bottom = BoundRect.bottom;
  1550. _pUh->UH_ResetClipRegion();
  1551. }
  1552. else {
  1553. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1554. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1555. }
  1556. TIMERSTART;
  1557. Polygon(_pUh->_UH.hdcDraw, Points, (UINT16)pPG->NumDeltaEntries + 1);
  1558. TIMERSTOP;
  1559. UPDATECOUNTER(FC_POLYGONSC_TYPE);
  1560. DC_EXIT_POINT:
  1561. DC_END_FN();
  1562. return hr;
  1563. }
  1564. /****************************************************************************/
  1565. // ODHandlePolygonCB
  1566. //
  1567. // Order handler for Polygon with complex brush.
  1568. /****************************************************************************/
  1569. HRESULT DCINTERNAL COD::ODHandlePolygonCB(PUH_ORDER pOrder,
  1570. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1571. {
  1572. HRESULT hr = S_OK;
  1573. POINT Points[ORD_MAX_POLYGON_ENCODED_POINTS + 1];
  1574. RECT BoundRect;
  1575. DCCOLOR ZeroColor;
  1576. POLYGON_CB_ORDER FAR *pPG = (POLYGON_CB_ORDER FAR *)pOrder->orderData;
  1577. DC_BEGIN_FN("ODHandlePolygonCB");
  1578. TRC_NRM((TB, _T("ORDER: PolyGonCB xs=%d ys=%d rop2=%04X fill=%d ")
  1579. _T("#entr=%d"),
  1580. pPG->XStart, pPG->YStart, pPG->ROP2, pPG->FillMode,
  1581. pPG->NumDeltaEntries));
  1582. ZeroColor.u.rgb.red = 0;
  1583. ZeroColor.u.rgb.green = 0;
  1584. ZeroColor.u.rgb.blue = 0;
  1585. UHUseBkColor(pPG->BackColor, UH_COLOR_PALETTE, _pUh);
  1586. // If the brush is a hatched brush, we need to check the high bit (bit 7)
  1587. // of ROP2 to see if the background mode should be transparent or opaque:
  1588. // 1 means transparent mode, 0 means opaque mode
  1589. if (pPG->BrushStyle == BS_HATCHED) {
  1590. if (!(pPG->ROP2 & 0x80)) {
  1591. UHUseBkMode(OPAQUE, _pUh);
  1592. }
  1593. else {
  1594. UHUseBkMode(TRANSPARENT, _pUh);
  1595. }
  1596. }
  1597. // Set the ROP2 for the forground mix mode
  1598. UHUseROP2(((int)pPG->ROP2) & 0x1F, _pUh);
  1599. UHUseTextColor(pPG->ForeColor, UH_COLOR_PALETTE, _pUh);
  1600. _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE);
  1601. UHUseBrushOrg((int)pPG->BrushOrgX, (int)pPG->BrushOrgY, _pUh);
  1602. hr = _pUh->UHUseBrush((unsigned)pPG->BrushStyle, (unsigned)pPG->BrushHatch,
  1603. pPG->ForeColor, UH_COLOR_PALETTE, pPG->BrushExtra);
  1604. DC_QUIT_ON_FAIL(hr);
  1605. UHUseFillMode(pPG->FillMode, _pUh);
  1606. Points[0].x = (int)pPG->XStart;
  1607. Points[0].y = (int)pPG->YStart;
  1608. BoundRect.left = BoundRect.right = Points[0].x;
  1609. BoundRect.top = BoundRect.bottom = Points[0].y;
  1610. hr = ODDecodePathPoints(Points, &BoundRect,
  1611. pPG->CodedDeltaList.Deltas,
  1612. (unsigned)pPG->NumDeltaEntries, ORD_MAX_POLYGON_ENCODED_POINTS,
  1613. pPG->CodedDeltaList.len, ORD_MAX_POLYGON_CODEDDELTAS_LEN +
  1614. ORD_MAX_POLYGON_ZERO_FLAGS_BYTES, uiVarDataLen, !bBoundsSet);
  1615. DC_QUIT_ON_FAIL(hr);
  1616. // If we didn't get a rect across the net, use the one we calculated.
  1617. // This rect might be needed later to add to the clip region for
  1618. // updating the shadow buffer to the screen.
  1619. if (!bBoundsSet) {
  1620. pOrder->dstRect.left = BoundRect.left;
  1621. pOrder->dstRect.top = BoundRect.top;
  1622. pOrder->dstRect.right = BoundRect.right;
  1623. pOrder->dstRect.bottom = BoundRect.bottom;
  1624. _pUh->UH_ResetClipRegion();
  1625. }
  1626. else {
  1627. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1628. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1629. }
  1630. TIMERSTART;
  1631. Polygon(_pUh->_UH.hdcDraw, Points, (UINT16)pPG->NumDeltaEntries + 1);
  1632. TIMERSTOP;
  1633. UPDATECOUNTER(FC_POLYGONCB_TYPE);
  1634. DC_EXIT_POINT:
  1635. DC_END_FN();
  1636. return hr;
  1637. }
  1638. /****************************************************************************/
  1639. // ODHandleEllipseSC
  1640. //
  1641. // Order handler for Ellipse with solid color brush.
  1642. /****************************************************************************/
  1643. HRESULT DCINTERNAL COD::ODHandleEllipseSC(PUH_ORDER pOrder,
  1644. UINT16 uiVarDataLen, BOOL bBoundsSet)
  1645. {
  1646. HRESULT hr = S_OK;
  1647. unsigned FudgeFactor;
  1648. DCCOLOR ZeroColor;
  1649. PELLIPSE_SC_ORDER pEL = (PELLIPSE_SC_ORDER)pOrder->orderData;
  1650. DC_BEGIN_FN("ODHandleEllipseSC");
  1651. TRC_ASSERT((0==uiVarDataLen),
  1652. (TB, _T("Varaible length data in fixed length packet")));
  1653. TRC_NRM((TB, _T("ORDER: Ellipse SC xs=%d ys=%d xe=%d ye=%d rop2=%04X ")
  1654. _T("fillmode=%d penc=%08lX"),
  1655. pEL->LeftRect, pEL->TopRect, pEL->RightRect, pEL->BottomRect,
  1656. pEL->ROP2, pEL->FillMode, pEL->Color));
  1657. ZeroColor.u.rgb.red = 0;
  1658. ZeroColor.u.rgb.green = 0;
  1659. ZeroColor.u.rgb.blue = 0;
  1660. UHUseBkColor(ZeroColor, UH_COLOR_PALETTE, _pUh);
  1661. UHUseBkMode(TRANSPARENT, _pUh);
  1662. UHUseROP2((int)pEL->ROP2, _pUh);
  1663. if (pEL->FillMode) {
  1664. _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE);
  1665. _pUh->UHUseSolidPaletteBrush(pEL->Color);
  1666. UHUseFillMode(pEL->FillMode, _pUh);
  1667. // Because of the way the null pen works, we need to fudge the bottom
  1668. // and right coords a bit.
  1669. FudgeFactor = 1;
  1670. }
  1671. else {
  1672. UINT32 extra[2] = { 0, 0 };
  1673. _pUh->UHUsePen(PS_SOLID, 1, pEL->Color, UH_COLOR_PALETTE);
  1674. hr = _pUh->UHUseBrush(BS_NULL, 0, ZeroColor, UH_COLOR_PALETTE,
  1675. (BYTE FAR *)extra);
  1676. DC_QUIT_ON_FAIL(hr);
  1677. FudgeFactor = 0;
  1678. }
  1679. // If we didn't get a rect across the net, use the one we calculated.
  1680. // This rect might be needed later to add to the clip region for
  1681. // updating the shadow buffer to the screen.
  1682. if (!bBoundsSet) {
  1683. pOrder->dstRect.left = (int)pEL->LeftRect;
  1684. pOrder->dstRect.top = (int)pEL->TopRect;
  1685. pOrder->dstRect.right = (int)pEL->RightRect;
  1686. pOrder->dstRect.bottom = (int)pEL->BottomRect;
  1687. _pUh->UH_ResetClipRegion();
  1688. }
  1689. else {
  1690. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1691. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1692. }
  1693. TIMERSTART;
  1694. // We add 1 to bottom and right here since the server sends an
  1695. // inclusive rect to us but GDI is exclusive.
  1696. Ellipse(_pUh->_UH.hdcDraw, (int)pEL->LeftRect, (int)pEL->TopRect,
  1697. (int)pEL->RightRect + 1 + FudgeFactor,
  1698. (int)pEL->BottomRect + 1 + FudgeFactor);
  1699. TIMERSTOP;
  1700. UPDATECOUNTER(FC_ELLIPSESC_TYPE);
  1701. DC_EXIT_POINT:
  1702. DC_END_FN();
  1703. return hr;
  1704. }
  1705. /****************************************************************************/
  1706. // ODHandleEllipseCB
  1707. //
  1708. // Order handler for Ellipse with complex brush.
  1709. /****************************************************************************/
  1710. HRESULT DCINTERNAL COD::ODHandleEllipseCB(PUH_ORDER pOrder, UINT16 uiVarDataLen,
  1711. BOOL bBoundsSet)
  1712. {
  1713. HRESULT hr = S_OK;
  1714. DCCOLOR ZeroColor;
  1715. PELLIPSE_CB_ORDER pEL = (PELLIPSE_CB_ORDER)pOrder->orderData;
  1716. DC_BEGIN_FN("ODHandleEllipseCB");
  1717. TRC_ASSERT((0==uiVarDataLen),
  1718. (TB, _T("Varaible length data in fixed length packet")));
  1719. TRC_NRM((TB, _T("ORDER: Ellipse CB xs=%d ys=%d xe=%d ye=%d rop2=%04X ")
  1720. _T("fillmode=%d"),
  1721. pEL->LeftRect, pEL->TopRect, pEL->RightRect, pEL->BottomRect,
  1722. pEL->ROP2, pEL->FillMode));
  1723. TRC_DBG((TB, _T("ORDER: Ellipse Brush %02X %02X BC %02x FC %02x ")
  1724. _T("(%02x %02x %02x %02x %02x %02x %02x) rop %08lX"),
  1725. (int)pEL->BrushStyle,
  1726. (int)pEL->BrushHatch,
  1727. (int)pEL->BackColor.u.index,
  1728. (int)pEL->ForeColor.u.index,
  1729. (int)pEL->BrushExtra[0],
  1730. (int)pEL->BrushExtra[1],
  1731. (int)pEL->BrushExtra[2],
  1732. (int)pEL->BrushExtra[3],
  1733. (int)pEL->BrushExtra[4],
  1734. (int)pEL->BrushExtra[5],
  1735. (int)pEL->BrushExtra[6],
  1736. (int)pEL->ROP2));
  1737. ZeroColor.u.rgb.red = 0;
  1738. ZeroColor.u.rgb.green = 0;
  1739. ZeroColor.u.rgb.blue = 0;
  1740. _pUh->UHUsePen(PS_NULL, 1, ZeroColor, UH_COLOR_PALETTE);
  1741. UHUseBkColor(pEL->BackColor, UH_COLOR_PALETTE, _pUh);
  1742. // If the brush is a hatched brush, we need to check the high bit (bit 7)
  1743. // of ROP2 to see if the background mode should be transparent or opaque:
  1744. // 1 means transparent mode, 0 means opaque mode
  1745. if (pEL->BrushStyle == BS_HATCHED) {
  1746. if (!(pEL->ROP2 & 0x80)) {
  1747. UHUseBkMode(OPAQUE, _pUh);
  1748. }
  1749. else {
  1750. UHUseBkMode(TRANSPARENT, _pUh);
  1751. }
  1752. }
  1753. // Set the ROP2 for the forground mix mode
  1754. UHUseROP2((((int)pEL->ROP2) & 0x1F), _pUh);
  1755. UHUseTextColor(pEL->ForeColor, UH_COLOR_PALETTE, _pUh);
  1756. UHUseBrushOrg((int)pEL->BrushOrgX, (int)pEL->BrushOrgY, _pUh);
  1757. hr = _pUh->UHUseBrush((unsigned)pEL->BrushStyle, (unsigned)pEL->BrushHatch,
  1758. pEL->ForeColor, UH_COLOR_PALETTE, pEL->BrushExtra);
  1759. DC_QUIT_ON_FAIL(hr);
  1760. UHUseFillMode(pEL->FillMode, _pUh);
  1761. // If we didn't get a rect across the net, use the one we calculated.
  1762. // This rect might be needed later to add to the clip region for
  1763. // updating the shadow buffer to the screen.
  1764. if (!bBoundsSet) {
  1765. pOrder->dstRect.left = (int)pEL->LeftRect;
  1766. pOrder->dstRect.top = (int)pEL->TopRect;
  1767. pOrder->dstRect.right = (int)pEL->RightRect;
  1768. pOrder->dstRect.bottom = (int)pEL->BottomRect;
  1769. _pUh->UH_ResetClipRegion();
  1770. }
  1771. else {
  1772. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1773. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1774. }
  1775. TIMERSTART;
  1776. // We add 1 to bottom and right here since the server sends an
  1777. // inclusive rect to us but GDI is exclusive. Also, to offset
  1778. // a null-pen bias at the bottom and right by adding another 1.
  1779. Ellipse(_pUh->_UH.hdcDraw, (int)pEL->LeftRect, (int)pEL->TopRect,
  1780. (int)pEL->RightRect + 2, (int)pEL->BottomRect + 2);
  1781. TIMERSTOP;
  1782. UPDATECOUNTER(FC_ELLIPSECB_TYPE);
  1783. DC_EXIT_POINT:
  1784. DC_END_FN();
  1785. return hr;
  1786. }
  1787. /****************************************************************************/
  1788. // ODDecodeFastIndex
  1789. //
  1790. // Fast-path order decoder for FastIndex orders.
  1791. /****************************************************************************/
  1792. HRESULT DCINTERNAL COD::ODDecodeFastIndex(
  1793. BYTE ControlFlags,
  1794. BYTE FAR * FAR *ppFieldDecode,
  1795. DCUINT dataLen,
  1796. UINT32 FieldFlags)
  1797. {
  1798. HRESULT hr = S_OK;
  1799. unsigned OpEncodeFlags = 0;
  1800. PUH_ORDER pOrder = (PUH_ORDER)_OD.lastFastIndex;
  1801. LPINDEX_ORDER pGI = (LPINDEX_ORDER)(_OD.lastFastIndex +
  1802. UH_ORDER_HEADER_SIZE);
  1803. FAST_INDEX_ORDER FAR *pFI = (FAST_INDEX_ORDER FAR *)
  1804. (_OD.lastFastIndex + UH_ORDER_HEADER_SIZE);
  1805. BYTE FAR *pFieldDecode = *ppFieldDecode;
  1806. BYTE FAR *pEnd = pFieldDecode + dataLen;
  1807. DC_BEGIN_FN("ODDecodeFastIndex");
  1808. // Copy initial non-coordinate fields if present.
  1809. if (FieldFlags & 0x0001) {
  1810. OD_DECODE_CHECK_READ(pFieldDecode, BYTE, pEnd, hr);
  1811. pFI->cacheId = *pFieldDecode++;
  1812. }
  1813. if (FieldFlags & 0x0002) {
  1814. OD_DECODE_CHECK_READ(pFieldDecode, UINT16, pEnd, hr);
  1815. pFI->fDrawing = *((UINT16 UNALIGNED FAR *)pFieldDecode);
  1816. pFieldDecode += 2;
  1817. }
  1818. if (FieldFlags & 0x0004) {
  1819. OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, 3, pEnd, hr);
  1820. pFI->BackColor.u.rgb.red = *pFieldDecode++;
  1821. pFI->BackColor.u.rgb.green = *pFieldDecode++;
  1822. pFI->BackColor.u.rgb.blue = *pFieldDecode++;
  1823. }
  1824. if (FieldFlags & 0x0008) {
  1825. OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, 3, pEnd, hr);
  1826. pFI->ForeColor.u.rgb.red = *pFieldDecode++;
  1827. pFI->ForeColor.u.rgb.green = *pFieldDecode++;
  1828. pFI->ForeColor.u.rgb.blue = *pFieldDecode++;
  1829. }
  1830. if (ControlFlags & TS_DELTA_COORDINATES) {
  1831. // All coord fields are 1-byte signed deltas from the last values.
  1832. if (FieldFlags & 0x0010) {
  1833. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1834. pFI->BkLeft += *((char FAR *)pFieldDecode);
  1835. pFieldDecode++;
  1836. }
  1837. if (FieldFlags & 0x0020) {
  1838. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1839. pFI->BkTop += *((char FAR *)pFieldDecode);
  1840. pFieldDecode++;
  1841. }
  1842. if (FieldFlags & 0x0040) {
  1843. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1844. pFI->BkRight += *((char FAR *)pFieldDecode);
  1845. pFieldDecode++;
  1846. }
  1847. if (FieldFlags & 0x0080) {
  1848. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1849. pFI->BkBottom += *((char FAR *)pFieldDecode);
  1850. pFieldDecode++;
  1851. }
  1852. if (FieldFlags & 0x0100) {
  1853. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1854. pFI->OpLeft += *((char FAR *)pFieldDecode);
  1855. pFieldDecode++;
  1856. }
  1857. if (FieldFlags & 0x0200) {
  1858. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1859. pFI->OpTop += *((char FAR *)pFieldDecode);
  1860. pFieldDecode++;
  1861. }
  1862. if (FieldFlags & 0x0400) {
  1863. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1864. pFI->OpRight += *((char FAR *)pFieldDecode);
  1865. pFieldDecode++;
  1866. }
  1867. if (FieldFlags & 0x0800) {
  1868. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1869. pFI->OpBottom += *((char FAR *)pFieldDecode);
  1870. pFieldDecode++;
  1871. }
  1872. if (FieldFlags & 0x1000) {
  1873. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1874. pFI->x += *((char FAR *)pFieldDecode);
  1875. pFieldDecode++;
  1876. }
  1877. if (FieldFlags & 0x2000) {
  1878. OD_DECODE_CHECK_READ(pFieldDecode, char, pEnd, hr);
  1879. pFI->y += *((char FAR *)pFieldDecode);
  1880. pFieldDecode++;
  1881. }
  1882. }
  1883. else {
  1884. // All coord fields are 2-byte values.sign-extended from the output.
  1885. if (FieldFlags & 0x0010) {
  1886. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1887. pFI->BkLeft = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1888. pFieldDecode += 2;
  1889. }
  1890. if (FieldFlags & 0x0020) {
  1891. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1892. pFI->BkTop = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1893. pFieldDecode += 2;
  1894. }
  1895. if (FieldFlags & 0x0040) {
  1896. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1897. pFI->BkRight = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1898. pFieldDecode += 2;
  1899. }
  1900. if (FieldFlags & 0x0080) {
  1901. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1902. pFI->BkBottom = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1903. pFieldDecode += 2;
  1904. }
  1905. if (FieldFlags & 0x0100) {
  1906. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1907. pFI->OpLeft = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1908. pFieldDecode += 2;
  1909. }
  1910. if (FieldFlags & 0x0200) {
  1911. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1912. pFI->OpTop = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1913. pFieldDecode += 2;
  1914. }
  1915. if (FieldFlags & 0x0400) {
  1916. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1917. pFI->OpRight = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1918. pFieldDecode += 2;
  1919. }
  1920. if (FieldFlags & 0x0800) {
  1921. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1922. pFI->OpBottom = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1923. pFieldDecode += 2;
  1924. }
  1925. if (FieldFlags & 0x1000) {
  1926. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1927. pFI->x = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1928. pFieldDecode += 2;
  1929. }
  1930. if (FieldFlags & 0x2000) {
  1931. OD_DECODE_CHECK_READ(pFieldDecode, INT16, pEnd, hr);
  1932. pFI->y = *((INT16 UNALIGNED FAR *)pFieldDecode);
  1933. pFieldDecode += 2;
  1934. }
  1935. }
  1936. if (FieldFlags & 0x4000) {
  1937. // First byte is the number of following bytes.
  1938. OD_DECODE_CHECK_READ(pFieldDecode, BYTE, pEnd, hr);
  1939. pFI->variableBytes.len = *pFieldDecode++;
  1940. // The structure is defined with 255 elements
  1941. if (255 < pFI->variableBytes.len) {
  1942. TRC_ABORT(( TB, _T("VARIBLE_INDEXBYTES len too great; len %u"),
  1943. pFI->variableBytes.len ));
  1944. hr = E_TSC_CORE_LENGTH;
  1945. DC_QUIT;
  1946. }
  1947. OD_DECODE_CHECK_READ_MULT(pFieldDecode, BYTE, pFI->variableBytes.len,
  1948. pEnd, hr);
  1949. memcpy(pFI->variableBytes.arecs, pFieldDecode,
  1950. pFI->variableBytes.len);
  1951. pFieldDecode += pFI->variableBytes.len;
  1952. }
  1953. // Return the incremented pointer to the main routine.
  1954. *ppFieldDecode = pFieldDecode;
  1955. // If we've not already set the bounds (the order didn't contain
  1956. // any), set the bounds to the blt rect and reset the clip region.
  1957. // This rect might be needed later to add to the clip region for
  1958. // updating the shadow buffer to the screen.
  1959. if (!(ControlFlags & TS_BOUNDS)) {
  1960. if (pFI->OpTop < pFI->OpBottom) {
  1961. pOrder->dstRect.right = (int)pFI->OpRight;
  1962. pOrder->dstRect.left = (int)pFI->OpLeft;
  1963. pOrder->dstRect.top = (int)pFI->OpTop;
  1964. pOrder->dstRect.bottom = (int)pFI->OpBottom;
  1965. }
  1966. else {
  1967. // Since we encode OpRect fields, we have to
  1968. // decode it to get the correct bound rect.
  1969. if (pFI->OpTop == 0xF) {
  1970. // Opaque rect is same as bk rect
  1971. pOrder->dstRect.left = (int)pFI->BkLeft;
  1972. pOrder->dstRect.top = (int)pFI->BkTop;
  1973. pOrder->dstRect.right = (int)pFI->BkRight;
  1974. pOrder->dstRect.bottom = (int)pFI->BkBottom;
  1975. }
  1976. else if (pFI->OpTop == 0xD) {
  1977. // Opaque rect is same as bk rect except
  1978. // OpRight stored in OpTop field
  1979. pOrder->dstRect.left = (int)pFI->BkLeft;
  1980. pOrder->dstRect.top = (int)pFI->BkTop;
  1981. pOrder->dstRect.right = (int)pFI->OpRight;
  1982. pOrder->dstRect.bottom = (int)pFI->BkBottom;
  1983. }
  1984. else {
  1985. // We take the Bk rect as bound rect
  1986. pOrder->dstRect.right = (int)pFI->BkRight;
  1987. pOrder->dstRect.left = (int)pFI->BkLeft;
  1988. pOrder->dstRect.top = (int)pFI->BkTop;
  1989. pOrder->dstRect.bottom = (int)pFI->BkBottom;
  1990. }
  1991. }
  1992. _pUh->UH_ResetClipRegion();
  1993. }
  1994. else {
  1995. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  1996. pOrder->dstRect.right, pOrder->dstRect.bottom);
  1997. }
  1998. // pGI and pFI are different views of the same order memory.
  1999. // We translate to the regular glyph index order format for display
  2000. // handling, then translate back.
  2001. pGI->cacheId = (BYTE)(pFI->cacheId & 0xF); // Mask out high bits for future use.
  2002. pGI->flAccel = (BYTE)(pFI->fDrawing >> 8);
  2003. pGI->ulCharInc = (BYTE)(pFI->fDrawing & 0xFF);
  2004. pGI->fOpRedundant = 0;
  2005. // For Fast Index order, we need to decode for x, y and
  2006. // opaque rect.
  2007. if (pFI->OpBottom == INT16_MIN) {
  2008. OpEncodeFlags = (unsigned)pFI->OpTop;
  2009. if (OpEncodeFlags == 0xF) {
  2010. // Opaque rect is redundant
  2011. pGI->OpLeft = pFI->BkLeft;
  2012. pGI->OpTop = pFI->BkTop;
  2013. pGI->OpRight = pFI->BkRight;
  2014. pGI->OpBottom = pFI->BkBottom;
  2015. }
  2016. else if (OpEncodeFlags == 0xD) {
  2017. // Opaque rect is redundant except OpRight
  2018. // which is stored in OpTop
  2019. pGI->OpLeft = pFI->BkLeft;
  2020. pGI->OpTop = pFI->BkTop;
  2021. pGI->OpRight = pFI->OpRight;
  2022. pGI->OpBottom = pFI->BkBottom;
  2023. }
  2024. }
  2025. if (pFI->x == INT16_MIN)
  2026. pGI->x = pFI->BkLeft;
  2027. if (pFI->y == INT16_MIN)
  2028. pGI->y = pFI->BkTop;
  2029. TRC_NRM((TB, _T("ORDER: Glyph index cacheId %u flAccel %u ")
  2030. _T("ulCharInc %u fOpRedundant %u"),
  2031. pGI->cacheId, (unsigned)pGI->flAccel, (unsigned)pGI->ulCharInc,
  2032. (unsigned)pGI->fOpRedundant));
  2033. TRC_NRM((TB, _T(" bc %08lX fc %08lX Bk(%ld,%ld)-(%ld,%ld) ")
  2034. _T("Op(%ld,%ld)-(%ld,%ld)"),
  2035. pGI->BackColor, pGI->ForeColor,
  2036. pGI->BkLeft, pGI->BkTop, pGI->BkRight, pGI->BkBottom,
  2037. pGI->OpLeft, pGI->OpTop, pGI->OpRight, pGI->OpBottom));
  2038. TRC_NRM((TB, _T(" BrushOrg x %ld y %ld BrushStyle %lu x %ld y %ld"),
  2039. pGI->BrushOrgX, pGI->BrushOrgY,
  2040. pGI->BrushStyle, pGI->x, pGI->y));
  2041. TIMERSTART;
  2042. hr = _pUh->UHDrawGlyphOrder(pGI, &pFI->variableBytes);
  2043. TIMERSTOP;
  2044. UPDATECOUNTER(FC_FAST_INDEX_TYPE);
  2045. DC_QUIT_ON_FAIL(hr);
  2046. // Now we need to put bits back
  2047. if (OpEncodeFlags) {
  2048. if (OpEncodeFlags == 0xF) {
  2049. pGI->OpLeft = 0;
  2050. pGI->OpTop = OpEncodeFlags;
  2051. pGI->OpRight = 0;
  2052. pGI->OpBottom = INT16_MIN;
  2053. }
  2054. else if (OpEncodeFlags == 0xD) {
  2055. pGI->OpLeft = 0;
  2056. pGI->OpTop = OpEncodeFlags;
  2057. pGI->OpRight = pGI->OpRight;
  2058. pGI->OpBottom = INT16_MIN;
  2059. }
  2060. }
  2061. if (pFI->x == pFI->BkLeft)
  2062. pGI->x = INT16_MIN;
  2063. if (pFI->y == pFI->BkTop)
  2064. pGI->y = INT16_MIN;
  2065. DC_EXIT_POINT:
  2066. DC_END_FN();
  2067. return hr;
  2068. }
  2069. /****************************************************************************/
  2070. // ODHandleFastGlyph
  2071. //
  2072. // Order handler for FastGlyph orders.
  2073. /****************************************************************************/
  2074. HRESULT DCINTERNAL COD::ODHandleFastGlyph(PUH_ORDER pOrder, UINT16 uiVarDataLen,
  2075. BOOL bBoundsSet)
  2076. {
  2077. HRESULT hr = S_OK;
  2078. unsigned OpEncodeFlags = 0;
  2079. VARIABLE_INDEXBYTES VariableBytes;
  2080. LPINDEX_ORDER pGI = (LPINDEX_ORDER)pOrder->orderData;
  2081. LPFAST_GLYPH_ORDER pFG = (LPFAST_GLYPH_ORDER)pOrder->orderData;
  2082. DC_BEGIN_FN("ODHandleFastGlyph");
  2083. // If we've not already set the bounds (the order didn't contain
  2084. // any), set the bounds to the blt rect and reset the clip region.
  2085. // This rect might be needed later to add to the clip region for
  2086. // updating the shadow buffer to the screen.
  2087. if (!bBoundsSet) {
  2088. if (pFG->OpTop < pFG->OpBottom) {
  2089. pOrder->dstRect.right = (int)pFG->OpRight;
  2090. pOrder->dstRect.left = (int)pFG->OpLeft;
  2091. pOrder->dstRect.top = (int)pFG->OpTop;
  2092. pOrder->dstRect.bottom = (int)pFG->OpBottom;
  2093. }
  2094. else {
  2095. // Since we encode OpRect fields, we have to
  2096. // decode it to get the correct bound rect.
  2097. if (pFG->OpTop == 0xF) {
  2098. // Opaque rect is same as bk rect
  2099. pOrder->dstRect.left = (int)pFG->BkLeft;
  2100. pOrder->dstRect.top = (int)pFG->BkTop;
  2101. pOrder->dstRect.right = (int)pFG->BkRight;
  2102. pOrder->dstRect.bottom = (int)pFG->BkBottom;
  2103. }
  2104. else if (pFG->OpTop == 0xD) {
  2105. // Opaque rect is same as bk rect except
  2106. // OpRight stored in OpTop field
  2107. pOrder->dstRect.left = (int)pFG->BkLeft;
  2108. pOrder->dstRect.top = (int)pFG->BkTop;
  2109. pOrder->dstRect.right = (int)pFG->OpRight;
  2110. pOrder->dstRect.bottom = (int)pFG->BkBottom;
  2111. }
  2112. else {
  2113. // We take the Bk rect as bound rect
  2114. pOrder->dstRect.right = (int)pFG->BkRight;
  2115. pOrder->dstRect.left = (int)pFG->BkLeft;
  2116. pOrder->dstRect.top = (int)pFG->BkTop;
  2117. pOrder->dstRect.bottom = (int)pFG->BkBottom;
  2118. }
  2119. }
  2120. _pUh->UH_ResetClipRegion();
  2121. }
  2122. else {
  2123. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  2124. pOrder->dstRect.right, pOrder->dstRect.bottom);
  2125. }
  2126. // pGI and pFG are different views of the same order memory.
  2127. // We translate to the regular glyph index order format for display
  2128. // handling, then translate back.
  2129. pGI->cacheId = (BYTE)(pFG->cacheId & 0xF); // Mask out high bits for future use.
  2130. OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, pFG->variableBytes.len);
  2131. // The structure is defined with 255 elements
  2132. if (255 < pFG->variableBytes.len) {
  2133. TRC_ABORT(( TB, _T("VARIBLE_INDEXBYTES len too great; len %u"),
  2134. pFG->variableBytes.len ));
  2135. hr = E_TSC_CORE_LENGTH;
  2136. DC_QUIT;
  2137. }
  2138. if (pFG->variableBytes.len < 1) {
  2139. TRC_ERR((TB,_T("No variable bytes")));
  2140. DC_QUIT;
  2141. }
  2142. if (pFG->variableBytes.len > 1) {
  2143. // SECURITY - the cacheId is verify in call to UHProcessCacheGlyphOrderRev2
  2144. hr = _pUh->UHProcessCacheGlyphOrderRev2(pGI->cacheId, 1,
  2145. pFG->variableBytes.glyphData,
  2146. (unsigned)pFG->variableBytes.len);
  2147. DC_QUIT_ON_FAIL(hr);
  2148. }
  2149. pGI->flAccel = (BYTE)(pFG->fDrawing >> 8);
  2150. pGI->ulCharInc = (BYTE)(pFG->fDrawing & 0xff);
  2151. pGI->fOpRedundant = 0;
  2152. // For Fast Index order, we need to decode for x, y and
  2153. // opaque rect.
  2154. if (pFG->OpBottom == INT16_MIN) {
  2155. OpEncodeFlags = (unsigned)pFG->OpTop;
  2156. if (OpEncodeFlags == 0xF) {
  2157. // Opaque rect is redundant
  2158. pGI->OpLeft = pFG->BkLeft;
  2159. pGI->OpTop = pFG->BkTop;
  2160. pGI->OpRight = pFG->BkRight;
  2161. pGI->OpBottom = pFG->BkBottom;
  2162. }
  2163. else if (OpEncodeFlags == 0xD) {
  2164. // Opaque rect is redundant except OpRight
  2165. // which is stored in OpTop
  2166. pGI->OpLeft = pFG->BkLeft;
  2167. pGI->OpTop = pFG->BkTop;
  2168. pGI->OpRight = pFG->OpRight;
  2169. pGI->OpBottom = pFG->BkBottom;
  2170. }
  2171. }
  2172. if (pFG->x == INT16_MIN)
  2173. pGI->x = pFG->BkLeft;
  2174. if (pFG->y == INT16_MIN)
  2175. pGI->y = pFG->BkTop;
  2176. // Setup index order for the glyph
  2177. VariableBytes.len = 2;
  2178. VariableBytes.arecs[0].byte = (BYTE)pFG->variableBytes.glyphData[0];
  2179. VariableBytes.arecs[1].byte = 0;
  2180. TIMERSTART;
  2181. hr = _pUh->UHDrawGlyphOrder(pGI, &VariableBytes);
  2182. TIMERSTOP;
  2183. UPDATECOUNTER(FC_FAST_INDEX_TYPE);
  2184. DC_QUIT_ON_FAIL(hr);
  2185. // Now we need to put bits back
  2186. if (OpEncodeFlags) {
  2187. if (OpEncodeFlags == 0xF) {
  2188. pGI->OpLeft = 0;
  2189. pGI->OpTop = OpEncodeFlags;
  2190. pGI->OpRight = 0;
  2191. pGI->OpBottom = INT16_MIN;
  2192. }
  2193. else if (OpEncodeFlags == 0xD) {
  2194. pGI->OpLeft = 0;
  2195. pGI->OpTop = OpEncodeFlags;
  2196. pGI->OpRight = pGI->OpRight;
  2197. pGI->OpBottom = INT16_MIN;
  2198. }
  2199. }
  2200. if (pFG->x == pFG->BkLeft)
  2201. pGI->x = INT16_MIN;
  2202. if (pFG->y == pFG->BkTop)
  2203. pGI->y = INT16_MIN;
  2204. DC_EXIT_POINT:
  2205. DC_END_FN();
  2206. return hr;
  2207. }
  2208. /****************************************************************************/
  2209. // ODHandleGlyphIndex
  2210. //
  2211. // Order handler for GlyphIndex orders.
  2212. /****************************************************************************/
  2213. HRESULT DCINTERNAL COD::ODHandleGlyphIndex(PUH_ORDER pOrder,
  2214. UINT16 uiVarDataLen, BOOL bBoundsSet)
  2215. {
  2216. HRESULT hr = S_OK;
  2217. LPINDEX_ORDER pGI = (LPINDEX_ORDER)pOrder->orderData;
  2218. DC_BEGIN_FN("ODHandleGlyphIndex");
  2219. // If we've not already set the bounds (the order didn't contain
  2220. // any), set the bounds to the blt rect and reset the clip region.
  2221. // This rect might be needed later to add to the clip region for
  2222. // updating the shadow buffer to the screen.
  2223. if (!bBoundsSet) {
  2224. if (pGI->OpTop < pGI->OpBottom) {
  2225. pOrder->dstRect.right = (int)pGI->OpRight;
  2226. pOrder->dstRect.left = (int)pGI->OpLeft;
  2227. pOrder->dstRect.top = (int)pGI->OpTop;
  2228. pOrder->dstRect.bottom = (int)pGI->OpBottom;
  2229. }
  2230. else {
  2231. pOrder->dstRect.right = (int)pGI->BkRight;
  2232. pOrder->dstRect.left = (int)pGI->BkLeft;
  2233. pOrder->dstRect.top = (int)pGI->BkTop;
  2234. pOrder->dstRect.bottom = (int)pGI->BkBottom;
  2235. }
  2236. _pUh->UH_ResetClipRegion();
  2237. }
  2238. else {
  2239. _pUh->UH_SetClipRegion(pOrder->dstRect.left, pOrder->dstRect.top,
  2240. pOrder->dstRect.right, pOrder->dstRect.bottom);
  2241. }
  2242. // Handle the opaque rectangle if given.
  2243. if (pGI->fOpRedundant) {
  2244. pGI->OpTop = pGI->BkTop;
  2245. pGI->OpRight = pGI->BkRight;
  2246. pGI->OpBottom = pGI->BkBottom;
  2247. pGI->OpLeft = pGI->BkLeft;
  2248. }
  2249. TRC_NRM((TB, _T("ORDER: Glyph index cacheId %u flAccel %u ")
  2250. _T("ulCharInc %u fOpRedundant %u"),
  2251. pGI->cacheId, (unsigned)pGI->flAccel, (unsigned)pGI->ulCharInc,
  2252. (unsigned)pGI->fOpRedundant));
  2253. TRC_NRM((TB, _T(" bc %08lX fc %08lX Bk(%ld,%ld)-(%ld,%ld) ")
  2254. _T("Op(%ld,%ld)-(%ld,%ld)"),
  2255. pGI->BackColor, pGI->ForeColor,
  2256. pGI->BkLeft, pGI->BkTop, pGI->BkRight, pGI->BkBottom,
  2257. pGI->OpLeft, pGI->OpTop, pGI->OpRight, pGI->OpBottom));
  2258. TRC_NRM((TB, _T(" BrushOrg x %ld y %ld BrushStyle %lu x %ld y %ld"),
  2259. pGI->BrushOrgX, pGI->BrushOrgY,
  2260. pGI->BrushStyle, pGI->x, pGI->y));
  2261. OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, pGI->variableBytes.len);
  2262. // The structure is defined with 255 elements
  2263. if (255 < pGI->variableBytes.len) {
  2264. TRC_ABORT((TB, _T("Variable bytes length too great; %u"),
  2265. pGI->variableBytes.len));
  2266. hr = E_TSC_CORE_LENGTH;
  2267. DC_QUIT;
  2268. }
  2269. TIMERSTART;
  2270. hr = _pUh->UHDrawGlyphOrder(pGI, &pGI->variableBytes);
  2271. TIMERSTOP;
  2272. UPDATECOUNTER(FC_INDEX_TYPE);
  2273. DC_QUIT_ON_FAIL(hr);
  2274. // Restore the correct last order data.
  2275. if (pGI->fOpRedundant) {
  2276. pGI->OpTop = 0;
  2277. pGI->OpRight = 0;
  2278. pGI->OpBottom = 0;
  2279. pGI->OpLeft = 0;
  2280. }
  2281. DC_EXIT_POINT:
  2282. DC_END_FN();
  2283. return hr;
  2284. }
  2285. /****************************************************************************/
  2286. // ODDecodeMultipleRects
  2287. //
  2288. // Translates wire protocol multiple clipping rects to unpacked form.
  2289. /****************************************************************************/
  2290. #define DECODE_DELTA() \
  2291. if (bDeltaZero) { \
  2292. Delta = 0; \
  2293. } \
  2294. else { \
  2295. OD_DECODE_CHECK_READ(pCurDecode, char, pDataEnd, hr); \
  2296. \
  2297. /* Sign-extend the low 7 bits of first byte into int. */ \
  2298. Delta = (int)((char)((*pCurDecode & 0x7F) | \
  2299. ((*pCurDecode & 0x40) << 1))); \
  2300. \
  2301. /* Get 2nd byte if present. */ \
  2302. if (*pCurDecode++ & ORD_CLIP_RECTS_LONG_DELTA) { \
  2303. OD_DECODE_CHECK_READ(pCurDecode, BYTE, pDataEnd, hr); \
  2304. Delta = (Delta << 8) | (*pCurDecode++); \
  2305. } \
  2306. } \
  2307. HRESULT COD::ODDecodeMultipleRects(
  2308. RECT *Rects,
  2309. UINT32 nDeltaEntries,
  2310. CLIP_RECT_VARIABLE_CODEDDELTALIST FAR *codedDeltaList,
  2311. UINT16 uiVarDataLen)
  2312. {
  2313. int Delta;
  2314. BYTE *ZeroFlags;
  2315. BOOL bDeltaZero;
  2316. unsigned i;
  2317. unsigned char *pCurDecode;
  2318. BYTE *pDataEnd;
  2319. HRESULT hr = S_OK;
  2320. DC_BEGIN_FN("ODDecodeMultipleRects");
  2321. TRC_ASSERT((nDeltaEntries > 0), (TB,_T("No rects passed in")));
  2322. OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, codedDeltaList->len);
  2323. // SECURITY: Because the OD_Decode already wrote this varible data into
  2324. // the lastOrderBuffer, we should be sure that we didn't get too much
  2325. // data at this point
  2326. if (codedDeltaList->len > ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN +
  2327. ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES) {
  2328. TRC_ABORT((TB, _T("codedDeltaList length too great; [got %u, max %u]"),
  2329. codedDeltaList->len, ORD_MAX_CLIP_RECTS_CODEDDELTAS_LEN +
  2330. ORD_MAX_CLIP_RECTS_ZERO_FLAGS_BYTES));
  2331. hr = E_TSC_CORE_LENGTH;
  2332. DC_QUIT;
  2333. }
  2334. if (nDeltaEntries > ORD_MAX_ENCODED_CLIP_RECTS) {
  2335. TRC_ABORT((TB, _T("number deltas too great; [got %u, max %u]"),
  2336. nDeltaEntries, ORD_MAX_ENCODED_CLIP_RECTS));
  2337. hr = E_TSC_CORE_LENGTH;
  2338. DC_QUIT;
  2339. }
  2340. pDataEnd = ((BYTE*)codedDeltaList->Deltas) + codedDeltaList->len;
  2341. // Get pointers to the zero flags placed before the encoded deltas, and
  2342. // the encoded deltas. Note the zero flags take 2 bits per encode
  2343. // point, 2 points per rectangle, rounded up to the nearest byte.
  2344. ZeroFlags = codedDeltaList->Deltas;
  2345. pCurDecode = codedDeltaList->Deltas + ((nDeltaEntries + 1) / 2);
  2346. // All access to ZeroFlags are checked with this
  2347. CHECK_READ_N_BYTES(ZeroFlags, pDataEnd, (BYTE*)pCurDecode-(BYTE*)ZeroFlags, hr,
  2348. (TB, _T("Read past end of data")));
  2349. // The first points are encoded as a delta from (0,0).
  2350. bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_XLDELTA_ZERO;
  2351. DECODE_DELTA();
  2352. TRC_DBG((TB, _T("Start x left %d"), Delta));
  2353. Rects[0].left = Delta;
  2354. bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_YTDELTA_ZERO;
  2355. DECODE_DELTA();
  2356. TRC_DBG((TB, _T("Start y top %d"), Delta));
  2357. Rects[0].top = Delta;
  2358. bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_XRDELTA_ZERO;
  2359. DECODE_DELTA();
  2360. TRC_DBG((TB, _T("Start x right %d"), Delta));
  2361. Rects[0].right = Rects[0].left + Delta;
  2362. bDeltaZero = ZeroFlags[0] & ORD_CLIP_RECTS_YBDELTA_ZERO;
  2363. DECODE_DELTA();
  2364. TRC_DBG((TB, _T("Start y %d"), Delta));
  2365. Rects[0].bottom = Rects[0].top + Delta;
  2366. TRC_NRM((TB,
  2367. _T("Rectangle #0 l,t %d,%d - r,b %d,%d"),
  2368. (int)Rects[0].left,
  2369. (int)Rects[0].top,
  2370. (int)Rects[0].right,
  2371. (int)Rects[0].bottom));
  2372. // Decode the encoded point deltas into regular POINTs to draw.
  2373. for (i = 1; i < nDeltaEntries; i++) {
  2374. // Decode the top left corner.
  2375. bDeltaZero = ZeroFlags[i / 2] &
  2376. (ORD_CLIP_RECTS_XLDELTA_ZERO >> (4 * (i & 0x01)));
  2377. DECODE_DELTA();
  2378. TRC_DBG((TB, _T("Delta x left %d"), Delta));
  2379. Rects[i].left = Rects[i - 1].left + Delta;
  2380. bDeltaZero = ZeroFlags[i / 2] &
  2381. (ORD_CLIP_RECTS_YTDELTA_ZERO >> (4 * (i & 0x01)));
  2382. DECODE_DELTA();
  2383. TRC_DBG((TB, _T("Delta y top %d"), Delta));
  2384. Rects[i].top = Rects[i - 1].top + Delta;
  2385. // and now the bottom right - note this is relative to the current
  2386. // top left rather than to the previous bottom right
  2387. bDeltaZero = ZeroFlags[i / 2] &
  2388. (ORD_CLIP_RECTS_XRDELTA_ZERO >> (4 * (i & 0x01)));
  2389. DECODE_DELTA();
  2390. TRC_DBG((TB, _T("Delta x right %d"), Delta));
  2391. Rects[i].right = Rects[i].left + Delta;
  2392. bDeltaZero = ZeroFlags[i / 2] &
  2393. (ORD_CLIP_RECTS_YBDELTA_ZERO >> (4 * (i & 0x01)));
  2394. DECODE_DELTA();
  2395. TRC_DBG((TB, _T("Delta y bottom %d"), Delta));
  2396. Rects[i].bottom = Rects[i].top + Delta;
  2397. TRC_NRM((TB,
  2398. _T("Drawing rectangle #%d l,t %d,%d - r,b %d,%d"),
  2399. i,
  2400. (int)Rects[i].left,
  2401. (int)Rects[i].top,
  2402. (int)Rects[i].right,
  2403. (int)Rects[i].bottom));
  2404. }
  2405. DC_EXIT_POINT:
  2406. DC_END_FN();
  2407. return hr;
  2408. }
  2409. /****************************************************************************/
  2410. // ODDecodePathPoints
  2411. //
  2412. // Decode encoded polygon and ellipse path points.
  2413. /****************************************************************************/
  2414. HRESULT DCINTERNAL COD::ODDecodePathPoints(
  2415. POINT *Points,
  2416. RECT *BoundRect,
  2417. BYTE FAR *pData,
  2418. unsigned NumDeltaEntries,
  2419. unsigned MaxNumDeltaEntries,
  2420. unsigned dataLen,
  2421. unsigned MaxDataLen,
  2422. UINT16 uiVarDataLen,
  2423. BOOL fUnClipped)
  2424. {
  2425. HRESULT hr = S_OK;
  2426. int Delta;
  2427. BOOL bDeltaZero;
  2428. unsigned i;
  2429. BYTE FAR * ZeroFlags;
  2430. BYTE FAR * pCurDecode;
  2431. BYTE FAR * pEnd;
  2432. DC_BEGIN_FN("ODDecodePathPoints");
  2433. OD_DECODE_CHECK_VARIABLE_DATALEN(uiVarDataLen, (UINT16)dataLen);
  2434. if (NumDeltaEntries > MaxNumDeltaEntries) {
  2435. TRC_ABORT((TB, _T("NumDeltaEntries too great; [got %u max %u]"),
  2436. NumDeltaEntries, MaxNumDeltaEntries));
  2437. hr = E_TSC_CORE_LENGTH;
  2438. DC_QUIT;
  2439. }
  2440. if (dataLen > MaxDataLen) {
  2441. TRC_ABORT((TB,_T("Received PolyLine with too-large internal length; ")
  2442. _T("[got %u max %u]"), dataLen, MaxDataLen));
  2443. hr = E_TSC_CORE_LENGTH;
  2444. DC_QUIT;
  2445. }
  2446. // Get pointers to the zero flags placed before the encoded
  2447. // deltas, and the encoded deltas. Note the zero flags take 2
  2448. // bits per encode point, rounded up to the nearest byte.
  2449. ZeroFlags = pData;
  2450. pCurDecode = pData +
  2451. ((NumDeltaEntries + 3) / 4);
  2452. pEnd = ZeroFlags + dataLen;
  2453. CHECK_READ_N_BYTES(ZeroFlags, pEnd, (BYTE*)pCurDecode-(BYTE*)ZeroFlags, hr,
  2454. (TB, _T("Read past end of data")));
  2455. // Decode the encoded point deltas into regular POINTs to draw.
  2456. for (i = 0; i < NumDeltaEntries; i++) {
  2457. // Determine if the X delta is zero by checking the 0 flag.
  2458. bDeltaZero = ZeroFlags[i / 4] &
  2459. (ORD_POLYLINE_XDELTA_ZERO >> (2 * (i & 0x03)));
  2460. if (bDeltaZero) {
  2461. Delta = 0;
  2462. }
  2463. else {
  2464. OD_DECODE_CHECK_READ(pCurDecode, char, pEnd, hr);
  2465. // Sign-extend the low 7 bits of first X byte into int.
  2466. Delta = (int)((char)((*pCurDecode & 0x7F) |
  2467. ((*pCurDecode & 0x40) << 1)));
  2468. // Get 2nd X byte if present.
  2469. if (*pCurDecode++ & ORD_POLYLINE_LONG_DELTA) {
  2470. OD_DECODE_CHECK_READ(pCurDecode, BYTE, pEnd, hr);
  2471. Delta = (Delta << 8) | (*pCurDecode++);
  2472. }
  2473. }
  2474. Points[i + 1].x = Points[i].x + Delta;
  2475. // Determine if the Y delta is zero by checking the 0 flag.
  2476. bDeltaZero = ZeroFlags[i / 4] &
  2477. (ORD_POLYLINE_YDELTA_ZERO >> (2 * (i & 0x03)));
  2478. if (bDeltaZero) {
  2479. Delta = 0;
  2480. }
  2481. else {
  2482. OD_DECODE_CHECK_READ(pCurDecode, char, pEnd, hr);
  2483. // Sign-extend the low 7 bits of first Y byte into int.
  2484. Delta = (int)((char)((*pCurDecode & 0x7F) |
  2485. ((*pCurDecode & 0x40) << 1)));
  2486. // Get 2nd Y byte if present.
  2487. if (*pCurDecode++ & ORD_POLYLINE_LONG_DELTA) {
  2488. OD_DECODE_CHECK_READ(pCurDecode, BYTE, pEnd, hr);
  2489. Delta = (Delta << 8) | (*pCurDecode++);
  2490. }
  2491. }
  2492. Points[i + 1].y = Points[i].y + Delta;
  2493. if (fUnClipped) {
  2494. // Update the calculated bounding rect.
  2495. if (Points[i + 1].x < BoundRect->left)
  2496. BoundRect->left = Points[i + 1].x;
  2497. else if (Points[i + 1].x > BoundRect->right)
  2498. BoundRect->right = Points[i + 1].x;
  2499. if (Points[i + 1].y < BoundRect->top)
  2500. BoundRect->top = Points[i + 1].y;
  2501. else if (Points[i + 1].y > BoundRect->bottom)
  2502. BoundRect->bottom = Points[i + 1].y;
  2503. }
  2504. }
  2505. DC_EXIT_POINT:
  2506. DC_END_FN();
  2507. return hr;
  2508. }
  2509. /****************************************************************************/
  2510. // ODDecodeFieldSingle
  2511. //
  2512. // Copies a single field entry from src to dest with field size
  2513. // conversion as necessary.
  2514. /****************************************************************************/
  2515. HRESULT DCINTERNAL COD::ODDecodeFieldSingle(
  2516. PPDCUINT8 ppSrc,
  2517. PDCVOID pDst,
  2518. unsigned srcFieldLength,
  2519. unsigned dstFieldLength,
  2520. BOOL signedValue)
  2521. {
  2522. HRESULT hr = S_OK;
  2523. DC_BEGIN_FN("ODDecodeFieldSingle");
  2524. if (dstFieldLength < srcFieldLength) {
  2525. TRC_ABORT((TB, _T("Src size greater than dest")));
  2526. hr = E_TSC_CORE_LENGTH;
  2527. DC_QUIT;
  2528. }
  2529. // If the source and destination field lengths are the same, we can
  2530. // just do a copy (no type conversion required).
  2531. if (srcFieldLength == dstFieldLength) {
  2532. memcpy(pDst, *ppSrc, dstFieldLength);
  2533. }
  2534. else {
  2535. // 3 types left to consider:
  2536. // 8 bit -> 16 bit
  2537. // 8 bit -> 32 bit
  2538. // 16 bit -> 32 bit
  2539. //
  2540. // We also have to get the signed / unsigned attributes correct. If
  2541. // we try to promote a signed value using unsigned pointers, we
  2542. // will get the wrong result.
  2543. //
  2544. // e.g. Consider converting the value -1 from a INT16 to INT32
  2545. // using unsigned pointers.
  2546. //
  2547. // -1 -> DCUINT16 == 65535
  2548. // -> DCUINT32 == 65535
  2549. // -> DCINT32 == 65535
  2550. // Most common among non-coord entries: 1-byte source.
  2551. if (srcFieldLength == 1) {
  2552. // Most common: 4-byte destination.
  2553. if (dstFieldLength == 4) {
  2554. // Most common: unsigned
  2555. if (!signedValue)
  2556. *((UINT32 FAR *)pDst) = *((BYTE FAR *)*ppSrc);
  2557. else
  2558. *((INT32 FAR *)pDst) = *((char FAR *)*ppSrc);
  2559. }
  2560. else if (dstFieldLength == 2) {
  2561. if (!signedValue)
  2562. *((UINT16 FAR *)pDst) = *((UINT16 UNALIGNED FAR *)*ppSrc);
  2563. else
  2564. *((INT16 FAR *)pDst) = *((short UNALIGNED FAR *)*ppSrc);
  2565. }
  2566. else {
  2567. TRC_ABORT((TB,_T("src size 1->dst %u"), dstFieldLength));
  2568. hr = E_TSC_CORE_LENGTH;
  2569. DC_QUIT;
  2570. }
  2571. }
  2572. // Only thing left should be 2-byte to 4-byte.
  2573. else if (srcFieldLength == 2 && dstFieldLength == 4) {
  2574. if (!signedValue)
  2575. *((UINT32 FAR *)pDst) = *((UINT16 UNALIGNED FAR *)*ppSrc);
  2576. else
  2577. *((INT32 FAR *)pDst) = *((short UNALIGNED FAR *)*ppSrc);
  2578. }
  2579. else {
  2580. TRC_ABORT((TB,_T("src=%u, dst=%u - unexpected"), srcFieldLength,
  2581. dstFieldLength));
  2582. hr = E_TSC_CORE_LENGTH;
  2583. DC_QUIT;
  2584. }
  2585. }
  2586. *ppSrc += srcFieldLength;
  2587. DC_EXIT_POINT:
  2588. DC_END_FN();
  2589. return hr;
  2590. }
  2591. #ifdef OS_WINCE
  2592. BOOL DCINTERNAL COD::ODHandleAlwaysOnTopRects(LPMULTI_SCRBLT_ORDER pSB)
  2593. {
  2594. DC_BEGIN_FN("ODHandleAlwaysOnTopRects");
  2595. BOOL bIntersect = FALSE;
  2596. RECT rectSrc, rectIntersect, rectInvalid;
  2597. SetRect(&rectSrc, (int)pSB->nXSrc, (int)pSB->nYSrc,
  2598. (int)(pSB->nXSrc + pSB->nWidth), (int)(pSB->nYSrc + pSB->nHeight));
  2599. for (DWORD j=0; j<_pUh->_UH.ulNumAOTRects; j++)
  2600. {
  2601. if (IntersectRect(&rectIntersect, &rectSrc, &(_pUh->_UH.rcaAOT[j])))
  2602. {
  2603. bIntersect = TRUE;
  2604. break;
  2605. }
  2606. }
  2607. if (!bIntersect)
  2608. {
  2609. GetUpdateRect(_pOp->OP_GetOutputWindowHandle(), &rectInvalid, FALSE);
  2610. bIntersect = (IntersectRect(&rectIntersect, &rectSrc, &rectInvalid));
  2611. }
  2612. if (bIntersect)
  2613. {
  2614. SetRect(&rectInvalid, pSB->nLeftRect, pSB->nTopRect,
  2615. pSB->nLeftRect+pSB->nWidth, pSB->nTopRect+pSB->nHeight);
  2616. InvalidateRect(_pOp->OP_GetOutputWindowHandle(), &rectInvalid, FALSE);
  2617. }
  2618. DC_END_FN();
  2619. return bIntersect;
  2620. }
  2621. #endif