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.

2880 lines
96 KiB

  1. /****************************************************************************/
  2. // wghint.c
  3. //
  4. // Glyph handler - internal Windows specific
  5. //
  6. // Copyright (C) 1997-1999 Microsoft Corporation 1997-1999
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_GROUP TRC_GROUP_CORE
  11. #define TRC_FILE "wghint"
  12. #include <atrcapi.h>
  13. }
  14. #define TSC_HR_FILEID TSC_HR_GHINT_CPP
  15. #include "autil.h"
  16. #include "gh.h"
  17. #include "uh.h"
  18. #include <wxlint.h>
  19. #if defined(OS_WINCE) || defined(OS_WINNT)
  20. #ifdef DC_HICOLOR
  21. /******************************Public*Routine******************************\
  22. * vSrcOpaqCopyS1D8_24
  23. *
  24. * Opaque blt of 1BPP src to 24bpp destination
  25. *
  26. * Arguments:
  27. * pjSrcIn - pointer to beginning of current scan line of src buffer
  28. * SrcLeft - left (starting) pixel in src rectangle
  29. * DeltaSrcIn - bytes from one src scan line to next
  30. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  31. * DstLeft - left(first) dst pixel
  32. * DstRight - right(last) dst pixel
  33. * DeltaDstIn - bytes from one Dst scan line to next
  34. * cy - number of scan lines
  35. * fgCol - Foreground color
  36. * bgCol - Background color
  37. \**************************************************************************/
  38. VOID CGH::vSrcOpaqCopyS1D8_24(
  39. PBYTE pjSrcIn,
  40. LONG SrcLeft,
  41. LONG DeltaSrcIn,
  42. PBYTE pjDstIn,
  43. LONG DstLeft,
  44. LONG DstRight,
  45. LONG DeltaDstIn,
  46. LONG cy,
  47. DCRGB fgCol,
  48. DCRGB bgCol)
  49. {
  50. // We access the 1bpp source a byte at a time, so we have to start accessing
  51. // the destination on a corresponding 8-pel aligned left edge
  52. ULONG LeftAln = (DstLeft & ~0x07);
  53. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  54. ULONG RightAln = (DstRight & ~0x07);
  55. ULONG AlnDelta = RightAln - LeftAln;
  56. LONG DeltaDst;
  57. LONG DeltaSrc;
  58. PBYTE pjDstEndY;
  59. PBYTE pjSrc;
  60. PBYTE pjDst;
  61. DC_BEGIN_FN("vSrcTranCopyS1D8_24");
  62. // calculate the pel-aligned pointers and row deltas
  63. pjDst = pjDstIn + LeftAln * 3;
  64. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  65. pjSrc = pjSrcIn + (SrcLeft >> 3);
  66. DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
  67. DeltaDst = (DeltaDstIn - AlnDelta) * 3;
  68. // make sure at least 1 QWORD needs copying
  69. if (RightAln != LeftAln)
  70. {
  71. // for each row...
  72. do
  73. {
  74. PBYTE pjDstEnd = pjDst + AlnDelta * 3;
  75. BYTE currentPels;
  76. ULONG i;
  77. // Mask off the left edge
  78. currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
  79. for (i = 0; i < 8; i++)
  80. {
  81. if ((0xff >> i) > (BYTE)(LeftEdgeMask))
  82. {
  83. pjDst += 3;
  84. }
  85. else if ((currentPels & 0x80) == 0)
  86. {
  87. *pjDst++ = bgCol.blue;
  88. *pjDst++ = bgCol.green;
  89. *pjDst++ = bgCol.red;
  90. }
  91. else
  92. {
  93. *pjDst++ = fgCol.blue;
  94. *pjDst++ = fgCol.green;
  95. *pjDst++ = fgCol.red;
  96. }
  97. currentPels = (BYTE)(currentPels << 1);
  98. }
  99. pjSrc ++;
  100. // now do the rest of the row
  101. while (pjDst != pjDstEnd)
  102. {
  103. currentPels = *pjSrc;
  104. if (currentPels != 0)
  105. {
  106. for (i = 0; i < 8 ; i++)
  107. {
  108. if ((currentPels & 0x80) == 0)
  109. {
  110. *pjDst++ = bgCol.blue;
  111. *pjDst++ = bgCol.green;
  112. *pjDst++ = bgCol.red;
  113. }
  114. else
  115. {
  116. *pjDst++ = fgCol.blue;
  117. *pjDst++ = fgCol.green;
  118. *pjDst++ = fgCol.red;
  119. }
  120. currentPels = (BYTE)(currentPels << 1);
  121. }
  122. }
  123. else
  124. {
  125. for (i = 0; i < 8 ; i++)
  126. {
  127. *pjDst++ = bgCol.blue;
  128. *pjDst++ = bgCol.green;
  129. *pjDst++ = bgCol.red;
  130. }
  131. }
  132. pjSrc++;
  133. }
  134. pjDst += DeltaDst;
  135. pjSrc += DeltaSrc;
  136. } while (pjDst != pjDstEndY);
  137. }
  138. // Now fill in the right edge
  139. RightAln = DstRight & 0x07;
  140. if (RightAln)
  141. {
  142. BYTE currentPels;
  143. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  144. LeftAln = DstLeft & 0x07;
  145. // if left and right edges are in same qword handle with masked
  146. // read-modify-write
  147. if (bSameQWord)
  148. {
  149. LONG xCount;
  150. LONG lDeltaDst;
  151. PBYTE pjDstEnd;
  152. xCount = RightAln - LeftAln;
  153. // sanity checks!
  154. if (xCount <= 0)
  155. {
  156. return;
  157. }
  158. lDeltaDst = (DeltaDstIn - xCount) * 3;
  159. pjDst = pjDstIn + DstLeft * 3;
  160. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  161. pjSrc = pjSrcIn + (SrcLeft >> 3);
  162. // expand, one src byte is all that's required
  163. do
  164. {
  165. // load src and shift into place
  166. currentPels = *pjSrc;
  167. currentPels <<= LeftAln;
  168. pjDstEnd = pjDst + xCount * 3;
  169. do
  170. {
  171. if ((currentPels & 0x80) == 0)
  172. {
  173. *pjDst++ = bgCol.blue;
  174. *pjDst++ = bgCol.green;
  175. *pjDst++ = bgCol.red;
  176. }
  177. else
  178. {
  179. *pjDst++ = fgCol.blue;
  180. *pjDst++ = fgCol.green;
  181. *pjDst++ = fgCol.red;
  182. }
  183. currentPels = (BYTE)(currentPels << 1);
  184. } while (pjDst != pjDstEnd);
  185. pjDst += lDeltaDst;
  186. pjSrc += DeltaSrcIn;
  187. } while (pjDst != pjDstEndY);
  188. return;
  189. }
  190. else
  191. {
  192. BYTE currentPels;
  193. LONG lDeltaDst = (DeltaDstIn - RightAln) * 3;
  194. PBYTE pjDstEnd;
  195. ULONG i;
  196. pjDst = pjDstIn + (DstRight & ~0x07) * 3;
  197. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  198. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  199. do
  200. {
  201. // read src
  202. currentPels = *pjSrc;
  203. if (currentPels != 0)
  204. {
  205. pjDstEnd = pjDst + RightAln * 3;
  206. do
  207. {
  208. if ((currentPels & 0x80) == 0)
  209. {
  210. *pjDst++ = bgCol.blue;
  211. *pjDst++ = bgCol.green;
  212. *pjDst++ = bgCol.red;
  213. }
  214. else
  215. {
  216. *pjDst++ = fgCol.blue;
  217. *pjDst++ = fgCol.green;
  218. *pjDst++ = fgCol.red;
  219. }
  220. currentPels = (BYTE)(currentPels << 1);
  221. } while (pjDst != pjDstEnd);
  222. }
  223. else
  224. {
  225. // short cut for zero
  226. for (i = 0; i < RightAln ; i++)
  227. {
  228. *pjDst++ = bgCol.blue;
  229. *pjDst++ = bgCol.green;
  230. *pjDst++ = bgCol.red;
  231. }
  232. }
  233. pjDst += lDeltaDst;
  234. pjSrc += DeltaSrcIn;
  235. } while (pjDst != pjDstEndY);
  236. }
  237. }
  238. DC_END_FN();
  239. }
  240. /******************************Public*Routine******************************\
  241. * vSrcOpaqCopyS1D8_16
  242. *
  243. * Opaque blt of 1BPP src to 16bpp destination
  244. *
  245. * Arguments:
  246. * pjSrcIn - pointer to beginning of current scan line of src buffer
  247. * SrcLeft - left (starting) pixel in src rectangle
  248. * DeltaSrcIn - bytes from one src scan line to next
  249. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  250. * DstLeft - left(first) dst pixel
  251. * DstRight - right(last) dst pixel
  252. * DeltaDstIn - bytes from one Dst scan line to next
  253. * cy - number of scan lines
  254. * fgCol - Foreground color
  255. * bgCol - Background color
  256. \**************************************************************************/
  257. VOID CGH::vSrcOpaqCopyS1D8_16(
  258. PBYTE pjSrcIn,
  259. LONG SrcLeft,
  260. LONG DeltaSrcIn,
  261. PBYTE pjDstIn,
  262. LONG DstLeft,
  263. LONG DstRight,
  264. LONG DeltaDstIn,
  265. LONG cy,
  266. ULONG fgCol,
  267. ULONG bgCol)
  268. {
  269. // We access the 1bpp source a byte at a time, so we have to start accessing
  270. // the destination on a corresponding 8-pel aligned left edge
  271. ULONG LeftAln = (DstLeft & ~0x07);
  272. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  273. ULONG RightAln = (DstRight & ~0x07);
  274. ULONG AlnDelta = RightAln - LeftAln;
  275. LONG DeltaDst;
  276. LONG DeltaSrc;
  277. PBYTE pjDstEndY;
  278. PBYTE pjSrc;
  279. PBYTE pjDst;
  280. DC_BEGIN_FN("vSrcTranCopyS1D8_16");
  281. // calculate the pel-aligned pointers and row deltas
  282. pjDst = pjDstIn + LeftAln * 2;
  283. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  284. pjSrc = pjSrcIn + (SrcLeft >> 3);
  285. DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
  286. DeltaDst = (DeltaDstIn - AlnDelta) * 2;
  287. // make sure at least 1 QWORD needs copying
  288. if (RightAln != LeftAln)
  289. {
  290. // for each row...
  291. do
  292. {
  293. PBYTE pjDstEnd = pjDst + AlnDelta * 2;
  294. BYTE currentPels;
  295. ULONG i;
  296. // Mask off the left edge
  297. currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
  298. for (i = 0; i < 8; i++)
  299. {
  300. if ((0xff >> i) <= (BYTE)(LeftEdgeMask))
  301. {
  302. if ((currentPels & 0x80) == 0)
  303. {
  304. *(UINT16 *)pjDst = (UINT16)bgCol;
  305. }
  306. else
  307. {
  308. *(UINT16 *)pjDst = (UINT16)fgCol;
  309. }
  310. }
  311. pjDst += 2;
  312. currentPels = (BYTE)(currentPels << 1);
  313. }
  314. pjSrc ++;
  315. // now do the rest of the row
  316. while (pjDst != pjDstEnd)
  317. {
  318. currentPels = *pjSrc;
  319. if (currentPels != 0)
  320. {
  321. for (i = 0; i < 8 ; i++)
  322. {
  323. if ((currentPels & 0x80) == 0)
  324. {
  325. *(UINT16 *)pjDst = (UINT16)bgCol;
  326. }
  327. else
  328. {
  329. *(UINT16 *)pjDst = (UINT16)fgCol;
  330. }
  331. pjDst += 2;
  332. currentPels = (BYTE)(currentPels << 1);
  333. }
  334. }
  335. else
  336. {
  337. for (i = 0; i < 8 ; i++)
  338. {
  339. *(UINT16 *)pjDst = (UINT16)bgCol;
  340. pjDst += 2;
  341. }
  342. }
  343. pjSrc++;
  344. }
  345. pjDst += DeltaDst;
  346. pjSrc += DeltaSrc;
  347. } while (pjDst != pjDstEndY);
  348. }
  349. // Now fill in the right edge
  350. RightAln = DstRight & 0x07;
  351. if (RightAln)
  352. {
  353. BYTE currentPels;
  354. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  355. LeftAln = DstLeft & 0x07;
  356. // if left and right edges are in same qword handle with masked
  357. // read-modify-write
  358. if (bSameQWord)
  359. {
  360. LONG xCount;
  361. LONG lDeltaDst;
  362. PBYTE pjDstEnd;
  363. xCount = RightAln - LeftAln;
  364. // sanity checks!
  365. if (xCount <= 0)
  366. {
  367. return;
  368. }
  369. lDeltaDst = (DeltaDstIn - xCount) * 2;
  370. pjDst = pjDstIn + DstLeft * 2;
  371. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  372. pjSrc = pjSrcIn + (SrcLeft >> 3);
  373. // expand, one src byte is all that's required
  374. do
  375. {
  376. // load src and shift into place
  377. currentPels = *pjSrc;
  378. currentPels <<= LeftAln;
  379. pjDstEnd = pjDst + xCount * 2;
  380. do
  381. {
  382. if ((currentPels & 0x80) == 0)
  383. {
  384. *(UINT16 *)pjDst = (UINT16)bgCol;
  385. }
  386. else
  387. {
  388. *(UINT16 *)pjDst = (UINT16)fgCol;
  389. }
  390. pjDst += 2;
  391. currentPels = (BYTE)(currentPels << 1);
  392. } while (pjDst != pjDstEnd);
  393. pjDst += lDeltaDst;
  394. pjSrc += DeltaSrcIn;
  395. } while (pjDst != pjDstEndY);
  396. return;
  397. }
  398. else
  399. {
  400. BYTE currentPels;
  401. LONG lDeltaDst = (DeltaDstIn - RightAln) * 2;
  402. PBYTE pjDstEnd;
  403. ULONG i;
  404. pjDst = pjDstIn + (DstRight & ~0x07) * 2;
  405. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  406. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  407. do
  408. {
  409. // read src
  410. currentPels = *pjSrc;
  411. if (currentPels != 0)
  412. {
  413. pjDstEnd = pjDst + RightAln * 2;
  414. do
  415. {
  416. if ((currentPels & 0x80) == 0)
  417. {
  418. *(UINT16 *)pjDst = (UINT16)bgCol;
  419. }
  420. else
  421. {
  422. *(UINT16 *)pjDst = (UINT16)fgCol;
  423. }
  424. pjDst += 2;
  425. currentPels = (BYTE)(currentPels << 1);
  426. } while (pjDst != pjDstEnd);
  427. }
  428. else
  429. {
  430. // short cut for zero
  431. for (i = 0; i < RightAln ; i++)
  432. {
  433. *(UINT16 *)pjDst = (UINT16)bgCol;
  434. pjDst += 2;
  435. }
  436. }
  437. pjDst += lDeltaDst;
  438. pjSrc += DeltaSrcIn;
  439. } while (pjDst != pjDstEndY);
  440. }
  441. }
  442. DC_END_FN();
  443. }
  444. #endif // HICOLOR
  445. /******************************Public*Routine******************************\
  446. * vSrcOpaqCopyS1D8
  447. *
  448. * Opaque blt of 1BPP src to destination format
  449. *
  450. * Arguments:
  451. * pjSrcIn - pointer to beginning of current scan line of src buffer
  452. * SrcLeft - left (starting) pixel in src rectangle
  453. * DeltaSrcIn - bytes from one src scan line to next
  454. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  455. * DstLeft - left(first) dst pixel
  456. * DstRight - right(last) dst pixel
  457. * DeltaDstIn - bytes from one Dst scan line to next
  458. * cy - number of scan lines
  459. * uF - Foreground color
  460. * uB - Background color
  461. \**************************************************************************/
  462. VOID CGH::vSrcOpaqCopyS1D8(
  463. PBYTE pjSrcIn,
  464. LONG SrcLeft,
  465. LONG DeltaSrcIn,
  466. PBYTE pjDstIn,
  467. LONG DstLeft,
  468. LONG DstRight,
  469. LONG DeltaDstIn,
  470. LONG cy,
  471. ULONG uF,
  472. ULONG uB)
  473. {
  474. // Aligned portion
  475. ULONG LeftAln = ((DstLeft + 7) & ~0x07);
  476. ULONG RightAln = ((DstRight) & ~0x07);
  477. ULONG EndOffset = RightAln - LeftAln;
  478. ULONG EndOffset4 = EndOffset & ~0x0F;
  479. ULONG EndOffset8 = EndOffset & ~0x1F;
  480. LONG DeltaDst;
  481. LONG DeltaSrc;
  482. PBYTE pjDstEndY;
  483. PBYTE pjSrc;
  484. PBYTE pjDst;
  485. ULONG TextExpTable[16];
  486. // Generate text expasion table
  487. ULONG Accum = uB;
  488. Accum = Accum | (Accum << 8);
  489. Accum = Accum | (Accum << 16);
  490. TextExpTable[0] = Accum; // 0 0 0 0
  491. Accum <<= 8;
  492. Accum |= uF;
  493. TextExpTable[8] = Accum; // 0 0 0 1
  494. Accum <<= 8;
  495. Accum |= uB;
  496. TextExpTable[4] = Accum; // 0 0 1 0
  497. Accum <<= 8;
  498. Accum |= uF;
  499. TextExpTable[10] = Accum; // 0 1 0 1
  500. Accum <<= 8;
  501. Accum |= uB;
  502. TextExpTable[5] = Accum; // 1 0 1 0
  503. Accum <<= 8;
  504. Accum |= uB;
  505. TextExpTable[ 2] = Accum; // 0 1 0 0
  506. Accum <<= 8;
  507. Accum |= uF;
  508. TextExpTable[ 9] = Accum; // 1 0 0 1
  509. Accum <<= 8;
  510. Accum |= uF;
  511. TextExpTable[12] = Accum; // 0 0 1 1
  512. Accum <<= 8;
  513. Accum |= uF;
  514. TextExpTable[14] = Accum; // 0 1 1 1
  515. Accum <<= 8;
  516. Accum |= uF;
  517. TextExpTable[15] = Accum; // 1 1 1 1
  518. Accum <<= 8;
  519. Accum |= uB;
  520. TextExpTable[ 7] = Accum; // 1 1 1 0
  521. Accum <<= 8;
  522. Accum |= uF;
  523. TextExpTable[11] = Accum; // 1 1 0 1
  524. Accum <<= 8;
  525. Accum |= uF;
  526. TextExpTable[13] = Accum; // 1 0 1 1
  527. Accum <<= 8;
  528. Accum |= uB;
  529. TextExpTable[06] = Accum; // 0 1 1 0
  530. Accum <<= 8;
  531. Accum |= uB;
  532. TextExpTable[ 3] = Accum; // 1 1 0 0
  533. Accum <<= 8;
  534. Accum |= uB;
  535. TextExpTable[ 1] = Accum; // 1 0 0 0
  536. // calc addresses and strides
  537. pjDst = pjDstIn + LeftAln;
  538. pjDstEndY = pjDst + cy * DeltaDstIn;
  539. pjSrc = pjSrcIn + ((SrcLeft+7) >> 3);
  540. DeltaSrc = DeltaSrcIn - (EndOffset >> 3);
  541. DeltaDst = DeltaDstIn - EndOffset;
  542. // make sure at least 1 QWORD needs copied
  543. if (RightAln > LeftAln) {
  544. // expand buffer
  545. do {
  546. PBYTE pjDstEnd = pjDst + EndOffset;
  547. PBYTE pjDstEnd4 = pjDst + EndOffset4;
  548. PBYTE pjDstEnd8 = pjDst + EndOffset8;
  549. // 4 times unrolled
  550. while (pjDst != pjDstEnd8) {
  551. BYTE c0 = *(pjSrc + 0);
  552. BYTE c1 = *(pjSrc + 1);
  553. BYTE c2 = *(pjSrc + 2);
  554. BYTE c3 = *(pjSrc + 3);
  555. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  556. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  557. *(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4];
  558. *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
  559. *(PULONG)(pjDst +16) = TextExpTable[c2 >> 4];
  560. *(PULONG)(pjDst +20) = TextExpTable[c2 & 0x0F];
  561. *(PULONG)(pjDst +24) = TextExpTable[c3 >> 4];
  562. *(PULONG)(pjDst +28) = TextExpTable[c3 & 0x0F];
  563. pjSrc += 4;
  564. pjDst += 32;
  565. }
  566. // 2 times unrolled
  567. while (pjDst != pjDstEnd4) {
  568. BYTE c0 = *(pjSrc + 0);
  569. BYTE c1 = *(pjSrc + 1);
  570. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  571. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  572. *(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4];
  573. *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
  574. pjSrc += 2;
  575. pjDst += 16;
  576. }
  577. // 1 byte expansion loop
  578. while (pjDst != pjDstEnd) {
  579. BYTE c0 = *(pjSrc + 0);
  580. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  581. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  582. pjSrc++;
  583. pjDst += 8;
  584. }
  585. pjDst += DeltaDst;
  586. pjSrc += DeltaSrc;
  587. } while (pjDst != pjDstEndY);
  588. }
  589. //
  590. // Starting alignment case: at most 1 src byte is required.
  591. // Start and end may occur in same Quadword.
  592. //
  593. //
  594. // Left Right
  595. // 0 1 2 3�4 5 6 7 0 1 2 3�4 5 6 7
  596. // ���������������Ŀ �������ĺ������Ŀ
  597. // 1 � �x�x�x�x�x�x�x� 1 �x� � � � � � � �
  598. // �������ĺ������Ĵ �������ĺ������Ĵ
  599. // 2 � � �x�x�x�x�x�x� 2 �x�x� � � � � � �
  600. // �������ĺ������Ĵ �������ĺ������Ĵ
  601. // 3 � � � �x�x�x�x�x� 3 �x�x�x� � � � � �
  602. // �������ĺ������Ĵ �������ĺ������Ĵ
  603. // 4 � � � � �x�x�x�x� 4 �x�x�x�x� � � � �
  604. // �������ĺ������Ĵ �������ĺ������Ĵ
  605. // 5 � � � � � �x�x�x� 5 �x�x�x�x�x� � � �
  606. // �������ĺ������Ĵ �������ĺ������Ĵ
  607. // 6 � � � � � � �x�x� 6 �x�x�x�x�x�x� � �
  608. // �������ĺ������Ĵ �������ĺ������Ĵ
  609. // 7 � � � � � � � �x� 7 �x�x�x�x�x�x�x� �
  610. // ����������������� ��������������
  611. //
  612. LeftAln = DstLeft & 0x07;
  613. RightAln = DstRight & 0x07;
  614. if (LeftAln) {
  615. BYTE jSrc;
  616. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  617. ULONG ul0,ul1;
  618. // if left and right edges are in same qword handle with masked
  619. // read-modify-write
  620. if (bSameQWord) {
  621. ULONG Mask0,Mask1;
  622. Mask0 = gTextLeftMask[LeftAln][0] & gTextRightMask[RightAln][0];
  623. Mask1 = gTextLeftMask[LeftAln][1] & gTextRightMask[RightAln][1];
  624. pjDst = pjDstIn + (DstLeft & ~0x07);
  625. pjDstEndY = pjDst + cy * DeltaDstIn;
  626. pjSrc = pjSrcIn + (SrcLeft >> 3);
  627. // expand
  628. do {
  629. jSrc = *pjSrc;
  630. ul0 = TextExpTable[jSrc >> 4];
  631. ul1 = TextExpTable[jSrc & 0x0F];
  632. *(PULONG)(pjDst) = (*(PULONG)(pjDst) & ~Mask0) | (ul0 & Mask0);
  633. *(PULONG)(pjDst+4) = (*(PULONG)(pjDst+4) & ~Mask1) | (ul1 & Mask1);
  634. pjDst += DeltaDstIn;
  635. pjSrc += DeltaSrcIn;
  636. } while (pjDst != pjDstEndY);
  637. return;
  638. }
  639. // Left edge only, handle with special write-only loops
  640. pjDst = pjDstIn + (DstLeft & ~0x07);
  641. pjDstEndY = pjDst + cy * DeltaDstIn;
  642. pjSrc = pjSrcIn + (SrcLeft >> 3);
  643. switch (LeftAln) {
  644. case 1:
  645. do {
  646. jSrc = *pjSrc;
  647. ul0 = TextExpTable[jSrc >> 4];
  648. ul1 = TextExpTable[jSrc & 0x0F];
  649. *(pjDst+1) = (BYTE)(ul0 >> 8);
  650. *((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16);
  651. *((PULONG)(pjDst+4)) = ul1;
  652. pjDst += DeltaDstIn;
  653. pjSrc += DeltaSrcIn;
  654. } while (pjDst != pjDstEndY);
  655. break;
  656. case 2:
  657. do {
  658. jSrc = *pjSrc;
  659. ul0 = TextExpTable[jSrc >> 4];
  660. ul1 = TextExpTable[jSrc & 0x0F];
  661. *((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16);
  662. *((PULONG)(pjDst+4)) = ul1;
  663. pjDst += DeltaDstIn;
  664. pjSrc += DeltaSrcIn;
  665. } while (pjDst != pjDstEndY);
  666. break;
  667. case 3:
  668. do {
  669. jSrc = *pjSrc;
  670. ul0 = TextExpTable[jSrc >> 4];
  671. ul1 = TextExpTable[jSrc & 0x0F];
  672. *(pjDst+3) = (BYTE)(ul0 >> 24);
  673. *((PULONG)(pjDst+4)) = ul1;
  674. pjDst += DeltaDstIn;
  675. pjSrc += DeltaSrcIn;
  676. } while (pjDst != pjDstEndY);
  677. break;
  678. case 4:
  679. do {
  680. jSrc = *pjSrc;
  681. ul1 = TextExpTable[jSrc & 0x0F];
  682. *((PULONG)(pjDst+4)) = ul1;
  683. pjDst += DeltaDstIn;
  684. pjSrc += DeltaSrcIn;
  685. } while (pjDst != pjDstEndY);
  686. break;
  687. case 5:
  688. do {
  689. jSrc = *pjSrc;
  690. ul1 = TextExpTable[jSrc & 0x0F];
  691. *(pjDst+5) = (BYTE)(ul1 >> 8);
  692. *((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
  693. pjDst += DeltaDstIn;
  694. pjSrc += DeltaSrcIn;
  695. } while (pjDst != pjDstEndY);
  696. break;
  697. case 6:
  698. do {
  699. jSrc = *pjSrc;
  700. ul1 = TextExpTable[jSrc & 0x0F];
  701. *((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
  702. pjDst += DeltaDstIn;
  703. pjSrc += DeltaSrcIn;
  704. } while (pjDst != pjDstEndY);
  705. break;
  706. case 7:
  707. do {
  708. jSrc = *pjSrc;
  709. ul1 = TextExpTable[jSrc & 0x0F];
  710. *(pjDst+7) = (BYTE)(ul1 >> 24);
  711. pjDst += DeltaDstIn;
  712. pjSrc += DeltaSrcIn;
  713. } while (pjDst != pjDstEndY);
  714. break;
  715. }
  716. }
  717. // handle right edge only, use special write-only loops for each case
  718. if (RightAln) {
  719. ULONG ul0,ul1;
  720. BYTE jSrc;
  721. pjDst = pjDstIn + (DstRight & ~0x07);
  722. pjDstEndY = pjDst + cy * DeltaDstIn;
  723. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  724. // select right case
  725. switch (RightAln) {
  726. case 1:
  727. do {
  728. jSrc = *pjSrc;
  729. ul0 = TextExpTable[jSrc >> 4];
  730. *(pjDst) = (BYTE)ul0;
  731. pjDst += DeltaDstIn;
  732. pjSrc += DeltaSrcIn;
  733. } while (pjDst != pjDstEndY);
  734. break;
  735. case 2:
  736. do {
  737. jSrc = *pjSrc;
  738. ul0 = TextExpTable[jSrc >> 4];
  739. *(PUSHORT)(pjDst) = (USHORT)ul0;
  740. pjDst += DeltaDstIn;
  741. pjSrc += DeltaSrcIn;
  742. } while (pjDst != pjDstEndY);
  743. break;
  744. case 3:
  745. do {
  746. jSrc = *pjSrc;
  747. ul0 = TextExpTable[jSrc >> 4];
  748. *(PUSHORT)(pjDst) = (USHORT)ul0;
  749. *(pjDst+2) = (BYTE)(ul0 >> 16);
  750. pjDst += DeltaDstIn;
  751. pjSrc += DeltaSrcIn;
  752. } while (pjDst != pjDstEndY);
  753. break;
  754. case 4:
  755. do {
  756. jSrc = *pjSrc;
  757. ul0 = TextExpTable[jSrc >> 4];
  758. *(PULONG)(pjDst) = ul0;
  759. pjDst += DeltaDstIn;
  760. pjSrc += DeltaSrcIn;
  761. } while (pjDst != pjDstEndY);
  762. break;
  763. case 5:
  764. do {
  765. jSrc = *pjSrc;
  766. ul0 = TextExpTable[jSrc >> 4];
  767. ul1 = TextExpTable[jSrc & 0x0F];
  768. *(PULONG)(pjDst) = ul0;
  769. *(pjDst+4) = (BYTE)ul1;
  770. pjDst += DeltaDstIn;
  771. pjSrc += DeltaSrcIn;
  772. } while (pjDst != pjDstEndY);
  773. break;
  774. case 6:
  775. do {
  776. jSrc = *pjSrc;
  777. ul0 = TextExpTable[jSrc >> 4];
  778. ul1 = TextExpTable[jSrc & 0x0F];
  779. *(PULONG)(pjDst) = ul0;
  780. *(PUSHORT)(pjDst+4) = (USHORT)ul1;
  781. pjDst += DeltaDstIn;
  782. pjSrc += DeltaSrcIn;
  783. } while (pjDst != pjDstEndY);
  784. break;
  785. case 7:
  786. do {
  787. jSrc = *pjSrc;
  788. ul0 = TextExpTable[jSrc >> 4];
  789. ul1 = TextExpTable[jSrc & 0x0F];
  790. *(PULONG)(pjDst) = ul0;
  791. *(PUSHORT)(pjDst+4) = (USHORT)ul1;
  792. *(pjDst+6) = (BYTE)(ul1 >> 16);
  793. pjDst += DeltaDstIn;
  794. pjSrc += DeltaSrcIn;
  795. } while (pjDst != pjDstEndY);
  796. break;
  797. }
  798. }
  799. }
  800. #ifdef DC_HICOLOR
  801. /******************************Public*Routine******************************\
  802. * vSrcTranCopyS1D8_24
  803. *
  804. * Transparent blt of 1BPP src to 24bpp destination
  805. * src bits that are "1" are copied to the dest as foreground color,
  806. * src bits that are "0" are not copied
  807. *
  808. * Arguments:
  809. * pjSrcIn - pointer to beginning of current scan line of src buffer
  810. * SrcLeft - left (starting) pixel in src rectangle
  811. * DeltaSrcIn - bytes from one src scan line to next
  812. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  813. * DstLeft - left(first) dst pixel
  814. * DstRight - right(last) dst pixel
  815. * DeltaDstIn - bytes from one Dst scan line to next
  816. * cy - number of scan lines
  817. * fgCol - Foreground color
  818. \**************************************************************************/
  819. VOID CGH::vSrcTranCopyS1D8_24(
  820. PBYTE pjSrcIn,
  821. LONG SrcLeft,
  822. LONG DeltaSrcIn,
  823. PBYTE pjDstIn,
  824. LONG DstLeft,
  825. LONG DstRight,
  826. LONG DeltaDstIn,
  827. LONG cy,
  828. DCRGB fgCol)
  829. {
  830. // We access the 1bpp source a byte at a time, so we have to start accessing
  831. // the destination on a corresponding 8-pel aligned left edge
  832. ULONG LeftAln = (DstLeft & ~0x07);
  833. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  834. ULONG RightAln = (DstRight & ~0x07);
  835. ULONG AlnDelta = RightAln - LeftAln;
  836. LONG DeltaDst;
  837. LONG DeltaSrc;
  838. PBYTE pjDstEndY;
  839. PBYTE pjSrc;
  840. PBYTE pjDst;
  841. DC_BEGIN_FN("vSrcTranCopyS1D8_24");
  842. // calculate the pel-aligned pointers and row deltas
  843. pjDst = pjDstIn + LeftAln * 3;
  844. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  845. pjSrc = pjSrcIn + (SrcLeft >> 3);
  846. DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
  847. DeltaDst = (DeltaDstIn - AlnDelta) * 3;
  848. // make sure at least 1 QWORD needs copying
  849. if (RightAln != LeftAln)
  850. {
  851. // for each row...
  852. do
  853. {
  854. PBYTE pjDstEnd = pjDst + AlnDelta * 3;
  855. // Mask off the left edge
  856. BYTE currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
  857. if (currentPels != 0)
  858. {
  859. int i;
  860. for (i = 0; i < 8 ; i++)
  861. {
  862. if ((currentPels & 0x80) == 0)
  863. {
  864. pjDst += 3;
  865. }
  866. else
  867. {
  868. *pjDst++ = fgCol.blue;
  869. *pjDst++ = fgCol.green;
  870. *pjDst++ = fgCol.red;
  871. }
  872. currentPels = (BYTE)(currentPels << 1);
  873. }
  874. }
  875. else
  876. {
  877. pjDst += 24;
  878. }
  879. pjSrc ++;
  880. // now do the rest of the row
  881. while (pjDst != pjDstEnd)
  882. {
  883. currentPels = *pjSrc;
  884. if (currentPels != 0)
  885. {
  886. int i;
  887. for (i = 0; i < 8 ; i++)
  888. {
  889. if ((currentPels & 0x80) == 0)
  890. {
  891. pjDst += 3;
  892. }
  893. else
  894. {
  895. *pjDst++ = fgCol.blue;
  896. *pjDst++ = fgCol.green;
  897. *pjDst++ = fgCol.red;
  898. }
  899. currentPels = (BYTE)(currentPels << 1);
  900. }
  901. }
  902. else
  903. {
  904. pjDst += 24;
  905. }
  906. pjSrc++;
  907. }
  908. pjDst += DeltaDst;
  909. pjSrc += DeltaSrc;
  910. } while (pjDst != pjDstEndY);
  911. }
  912. // Now fill in the right edge
  913. RightAln = DstRight & 0x07;
  914. if (RightAln)
  915. {
  916. BYTE currentPels;
  917. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  918. LeftAln = DstLeft & 0x07;
  919. // if left and right edges are in same qword handle with masked
  920. // read-modify-write
  921. if (bSameQWord)
  922. {
  923. LONG xCount;
  924. LONG lDeltaDst;
  925. PBYTE pjDstEnd;
  926. xCount = RightAln - LeftAln;
  927. // sanity checks!
  928. if (xCount <= 0)
  929. {
  930. return;
  931. }
  932. lDeltaDst = (DeltaDstIn - xCount) * 3;
  933. pjDst = pjDstIn + DstLeft * 3;
  934. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  935. pjSrc = pjSrcIn + (SrcLeft >> 3);
  936. // expand, one src byte is all that's required
  937. do
  938. {
  939. // load src and shift into place
  940. currentPels = *pjSrc;
  941. currentPels <<= LeftAln;
  942. pjDstEnd = pjDst + xCount * 3;
  943. do
  944. {
  945. if ((currentPels & 0x80) == 0)
  946. {
  947. pjDst += 3;
  948. }
  949. else
  950. {
  951. *pjDst++ = fgCol.blue;
  952. *pjDst++ = fgCol.green;
  953. *pjDst++ = fgCol.red;
  954. }
  955. currentPels = (BYTE)(currentPels << 1);
  956. } while (pjDst != pjDstEnd);
  957. pjDst += lDeltaDst;
  958. pjSrc += DeltaSrcIn;
  959. } while (pjDst != pjDstEndY);
  960. return;
  961. }
  962. else
  963. {
  964. BYTE currentPels;
  965. LONG lDeltaDst = (DeltaDstIn - RightAln) * 3;
  966. PBYTE pjDstEnd;
  967. pjDst = pjDstIn + (DstRight & ~0x07) * 3;
  968. pjDstEndY = pjDst + cy * DeltaDstIn * 3;
  969. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  970. do
  971. {
  972. // read src
  973. currentPels = *pjSrc;
  974. if (currentPels != 0)
  975. {
  976. pjDstEnd = pjDst + RightAln * 3;
  977. do
  978. {
  979. if ((currentPels & 0x80) == 0)
  980. {
  981. pjDst += 3;
  982. }
  983. else
  984. {
  985. *pjDst++ = fgCol.blue;
  986. *pjDst++ = fgCol.green;
  987. *pjDst++ = fgCol.red;
  988. }
  989. currentPels = (BYTE)(currentPels << 1);
  990. } while (pjDst != pjDstEnd);
  991. }
  992. else
  993. {
  994. // short cut for zero
  995. pjDst += RightAln * 3;
  996. }
  997. pjDst += lDeltaDst;
  998. pjSrc += DeltaSrcIn;
  999. } while (pjDst != pjDstEndY);
  1000. }
  1001. }
  1002. DC_END_FN();
  1003. }
  1004. /******************************Public*Routine******************************\
  1005. * vSrcTranCopyS1D8_16
  1006. *
  1007. * Transparent blt of 1BPP src to 16bpp destination
  1008. * src bits that are "1" are copied to the dest as foreground color,
  1009. * src bits that are "0" are not copied
  1010. *
  1011. * Arguments:
  1012. * pjSrcIn - pointer to beginning of current scan line of src buffer
  1013. * SrcLeft - left (starting) pixel in src rectangle
  1014. * DeltaSrcIn - bytes from one src scan line to next
  1015. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  1016. * DstLeft - left(first) dst pixel
  1017. * DstRight - right(last) dst pixel
  1018. * DeltaDstIn - bytes from one Dst scan line to next
  1019. * cy - number of scan lines
  1020. * fgCol - Foreground color
  1021. \**************************************************************************/
  1022. VOID CGH::vSrcTranCopyS1D8_16(
  1023. PBYTE pjSrcIn,
  1024. LONG SrcLeft,
  1025. LONG DeltaSrcIn,
  1026. PBYTE pjDstIn,
  1027. LONG DstLeft,
  1028. LONG DstRight,
  1029. LONG DeltaDstIn,
  1030. LONG cy,
  1031. ULONG fgCol)
  1032. {
  1033. // We access the 1bpp source a byte at a time, so we have to start accessing
  1034. // the destination on a corresponding 8-pel aligned left edge
  1035. ULONG LeftAln = (DstLeft & ~0x07);
  1036. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  1037. ULONG RightAln = (DstRight & ~0x07);
  1038. ULONG AlnDelta = RightAln - LeftAln;
  1039. LONG DeltaDst;
  1040. LONG DeltaSrc;
  1041. PBYTE pjDstEndY;
  1042. PBYTE pjSrc;
  1043. PBYTE pjDst;
  1044. DC_BEGIN_FN("vSrcTranCopyS1D8_16");
  1045. // calculate the pel-aligned pointers and row deltas
  1046. pjDst = pjDstIn + LeftAln * 2;
  1047. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  1048. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1049. DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
  1050. DeltaDst = (DeltaDstIn - AlnDelta) * 2;
  1051. // make sure at least 1 QWORD needs copying
  1052. if (RightAln != LeftAln)
  1053. {
  1054. // for each row...
  1055. do
  1056. {
  1057. PBYTE pjDstEnd = pjDst + AlnDelta * 2;
  1058. // Mask off the left edge
  1059. BYTE currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
  1060. if (currentPels != 0)
  1061. {
  1062. int i;
  1063. for (i = 0; i < 8 ; i++)
  1064. {
  1065. if (currentPels & 0x80)
  1066. {
  1067. *(UINT16 *)pjDst = (UINT16)fgCol;
  1068. }
  1069. pjDst += 2;
  1070. currentPels = (BYTE)(currentPels << 1);
  1071. }
  1072. }
  1073. else
  1074. {
  1075. pjDst += 16;
  1076. }
  1077. pjSrc ++;
  1078. // now do the rest of the row
  1079. while (pjDst != pjDstEnd)
  1080. {
  1081. currentPels = *pjSrc;
  1082. if (currentPels != 0)
  1083. {
  1084. int i;
  1085. for (i = 0; i < 8 ; i++)
  1086. {
  1087. if (currentPels & 0x80)
  1088. {
  1089. *(UINT16 *)pjDst = (UINT16)fgCol;
  1090. }
  1091. pjDst += 2;
  1092. currentPels = (BYTE)(currentPels << 1);
  1093. }
  1094. }
  1095. else
  1096. {
  1097. pjDst += 16;
  1098. }
  1099. pjSrc++;
  1100. }
  1101. pjDst += DeltaDst;
  1102. pjSrc += DeltaSrc;
  1103. } while (pjDst != pjDstEndY);
  1104. }
  1105. // Now fill in the right edge
  1106. RightAln = DstRight & 0x07;
  1107. if (RightAln)
  1108. {
  1109. BYTE currentPels;
  1110. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  1111. LeftAln = DstLeft & 0x07;
  1112. // if left and right edges are in same qword handle with masked
  1113. // read-modify-write
  1114. if (bSameQWord)
  1115. {
  1116. LONG xCount;
  1117. LONG lDeltaDst;
  1118. PBYTE pjDstEnd;
  1119. xCount = RightAln - LeftAln;
  1120. // sanity checks!
  1121. if (xCount <= 0)
  1122. {
  1123. return;
  1124. }
  1125. lDeltaDst = (DeltaDstIn - xCount) * 2;
  1126. pjDst = pjDstIn + DstLeft * 2;
  1127. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  1128. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1129. // expand, one src byte is all that's required
  1130. do
  1131. {
  1132. // load src and shift into place
  1133. currentPels = *pjSrc;
  1134. currentPels <<= LeftAln;
  1135. pjDstEnd = pjDst + xCount * 2;
  1136. do
  1137. {
  1138. if (currentPels & 0x80)
  1139. {
  1140. *(UINT16 *)pjDst = (UINT16)fgCol;
  1141. }
  1142. pjDst += 2;
  1143. currentPels = (BYTE)(currentPels << 1);
  1144. } while (pjDst != pjDstEnd);
  1145. pjDst += lDeltaDst;
  1146. pjSrc += DeltaSrcIn;
  1147. } while (pjDst != pjDstEndY);
  1148. return;
  1149. }
  1150. else
  1151. {
  1152. BYTE currentPels;
  1153. LONG lDeltaDst = (DeltaDstIn - RightAln) * 2;
  1154. PBYTE pjDstEnd;
  1155. pjDst = pjDstIn + (DstRight & ~0x07) * 2;
  1156. pjDstEndY = pjDst + cy * DeltaDstIn * 2;
  1157. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  1158. do
  1159. {
  1160. // read src
  1161. currentPels = *pjSrc;
  1162. if (currentPels != 0)
  1163. {
  1164. pjDstEnd = pjDst + RightAln * 2;
  1165. do
  1166. {
  1167. if (currentPels & 0x80)
  1168. {
  1169. *(UINT16 *)pjDst = (UINT16)fgCol;
  1170. }
  1171. pjDst += 2;
  1172. currentPels = (BYTE)(currentPels << 1);
  1173. } while (pjDst != pjDstEnd);
  1174. }
  1175. else
  1176. {
  1177. // short cut for zero
  1178. pjDst += RightAln * 2;
  1179. }
  1180. pjDst += lDeltaDst;
  1181. pjSrc += DeltaSrcIn;
  1182. } while (pjDst != pjDstEndY);
  1183. }
  1184. }
  1185. DC_END_FN();
  1186. }
  1187. #endif // DC_HICOLOR
  1188. /******************************Public*Routine******************************\
  1189. * vSrcTranCopyS1D8
  1190. *
  1191. #ifdef DC_HICOLOR
  1192. * Transparent blt of 1BPP src to 8bpp destination
  1193. #else
  1194. * Transparent blt of 1BPP src to all destination format
  1195. #endif
  1196. * src bits that are "1" are copied to the dest as foreground color,
  1197. * src bits that are "0" are not copied
  1198. *
  1199. * Arguments:
  1200. * pjSrcIn - pointer to beginning of current scan line of src buffer
  1201. * SrcLeft - left (starting) pixel in src rectangle
  1202. * DeltaSrcIn - bytes from one src scan line to next
  1203. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  1204. * DstLeft - left(first) dst pixel
  1205. * DstRight - right(last) dst pixel
  1206. * DeltaDstIn - bytes from one Dst scan line to next
  1207. * cy - number of scan lines
  1208. * uF - Foreground color
  1209. * uB - Background color
  1210. \**************************************************************************/
  1211. VOID CGH::vSrcTranCopyS1D8(
  1212. PBYTE pjSrcIn,
  1213. LONG SrcLeft,
  1214. LONG DeltaSrcIn,
  1215. PBYTE pjDstIn,
  1216. LONG DstLeft,
  1217. LONG DstRight,
  1218. LONG DeltaDstIn,
  1219. LONG cy,
  1220. ULONG uF,
  1221. ULONG uB)
  1222. {
  1223. // start at 8-byte aligned left edge
  1224. ULONG uExpand = uF | (uF << 8);
  1225. ULONG LeftAln = (DstLeft & ~0x07);
  1226. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  1227. ULONG RightAln = (DstRight & ~0x07);
  1228. ULONG EndOffset = RightAln - LeftAln;
  1229. LONG DeltaDst;
  1230. LONG DeltaSrc;
  1231. PBYTE pjDstEndY;
  1232. PBYTE pjSrc;
  1233. PBYTE pjDst;
  1234. DC_IGNORE_PARAMETER(uB);
  1235. uExpand = uExpand | (uExpand << 16);
  1236. // calc addresses and strides
  1237. pjDst = pjDstIn + LeftAln;
  1238. pjDstEndY = pjDst + cy * DeltaDstIn;
  1239. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1240. DeltaSrc = DeltaSrcIn - (EndOffset >> 3);
  1241. DeltaDst = DeltaDstIn - EndOffset;
  1242. // make sure at least 1 QWORD needs copied
  1243. if (RightAln != LeftAln) {
  1244. do {
  1245. PBYTE pjDstEnd = pjDst + EndOffset;
  1246. // and first src byte to cover left edge
  1247. BYTE c0 = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
  1248. if (c0 != 0) {
  1249. ULONG MaskLow = TranTable[c0 >> 4];
  1250. ULONG MaskHi = TranTable[c0 & 0x0F];
  1251. ULONG d0 = *(PULONG)pjDst;
  1252. ULONG d1 = *(PULONG)(pjDst + 4);
  1253. d0 = (d0 & ~MaskLow) | (uExpand & MaskLow);
  1254. d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
  1255. *(PULONG)pjDst = d0;
  1256. *(PULONG)(pjDst + 4) = d1;
  1257. }
  1258. pjSrc ++;
  1259. pjDst += 8;
  1260. while (pjDst != pjDstEnd) {
  1261. c0 = *pjSrc;
  1262. if (c0 != 0) {
  1263. ULONG MaskLow = TranTable[c0 >> 4];
  1264. ULONG MaskHi = TranTable[c0 & 0x0F];
  1265. ULONG d0 = *(PULONG)pjDst;
  1266. ULONG d1 = *(PULONG)(pjDst + 4);
  1267. d0 = (d0 & ~MaskLow) | (uExpand & MaskLow);
  1268. d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
  1269. *(PULONG)pjDst = d0;
  1270. *(PULONG)(pjDst + 4) = d1;
  1271. }
  1272. pjSrc ++;
  1273. pjDst += 8;
  1274. }
  1275. pjDst += DeltaDst;
  1276. pjSrc += DeltaSrc;
  1277. } while (pjDst != pjDstEndY);
  1278. }
  1279. RightAln = DstRight & 0x07;
  1280. if (RightAln) {
  1281. BYTE jSrc;
  1282. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  1283. // if left and right edges are in same qword handle with masked
  1284. // read-modify-write
  1285. if (bSameQWord) {
  1286. LONG xCount;
  1287. LONG lDeltaDst;
  1288. PBYTE pjDstEnd;
  1289. LeftAln = DstLeft & 0x07;
  1290. xCount = RightAln - LeftAln;
  1291. // assert ic xCount < 0
  1292. if (xCount <= 0)
  1293. return;
  1294. lDeltaDst = DeltaDstIn - xCount;
  1295. pjDst = pjDstIn + DstLeft;
  1296. pjDstEndY = pjDst + cy * DeltaDstIn;
  1297. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1298. // expand, one src byte is all that's required
  1299. do {
  1300. // load src and shift into place
  1301. jSrc = *pjSrc;
  1302. jSrc <<= LeftAln;
  1303. pjDstEnd = pjDst + xCount;
  1304. do {
  1305. if (jSrc & 0x80)
  1306. *pjDst = (BYTE)uF;
  1307. jSrc <<=1;
  1308. pjDst++;
  1309. } while (pjDst != pjDstEnd);
  1310. pjDst += lDeltaDst;
  1311. pjSrc += DeltaSrcIn;
  1312. } while (pjDst != pjDstEndY);
  1313. return;
  1314. } else {
  1315. BYTE jSrc;
  1316. LONG lDeltaDst = DeltaDstIn - RightAln;
  1317. PBYTE pjDstEnd;
  1318. pjDst = pjDstIn + (DstRight & ~0x07);
  1319. pjDstEndY = pjDst + cy * DeltaDstIn;
  1320. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  1321. do {
  1322. // read src
  1323. jSrc = *pjSrc;
  1324. if (jSrc != 0) {
  1325. pjDstEnd = pjDst + RightAln;
  1326. do {
  1327. if (jSrc & 0x80)
  1328. *pjDst = (BYTE)uF;
  1329. jSrc <<=1;
  1330. pjDst++;
  1331. } while (pjDst != pjDstEnd);
  1332. } else {
  1333. // short cut for zero
  1334. pjDst += RightAln;
  1335. }
  1336. pjDst += lDeltaDst;
  1337. pjSrc += DeltaSrcIn;
  1338. } while (pjDst != pjDstEndY);
  1339. }
  1340. }
  1341. }
  1342. #endif // defined(OS_WINCE) || defined(OS_WINNT)
  1343. /****************************************************************************/
  1344. /* Name: CalculateGlyphClipRect */
  1345. /* */
  1346. /* This function is used to determine if the glyph bits should be clipped */
  1347. /* using the clip rect passed in the order. */
  1348. /* */
  1349. /* It returns one of the values bellow: */
  1350. /* GLYPH_CLIP_NONE-The glyph will fit in the clip rect.No clipping needed */
  1351. /* GLYPH_CLIP_PARTIAL-The glyph is clipped by the clip rect */
  1352. /* GLYPH_CLIP_ALL - The glyph is completly clipped. */
  1353. /* */
  1354. /* */
  1355. /* Params: pGlyphRectClipOffset - OUT - it receives the clip offsets */
  1356. /* pOrder - Pointer to the order */
  1357. /* pHdr - Pointer to the glyph header */
  1358. /* x,y - The coord where the glyph will be drawn */
  1359. /****************************************************************************/
  1360. inline DCUINT CalculateGlyphClipRect( PRECTCLIPOFFSET pGlyphRectClipOffset,
  1361. LPINDEX_ORDER pOrder,
  1362. HPUHGLYPHCACHEENTRYHDR pHdr,
  1363. DCINT x,
  1364. DCINT y)
  1365. {
  1366. RECT rcGlyph;
  1367. DC_BEGIN_FN("CalculateGlyphClipRect");
  1368. // Here we calculate how the glyph bits will map in the clip rect.
  1369. rcGlyph.left = x + pHdr->x;
  1370. rcGlyph.top = y + pHdr->y;
  1371. rcGlyph.right = rcGlyph.left + pHdr->cx;
  1372. rcGlyph.bottom = rcGlyph.top + pHdr->cy;
  1373. // Check if the clip rect clips the glyph rect all the way
  1374. if ((rcGlyph.left >= pOrder->BkRight) ||
  1375. (rcGlyph.right <= pOrder->BkLeft) ||
  1376. (rcGlyph.top >= pOrder->BkBottom) ||
  1377. (rcGlyph.bottom <= pOrder->BkTop)) {
  1378. return GLYPH_CLIP_ALL;
  1379. }
  1380. pGlyphRectClipOffset->left = pOrder->BkLeft - rcGlyph.left;
  1381. pGlyphRectClipOffset->top = pOrder->BkTop - rcGlyph.top;
  1382. pGlyphRectClipOffset->right = rcGlyph.right - pOrder->BkRight;
  1383. pGlyphRectClipOffset->bottom = rcGlyph.bottom - pOrder->BkBottom;
  1384. if ((pGlyphRectClipOffset->left > 0) ||
  1385. (pGlyphRectClipOffset->top > 0) ||
  1386. (pGlyphRectClipOffset->right > 0) ||
  1387. (pGlyphRectClipOffset->bottom > 0)) {
  1388. return GLYPH_CLIP_PARTIAL;
  1389. };
  1390. DC_END_FN();
  1391. return GLYPH_CLIP_NONE;
  1392. }
  1393. /****************************************************************************/
  1394. /* Name: ClipGlyphBits */
  1395. /* */
  1396. /* This function will clip the glyph bits according to the clipping rect. */
  1397. /* It will actually generate a new glyph that would fit inside the */
  1398. /* clip rect. */
  1399. /* */
  1400. /* Params: inst - pointer to a CGH instance */
  1401. /* pGlyphRectClipOffset - Pointer to the glyph clip offset struct */
  1402. /* filled in by CalculateGlyphClipRect */
  1403. /* pHdr - Pointer to the glyph header. This will */
  1404. /* be modified accordingly */
  1405. /* ppData (IN/OUT) - Pointer to the start of the glyph bits */
  1406. /* ppEndData (IN/OUT) - Pointer to the end of the glyph bits */
  1407. /****************************************************************************/
  1408. inline HRESULT ClipGlyphBits(CGH* inst,
  1409. PRECTCLIPOFFSET pGlyphRectClipOffset,
  1410. HPUHGLYPHCACHEENTRYHDR pHdr,
  1411. PPDCUINT8 ppData,
  1412. PPDCUINT8 ppEndData)
  1413. {
  1414. HRESULT hr = S_OK;
  1415. PDCUINT8 pNewData, pNewDataEnd;
  1416. DCUINT ScanLineSize, NewScanLineSize;
  1417. DCUINT LastByteIndex;
  1418. DCUINT8 LastByteMask;
  1419. DCUINT16 wTmp;
  1420. DCUINT8 clipRightMask, clipLeftBits, clipRightBits;
  1421. DCUINT clipLeftBytes;
  1422. DCUINT i,j;
  1423. PDCUINT8 pSrcScanLineStart, pDstScanLineStart, pTmpData, pEndTmpData;
  1424. DC_BEGIN_FN("ClipGlyphBits");
  1425. ScanLineSize = (pHdr->cx+7) / 8;
  1426. // If we have to clip from the top we just decrease the
  1427. // number of scanlines in the glyph and advance the start
  1428. // pointer for the glyph bitmap.
  1429. if (pGlyphRectClipOffset->top > 0) {
  1430. // When we clip the top of the glypy we will modify the actual origin
  1431. // of the glyph so we have to adjust the vector.
  1432. pHdr->y += pGlyphRectClipOffset->top;
  1433. // We decrease the height of the glyph
  1434. pHdr->cy -= pGlyphRectClipOffset->top;
  1435. // We move the start pointer
  1436. pNewData = *ppData + ScanLineSize * (pGlyphRectClipOffset->top);
  1437. } else {
  1438. pNewData = *ppData;
  1439. }
  1440. // If we have to clip the bootom we just decrease the number
  1441. // of lines in the glyph and we adjust the end pointer.
  1442. if (pGlyphRectClipOffset->bottom > 0) {
  1443. pHdr->cy -= pGlyphRectClipOffset->bottom;
  1444. pNewDataEnd = pNewData + ScanLineSize * pHdr->cy;
  1445. } else {
  1446. pNewDataEnd = *ppEndData;
  1447. }
  1448. // Check that the new pointers are still inside the src buffer.
  1449. TRC_ASSERT(((pNewData >=*ppData) && (pNewDataEnd <= *ppEndData)),
  1450. (TB, _T("Error recalculating the glyph src buffer")));
  1451. // In case we clipped only top/bottom we don't have to do any copy
  1452. // operation because the scanline start and the scanlise size remains
  1453. // the same. We just adjust pointers. In case we have to clip from the
  1454. // width we have to generate a new glyph and return its start address
  1455. // in ppData. In case we clip to the left we have to rotate some bits.
  1456. // in case we clip to the right we have to mask some bits.
  1457. clipRightMask = 0xff;
  1458. if ((pGlyphRectClipOffset->right > 0) ||
  1459. (pGlyphRectClipOffset->left > 0)) {
  1460. if (pGlyphRectClipOffset->right > 0) {
  1461. // Calculate how many bits are we gonna clip to the right
  1462. clipRightBits = (DCUINT8)(pGlyphRectClipOffset->right & 7);
  1463. // Then adjust the with of the glyph
  1464. pHdr->cx -= pGlyphRectClipOffset->right;
  1465. } else {
  1466. clipRightBits = 0;
  1467. }
  1468. if (pGlyphRectClipOffset->left > 0) {
  1469. // Calculate how many bytes we clip to the left. These are bytes
  1470. // we just won't copy. Then calculate how many bits are left to
  1471. // clip after we clip the bytes. This will tell us how much we
  1472. // have to rotate.
  1473. clipLeftBytes = pGlyphRectClipOffset->left / 8;
  1474. clipLeftBits = (DCUINT8)(pGlyphRectClipOffset->left & 7);
  1475. // Adjust the glyph width
  1476. pHdr->cx -= pGlyphRectClipOffset->left;
  1477. // Adjust the origin pointer. Clipping to the right actually
  1478. // modifies the origin.
  1479. pHdr->x += pGlyphRectClipOffset->left;
  1480. } else {
  1481. clipLeftBytes = 0;
  1482. clipLeftBits = 0;
  1483. }
  1484. //
  1485. // We check if we have to keep some bits at the end of the
  1486. // scanline. We update the mask...
  1487. if ((pHdr->cx+clipLeftBits) & 7) {
  1488. clipRightMask <<= ( 8 - ((pHdr->cx + clipLeftBits) & 7) );
  1489. }
  1490. NewScanLineSize = (pHdr->cx+7) / 8;
  1491. // This buffer is maintained by CGH. We don't have to free it.
  1492. pTmpData = inst->GetGlyphClipBuffer(NewScanLineSize * pHdr->cy);
  1493. if (pTmpData == NULL) {
  1494. hr = E_OUTOFMEMORY;
  1495. DC_QUIT;
  1496. }
  1497. pEndTmpData = pTmpData + NewScanLineSize * pHdr->cy;
  1498. pSrcScanLineStart = pNewData + clipLeftBytes;
  1499. pDstScanLineStart = pTmpData;
  1500. if (clipLeftBits == 0) {
  1501. // In case we don't clip to the left we don't have to rotate so
  1502. // things go faster.
  1503. for (i=0; i < pHdr->cy; i++) {
  1504. memcpy(pDstScanLineStart, pSrcScanLineStart, NewScanLineSize);
  1505. pDstScanLineStart[NewScanLineSize-1] &= clipRightMask;
  1506. pSrcScanLineStart += ScanLineSize;
  1507. pDstScanLineStart += NewScanLineSize;
  1508. }
  1509. } else {
  1510. // The transfer requires rotation
  1511. // We check to see if we need the last byte.
  1512. LastByteIndex = ((pHdr->cx + clipLeftBits + 7) / 8) - 1;
  1513. // LastByteIndex+1 is equal to the size of a scanline before
  1514. // clipping the left bits. If this size is grater then NewScanLineSize
  1515. // it means that clipping to the left would shrink the buffer with
  1516. // one byte and that some of the bits we need have to be transfered
  1517. // from that last byte.
  1518. // Note that LastByteIndex+1 can be grater then NewScanLineSize only
  1519. // with 1 byte.
  1520. // this is the case where LastByteIndex+1 is grater then NewScanLineSize
  1521. if ((LastByteIndex==NewScanLineSize)) {
  1522. for (i=0; i < pHdr->cy; i++) {
  1523. TRC_ASSERT(((pSrcScanLineStart + NewScanLineSize - 1 < pNewDataEnd) &&
  1524. (pDstScanLineStart + NewScanLineSize - 1 < pEndTmpData)),
  1525. (TB, _T("Overflow transfering glyph bits.")));
  1526. wTmp = (pSrcScanLineStart[LastByteIndex] & clipRightMask) <<
  1527. clipLeftBits;
  1528. for (j=NewScanLineSize; j>0; j--) {
  1529. pDstScanLineStart[j-1] = HIBYTE(wTmp);
  1530. wTmp = pSrcScanLineStart[j-1] << clipLeftBits;
  1531. pDstScanLineStart[j-1] |= LOBYTE(wTmp);
  1532. }
  1533. pSrcScanLineStart += ScanLineSize;
  1534. pDstScanLineStart += NewScanLineSize;
  1535. }
  1536. }else {
  1537. for (i=0; i < pHdr->cy; i++) {
  1538. TRC_ASSERT(((pSrcScanLineStart + NewScanLineSize - 1 < pNewDataEnd) &&
  1539. (pDstScanLineStart + NewScanLineSize - 1 < pEndTmpData)),
  1540. (TB, _T("Overflow transfering glyph bits.")));
  1541. wTmp = (pSrcScanLineStart[LastByteIndex] & clipRightMask) <<
  1542. clipLeftBits;
  1543. pDstScanLineStart[NewScanLineSize-1] = LOBYTE(wTmp);
  1544. for (j=NewScanLineSize-1; j>0; j--) {
  1545. pDstScanLineStart[j-1] = HIBYTE(wTmp);
  1546. wTmp = pSrcScanLineStart[j-1] << clipLeftBits;
  1547. pDstScanLineStart[j-1] |= LOBYTE(wTmp);
  1548. }
  1549. pSrcScanLineStart += ScanLineSize;
  1550. pDstScanLineStart += NewScanLineSize;
  1551. }
  1552. }
  1553. }
  1554. *ppData = pTmpData;
  1555. *ppEndData = pEndTmpData;
  1556. } else {
  1557. *ppData = pNewData;
  1558. *ppEndData = pNewDataEnd;
  1559. }
  1560. DC_EXIT_POINT:
  1561. DC_END_FN();
  1562. return hr;
  1563. }
  1564. inline BOOL CheckSourceGlyphBits(UINT32 cx,
  1565. UINT32 cy,
  1566. PDCUINT8 pStart,
  1567. PDCUINT8 pEnd)
  1568. {
  1569. DC_BEGIN_FN("CheckSourceGlyphBits");
  1570. UINT32 SrcScanLineSize = (cx+7) / 8;
  1571. UINT32 SrcBitmapSize = SrcScanLineSize & cy ;
  1572. TRC_ASSERT((pEnd >= pStart),(TB, _T("pEnd is less then pStart!!")));
  1573. DC_END_FN();
  1574. return ((SrcBitmapSize <= (UINT32)((PBYTE)pEnd - (PBYTE)pStart)) &&
  1575. (SrcBitmapSize <= SrcScanLineSize) &&
  1576. (SrcBitmapSize <= cy));
  1577. }
  1578. /****************************************************************************/
  1579. /* Name: GHSlowOutputBuffer */
  1580. /* */
  1581. /* Routine to output the composite glyphout buffer via normal bitblt */
  1582. /* operation(s) */
  1583. /* */
  1584. /* Params: pOrder - Pointer to glyph index order */
  1585. /* pData - Pointer to composite glyph buffer */
  1586. /* BufferAlign - Buffer alignment */
  1587. /* ulBufferWidth - Buffer width (in bytes) */
  1588. /****************************************************************************/
  1589. void DCINTERNAL CGH::GHSlowOutputBuffer(
  1590. LPINDEX_ORDER pOrder,
  1591. PDCUINT8 pData,
  1592. ULONG BufferAlign,
  1593. unsigned ulBufferWidth)
  1594. {
  1595. HBITMAP hbmOld;
  1596. unsigned cxBits;
  1597. unsigned cyBits;
  1598. #ifndef OS_WINCE
  1599. DCCOLOR color;
  1600. DWORD dwRop;
  1601. #ifdef DISABLE_SHADOW_IN_FULLSCREEN
  1602. COLORREF rgb;
  1603. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  1604. #else // OS_WINCE
  1605. HBRUSH hbr;
  1606. COLORREF rgb;
  1607. #endif // OS_WINCE
  1608. DC_BEGIN_FN("GHSlowOutputBuffer");
  1609. /************************************************************************/
  1610. /* Use the glyph GDI resources */
  1611. /************************************************************************/
  1612. // Calculate the proper cx and cy aligned sizes.
  1613. cxBits = (int)(ulBufferWidth << 3);
  1614. cyBits = (int)(pOrder->BkBottom - pOrder->BkTop);
  1615. #ifdef OS_WINCE
  1616. // Create a bitmap with the composite glyph data provided.
  1617. _pUh->_UH.hbmGlyph = CreateBitmap(cxBits, cyBits, 1, 1, pData);
  1618. if (_pUh->_UH.hbmGlyph == NULL) {
  1619. TRC_NRM((TB, _T("Unable to create composite glyph bitmap")));
  1620. DC_QUIT;
  1621. }
  1622. #else
  1623. // If the current cache bitmap is not large enough to accomodate the
  1624. // request, then free it so we can alloc one properly sized.
  1625. if (cxBits != _pUh->_UH.cxGlyphBits || cyBits > _pUh->_UH.cyGlyphBits) {
  1626. if (_pUh->_UH.hbmGlyph != NULL) {
  1627. DeleteObject(_pUh->_UH.hbmGlyph);
  1628. _pUh->_UH.hbmGlyph = NULL;
  1629. goto NullGlyphBitmap;
  1630. }
  1631. }
  1632. // If we have a bitmap of sufficient dimensions, then just set the bits
  1633. // otherwise we need to alloc a new bitmap with the given data.
  1634. if (_pUh->_UH.hbmGlyph != NULL) {
  1635. SetBitmapBits(_pUh->_UH.hbmGlyph, (cxBits * cyBits) >> 3, pData);
  1636. }
  1637. else {
  1638. NullGlyphBitmap:
  1639. _pUh->_UH.hbmGlyph = CreateBitmap(cxBits, cyBits, 1, 1, pData);
  1640. if (_pUh->_UH.hbmGlyph != NULL) {
  1641. _pUh->_UH.cxGlyphBits = cxBits;
  1642. _pUh->_UH.cyGlyphBits = cyBits;
  1643. }
  1644. else {
  1645. TRC_NRM((TB, _T("Unable to create composite glyph bitmap")));
  1646. DC_QUIT;
  1647. }
  1648. }
  1649. #endif
  1650. // Create a DC for the composite bitmap and load it into it.
  1651. if (_pUh->_UH.hdcGlyph == NULL)
  1652. _pUh->_UH.hdcGlyph = CreateCompatibleDC(NULL);
  1653. if (_pUh->_UH.hdcGlyph != NULL) {
  1654. hbmOld = (HBITMAP)SelectObject(_pUh->_UH.hdcGlyph, _pUh->_UH.hbmGlyph);
  1655. }
  1656. else {
  1657. TRC_NRM((TB, _T("Unable to create compatible DC")));
  1658. DC_QUIT;
  1659. }
  1660. /************************************************************************/
  1661. /* If the output is to be opaque, then set the fore and back colors */
  1662. /* appropriately and set the correct rop code */
  1663. /************************************************************************/
  1664. if (pOrder->OpTop < pOrder->OpBottom) {
  1665. #ifndef OS_WINCE
  1666. #ifndef DISABLE_SHADOW_IN_FULLSCREEN
  1667. UHUseTextColor(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
  1668. UHUseBkColor(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
  1669. #else
  1670. // When in multimon and two desktops have different color depths
  1671. // glyph color don't look right in 256 color connection
  1672. // Here is the temporary solution, need to investigate more later.
  1673. if (_pUh->_UH.protocolBpp <= 8) {
  1674. rgb = UHGetColorRef(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
  1675. rgb = GetNearestColor(_pUh->_UH.hdcDraw, rgb);
  1676. SetTextColor(_pUh->_UH.hdcDraw, rgb);
  1677. _pUh->_UH.lastTextColor = rgb;
  1678. #if defined (OS_WINCE)
  1679. _pUh->_UH.validTextColorDC = _pUh->_UH.hdcDraw;
  1680. #endif
  1681. rgb = UHGetColorRef(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
  1682. rgb = GetNearestColor(_pUh->_UH.hdcDraw, rgb);
  1683. SetBkColor(_pUh->_UH.hdcDraw, rgb);
  1684. _pUh->_UH.lastBkColor = rgb;
  1685. #if defined (OS_WINCE)
  1686. _pUh->_UH.validBkColorDC = _pUh->_UH.hdcDraw;
  1687. #endif
  1688. }
  1689. else {
  1690. UHUseTextColor(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
  1691. UHUseBkColor(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
  1692. }
  1693. #endif // DISABLE_SHADOW_IN_FULLSCREEN
  1694. dwRop = SRCCOPY;
  1695. #else // OS_WINCE
  1696. /********************************************************************/
  1697. /* On WinCE, the Transparent ROP is heavily accelerated. For opaque */
  1698. /* just draw a solid rectangle, and then go on to do the */
  1699. /* transparent blt. */
  1700. /********************************************************************/
  1701. rgb = UHGetColorRef(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
  1702. hbr = CECreateSolidBrush(rgb);
  1703. if(hbr != NULL) {
  1704. FillRect(_pUh->_UH.hdcDraw, (LPRECT) &pOrder->BkLeft, hbr);
  1705. CEDeleteBrush(hbr);
  1706. }
  1707. #endif // OS_WINCE
  1708. }
  1709. #ifndef OS_WINCE
  1710. // If the output is to be transparent, then set the fore and back
  1711. // colors appropriately and set the correct rop code.
  1712. else {
  1713. UHUseBrushOrg(0, 0, _pUh);
  1714. _pUh->UHUseSolidPaletteBrush(pOrder->BackColor);
  1715. color.u.rgb.red = 0;
  1716. color.u.rgb.green = 0;
  1717. color.u.rgb.blue = 0;
  1718. UHUseTextColor(color, UH_COLOR_RGB, _pUh);
  1719. color.u.rgb.red = 0xff;
  1720. color.u.rgb.green = 0xff;
  1721. color.u.rgb.blue = 0xff;
  1722. UHUseBkColor(color, UH_COLOR_RGB, _pUh);
  1723. dwRop = 0xE20746;
  1724. }
  1725. #endif // OS_WINCE
  1726. /************************************************************************/
  1727. /* The opaque vs transparent preamble is done, now just do the right */
  1728. /* blt operation */
  1729. /************************************************************************/
  1730. #ifdef OS_WINCE
  1731. /************************************************************************/
  1732. /* Create a brush for the foreground color and maskblt with that */
  1733. /* brush with the glyph bitmap as the mask */
  1734. /************************************************************************/
  1735. UHUseBrushOrg(0, 0, _pUh);
  1736. _pUh->UHUseSolidPaletteBrush(pOrder->BackColor);
  1737. /************************************************************************/
  1738. /* The 6th, 7th and 8th parameters (src bitmap) aren't used by the ROP */
  1739. /* that we pass in. The documentation says that in this case, hdcSrc */
  1740. /* should be zero but this causes the call to fail. We also have to */
  1741. /* pass in reasonable values for nXSrc and nYSrc or the parameter */
  1742. /* checking will fail. */
  1743. /************************************************************************/
  1744. if (!MaskBlt(_pUh->_UH.hdcDraw,
  1745. (int)pOrder->BkLeft,
  1746. (int)pOrder->BkTop,
  1747. (int)(pOrder->BkRight - pOrder->BkLeft),
  1748. (int)(pOrder->BkBottom - pOrder->BkTop),
  1749. _pUh->_UH.hdcGlyph, // next 3 not used for this ROP
  1750. 0,
  1751. 0,
  1752. _pUh->_UH.hbmGlyph,
  1753. (int)BufferAlign,
  1754. 0,
  1755. 0xAAF00000))
  1756. {
  1757. TRC_ERR((TB, _T("Composite glyph MaskBlt failed, %lu"), GetLastError()));
  1758. }
  1759. /************************************************************************/
  1760. // If we're drawing opaque we need to set the brush back to what
  1761. // the fringe rect code is expecting.
  1762. /************************************************************************/
  1763. if (pOrder->OpTop < pOrder->OpBottom)
  1764. {
  1765. _pUh->UHUseSolidPaletteBrush(pOrder->ForeColor);
  1766. }
  1767. #else // OS_WINCE
  1768. /************************************************************************/
  1769. /* Bitblt out the composite bitmap */
  1770. /************************************************************************/
  1771. if (!BitBlt(_pUh->_UH.hdcDraw,
  1772. (int)pOrder->BkLeft,
  1773. (int)pOrder->BkTop,
  1774. (int)(pOrder->BkRight - pOrder->BkLeft),
  1775. (int)(pOrder->BkBottom - pOrder->BkTop),
  1776. _pUh->_UH.hdcGlyph,
  1777. (int)BufferAlign,
  1778. 0,
  1779. dwRop))
  1780. {
  1781. TRC_ERR((TB, _T("Composite glyph BitBlt failed")));
  1782. }
  1783. #endif // OS_WINCE
  1784. /************************************************************************/
  1785. /* Release GDI resources */
  1786. /************************************************************************/
  1787. SelectObject(_pUh->_UH.hdcGlyph, hbmOld);
  1788. #ifdef OS_WINCE
  1789. DeleteDC(_pUh->_UH.hdcGlyph);
  1790. _pUh->_UH.hdcGlyph = NULL;
  1791. DeleteObject(_pUh->_UH.hbmGlyph);
  1792. _pUh->_UH.hbmGlyph = NULL;
  1793. #endif
  1794. DC_EXIT_POINT:
  1795. DC_END_FN();
  1796. }
  1797. /****************************************************************************/
  1798. /* Name: draw_nf_ntb_o_to_temp_start */
  1799. /* */
  1800. /* Specialized glyph dispatch routine for non-fixed pitch, top and */
  1801. /* bottom not aligned glyphs that do overlap. This routine calculates */
  1802. /* the glyph's position on the temp buffer, then determines the correct */
  1803. /* highly specialized routine to be used to draw each glyph based on */
  1804. /* the glyph width, alignment and rotation */
  1805. /* */
  1806. /* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
  1807. /* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
  1808. /* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
  1809. /****************************************************************************/
  1810. HRESULT CGH::draw_nf_ntb_o_to_temp_start(
  1811. CGH* inst,
  1812. LPINDEX_ORDER pOrder,
  1813. unsigned iGlyph,
  1814. PDCUINT8 DCPTR ppjItem,
  1815. PDCUINT8 pjEndItem,
  1816. PDCINT px,
  1817. PDCINT py,
  1818. PDCUINT8 pjTempBuffer,
  1819. PDCUINT8 pjEndTempBuffer,
  1820. ULONG ulCharInc,
  1821. unsigned TempBufDelta,
  1822. PDCUINT16 pUnicode,
  1823. int * pnRet)
  1824. {
  1825. HRESULT hr = S_OK;
  1826. PDCUINT8 pTempOutput;
  1827. LONG GlyphPosX;
  1828. int GlyphPixels;
  1829. LONG GlyphAlignment;
  1830. LONG SrcBytes;
  1831. LONG DstBytes;
  1832. ULONG ulDrawFlag;
  1833. PFN_GLYPHLOOPN pfnGlyphLoopN;
  1834. PFN_GLYPHLOOP pfnGlyphLoop;
  1835. LONG GlyphPosY;
  1836. HPUHGLYPHCACHE pCache;
  1837. HPUHGLYPHCACHEENTRYHDR pHdr;
  1838. PDCUINT8 pData;
  1839. PDCUINT8 pEndData;
  1840. ULONG cacheIndex;
  1841. INT16 delta;
  1842. INT32 GlyphClippingMode;
  1843. UHGLYPHCACHEENTRYHDR NewHdr;
  1844. RECTCLIPOFFSET rcOffset;
  1845. DC_BEGIN_FN("draw_nf_ntb_o_to_temp_start");
  1846. DC_IGNORE_PARAMETER(iGlyph);
  1847. *pnRet = 0;
  1848. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  1849. (TB, _T("Read Glyph Cache ID error")));
  1850. cacheIndex = **ppjItem;
  1851. (*ppjItem)++;
  1852. hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
  1853. DC_QUIT_ON_FAIL(hr);
  1854. pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
  1855. pHdr = &(pCache->pHdr[cacheIndex]);
  1856. pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
  1857. pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
  1858. if (pUnicode)
  1859. pUnicode[iGlyph] = (UINT16)(pHdr->unicode);
  1860. // Draw non fixed pitch, tops and bottoms not aligned,overlap
  1861. if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
  1862. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  1863. (TB, _T("Read Glyph delta")));
  1864. delta = (char)(*(*ppjItem)++);
  1865. if (delta & 0x80) {
  1866. CHECK_READ_N_BYTES(*ppjItem, pjEndItem, sizeof(INT16), hr,
  1867. (TB, _T("Read Glyph delta")));
  1868. delta = (*(short UNALIGNED FAR *)(*ppjItem));
  1869. (*ppjItem) += sizeof(INT16);
  1870. }
  1871. if (pOrder->flAccel & SO_HORIZONTAL)
  1872. *px += delta;
  1873. else
  1874. *py += delta;
  1875. }
  1876. // We make sure that we actually have enough bits for the glyph in the buffer
  1877. if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
  1878. hr=E_TSC_UI_GLYPH;
  1879. DC_QUIT;
  1880. }
  1881. GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
  1882. if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
  1883. if (GlyphClippingMode==GLYPH_CLIP_ALL) {
  1884. goto SkipGlyphOutput;
  1885. } else {
  1886. // In case we do clipping we have to modify the header. We make a
  1887. // copy so we don't modify the cache.
  1888. memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
  1889. pHdr = &NewHdr;
  1890. hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
  1891. if (FAILED(hr)) {
  1892. DC_QUIT;
  1893. }
  1894. }
  1895. }
  1896. // Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xffffffe0)
  1897. GlyphPosX = *px + pHdr->x - ulCharInc;
  1898. GlyphPosY = *py + pHdr->y - pOrder->BkTop;
  1899. GlyphPosY = DC_MAX(0,GlyphPosY);
  1900. GlyphAlignment = GlyphPosX & 0x07;
  1901. // calc byte offset
  1902. pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
  1903. // glyph width
  1904. GlyphPixels = (int)pHdr->cx;
  1905. // source and dest bytes required
  1906. DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
  1907. SrcBytes = (GlyphPixels + 7) >> 3;
  1908. pTempOutput += (GlyphPosY * TempBufDelta);
  1909. TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
  1910. (pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
  1911. (TB,_T("Bad glyph buffer addressing: pTempOutput=%p, pjTempBuffer=%p, g_ulBytes=%d, DstBytes=%d"),
  1912. pTempOutput, pjTempBuffer, inst->g_ulBytes, DstBytes));
  1913. if (pTempOutput < pjTempBuffer) {
  1914. TRC_ABORT((TB, _T("Reading before buffer")));
  1915. goto SkipGlyphOutput;
  1916. }
  1917. if (DstBytes < 0) {
  1918. TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
  1919. _T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
  1920. _T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
  1921. DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
  1922. pHdr->x, ulCharInc));
  1923. hr = E_TSC_UI_GLYPH;
  1924. DC_QUIT;
  1925. }
  1926. if (DstBytes <= 4) {
  1927. // use narrow initial table
  1928. ulDrawFlag = ((DstBytes << 2) |
  1929. ((DstBytes > SrcBytes) << 1) |
  1930. ((GlyphAlignment == 0)));
  1931. pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
  1932. pfnGlyphLoop(pHdr->cy,
  1933. GlyphAlignment,
  1934. TempBufDelta,
  1935. pData,
  1936. pEndData,
  1937. pTempOutput,
  1938. pjEndTempBuffer,
  1939. SrcBytes);
  1940. }
  1941. else {
  1942. // use wide glyph drawing
  1943. ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
  1944. ((GlyphAlignment == 0)));
  1945. pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
  1946. pfnGlyphLoopN(pHdr->cy,
  1947. GlyphAlignment,
  1948. TempBufDelta,
  1949. pData,
  1950. pEndData,
  1951. pTempOutput,
  1952. pjEndTempBuffer,
  1953. SrcBytes,
  1954. DstBytes);
  1955. }
  1956. SkipGlyphOutput:
  1957. if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) {
  1958. if (pOrder->flAccel & SO_HORIZONTAL)
  1959. *px += (unsigned)pHdr->cx;
  1960. else
  1961. *py += (unsigned)pHdr->cy;
  1962. }
  1963. *pnRet = GlyphPixels;
  1964. DC_EXIT_POINT:
  1965. DC_END_FN();
  1966. return hr;
  1967. }
  1968. /****************************************************************************/
  1969. /* Name: draw_f_ntb_o_to_temp_start */
  1970. /* */
  1971. /* Specialized glyph dispatch routine for fixed pitch, top and */
  1972. /* bottom not aligned glyphs that do overlap. This routine calculates */
  1973. /* the glyph's position on the temp buffer, then determines the correct */
  1974. /* highly specialized routine to be used to draw each glyph based on */
  1975. /* the glyph width, alignment and rotation */
  1976. /* */
  1977. /* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
  1978. /* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
  1979. /* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
  1980. /****************************************************************************/
  1981. HRESULT CGH::draw_f_ntb_o_to_temp_start(
  1982. CGH* inst,
  1983. LPINDEX_ORDER pOrder,
  1984. unsigned iGlyph,
  1985. PDCUINT8 DCPTR ppjItem,
  1986. PDCUINT8 pjEndItem,
  1987. PDCINT px,
  1988. PDCINT py,
  1989. PDCUINT8 pjTempBuffer,
  1990. PDCUINT8 pjEndTempBuffer,
  1991. ULONG ulCharInc,
  1992. unsigned TempBufDelta,
  1993. PDCUINT16 pUnicode,
  1994. int * pnRet)
  1995. {
  1996. HRESULT hr = S_OK;
  1997. PDCUINT8 pTempOutput;
  1998. LONG GlyphPosX;
  1999. LONG GlyphPixels;
  2000. LONG GlyphAlignment;
  2001. LONG SrcBytes;
  2002. LONG DstBytes;
  2003. ULONG ulDrawFlag;
  2004. PFN_GLYPHLOOP pfnGlyphLoop;
  2005. PFN_GLYPHLOOPN pfnGlyphLoopN;
  2006. LONG GlyphPitchX;
  2007. LONG GlyphPitchY;
  2008. LONG GlyphPosY;
  2009. HPUHGLYPHCACHE pCache;
  2010. HPUHGLYPHCACHEENTRYHDR pHdr;
  2011. PDCUINT8 pData;
  2012. PDCUINT8 pEndData;
  2013. ULONG cacheIndex;
  2014. INT32 GlyphClippingMode;
  2015. UHGLYPHCACHEENTRYHDR NewHdr;
  2016. RECTCLIPOFFSET rcOffset;
  2017. DC_BEGIN_FN("draw_f_ntb_o_to_temp_start");
  2018. DC_IGNORE_PARAMETER(iGlyph);
  2019. *pnRet = 0;
  2020. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  2021. (TB, _T("Read Glyph Cache ID error")));
  2022. cacheIndex = **ppjItem;
  2023. (*ppjItem)++;
  2024. hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
  2025. DC_QUIT_ON_FAIL(hr);
  2026. pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
  2027. // Draw fixed pitch, tops and bottoms not aligned,overlap
  2028. GlyphPitchX = *px;
  2029. GlyphPitchY = *py - pOrder->BkTop;
  2030. pHdr = &(pCache->pHdr[cacheIndex]);
  2031. pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
  2032. pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
  2033. if (pUnicode)
  2034. pUnicode[iGlyph] = (DCUINT16)(pHdr->unicode);
  2035. // We make sure that we actually have enough bits for the glyph in the buffer
  2036. if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
  2037. hr=E_TSC_UI_GLYPH;
  2038. DC_QUIT;
  2039. }
  2040. GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
  2041. if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
  2042. if (GlyphClippingMode==GLYPH_CLIP_ALL) {
  2043. goto SkipGlyphOutput;
  2044. } else {
  2045. // In case we do clipping we have to modify the header. We make a
  2046. // copy so we don't modify the cache.
  2047. memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
  2048. pHdr = &NewHdr;
  2049. hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
  2050. if (FAILED(hr)) {
  2051. DC_QUIT;
  2052. }
  2053. }
  2054. }
  2055. // Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
  2056. GlyphPosX = GlyphPitchX + pHdr->x - ulCharInc;
  2057. GlyphPosY = GlyphPitchY + pHdr->y;
  2058. GlyphAlignment = GlyphPosX & 0x07;
  2059. // calc byte offset
  2060. pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
  2061. // glyph width
  2062. GlyphPixels = pHdr->cx;
  2063. // source and dest bytes required
  2064. DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
  2065. SrcBytes = (GlyphPixels + 7) >> 3;
  2066. // calc glyph destination scan line
  2067. pTempOutput += (GlyphPosY * TempBufDelta);
  2068. TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
  2069. (pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
  2070. (TB,_T("Bad glyph buffer addressing")));
  2071. if (pTempOutput < pjTempBuffer) {
  2072. TRC_ABORT((TB, _T("Reading before buffer")));
  2073. goto SkipGlyphOutput;
  2074. }
  2075. if (DstBytes < 0) {
  2076. TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
  2077. _T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
  2078. _T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
  2079. DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
  2080. pHdr->x, ulCharInc));
  2081. hr = E_TSC_UI_GLYPH;
  2082. DC_QUIT;
  2083. }
  2084. if (DstBytes <= 4) {
  2085. // use narrow initial table
  2086. ulDrawFlag = ((DstBytes << 2) |
  2087. ((DstBytes > SrcBytes) << 1) |
  2088. ((GlyphAlignment == 0)));
  2089. pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
  2090. pfnGlyphLoop(pHdr->cy,
  2091. GlyphAlignment,
  2092. TempBufDelta,
  2093. pData,
  2094. pEndData,
  2095. pTempOutput,
  2096. pjEndTempBuffer,
  2097. SrcBytes);
  2098. }
  2099. else {
  2100. // use wide glyph drawing
  2101. ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
  2102. ((GlyphAlignment == 0)));
  2103. pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
  2104. pfnGlyphLoopN(pHdr->cy,
  2105. GlyphAlignment,
  2106. TempBufDelta,
  2107. pData,
  2108. pEndData,
  2109. pTempOutput,
  2110. pjEndTempBuffer,
  2111. SrcBytes,
  2112. DstBytes);
  2113. }
  2114. SkipGlyphOutput:
  2115. *px += pOrder->ulCharInc;
  2116. *pnRet = pOrder->ulCharInc;
  2117. DC_EXIT_POINT:
  2118. DC_END_FN();
  2119. return hr;
  2120. }
  2121. /****************************************************************************/
  2122. /* Name: draw_nf_tb_no_to_temp_start */
  2123. /* */
  2124. /* Specialized glyph dispatch routine for non-fixed pitch, top and */
  2125. /* bottom aligned glyphs that do not overlap. This routine calculates */
  2126. /* the glyph's position on the temp buffer, then determines the correct */
  2127. /* highly specialized routine to be used to draw each glyph based on */
  2128. /* the glyph width, alignment and rotation */
  2129. /* */
  2130. /* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
  2131. /* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
  2132. /* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
  2133. /****************************************************************************/
  2134. HRESULT CGH::draw_nf_tb_no_to_temp_start(
  2135. CGH* inst,
  2136. LPINDEX_ORDER pOrder,
  2137. unsigned iGlyph,
  2138. PDCUINT8 DCPTR ppjItem,
  2139. PDCUINT8 pjEndItem,
  2140. PDCINT px,
  2141. PDCINT py,
  2142. PDCUINT8 pjTempBuffer,
  2143. PDCUINT8 pjEndTempBuffer,
  2144. ULONG ulCharInc,
  2145. unsigned TempBufDelta,
  2146. PDCUINT16 pUnicode,
  2147. int * pnRet)
  2148. {
  2149. HRESULT hr = S_OK;
  2150. PDCUINT8 pTempOutput;
  2151. LONG GlyphPosX;
  2152. int GlyphPixels;
  2153. LONG GlyphAlignment;
  2154. LONG SrcBytes;
  2155. LONG DstBytes;
  2156. ULONG ulDrawFlag;
  2157. PFN_GLYPHLOOP pfnGlyphLoop;
  2158. PFN_GLYPHLOOPN pfnGlyphLoopN;
  2159. HPUHGLYPHCACHE pCache;
  2160. HPUHGLYPHCACHEENTRYHDR pHdr;
  2161. PDCUINT8 pData;
  2162. PDCUINT8 pEndData;
  2163. ULONG cacheIndex;
  2164. INT16 delta;
  2165. INT32 GlyphClippingMode;
  2166. UHGLYPHCACHEENTRYHDR NewHdr;
  2167. RECTCLIPOFFSET rcOffset;
  2168. DC_BEGIN_FN("draw_nf_tb_no_to_temp_start");
  2169. DC_IGNORE_PARAMETER(iGlyph);
  2170. *pnRet = 0;
  2171. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  2172. (TB, _T("Read Glyph Cache ID error")));
  2173. // Draw non fixed pitch, tops and bottoms not aligned, overlap
  2174. cacheIndex = **ppjItem;
  2175. (*ppjItem)++;
  2176. hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
  2177. DC_QUIT_ON_FAIL(hr);
  2178. pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
  2179. if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
  2180. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  2181. (TB, _T("Read Glyph delta error")));
  2182. delta = (DCINT8)(*(*ppjItem)++);
  2183. if (delta & 0x80) {
  2184. CHECK_READ_N_BYTES(*ppjItem, pjEndItem, sizeof(DCINT16), hr,
  2185. (TB, _T("Read Glyph delta error")));
  2186. delta = (*(short UNALIGNED FAR *)(*ppjItem));
  2187. (*ppjItem) += sizeof(DCINT16);
  2188. }
  2189. if (pOrder->flAccel & SO_HORIZONTAL)
  2190. *px += delta;
  2191. else
  2192. *py += delta;
  2193. }
  2194. pHdr = &(pCache->pHdr[cacheIndex]);
  2195. pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
  2196. pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
  2197. if (pUnicode)
  2198. pUnicode[iGlyph] = (DCUINT16)(pHdr->unicode);
  2199. // We make sure that we actually have enough bits for the glyph in the buffer
  2200. if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
  2201. hr=E_TSC_UI_GLYPH;
  2202. DC_QUIT;
  2203. }
  2204. GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
  2205. if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
  2206. if (GlyphClippingMode==GLYPH_CLIP_ALL) {
  2207. goto SkipGlyphOutput;
  2208. } else {
  2209. // In case we do clipping we have to modify the header. We make a
  2210. // copy so we don't modify the cache.
  2211. memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
  2212. pHdr = &NewHdr;
  2213. hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
  2214. if (FAILED(hr)) {
  2215. DC_QUIT;
  2216. }
  2217. }
  2218. }
  2219. // Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
  2220. GlyphPosX = *px + pHdr->x - ulCharInc;
  2221. GlyphAlignment = GlyphPosX & 0x07;
  2222. // calc byte offset
  2223. pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
  2224. // glyph width
  2225. GlyphPixels = (DCINT) pHdr->cx;
  2226. // source and dest bytes required
  2227. DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
  2228. SrcBytes = (GlyphPixels + 7) >> 3;
  2229. TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
  2230. (pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
  2231. (TB,_T("Bad glyph buffer addressing")));
  2232. if (pTempOutput < pjTempBuffer) {
  2233. TRC_ABORT((TB, _T("Reading before buffer")));
  2234. goto SkipGlyphOutput;
  2235. }
  2236. if (DstBytes < 0) {
  2237. TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
  2238. _T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
  2239. _T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
  2240. DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
  2241. pHdr->x, ulCharInc));
  2242. hr = E_TSC_UI_GLYPH;
  2243. DC_QUIT;
  2244. }
  2245. if (DstBytes <= 4) {
  2246. // use narrow initial table
  2247. ulDrawFlag = ((DstBytes << 2) |
  2248. ((DstBytes > SrcBytes) << 1) |
  2249. ((GlyphAlignment == 0)));
  2250. pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
  2251. pfnGlyphLoop(pHdr->cy,
  2252. GlyphAlignment,
  2253. TempBufDelta,
  2254. pData,
  2255. pEndData,
  2256. pTempOutput,
  2257. pjEndTempBuffer,
  2258. SrcBytes);
  2259. }
  2260. else {
  2261. // use wide glyph drawing
  2262. ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
  2263. ((GlyphAlignment == 0)));
  2264. pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
  2265. pfnGlyphLoopN(pHdr->cy,
  2266. GlyphAlignment,
  2267. TempBufDelta,
  2268. pData,
  2269. pEndData,
  2270. pTempOutput,
  2271. pjEndTempBuffer,
  2272. SrcBytes,
  2273. DstBytes);
  2274. }
  2275. SkipGlyphOutput:
  2276. if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
  2277. *px += (DCINT) pHdr->cx;
  2278. *pnRet = GlyphPixels;
  2279. DC_EXIT_POINT:
  2280. DC_END_FN();
  2281. return hr;
  2282. }
  2283. /****************************************************************************/
  2284. /* Name: draw_f_tb_no_to_temp_start */
  2285. /* */
  2286. /* Specialized glyph dispatch routine for fixed pitch, top and */
  2287. /* bottom aligned glyphs that do not overlap. This routine calculates */
  2288. /* the glyph's position on the temp buffer, then determines the correct */
  2289. /* highly specialized routine to be used to draw each glyph based on */
  2290. /* the glyph width, alignment and rotation */
  2291. /* */
  2292. /* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
  2293. /* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
  2294. /* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
  2295. /****************************************************************************/
  2296. HRESULT CGH::draw_f_tb_no_to_temp_start(
  2297. CGH* inst,
  2298. LPINDEX_ORDER pOrder,
  2299. unsigned iGlyph,
  2300. PDCUINT8 DCPTR ppjItem,
  2301. PDCUINT8 pjEndItem,
  2302. PDCINT px,
  2303. PDCINT py,
  2304. PDCUINT8 pjTempBuffer,
  2305. PDCUINT8 pjEndTempBuffer,
  2306. ULONG ulLeftEdge,
  2307. unsigned TempBufDelta,
  2308. PDCUINT16 pUnicode,
  2309. int * pnRet)
  2310. {
  2311. HRESULT hr = S_OK;
  2312. PDCUINT8 pTempOutput;
  2313. LONG GlyphPosX;
  2314. LONG GlyphPixels;
  2315. LONG GlyphPitchX;
  2316. LONG GlyphAlignment;
  2317. LONG SrcBytes;
  2318. LONG DstBytes;
  2319. ULONG ulDrawFlag;
  2320. PFN_GLYPHLOOPN pfnGlyphLoopN;
  2321. PFN_GLYPHLOOP pfnGlyphLoop;
  2322. HPUHGLYPHCACHE pCache;
  2323. HPUHGLYPHCACHEENTRYHDR pHdr;
  2324. PDCUINT8 pData;
  2325. PDCUINT8 pEndData;
  2326. ULONG cacheIndex;
  2327. INT32 GlyphClippingMode;
  2328. UHGLYPHCACHEENTRYHDR NewHdr;
  2329. RECTCLIPOFFSET rcOffset;
  2330. DC_BEGIN_FN("draw_f_tb_no_to_temp_start");
  2331. DC_IGNORE_PARAMETER(iGlyph);
  2332. DC_IGNORE_PARAMETER(py);
  2333. *pnRet = 0;
  2334. CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
  2335. (TB, _T("Read Glyph Cache ID error")));
  2336. cacheIndex = **ppjItem;
  2337. (*ppjItem)++;
  2338. hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
  2339. DC_QUIT_ON_FAIL(hr);
  2340. pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
  2341. // Draw fixed pitch, tops and bottoms not aligned,overlap
  2342. GlyphPitchX = *px;
  2343. pHdr = &(pCache->pHdr[cacheIndex]);
  2344. pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
  2345. pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
  2346. if (pUnicode)
  2347. pUnicode[iGlyph] = (UINT16)(pHdr->unicode);
  2348. // We make sure that we actually have enough bits for the glyph in the buffer
  2349. if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
  2350. hr=E_TSC_UI_GLYPH;
  2351. DC_QUIT;
  2352. }
  2353. GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
  2354. if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
  2355. if (GlyphClippingMode==GLYPH_CLIP_ALL) {
  2356. goto SkipGlyphOutput;
  2357. } else {
  2358. // In case we do clipping we have to modify the header. We make a
  2359. // copy so we don't modify the cache.
  2360. memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
  2361. pHdr = &NewHdr;
  2362. hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
  2363. if (FAILED(hr)) {
  2364. DC_QUIT;
  2365. }
  2366. }
  2367. }
  2368. // Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
  2369. GlyphPosX = GlyphPitchX + pHdr->x - ulLeftEdge;
  2370. GlyphAlignment = GlyphPosX & 0x07;
  2371. // calc byte offset
  2372. pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
  2373. // glyph width
  2374. GlyphPixels = pHdr->cx;
  2375. // source and dest bytes required
  2376. DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
  2377. SrcBytes = (GlyphPixels + 7) >> 3;
  2378. TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
  2379. (pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
  2380. (TB,_T("Bad glyph buffer addressing")));
  2381. if (pTempOutput < pjTempBuffer) {
  2382. TRC_ABORT((TB, _T("Reading before buffer")));
  2383. goto SkipGlyphOutput;
  2384. }
  2385. if (DstBytes < 0) {
  2386. TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
  2387. _T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
  2388. _T("GlyphPosX=%d *px=%d pHdr->x=%d ulLeftEdge=%d"),
  2389. DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
  2390. pHdr->x, ulLeftEdge));
  2391. hr = E_TSC_UI_GLYPH;
  2392. DC_QUIT;
  2393. }
  2394. if (DstBytes <= 4) {
  2395. // use narrow initial table
  2396. ulDrawFlag = ((DstBytes << 2) |
  2397. ((DstBytes > SrcBytes) << 1) |
  2398. (GlyphAlignment == 0));
  2399. pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
  2400. pfnGlyphLoop(pHdr->cy,
  2401. GlyphAlignment,
  2402. TempBufDelta,
  2403. pData,
  2404. pEndData,
  2405. pTempOutput,
  2406. pjEndTempBuffer,
  2407. SrcBytes);
  2408. }
  2409. else {
  2410. // use wide glyph drawing
  2411. ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
  2412. ((GlyphAlignment == 0)));
  2413. pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
  2414. pfnGlyphLoopN(pHdr->cy,
  2415. GlyphAlignment,
  2416. TempBufDelta,
  2417. pData,
  2418. pEndData,
  2419. pTempOutput,
  2420. pjEndTempBuffer,
  2421. SrcBytes,
  2422. DstBytes);
  2423. }
  2424. SkipGlyphOutput:
  2425. *px += pOrder->ulCharInc;
  2426. *pnRet = pOrder->ulCharInc;
  2427. DC_EXIT_POINT:
  2428. DC_END_FN();
  2429. return hr;
  2430. }