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.

5911 lines
175 KiB

  1. #include "precomp.h"
  2. //
  3. // OE.C
  4. // Order Encoder, display driver side
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. //
  9. // Number of entries in the font alias table.
  10. //
  11. #define NUM_ALIAS_FONTS 3
  12. //
  13. // Define entries in the Font Alias table. This table is used to convert
  14. // non-existant fonts (used by certain widely used applications) into
  15. // something we can use as a local font.
  16. //
  17. // The font names that we alias are:
  18. //
  19. // "Helv"
  20. // This is used by Excel. It is mapped directly onto "MS Sans Serif".
  21. //
  22. // "MS Dialog"
  23. // This is used by Word. It is the same as an 8pt bold MS Sans Serif.
  24. // We actually map it to a "MS Sans Serif" font that is one pel narrower
  25. // than the metrics specify (because all matching is done on non-bold
  26. // fonts) - hence the 1 value in the charWidthAdjustment field.
  27. //
  28. // "MS Dialog Light"
  29. // Added as part of the Win95 performance enhancements...Presumably for
  30. // MS-Word...
  31. //
  32. //
  33. FONT_ALIAS_TABLE fontAliasTable[NUM_ALIAS_FONTS] =
  34. {
  35. { "Helv", "MS Sans Serif", 0 },
  36. { "MS Dialog", "MS Sans Serif", 1 },
  37. { "MS Dialog Light", "MS Sans Serif", 0 }
  38. };
  39. //
  40. // FUNCTION: OE_SendAsOrder see oe.h
  41. //
  42. BOOL OE_SendAsOrder(DWORD order)
  43. {
  44. BOOL rc = FALSE;
  45. DebugEntry(OE_SendAsOrder);
  46. //
  47. // Only check the order if we are allowed to send orders in the first
  48. // place!
  49. //
  50. if (g_oeSendOrders)
  51. {
  52. TRACE_OUT(("Orders enabled"));
  53. //
  54. // We are sending some orders, so check individual flags.
  55. //
  56. rc = (BOOL)g_oeOrderSupported[HIWORD(order)];
  57. TRACE_OUT(("Send order %lx HIWORD %hu", order, HIWORD(order)));
  58. }
  59. DebugExitDWORD(OE_SendAsOrder, rc);
  60. return(rc);
  61. }
  62. //
  63. // OE_RectIntersectsSDA - see oe.h
  64. //
  65. BOOL OE_RectIntersectsSDA(LPRECT pRect)
  66. {
  67. RECT rectVD;
  68. BOOL fIntersection = FALSE;
  69. UINT i;
  70. DebugEntry(OE_RectIntersectsSDA);
  71. //
  72. // Copy the supplied rectangle, converting to inclusive Virtual
  73. // Desktop coords.
  74. //
  75. rectVD.left = pRect->left;
  76. rectVD.top = pRect->top;
  77. rectVD.right = pRect->right - 1;
  78. rectVD.bottom = pRect->bottom - 1;
  79. //
  80. // Loop through each of the bounding rectangles checking for
  81. // an intersection with the supplied rectangle.
  82. //
  83. for (i = 0; i <= BA_NUM_RECTS; i++)
  84. {
  85. if ( (g_baBounds[i].InUse) &&
  86. (g_baBounds[i].Coord.left <= rectVD.right) &&
  87. (g_baBounds[i].Coord.top <= rectVD.bottom) &&
  88. (g_baBounds[i].Coord.right >= rectVD.left) &&
  89. (g_baBounds[i].Coord.bottom >= rectVD.top) )
  90. {
  91. TRACE_OUT(("Rect(%d,%d)(%d,%d) intersects SDA(%d,%d)(%d,%d)",
  92. rectVD.left, rectVD.top,
  93. rectVD.right, rectVD.bottom,
  94. g_baBounds[i].Coord.left, g_baBounds[i].Coord.top,
  95. g_baBounds[i].Coord.right, g_baBounds[i].Coord.bottom));
  96. fIntersection = TRUE;
  97. break;
  98. }
  99. }
  100. DebugExitDWORD(OE_RectIntersectsSDA, fIntersection);
  101. return(fIntersection);
  102. }
  103. //
  104. // DrvBitBlt - see NT DDK documentation.
  105. //
  106. BOOL DrvBitBlt( SURFOBJ *psoDst,
  107. SURFOBJ *psoSrc,
  108. SURFOBJ *psoMask,
  109. CLIPOBJ *pco,
  110. XLATEOBJ *pxlo,
  111. RECTL *prclDst,
  112. POINTL *pptlSrc,
  113. POINTL *pptlMask,
  114. BRUSHOBJ *pbo,
  115. POINTL *pptlBrush,
  116. ROP4 rop4 )
  117. {
  118. LPOSI_PDEV ppdev = (LPOSI_PDEV)psoDst->dhpdev;
  119. BOOL rc = TRUE;
  120. UINT orderType = 0;
  121. BYTE rop3;
  122. LPINT_ORDER pOrder = NULL;
  123. LPDSTBLT_ORDER pDstBlt;
  124. LPSCRBLT_ORDER pScrBlt;
  125. LPMEMBLT_ORDER pMemBlt;
  126. LPMEM3BLT_ORDER pMem3Blt;
  127. BOOL fSendOrder = FALSE;
  128. BOOL fAccumulate = FALSE;
  129. UINT fOrderFlags = OF_SPOILABLE;
  130. RECT bounds;
  131. RECT intersectRect;
  132. POINT origin;
  133. POE_BRUSH_DATA pCurrentBrush;
  134. MEMBLT_ORDER_EXTRA_INFO memBltExtraInfo;
  135. DebugEntry(DrvBitBlt);
  136. //
  137. // DO THIS _BEFORE_ TAKING LOCKS
  138. //
  139. if (!g_oeViewers)
  140. goto NO_LOCK_EXIT;
  141. OE_SHM_START_WRITING;
  142. //
  143. // Get the bounding rectangle for the operation.
  144. //
  145. RECT_FROM_RECTL(bounds, (*prclDst));
  146. //
  147. // Check if we are accumulating data for this function
  148. //
  149. fAccumulate = OEAccumulateOutput(psoDst, pco, &bounds);
  150. if (!fAccumulate)
  151. {
  152. DC_QUIT;
  153. }
  154. //
  155. // Convert the data to virtual coordinates.
  156. //
  157. OELRtoVirtual(&bounds, 1);
  158. //
  159. // Check if this 4-way ROP simplifies to a 3-way ROP. A 4-way ROP
  160. // contains two 3-way ROPS, one for each setting of a mask bit - the
  161. // high ROP3 corresponds to a value of zero in the mask bit.
  162. //
  163. // If the two 3-way ROPs are the same, we know the 4-way ROP is a 3-way
  164. // ROP.
  165. //
  166. if (ROP3_LOW_FROM_ROP4(rop4) == ROP3_HIGH_FROM_ROP4(rop4))
  167. {
  168. //
  169. // Take the high byte as the 3-way ROP.
  170. //
  171. rop3 = ROP3_HIGH_FROM_ROP4(rop4);
  172. TRACE_OUT(( "4-way ROP %04x is really 3-way %02x", rop4, rop3));
  173. }
  174. else
  175. {
  176. TRACE_OUT(( "4-way ROP %08x", rop4));
  177. DC_QUIT;
  178. }
  179. //
  180. // Determine the command type. It can be one of the following.
  181. //
  182. // DSTBLT - A destination only BLT (no source, or pattern)
  183. // PATBLT - a pattern BLT (no source)
  184. // SCRBLT - a screen to screen BLT
  185. // MEMBLT - a memory to screen BLT (no pattern)
  186. // MEM3BLT - a memory to screen 3-way BLT
  187. //
  188. //
  189. // Check for destination only BLTs (ie. independent of source bits).
  190. //
  191. if ((psoSrc == NULL) || ROP3_NO_SOURCE(rop3))
  192. {
  193. //
  194. // Check for a pattern or true destination BLT.
  195. //
  196. if (ROP3_NO_PATTERN(rop3))
  197. {
  198. TRACE_OUT(( "DSTBLT"));
  199. orderType = ORD_DSTBLT;
  200. }
  201. else
  202. {
  203. TRACE_OUT(( "PATBLT"));
  204. orderType = ORD_PATBLT;
  205. }
  206. }
  207. else
  208. {
  209. //
  210. // We have a source BLT, check whether we have screen or memory
  211. // BLTs.
  212. //
  213. if (psoSrc->hsurf != ppdev->hsurfScreen)
  214. {
  215. if (psoDst->hsurf != ppdev->hsurfScreen)
  216. {
  217. ERROR_OUT(( "MEM to MEM blt!"));
  218. }
  219. else
  220. {
  221. //
  222. // We have a memory to screen BLT, check which type.
  223. //
  224. if ((ppdev->cBitsPerPel == 4) && (rop3 != 0xcc))
  225. {
  226. //
  227. // No order -- the result depends on the palette
  228. // which is dicy in VGA
  229. //
  230. TRACE_OUT(("No order on VGA for rop 0x%02x", rop3));
  231. DC_QUIT;
  232. }
  233. if (ROP3_NO_PATTERN(rop3))
  234. {
  235. TRACE_OUT(( "MEMBLT"));
  236. orderType = ORD_MEMBLT;
  237. }
  238. else
  239. {
  240. TRACE_OUT(( "MEM3BLT"));
  241. orderType = ORD_MEM3BLT;
  242. }
  243. }
  244. }
  245. else
  246. {
  247. if (psoDst->hsurf != ppdev->hsurfScreen)
  248. {
  249. TRACE_OUT(( "SCR to MEM blt!"));
  250. }
  251. else
  252. {
  253. //
  254. // We only support destination only screen BLTs (ie. no
  255. // patterns allowed).
  256. //
  257. if (ROP3_NO_PATTERN(rop3))
  258. {
  259. TRACE_OUT(( "SCRBLT"));
  260. orderType = ORD_SCRBLT;
  261. }
  262. else
  263. {
  264. TRACE_OUT(( "Unsupported screen ROP %x", rop3));
  265. }
  266. }
  267. }
  268. }
  269. //
  270. // Check if we have a supported order.
  271. //
  272. if (orderType == 0)
  273. {
  274. TRACE_OUT(( "Unsupported BLT"));
  275. fAccumulate = FALSE;
  276. DC_QUIT;
  277. }
  278. //
  279. // Check if we are allowed to send this order (determined by the
  280. // negotiated capabilities of all the machines in the conference).
  281. //
  282. if (!OE_SendAsOrder(orderType))
  283. {
  284. TRACE_OUT(( "Order %d not allowed", orderType));
  285. DC_QUIT;
  286. }
  287. //
  288. // Check if we are allowed to send the ROP.
  289. //
  290. if (!OESendRop3AsOrder(rop3))
  291. {
  292. TRACE_OUT(( "Cannot send ROP %d", rop3));
  293. DC_QUIT;
  294. }
  295. //
  296. // Check for overcomplicated clipping.
  297. //
  298. if (OEClippingIsComplex(pco))
  299. {
  300. TRACE_OUT(( "Clipping is too complex"));
  301. DC_QUIT;
  302. }
  303. //
  304. // If this is a Memblt, do an initial check on whether it is cachable
  305. //
  306. if ((orderType == ORD_MEMBLT) || (orderType == ORD_MEM3BLT))
  307. {
  308. //
  309. // We have to fill in a structure containing extra into
  310. // specifically for a MEM(3)BLT order.
  311. //
  312. memBltExtraInfo.pSource = psoSrc;
  313. memBltExtraInfo.pDest = psoDst;
  314. memBltExtraInfo.pXlateObj = pxlo;
  315. if (!SBC_DDIsMemScreenBltCachable(&memBltExtraInfo))
  316. {
  317. TRACE_OUT(( "MemBlt is not cachable"));
  318. DC_QUIT;
  319. }
  320. //
  321. // It is cachable. Before we get SBC to do the caching, we have to
  322. // allow it to queue a color table (if required).
  323. //
  324. if (!SBC_DDMaybeQueueColorTable(ppdev))
  325. {
  326. TRACE_OUT(( "Unable to queue color table for MemBlt"));
  327. DC_QUIT;
  328. }
  329. }
  330. //
  331. // We have a recognised order - do the specific checks for each order.
  332. //
  333. switch (orderType)
  334. {
  335. case ORD_DSTBLT:
  336. //
  337. // Allocate the memory for the order.
  338. //
  339. pOrder = OA_DDAllocOrderMem(sizeof(DSTBLT_ORDER),0);
  340. if (pOrder == NULL)
  341. {
  342. TRACE_OUT(( "Failed to alloc order"));
  343. DC_QUIT;
  344. }
  345. pDstBlt = (LPDSTBLT_ORDER)pOrder->abOrderData;
  346. //
  347. // Set the spoiler flag if the rop is opaque.
  348. //
  349. if (ROP3_IS_OPAQUE(rop3))
  350. {
  351. fOrderFlags |= OF_SPOILER;
  352. }
  353. //
  354. // Store the order type.
  355. //
  356. pDstBlt->type = LOWORD(orderType);
  357. //
  358. // Virtual desktop co-ordinates.
  359. //
  360. pDstBlt->nLeftRect = bounds.left;
  361. pDstBlt->nTopRect = bounds.top;
  362. pDstBlt->nWidth = bounds.right - bounds.left + 1;
  363. pDstBlt->nHeight = bounds.bottom - bounds.top + 1;
  364. pDstBlt->bRop = rop3;
  365. TRACE_OUT(( "DstBlt X %d Y %d w %d h %d rop %02X",
  366. pDstBlt->nLeftRect,
  367. pDstBlt->nTopRect,
  368. pDstBlt->nWidth,
  369. pDstBlt->nHeight,
  370. pDstBlt->bRop));
  371. break;
  372. case ORD_PATBLT:
  373. if ( !OEEncodePatBlt(ppdev,
  374. pbo,
  375. pptlBrush,
  376. rop3,
  377. &bounds,
  378. &pOrder) )
  379. {
  380. //
  381. // Something went wrong with the encoding, so skip to the
  382. // end to add this operation to the SDA.
  383. //
  384. DC_QUIT;
  385. }
  386. fOrderFlags = pOrder->OrderHeader.Common.fOrderFlags;
  387. break;
  388. case ORD_SCRBLT:
  389. //
  390. // Check for a SCRBLT as a result of a Desktop Scroll. We must
  391. // ignore these as they will stuff the remote desktop.
  392. //
  393. // The check is simple - if the virtual position of the source
  394. // is the same as the virual position of the target for a
  395. // SRCCOPY type SCRBLT, we have a hit...
  396. //
  397. POINT_FROM_POINTL(origin, (*pptlSrc));
  398. //
  399. // Allocate the memory for the order.
  400. //
  401. pOrder = OA_DDAllocOrderMem(sizeof(SCRBLT_ORDER),0);
  402. if (pOrder == NULL)
  403. {
  404. TRACE_OUT(( "Failed to alloc order"));
  405. DC_QUIT;
  406. }
  407. pScrBlt = (LPSCRBLT_ORDER)pOrder->abOrderData;
  408. //
  409. // Store the order type.
  410. //
  411. pScrBlt->type = LOWORD(orderType);
  412. //
  413. // All data which is sent over the wire must be in virtual
  414. // desktop co-ordinates. OELRtoVirtual has already converted
  415. // bounds to an inclusive rectangle in virtual co-ordinates.
  416. //
  417. pScrBlt->nLeftRect = bounds.left;
  418. pScrBlt->nTopRect = bounds.top;
  419. pScrBlt->nWidth = bounds.right - bounds.left + 1;
  420. pScrBlt->nHeight = bounds.bottom - bounds.top + 1;
  421. pScrBlt->bRop = rop3;
  422. //
  423. // Source point on the screen.
  424. //
  425. OELPtoVirtual(&origin, 1);
  426. pScrBlt->nXSrc = origin.x;
  427. pScrBlt->nYSrc = origin.y;
  428. //
  429. // Screen to screen blts are Blocking orders (i.e. they
  430. // prevent any previous orders from being spoilt).
  431. //
  432. // We do not mark Screen to Screen blts as SPOILER orders. If
  433. // the ROP is opaque we could spoil the destination rect, but
  434. // only the area that does not overlap with the src rectangle.
  435. // The most common use of Screen to Screen blts is scrolling,
  436. // where the src and dst rects almost completely overlap,
  437. // giving only a small "spoiler" region. The spoiler region
  438. // could also be complex (more that 1 rect).
  439. //
  440. // Consequently, the potential gains of trying to spoil using
  441. // these orders are small compared to the complexity of the
  442. // code required.
  443. //
  444. //
  445. fOrderFlags |= OF_BLOCKER;
  446. //
  447. // If the blt is screen to screen and the source overlaps the
  448. // destination and the clipping is not simple (> 1 rect) then
  449. // we do not want to send this as an order.
  450. //
  451. // (This is because we would need some complex code to
  452. // calculate the order in which to blt through each of the clip
  453. // rects. As this case is pretty rare, it seems reasonable to
  454. // just send it as Screen Data).
  455. //
  456. if (!OEClippingIsSimple(pco))
  457. {
  458. //
  459. // Calculate the overlapping rectangle.
  460. //
  461. intersectRect.left = max(pScrBlt->nLeftRect, pScrBlt->nXSrc);
  462. intersectRect.right = min(
  463. pScrBlt->nLeftRect + pScrBlt->nWidth-1,
  464. pScrBlt->nXSrc + pScrBlt->nWidth-1 );
  465. intersectRect.top = max(pScrBlt->nTopRect, pScrBlt->nYSrc);
  466. intersectRect.bottom = min(
  467. pScrBlt->nTopRect + pScrBlt->nHeight-1,
  468. pScrBlt->nYSrc + pScrBlt->nHeight-1 );
  469. //
  470. // Check for a src / dst overlap. If they overlap, the
  471. // intersection is a well-ordered non-trivial rectangle.
  472. //
  473. if ( (intersectRect.left <= intersectRect.right ) &&
  474. (intersectRect.top <= intersectRect.bottom) )
  475. {
  476. //
  477. // The src & dest overlap. Free up the order memory
  478. // and skip out now. The destination rectangle will be
  479. // added to the Screen Data Area.
  480. //
  481. OA_DDFreeOrderMem(pOrder);
  482. DC_QUIT;
  483. }
  484. }
  485. TRACE_OUT(( "ScrBlt x %d y %d w %d h %d sx %d sy %d rop %02X",
  486. pScrBlt->nLeftRect,
  487. pScrBlt->nTopRect,
  488. pScrBlt->nWidth,
  489. pScrBlt->nHeight,
  490. pScrBlt->nXSrc,
  491. pScrBlt->nYSrc,
  492. pScrBlt->bRop));
  493. break;
  494. case ORD_MEMBLT:
  495. //
  496. // Allocate the memory for the order - don't use OA as we are
  497. // only going to tile this order immediately. Instead, we have
  498. // a static buffer to receive the template order data.
  499. //
  500. pOrder = (LPINT_ORDER)g_oeTmpOrderBuffer;
  501. pMemBlt = (LPMEMBLT_ORDER)pOrder->abOrderData;
  502. pOrder->OrderHeader.Common.cbOrderDataLength
  503. = sizeof(MEMBLT_R2_ORDER);
  504. //
  505. // Store the order type.
  506. //
  507. pMemBlt->type = LOWORD(orderType);
  508. //
  509. // Any data which is sent over the wire must be in virtual
  510. // desktop co-ordinates. The bounding rectangle has already
  511. // been converted by OELRtoScreen.
  512. //
  513. pMemBlt->nLeftRect = bounds.left;
  514. pMemBlt->nTopRect = bounds.top;
  515. pMemBlt->nWidth = bounds.right - bounds.left + 1;
  516. pMemBlt->nHeight = bounds.bottom - bounds.top + 1;
  517. pMemBlt->bRop = rop3;
  518. //
  519. // We need to store the source bitmap origin. This is a memory
  520. // object, so screen/virtual conversions are unnecessary.
  521. //
  522. pMemBlt->nXSrc = pptlSrc->x;
  523. pMemBlt->nYSrc = pptlSrc->y;
  524. //
  525. // Mark the order as opaque if necessary.
  526. //
  527. if (ROP3_IS_OPAQUE(rop3))
  528. {
  529. fOrderFlags |= OF_SPOILER;
  530. }
  531. //
  532. // Store the src bitmap handle in the order.
  533. //
  534. pMemBlt->cacheId = 0;
  535. TRACE_OUT(( "MemBlt dx %d dy %d w %d h %d sx %d sy %d rop %04X",
  536. pMemBlt->nLeftRect,
  537. pMemBlt->nTopRect,
  538. pMemBlt->nWidth,
  539. pMemBlt->nHeight,
  540. pMemBlt->nXSrc,
  541. pMemBlt->nYSrc,
  542. pMemBlt->bRop));
  543. break;
  544. case ORD_MEM3BLT:
  545. //
  546. // Check that the brush pattern is simple.
  547. //
  548. if (!OECheckBrushIsSimple(ppdev, pbo, &pCurrentBrush))
  549. {
  550. TRACE_OUT(( "Brush is not simple"));
  551. orderType = 0;
  552. DC_QUIT;
  553. }
  554. //
  555. // Allocate the memory for the order - don't use OA as we are
  556. // only going to tile this order immediately. Instead, we have
  557. // a static buffer to receive the template order data.
  558. //
  559. pOrder = (LPINT_ORDER)g_oeTmpOrderBuffer;
  560. pMem3Blt = (LPMEM3BLT_ORDER)pOrder->abOrderData;
  561. pOrder->OrderHeader.Common.cbOrderDataLength
  562. = sizeof(MEM3BLT_R2_ORDER);
  563. //
  564. // Store the order type.
  565. //
  566. pMem3Blt->type = LOWORD(orderType);
  567. //
  568. // All data which is sent over the wire must be in virtual
  569. // desktop co-ordinates. OELRtoVirtual has already done this
  570. // conversion for us.
  571. //
  572. pMem3Blt->nLeftRect = bounds.left;
  573. pMem3Blt->nTopRect = bounds.top;
  574. pMem3Blt->nWidth = bounds.right - bounds.left + 1;
  575. pMem3Blt->nHeight = bounds.bottom - bounds.top + 1;
  576. pMem3Blt->bRop = rop3;
  577. //
  578. // We need to store the source bitmap origin. This is a memory
  579. // object, so screen/virtual conversions are unnecessary.
  580. //
  581. pMem3Blt->nXSrc = pptlSrc->x;
  582. pMem3Blt->nYSrc = pptlSrc->y;
  583. //
  584. // Mark the order as opaque if necessary.
  585. //
  586. if (ROP3_IS_OPAQUE(rop3))
  587. {
  588. fOrderFlags |= OF_SPOILER;
  589. }
  590. //
  591. // Store the src bitmap handle in the order.
  592. //
  593. pMem3Blt->cacheId = 0;
  594. //
  595. // Set up the information required for the pattern.
  596. //
  597. pMem3Blt->BackColor = pCurrentBrush->back;
  598. pMem3Blt->ForeColor = pCurrentBrush->fore;
  599. //
  600. // The protocol brush origin is the point on the screen where
  601. // we want the brush to start being drawn from (tiling where
  602. // necessary). This must be in virtual coordinates.
  603. //
  604. pMem3Blt->BrushOrgX = pptlBrush->x;
  605. pMem3Blt->BrushOrgY = pptlBrush->y;
  606. OELPtoVirtual((LPPOINT)&pMem3Blt->BrushOrgX, 1);
  607. //
  608. // Extra brush data from the data when we realised the brush.
  609. //
  610. pMem3Blt->BrushStyle = pCurrentBrush->style;
  611. pMem3Blt->BrushHatch = pCurrentBrush->style;
  612. RtlCopyMemory(pMem3Blt->BrushExtra,
  613. pCurrentBrush->brushData,
  614. sizeof(pMem3Blt->BrushExtra));
  615. TRACE_OUT(( "Mem3Blt brush %02X %02X dx %d dy %d w %d h %d "
  616. "sx %d sy %d rop %04X",
  617. pMem3Blt->BrushStyle,
  618. pMem3Blt->BrushHatch,
  619. pMem3Blt->nLeftRect,
  620. pMem3Blt->nTopRect,
  621. pMem3Blt->nWidth,
  622. pMem3Blt->nHeight,
  623. pMem3Blt->nXSrc,
  624. pMem3Blt->nYSrc,
  625. pMem3Blt->bRop));
  626. break;
  627. default:
  628. ERROR_OUT(( "New unsupported order %08lx", orderType));
  629. orderType = 0;
  630. break;
  631. }
  632. //
  633. // We have generated an order so make sure we send it.
  634. //
  635. if (orderType != 0)
  636. {
  637. fSendOrder = TRUE;
  638. }
  639. DC_EXIT_POINT:
  640. //
  641. // If we did not send an order, we must accumulate the output in the
  642. // Screen Data Area.
  643. //
  644. if (fSendOrder)
  645. {
  646. //
  647. // Check if the ROP has a dependency on the destination.
  648. //
  649. if (!ROP3_NO_TARGET(rop3))
  650. {
  651. TRACE_OUT(( "ROP has a target dependency"));
  652. fOrderFlags |= OF_DESTROP;
  653. }
  654. //
  655. // Store the general order data. The bounding rectagle
  656. // co-ordinates must be virtual desktop. OELRtoVirtual has already
  657. // converted rect for us.
  658. //
  659. pOrder->OrderHeader.Common.fOrderFlags = (TSHR_UINT16)fOrderFlags;
  660. TSHR_RECT16_FROM_RECT(&pOrder->OrderHeader.Common.rcsDst, bounds);
  661. //
  662. // Add the order to the cache. Note that we have the new tiled
  663. // processing for MEMBLT and MEM3BLT orders.
  664. //
  665. if ((orderType == ORD_MEMBLT) || (orderType == ORD_MEM3BLT))
  666. {
  667. OETileBitBltOrder(pOrder, &memBltExtraInfo, pco);
  668. }
  669. else
  670. {
  671. OEClipAndAddOrder(pOrder, NULL, pco);
  672. }
  673. }
  674. else
  675. {
  676. if (fAccumulate)
  677. {
  678. OEClipAndAddScreenData(&bounds, pco);
  679. }
  680. }
  681. OE_SHM_STOP_WRITING;
  682. NO_LOCK_EXIT:
  683. DebugExitDWORD(DrvBitBlt, rc);
  684. return(rc);
  685. }
  686. //
  687. // DrvStretchBlt - see NT DDK documentation.
  688. //
  689. BOOL DrvStretchBlt(SURFOBJ *psoDst,
  690. SURFOBJ *psoSrc,
  691. SURFOBJ *psoMask,
  692. CLIPOBJ *pco,
  693. XLATEOBJ *pxlo,
  694. COLORADJUSTMENT *pca,
  695. POINTL *pptlHTOrg,
  696. RECTL *prclDst,
  697. RECTL *prclSrc,
  698. POINTL *pptlMask,
  699. ULONG iMode)
  700. {
  701. BOOL rc = TRUE;
  702. RECT rectSrc;
  703. RECT rectDst;
  704. BOOL fAccumulate = FALSE;
  705. POINTL ptlSrc;
  706. BOOL usedBitBlt = FALSE;
  707. DebugEntry(DrvStretchBlt);
  708. //
  709. // DO THIS _BEFORE_ TAKING LOCK
  710. //
  711. if (!g_oeViewers)
  712. goto NO_LOCK_EXIT;
  713. OE_SHM_START_WRITING;
  714. //
  715. // Get the source and destination rectangles
  716. //
  717. RECT_FROM_RECTL(rectSrc, (*prclSrc));
  718. RECT_FROM_RECTL(rectDst, (*prclDst));
  719. //
  720. // Check if we are accumulating data for this function
  721. //
  722. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  723. if (!fAccumulate)
  724. {
  725. DC_QUIT;
  726. }
  727. //
  728. // Check that we have a valid ROP code. The NT DDK states that the ROP
  729. // code for the StretchBlt is implicit in the mask specification. If a
  730. // mask is specified, we have an implicit ROP4 of 0xCCAA, otherwise the
  731. // code is 0xCCCC.
  732. //
  733. // Our BitBlt code only encodes orders for ROP3s, so we must throw any
  734. // StretchBlts with a mask.
  735. //
  736. if (psoMask != NULL)
  737. {
  738. TRACE_OUT(( "Mask specified"));
  739. DC_QUIT;
  740. }
  741. //
  742. // Check for overcomplicated clipping.
  743. //
  744. if (OEClippingIsComplex(pco))
  745. {
  746. TRACE_OUT(( "Clipping is too complex"));
  747. DC_QUIT;
  748. }
  749. //
  750. // Rectangles are now well-ordered, check if we have a degenerate (ie.
  751. // no stretch) case.
  752. //
  753. if ( (rectSrc.right - rectSrc.left == rectDst.right - rectDst.left) &&
  754. (rectSrc.bottom - rectSrc.top == rectDst.bottom - rectDst.top ) )
  755. {
  756. //
  757. // This can be passed on to the BitBlt code.
  758. //
  759. usedBitBlt = TRUE;
  760. ptlSrc.x = prclSrc->left;
  761. ptlSrc.y = prclSrc->top;
  762. rc = DrvBitBlt(psoDst,
  763. psoSrc,
  764. psoMask,
  765. pco,
  766. pxlo,
  767. prclDst,
  768. &ptlSrc,
  769. pptlMask,
  770. NULL,
  771. NULL,
  772. 0xCCCC);
  773. //
  774. // We have stored this object in the BitBlt, so don't store the
  775. // data again.
  776. //
  777. fAccumulate = FALSE;
  778. }
  779. DC_EXIT_POINT:
  780. if (fAccumulate)
  781. {
  782. //
  783. // Convert the data to virtual coordinates.
  784. //
  785. OELRtoVirtual(&rectDst, 1);
  786. //
  787. // Update the screen data area
  788. //
  789. OEClipAndAddScreenData(&rectDst, pco);
  790. }
  791. OE_SHM_STOP_WRITING;
  792. NO_LOCK_EXIT:
  793. DebugExitDWORD(DrvStretchBlt, rc);
  794. return(rc);
  795. }
  796. //
  797. // DrvCopyBits - see NT DDK documentation.
  798. //
  799. BOOL DrvCopyBits(SURFOBJ *psoDst,
  800. SURFOBJ *psoSrc,
  801. CLIPOBJ *pco,
  802. XLATEOBJ *pxlo,
  803. RECTL *prclDst,
  804. POINTL *pptlSrc)
  805. {
  806. //
  807. // CopyBits is a fast path for the NT display drivers. In our case it
  808. // can always be processed as a BITBLT.
  809. //
  810. return(DrvBitBlt( psoDst,
  811. psoSrc,
  812. NULL,
  813. pco,
  814. pxlo,
  815. prclDst,
  816. pptlSrc,
  817. NULL,
  818. NULL,
  819. NULL,
  820. 0xCCCC));
  821. }
  822. //
  823. // DrvTextOut - see NT DDK documentation.
  824. //
  825. BOOL DrvTextOut(SURFOBJ *pso,
  826. STROBJ *pstro,
  827. FONTOBJ *pfo,
  828. CLIPOBJ *pco,
  829. RECTL *prclExtra,
  830. RECTL *prclOpaque,
  831. BRUSHOBJ *pboFore,
  832. BRUSHOBJ *pboOpaque,
  833. POINTL *pptlOrg,
  834. MIX mix)
  835. {
  836. LPOSI_PDEV ppdev = (LPOSI_PDEV)pso->dhpdev;
  837. BOOL rc = TRUE;
  838. RECT rectDst;
  839. RECT rectText;
  840. LPINT_ORDER pOrder;
  841. LPINT_ORDER pOpaqueOrder;
  842. LPTEXTOUT_ORDER pTextOut;
  843. LPEXTTEXTOUT_ORDER pExtTextOut;
  844. BOOL fSendOrder = FALSE;
  845. BOOL fAccumulate = FALSE;
  846. char ansiString[ORD_MAX_STRING_LEN_WITHOUT_DELTAS+2];
  847. ULONG ansiLen;
  848. ULONG tempLen;
  849. UINT orderType = 0;
  850. ULONG maxLength;
  851. LPSTR lpVariable;
  852. BOOL fMoreData;
  853. ULONG count;
  854. ULONG i;
  855. GLYPHPOS* pGlyphData;
  856. int currentDelta;
  857. LPVARIABLE_DELTAX lpDeltaPos;
  858. UINT fontFlags;
  859. UINT fontAscender;
  860. UINT fontHeight;
  861. UINT fontWidth;
  862. UINT fontWeight;
  863. UINT fontIndex;
  864. POINTL lastPtl;
  865. LPCOMMON_TEXTORDER pCommon;
  866. POINT startPoint;
  867. BOOL sendDeltaX = FALSE;
  868. DebugEntry(DrvTextOut);
  869. //
  870. // DO THIS _BEFORE_ TAKING LOCKS
  871. //
  872. if (!g_oeViewers)
  873. goto NO_LOCK_EXIT;
  874. OE_SHM_START_WRITING;
  875. //
  876. // Get bounding rectangle and convert to a RECT.
  877. //
  878. if (prclOpaque != NULL)
  879. {
  880. RECT_FROM_RECTL(rectDst, (*prclOpaque));
  881. }
  882. else
  883. {
  884. RECT_FROM_RECTL(rectDst, pstro->rclBkGround);
  885. TRACE_OUT(( "Using STROBJ bgd for size"));
  886. }
  887. //
  888. // Check if we are accumulating data for this function
  889. //
  890. fAccumulate = OEAccumulateOutput(pso, pco, &rectDst);
  891. if (!fAccumulate)
  892. {
  893. DC_QUIT;
  894. }
  895. //
  896. // Convert to virtual coordinates
  897. //
  898. OELRtoVirtual(&rectDst, 1);
  899. //
  900. // Determine which order we will generate
  901. //
  902. if ( ((pstro->flAccel & SO_FLAG_DEFAULT_PLACEMENT) != 0) &&
  903. (prclOpaque == NULL) )
  904. {
  905. orderType = ORD_TEXTOUT;
  906. maxLength = ORD_MAX_STRING_LEN_WITHOUT_DELTAS;
  907. }
  908. else
  909. {
  910. orderType = ORD_EXTTEXTOUT;
  911. maxLength = ORD_MAX_STRING_LEN_WITH_DELTAS;
  912. }
  913. //
  914. // Check if we are allowed to send this order (determined by the
  915. // negotiated capabilities of all the machines in the conference).
  916. //
  917. if (!OE_SendAsOrder(orderType))
  918. {
  919. TRACE_OUT(( "Text order %x not allowed", orderType));
  920. DC_QUIT;
  921. }
  922. //
  923. // Check for a valid brush for the test operation.
  924. //
  925. if (pboFore->iSolidColor == -1)
  926. {
  927. TRACE_OUT(( "Bad brush for text fg"));
  928. DC_QUIT;
  929. }
  930. if (pboOpaque->iSolidColor == -1)
  931. {
  932. TRACE_OUT(( "Bad brush for text bg"));
  933. DC_QUIT;
  934. }
  935. //
  936. // Check that we don't have any modifiers rects on the font
  937. //
  938. if (prclExtra != NULL)
  939. {
  940. TRACE_OUT(( "Unsupported extra rects"));
  941. DC_QUIT;
  942. }
  943. //
  944. // Check that text orientation is OK.
  945. //
  946. if (pstro->flAccel & OE_BAD_TEXT_MASK)
  947. {
  948. TRACE_OUT(("DrvTextOut - unsupported flAccel 0x%08x", pstro->flAccel));
  949. DC_QUIT;
  950. }
  951. //
  952. // Check we have a valid string.
  953. //
  954. if (pstro->pwszOrg == NULL)
  955. {
  956. TRACE_OUT(( "No string - opaque %x", prclOpaque));
  957. DC_QUIT;
  958. }
  959. //
  960. // Check for overcomplicated clipping.
  961. //
  962. if (OEClippingIsComplex(pco))
  963. {
  964. TRACE_OUT(( "Clipping is too complex"));
  965. DC_QUIT;
  966. }
  967. //
  968. // Convert the string to an ANSI representation.
  969. //
  970. RtlFillMemory(ansiString, sizeof(ansiString), 0);
  971. EngUnicodeToMultiByteN(ansiString,
  972. maxLength,
  973. &ansiLen,
  974. pstro->pwszOrg,
  975. pstro->cGlyphs * sizeof(WCHAR));
  976. //
  977. // The conversion claims it never fails, but we have seen results that
  978. // are completely different on the remote box. So we convert the ANSI
  979. // string back to UNICODE and check that we still have what we started
  980. // with.
  981. //
  982. EngMultiByteToUnicodeN(g_oeTempString,
  983. sizeof(g_oeTempString),
  984. &tempLen,
  985. ansiString,
  986. ansiLen);
  987. //
  988. // Check we don't have too much data, or that the translation failed to
  989. // give the correct data. This happens when we try to translate
  990. // UNICODE text.
  991. //
  992. if ( (tempLen != pstro->cGlyphs * sizeof(WCHAR)) ||
  993. (memcmp(pstro->pwszOrg, g_oeTempString, tempLen) != 0) )
  994. {
  995. TRACE_OUT(( "String not translated"));
  996. DC_QUIT;
  997. }
  998. //
  999. // Check that the font is valid.
  1000. //
  1001. if (!OECheckFontIsSupported(pfo, ansiString, ansiLen,
  1002. &fontHeight,
  1003. &fontAscender,
  1004. &fontWidth,
  1005. &fontWeight,
  1006. &fontFlags,
  1007. &fontIndex,
  1008. &sendDeltaX))
  1009. {
  1010. TRACE_OUT(( "Unsupported font for '%s'", ansiString));
  1011. //
  1012. // Check if there is an opaque rectangle. If so it is worth
  1013. // splitting this out. Word can output an entire line comprising a
  1014. // single character followed by background, eg bullets, where the
  1015. // line is blanked by drawing the bullet character at the start of
  1016. // the line followed by a large - >1000 pixel - opaque rect.
  1017. // Splitting the opaque rect from the text means we can send a
  1018. // small area of SD for the unmatched font char while encoding the
  1019. // large opaque rectangle.
  1020. //
  1021. if ( (prclOpaque != NULL) &&
  1022. (pstro->cGlyphs == 1) &&
  1023. (pstro->flAccel & SO_HORIZONTAL) &&
  1024. OE_SendAsOrder(ORD_PATBLT))
  1025. {
  1026. //
  1027. // There is an opaque rectangle and a single char.
  1028. // Encode the opaque rectangle. First get a copy of the target
  1029. // rect so we can use it later (and flip it into screen
  1030. // coordinates).
  1031. //
  1032. TRACE_OUT(( "Have 1 char + opaque rect"));
  1033. rectText.left = rectDst.left;
  1034. rectText.top = rectDst.top;
  1035. rectText.right = rectDst.right + 1;
  1036. rectText.bottom = rectDst.bottom + 1;
  1037. //
  1038. // Call into the PATBLT encoding function.
  1039. //
  1040. if ( !OEEncodePatBlt(ppdev,
  1041. pboOpaque,
  1042. pptlOrg,
  1043. OE_COPYPEN_ROP,
  1044. &rectDst,
  1045. &pOpaqueOrder) )
  1046. {
  1047. //
  1048. // Something went wrong with the encoding, so skip to the
  1049. // end to add this operation to the SDA.
  1050. //
  1051. TRACE_OUT(( "Failed to encode opaque rect"));
  1052. DC_QUIT;
  1053. }
  1054. //
  1055. // Store the general order data. The bounding rectagle
  1056. // co-ordinates must be virtual desktop. OELRtoVirtual has
  1057. // already converted rect for us.
  1058. //
  1059. TSHR_RECT16_FROM_RECT(&pOpaqueOrder->OrderHeader.Common.rcsDst, rectDst);
  1060. //
  1061. // Add the order to the cache.
  1062. //
  1063. OEClipAndAddOrder(pOpaqueOrder, NULL, pco);
  1064. //
  1065. // Calculate the bounds of the text. Get the glyph positions
  1066. // for the left and right, and assume the top and bottom equate
  1067. // approximately to the opaque rectangle.
  1068. //
  1069. if ( pstro->pgp == NULL)
  1070. {
  1071. //
  1072. // The string object doesn't contain the GLYPHPOS info, so
  1073. // enumerate the glyphs.
  1074. //
  1075. TRACE_OUT(( "Enumerate glyphs"));
  1076. STROBJ_vEnumStart(pstro);
  1077. STROBJ_bEnum(pstro, &count, &pGlyphData);
  1078. }
  1079. else
  1080. {
  1081. //
  1082. // The string object already contains the GLYPHPOS info, so
  1083. // just grab the pointer to it.
  1084. //
  1085. pGlyphData = pstro->pgp;
  1086. }
  1087. rectDst = rectText;
  1088. rectDst.left = max(rectDst.left, pGlyphData[0].ptl.x);
  1089. if ( pstro->ulCharInc == 0 )
  1090. {
  1091. //
  1092. // No character increment for this string object. Just use
  1093. // the maximum glyph width to calculate the right bounding
  1094. // edge.
  1095. //
  1096. TRACE_OUT(( "no charinc glyph %d trg %d left %d maxX %d",
  1097. pGlyphData[0].ptl.x,
  1098. rectDst.right,
  1099. rectDst.left,
  1100. pfo->cxMax));
  1101. rectDst.right = min(rectDst.right, (int)(pGlyphData[0].ptl.x +
  1102. pfo->cxMax - 1));
  1103. }
  1104. else
  1105. {
  1106. //
  1107. // The string object has a character increment, so use it
  1108. // to determine the right bounding edge.
  1109. //
  1110. TRACE_OUT(( "charinc %x glyph %d trg %d left %d",
  1111. pstro->ulCharInc,
  1112. pGlyphData[0].ptl.x,
  1113. rectDst.right,
  1114. rectDst.left));
  1115. rectDst.right = min(rectDst.right, (int)(pGlyphData[0].ptl.x +
  1116. pstro->ulCharInc - 1));
  1117. }
  1118. //
  1119. // Flip the target rectangle back to virtual coordinates.
  1120. //
  1121. rectDst.right -= 1;
  1122. rectDst.bottom -= 1;
  1123. }
  1124. //
  1125. // Skip to the end to add to the SDA.
  1126. //
  1127. DC_QUIT;
  1128. }
  1129. //
  1130. // It is possible that the font matching blows our previous decision to
  1131. // generate a TextOut order and we need to generate an ExtTextOut order
  1132. // instead. We need to reverify our parameters if this is the case.
  1133. //
  1134. if ((sendDeltaX) && (orderType != ORD_EXTTEXTOUT))
  1135. {
  1136. TRACE_OUT(( "Text order must be EXTTEXTOUT"));
  1137. //
  1138. // Set up for ExtTexOut orders.
  1139. //
  1140. orderType = ORD_EXTTEXTOUT;
  1141. maxLength = ORD_MAX_STRING_LEN_WITH_DELTAS;
  1142. //
  1143. // Check if we are allowed to send this order (determined by the
  1144. // negotiated capabilities of all the machines in the conference).
  1145. //
  1146. if (!OE_SendAsOrder(orderType))
  1147. {
  1148. TRACE_OUT(( "Text order %x not allowed", orderType));
  1149. DC_QUIT;
  1150. }
  1151. //
  1152. // Make sure we haven't blown the order size.
  1153. //
  1154. if (pstro->cGlyphs > maxLength)
  1155. {
  1156. TRACE_OUT(( "Text limit blown", pstro->cGlyphs));
  1157. DC_QUIT;
  1158. }
  1159. }
  1160. //
  1161. // Get the proper start position for the text.
  1162. //
  1163. if ( pstro->pgp == NULL)
  1164. {
  1165. STROBJ_vEnumStart(pstro);
  1166. STROBJ_bEnum(pstro, &count, &pGlyphData);
  1167. if (count == 0)
  1168. {
  1169. WARNING_OUT(( "No glyphs"));
  1170. DC_QUIT;
  1171. }
  1172. }
  1173. else
  1174. {
  1175. pGlyphData = pstro->pgp;
  1176. }
  1177. startPoint.x = pGlyphData[0].ptl.x;
  1178. //
  1179. // Check if we should be using baseline alignment for the y
  1180. // coordinate. If we should be, the value in the glyph data is
  1181. // correct. If not, we the y coordinate is for the top of the
  1182. // text, and we have to calculate it.
  1183. //
  1184. if (g_oeBaselineTextEnabled)
  1185. {
  1186. startPoint.y = pGlyphData[0].ptl.y;
  1187. fontFlags |= NF_BASELINE;
  1188. }
  1189. else
  1190. {
  1191. startPoint.y = pGlyphData[0].ptl.y - fontAscender;
  1192. }
  1193. //
  1194. // Allocate memory for the order
  1195. //
  1196. switch (orderType)
  1197. {
  1198. case ORD_TEXTOUT:
  1199. {
  1200. //
  1201. // Allocate the memory
  1202. //
  1203. pOrder = OA_DDAllocOrderMem((UINT)( sizeof(TEXTOUT_ORDER)
  1204. - ORD_MAX_STRING_LEN_WITHOUT_DELTAS
  1205. + ansiLen ),
  1206. 0);
  1207. if (pOrder == NULL)
  1208. {
  1209. TRACE_OUT(( "Failed to alloc order"));
  1210. DC_QUIT;
  1211. }
  1212. pTextOut = (LPTEXTOUT_ORDER)pOrder->abOrderData;
  1213. //
  1214. // Set up the order type.
  1215. //
  1216. pTextOut->type = ORD_TEXTOUT_TYPE;
  1217. //
  1218. // Get a pointer to the fields which are common to both TextOut
  1219. // and ExtTextOut
  1220. //
  1221. pCommon = &pTextOut->common;
  1222. }
  1223. break;
  1224. case ORD_EXTTEXTOUT:
  1225. {
  1226. //
  1227. // BOGUS LAURABU
  1228. // This allocates space for a deltax array whether or not one is needed
  1229. //
  1230. //
  1231. // Allocate the memory
  1232. //
  1233. pOrder = OA_DDAllocOrderMem((UINT)( sizeof(EXTTEXTOUT_ORDER)
  1234. - ORD_MAX_STRING_LEN_WITHOUT_DELTAS
  1235. - (ORD_MAX_STRING_LEN_WITH_DELTAS
  1236. * sizeof(TSHR_INT32))
  1237. + ansiLen * (sizeof(TSHR_INT32) + 1)
  1238. + 4), // Allow for internal padding
  1239. 0);
  1240. if (pOrder == NULL)
  1241. {
  1242. TRACE_OUT(( "Failed to alloc order"));
  1243. DC_QUIT;
  1244. }
  1245. pExtTextOut = (LPEXTTEXTOUT_ORDER)pOrder->abOrderData;
  1246. //
  1247. // Set up the order type.
  1248. //
  1249. pExtTextOut->type = ORD_EXTTEXTOUT_TYPE;
  1250. //
  1251. // Get a pointer to the fields which are common to both TextOut
  1252. // and ExtTextOut
  1253. //
  1254. pCommon = &pExtTextOut->common;
  1255. }
  1256. break;
  1257. default:
  1258. {
  1259. ERROR_OUT(( "Unknown order %x", orderType));
  1260. DC_QUIT;
  1261. }
  1262. break;
  1263. }
  1264. //
  1265. // Fill in the fields which are common to both TextOut and ExtTextOut
  1266. //
  1267. // Convert to virtual coordinates
  1268. //
  1269. OELPtoVirtual(&startPoint, 1);
  1270. //
  1271. // The x and y values are available in virtual coords from the bounds
  1272. // rectangle.
  1273. //
  1274. pCommon->nXStart = startPoint.x;
  1275. pCommon->nYStart = startPoint.y;
  1276. //
  1277. // Get the text colours.
  1278. //
  1279. OEConvertColor(ppdev,
  1280. &pCommon->BackColor,
  1281. pboOpaque->iSolidColor,
  1282. NULL);
  1283. OEConvertColor(ppdev,
  1284. &pCommon->ForeColor,
  1285. pboFore->iSolidColor,
  1286. NULL);
  1287. //
  1288. // The transparency of the operation is determined by whether we have
  1289. // an opaque rectangle or not.
  1290. //
  1291. pCommon->BackMode = (prclOpaque == NULL) ? TRANSPARENT : OPAQUE;
  1292. //
  1293. // NT has a character extra spacing, not a generic for every character
  1294. // spacing. So, we always set this value to 0.
  1295. //
  1296. pCommon->CharExtra = 0;
  1297. //
  1298. // NT does not provide a break of any sorts.
  1299. //
  1300. pCommon->BreakExtra = 0;
  1301. pCommon->BreakCount = 0;
  1302. //
  1303. // Copy the font details
  1304. //
  1305. pCommon->FontHeight = fontHeight;
  1306. pCommon->FontWidth = fontWidth;
  1307. pCommon->FontWeight = fontWeight;
  1308. pCommon->FontFlags = fontFlags;
  1309. pCommon->FontIndex = fontIndex;
  1310. //
  1311. // Now fill in the order specific data
  1312. //
  1313. switch (orderType)
  1314. {
  1315. case ORD_TEXTOUT:
  1316. //
  1317. // Copy across the text string.
  1318. //
  1319. pTextOut->variableString.len = (BYTE)ansiLen;
  1320. RtlCopyMemory(pTextOut->variableString.string,
  1321. ansiString,
  1322. ansiLen);
  1323. //
  1324. // Make sure we send the order
  1325. //
  1326. fSendOrder = TRUE;
  1327. TRACE_OUT(( "TEXTOUT: X %u Y %u bm %u FC %02X%02X%02X "
  1328. "BC %02X%02X%02X",
  1329. pTextOut->common.nXStart,
  1330. pTextOut->common.nYStart,
  1331. pTextOut->common.BackMode,
  1332. pTextOut->common.ForeColor.red,
  1333. pTextOut->common.ForeColor.green,
  1334. pTextOut->common.ForeColor.blue,
  1335. pTextOut->common.BackColor.red,
  1336. pTextOut->common.BackColor.green,
  1337. pTextOut->common.BackColor.blue));
  1338. TRACE_OUT(( "Font: fx %u fy %u fw %u ff %04x fh %u len %u",
  1339. pTextOut->common.FontWidth,
  1340. pTextOut->common.FontHeight,
  1341. pTextOut->common.FontWeight,
  1342. pTextOut->common.FontFlags,
  1343. pTextOut->common.FontIndex,
  1344. ansiLen));
  1345. TRACE_OUT(( "String '%s'", ansiString));
  1346. break;
  1347. case ORD_EXTTEXTOUT:
  1348. //
  1349. // Since our text is only ever fully contained within the
  1350. // opaque rectangle, we only set the opaque flag (and ignore
  1351. // the clipping).
  1352. //
  1353. pExtTextOut->fuOptions = (prclOpaque == NULL) ? 0 : ETO_OPAQUE;
  1354. //
  1355. // Set up the bounding rectangle for the operation.
  1356. // EXT_TEXT_OUT orders use TSHR_RECT32s, hence we can't directly
  1357. // assign rectDst to it.
  1358. //
  1359. pExtTextOut->rectangle.left = rectDst.left;
  1360. pExtTextOut->rectangle.top = rectDst.top;
  1361. pExtTextOut->rectangle.right = rectDst.right;
  1362. pExtTextOut->rectangle.bottom = rectDst.bottom;
  1363. //
  1364. // Copy across the text string.
  1365. //
  1366. pExtTextOut->variableString.len = ansiLen;
  1367. RtlCopyMemory(pExtTextOut->variableString.string,
  1368. ansiString,
  1369. ansiLen);
  1370. //
  1371. // WHOOP WHOOP WHOOP - Prepare to shut your eyes...
  1372. //
  1373. // Although we have a defined fixed length structure for
  1374. // storing ExtTextOut orders, we must not send the full
  1375. // structure over the network as the text will only be, say, 10
  1376. // characters while the structure contains room for 127.
  1377. //
  1378. // Hence we pack the structure now to remove all the blank data
  1379. // BUT we must maintain the natural alignment of the variables.
  1380. //
  1381. // So we know the length of the string which we can use to
  1382. // start the new delta structure at the next 4-byte boundary.
  1383. //
  1384. lpVariable = ((LPBYTE)(&pExtTextOut->variableString))
  1385. + ansiLen
  1386. + sizeof(pExtTextOut->variableString.len);
  1387. lpVariable = (LPSTR)
  1388. DC_ROUND_UP_4((UINT_PTR)lpVariable);
  1389. lpDeltaPos = (LPVARIABLE_DELTAX)lpVariable;
  1390. //
  1391. // Do we need a delta array, or are the chars at their default
  1392. // positions.
  1393. //
  1394. if ( sendDeltaX ||
  1395. ((pstro->flAccel & SO_FLAG_DEFAULT_PLACEMENT) == 0) )
  1396. {
  1397. //
  1398. // Store the length of the position deltas.
  1399. //
  1400. lpDeltaPos->len = ansiLen * sizeof(TSHR_INT32);
  1401. //
  1402. // Set up the position deltas.
  1403. //
  1404. STROBJ_vEnumStart(pstro);
  1405. fMoreData = TRUE;
  1406. currentDelta = 0;
  1407. while (fMoreData)
  1408. {
  1409. //
  1410. // Get the next set of glyph data
  1411. //
  1412. fMoreData = STROBJ_bEnum(pstro, &count, &pGlyphData);
  1413. for (i = 0; i < count; i++)
  1414. {
  1415. //
  1416. // The first time through we must set up the first
  1417. // glyph position.
  1418. //
  1419. if ((currentDelta == 0) && (i == 0))
  1420. {
  1421. lastPtl.x = pGlyphData[0].ptl.x;
  1422. lastPtl.y = pGlyphData[0].ptl.y;
  1423. TRACE_OUT(( "First Pos %d", lastPtl.x));
  1424. }
  1425. else
  1426. {
  1427. //
  1428. // For subsequent entries, we need to add the
  1429. // delta on the X position to the array.
  1430. //
  1431. if (pstro->ulCharInc == 0)
  1432. {
  1433. lpDeltaPos->deltaX[currentDelta]
  1434. = pGlyphData[i].ptl.x
  1435. - lastPtl.x;
  1436. //
  1437. // Check for delta Y's - which we can't
  1438. // encode
  1439. //
  1440. if (pGlyphData[i].ptl.y - lastPtl.y)
  1441. {
  1442. WARNING_OUT(( "New Y %d",
  1443. pGlyphData[i].ptl.y));
  1444. OA_DDFreeOrderMem(pOrder);
  1445. DC_QUIT;
  1446. }
  1447. //
  1448. // Store the last position for the next
  1449. // time round.
  1450. //
  1451. lastPtl.x = pGlyphData[i].ptl.x;
  1452. lastPtl.y = pGlyphData[i].ptl.y;
  1453. TRACE_OUT(( "Next Pos %d %d", i, lastPtl.x));
  1454. }
  1455. else
  1456. {
  1457. lpDeltaPos->deltaX[currentDelta]
  1458. = pstro->ulCharInc;
  1459. }
  1460. currentDelta++;
  1461. }
  1462. }
  1463. }
  1464. //
  1465. // For the last entry, we need to set up the data by hand
  1466. // (there are only n-1 deltas for n chars)
  1467. //
  1468. // This is done for compatibility with Windows 95 which
  1469. // requires the last delta to be the delta to the place
  1470. // where the next char would be if there were n+1 chars in
  1471. // the string.
  1472. //
  1473. if (pstro->ulCharInc == 0)
  1474. {
  1475. //
  1476. // No characters left - fudge a value of the width of
  1477. // the last character.
  1478. //
  1479. lpDeltaPos->deltaX[currentDelta] =
  1480. pGlyphData[count-1].pgdf->pgb->sizlBitmap.cx;
  1481. }
  1482. else
  1483. {
  1484. //
  1485. // All chars are evenly spaced, so just stick the value
  1486. // in.
  1487. //
  1488. lpDeltaPos->deltaX[currentDelta] = pstro->ulCharInc;
  1489. }
  1490. //
  1491. // WHOOP WHOOP WHOOP - You can open your eyes now...
  1492. //
  1493. //
  1494. // We must indicate the presence of this field to the
  1495. // receiver.
  1496. //
  1497. pExtTextOut->fuOptions |= ETO_LPDX;
  1498. }
  1499. else
  1500. {
  1501. //
  1502. // Mark the delta array as empty.
  1503. //
  1504. lpDeltaPos->len = 0;
  1505. }
  1506. //
  1507. // WHOOP WHOOP WHOOP - You can open your eyes now...
  1508. //
  1509. //
  1510. // Make sure we send the order
  1511. //
  1512. fSendOrder = TRUE;
  1513. TRACE_OUT(( "EXTTEXTOUT: X %u Y %u bm %u FC %02X%02X%02X "
  1514. "BC %02X%02X%02X",
  1515. pExtTextOut->common.nXStart,
  1516. pExtTextOut->common.nYStart,
  1517. pExtTextOut->common.BackMode,
  1518. pExtTextOut->common.ForeColor.red,
  1519. pExtTextOut->common.ForeColor.green,
  1520. pExtTextOut->common.ForeColor.blue,
  1521. pExtTextOut->common.BackColor.red,
  1522. pExtTextOut->common.BackColor.green,
  1523. pExtTextOut->common.BackColor.blue));
  1524. TRACE_OUT(( "Extra: Opt %x X1 %d Y1 %d X2 %d Y2 %d",
  1525. pExtTextOut->fuOptions,
  1526. pExtTextOut->rectangle.left,
  1527. pExtTextOut->rectangle.top,
  1528. pExtTextOut->rectangle.right,
  1529. pExtTextOut->rectangle.bottom));
  1530. TRACE_OUT(( "Font: fx %u fy %u fw %u ff %04x fh %u len %u",
  1531. pExtTextOut->common.FontWidth,
  1532. pExtTextOut->common.FontHeight,
  1533. pExtTextOut->common.FontWeight,
  1534. pExtTextOut->common.FontFlags,
  1535. pExtTextOut->common.FontIndex,
  1536. ansiLen));
  1537. TRACE_OUT(( "String '%s'", ansiString));
  1538. break;
  1539. default:
  1540. ERROR_OUT(( "Unknown order %x", orderType));
  1541. break;
  1542. }
  1543. DC_EXIT_POINT:
  1544. //
  1545. // If we did not send an order, we must accumulate the output in the
  1546. // Screen Data Area.
  1547. //
  1548. if (fSendOrder)
  1549. {
  1550. //
  1551. // Store the general order data. The bounding rectangle position
  1552. // must be in virtual desktop co-ordinates. OELRtoVirtual has
  1553. // already done this.
  1554. //
  1555. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  1556. TSHR_RECT16_FROM_RECT(&pOrder->OrderHeader.Common.rcsDst, rectDst);
  1557. //
  1558. // Add the order to the cache.
  1559. //
  1560. OEClipAndAddOrder(pOrder, NULL, pco);
  1561. }
  1562. else
  1563. {
  1564. if (fAccumulate)
  1565. {
  1566. OEClipAndAddScreenData(&rectDst, pco);
  1567. }
  1568. }
  1569. OE_SHM_STOP_WRITING;
  1570. NO_LOCK_EXIT:
  1571. DebugExitDWORD(DrvTextOut, rc);
  1572. return(rc);
  1573. }
  1574. //
  1575. // DrvLineTo - see NT DDK documentation.
  1576. //
  1577. BOOL DrvLineTo(SURFOBJ *pso,
  1578. CLIPOBJ *pco,
  1579. BRUSHOBJ *pbo,
  1580. LONG x1,
  1581. LONG y1,
  1582. LONG x2,
  1583. LONG y2,
  1584. RECTL *prclBounds,
  1585. MIX mix)
  1586. {
  1587. LPOSI_PDEV ppdev = (LPOSI_PDEV)pso->dhpdev;
  1588. BOOL rc = TRUE;
  1589. RECT rectDst;
  1590. POINT startPoint;
  1591. POINT endPoint;
  1592. BOOL fAccumulate = FALSE;
  1593. DebugEntry(DrvLineTo);
  1594. //
  1595. // DO THIS _BEFORE_ TAKING LOCK
  1596. //
  1597. if (!g_oeViewers)
  1598. goto NO_LOCK_EXIT;
  1599. OE_SHM_START_WRITING;
  1600. //
  1601. // Get bounding rectangle and convert to a RECT.
  1602. //
  1603. RECT_FROM_RECTL(rectDst, (*prclBounds));
  1604. //
  1605. // Check if we are accumulating data for this function
  1606. //
  1607. fAccumulate = OEAccumulateOutput(pso, pco, &rectDst);
  1608. if (!fAccumulate)
  1609. {
  1610. DC_QUIT;
  1611. }
  1612. //
  1613. // Convert the data to virtual coordinates.
  1614. //
  1615. OELRtoVirtual(&rectDst, 1);
  1616. //
  1617. // Check if we are allowed to send this order (determined by the
  1618. // negotiated capabilities of all the machines in the conference).
  1619. //
  1620. if (!OE_SendAsOrder(ORD_LINETO))
  1621. {
  1622. TRACE_OUT(( "LineTo order not allowed"));
  1623. DC_QUIT;
  1624. }
  1625. //
  1626. // Check for a valid brush for the test operation.
  1627. //
  1628. if (pbo->iSolidColor == -1)
  1629. {
  1630. TRACE_OUT(( "Bad brush for line"));
  1631. DC_QUIT;
  1632. }
  1633. //
  1634. // Check for overcomplicated clipping.
  1635. //
  1636. if (OEClippingIsComplex(pco))
  1637. {
  1638. TRACE_OUT(( "Clipping is too complex"));
  1639. DC_QUIT;
  1640. }
  1641. //
  1642. // Set up data for order
  1643. //
  1644. startPoint.x = x1;
  1645. startPoint.y = y1;
  1646. endPoint.x = x2;
  1647. endPoint.y = y2;
  1648. //
  1649. // Store that order.
  1650. //
  1651. if (!OEAddLine(ppdev,
  1652. &startPoint,
  1653. &endPoint,
  1654. &rectDst,
  1655. mix & 0x1F,
  1656. 1,
  1657. pbo->iSolidColor,
  1658. pco))
  1659. {
  1660. TRACE_OUT(( "Failed to add order - use SDA"));
  1661. DC_QUIT;
  1662. }
  1663. //
  1664. // We have stored this object, so don't store the data in the SDA
  1665. // again.
  1666. //
  1667. fAccumulate = FALSE;
  1668. DC_EXIT_POINT:
  1669. if (fAccumulate)
  1670. {
  1671. OEClipAndAddScreenData(&rectDst, pco);
  1672. }
  1673. OE_SHM_STOP_WRITING;
  1674. NO_LOCK_EXIT:
  1675. DebugExitDWORD(DrvLineTo, rc);
  1676. return(rc);
  1677. }
  1678. //
  1679. // DrvStrokePath - see NT DDK documentation.
  1680. //
  1681. BOOL DrvStrokePath(SURFOBJ *pso,
  1682. PATHOBJ *ppo,
  1683. CLIPOBJ *pco,
  1684. XFORMOBJ *pxo,
  1685. BRUSHOBJ *pbo,
  1686. POINTL *pptlBrushOrg,
  1687. LINEATTRS *plineattrs,
  1688. MIX mix)
  1689. {
  1690. LPOSI_PDEV ppdev = (LPOSI_PDEV)pso->dhpdev;
  1691. BOOL rc = TRUE;
  1692. RECTFX rectfxTrg;
  1693. RECT rectDst;
  1694. BOOL fMore = TRUE;
  1695. PATHDATA pathData;
  1696. POINT startPoint;
  1697. POINT nextPoint;
  1698. POINT endPoint;
  1699. BOOL fAccumulate = FALSE;
  1700. UINT i;
  1701. DebugEntry(DrvStrokePath);
  1702. //
  1703. // DO THIS _BEFORE_ TAKING LOCK
  1704. //
  1705. if (!g_oeViewers)
  1706. goto NO_LOCK_EXIT;
  1707. OE_SHM_START_WRITING;
  1708. //
  1709. // Get bounding rectangle and convert to a RECT.
  1710. //
  1711. PATHOBJ_vGetBounds(ppo, &rectfxTrg);
  1712. RECT_FROM_RECTFX(rectDst, rectfxTrg);
  1713. //
  1714. // Check if we are accumulating data for this function
  1715. //
  1716. fAccumulate = OEAccumulateOutput(pso, pco, &rectDst);
  1717. if (!fAccumulate)
  1718. {
  1719. DC_QUIT;
  1720. }
  1721. //
  1722. // Check if we are allowed to send this order (determined by the
  1723. // negotiated capabilities of all the machines in the conference).
  1724. //
  1725. if (!OE_SendAsOrder(ORD_LINETO))
  1726. {
  1727. TRACE_OUT(( "LineTo order not allowed"));
  1728. DC_QUIT;
  1729. }
  1730. //
  1731. // Check for a valid brush for the test operation.
  1732. //
  1733. if (pbo->iSolidColor == -1)
  1734. {
  1735. TRACE_OUT(( "Bad brush for line"));
  1736. DC_QUIT;
  1737. }
  1738. //
  1739. // Check for overcomplicated clipping.
  1740. //
  1741. if (OEClippingIsComplex(pco))
  1742. {
  1743. TRACE_OUT(( "Clipping is too complex"));
  1744. DC_QUIT;
  1745. }
  1746. //
  1747. // See if we can optimize the path...
  1748. //
  1749. // We cannot send:
  1750. //
  1751. // - curvy lines (i.e. beziers)
  1752. // - lines with funny end patterns (i.e. geometric lines)
  1753. // - non Windows standard patterns
  1754. //
  1755. if ( ((ppo->fl & PO_BEZIERS) == 0) &&
  1756. ((plineattrs->fl & LA_GEOMETRIC) == 0) &&
  1757. (plineattrs->pstyle == NULL) )
  1758. {
  1759. //
  1760. // This is a set of solid cosmetic (i.e. no fancy end styles)
  1761. // lines. Let's send those orders.
  1762. //
  1763. // NT stores all paths as a set of independent sub-paths. Each
  1764. // sub-path can start at a new point that is NOT linked to the
  1765. // previous sub-path.
  1766. //
  1767. // Paths used for this function (as opposed to DrvFillPath or
  1768. // DrvStrokeAndFillPath) do not need to be closed.
  1769. //
  1770. PATHOBJ_vEnumStart(ppo);
  1771. while (fMore)
  1772. {
  1773. //
  1774. // Get the next set of lines
  1775. //
  1776. fMore = PATHOBJ_bEnum(ppo, &pathData);
  1777. TRACE_OUT(( "PTS: %lu FLAG: %08lx",
  1778. pathData.count,
  1779. pathData.flags));
  1780. //
  1781. // If this is the start of a path, remember the point in case
  1782. // we need to close the path at the end.
  1783. //
  1784. if (pathData.flags & PD_BEGINSUBPATH)
  1785. {
  1786. POINT_FROM_POINTFIX(startPoint, pathData.pptfx[0]);
  1787. POINT_FROM_POINTFIX(nextPoint, pathData.pptfx[0]);
  1788. }
  1789. //
  1790. // Generate orders for each line in the path.
  1791. //
  1792. for (i = 0; i < pathData.count; i++)
  1793. {
  1794. POINT_FROM_POINTFIX(endPoint, pathData.pptfx[i]);
  1795. if ( (nextPoint.x != endPoint.x) ||
  1796. (nextPoint.y != endPoint.y) )
  1797. {
  1798. if (!OEAddLine(ppdev,
  1799. &nextPoint,
  1800. &endPoint,
  1801. &rectDst,
  1802. mix & 0x1f,
  1803. plineattrs->elWidth.l,
  1804. pbo->iSolidColor,
  1805. pco))
  1806. {
  1807. DC_QUIT;
  1808. }
  1809. }
  1810. nextPoint.x = endPoint.x;
  1811. nextPoint.y = endPoint.y;
  1812. }
  1813. //
  1814. // Close the path if necessary.
  1815. //
  1816. if ((pathData.flags & PD_CLOSEFIGURE) != 0)
  1817. {
  1818. if (!OEAddLine(ppdev,
  1819. &endPoint,
  1820. &startPoint,
  1821. &rectDst,
  1822. mix & 0x1f,
  1823. plineattrs->elWidth.l,
  1824. pbo->iSolidColor,
  1825. pco))
  1826. {
  1827. DC_QUIT;
  1828. }
  1829. }
  1830. }
  1831. //
  1832. // We have processed the entire thing as orders - don't send screen
  1833. // data.
  1834. //
  1835. fAccumulate = FALSE;
  1836. }
  1837. DC_EXIT_POINT:
  1838. if (fAccumulate)
  1839. {
  1840. //
  1841. // Convert the bounds to virtual coordinates.
  1842. //
  1843. OELRtoVirtual(&rectDst, 1);
  1844. TRACE_OUT(( "SDA: (%d,%d)(%d,%d)",
  1845. rectDst.left,
  1846. rectDst.top,
  1847. rectDst.right,
  1848. rectDst.bottom));
  1849. //
  1850. // Update the Screen Data Area
  1851. //
  1852. OEClipAndAddScreenData(&rectDst, pco);
  1853. }
  1854. OE_SHM_STOP_WRITING;
  1855. NO_LOCK_EXIT:
  1856. DebugExitDWORD(DrvStrokePath, rc);
  1857. return(rc);
  1858. }
  1859. //
  1860. // DrvFillPath - see NT DDK documentation.
  1861. //
  1862. BOOL DrvFillPath(SURFOBJ *pso,
  1863. PATHOBJ *ppo,
  1864. CLIPOBJ *pco,
  1865. BRUSHOBJ *pbo,
  1866. POINTL *pptlBrushOrg,
  1867. MIX mix,
  1868. FLONG flOptions)
  1869. {
  1870. BOOL rc = TRUE;
  1871. RECTFX rectfxTrg;
  1872. RECT rectDst;
  1873. DebugEntry(DrvFillPath);
  1874. //
  1875. // DO THIS _BEFORE_ TAKING LOCK
  1876. //
  1877. if (!g_oeViewers)
  1878. goto NO_LOCK_EXIT;
  1879. OE_SHM_START_WRITING;
  1880. //
  1881. // Get bounding rectangle and convert to a RECT.
  1882. //
  1883. PATHOBJ_vGetBounds(ppo, &rectfxTrg);
  1884. RECT_FROM_RECTFX(rectDst, rectfxTrg);
  1885. //
  1886. // Check if we are accumulating data for this function
  1887. //
  1888. if (!OEAccumulateOutput(pso, pco, &rectDst))
  1889. {
  1890. DC_QUIT;
  1891. }
  1892. //
  1893. // Convert the bounds to virtual coordinates.
  1894. //
  1895. OELRtoVirtual(&rectDst, 1);
  1896. TRACE_OUT(( "SDA: (%d,%d)(%d,%d)",
  1897. rectDst.left,
  1898. rectDst.top,
  1899. rectDst.right,
  1900. rectDst.bottom));
  1901. //
  1902. // Update the Screen Data Area
  1903. //
  1904. OEClipAndAddScreenData(&rectDst, pco);
  1905. DC_EXIT_POINT:
  1906. OE_SHM_STOP_WRITING;
  1907. NO_LOCK_EXIT:
  1908. DebugExitDWORD(DrvFillPath, rc);
  1909. return(rc);
  1910. }
  1911. //
  1912. // DrvStrokeAndFillPath - see NT DDK documentation.
  1913. //
  1914. BOOL DrvStrokeAndFillPath(SURFOBJ *pso,
  1915. PATHOBJ *ppo,
  1916. CLIPOBJ *pco,
  1917. XFORMOBJ *pxo,
  1918. BRUSHOBJ *pboStroke,
  1919. LINEATTRS *plineattrs,
  1920. BRUSHOBJ *pboFill,
  1921. POINTL *pptlBrushOrg,
  1922. MIX mixFill,
  1923. FLONG flOptions)
  1924. {
  1925. BOOL rc = TRUE;
  1926. RECTFX rectfxTrg;
  1927. RECT rectDst;
  1928. DebugEntry(DrvStrokeAndFillPath);
  1929. //
  1930. // DO THIS _BEFORE_ TAKING LOCK
  1931. //
  1932. if (!g_oeViewers)
  1933. goto NO_LOCK_EXIT;
  1934. OE_SHM_START_WRITING;
  1935. //
  1936. // Get bounding rectangle and convert to a RECT.
  1937. //
  1938. PATHOBJ_vGetBounds(ppo, &rectfxTrg);
  1939. RECT_FROM_RECTFX(rectDst, rectfxTrg);
  1940. //
  1941. // Check if we are accumulating data for this function
  1942. //
  1943. if (!OEAccumulateOutput(pso, pco, &rectDst))
  1944. {
  1945. DC_QUIT;
  1946. }
  1947. //
  1948. // Convert the bounds to virtual coordinates.
  1949. //
  1950. OELRtoVirtual(&rectDst, 1);
  1951. //
  1952. // Update the Screen Data Area
  1953. //
  1954. OEClipAndAddScreenData(&rectDst, pco);
  1955. DC_EXIT_POINT:
  1956. OE_SHM_STOP_WRITING;
  1957. NO_LOCK_EXIT:
  1958. DebugExitDWORD(DrvStrokeAndFillPath, rc);
  1959. return(rc);
  1960. }
  1961. //
  1962. // DrvPaint - see NT DDK documentation.
  1963. //
  1964. BOOL DrvPaint(SURFOBJ *pso,
  1965. CLIPOBJ *pco,
  1966. BRUSHOBJ *pbo,
  1967. POINTL *pptlBrushOrg,
  1968. MIX mix)
  1969. {
  1970. BOOL rc = TRUE;
  1971. RECT rectDst;
  1972. BOOL fAccumulate = FALSE;
  1973. ROP4 rop4;
  1974. DebugEntry(DrvPaint);
  1975. //
  1976. // DO THIS _BEFORE_ TAKING LOCK
  1977. //
  1978. if (!g_oeViewers)
  1979. goto NO_LOCK_EXIT;
  1980. OE_SHM_START_WRITING;
  1981. //
  1982. // Get bounding rectangle and convert to a RECT.
  1983. //
  1984. RECT_FROM_RECTL(rectDst, pco->rclBounds);
  1985. //
  1986. // Check if we are accumulating data for this function
  1987. //
  1988. fAccumulate = OEAccumulateOutput(pso, pco, &rectDst);
  1989. if (!fAccumulate)
  1990. {
  1991. DC_QUIT;
  1992. }
  1993. //
  1994. // Convert to virtual coordinates.
  1995. //
  1996. OELRtoVirtual(&rectDst, 1);
  1997. //
  1998. // Check for overcomplicated clipping.
  1999. //
  2000. if (OEClippingIsComplex(pco))
  2001. {
  2002. TRACE_OUT(( "Clipping is too complex"));
  2003. DC_QUIT;
  2004. }
  2005. //
  2006. // The low byte of the mix represents a ROP2. We need a ROP4 for
  2007. // BitBlt, so convert the mix as follows.
  2008. //
  2009. // Remember the definitions of 2, 3 & 4 way ROP codes.
  2010. //
  2011. // Msk Pat Src Dst
  2012. //
  2013. // 1 1 1 1 �������͸�����ͻ ROP2 uses P & D only
  2014. // 1 1 1 0 � �
  2015. // 1 1 0 1 Ŀ � � ROP3 uses P, S & D
  2016. // 1 1 0 0 �ROP2-1�ROP3 �ROP4
  2017. // 1 0 1 1 �(see � � ROP4 uses M, P, S & D
  2018. // 1 0 1 0 �� note)� �
  2019. // 1 0 0 1 � �
  2020. // 1 0 0 0 �������; �
  2021. // 0 1 1 1 �
  2022. // 0 1 1 0 � NOTE: Windows defines its
  2023. // 0 1 0 1 � ROP2 codes as the bitwise
  2024. // 0 1 0 0 � value calculated here
  2025. // 0 0 1 1 � plus one. All other ROP
  2026. // 0 0 1 0 � codes are the straight
  2027. // 0 0 0 1 � bitwise value.
  2028. // 0 0 0 0 ��������������ͼ
  2029. //
  2030. // Or, algorithmically...
  2031. //
  2032. // ROP3 = (ROP2 & 0x3) | ((ROP2 & 0xC) << 4) | (ROP2 << 2)
  2033. //
  2034. // ROP4 = (ROP3 << 8) | ROP3
  2035. //
  2036. mix = (mix & 0x1F) - 1;
  2037. rop4 = (mix & 0x3) | ((mix & 0xC) << 4) | (mix << 2);
  2038. rop4 = (rop4 << 8) | rop4;
  2039. //
  2040. // This can be passed on to the BitBlt code.
  2041. //
  2042. rc = DrvBitBlt( pso,
  2043. NULL,
  2044. NULL,
  2045. pco,
  2046. NULL,
  2047. &pco->rclBounds,
  2048. NULL,
  2049. NULL,
  2050. pbo,
  2051. pptlBrushOrg,
  2052. rop4 );
  2053. //
  2054. // We have stored this object in the BitBlt, so don't store the data
  2055. // again.
  2056. //
  2057. fAccumulate = FALSE;
  2058. DC_EXIT_POINT:
  2059. if (fAccumulate)
  2060. {
  2061. OEClipAndAddScreenData(&rectDst, pco);
  2062. }
  2063. OE_SHM_STOP_WRITING;
  2064. NO_LOCK_EXIT:
  2065. DebugExitDWORD(DrvPaint, rc);
  2066. return(rc);
  2067. }
  2068. //
  2069. // OE_DDProcessRequest - see oe.h
  2070. //
  2071. ULONG OE_DDProcessRequest
  2072. (
  2073. SURFOBJ* pso,
  2074. UINT cjIn,
  2075. void * pvIn,
  2076. UINT cjOut,
  2077. void * pvOut
  2078. )
  2079. {
  2080. BOOL rc = TRUE;
  2081. LPOSI_ESCAPE_HEADER pHeader;
  2082. DebugEntry(OE_DDProcessRequest);
  2083. //
  2084. // Get the request number.
  2085. //
  2086. pHeader = pvIn;
  2087. switch (pHeader->escapeFn)
  2088. {
  2089. case OE_ESC_NEW_FONTS:
  2090. {
  2091. if ((cjIn != sizeof(OE_NEW_FONTS)) ||
  2092. (cjOut != sizeof(OE_NEW_FONTS)))
  2093. {
  2094. ERROR_OUT(("OE_DDProcessRequest: Invalid sizes %d, %d for OE_ESC_NEW_FONTS",
  2095. cjIn, cjOut));
  2096. rc = FALSE;
  2097. DC_QUIT;
  2098. }
  2099. //
  2100. // Get new local font data
  2101. //
  2102. OEDDSetNewFonts(pvIn);
  2103. }
  2104. break;
  2105. case OE_ESC_NEW_CAPABILITIES:
  2106. {
  2107. if ((cjIn != sizeof(OE_NEW_CAPABILITIES)) ||
  2108. (cjOut != sizeof(OE_NEW_CAPABILITIES)))
  2109. {
  2110. ERROR_OUT(("OE_DDProcessRequest: Invalid sizes %d, %d for OE_ESC_NEW_CAPABILITIES",
  2111. cjIn, cjOut));
  2112. rc = FALSE;
  2113. DC_QUIT;
  2114. }
  2115. //
  2116. // The capabilities have changed - take the new copy.
  2117. //
  2118. OEDDSetNewCapabilities(pvIn);
  2119. }
  2120. break;
  2121. default:
  2122. {
  2123. ERROR_OUT(("Unrecognised OE escape"));
  2124. rc = FALSE;
  2125. }
  2126. break;
  2127. }
  2128. DC_EXIT_POINT:
  2129. DebugExitDWORD(OE_DDProcessRequest, rc);
  2130. return((ULONG)rc);
  2131. }
  2132. //
  2133. // OE_DDTerm()
  2134. // This cleans up objects used
  2135. //
  2136. void OE_DDTerm(void)
  2137. {
  2138. DebugEntry(OE_DDTerm);
  2139. //
  2140. // Free font list
  2141. //
  2142. if (g_poeLocalFonts)
  2143. {
  2144. TRACE_OUT(("OE_DDLocalHosting: freeing font block since we're done sharing"));
  2145. EngFreeMem(g_poeLocalFonts);
  2146. g_poeLocalFonts = NULL;
  2147. g_oeNumFonts = 0;
  2148. }
  2149. DebugExitVOID(OE_DDTerm);
  2150. }
  2151. //
  2152. // DrvRealizeBrush - see NT DDK documentation.
  2153. //
  2154. BOOL DrvRealizeBrush(BRUSHOBJ *pbo,
  2155. SURFOBJ *psoTarget,
  2156. SURFOBJ *psoPattern,
  2157. SURFOBJ *psoMask,
  2158. XLATEOBJ *pxlo,
  2159. ULONG iHatch)
  2160. {
  2161. LPOSI_PDEV ppdev = (LPOSI_PDEV)psoTarget->dhpdev;
  2162. BOOL rc = TRUE;
  2163. LPBYTE pData;
  2164. BYTE brushBits[8];
  2165. UINT color1;
  2166. UINT color2;
  2167. int i;
  2168. int j;
  2169. BOOL monochromeBrush = TRUE;
  2170. DebugEntry(DrvRealizeBrush);
  2171. //
  2172. // This function only sets up local data, so shared memory protection
  2173. // is not required.
  2174. //
  2175. //
  2176. // Since this function is called only when we call BRUSHOBJ_pvGetRBrush
  2177. // and we don't do any processing until we are in a share we don't need
  2178. // an explicit check for hosting here ('coz that happened before the
  2179. // call to realise the brush).
  2180. //
  2181. //
  2182. // A valid brush satisfies either of the following criteria.
  2183. //
  2184. // 1) It is a standard hatch brush (as passed by DrvEnablePDEV)
  2185. // 2) It is an 8x8 monochrome bitmap
  2186. //
  2187. //
  2188. // Check for a Windows standard hatch
  2189. //
  2190. if (iHatch < HS_DDI_MAX)
  2191. {
  2192. TRACE_OUT(( "Standard hatch %lu", iHatch));
  2193. rc = OEStoreBrush(ppdev,
  2194. pbo,
  2195. BS_HATCHED,
  2196. NULL,
  2197. pxlo,
  2198. (BYTE)iHatch,
  2199. 0,
  2200. 1);
  2201. DC_QUIT;
  2202. }
  2203. //
  2204. // If the driver has been passed a dither color brush we can support
  2205. // this by sending a solid color brush definition
  2206. //
  2207. if ((iHatch & RB_DITHERCOLOR) != 0)
  2208. {
  2209. TRACE_OUT(( "Standard hatch %lu", iHatch));
  2210. rc = OEStoreBrush(ppdev,
  2211. pbo,
  2212. BS_SOLID,
  2213. NULL,
  2214. NULL,
  2215. (BYTE)iHatch,
  2216. iHatch & 0xFFFFFF,
  2217. 0);
  2218. DC_QUIT;
  2219. }
  2220. //
  2221. // Check for a simple 8x8 brush
  2222. //
  2223. if ( (psoPattern->sizlBitmap.cx == 8) &&
  2224. (psoPattern->sizlBitmap.cy == 8) )
  2225. {
  2226. //
  2227. // Check for 2 colours only in the bitmap.
  2228. //
  2229. // NOTE: There's a flag (BMF_TOPDOWN) in psoPattern->fjBitmap
  2230. // that's supposed to indicate whether the bitmap is top-down or
  2231. // bottom-up, but it is not always set up correctly. In fact, the
  2232. // bitmaps are always the wrong way up for our protocol, so we have
  2233. // to flip them regardless of the flag. Hence the row numbers are
  2234. // reversed ('i' loops) in all the conversions below.
  2235. //
  2236. pData = psoPattern->pvScan0;
  2237. switch (psoPattern->iBitmapFormat)
  2238. {
  2239. case BMF_1BPP:
  2240. {
  2241. //
  2242. // 1 bpp MUST be 2 colours maximum.
  2243. //
  2244. color1 = 1;
  2245. color2 = 0;
  2246. for (i = 7; i >= 0; i--)
  2247. {
  2248. brushBits[i] = *pData;
  2249. pData += psoPattern->lDelta;
  2250. }
  2251. }
  2252. break;
  2253. case BMF_4BPP:
  2254. {
  2255. //
  2256. // See if it is really a 2 colour brush. Start off with
  2257. // both colours the same.
  2258. //
  2259. color1 = pData[0] & 15;
  2260. color2 = color1;
  2261. //
  2262. // Iterate through each row of the bitmap.
  2263. //
  2264. for (i = 7; (i >= 0) && (monochromeBrush); i--)
  2265. {
  2266. brushBits[i] = 0;
  2267. //
  2268. // Check each pixel in the row: 4bpp->2 pixels per byte
  2269. //
  2270. for (j = 0; (j < 4) && (monochromeBrush); j++)
  2271. {
  2272. //
  2273. // Check the 1st pixel color
  2274. //
  2275. if ( (color1 != (UINT)(pData[j] & 0x0F)) &&
  2276. (color2 != (UINT)(pData[j] & 0x0F)) )
  2277. {
  2278. if (color1 == color2)
  2279. {
  2280. color2 = (pData[j] & 0x0F);
  2281. }
  2282. else
  2283. {
  2284. monochromeBrush = FALSE;
  2285. }
  2286. }
  2287. //
  2288. // Check the 2nd pixel color
  2289. //
  2290. if ( (color1 != (UINT)((pData[j] & 0xF0) >> 4)) &&
  2291. (color2 != (UINT)((pData[j] & 0xF0) >> 4)) )
  2292. {
  2293. if (color1 == color2)
  2294. {
  2295. color2 = (pData[j] & 0xF0) >> 4;
  2296. }
  2297. else
  2298. {
  2299. monochromeBrush = FALSE;
  2300. }
  2301. }
  2302. //
  2303. // Set up the brush data. High bit is leftmost.
  2304. //
  2305. if ((UINT)(pData[j] & 0x0F) == color1)
  2306. {
  2307. brushBits[i] |= 0x40 >> (j * 2);
  2308. }
  2309. if ((UINT)(pData[j] & 0xF0) >> 4 == color1)
  2310. {
  2311. brushBits[i] |= 0x80 >> (j * 2);
  2312. }
  2313. }
  2314. //
  2315. // Get start of next row.
  2316. //
  2317. pData += psoPattern->lDelta;
  2318. }
  2319. }
  2320. break;
  2321. case BMF_8BPP:
  2322. {
  2323. //
  2324. // See if it is really a 2 colour brush. Start off with
  2325. // both colours the same.
  2326. //
  2327. color1 = pData[0];
  2328. color2 = color1;
  2329. //
  2330. // Iterate through each row of the bitmap.
  2331. //
  2332. for (i = 7; (i >= 0) && (monochromeBrush); i--)
  2333. {
  2334. brushBits[i] = 0;
  2335. //
  2336. // Check each pixel in the row: 8bpp->1 pixel per byte
  2337. //
  2338. for (j = 0; (j < 8) && (monochromeBrush); j++)
  2339. {
  2340. //
  2341. // Check each pixel.
  2342. //
  2343. if ( (color1 != pData[j]) &&
  2344. (color2 != pData[j]) )
  2345. {
  2346. if (color1 == color2)
  2347. {
  2348. color2 = pData[j];
  2349. }
  2350. else
  2351. {
  2352. monochromeBrush = FALSE;
  2353. }
  2354. }
  2355. //
  2356. // Update the brush data. High bit is leftmost.
  2357. //
  2358. if (pData[j] == color1)
  2359. {
  2360. brushBits[i] |= 0x80 >> j;
  2361. }
  2362. }
  2363. //
  2364. // Get start of next row.
  2365. //
  2366. pData += psoPattern->lDelta;
  2367. }
  2368. }
  2369. break;
  2370. default:
  2371. {
  2372. //
  2373. // Unsupported colour depth.
  2374. //
  2375. monochromeBrush = FALSE;
  2376. }
  2377. break;
  2378. }
  2379. }
  2380. else
  2381. {
  2382. //
  2383. // The brush is the wrong size or requires dithering and so cannot
  2384. // be sent over the wire.
  2385. //
  2386. monochromeBrush = FALSE;
  2387. }
  2388. //
  2389. // Store that brush.
  2390. //
  2391. if (monochromeBrush)
  2392. {
  2393. //
  2394. // Store the brush - note that we have a monochrome brush where the
  2395. // color bit is set up so that 0 = color2 and 1 = color1. This
  2396. // actually corresponds to 0 = fg and 1 = bg for the protocol
  2397. // colors.
  2398. //
  2399. TRACE_OUT(( "Storing brush: type %d bg %x fg %x",
  2400. psoPattern->iBitmapFormat,
  2401. color1,
  2402. color2));
  2403. rc = OEStoreBrush(ppdev,
  2404. pbo,
  2405. BS_PATTERN,
  2406. brushBits,
  2407. pxlo,
  2408. 0,
  2409. color2,
  2410. color1);
  2411. }
  2412. else
  2413. {
  2414. TRACE_OUT(( "Rejected brush h %08lx s (%ld, %ld) fmt %lu",
  2415. iHatch,
  2416. psoPattern != NULL ? psoPattern->sizlBitmap.cx : 0,
  2417. psoPattern != NULL ? psoPattern->sizlBitmap.cy : 0,
  2418. psoPattern != NULL ? psoPattern->iBitmapFormat : 0));
  2419. rc = OEStoreBrush(ppdev, pbo, BS_NULL, NULL, pxlo, 0, 0, 0);
  2420. }
  2421. DC_EXIT_POINT:
  2422. DebugExitDWORD(DrvRealizeBrush, rc);
  2423. return(rc);
  2424. }
  2425. //
  2426. // DrvSaveScreenBits - see NT DDK documentation.
  2427. //
  2428. ULONG_PTR DrvSaveScreenBits(SURFOBJ *pso,
  2429. ULONG iMode,
  2430. ULONG_PTR ident,
  2431. RECTL *prcl)
  2432. {
  2433. BOOL rc;
  2434. UINT ourMode;
  2435. RECT rectDst;
  2436. DebugEntry(DrvSaveScreenBits);
  2437. TRACE_OUT(("DrvSaveScreenBits: %s",
  2438. ((iMode == SS_SAVE) ? "SAVE" :
  2439. ((iMode == SS_RESTORE) ? "RESTORE" : "DISCARD"))));
  2440. TRACE_OUT((" rect {%04ld, %04ld, %04ld, %04ld}",
  2441. prcl->left, prcl->top, prcl->right, prcl->bottom));
  2442. //
  2443. // Default is TRUE, let SaveBits happen if we don't care. Which we don't
  2444. // if we have no shared memory (NetMeeting isn't running), no window list
  2445. // (no shared apps), or the operation isn't intersecting a window we
  2446. // care about.
  2447. //
  2448. // Note that if we return TRUE on a save, and FALSE on a restore later
  2449. // (because we are now sharing that area for example), USER+GRE handle
  2450. // that. So it's ok.
  2451. //
  2452. rc = TRUE;
  2453. //
  2454. // DO THIS _BEFORE_ TAKING LOCK
  2455. //
  2456. if (!g_oeViewers)
  2457. goto NO_LOCK_EXIT;
  2458. //
  2459. // If we have no shared memory (NetMeeting isn't running), this will bail
  2460. // out immediately.
  2461. //
  2462. OE_SHM_START_WRITING;
  2463. //
  2464. // Get the bounding rectangle for the operation. NOTE that this is
  2465. // meaningless for SS_FREE.
  2466. //
  2467. RECT_FROM_RECTL(rectDst, (*prcl));
  2468. if (iMode != SS_FREE)
  2469. {
  2470. //
  2471. // Check if we are accumulating data for this area, ONLY FOR
  2472. // SAVEs. We may get notified after a window is gone to
  2473. // restore or discard bits we had saved.
  2474. //
  2475. if (!OEAccumulateOutputRect(pso, &rectDst))
  2476. {
  2477. TRACE_OUT(("DrvSaveScreenBits: save/restore in area we don't care about"));
  2478. DC_QUIT;
  2479. }
  2480. }
  2481. //
  2482. // Convert the NT orders to our generic save/restore types.
  2483. //
  2484. switch (iMode)
  2485. {
  2486. case SS_SAVE:
  2487. {
  2488. ourMode = ONBOARD_SAVE;
  2489. }
  2490. break;
  2491. case SS_RESTORE:
  2492. {
  2493. ourMode = ONBOARD_RESTORE;
  2494. }
  2495. break;
  2496. case SS_FREE:
  2497. {
  2498. ourMode = ONBOARD_DISCARD;
  2499. }
  2500. break;
  2501. default:
  2502. {
  2503. ERROR_OUT(( "Unknown type %lu", iMode));
  2504. DC_QUIT;
  2505. }
  2506. }
  2507. //
  2508. // Call through to the SSI handler.
  2509. //
  2510. rc = SSI_SaveScreenBitmap(&rectDst, ourMode);
  2511. DC_EXIT_POINT:
  2512. OE_SHM_STOP_WRITING;
  2513. NO_LOCK_EXIT:
  2514. TRACE_OUT(("DrvSaveScreenBits returning %d", rc));
  2515. DebugExitDWORD(DrvSaveScreenBits, rc);
  2516. return(rc);
  2517. }
  2518. //
  2519. // Function: OEUnicodeStrlen
  2520. //
  2521. // Description: Get the length of a unicode string in bytes.
  2522. //
  2523. // Parameters: pString - Unicode string to be read
  2524. //
  2525. // Returns: Length of the Unicode string in bytes
  2526. //
  2527. int OEUnicodeStrlen(PWSTR pString)
  2528. {
  2529. int i;
  2530. for (i = 0; pString[i] != 0; i++)
  2531. ;
  2532. return((i + 1) * sizeof(WCHAR));
  2533. }
  2534. //
  2535. // Function: OEExpandColor
  2536. //
  2537. // Description: Converts a generic bitwise representation of an RGB color
  2538. // index into an 8-bit color index as used by the line
  2539. // protocol.
  2540. //
  2541. //
  2542. void OEExpandColor
  2543. (
  2544. LPBYTE lpField,
  2545. ULONG srcColor,
  2546. ULONG mask
  2547. )
  2548. {
  2549. ULONG colorTmp;
  2550. DebugEntry(OEExpandColor);
  2551. //
  2552. // Different example bit masks:
  2553. //
  2554. // Normal 24-bit:
  2555. // 0x000000FF (red)
  2556. // 0x0000FF00 (green)
  2557. // 0x00FF0000 (blue)
  2558. //
  2559. // True color 32-bits:
  2560. // 0xFF000000 (red)
  2561. // 0x00FF0000 (green)
  2562. // 0x0000FF00 (blue)
  2563. //
  2564. // 5-5-5 16-bits
  2565. // 0x0000001F (red)
  2566. // 0x000003E0 (green)
  2567. // 0x00007C00 (blue)
  2568. //
  2569. // 5-6-5 16-bits
  2570. // 0x0000001F (red)
  2571. // 0x000007E0 (green)
  2572. // 0x0000F800 (blue)
  2573. //
  2574. //
  2575. // Convert the color using the following algorithm.
  2576. //
  2577. // <new color> = <old color> * <new bpp mask> / <old bpp mask>
  2578. //
  2579. // where:
  2580. //
  2581. // new bpp mask = mask for all bits at new setting (0xFF for 8bpp)
  2582. //
  2583. // This way maximal (eg. 0x1F) and minimal (eg. 0x00) settings are
  2584. // converted into the correct 8-bit maximum and minimum.
  2585. //
  2586. // Rearranging the above equation we get:
  2587. //
  2588. // <new color> = (<old color> & <old bpp mask>) * 0xFF / <old bpp mask>
  2589. //
  2590. // where:
  2591. //
  2592. // <old bpp mask> = mask for the color
  2593. //
  2594. //
  2595. // LAURABU BOGUS:
  2596. // We need to avoid overflow caused by the multiply. NOTE: in theory
  2597. // we should use a double, but that's painfully slow. So for now hack
  2598. // it. If the HIBYTE is set, just right shift 24 bits.
  2599. //
  2600. colorTmp = srcColor & mask;
  2601. if (colorTmp & 0xFF000000)
  2602. colorTmp >>= 24;
  2603. else
  2604. colorTmp = (colorTmp * 0xFF) / mask;
  2605. *lpField = (BYTE)colorTmp;
  2606. TRACE_OUT(( "0x%lX -> 0x%X", srcColor, *lpField));
  2607. DebugExitVOID(OEExpandColor);
  2608. }
  2609. //
  2610. // Function: OEConvertColor
  2611. //
  2612. // Description: Convert a color from the NT Display Driver into a TSHR_COLOR
  2613. //
  2614. // Parameters: pDCColor - (returned) color in protocol format
  2615. // osColor - color from the NT display driver
  2616. // pxlo - XLATEOBJ for the color to be converted
  2617. // (NULL if no translation is required)
  2618. //
  2619. // Returns: (none)
  2620. //
  2621. void OEConvertColor(LPOSI_PDEV ppdev, LPTSHR_COLOR pTshrColor,
  2622. ULONG osColor,
  2623. XLATEOBJ* pxlo)
  2624. {
  2625. ULONG realIndex;
  2626. DebugEntry(OEConvertColor);
  2627. //
  2628. // Make sure we have a default setting.
  2629. //
  2630. RtlFillMemory(pTshrColor, sizeof(TSHR_COLOR), 0);
  2631. //
  2632. // Check if color translation is required.
  2633. //
  2634. if ((pxlo != NULL) && (pxlo->flXlate != XO_TRIVIAL))
  2635. {
  2636. //
  2637. // Convert from BMP to device color.
  2638. //
  2639. realIndex = XLATEOBJ_iXlate(pxlo, osColor);
  2640. if (realIndex == -1)
  2641. {
  2642. ERROR_OUT(( "Failed to convert color 0x%lx", osColor));
  2643. DC_QUIT;
  2644. }
  2645. }
  2646. else
  2647. {
  2648. //
  2649. // Use the OS color without translation
  2650. //
  2651. realIndex = osColor;
  2652. }
  2653. TRACE_OUT(( "Device color 0x%lX", realIndex));
  2654. //
  2655. // We now have the device specific version of the color. Time to
  2656. // convert it into a 24-bit RGB color as used by the line protocol.
  2657. //
  2658. switch (ppdev->iBitmapFormat)
  2659. {
  2660. case BMF_1BPP:
  2661. case BMF_4BPP:
  2662. case BMF_4RLE:
  2663. case BMF_8BPP:
  2664. case BMF_8RLE:
  2665. //
  2666. // Palette type device - use the device color as an index into
  2667. // our palette array.
  2668. //
  2669. pTshrColor->red = (BYTE)ppdev->pPal[realIndex].peRed;
  2670. pTshrColor->green= (BYTE)ppdev->pPal[realIndex].peGreen;
  2671. pTshrColor->blue = (BYTE)ppdev->pPal[realIndex].peBlue;
  2672. break;
  2673. case BMF_16BPP:
  2674. case BMF_24BPP:
  2675. case BMF_32BPP:
  2676. //
  2677. // Generic colour masks (could be eg. 5-6-5 for 16 or 8-8-8
  2678. // for 24 bits per pel). We must mask off the other bits and
  2679. // shift down to bit 0.
  2680. //
  2681. OEExpandColor(&(pTshrColor->red),
  2682. realIndex,
  2683. ppdev->flRed);
  2684. OEExpandColor(&(pTshrColor->green),
  2685. realIndex,
  2686. ppdev->flGreen);
  2687. OEExpandColor(&(pTshrColor->blue),
  2688. realIndex,
  2689. ppdev->flBlue);
  2690. break;
  2691. default:
  2692. ERROR_OUT(( "Unrecognised BMP color depth %lu",
  2693. ppdev->iBitmapFormat));
  2694. break;
  2695. }
  2696. TRACE_OUT(( "Red %x green %x blue %x", pTshrColor->red,
  2697. pTshrColor->green,
  2698. pTshrColor->blue));
  2699. DC_EXIT_POINT:
  2700. DebugExitVOID(OEConvertColor);
  2701. }
  2702. //
  2703. // Function: OEStoreBrush
  2704. //
  2705. // Description: Store the brush data required for pattern realted orders.
  2706. // This function is called by DrvRealiseBrush when it has data
  2707. // to be stored about a brush.
  2708. //
  2709. // Parameters: pbo - BRUSHOBJ of the brush to be stored
  2710. // style - Style of the brush (as defined in the DC-Share
  2711. // protocol)
  2712. // pBits - Pointer to the bits which are used to define
  2713. // a BS_PATTERN brush.
  2714. // pxlo - XLATEOBJ for the brush.
  2715. // hatch - Standard Windows hatch pattern index for a
  2716. // BS_HATCHED brush.
  2717. // color1 - index into XLATEOBJ for bit set color
  2718. // OR exact 24bpp color to use (pxlo == NULL)
  2719. // color2 - index into XLATEOBJ for bit clear color
  2720. // OR exact 24bpp color to use (pxlo == NULL)
  2721. //
  2722. // Returns: (none)
  2723. //
  2724. BOOL OEStoreBrush(LPOSI_PDEV ppdev,
  2725. BRUSHOBJ* pbo,
  2726. BYTE style,
  2727. LPBYTE pBits,
  2728. XLATEOBJ* pxlo,
  2729. BYTE hatch,
  2730. UINT color1,
  2731. UINT color2)
  2732. {
  2733. BOOL rc = FALSE;
  2734. int i;
  2735. LPBYTE pData;
  2736. ULONG* pColorTable;
  2737. POE_BRUSH_DATA pBrush;
  2738. DebugEntry(OEStoreBrush);
  2739. //
  2740. // Allocate the space for the brush data.
  2741. //
  2742. pBrush = (POE_BRUSH_DATA)BRUSHOBJ_pvAllocRbrush(pbo,
  2743. sizeof(OE_BRUSH_DATA));
  2744. if (pBrush == NULL)
  2745. {
  2746. ERROR_OUT(( "No memory"));
  2747. DC_QUIT;
  2748. }
  2749. //
  2750. // Reset the brush definition
  2751. //
  2752. RtlFillMemory(pBrush, sizeof(OE_BRUSH_DATA), 0);
  2753. //
  2754. // Set the new brush data.
  2755. //
  2756. pBrush->style = style;
  2757. pBrush->hatch = hatch;
  2758. TRACE_OUT(( " Style: %d Hatch: %d", style, hatch));
  2759. //
  2760. // For pattern brushes, copy the brush specific data.
  2761. //
  2762. if (style == BS_PATTERN)
  2763. {
  2764. //
  2765. // Copy the brush bits. Since this is an 8x8 mono bitmap, we can
  2766. // copy the first byte of the brush data for each scan line.
  2767. //
  2768. // NOTE however that the brush structures sent over the wire
  2769. // re-use the hatching variable as the first byte of the brush data.
  2770. //
  2771. pData = pBits;
  2772. pBrush->hatch = *pData;
  2773. TRACE_OUT(( " Hatch: %d", *pData));
  2774. pData++;
  2775. for (i = 0; i < 7; i++)
  2776. {
  2777. pBrush->brushData[i] = pData[i];
  2778. TRACE_OUT(( " Data[%d]: %d", i, pData[i]));
  2779. }
  2780. //
  2781. // Get pointer to the bitmap color table.
  2782. //
  2783. pColorTable = pxlo->pulXlate;
  2784. if (pColorTable == NULL)
  2785. {
  2786. pColorTable = XLATEOBJ_piVector(pxlo);
  2787. }
  2788. }
  2789. //
  2790. // Store the foreground and background colours for the brush.
  2791. //
  2792. if (pxlo != NULL)
  2793. {
  2794. //
  2795. // Conversion required.
  2796. //
  2797. OEConvertColor(ppdev,
  2798. &pBrush->fore,
  2799. color1,
  2800. pxlo);
  2801. OEConvertColor(ppdev,
  2802. &pBrush->back,
  2803. color2,
  2804. pxlo);
  2805. }
  2806. else
  2807. {
  2808. //
  2809. // We have been passed an exact 24bpp color - this only happens for
  2810. // solid brushes so we don't need to convert color2.
  2811. //
  2812. pBrush->fore.red = (BYTE) (color1 & 0x0000FF);
  2813. pBrush->fore.green = (BYTE)((color1 & 0x00FF00) >> 8);
  2814. pBrush->fore.blue = (BYTE)((color1 & 0xFF0000) >> 16);
  2815. }
  2816. rc = TRUE;
  2817. DC_EXIT_POINT:
  2818. DebugExitDWORD(OEStoreBrush, rc);
  2819. return(rc);
  2820. }
  2821. //
  2822. // Function: OECheckBrushIsSimple
  2823. //
  2824. // Description: Check that the brush is a 'simple' object we can transfer
  2825. // over the DC-Share protocol.
  2826. //
  2827. // Parameters: pbo - BRUSHOBJ of the brush to be checked.
  2828. //
  2829. // Returns: TRUE - brush can be sent as DC-Share order
  2830. // FALSE - brush is too complicated.
  2831. //
  2832. BOOL OECheckBrushIsSimple(LPOSI_PDEV ppdev,
  2833. BRUSHOBJ* pbo,
  2834. POE_BRUSH_DATA* ppBrush)
  2835. {
  2836. BOOL rc = FALSE;
  2837. POE_BRUSH_DATA pBrush = NULL;
  2838. DebugEntry(OECheckBrushIsSimple);
  2839. //
  2840. // A 'simple' brush satisfies any of the following.
  2841. //
  2842. // 1) It is a solid color.
  2843. // 2) It is a valid brush as stored by DrvRealizeBrush.
  2844. //
  2845. //
  2846. // Check for a simple solid colour.
  2847. //
  2848. if (pbo->iSolidColor != -1)
  2849. {
  2850. //
  2851. // Use the reserved brush definition to set up the solid colour.
  2852. //
  2853. TRACE_OUT(( "Simple solid colour %08lx", pbo->iSolidColor));
  2854. pBrush = &g_oeBrushData;
  2855. //
  2856. // Set up the specific data for this brush.
  2857. //
  2858. OEConvertColor(ppdev, &pBrush->fore, pbo->iSolidColor, NULL);
  2859. pBrush->back.red = 0;
  2860. pBrush->back.green = 0;
  2861. pBrush->back.blue = 0;
  2862. pBrush->style = BS_SOLID;
  2863. pBrush->hatch = 0;
  2864. RtlFillMemory(pBrush->brushData, 7, 0);
  2865. //
  2866. // We have a valid brush - return true.
  2867. //
  2868. rc = TRUE;
  2869. DC_QUIT;
  2870. }
  2871. //
  2872. // Check brush definition (which was stored when we realized the
  2873. // brush).
  2874. //
  2875. pBrush = (POE_BRUSH_DATA)pbo->pvRbrush;
  2876. if (pBrush == NULL)
  2877. {
  2878. pBrush = (POE_BRUSH_DATA)BRUSHOBJ_pvGetRbrush(pbo);
  2879. if (pBrush == NULL)
  2880. {
  2881. //
  2882. // We can get NULL returned from BRUSHOBJ_pvGetRbrush when the
  2883. // brush is NULL or in low-memory situations (when the brush
  2884. // realization may fail).
  2885. //
  2886. TRACE_OUT(( "NULL returned from BRUSHOBJ_pvGetRbrush"));
  2887. DC_QUIT;
  2888. }
  2889. }
  2890. //
  2891. // Check it is an encodable brush.
  2892. //
  2893. if (pBrush->style == BS_NULL)
  2894. {
  2895. TRACE_OUT(( "Complex brush"));
  2896. DC_QUIT;
  2897. }
  2898. //
  2899. // Evrything passed - let's use this brush.
  2900. //
  2901. rc = TRUE;
  2902. DC_EXIT_POINT:
  2903. //
  2904. // Return the brush definition
  2905. //
  2906. *ppBrush = pBrush;
  2907. TRACE_OUT(( "Returning %d - 0x%08lx", rc, pBrush));
  2908. DebugExitDWORD(OECheckBrushIsSimple, rc);
  2909. return(rc);
  2910. }
  2911. //
  2912. // Function: OEClippingIsSimple
  2913. //
  2914. // Description: Check to see if the clipping on the graphics object is
  2915. // trivial
  2916. //
  2917. // Parameters: pco - CLIPOBJ of the graphics object to be checked.
  2918. //
  2919. // Returns: TRUE - Clipping is trivial
  2920. // FALSE - Clipping is complex
  2921. //
  2922. BOOL OEClippingIsSimple(CLIPOBJ* pco)
  2923. {
  2924. BOOL rc = TRUE;
  2925. DebugEntry(OEClippingIsSimple);
  2926. //
  2927. // Check for a valid clip object
  2928. //
  2929. if (pco == NULL)
  2930. {
  2931. TRACE_OUT(( "No clipobj"));
  2932. DC_QUIT;
  2933. }
  2934. //
  2935. // Check for complexity of clipping
  2936. //
  2937. switch (pco->iDComplexity)
  2938. {
  2939. case DC_TRIVIAL:
  2940. case DC_RECT:
  2941. //
  2942. // Trivial (ignore clipping) or simple (one square) clipping -
  2943. // no worries.
  2944. //
  2945. TRACE_OUT(( "Simple clipping"));
  2946. DC_QUIT;
  2947. default:
  2948. TRACE_OUT(( "Clipping is complex"));
  2949. break;
  2950. }
  2951. //
  2952. // Failed all tests - must be too complicated.
  2953. //
  2954. rc = FALSE;
  2955. DC_EXIT_POINT:
  2956. DebugExitDWORD(OEClippingIsSimple, rc);
  2957. return(rc);
  2958. }
  2959. //
  2960. // Function: OEClippingIsComplex
  2961. //
  2962. // Description: Check to see if the clipping on the graphics object is too
  2963. // complicated to be sent as an order or multiple orders.
  2964. //
  2965. // Parameters: pco - CLIPOBJ of the graphics object to be checked.
  2966. //
  2967. // Returns: TRUE - Clipping is too complicated
  2968. // FALSE - Clipping is sufficiently simple to send as orders
  2969. //
  2970. BOOL OEClippingIsComplex(CLIPOBJ* pco)
  2971. {
  2972. BOOL rc = FALSE;
  2973. BOOL fMoreRects;
  2974. OE_ENUMRECTS clip;
  2975. UINT numRects = 0;
  2976. DebugEntry(OEClippingIsComplex);
  2977. //
  2978. // If the any of the following are true, the clipping is not too
  2979. // complicated.
  2980. //
  2981. // 1) The clip object does not exist.
  2982. // 2) The clipping is trivial (the object exists, but there are no
  2983. // clipping rectangles).
  2984. // 3) The clipping is a single rectangle.
  2985. // 4) The object enumerates to less than 'n' rectangles.
  2986. //
  2987. //
  2988. // Check for a valid clip object
  2989. //
  2990. if (pco == NULL)
  2991. {
  2992. TRACE_OUT(( "No clipobj"));
  2993. DC_QUIT;
  2994. }
  2995. //
  2996. // Check for complexity of clipping
  2997. //
  2998. switch (pco->iDComplexity)
  2999. {
  3000. case DC_TRIVIAL:
  3001. case DC_RECT:
  3002. //
  3003. // Trivial or simple clipping - no worries.
  3004. //
  3005. TRACE_OUT(( "Simple clipping"));
  3006. DC_QUIT;
  3007. case DC_COMPLEX:
  3008. //
  3009. // Lots of rectangles - make sure that it is less than the
  3010. // acceptable limit.
  3011. // The documentation for this function incorrectly states that
  3012. // the returned value is the total number of rectangles
  3013. // comprising the clip region. In fact, -1 is always returned,
  3014. // even when the final parameter is non-zero. This means we
  3015. // have to enumerate to get the number of rects.
  3016. //
  3017. CLIPOBJ_cEnumStart(pco,
  3018. FALSE,
  3019. CT_RECTANGLES,
  3020. CD_ANY,
  3021. 0);
  3022. //
  3023. // MSDN: It is possible for CLIPOBJ_bEnum to return TRUE with
  3024. // the number of clipping rectangles equal to zero. In such
  3025. // cases, the driver should call CLIPOBJ_bEnum again without
  3026. // taking any action. Get as many rectangles as we permit for
  3027. // order encoding - this loop should execute once only.
  3028. // If the number of rects equals COMPLEX_CLIP_RECT_COUNT the
  3029. // 1st invocation of CLIPOBJ_bEnum returns that there are more
  3030. // rects and a second call returns there are no more without
  3031. // returning any in addition to those returned on the first
  3032. // call. Our buffer has space for COMPLEX_CLIP_RECT_COUNT+1
  3033. // rects so we should never have to execute the loop more than
  3034. // once.
  3035. //
  3036. do
  3037. {
  3038. fMoreRects = CLIPOBJ_bEnum(pco,
  3039. sizeof(clip),
  3040. (ULONG *)&clip.rects);
  3041. numRects += clip.rects.c;
  3042. } while ( fMoreRects && (numRects <= COMPLEX_CLIP_RECT_COUNT) );
  3043. //
  3044. // If there are no more rectangles in the clip region then the
  3045. // clipping complexity is within our limits for order encoding.
  3046. //
  3047. if ( numRects <= COMPLEX_CLIP_RECT_COUNT )
  3048. {
  3049. TRACE_OUT(( "Acceptable clipping %u", numRects));
  3050. DC_QUIT;
  3051. }
  3052. break;
  3053. default:
  3054. ERROR_OUT(( "Unknown clipping"));
  3055. break;
  3056. }
  3057. //
  3058. // Failed all tests - must be too complicated.
  3059. //
  3060. TRACE_OUT(( "Complex clipping"));
  3061. rc = TRUE;
  3062. DC_EXIT_POINT:
  3063. DebugExitDWORD(OEClippingIsComplex, rc);
  3064. return(rc);
  3065. }
  3066. //
  3067. // Function: OEAccumulateOutput
  3068. //
  3069. // Description: Check to see if we should accumulate this output for
  3070. // sending to the remote machine.
  3071. //
  3072. // Parameters: pso - Pointer to the target surface
  3073. // pco - Pointer to the clip object (may be NULL)
  3074. // pRect - Pointer to the bounding rectangle of the operation
  3075. //
  3076. // Returns: TRUE - We should accumulate the output
  3077. // FALSE - ignore the output
  3078. //
  3079. BOOL OEAccumulateOutput(SURFOBJ* pso, CLIPOBJ *pco, LPRECT pRect)
  3080. {
  3081. BOOL rc = FALSE;
  3082. POINT pt = {0,0};
  3083. ENUMRECTS clipRect;
  3084. LPOSI_PDEV ppdev = ((LPOSI_PDEV)pso->dhpdev);
  3085. DebugEntry(OEAccumulateOutput);
  3086. //
  3087. // Validate we have valid parameters to access the surface.
  3088. //
  3089. if (ppdev == NULL)
  3090. {
  3091. TRACE_OUT(( "NULL PDEV"));
  3092. DC_QUIT;
  3093. }
  3094. //
  3095. // Check for the screen surface, which will be a bitmap in the hosting
  3096. // only code.
  3097. //
  3098. if (ppdev->hsurfScreen != pso->hsurf)
  3099. {
  3100. TRACE_OUT(( "Dest is not our surface"));
  3101. DC_QUIT;
  3102. }
  3103. if (pso->dhsurf == NULL)
  3104. {
  3105. ERROR_OUT(( "NULL hSurf"));
  3106. DC_QUIT;
  3107. }
  3108. //
  3109. // Extract a single point from the clip object
  3110. //
  3111. if (pco == NULL)
  3112. {
  3113. //
  3114. // No clip object - use a point from the bounding rectangle
  3115. //
  3116. pt.x = pRect->left;
  3117. pt.y = pRect->top;
  3118. TRACE_OUT(( "No clip object, point is %d, %d", pt.x, pt.y));
  3119. }
  3120. else if (pco->iDComplexity == DC_TRIVIAL)
  3121. {
  3122. //
  3123. // Trivial clip object - use a point from the bounding rectangle
  3124. //
  3125. pt.x = pRect->left;
  3126. pt.y = pRect->top;
  3127. TRACE_OUT(( "Trivial clip object, point is %d, %d", pt.x, pt.y));
  3128. }
  3129. else if (pco->iDComplexity == DC_RECT)
  3130. {
  3131. //
  3132. // Single clip rectangle - use a point from it
  3133. //
  3134. // It appears that the clip rectangle is frequantly the entire
  3135. // display. This is about as much use as a chocolate teapot. If
  3136. // this is the case, use a point from the bounding rectangle
  3137. // instead.
  3138. //
  3139. if ((pco->rclBounds.left == 0) && (pco->rclBounds.top == 0))
  3140. {
  3141. pt.x = pRect->left;
  3142. pt.y = pRect->top;
  3143. TRACE_OUT(( "Meaningless clip rect, point is %d, %d",
  3144. pt.x, pt.y));
  3145. }
  3146. else
  3147. {
  3148. pt.x = pco->rclBounds.left;
  3149. pt.y = pco->rclBounds.top;
  3150. TRACE_OUT(( "Single clip rect, point is %d, %d", pt.x, pt.y));
  3151. }
  3152. }
  3153. else
  3154. {
  3155. //
  3156. // Complex clip object - enumerate its first rectangle and use a
  3157. // point from that.
  3158. //
  3159. TRACE_OUT(( "Complex clip rect - call cEnumStart"));
  3160. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  3161. clipRect.c = 1;
  3162. memset(clipRect.arcl, 0, sizeof(RECTL));
  3163. TRACE_OUT(( "Complex clip rect - call bEnum"));
  3164. CLIPOBJ_bEnum(pco, sizeof(clipRect), (ULONG *)(&clipRect));
  3165. pt.x = clipRect.arcl[0].left;
  3166. pt.y = clipRect.arcl[0].top;
  3167. TRACE_OUT(( "Complex clip rect, point is %d, %d", pt.x, pt.y));
  3168. }
  3169. //
  3170. // Check if we are accumulating this window.
  3171. //
  3172. rc = HET_DDOutputIsHosted(pt);
  3173. DC_EXIT_POINT:
  3174. TRACE_OUT(("OEAccumulateOutput: point {%d, %d} is %sshared",
  3175. pt.x, pt.y, (rc ? "" : "NOT ")));
  3176. DebugExitBOOL(OEAccumulateOutput, rc);
  3177. return(rc);
  3178. }
  3179. //
  3180. // Function: OEAccumulateOutputRect
  3181. //
  3182. // Description: Check to see if we should accumulate the given output rect
  3183. // for sending to the remote machine.
  3184. //
  3185. // Most drawing functions will use OEAccumulateOutput, which
  3186. // just checks for a single point within the hosted area.
  3187. // This function checks for any part of the given rectangle
  3188. // intersecting with the hosted area. It is currently only
  3189. // used by DrvSaveScreenBitmap - operations which may not
  3190. // lie completetely within the hosted area.
  3191. //
  3192. // Parameters: pso - Pointer to the target surface
  3193. // pRect - Pointer to the bounding rectangle of the operation
  3194. //
  3195. // Returns: TRUE - We should accumulate the output
  3196. // FALSE - ignore the output
  3197. //
  3198. BOOL OEAccumulateOutputRect( SURFOBJ* pso, LPRECT pRect)
  3199. {
  3200. BOOL rc = FALSE;
  3201. LPOSI_PDEV ppdev = ((LPOSI_PDEV)pso->dhpdev);
  3202. DebugEntry(OEAccumulateOutputRect);
  3203. //
  3204. // Validate we have valid parameters to access the surface.
  3205. //
  3206. if (ppdev == NULL)
  3207. {
  3208. TRACE_OUT(( "NULL PDEV"));
  3209. DC_QUIT;
  3210. }
  3211. //
  3212. // Check for the screen surface, which will be a bitmap in the hosting
  3213. // only code.
  3214. //
  3215. if (ppdev->hsurfScreen != pso->hsurf)
  3216. {
  3217. TRACE_OUT(( "Dest is not our surface"));
  3218. DC_QUIT;
  3219. }
  3220. if (pso->dhsurf == NULL)
  3221. {
  3222. ERROR_OUT(( "NULL hSurf"));
  3223. DC_QUIT;
  3224. }
  3225. //
  3226. // Check if we are accumulating this window.
  3227. //
  3228. rc = HET_DDOutputRectIsHosted(pRect);
  3229. DC_EXIT_POINT:
  3230. TRACE_OUT(("OEAccumulateOutputRect: rect {%d, %d, %d, %d} is %sshared",
  3231. pRect->left, pRect->top, pRect->right, pRect->bottom,
  3232. (rc ? "" : "NOT ")));
  3233. DebugExitBOOL(OEAccumulateOutputRect, rc);
  3234. return(rc);
  3235. }
  3236. //
  3237. // Function: OESendRop3AsOrder
  3238. //
  3239. // Description: Check if we are allowed to send this 3-way ROP. A ROP may
  3240. // be disallowed if it relies on the destination data.
  3241. //
  3242. // Parameters: rop3 - the 3-way ROP to be checked.
  3243. //
  3244. // Returns: TRUE - We are allowed to send this ROP
  3245. // FALSE - We can't send this ROP
  3246. //
  3247. BOOL OESendRop3AsOrder(BYTE rop3)
  3248. {
  3249. BOOL rc = TRUE;
  3250. DebugEntry(OESendRop3AsOrder);
  3251. //
  3252. // Rop 0x5F is used by MSDN to highlight search keywords. This XORs
  3253. // a pattern with the destination, producing markedly different (and
  3254. // sometimes unreadable) shadow output. We special-case no-encoding for
  3255. // it.
  3256. //
  3257. if (rop3 == 0x5F)
  3258. {
  3259. TRACE_OUT(("Rop3 0x5F never encoded"));
  3260. rc = FALSE;
  3261. }
  3262. DebugExitBOOL(OESendRop3AsOrder, rc);
  3263. return(rc);
  3264. }
  3265. //
  3266. // Function: OECheckFontIsSupported
  3267. //
  3268. // Description: Check if we are allowed to send this font. Fonts are
  3269. // disallowed while they are being negotiated on a new entry
  3270. // to the share.
  3271. //
  3272. // Parameters: pfo - (IN) the font to be checked
  3273. // pFontText - (IN) text message to be sent
  3274. // textLen - (IN) length of text message
  3275. // pFontHeight - (OUT) font height in points
  3276. // pFontAscender - (OUT) font ascender in points
  3277. // pFontWidth - (OUT) ave font width in points
  3278. // pFontWeight - (OUT) font weight
  3279. // pFontFlags - (OUT) font style flags
  3280. // pFontIndex - (OUT) font table index
  3281. // pSendDeltaX - (OUT) Do we need to send delta X coords?
  3282. //
  3283. // Returns: TRUE - We are allowed to send this font
  3284. // FALSE - We can't send this font
  3285. //
  3286. BOOL OECheckFontIsSupported
  3287. (
  3288. FONTOBJ* pfo,
  3289. LPSTR pFontText,
  3290. UINT textLen,
  3291. LPUINT pFontHeight,
  3292. LPUINT pFontAscender,
  3293. LPUINT pFontWidth,
  3294. LPUINT pFontWeight,
  3295. LPUINT pFontFlags,
  3296. LPUINT pFontIndex,
  3297. LPBOOL pSendDeltaX
  3298. )
  3299. {
  3300. BOOL rc = FALSE;
  3301. PIFIMETRICS pFontMetrics;
  3302. UINT codePage;
  3303. UINT i;
  3304. UINT iLocal;
  3305. UINT matchQuality;
  3306. UINT charWidthAdjustment = 0;
  3307. char fontName[FH_FACESIZE];
  3308. ULONG fontNameLen;
  3309. PWSTR pUnicodeString;
  3310. XFORMOBJ* pxform;
  3311. POINTL xformSize[3];
  3312. int compareResult;
  3313. FLOATOBJ_XFORM xformFloatData;
  3314. DebugEntry(OECheckFontIsSupported);
  3315. //
  3316. // Set up default return values
  3317. //
  3318. *pSendDeltaX = FALSE;
  3319. //
  3320. // Check that we have a valid list of font data from the remotes.
  3321. //
  3322. if (!g_oeTextEnabled)
  3323. {
  3324. TRACE_OUT(( "Fonts unavailable"));
  3325. DC_QUIT;
  3326. }
  3327. //
  3328. // Check for valid font attributes
  3329. //
  3330. pFontMetrics = FONTOBJ_pifi(pfo);
  3331. if (pFontMetrics->fsSelection & FM_SEL_OUTLINED)
  3332. {
  3333. TRACE_OUT(( "Unsupported font style"));
  3334. DC_QUIT;
  3335. }
  3336. //
  3337. // The current protocol cannot apply a general 2-D transform to text
  3338. // orders, so we must reject any weird ones such as:
  3339. //
  3340. // - rotations
  3341. // - X or Y shears
  3342. // - X or Y reflections
  3343. // - scaling with a negative value.
  3344. //
  3345. // Or put another way, we only allow:
  3346. //
  3347. // - the identity transformation
  3348. // - scaling with a positive value.
  3349. //
  3350. pxform = FONTOBJ_pxoGetXform(pfo);
  3351. if (pxform != NULL)
  3352. {
  3353. //
  3354. // Get the details of the transformation. Note we can ignore the
  3355. // translation vector as it does not affect the font sizing /
  3356. // orientation, so we are only interested in the matrix values...
  3357. //
  3358. //
  3359. // NOTE: Do NOT use floating point explicitly!
  3360. // Can't do float ops in ring 0 with normal lib for x86.
  3361. // Use FLOATOBJs instead and corresponding Eng services.
  3362. // On alpha, these are macros and are way fast in any case.
  3363. //
  3364. if (XFORMOBJ_iGetFloatObjXform(pxform, &xformFloatData) != DDI_ERROR)
  3365. {
  3366. //
  3367. // Rotations and shears will have cross dependencies on the x
  3368. // and y components.
  3369. //
  3370. if ( (!FLOATOBJ_EqualLong(&xformFloatData.eM12, 0)) ||
  3371. (!FLOATOBJ_EqualLong(&xformFloatData.eM21, 0)) )
  3372. {
  3373. TRACE_OUT(( "Rejected rotn/shear"));
  3374. DC_QUIT;
  3375. }
  3376. //
  3377. // Reflections and scaling operations with negative scale
  3378. // factors will have negative values on the leading diagonal of
  3379. // the matrix.
  3380. //
  3381. if ( (FLOATOBJ_LessThanLong(&xformFloatData.eM11, 0)) ||
  3382. (FLOATOBJ_LessThanLong(&xformFloatData.eM22, 0)) )
  3383. {
  3384. TRACE_OUT(( "Rejected refln/-ive"));
  3385. DC_QUIT;
  3386. }
  3387. }
  3388. }
  3389. //
  3390. // Get the current font code page for font matching.
  3391. //
  3392. switch (pFontMetrics->jWinCharSet)
  3393. {
  3394. case ANSI_CHARSET:
  3395. TRACE_OUT(( "ANSI font"));
  3396. codePage = NF_CP_WIN_ANSI;
  3397. break;
  3398. case OEM_CHARSET:
  3399. TRACE_OUT(( "OEM font"));
  3400. codePage = NF_CP_WIN_OEM;
  3401. break;
  3402. case SYMBOL_CHARSET:
  3403. TRACE_OUT(("Symbol font"));
  3404. codePage = NF_CP_WIN_SYMBOL;
  3405. break;
  3406. default:
  3407. TRACE_OUT(( "Unknown CP %d", pFontMetrics->jWinCharSet));
  3408. codePage = NF_CP_UNKNOWN;
  3409. break;
  3410. }
  3411. //
  3412. // Get the name of the font.
  3413. //
  3414. pUnicodeString = (PWSTR)( (LPBYTE)pFontMetrics +
  3415. pFontMetrics->dpwszFamilyName );
  3416. EngUnicodeToMultiByteN(fontName,
  3417. sizeof(fontName),
  3418. &fontNameLen,
  3419. pUnicodeString,
  3420. OEUnicodeStrlen(pUnicodeString));
  3421. //
  3422. // Search our Font Alias Table for the current family name. If we find
  3423. // it, replace it with the alias name from the table.
  3424. //
  3425. for (i = 0; i < NUM_ALIAS_FONTS; i++)
  3426. {
  3427. if (!strcmp((LPSTR)fontName,
  3428. (LPSTR)(fontAliasTable[i].pszOriginalFontName)))
  3429. {
  3430. TRACE_OUT(( "Alias name: %s -> %s",
  3431. (LPSTR)fontName,
  3432. (LPSTR)(fontAliasTable[i].pszAliasFontName)));
  3433. strcpy((LPSTR)fontName,
  3434. (LPSTR)(fontAliasTable[i].pszAliasFontName));
  3435. charWidthAdjustment = fontAliasTable[i].charWidthAdjustment;
  3436. break;
  3437. }
  3438. }
  3439. TRACE_OUT(( "Font name: '%s'", fontName));
  3440. //
  3441. // We have a font name to match with those we know to be available
  3442. // remotely. Try to jump straight to the first entry in the local font
  3443. // table starting with the same character as this font. If this index
  3444. // slot is empty (i.e. has a value of USHRT_MAX) then the loop will
  3445. // immediately exit
  3446. //
  3447. TRACE_OUT(( "Looking for matching fonts"));
  3448. for (iLocal = g_oeLocalFontIndex[(BYTE)fontName[0]];
  3449. iLocal < g_oeNumFonts;
  3450. iLocal++)
  3451. {
  3452. TRACE_OUT(( "Trying font number %hd", iLocal));
  3453. //
  3454. // If this font is not supported remotely then skip it.
  3455. //
  3456. ASSERT(g_poeLocalFonts);
  3457. matchQuality = g_poeLocalFonts[iLocal].SupportCode;
  3458. if (matchQuality == FH_SC_NO_MATCH)
  3459. {
  3460. continue;
  3461. }
  3462. //
  3463. // See if we've got a facename match
  3464. //
  3465. compareResult =
  3466. strcmp(g_poeLocalFonts[iLocal].Details.nfFaceName, fontName);
  3467. if (compareResult < 0)
  3468. {
  3469. //
  3470. // We haven't found a match yet, but we haven't gone far enough
  3471. // into this list.
  3472. //
  3473. continue;
  3474. }
  3475. else if (compareResult > 0)
  3476. {
  3477. //
  3478. // We're past the part of the local font array that's applicable.
  3479. // We didn't find a match, it must not exist.
  3480. //
  3481. break;
  3482. }
  3483. //
  3484. // The font names match. Now see if the other attributes do...
  3485. //
  3486. //
  3487. // This is looking promising - a font with the right name is
  3488. // supported on the remote system.
  3489. //
  3490. // Start building up the details in the global variables while
  3491. // making further checks...
  3492. //
  3493. *pFontFlags = 0;
  3494. *pFontIndex = iLocal;
  3495. *pFontWeight = pFontMetrics->usWinWeight;
  3496. //
  3497. // Check for a fixed pitch font.
  3498. //
  3499. if ((pFontMetrics->jWinPitchAndFamily & FIXED_PITCH) != 0)
  3500. {
  3501. *pFontFlags |= NF_FIXED_PITCH;
  3502. }
  3503. //
  3504. // Is it a TrueType font?
  3505. //
  3506. if ((pfo->flFontType & TRUETYPE_FONTTYPE) != 0)
  3507. {
  3508. *pFontFlags |= NF_TRUE_TYPE;
  3509. }
  3510. //
  3511. // Get the basic width and height.
  3512. //
  3513. xformSize[0].y = 0;
  3514. xformSize[0].x = 0;
  3515. xformSize[1].y = pFontMetrics->fwdUnitsPerEm;
  3516. xformSize[1].x = pFontMetrics->fwdAveCharWidth;
  3517. xformSize[2].y = pFontMetrics->fwdWinAscender;
  3518. xformSize[2].x = 0;
  3519. //
  3520. // We now need to convert these sizes if the GDI has provided a
  3521. // transform object.
  3522. //
  3523. if (pxform != NULL)
  3524. {
  3525. if (!XFORMOBJ_bApplyXform(pxform,
  3526. XF_LTOL,
  3527. 3,
  3528. xformSize,
  3529. xformSize))
  3530. {
  3531. ERROR_OUT(( "Xform failed"));
  3532. continue;
  3533. }
  3534. }
  3535. //
  3536. // Calculate the font width and height.
  3537. //
  3538. *pFontHeight = (UINT)(xformSize[1].y - xformSize[0].y);
  3539. *pFontWidth = (UINT)(xformSize[1].x - xformSize[0].x
  3540. - charWidthAdjustment);
  3541. TRACE_OUT(( "Device font size %hdx%hd", *pFontWidth, *pFontHeight));
  3542. //
  3543. // Get the offset to the start of the text cell.
  3544. //
  3545. *pFontAscender = (UINT)(xformSize[2].y - xformSize[0].y);
  3546. //
  3547. // Check that we have a matching pair - where we require that the
  3548. // fonts (ie the one being used by the application and the one
  3549. // we've matched with the remote system) are the same pitch (ie
  3550. // variable or fixed) and use the same technology (ie TrueType or
  3551. // not).
  3552. //
  3553. if ((g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_FIXED_PITCH) !=
  3554. ((TSHR_UINT16)(*pFontFlags) & NF_FIXED_PITCH))
  3555. {
  3556. TRACE_OUT(( "Fixed pitch mismatch"));
  3557. continue;
  3558. }
  3559. if ((g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_TRUE_TYPE) !=
  3560. ((TSHR_UINT16)*pFontFlags & NF_TRUE_TYPE))
  3561. {
  3562. TRACE_OUT(( "True type mismatch"));
  3563. continue;
  3564. }
  3565. //
  3566. // We have a pair of fonts with the same attributes - either both
  3567. // fixed pitch or both variable pitch - and using the same font
  3568. // technology.
  3569. //
  3570. // If the font is fixed pitch then we must also check that this
  3571. // particular size matches.
  3572. //
  3573. // If the font is not fixed pitch (scalable) then we assume that it
  3574. // is matchable.
  3575. //
  3576. if (g_poeLocalFonts[iLocal].Details.nfFontFlags & NF_FIXED_SIZE)
  3577. {
  3578. //
  3579. // The font is fixed size, so we must check that this
  3580. // particular size is matchable.
  3581. //
  3582. if ( (*pFontHeight != g_poeLocalFonts[iLocal].Details.nfAveHeight) ||
  3583. (*pFontWidth != g_poeLocalFonts[iLocal].Details.nfAveWidth) )
  3584. {
  3585. //
  3586. // The sizes differ, so we must fail this match.
  3587. //
  3588. TRACE_OUT(( "Size mismatch"));
  3589. continue;
  3590. }
  3591. }
  3592. //
  3593. // Hey! We've got a matched pair!
  3594. //
  3595. rc = TRUE;
  3596. TRACE_OUT(( "Found match at local font %hd", iLocal));
  3597. break;
  3598. }
  3599. if (rc != TRUE)
  3600. {
  3601. TRACE_OUT(( "Couldn't find matching font in table"));
  3602. DC_QUIT;
  3603. }
  3604. //
  3605. // Build up the rest of the font flags. We have already put the pitch
  3606. // flag in place.
  3607. //
  3608. if ( ((pFontMetrics->fsSelection & FM_SEL_ITALIC) != 0) ||
  3609. ((pfo->flFontType & FO_SIM_ITALIC) != 0) )
  3610. {
  3611. TRACE_OUT(( "Italic"));
  3612. *pFontFlags |= NF_ITALIC;
  3613. }
  3614. if ((pFontMetrics->fsSelection & FM_SEL_UNDERSCORE) != 0)
  3615. {
  3616. TRACE_OUT(( "Underline"));
  3617. *pFontFlags |= NF_UNDERLINE;
  3618. }
  3619. if ((pFontMetrics->fsSelection & FM_SEL_STRIKEOUT) != 0)
  3620. {
  3621. TRACE_OUT(( "Strikeout"));
  3622. *pFontFlags |= NF_STRIKEOUT;
  3623. }
  3624. //
  3625. // It is possible to have a font made bold by Windows, i.e. the
  3626. // standard font definition is not bold, but windows manipulates the
  3627. // font data to create a bold effect. This is marked by the
  3628. // FO_SIM_BOLD flag.
  3629. //
  3630. // In this case we need to ensure that the font flags are marked as
  3631. // bold according to the weight.
  3632. //
  3633. if ( ((pfo->flFontType & FO_SIM_BOLD) != 0) &&
  3634. ( pFontMetrics->usWinWeight < FW_BOLD) )
  3635. {
  3636. TRACE_OUT(( "Upgrading weight for a bold font"));
  3637. *pFontWeight = FW_BOLD;
  3638. }
  3639. //
  3640. // If the font is an exact match, or if it is an approximate match for
  3641. // its entire range (0x00 to 0xFF) then send it happily. If not...only
  3642. // send chars within the range 0x20->0x7F ("true ASCII").
  3643. //
  3644. ASSERT(g_poeLocalFonts);
  3645. if (codePage != g_poeLocalFonts[iLocal].Details.nfCodePage)
  3646. {
  3647. TRACE_OUT(( "Using different CP: downgrade to APPROX_ASC"));
  3648. matchQuality = FH_SC_APPROX_ASCII_MATCH;
  3649. }
  3650. //
  3651. // If we don't have an exact match, check the individual characters.
  3652. //
  3653. if ( (matchQuality != FH_SC_EXACT_MATCH ) &&
  3654. (matchQuality != FH_SC_APPROX_MATCH) )
  3655. {
  3656. //
  3657. // The approximate match is only valid if we use a font that
  3658. // supports the ANSI character set.
  3659. //
  3660. if ((pFontMetrics->jWinCharSet & ANSI_CHARSET) != 0)
  3661. {
  3662. TRACE_OUT(( "Cannot do match without ANSI support"));
  3663. DC_QUIT;
  3664. }
  3665. //
  3666. // This font is not a good match across its entire range. Check
  3667. // that all chars are within the desired range.
  3668. //
  3669. for (i = 0; i < textLen; i++)
  3670. {
  3671. if ( (pFontText[i] == 0) ||
  3672. ( (pFontText[i] >= NF_ASCII_FIRST) &&
  3673. (pFontText[i] <= NF_ASCII_LAST) ) )
  3674. {
  3675. continue;
  3676. }
  3677. //
  3678. // Can only get here by finding a char outside our acceptable
  3679. // range.
  3680. //
  3681. TRACE_OUT(( "found non ASCII char %x", pFontText[i]));
  3682. DC_QUIT;
  3683. }
  3684. }
  3685. //
  3686. // We have a valid font. Now sort out delta X issues.
  3687. //
  3688. //
  3689. // If we do not need to send delta X arrays then exit now.
  3690. //
  3691. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_ALWAYS))
  3692. {
  3693. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_SOMETIMES))
  3694. {
  3695. //
  3696. // CAPS_FONT_NEED_X_SOMETIMES and CAPS_FONT_NEED_X_ALWAYS are
  3697. // both not set so we can exit now. (We do not need a delta X
  3698. // array).
  3699. //
  3700. TRACE_OUT(( "Capabilities eliminated delta X"));
  3701. DC_QUIT;
  3702. }
  3703. //
  3704. // CAPS_FONT_NEED_X_SOMETIMES is set and CAPS_FONT_NEED_X_ALWAYS is
  3705. // not set. In this case whether we need a delta X is determined
  3706. // by whether the font is an exact match or an approximate match
  3707. // (because of either approximation of name, signature, or aspect
  3708. // ratio). We can only find this out after we have extracted the
  3709. // font handle from the existing order.
  3710. //
  3711. }
  3712. //
  3713. // If the string is a single character (or less) then we can just
  3714. // return.
  3715. //
  3716. if (textLen <= 1)
  3717. {
  3718. TRACE_OUT(( "String only %lu long", textLen));
  3719. DC_QUIT;
  3720. }
  3721. //
  3722. // Capabilities allow us to ignore delta X position if we have an exact
  3723. // match.
  3724. //
  3725. if ((matchQuality & FH_SC_EXACT) != 0)
  3726. {
  3727. //
  3728. // Exit immediately, providing that there is no override to always
  3729. // send increments.
  3730. //
  3731. if (!(g_oeFontCaps & CAPS_FONT_NEED_X_ALWAYS))
  3732. {
  3733. TRACE_OUT(( "Font has exact match"));
  3734. DC_QUIT;
  3735. }
  3736. }
  3737. //
  3738. // We have passed all the checks - we must send a delta X array.
  3739. //
  3740. TRACE_OUT(( "Must send delta X"));
  3741. *pSendDeltaX = TRUE;
  3742. DC_EXIT_POINT:
  3743. DebugExitDWORD(OECheckFontIsSupported, rc);
  3744. return(rc);
  3745. }
  3746. //
  3747. // Function: OELPtoVirtual
  3748. //
  3749. // Description: Adjusts window coordinates to virtual desktop coordinates.
  3750. // Clips the result to [+32766, -32768].
  3751. //
  3752. // Parameters: pPoints - Array of points to be converted
  3753. // cPoints - Number of points to be converted
  3754. //
  3755. // Returns: (none)
  3756. //
  3757. void OELPtoVirtual
  3758. (
  3759. LPPOINT aPts,
  3760. UINT cPts
  3761. )
  3762. {
  3763. int l;
  3764. TSHR_INT16 s;
  3765. DebugEntry(OELPtoVirtual);
  3766. //
  3767. // Convert to screen coordinates
  3768. //
  3769. while (cPts > 0)
  3770. {
  3771. //
  3772. // Look for int16 overflow in the X coordinate
  3773. //
  3774. l = aPts->x;
  3775. s = (TSHR_INT16)l;
  3776. if (l == (int)s)
  3777. {
  3778. aPts->x = s;
  3779. }
  3780. else
  3781. {
  3782. //
  3783. // HIWORD(l) will be 1 for positive overflow, 0xFFFF for
  3784. // negative overflow. Therefore we will get 0x7FFE or 0x8000
  3785. // (+32766 or -32768).
  3786. //
  3787. aPts->x = 0x7FFF - HIWORD(l);
  3788. TRACE_OUT(("adjusted X from %ld to %d", l, aPts->x));
  3789. }
  3790. //
  3791. // Look for int16 overflow in the Y coordinate
  3792. //
  3793. l = aPts->y;
  3794. s = (TSHR_INT16)l;
  3795. if (l == (int)s)
  3796. {
  3797. aPts->y = s;
  3798. }
  3799. else
  3800. {
  3801. //
  3802. // HIWORD(l) will be 1 for positive overflow, 0xFFFF for
  3803. // negative overflow. Therefore we will get 0x7FFE or 0x8000
  3804. // (+32766 or -32768).
  3805. //
  3806. aPts->y = 0x7FFF - HIWORD(l);
  3807. TRACE_OUT(("adjusted Y from %ld to %d", l, aPts->y));
  3808. }
  3809. //
  3810. // Move on to the next point
  3811. //
  3812. --cPts;
  3813. ++aPts;
  3814. }
  3815. DebugExitVOID(OELPtoVirtual);
  3816. }
  3817. //
  3818. // Function: OELRtoVirtual
  3819. //
  3820. // Description: Adjusts RECT in window coordinates to virtual coordinates.
  3821. // Clips the result to [+32766, -32768].
  3822. //
  3823. // Parameters: pRects - Array of rects to be converted
  3824. // numRects - Number of rects to be converted
  3825. //
  3826. // Returns: (none)
  3827. //
  3828. // NB. This function takes a Windows rectangle (exclusive coords) and
  3829. // returns a DC-Share rectangle (inclusive coords).
  3830. //
  3831. void OELRtoVirtual
  3832. (
  3833. LPRECT aRects,
  3834. UINT cRects
  3835. )
  3836. {
  3837. DebugEntry(OELRtoVirtual);
  3838. //
  3839. // Convert the points to screen coords, clipping to INT16s
  3840. //
  3841. OELPtoVirtual((LPPOINT)aRects, 2 * cRects);
  3842. //
  3843. // Make each rectangle inclusive
  3844. //
  3845. while (cRects > 0)
  3846. {
  3847. aRects->right--;
  3848. aRects->bottom--;
  3849. //
  3850. // Move on to the next rect
  3851. //
  3852. cRects--;
  3853. aRects++;
  3854. }
  3855. DebugExitVOID(OELRtoVirtual);
  3856. }
  3857. //
  3858. // Function: OEClipAndAddOrder
  3859. //
  3860. // Description: Adds the order to the order buffer, splitting it up into
  3861. // multiple orders if the clipping is complicated. If we fail
  3862. // to send the full order, we accumulate it in the SDA instead
  3863. //
  3864. // Parameters: pOrder - Order to be stored.
  3865. // pExtraInfo - Pointer to extra data associated with the
  3866. // order. This data depends on the order type,
  3867. // and may be NULL.
  3868. // pco - Clipping object for the area
  3869. //
  3870. // Returns: (none)
  3871. //
  3872. void OEClipAndAddOrder(LPINT_ORDER pOrder,
  3873. void * pExtraInfo,
  3874. CLIPOBJ* pco)
  3875. {
  3876. BOOL fOrderClipped;
  3877. BOOL fMoreRects;
  3878. RECT clippedRect;
  3879. RECT orderRect;
  3880. LPINT_ORDER pNewOrder;
  3881. LPINT_ORDER pLastOrder = NULL;
  3882. OE_ENUMRECTS clip;
  3883. UINT i;
  3884. UINT numRects = 0;
  3885. DebugEntry(OEClipAndAddOrder);
  3886. //
  3887. // Convert the order rectangle passed in (in virtual co-ordinates) back
  3888. // to screen co-ordinates. It is going to be clipped against clip
  3889. // rectangles returned to us in screen co-ordinates.
  3890. //
  3891. // Note that we also convert to exclusive coords here to make
  3892. // comparison with the exclusive Windows coords easier.
  3893. //
  3894. orderRect.left = pOrder->OrderHeader.Common.rcsDst.left;
  3895. orderRect.top = pOrder->OrderHeader.Common.rcsDst.top;
  3896. orderRect.right = pOrder->OrderHeader.Common.rcsDst.right + 1;
  3897. orderRect.bottom = pOrder->OrderHeader.Common.rcsDst.bottom + 1;
  3898. fOrderClipped = FALSE;
  3899. TRACE_OUT(( "orderRect: (%d,%d)(%d,%d)",
  3900. orderRect.left,
  3901. orderRect.top,
  3902. orderRect.right,
  3903. orderRect.bottom));
  3904. //
  3905. // Check if we have a clipping object at all.
  3906. //
  3907. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  3908. {
  3909. //
  3910. // No clipping object - just use the bounds
  3911. //
  3912. clippedRect = orderRect;
  3913. fOrderClipped = TRUE;
  3914. pLastOrder = pOrder;
  3915. }
  3916. else if (pco->iDComplexity == DC_RECT)
  3917. {
  3918. //
  3919. // One clipping rectangle - use it directly.
  3920. //
  3921. RECT_FROM_RECTL(clippedRect, pco->rclBounds);
  3922. clippedRect.left = max(clippedRect.left, orderRect.left);
  3923. clippedRect.bottom = min(clippedRect.bottom, orderRect.bottom);
  3924. clippedRect.right = min(clippedRect.right, orderRect.right);
  3925. clippedRect.top = max(clippedRect.top, orderRect.top);
  3926. fOrderClipped = TRUE;
  3927. pLastOrder = pOrder;
  3928. }
  3929. else
  3930. {
  3931. //
  3932. // OA can only cope as long as the orders are added in the same
  3933. // order that they were allocated, so we need to do a little
  3934. // shuffling here.
  3935. //
  3936. // We always keep one order outstanding (pLastOrder) and a flag to
  3937. // indicate if it is valid (fOrderClipped). The first time we find
  3938. // a valid clipping rectangle, we set up pLastOrder and
  3939. // fOrderClipped. If we find we need to allocate a new order, we
  3940. // request the memory for the new order (pNewOrder), add pLastOrder
  3941. // and store pNewOrder in pLastOrder.
  3942. //
  3943. // Once we have finished enumerating the clipping rectangles, if
  3944. // pLastOrder is valid, we add it in.
  3945. //
  3946. // Also, while we are adding all these orders, OA must not purge
  3947. // the order heap otherwise we'll be left holding an invalid
  3948. // pointer.
  3949. //
  3950. pNewOrder = pOrder;
  3951. g_oaPurgeAllowed = FALSE;
  3952. //
  3953. // Multiple clipping rectangles - Enumerate all the rectangles
  3954. // involved in this drawing operation.
  3955. // The documentation for this function incorrectly states that
  3956. // the returned value is the total number of rectangles
  3957. // comprising the clip region. In fact, -1 is always returned,
  3958. // even when the final parameter is non-zero.
  3959. //
  3960. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  3961. //
  3962. // Get the clip rectangles. We fetch these into the clip buffer
  3963. // which is big enough to get all the clip rectangles we expect + 1.
  3964. // If the order runs across this number of clip rects or more then
  3965. // we will already have decided to send it as screen data.
  3966. // The clip rectangle fetching is contained within a loop because,
  3967. // while we expect to call CLIPOBJ_bEnum once only, it is possible
  3968. // for this functio to return zero rects and report that there are
  3969. // more to fetch (according to MSDN).
  3970. //
  3971. do
  3972. {
  3973. fMoreRects = CLIPOBJ_bEnum(pco,
  3974. sizeof(clip),
  3975. (ULONG *)&clip.rects);
  3976. //
  3977. // The clipping object can decide that there are no more
  3978. // rectangles and that this query has returned no rectangles,
  3979. // so we must check for any valid data in the returned
  3980. // rectangle list.
  3981. //
  3982. if (clip.rects.c == 0)
  3983. {
  3984. //
  3985. // We didn't get any rects this time so go round again - if
  3986. // we're finished, the loop termination condition will take
  3987. // us out. CLIPOBJ_bEnum can return a count of zero when
  3988. // there are still more rects.
  3989. //
  3990. TRACE_OUT(( "No rects this time, more %u", fMoreRects));
  3991. continue;
  3992. }
  3993. //
  3994. // To get to here we expect to have fetched all the rects and
  3995. // no more. Do a quick check.
  3996. //
  3997. numRects += clip.rects.c;
  3998. ASSERT( (numRects <= COMPLEX_CLIP_RECT_COUNT) );
  3999. //
  4000. // Process each clip rectangle by clipping the drawing order to
  4001. // it.
  4002. //
  4003. for ( i = 0; i < clip.rects.c; i++ )
  4004. {
  4005. TRACE_OUT(( " (%d,%d)(%d,%d)",
  4006. clip.rects.arcl[i].left,
  4007. clip.rects.arcl[i].top,
  4008. clip.rects.arcl[i].right,
  4009. clip.rects.arcl[i].bottom));
  4010. //
  4011. // Check for an intersection
  4012. //
  4013. if ( (clip.rects.arcl[i].left >= orderRect.right) ||
  4014. (clip.rects.arcl[i].bottom <= orderRect.top) ||
  4015. (clip.rects.arcl[i].right <= orderRect.left) ||
  4016. (clip.rects.arcl[i].top >= orderRect.bottom) )
  4017. {
  4018. //
  4019. // No intersection, move on to next clip rect.
  4020. //
  4021. continue;
  4022. }
  4023. //
  4024. // There is an intersection, so we may need to add a new
  4025. // order to the buffer to cater for this rectangle.
  4026. //
  4027. if (fOrderClipped)
  4028. {
  4029. //
  4030. // The order has already been clipped once, so it
  4031. // actually intersects more than one clip rect, ie
  4032. // fOrderClipped is always FALSE for at least the first
  4033. // clip rectangle in the clip.rects buffer. We cope
  4034. // with this by duplicating the order and clipping it
  4035. // again.
  4036. //
  4037. pNewOrder = OA_DDAllocOrderMem(
  4038. pLastOrder->OrderHeader.Common.cbOrderDataLength, 0);
  4039. if (pNewOrder == NULL)
  4040. {
  4041. WARNING_OUT(( "Order memory allocation failed" ));
  4042. goto CLIP_ORDER_FAILED;
  4043. }
  4044. //
  4045. // Copy the header & data from the original order to
  4046. // the new order (making sure that we don't overwrite
  4047. // the list information at the start of the header).
  4048. //
  4049. memcpy((LPBYTE)pNewOrder
  4050. + FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4051. (LPBYTE)pLastOrder
  4052. + FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4053. pLastOrder->OrderHeader.Common.cbOrderDataLength
  4054. + sizeof(INT_ORDER_HEADER)
  4055. - FIELD_SIZE(INT_ORDER, OrderHeader.list));
  4056. //
  4057. // Set the destination (clip) rectangle (in virtual
  4058. // desktop coordinates).
  4059. //
  4060. TSHR_RECT16_FROM_RECT(
  4061. &pLastOrder->OrderHeader.Common.rcsDst,
  4062. clippedRect);
  4063. pLastOrder->OrderHeader.Common.rcsDst.right -= 1;
  4064. pLastOrder->OrderHeader.Common.rcsDst.bottom -= 1;
  4065. TRACE_OUT(( "Adding duplicate order (%d,%d) (%d,%d)",
  4066. pLastOrder->OrderHeader.Common.rcsDst.left,
  4067. pLastOrder->OrderHeader.Common.rcsDst.top,
  4068. pLastOrder->OrderHeader.Common.rcsDst.right,
  4069. pLastOrder->OrderHeader.Common.rcsDst.bottom));
  4070. //
  4071. // Add the order to the Order List.
  4072. //
  4073. OA_DDAddOrder(pLastOrder, pExtraInfo);
  4074. }
  4075. //
  4076. // Update the clipping rectangle for the order to be sent.
  4077. //
  4078. clippedRect.left = max(clip.rects.arcl[i].left,
  4079. orderRect.left);
  4080. clippedRect.bottom= min(clip.rects.arcl[i].bottom,
  4081. orderRect.bottom);
  4082. clippedRect.right = min(clip.rects.arcl[i].right,
  4083. orderRect.right);
  4084. clippedRect.top = max(clip.rects.arcl[i].top,
  4085. orderRect.top);
  4086. fOrderClipped = TRUE;
  4087. pLastOrder = pNewOrder;
  4088. }
  4089. } while (fMoreRects);
  4090. }
  4091. //
  4092. // Check whether the clipping has removed the order entirely.
  4093. //
  4094. if (fOrderClipped)
  4095. {
  4096. TSHR_RECT16_FROM_RECT(&pLastOrder->OrderHeader.Common.rcsDst,
  4097. clippedRect);
  4098. pLastOrder->OrderHeader.Common.rcsDst.right -= 1;
  4099. pLastOrder->OrderHeader.Common.rcsDst.bottom -= 1;
  4100. TRACE_OUT(( "Adding order (%d,%d) (%d,%d)",
  4101. pLastOrder->OrderHeader.Common.rcsDst.left,
  4102. pLastOrder->OrderHeader.Common.rcsDst.top,
  4103. pLastOrder->OrderHeader.Common.rcsDst.right,
  4104. pLastOrder->OrderHeader.Common.rcsDst.bottom));
  4105. //
  4106. // Add the order to the Order List.
  4107. //
  4108. OA_DDAddOrder(pLastOrder, pExtraInfo);
  4109. }
  4110. else
  4111. {
  4112. TRACE_OUT(( "Order clipped completely"));
  4113. OA_DDFreeOrderMem(pOrder);
  4114. }
  4115. DC_QUIT;
  4116. CLIP_ORDER_FAILED:
  4117. //
  4118. // Allocation of memory for a duplicate order failed. Just add the
  4119. // original order's destination rect into the SDA and free the order.
  4120. //
  4121. // The order rectangle is already in inclusive virtual coordinates.
  4122. //
  4123. TRACE_OUT(( "Order add failed, add to SDA"));
  4124. RECT_FROM_TSHR_RECT16(&orderRect,pLastOrder->OrderHeader.Common.rcsDst);
  4125. OA_DDFreeOrderMem(pLastOrder);
  4126. BA_AddScreenData(&orderRect);
  4127. DC_EXIT_POINT:
  4128. //
  4129. // Make sure that we always re-enable heap purging.
  4130. //
  4131. g_oaPurgeAllowed = TRUE;
  4132. DebugExitVOID(OEClipAndAddOrder);
  4133. }
  4134. //
  4135. // Function: OEClipAndAddScreenData
  4136. //
  4137. // Description: Determines if we need to accumulate any screen data for the
  4138. // specified area. If so, it is added to the SDA.
  4139. //
  4140. // Parameters: pRect - Bounding rectangle of area to be accumulated
  4141. // pco - Clipping object for the area
  4142. //
  4143. // Returns: (none)
  4144. //
  4145. void OEClipAndAddScreenData(LPRECT pRect, CLIPOBJ* pco)
  4146. {
  4147. RECT SDACandidate;
  4148. BOOL fMoreRects;
  4149. RECT clippedRect;
  4150. OE_ENUMRECTS clip;
  4151. UINT i;
  4152. DebugEntry(OEClipAndAddScreenData);
  4153. //
  4154. // Convert the order rectangle passed in (in virtual co-ordinates) back
  4155. // to screen co-ordinates. It is going to be clipped against clip
  4156. // rectangles returned to us in screen co-ordinates.
  4157. //
  4158. // Note that we also convert to exclusive coords here to make
  4159. // comparison with the exclusive Windows coords easier.
  4160. //
  4161. SDACandidate.left = pRect->left;
  4162. SDACandidate.top = pRect->top;
  4163. SDACandidate.right = pRect->right + 1;
  4164. SDACandidate.bottom = pRect->bottom + 1;
  4165. TRACE_OUT(( "SDACandidate: (%d,%d)(%d,%d)",
  4166. SDACandidate.left,
  4167. SDACandidate.top,
  4168. SDACandidate.right,
  4169. SDACandidate.bottom));
  4170. //
  4171. // Check if we have a clipping object at all.
  4172. //
  4173. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  4174. {
  4175. //
  4176. // Convert the clipped rect into Virtual Desktop coords.
  4177. //
  4178. clippedRect = SDACandidate;
  4179. clippedRect.right -= 1;
  4180. clippedRect.bottom -= 1;
  4181. //
  4182. // Add the clipped rect into the SDA.
  4183. //
  4184. TRACE_OUT(( "Adding SDA (%d,%d)(%d,%d)", clippedRect.left,
  4185. clippedRect.top,
  4186. clippedRect.right,
  4187. clippedRect.bottom));
  4188. BA_AddScreenData(&clippedRect);
  4189. }
  4190. else if (pco->iDComplexity == DC_RECT)
  4191. {
  4192. //
  4193. // One clipping rectangle - use it directly, converting into
  4194. // Virtual Desktop coords. Make sure the rectangle is valid before
  4195. // adding to the SDA.
  4196. //
  4197. RECT_FROM_RECTL(clippedRect, pco->rclBounds);
  4198. clippedRect.left = max(clippedRect.left, SDACandidate.left);
  4199. clippedRect.right = min(clippedRect.right, SDACandidate.right) + -1;
  4200. if ( clippedRect.left <= clippedRect.right )
  4201. {
  4202. clippedRect.bottom = min(clippedRect.bottom,
  4203. SDACandidate.bottom) + -1;
  4204. clippedRect.top = max(clippedRect.top, SDACandidate.top);
  4205. if ( clippedRect.bottom >= clippedRect.top )
  4206. {
  4207. //
  4208. // Add the clipped rect into the SDA.
  4209. //
  4210. TRACE_OUT(( "Adding SDA RECT (%d,%d)(%d,%d)",
  4211. clippedRect.left,
  4212. clippedRect.top,
  4213. clippedRect.right,
  4214. clippedRect.bottom));
  4215. BA_AddScreenData(&clippedRect);
  4216. }
  4217. }
  4218. }
  4219. else
  4220. {
  4221. //
  4222. // Enumerate all the rectangles involved in this drawing operation.
  4223. // The documentation for this function incorrectly states that
  4224. // the returned value is the total number of rectangles
  4225. // comprising the clip region. In fact, -1 is always returned,
  4226. // even when the final parameter is non-zero.
  4227. //
  4228. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  4229. do
  4230. {
  4231. //
  4232. // Get the next batch of clipping rectangles
  4233. //
  4234. fMoreRects = CLIPOBJ_bEnum(pco,
  4235. sizeof(clip),
  4236. (ULONG *)&clip.rects);
  4237. for ( i = 0; i < clip.rects.c; i++ )
  4238. {
  4239. TRACE_OUT(( " (%d,%d)(%d,%d)",
  4240. clip.rects.arcl[i].left,
  4241. clip.rects.arcl[i].top,
  4242. clip.rects.arcl[i].right,
  4243. clip.rects.arcl[i].bottom));
  4244. //
  4245. // Intersect the SDA rect with the clip rect, checking for
  4246. // no intersection.
  4247. //
  4248. clippedRect.left = max( clip.rects.arcl[i].left,
  4249. SDACandidate.left );
  4250. clippedRect.right = min( clip.rects.arcl[i].right,
  4251. SDACandidate.right );
  4252. if (clippedRect.left >= clippedRect.right)
  4253. {
  4254. //
  4255. // No horizontal intersection.
  4256. //
  4257. continue;
  4258. }
  4259. clippedRect.bottom = min( clip.rects.arcl[i].bottom,
  4260. SDACandidate.bottom );
  4261. clippedRect.top = max( clip.rects.arcl[i].top,
  4262. SDACandidate.top );
  4263. if (clippedRect.top >= clippedRect.bottom)
  4264. {
  4265. //
  4266. // No vertical intersection.
  4267. //
  4268. continue;
  4269. }
  4270. //
  4271. // Convert the clipped rect into Virtual Desktop coords.
  4272. //
  4273. clippedRect.right -= 1;
  4274. clippedRect.bottom -= 1;
  4275. //
  4276. // Add the clipped rect into the SDA.
  4277. //
  4278. TRACE_OUT(( "Adding SDA (%d,%d)(%d,%d)",
  4279. clippedRect.left,
  4280. clippedRect.top,
  4281. clippedRect.right,
  4282. clippedRect.bottom));
  4283. BA_AddScreenData(&clippedRect);
  4284. }
  4285. } while (fMoreRects);
  4286. }
  4287. DebugExitVOID(OEClipAndAddScreenData);
  4288. }
  4289. //
  4290. // FUNCTION: OEDDSetNewFonts
  4291. //
  4292. // DESCRIPTION:
  4293. //
  4294. // Set the new font handling information to be used by the display driver.
  4295. //
  4296. // RETURNS:
  4297. //
  4298. // NONE
  4299. //
  4300. //
  4301. void OEDDSetNewFonts(LPOE_NEW_FONTS pRequest)
  4302. {
  4303. UINT cbNewSize;
  4304. DebugEntry(OEDDSetNewFonts);
  4305. TRACE_OUT(( "New fonts %d", pRequest->countFonts));
  4306. //
  4307. // Initialize new number of fonts to zero in case an error happens.
  4308. // We don't want to use stale font info if so.
  4309. //
  4310. g_oeNumFonts = 0;
  4311. g_oeFontCaps = pRequest->fontCaps;
  4312. //
  4313. // Free our previous font block if we had one.
  4314. //
  4315. if (g_poeLocalFonts)
  4316. {
  4317. EngFreeMem(g_poeLocalFonts);
  4318. g_poeLocalFonts = NULL;
  4319. }
  4320. //
  4321. // Alloc a new one, the size of the new font block.
  4322. //
  4323. cbNewSize = pRequest->countFonts * sizeof(LOCALFONT);
  4324. g_poeLocalFonts = EngAllocMem(0, cbNewSize, OSI_ALLOC_TAG);
  4325. if (! g_poeLocalFonts)
  4326. {
  4327. ERROR_OUT(("OEDDSetNewFonts: can't allocate space for font info"));
  4328. DC_QUIT;
  4329. }
  4330. //
  4331. // OK, if we're here, this is going to succeed. Copy the info over.
  4332. //
  4333. g_oeNumFonts = pRequest->countFonts;
  4334. memcpy(g_poeLocalFonts, pRequest->fontData, cbNewSize);
  4335. memcpy(g_oeLocalFontIndex, pRequest->fontIndex,
  4336. sizeof(g_oeLocalFontIndex[0]) * FH_LOCAL_INDEX_SIZE);
  4337. DC_EXIT_POINT:
  4338. DebugExitVOID(OEDDSetNewFonts);
  4339. }
  4340. //
  4341. // FUNCTION: OEDDSetNewCapabilities
  4342. //
  4343. // DESCRIPTION:
  4344. //
  4345. // Set the new OE related capabilities
  4346. //
  4347. // RETURNS:
  4348. //
  4349. // NONE
  4350. //
  4351. // PARAMETERS:
  4352. //
  4353. // pDataIn - pointer to the input buffer
  4354. //
  4355. //
  4356. void OEDDSetNewCapabilities(LPOE_NEW_CAPABILITIES pCapabilities)
  4357. {
  4358. DebugEntry(OEDDSetNewCapabilities);
  4359. //
  4360. // Copy the data from the Share Core.
  4361. //
  4362. g_oeBaselineTextEnabled = pCapabilities->baselineTextEnabled;
  4363. g_oeSendOrders = pCapabilities->sendOrders;
  4364. g_oeTextEnabled = pCapabilities->textEnabled;
  4365. //
  4366. // The share core has passed down a pointer to it's copy of the order
  4367. // support array. We take a copy for the kernel here.
  4368. //
  4369. memcpy(g_oeOrderSupported,
  4370. pCapabilities->orderSupported,
  4371. sizeof(g_oeOrderSupported));
  4372. TRACE_OUT(( "OE caps: BLT %c Orders %c Text %c",
  4373. g_oeBaselineTextEnabled ? 'Y': 'N',
  4374. g_oeSendOrders ? 'Y': 'N',
  4375. g_oeTextEnabled ? 'Y': 'N'));
  4376. DebugExitVOID(OEDDSetNewCapabilities);
  4377. }
  4378. //
  4379. // Function: OETileBitBltOrder
  4380. //
  4381. // Description: Divides a single large BitBlt order into a series of small,
  4382. // "tiled" BitBlt orders, each of which is added to the order
  4383. // queue.
  4384. //
  4385. // Parameters: pOrder - Template order to be tiled
  4386. // pExtraInfo - Structure containing pointers to the source
  4387. // and destination surface objects, and a pointer
  4388. // to the color translation object for the Blt
  4389. // pco - Clipping object for the operation
  4390. //
  4391. // Returns: TRUE - Stored in orders (and possibly some SDA)
  4392. // FALSE- Stored in SDA (or contained bad data)
  4393. //
  4394. //
  4395. void OETileBitBltOrder
  4396. (
  4397. LPINT_ORDER pOrder,
  4398. LPMEMBLT_ORDER_EXTRA_INFO pExtraInfo,
  4399. CLIPOBJ* pco
  4400. )
  4401. {
  4402. UINT tileWidth;
  4403. UINT tileHeight;
  4404. int srcLeft;
  4405. int srcTop;
  4406. int srcRight;
  4407. int srcBottom;
  4408. int xFirstTile;
  4409. int yFirstTile;
  4410. int xTile;
  4411. int yTile;
  4412. UINT type;
  4413. int bmpWidth, bmpHeight;
  4414. RECT destRect;
  4415. DebugEntry(OETileBitBltOrder);
  4416. //
  4417. // Extract the src bitmap handle from the Order - if the order is not a
  4418. // memory to screen blit, we get out now.
  4419. //
  4420. type = ((LPMEMBLT_ORDER)pOrder->abOrderData)->type;
  4421. switch (type)
  4422. {
  4423. case ORD_MEMBLT_TYPE:
  4424. {
  4425. srcLeft = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nXSrc;
  4426. srcTop = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nYSrc;
  4427. srcRight = srcLeft +
  4428. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nWidth;
  4429. srcBottom = srcTop +
  4430. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nHeight;
  4431. destRect.left = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nLeftRect;
  4432. destRect.top = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nTopRect;
  4433. destRect.right = destRect.left +
  4434. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nWidth;
  4435. destRect.bottom= destRect.top +
  4436. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nHeight;
  4437. }
  4438. break;
  4439. case ORD_MEM3BLT_TYPE:
  4440. {
  4441. srcLeft = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nXSrc;
  4442. srcTop = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nYSrc;
  4443. srcRight = srcLeft +
  4444. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nWidth;
  4445. srcBottom = srcTop +
  4446. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nHeight;
  4447. destRect.left = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nLeftRect;
  4448. destRect.top = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nTopRect;
  4449. destRect.right= destRect.left +
  4450. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nWidth;
  4451. destRect.bottom = destRect.top +
  4452. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nHeight;
  4453. }
  4454. break;
  4455. default:
  4456. {
  4457. ERROR_OUT(( "Invalid order type %u", type));
  4458. }
  4459. break;
  4460. }
  4461. //
  4462. // Fetch the bitmap details.
  4463. //
  4464. bmpWidth = (int)pExtraInfo->pSource->sizlBitmap.cx;
  4465. bmpHeight = (int)pExtraInfo->pSource->sizlBitmap.cy;
  4466. if (!SBC_DDQueryBitmapTileSize(bmpWidth, bmpHeight, &tileWidth, &tileHeight))
  4467. {
  4468. //
  4469. // This could happen if some 2.x user joins the share.
  4470. //
  4471. TRACE_OUT(("Bitmap is not tileable"));
  4472. OEClipAndAddScreenData(&destRect, pco);
  4473. }
  4474. else
  4475. {
  4476. //
  4477. // Tile the order. If an individual tile fails to get queued as an
  4478. // order, OEAddTiledBitBltOrder() will add it as screen data. Hence
  4479. // no return value to be checked.
  4480. //
  4481. xFirstTile = srcLeft - (srcLeft % tileWidth);
  4482. yFirstTile = srcTop - (srcTop % tileHeight);
  4483. for (yTile = yFirstTile; yTile < srcBottom; yTile += tileHeight)
  4484. {
  4485. for (xTile = xFirstTile; xTile < srcRight; xTile += tileWidth)
  4486. {
  4487. OEAddTiledBitBltOrder(pOrder, pExtraInfo, pco, xTile, yTile,
  4488. tileWidth, tileHeight);
  4489. }
  4490. }
  4491. }
  4492. DebugExitVOID(OETileBitBltOrder);
  4493. }
  4494. //
  4495. // Function: OEAddTiledBitBltOrder
  4496. //
  4497. // Description: Takes an unmodified "large" BitBlt and a tile rectangle,
  4498. // makes a copy of the order and modifies the copied order's
  4499. // src/dest so it applies to the source tile only. The order
  4500. // is added to the order queue. If the allocation of the
  4501. // "tiled" order fails, the destination rect is added to SDA
  4502. //
  4503. // Parameters: pOrder - Template order to be added
  4504. // pExtraInfo - Pointer to the extra BitBlt info
  4505. // pco - Clipping object for the BitBlt
  4506. // xTile - X position of the tile
  4507. // yTile - Y position of the tile
  4508. // tileWidth - tile width
  4509. // tileHeight - tile height
  4510. //
  4511. // Returns: none
  4512. //
  4513. //
  4514. void OEAddTiledBitBltOrder(
  4515. LPINT_ORDER pOrder,
  4516. LPMEMBLT_ORDER_EXTRA_INFO pExtraInfo,
  4517. CLIPOBJ* pco,
  4518. int xTile,
  4519. int yTile,
  4520. UINT tileWidth,
  4521. UINT tileHeight)
  4522. {
  4523. LPINT_ORDER pTileOrder;
  4524. LPINT pXSrc = NULL;
  4525. LPINT pYSrc = NULL;
  4526. LPINT pLeft = NULL;
  4527. LPINT pTop = NULL;
  4528. LPINT pWidth = NULL;
  4529. LPINT pHeight = NULL;
  4530. RECT srcRect;
  4531. RECT destRect;
  4532. UINT type;
  4533. DebugEntry(OETileAndAddBitBltOrder);
  4534. //
  4535. // This is a trusted interface - assume the type is correct
  4536. //
  4537. type = ((LPMEMBLT_ORDER)pOrder->abOrderData)->type;
  4538. ASSERT(((type == ORD_MEMBLT_TYPE) || (type == ORD_MEM3BLT_TYPE)));
  4539. //
  4540. // Do processing which depends on the type of bit blt being tiled:
  4541. // - save existing src and dest rects
  4542. // - make a copy of the order (which will be the tile order)
  4543. // - save pointers to the fields in the tile order which we're likely
  4544. // to change.
  4545. //
  4546. if (type == ORD_MEMBLT_TYPE)
  4547. {
  4548. srcRect.left = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nXSrc;
  4549. srcRect.top = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nYSrc;
  4550. srcRect.right = srcRect.left +
  4551. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nWidth;
  4552. srcRect.bottom = srcRect.top +
  4553. ((LPMEMBLT_ORDER)pOrder->abOrderData)->nHeight;
  4554. destRect.left = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nLeftRect;
  4555. destRect.top = ((LPMEMBLT_ORDER)pOrder->abOrderData)->nTopRect;
  4556. //
  4557. // We must allocate enough space for the maximum size order that
  4558. // SBC may use (i.e. an R2 order). We default to filling in the
  4559. // data as an R1 order.
  4560. //
  4561. pTileOrder = OA_DDAllocOrderMem(sizeof(MEMBLT_R2_ORDER),0);
  4562. if (pTileOrder == NULL)
  4563. {
  4564. TRACE_OUT(( "No space for tile order"));
  4565. DC_QUIT;
  4566. }
  4567. //
  4568. // We must not mess up the linked list data in the orders.
  4569. //
  4570. RtlCopyMemory(((LPBYTE)pTileOrder) +
  4571. FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4572. ((LPBYTE)pOrder) +
  4573. FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4574. sizeof(INT_ORDER_HEADER)
  4575. + sizeof(MEMBLT_R2_ORDER)
  4576. - FIELD_SIZE(INT_ORDER, OrderHeader.list));
  4577. pXSrc = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nXSrc;
  4578. pYSrc = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nYSrc;
  4579. pWidth = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nWidth;
  4580. pHeight = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nHeight;
  4581. pLeft = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nLeftRect;
  4582. pTop = &((LPMEMBLT_ORDER)pTileOrder->abOrderData)->nTopRect;
  4583. }
  4584. else
  4585. {
  4586. srcRect.left = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nXSrc;
  4587. srcRect.top = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nYSrc;
  4588. srcRect.right = srcRect.left +
  4589. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nWidth;
  4590. srcRect.bottom = srcRect.top +
  4591. ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nHeight;
  4592. destRect.left = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nLeftRect;
  4593. destRect.top = ((LPMEM3BLT_ORDER)pOrder->abOrderData)->nTopRect;
  4594. //
  4595. // We must allocate enough space for the maximum size order that
  4596. // SBC may use (i.e. an R2 order). We default to filling in the
  4597. // data as an R1 order.
  4598. //
  4599. pTileOrder = OA_DDAllocOrderMem(sizeof(MEM3BLT_R2_ORDER),0);
  4600. if (pTileOrder == NULL)
  4601. {
  4602. TRACE_OUT(( "No space for tile order"));
  4603. DC_QUIT;
  4604. }
  4605. //
  4606. // We must not mess up the linked list data in the orders.
  4607. //
  4608. RtlCopyMemory(((LPBYTE)pTileOrder) +
  4609. FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4610. ((LPBYTE)pOrder) +
  4611. FIELD_SIZE(INT_ORDER, OrderHeader.list),
  4612. sizeof(INT_ORDER_HEADER)
  4613. + sizeof(MEM3BLT_R2_ORDER)
  4614. - FIELD_SIZE(INT_ORDER, OrderHeader.list));
  4615. pXSrc = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nXSrc;
  4616. pYSrc = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nYSrc;
  4617. pWidth = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nWidth;
  4618. pHeight = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nHeight;
  4619. pLeft = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nLeftRect;
  4620. pTop = &((LPMEM3BLT_ORDER)pTileOrder->abOrderData)->nTopRect;
  4621. }
  4622. TRACE_OUT(( "Tiling order, orig srcLeft=%hd, srcTop=%hd, srcRight=%hd, "
  4623. "srcBottom=%hd, destX=%hd, destY=%hd; "
  4624. "xTile=%hd, yTile=%hd, tileW=%hd, tileH=%hd",
  4625. srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
  4626. destRect.left, destRect.top,
  4627. xTile, yTile, tileWidth, tileHeight));
  4628. DC_EXIT_POINT:
  4629. //
  4630. // NOTE: ALL THE POINTERS MAY BE NULL AT THIS POINT - DO NOT USE THEM
  4631. // UNTIL YOU VERIFY PTILEORDER IS NON-NULL.
  4632. //
  4633. // Intersect source and tile rects, and set up destination rect
  4634. // accordingly - we need to do this even if we failed to copy the
  4635. // order, because the tiled source rect will have to be added to the
  4636. // screen data area.
  4637. //
  4638. if (xTile > srcRect.left)
  4639. {
  4640. destRect.left += (xTile - srcRect.left);
  4641. srcRect.left = xTile;
  4642. }
  4643. if (yTile > srcRect.top)
  4644. {
  4645. destRect.top += (yTile - srcRect.top);
  4646. srcRect.top = yTile;
  4647. }
  4648. srcRect.right = min((UINT)srcRect.right, xTile + tileWidth);
  4649. srcRect.bottom = min((UINT)srcRect.bottom, yTile + tileHeight);
  4650. destRect.right = destRect.left + (srcRect.right - srcRect.left);
  4651. destRect.bottom = destRect.top + (srcRect.bottom - srcRect.top);
  4652. //
  4653. // If the order was successfully copied above, then modify the order
  4654. // to contain the tiled coordinates, and add it to the order list.
  4655. // Otherwise, send the dest rect as screen data.
  4656. //
  4657. if (pTileOrder != NULL)
  4658. {
  4659. TRACE_OUT(( "Tile order originally: srcX=%hd, srcY=%hd, destX=%hd, "
  4660. "destY=%hd, w=%hd, h=%hd",
  4661. *pXSrc, *pYSrc, *pLeft, *pTop, *pWidth, *pHeight));
  4662. *pXSrc = srcRect.left;
  4663. *pYSrc = srcRect.top;
  4664. *pLeft = destRect.left;
  4665. *pTop = destRect.top;
  4666. *pWidth = srcRect.right - srcRect.left;
  4667. *pHeight = srcRect.bottom - srcRect.top;
  4668. pTileOrder->OrderHeader.Common.rcsDst.left = (TSHR_INT16)destRect.left;
  4669. pTileOrder->OrderHeader.Common.rcsDst.right = (TSHR_INT16)destRect.right;
  4670. pTileOrder->OrderHeader.Common.rcsDst.top = (TSHR_INT16)destRect.top;
  4671. pTileOrder->OrderHeader.Common.rcsDst.bottom =
  4672. (TSHR_INT16)destRect.bottom;
  4673. TRACE_OUT(( "Adding order srcX=%hd, srcY=%hd, destX=%hd, destY=%hd,"
  4674. " w=%hd, h=%hd",
  4675. *pXSrc, *pYSrc, *pLeft, *pTop, *pWidth, *pHeight));
  4676. OEClipAndAddOrder(pTileOrder, pExtraInfo, pco);
  4677. }
  4678. else
  4679. {
  4680. TRACE_OUT(( "Failed to allocate order - sending as screen data"));
  4681. OEClipAndAddScreenData(&destRect, pco);
  4682. }
  4683. DebugExitVOID(OETileAndAddBitBltOrder);
  4684. }
  4685. // NAME: OEAddLine
  4686. //
  4687. // PURPOSE:
  4688. //
  4689. // Add a LineTo order to the order heap.
  4690. //
  4691. // RETURNS:
  4692. //
  4693. // TRUE - Attempted to add to heap
  4694. // FALSE - No room left to allocate an order
  4695. //
  4696. // PARAMS:
  4697. //
  4698. // ppdev - display driver PDEV
  4699. // startPoint - start point of line
  4700. // endPoint - end point of line
  4701. // rectDst - bounding rectangle
  4702. // rop2 - ROP2 to use with line
  4703. // width - width of line to add
  4704. // color - color of line to add
  4705. // pco - clipping object for drawing operation
  4706. //
  4707. BOOL OEAddLine(LPOSI_PDEV ppdev,
  4708. LPPOINT startPoint,
  4709. LPPOINT endPoint,
  4710. LPRECT rectDst,
  4711. UINT rop2,
  4712. UINT width,
  4713. UINT color,
  4714. CLIPOBJ* pco)
  4715. {
  4716. BOOL rc = FALSE;
  4717. LPLINETO_ORDER pLineTo;
  4718. LPINT_ORDER pOrder;
  4719. DebugEntry(OEAddLine);
  4720. //
  4721. // Allocate the memory for the order.
  4722. //
  4723. pOrder = OA_DDAllocOrderMem(sizeof(LINETO_ORDER),0);
  4724. if (pOrder == NULL)
  4725. {
  4726. TRACE_OUT(( "Failed to alloc order"));
  4727. DC_QUIT;
  4728. }
  4729. pLineTo = (LPLINETO_ORDER)pOrder->abOrderData;
  4730. //
  4731. // Mark this order type.
  4732. //
  4733. pLineTo->type = ORD_LINETO_TYPE;
  4734. //
  4735. // Store the line end coordinates.
  4736. //
  4737. pLineTo->nXStart = startPoint->x;
  4738. pLineTo->nYStart = startPoint->y;
  4739. pLineTo->nXEnd = endPoint->x;
  4740. pLineTo->nYEnd = endPoint->y;
  4741. //
  4742. // We must convert these values to virtual coords.
  4743. //
  4744. OELPtoVirtual((LPPOINT)&pLineTo->nXStart, 2);
  4745. //
  4746. // Always do solid lines, so it does not matter what we specify as the
  4747. // back color.
  4748. //
  4749. RtlFillMemory(&pLineTo->BackColor,
  4750. sizeof(pLineTo->BackColor),
  4751. 0);
  4752. //
  4753. // We only draw solid lines with no option as to what we do to the
  4754. // background, so this is always transparent.
  4755. //
  4756. pLineTo->BackMode = TRANSPARENT;
  4757. //
  4758. // Get the ROP value.
  4759. //
  4760. pLineTo->ROP2 = rop2;
  4761. //
  4762. // The NT Display Driver is only called to accelerate simple solid
  4763. // lines. So we only support pen styles of PS_SOLID.
  4764. //
  4765. pLineTo->PenStyle = PS_SOLID;
  4766. //
  4767. // Get the pen width.
  4768. //
  4769. pLineTo->PenWidth = width;
  4770. //
  4771. // Set up the color.
  4772. //
  4773. OEConvertColor(ppdev,
  4774. &pLineTo->PenColor,
  4775. color,
  4776. NULL);
  4777. TRACE_OUT(( "LineTo BC %02x%02x%02x BM %04X rop2 %02X "
  4778. "pen %04X %04X %02x%02x%02x x1 %d y1 %d x2 %d y2 %d",
  4779. pLineTo->BackColor.red,
  4780. pLineTo->BackColor.green,
  4781. pLineTo->BackColor.blue,
  4782. pLineTo->BackMode,
  4783. pLineTo->ROP2,
  4784. pLineTo->PenStyle,
  4785. pLineTo->PenWidth,
  4786. pLineTo->PenColor.red,
  4787. pLineTo->PenColor.green,
  4788. pLineTo->PenColor.blue,
  4789. pLineTo->nXStart,
  4790. pLineTo->nYStart,
  4791. pLineTo->nXEnd,
  4792. pLineTo->nYEnd));
  4793. //
  4794. // Store the general order data. The bounding rectangle must be in to
  4795. // virtual desktop co-ordinates. OELRtoVirtual has already done this.
  4796. //
  4797. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILABLE;
  4798. pOrder->OrderHeader.Common.rcsDst.left = (TSHR_INT16)rectDst->left;
  4799. pOrder->OrderHeader.Common.rcsDst.right = (TSHR_INT16)rectDst->right;
  4800. pOrder->OrderHeader.Common.rcsDst.top = (TSHR_INT16)rectDst->top;
  4801. pOrder->OrderHeader.Common.rcsDst.bottom = (TSHR_INT16)rectDst->bottom;
  4802. //
  4803. // Store that order!
  4804. //
  4805. OEClipAndAddOrder(pOrder, NULL, pco);
  4806. rc = TRUE;
  4807. DC_EXIT_POINT:
  4808. DebugExitDWORD(OEAddLine, rc);
  4809. return(rc);
  4810. }
  4811. // NAME: OEEncodePatBlt
  4812. //
  4813. // PURPOSE:
  4814. //
  4815. // Attempts to encode a PatBlt order. This function allocates the memory
  4816. // for the encoded order (pointer returned in ppOrder). If the function
  4817. // completes successfully, it is the caller's responsibility to free this
  4818. // memory.
  4819. //
  4820. // RETURNS:
  4821. //
  4822. // TRUE - Order encoded
  4823. // FALSE - Order not encoded (so add to SDA)
  4824. //
  4825. // PARAMS:
  4826. //
  4827. // ppdev - display driver PDEV
  4828. // pbo - brush object for the blt
  4829. // pptlBrush - brush origin
  4830. // rop3 - 3-way rop to use
  4831. // pBounds - bounding rectangle
  4832. // ppOrder - the encoded order
  4833. //
  4834. BOOL OEEncodePatBlt(LPOSI_PDEV ppdev,
  4835. BRUSHOBJ *pbo,
  4836. POINTL *pptlBrush,
  4837. BYTE rop3,
  4838. LPRECT pBounds,
  4839. LPINT_ORDER *ppOrder)
  4840. {
  4841. BOOL rc = FALSE;
  4842. POE_BRUSH_DATA pCurrentBrush;
  4843. LPPATBLT_ORDER pPatBlt;
  4844. UINT orderFlags = OF_SPOILABLE;
  4845. DebugEntry(OEEncodePatBlt);
  4846. //
  4847. // Check for a simple brush pattern.
  4848. //
  4849. if ( OECheckBrushIsSimple(ppdev, pbo, &pCurrentBrush) )
  4850. {
  4851. //
  4852. // Allocate the memory for the order.
  4853. //
  4854. *ppOrder = OA_DDAllocOrderMem(sizeof(PATBLT_ORDER),0);
  4855. if (*ppOrder != NULL)
  4856. {
  4857. pPatBlt = (LPPATBLT_ORDER)((*ppOrder)->abOrderData);
  4858. //
  4859. // Set the opaque flag if the rop is opaque.
  4860. //
  4861. if (ROP3_IS_OPAQUE(rop3))
  4862. {
  4863. orderFlags |= OF_SPOILER;
  4864. }
  4865. //
  4866. // Set up order type.
  4867. //
  4868. pPatBlt->type = LOWORD(ORD_PATBLT);
  4869. //
  4870. // Virtual desktop co-ordinates.
  4871. //
  4872. pPatBlt->nLeftRect = pBounds->left;
  4873. pPatBlt->nTopRect = pBounds->top;
  4874. pPatBlt->nWidth = pBounds->right - pBounds->left + 1;
  4875. pPatBlt->nHeight = pBounds->bottom - pBounds->top + 1;
  4876. pPatBlt->bRop = rop3;
  4877. //
  4878. // Pattern colours.
  4879. //
  4880. pPatBlt->BackColor = pCurrentBrush->back;
  4881. pPatBlt->ForeColor = pCurrentBrush->fore;
  4882. //
  4883. // The protocol brush origin is the point on the screen where
  4884. // we want the brush to start being drawn from (tiling where
  4885. // necessary). This must be in virtual coordinates.
  4886. //
  4887. pPatBlt->BrushOrgX = pptlBrush->x;
  4888. pPatBlt->BrushOrgY = pptlBrush->y;
  4889. OELPtoVirtual((LPPOINT)&pPatBlt->BrushOrgX, 1);
  4890. //
  4891. // Extra brush data from the data when we realised the brush.
  4892. //
  4893. pPatBlt->BrushStyle = pCurrentBrush->style;
  4894. pPatBlt->BrushHatch = pCurrentBrush->hatch;
  4895. RtlCopyMemory(pPatBlt->BrushExtra,
  4896. pCurrentBrush->brushData,
  4897. sizeof(pPatBlt->BrushExtra));
  4898. TRACE_OUT(( "PatBlt BC %02x%02x%02x FC %02x%02x%02x "
  4899. "Brush %02X %02X X %d Y %d w %d h %d rop %02X",
  4900. pPatBlt->BackColor.red,
  4901. pPatBlt->BackColor.green,
  4902. pPatBlt->BackColor.blue,
  4903. pPatBlt->ForeColor.red,
  4904. pPatBlt->ForeColor.green,
  4905. pPatBlt->ForeColor.blue,
  4906. pPatBlt->BrushStyle,
  4907. pPatBlt->BrushHatch,
  4908. pPatBlt->nLeftRect,
  4909. pPatBlt->nTopRect,
  4910. pPatBlt->nWidth,
  4911. pPatBlt->nHeight,
  4912. pPatBlt->bRop));
  4913. //
  4914. // Copy any order flags into the encoded order structure.
  4915. //
  4916. (*ppOrder)->OrderHeader.Common.fOrderFlags = (TSHR_UINT16)orderFlags;
  4917. rc = TRUE;
  4918. }
  4919. else
  4920. {
  4921. TRACE_OUT(( "Failed to alloc order"));
  4922. }
  4923. }
  4924. else
  4925. {
  4926. TRACE_OUT(( "Brush is not simple"));
  4927. }
  4928. DebugExitDWORD(OEEncodePatBlt, rc);
  4929. return(rc);
  4930. }
  4931. //
  4932. // DrvTransparentBlt()
  4933. // NEW FOR NT5
  4934. //
  4935. BOOL DrvTransparentBlt
  4936. (
  4937. SURFOBJ * psoDst,
  4938. SURFOBJ * psoSrc,
  4939. CLIPOBJ * pco,
  4940. XLATEOBJ * pxlo,
  4941. RECTL * prclDst,
  4942. RECTL * prclSrc,
  4943. ULONG iTransColor,
  4944. ULONG ulReserved
  4945. )
  4946. {
  4947. BOOL rc = TRUE;
  4948. RECT rectSrc;
  4949. RECT rectDst;
  4950. BOOL fAccumulate = FALSE;
  4951. DebugEntry(DrvTransparentBlt);
  4952. //
  4953. // DO THIS _BEFORE_ TAKING LOCK
  4954. //
  4955. if (!g_oeViewers)
  4956. goto NO_LOCK_EXIT;
  4957. OE_SHM_START_WRITING;
  4958. //
  4959. // Get bounding rectangle and convert to a RECT.
  4960. //
  4961. RECT_FROM_RECTL(rectSrc, (*prclSrc));
  4962. RECT_FROM_RECTL(rectDst, (*prclDst));
  4963. //
  4964. // Check if we are accumulating data for this function
  4965. //
  4966. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  4967. if (!fAccumulate)
  4968. {
  4969. DC_QUIT;
  4970. }
  4971. //
  4972. // Convert to virtual coordinates.
  4973. //
  4974. OELRtoVirtual(&rectDst, 1);
  4975. DC_EXIT_POINT:
  4976. if (fAccumulate)
  4977. {
  4978. OEClipAndAddScreenData(&rectDst, pco);
  4979. }
  4980. OE_SHM_STOP_WRITING;
  4981. NO_LOCK_EXIT:
  4982. DebugExitBOOL(DrvTransparentBlt, rc);
  4983. return(rc);
  4984. }
  4985. //
  4986. // DrvAlphaBlend()
  4987. // NEW FOR NT5
  4988. //
  4989. BOOL DrvAlphaBlend
  4990. (
  4991. SURFOBJ * psoDst,
  4992. SURFOBJ * psoSrc,
  4993. CLIPOBJ * pco,
  4994. XLATEOBJ * pxlo,
  4995. RECTL * prclDst,
  4996. RECTL * prclSrc,
  4997. BLENDOBJ * pBlendObj
  4998. )
  4999. {
  5000. BOOL rc = TRUE;
  5001. RECT rectSrc;
  5002. RECT rectDst;
  5003. BOOL fAccumulate = FALSE;
  5004. DebugEntry(DrvAlphaBlend);
  5005. //
  5006. // DO THIS _BEFORE_ TAKING LOCK
  5007. //
  5008. if (!g_oeViewers)
  5009. goto NO_LOCK_EXIT;
  5010. OE_SHM_START_WRITING;
  5011. //
  5012. // Get bounding rectangle and convert to a RECT.
  5013. //
  5014. RECT_FROM_RECTL(rectSrc, (*prclSrc));
  5015. RECT_FROM_RECTL(rectDst, (*prclDst));
  5016. //
  5017. // Check if we are accumulating data for this function
  5018. //
  5019. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  5020. if (!fAccumulate)
  5021. {
  5022. DC_QUIT;
  5023. }
  5024. //
  5025. // Convert to virtual coordinates.
  5026. //
  5027. OELRtoVirtual(&rectDst, 1);
  5028. DC_EXIT_POINT:
  5029. if (fAccumulate)
  5030. {
  5031. OEClipAndAddScreenData(&rectDst, pco);
  5032. }
  5033. OE_SHM_STOP_WRITING;
  5034. NO_LOCK_EXIT:
  5035. DebugExitBOOL(DrvAlphaBlend, rc);
  5036. return(rc);
  5037. }
  5038. //
  5039. // DrvPlgBlt()
  5040. // NEW FOR NT5
  5041. //
  5042. BOOL DrvPlgBlt
  5043. (
  5044. SURFOBJ * psoDst,
  5045. SURFOBJ * psoSrc,
  5046. SURFOBJ * psoMsk,
  5047. CLIPOBJ * pco,
  5048. XLATEOBJ * pxlo,
  5049. COLORADJUSTMENT * pca,
  5050. POINTL * pptlBrushOrg,
  5051. POINTFIX * pptfx,
  5052. RECTL * prclDst,
  5053. POINTL * pptlSrc,
  5054. ULONG iMode
  5055. )
  5056. {
  5057. BOOL rc = TRUE;
  5058. RECT rectDst;
  5059. BOOL fAccumulate = FALSE;
  5060. DebugEntry(DrvPlgBlt);
  5061. //
  5062. // DO THIS _BEFORE_ TAKING LOCK
  5063. //
  5064. if (!g_oeViewers)
  5065. goto NO_LOCK_EXIT;
  5066. OE_SHM_START_WRITING;
  5067. //
  5068. // Get bounding rectangle and convert to a RECT.
  5069. //
  5070. RECT_FROM_RECTL(rectDst, (*prclDst));
  5071. //
  5072. // Check if we are accumulating data for this function
  5073. //
  5074. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  5075. if (!fAccumulate)
  5076. {
  5077. DC_QUIT;
  5078. }
  5079. //
  5080. // Convert to virtual coordinates.
  5081. //
  5082. OELRtoVirtual(&rectDst, 1);
  5083. DC_EXIT_POINT:
  5084. if (fAccumulate)
  5085. {
  5086. OEClipAndAddScreenData(&rectDst, pco);
  5087. }
  5088. OE_SHM_STOP_WRITING;
  5089. NO_LOCK_EXIT:
  5090. DebugExitBOOL(DrvPlgBlt, rc);
  5091. return(rc);
  5092. }
  5093. //
  5094. // DrvStretchBltROP()
  5095. // NEW FOR NT5
  5096. //
  5097. BOOL DrvStretchBltROP
  5098. (
  5099. SURFOBJ * psoDst,
  5100. SURFOBJ * psoSrc,
  5101. SURFOBJ * psoMask,
  5102. CLIPOBJ * pco,
  5103. XLATEOBJ * pxlo,
  5104. COLORADJUSTMENT * pca,
  5105. POINTL * pptlHTOrg,
  5106. RECTL * prclDst,
  5107. RECTL * prclSrc,
  5108. POINTL * pptlMask,
  5109. ULONG iMode,
  5110. BRUSHOBJ * pbo,
  5111. DWORD rop4
  5112. )
  5113. {
  5114. BOOL rc = TRUE;
  5115. RECT rectSrc;
  5116. RECT rectDst;
  5117. BOOL fAccumulate = FALSE;
  5118. DebugEntry(DrvStretchBltROP);
  5119. //
  5120. // DO THIS _BEFORE_ TAKING LOCK
  5121. //
  5122. if (!g_oeViewers)
  5123. goto NO_LOCK_EXIT;
  5124. OE_SHM_START_WRITING;
  5125. //
  5126. // Get bounding rectangle and convert to a RECT.
  5127. //
  5128. RECT_FROM_RECTL(rectSrc, (*prclSrc));
  5129. RECT_FROM_RECTL(rectDst, (*prclDst));
  5130. //
  5131. // Check if we are accumulating data for this function
  5132. //
  5133. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  5134. if (!fAccumulate)
  5135. {
  5136. DC_QUIT;
  5137. }
  5138. //
  5139. // Convert to virtual coordinates.
  5140. //
  5141. OELRtoVirtual(&rectDst, 1);
  5142. DC_EXIT_POINT:
  5143. if (fAccumulate)
  5144. {
  5145. OEClipAndAddScreenData(&rectDst, pco);
  5146. }
  5147. OE_SHM_STOP_WRITING;
  5148. NO_LOCK_EXIT:
  5149. DebugExitBOOL(DrvStretchBltROP, rc);
  5150. return(rc);
  5151. }
  5152. //
  5153. // DrvGradientFill()
  5154. // NEW FOR NT5
  5155. //
  5156. BOOL DrvGradientFill
  5157. (
  5158. SURFOBJ * psoDst,
  5159. CLIPOBJ * pco,
  5160. XLATEOBJ * pxlo,
  5161. TRIVERTEX * pVertex,
  5162. ULONG nVertex,
  5163. PVOID pMesh,
  5164. ULONG nMesh,
  5165. RECTL * prclExtents,
  5166. POINTL * pptlDitherOrg,
  5167. ULONG ulMode
  5168. )
  5169. {
  5170. BOOL rc = TRUE;
  5171. RECT rectDst;
  5172. BOOL fAccumulate = FALSE;
  5173. DebugEntry(DrvGradientFill);
  5174. //
  5175. // DO THIS _BEFORE_ TAKING LOCK
  5176. //
  5177. if (!g_oeViewers)
  5178. goto NO_LOCK_EXIT;
  5179. OE_SHM_START_WRITING;
  5180. //
  5181. // Get bounding rectangle and convert to a RECT.
  5182. //
  5183. RECT_FROM_RECTL(rectDst, pco->rclBounds);
  5184. //
  5185. // Check if we are accumulating data for this function
  5186. //
  5187. fAccumulate = OEAccumulateOutput(psoDst, pco, &rectDst);
  5188. if (!fAccumulate)
  5189. {
  5190. DC_QUIT;
  5191. }
  5192. //
  5193. // Convert to virtual coordinates.
  5194. //
  5195. OELRtoVirtual(&rectDst, 1);
  5196. DC_EXIT_POINT:
  5197. if (fAccumulate)
  5198. {
  5199. OEClipAndAddScreenData(&rectDst, pco);
  5200. }
  5201. OE_SHM_STOP_WRITING;
  5202. NO_LOCK_EXIT:
  5203. DebugExitBOOL(DrvGradientFill, rc);
  5204. return(rc);
  5205. }
  5206.