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.

645 lines
26 KiB

  1. /****************************************************************************/
  2. // ghapi.cpp
  3. //
  4. // Glyph handler - Windows specific
  5. //
  6. // Copyright (C) 1997-1999 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_GROUP TRC_GROUP_CORE
  11. #define TRC_FILE "wghapi"
  12. #include <atrcapi.h>
  13. }
  14. #define TSC_HR_FILEID TSC_HR_GHAPI_CPP
  15. #include "autil.h"
  16. #include "gh.h"
  17. #include "uh.h"
  18. #include "clx.h"
  19. static const PFN_MASTERTEXTTYPE MasterTextTypeTable[8] =
  20. {
  21. CGH::draw_nf_ntb_o_to_temp_start,
  22. CGH::draw_f_ntb_o_to_temp_start,
  23. CGH::draw_nf_ntb_o_to_temp_start,
  24. CGH::draw_f_ntb_o_to_temp_start,
  25. CGH::draw_nf_tb_no_to_temp_start,
  26. CGH::draw_f_tb_no_to_temp_start,
  27. CGH::draw_nf_ntb_o_to_temp_start,
  28. CGH::draw_f_ntb_o_to_temp_start
  29. };
  30. CGH::CGH(CObjs* objs)
  31. {
  32. _pClientObjects = objs;
  33. _pClipGlyphBitsBuffer = NULL;
  34. _ClipGlyphBitsBufferSize = 0;
  35. }
  36. CGH::~CGH()
  37. {
  38. if (_pClipGlyphBitsBuffer!=NULL) {
  39. LocalFree(_pClipGlyphBitsBuffer);
  40. }
  41. }
  42. DCVOID DCAPI CGH::GH_Init(DCVOID)
  43. {
  44. DC_BEGIN_FN("GH_GlyphOut");
  45. _pUh = _pClientObjects->_pUHObject;
  46. _pClx = _pClientObjects->_pCLXObject;
  47. _pUt = _pClientObjects->_pUtObject;
  48. DC_END_FN();
  49. }
  50. /****************************************************************************/
  51. /* Name: GH_GlyphOut */
  52. /* */
  53. /* Purpose: Process glyph output requests */
  54. /* */
  55. /* Returns: Process input event TRUE / FALSE */
  56. /****************************************************************************/
  57. HRESULT DCAPI CGH::GH_GlyphOut(
  58. LPINDEX_ORDER pOrder,
  59. LPVARIABLE_INDEXBYTES pVariableBytes)
  60. {
  61. HRESULT hr = E_FAIL;
  62. BYTE szTextBuffer[GH_TEXT_BUFFER_SIZE];
  63. BYTE ajFrag[256];
  64. UINT16 ajUnicode[256];
  65. unsigned ulBufferWidth;
  66. unsigned fDrawFlags;
  67. PDCUINT8 pjBuffer;
  68. PDCUINT8 pjEndBuffer;
  69. unsigned crclFringe;
  70. RECT arclFringe[4];
  71. unsigned i;
  72. int x;
  73. int y;
  74. PDCUINT8 pjData;
  75. PDCUINT8 pjDataEnd;
  76. unsigned iGlyph;
  77. unsigned cacheIndex;
  78. unsigned cbFrag;
  79. PDCUINT8 pjFrag;
  80. PDCUINT8 pjFragEnd;
  81. int dx;
  82. INT16 delta;
  83. ULONG BufferAlign;
  84. ULONG BufferOffset;
  85. unsigned ulBytes;
  86. unsigned ulHeight;
  87. PFN_MASTERTEXTTYPE pfnMasterType;
  88. DC_BEGIN_FN("GH_GlyphOut");
  89. dx = 0;
  90. // SECURITY 558128: GH_GlyphOut must verify data in VARAIBLE_INDEXBYTES
  91. // parameter which is defined as 255 elements
  92. if (255 < pVariableBytes->len) {
  93. TRC_ABORT(( TB, _T("variable bytes len too long %u"),
  94. pVariableBytes->len));
  95. hr = E_TSC_CORE_LENGTH;
  96. DC_QUIT;
  97. }
  98. /************************************************************************/
  99. // Alloc a temp work buffer -- use the stack buffer if large enough, or
  100. // alloc heap memory if need be.
  101. /************************************************************************/
  102. // Make the buffer width WORD aligned.
  103. ulBufferWidth = (unsigned)(((pOrder->BkRight + 31) & ~31) -
  104. (pOrder->BkLeft & ~31)) >> 3;
  105. ulHeight = (unsigned)(pOrder->BkBottom - pOrder->BkTop);
  106. if ((ulBufferWidth <= FIFTEEN_BITS) && (ulHeight <= FIFTEEN_BITS)) {
  107. ulBytes = ulBufferWidth * ulHeight + 64;
  108. #ifdef DC_DEBUG
  109. g_ulBytes = ulBytes;
  110. #endif
  111. // If the temp buffer is big enough, use it. Otherwise attempt to
  112. // allocate enough memory to satisfy the request.
  113. if (ulBytes <= (sizeof(szTextBuffer) - 20)) {
  114. pjBuffer = szTextBuffer;
  115. memset(szTextBuffer, 0, ulBytes);
  116. }
  117. else {
  118. TRC_NRM((TB, _T("Allocating %d byte temp glyph buffer"), ulBytes));
  119. pjBuffer = (PDCUINT8)UT_Malloc( _pUt, ulBytes);
  120. if (pjBuffer != NULL) {
  121. memset(pjBuffer, 0, ulBytes);
  122. }
  123. else {
  124. TRC_NRM((TB, _T("Unable to alloc temp glyph buffer")));
  125. DC_QUIT;
  126. }
  127. }
  128. }
  129. else {
  130. TRC_NRM((TB, _T("Temp glyph buffer calc overflow")));
  131. hr = E_TSC_UI_GLYPH;
  132. DC_QUIT;
  133. }
  134. pjEndBuffer = pjBuffer + ulBytes;
  135. #ifdef DC_HICOLOR
  136. TRC_NRM((TB, _T("Glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
  137. ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
  138. #endif
  139. /************************************************************************/
  140. // Clear the fringe opaque rect if need be.
  141. /************************************************************************/
  142. // crclFringe ends up holding the number of fringe rectangles to
  143. // post-process.
  144. crclFringe = 0;
  145. if (pOrder->OpTop < pOrder->OpBottom) {
  146. // Establish solid brush.
  147. UHUseBrushOrg(0, 0, _pUh);
  148. _pUh->UHUseSolidPaletteBrush(pOrder->ForeColor);
  149. // If the background brush is a solid brush, we need to compute the
  150. // fringe opaque area outside the text rectangle and include the
  151. // remaining rectangle in the text output. The fringe rectangles will
  152. // be output last to reduce flickering when a string is "moved"
  153. // continuously across the screen.
  154. if (pOrder->BrushStyle == BS_SOLID) {
  155. // Top fragment
  156. if (pOrder->BkTop > pOrder->OpTop) {
  157. arclFringe[crclFringe].left = (int) pOrder->OpLeft;
  158. arclFringe[crclFringe].top = (int) pOrder->OpTop;
  159. arclFringe[crclFringe].right = (int) pOrder->OpRight;
  160. arclFringe[crclFringe].bottom = (int) pOrder->BkTop;
  161. crclFringe++;
  162. }
  163. // Left fragment
  164. if (pOrder->BkLeft > pOrder->OpLeft) {
  165. arclFringe[crclFringe].left = (int) pOrder->OpLeft;
  166. arclFringe[crclFringe].top = (int) pOrder->BkTop;
  167. arclFringe[crclFringe].right = (int) pOrder->BkLeft;
  168. arclFringe[crclFringe].bottom = (int) pOrder->BkBottom;
  169. crclFringe++;
  170. }
  171. // Right fragment
  172. if (pOrder->BkRight < pOrder->OpRight) {
  173. arclFringe[crclFringe].left = (int) pOrder->BkRight;
  174. arclFringe[crclFringe].top = (int) pOrder->BkTop;
  175. arclFringe[crclFringe].right = (int) pOrder->OpRight;
  176. arclFringe[crclFringe].bottom = (int) pOrder->BkBottom;
  177. crclFringe++;
  178. }
  179. // Bottom fragment
  180. if (pOrder->BkBottom < pOrder->OpBottom) {
  181. arclFringe[crclFringe].left = (int) pOrder->OpLeft;
  182. arclFringe[crclFringe].top = (int) pOrder->BkBottom;
  183. arclFringe[crclFringe].right = (int) pOrder->OpRight;
  184. arclFringe[crclFringe].bottom = (int) pOrder->OpBottom;
  185. crclFringe++;
  186. }
  187. }
  188. else {
  189. // If the background brush is a pattern brush, we will output the
  190. // whole rectangle now.
  191. PatBlt(_pUh->_UH.hdcDraw,
  192. (int)pOrder->OpLeft,
  193. (int)pOrder->OpTop,
  194. (int)(pOrder->OpRight - pOrder->OpLeft),
  195. (int)(pOrder->OpBottom - pOrder->OpTop),
  196. PATCOPY);
  197. }
  198. }
  199. /************************************************************************/
  200. // Get fixed pitch, overlap, and top & bottom Y alignment flags.
  201. /************************************************************************/
  202. if ((pOrder->flAccel & SO_HORIZONTAL) &&
  203. !(pOrder->flAccel & SO_REVERSED)) {
  204. fDrawFlags = ((pOrder->ulCharInc != 0) |
  205. (((pOrder->flAccel &
  206. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) !=
  207. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) << 1) |
  208. (((pOrder->flAccel &
  209. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE)) ==
  210. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE)) << 2));
  211. }
  212. else {
  213. fDrawFlags = 0;
  214. }
  215. /************************************************************************/
  216. /* Draw the text into the temp buffer by selecting and calling the */
  217. /* appropriate glyph dispatch routine */
  218. /************************************************************************/
  219. pfnMasterType = MasterTextTypeTable[fDrawFlags];
  220. x = (int)pOrder->x;
  221. y = (int)pOrder->y;
  222. pjData = &(pVariableBytes->arecs[0].byte);
  223. pjDataEnd = pjData + pVariableBytes->len;
  224. BufferAlign = (pOrder->BkLeft & 31);
  225. BufferOffset = (pOrder->BkLeft - BufferAlign);
  226. iGlyph = 0;
  227. GHFRAGRESET(0);
  228. while (pjData < pjDataEnd) {
  229. /********************************************************************/
  230. /* 'Add Fragment' */
  231. /********************************************************************/
  232. if (*pjData == ORD_INDEX_FRAGMENT_ADD) {
  233. HPUHFRAGCACHE pCache;
  234. HPDCUINT8 pCacheEntryData;
  235. PUHFRAGCACHEENTRYHDR pCacheEntryHdr;
  236. pjData++;
  237. CHECK_READ_N_BYTES(pjData, pjDataEnd, 2, hr,
  238. ( TB, _T("reading glyph data off end")));
  239. cacheIndex = *pjData++;
  240. hr = _pUh->UHIsValidFragmentCacheIndex(cacheIndex);
  241. DC_QUIT_ON_FAIL(hr);
  242. cbFrag = *pjData++;
  243. // Add the fragment to the cache.
  244. pCache = &_pUh->_UH.fragCache;
  245. if (cbFrag > pCache->cbEntrySize) {
  246. TRC_ABORT((TB,_T("Invalid fragment size")));
  247. hr = E_TSC_CORE_LENGTH;
  248. DC_QUIT;
  249. }
  250. pCacheEntryHdr = &(pCache->pHdr[cacheIndex]);
  251. pCacheEntryHdr->cbFrag = cbFrag;
  252. pCacheEntryHdr->cacheId = pOrder->cacheId;
  253. pCacheEntryData = &(pCache->pData[cacheIndex *
  254. pCache->cbEntrySize]);
  255. CHECK_READ_N_BYTES_2ENDED(pjData - cbFrag - 3, &(pVariableBytes->arecs[0].byte),
  256. pjDataEnd, cbFrag, hr, (TB,_T("Fragment for ADD begins before data")))
  257. memcpy(pCacheEntryData, pjData - cbFrag - 3, cbFrag);
  258. if (pOrder->ulCharInc == 0) {
  259. if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
  260. if (pCacheEntryData[1] & 0x80) {
  261. pCacheEntryData[2] = 0;
  262. pCacheEntryData[3] = 0;
  263. }
  264. else {
  265. pCacheEntryData[1] = 0;
  266. }
  267. }
  268. }
  269. }
  270. /********************************************************************/
  271. /* 'Use Fragment' */
  272. /********************************************************************/
  273. else if (*pjData == ORD_INDEX_FRAGMENT_USE) {
  274. PUHFRAGCACHE pCache;
  275. PDCUINT8 pCacheEntryData;
  276. PUHFRAGCACHEENTRYHDR pCacheEntryHdr;
  277. unsigned cbFrag;
  278. pjData++;
  279. CHECK_READ_ONE_BYTE(pjData, pjDataEnd, hr,
  280. ( TB, _T("reading glyph data off end")));
  281. cacheIndex = *pjData++;
  282. hr = _pUh->UHIsValidFragmentCacheIndex(cacheIndex);
  283. DC_QUIT_ON_FAIL(hr);
  284. if ((pOrder->ulCharInc == 0) &&
  285. ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0)) {
  286. CHECK_READ_ONE_BYTE(pjData, pjDataEnd, hr,
  287. ( TB, _T("reading glyph data off end")))
  288. delta = (*(PDCINT8)pjData++);
  289. if (delta & 0x80) {
  290. CHECK_READ_N_BYTES(pjData, pjDataEnd, sizeof(DCINT16), hr,
  291. ( TB, _T("reading glyph data off end")))
  292. delta = (*(PDCINT16)pjData);
  293. pjData += sizeof(DCINT16);
  294. }
  295. if (pOrder->flAccel & SO_HORIZONTAL)
  296. x += delta;
  297. else
  298. y += delta;
  299. }
  300. // Get the fragment from the cache.
  301. pCache = &_pUh->_UH.fragCache;
  302. pCacheEntryHdr = &(pCache->pHdr[cacheIndex]);
  303. pCacheEntryData = &(pCache->pData[cacheIndex *
  304. pCache->cbEntrySize]);
  305. if (pCacheEntryHdr->cacheId != pOrder->cacheId) {
  306. TRC_ABORT((TB,_T("Fragment cache id mismatch")));
  307. hr = E_TSC_CORE_CACHEVALUE;
  308. DC_QUIT;
  309. }
  310. cbFrag = (unsigned)pCacheEntryHdr->cbFrag;
  311. if (cbFrag > sizeof(ajFrag)) {
  312. TRC_ABORT(( TB, _T("cbFrag > sizeof (ajFrag)")));
  313. hr = E_TSC_CORE_LENGTH;
  314. DC_QUIT;
  315. }
  316. memcpy(ajFrag, pCacheEntryData, cbFrag);
  317. GHFRAGLEFT(x);
  318. pjFrag = ajFrag;
  319. pjFragEnd = &ajFrag[cbFrag];
  320. while (pjFrag < pjFragEnd) {
  321. hr = pfnMasterType(this, pOrder, iGlyph++, &pjFrag, pjFragEnd, &x, &y,
  322. pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, ajUnicode, &dx);
  323. DC_QUIT_ON_FAIL(hr);
  324. }
  325. if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
  326. GHFRAGRIGHT(x);
  327. else
  328. GHFRAGRIGHT(x+dx);
  329. }
  330. /********************************************************************/
  331. /* Normal glyph out */
  332. /********************************************************************/
  333. else {
  334. int dummy;
  335. /****************************************************************/
  336. /* if we have more than 255 glyphs, we won't get any unicode */
  337. /* beyond 255 glyphs because ajUnicode has length of 256 */
  338. /****************************************************************/
  339. if (iGlyph < 255) {
  340. hr = pfnMasterType(this, pOrder, iGlyph++, &pjData, pjDataEnd, &x, &y,
  341. pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, ajUnicode, &dummy);
  342. DC_QUIT_ON_FAIL(hr);
  343. } else {
  344. hr = pfnMasterType(this, pOrder, iGlyph++, &pjData, pjDataEnd, &x, &y,
  345. pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, NULL, &dummy);
  346. DC_QUIT_ON_FAIL(hr);
  347. }
  348. }
  349. }
  350. if (iGlyph < 255)
  351. ajUnicode[iGlyph] = 0;
  352. else
  353. ajUnicode[255] = 0;
  354. /************************************************************************/
  355. /* Draw the temp buffer to the output device */
  356. /************************************************************************/
  357. #if defined(OS_WINCE) || defined(OS_WINNT)
  358. /************************************************************************/
  359. // For WinCE, Win9x, and NT use a fast path if possible.
  360. /************************************************************************/
  361. #ifdef USE_GDIPLUS
  362. if (_pUh->_UH.bmShadowBits != NULL &&
  363. _pUh->_UH.protocolBpp == _pUh->_UH.shadowBitmapBpp &&
  364. _pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap) {
  365. #else // USE_GDIPLUS
  366. if (_pUh->_UH.bmShadowBits != NULL &&
  367. _pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap) {
  368. #endif // USE_GDIPLUS
  369. INT32 left, right, top, bottom;
  370. UINT32 dx, dy;
  371. if (_pUh->_UH.rectReset) {
  372. left = pOrder->BkLeft;
  373. right = pOrder->BkRight;
  374. top = pOrder->BkTop;
  375. bottom = pOrder->BkBottom;
  376. }
  377. else {
  378. left = DC_MAX(pOrder->BkLeft, _pUh->_UH.lastLeft);
  379. right = DC_MIN(pOrder->BkRight, _pUh->_UH.lastRight + 1);
  380. top = DC_MAX(pOrder->BkTop, _pUh->_UH.lastTop);
  381. bottom = DC_MIN(pOrder->BkBottom, _pUh->_UH.lastBottom + 1);
  382. }
  383. //
  384. // Fix for bug#699321. In case the shadow bitmap is enabled and we will
  385. // use the "performant" functions to copy the glyph fragment into
  386. // the shadow buffer we have to make sure that the dest rect is clipped
  387. // to the screen area. If it is not we might overflow the shadow screen
  388. // buffer. The server should not send us orders that will result in
  389. // the dest rect not being fully contained by the screen area. This is
  390. // purely a security surface reduction fix.
  391. //
  392. if ((left < right) && (top < bottom) &&
  393. (left >= 0) && (right <= (INT32)_pUh->_UH.bmShadowWidth) &&
  394. (top >= 0) && (bottom <= (INT32)_pUh->_UH.bmShadowHeight)) {
  395. #ifdef OS_WINNT
  396. // On NT and Win9x we need to make sure all GDI buffered output
  397. // is flushed out to the offscreen bitmap.
  398. GdiFlush();
  399. #endif
  400. dx = (UINT32)(left - pOrder->BkLeft);
  401. dy = (UINT32)(top - pOrder->BkTop);
  402. if (pOrder->OpTop < pOrder->OpBottom) {
  403. #ifdef DC_HICOLOR
  404. TRC_NRM((TB, _T("Opaque glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
  405. ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
  406. if (_pUh->_UH.protocolBpp == 24)
  407. {
  408. vSrcOpaqCopyS1D8_24(pjBuffer + dy * ulBufferWidth,
  409. BufferAlign + dx,
  410. ulBufferWidth,
  411. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
  412. left,
  413. right,
  414. _pUh->_UH.bmShadowWidth,
  415. bottom - top,
  416. pOrder->BackColor.u.rgb,
  417. pOrder->ForeColor.u.rgb);
  418. }
  419. else if ((_pUh->_UH.protocolBpp == 16) || (_pUh->_UH.protocolBpp == 15))
  420. {
  421. vSrcOpaqCopyS1D8_16(pjBuffer + dy * ulBufferWidth,
  422. BufferAlign + dx,
  423. ulBufferWidth,
  424. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
  425. left,
  426. right,
  427. _pUh->_UH.bmShadowWidth,
  428. bottom - top,
  429. *((PDCUINT16)&(pOrder->BackColor)),
  430. *((PDCUINT16)&(pOrder->ForeColor)));
  431. }
  432. else
  433. {
  434. #endif
  435. vSrcOpaqCopyS1D8(pjBuffer + dy * ulBufferWidth, // pointer to beginning of current scan line of src buffer
  436. BufferAlign + dx, // left (starting) pixel in src rectangle
  437. ulBufferWidth, // bytes from one src scan line to next
  438. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth, // pointer to beginning of current scan line of Dst buffer
  439. left, // left(first) dst pixel
  440. right, // right(last) dst pixel
  441. _pUh->_UH.bmShadowWidth, // bytes from one Dst scan line to next
  442. bottom - top, // number of scan lines
  443. pOrder->BackColor.u.index, // Foreground color
  444. pOrder->ForeColor.u.index); // Background color
  445. #ifdef DC_HICOLOR
  446. }
  447. #endif
  448. }
  449. else {
  450. #ifdef DC_HICOLOR
  451. TRC_NRM((TB, _T("Transparent glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
  452. ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
  453. if (_pUh->_UH.protocolBpp == 24)
  454. {
  455. vSrcTranCopyS1D8_24(pjBuffer + dy * ulBufferWidth,
  456. BufferAlign + dx,
  457. ulBufferWidth,
  458. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
  459. left,
  460. right,
  461. _pUh->_UH.bmShadowWidth,
  462. bottom - top,
  463. pOrder->BackColor.u.rgb);
  464. }
  465. else if ((_pUh->_UH.protocolBpp == 16) || (_pUh->_UH.protocolBpp == 15))
  466. {
  467. vSrcTranCopyS1D8_16(pjBuffer + dy * ulBufferWidth,
  468. BufferAlign + dx,
  469. ulBufferWidth,
  470. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
  471. left,
  472. right,
  473. _pUh->_UH.bmShadowWidth,
  474. bottom - top,
  475. *((PDCUINT16)&(pOrder->BackColor)));
  476. }
  477. else
  478. {
  479. #endif
  480. vSrcTranCopyS1D8(pjBuffer + dy * ulBufferWidth,
  481. BufferAlign + dx,
  482. ulBufferWidth,
  483. _pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth,
  484. left,
  485. right,
  486. _pUh->_UH.bmShadowWidth,
  487. bottom - top,
  488. pOrder->BackColor.u.index,
  489. pOrder->ForeColor.u.index);
  490. #ifdef DC_HICOLOR
  491. }
  492. #endif
  493. }
  494. } else {
  495. if ((left > right) || (top > bottom)) {
  496. TRC_NRM((TB, _T("Non-ordered glyph paint rect (%d, %d, %d, %d)."),
  497. left, top, right, bottom));
  498. } else if ((left == right) || (top == bottom)) {
  499. TRC_NRM((TB, _T("Zero width/height glyph paint rect (%d, %d, %d, %d)."),
  500. left, top, right, bottom));
  501. } else {
  502. TRC_ERR((TB, _T("Bad glyph paint rect (%d, %d, %d, %d)->(%d, %d)."),
  503. left, top, right, bottom,
  504. _pUh->_UH.bmShadowWidth, _pUh->_UH.bmShadowHeight));
  505. }
  506. }
  507. }
  508. else
  509. #endif // defined(OS_WINCE) || defined(OS_WINNT)
  510. {
  511. #ifdef DC_HICOLOR
  512. TRC_NRM((TB, _T("Slow glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
  513. ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
  514. #endif
  515. GHSlowOutputBuffer(pOrder, pjBuffer, BufferAlign, ulBufferWidth);
  516. }
  517. // Send the bitmap thru CLX
  518. _pClx->CLX_ClxGlyphOut((UINT)(ulBufferWidth << 3),
  519. (UINT)(pOrder->BkBottom - pOrder->BkTop), pjBuffer);
  520. #ifdef DC_DEBUG
  521. // In debug, hatch the output yellow if the option is turned on.
  522. if (_pUh->_UH.hatchIndexPDUData) {
  523. unsigned i;
  524. for (i = 0; i < g_Fragment; i++)
  525. _pUh->UH_HatchRect((int)(g_FragmentLeft[i]),
  526. (int)pOrder->BkTop,
  527. (int)(g_FragmentRight[i]),
  528. (int)pOrder->BkBottom,
  529. UH_RGB_YELLOW,
  530. UH_BRUSHTYPE_FDIAGONAL);
  531. }
  532. #endif
  533. /************************************************************************/
  534. // Post-process draw fringe rects.
  535. /************************************************************************/
  536. for (i = 0; i < crclFringe; i++) {
  537. if (!PatBlt(_pUh->_UH.hdcDraw,
  538. arclFringe[i].left,
  539. arclFringe[i].top,
  540. (int)(arclFringe[i].right - arclFringe[i].left),
  541. (int)(arclFringe[i].bottom - arclFringe[i].top),
  542. PATCOPY))
  543. {
  544. TRC_ERR((TB, _T("Glyph PatBlt failed")));
  545. }
  546. }
  547. /************************************************************************/
  548. /* Free up any memory we may have allocated for the temp buffer */
  549. /************************************************************************/
  550. if (pjBuffer != szTextBuffer)
  551. UT_Free( _pUt, pjBuffer);
  552. /************************************************************************/
  553. /* Let the clx have a look-see at the unicode text data */
  554. /************************************************************************/
  555. if ( _pUh->_UH.hdcDraw == _pUh->_UH.hdcOffscreenBitmap ) {
  556. _pClx->CLX_ClxTextOut(ajUnicode, iGlyph, _pUh->_UH.hdcDraw,
  557. pOrder->BkLeft, pOrder->BkRight, pOrder->BkTop, pOrder->BkBottom);
  558. }
  559. else {
  560. _pClx->CLX_ClxTextOut(ajUnicode, iGlyph, NULL,
  561. pOrder->BkLeft, pOrder->BkRight, pOrder->BkTop, pOrder->BkBottom);
  562. }
  563. hr = S_OK;
  564. DC_EXIT_POINT:
  565. DC_END_FN();
  566. return hr;
  567. }