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.

2313 lines
71 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: rleblt4.cxx
  3. *
  4. * This contains the bitmap simulation functions that blt from a 4 bit
  5. * Run-Length Encoded (RLE) source to a DIB surface. The DIB surface can be
  6. * 1, 4, 8, 16, 24, or 32 bits/pel.
  7. *
  8. * The code is based on functions found in 'rleblt8.cxx', version 2.
  9. *
  10. * Added RLE Encoding functions: 10 Oct 92 @ 10:18
  11. * Gerrit van Wingerden [gerritv]
  12. *
  13. * Created: 03 Feb 92 @ 21:00
  14. *
  15. * Author: Andrew Milton (w-andym)
  16. *
  17. * Notes:
  18. *
  19. * 1) These functions return a BOOL value. This value is TRUE if the
  20. * function ends before running out of data in the source RLE or before
  21. * hitting an End-of-Bitmap code. Otherwise, we return FALSE. This return
  22. * value is used by <EngCopyajBits> in the complex clipping case to decide
  23. * if the blt is complete.
  24. *
  25. * 2) Before exiting a function with a TRUE value, position information is
  26. * saved by the macro <RLE_SavePosition>. This is used by <EngCopyajBits>
  27. * to speed up the complex clipping case.
  28. *
  29. * 3) The below functions use about twenty different macros. This is
  30. * because they are all using the same basic algorithm to play an RLE
  31. * compression. The macros allow us to focus in on the nifty stuff of writing
  32. * the bytes out to the DIB. Routine administrivia is handled by the macros.
  33. *
  34. * The macros themselves are used to manage
  35. *
  36. * - Source Access and data alignment
  37. * - Visability Checking
  38. * - Output position changes with Newline & Delta codes
  39. *
  40. * The macro <RLE_InitVars> is used to define the varibles that relate to
  41. * the above information, and to define variables common to all RLE 4
  42. * blt functions. Note that actual names of the common variables are passed
  43. * in as parameters to the macro. Why? Two reasons. Firstly, they are
  44. * initialized by values taken of the BLTINFO structure passed into the blt
  45. * function. Secondly, showing the variable names in the macro 'call' means
  46. * they don't just appear from nowhere into the function. RLE_InitVars
  47. * is the one macro that you should think three times about before modifying.
  48. *
  49. * One further note. The variables 'ulDstLeft' and 'ulDstRight' appear to
  50. * come from nowhere. This is not true. They are in fact declared by the
  51. * macro <RLE_GetVisibleRect>. However, showing these names in the macro
  52. * 'call' tended to obscure the code. Pretend you can see the declaration.
  53. *
  54. * Where can I find a macro definition?
  55. *
  56. * Good question, glad you asked. Look at the prefix:
  57. *
  58. * RLE_<stuff> - lives in RLEBLT.H
  59. * RLE4_<blah> - lives in RLE4BLT.H
  60. *
  61. * Anything else in here that looks like function call is not. It's a macro.
  62. * Probably for bitwise manipulations. Look for it in BITMANIP.H or in
  63. * the Miscellaneous section of RLEBLT.H
  64. *
  65. * 4) The 8 and 16 ajBits/Pel cases can be optimized by packing the source
  66. * colours into a word / dword. However, to actually see some net gain in
  67. * run time, it will take some tricky-dicky-doo pointer alignment checking.
  68. * This sort of thing may break on MIPS.
  69. *
  70. *
  71. * Copyright (c) 1990-1999 Microsoft Corporation
  72. *
  73. \**************************************************************************/
  74. #include "precomp.hxx"
  75. /*******************************Public*Routine*****************************\
  76. * bSrcCopySRLE4D8
  77. *
  78. * Secure RLE blting that does clipping and won't die or write somewhere
  79. * it shouldn't if given bad data.
  80. *
  81. * History:
  82. * 3 Feb 1992 - Andrew Milton (w-andym): Creation.
  83. *
  84. \**************************************************************************/
  85. BOOL
  86. bSrcCopySRLE4D8(
  87. PBLTINFO psb)
  88. {
  89. // Common RLE Initialization
  90. RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol, pulXlate);
  91. RLE_AssertValid(psb);
  92. RLE_FetchVisibleRect(psb);
  93. RLE_SetStartPos(psb, lOutCol);
  94. // Outta here if we start past the top edge. Don't need to save our position.
  95. if (RLE_PastTopEdge)
  96. return(TRUE); // Must have bits left in the bitmap since we haven't
  97. // consumed any.
  98. // Extra Variables
  99. BYTE jSource; // Packed RLE 4 colour code
  100. BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
  101. BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
  102. ULONG ulClipMargin; // Number of bytes clipped in an Encoded run
  103. // Main process loop
  104. LOOP_FOREVER
  105. {
  106. // Outta here if we can't get two more bytes
  107. if (RLE_SourceExhausted(2))
  108. return(FALSE);
  109. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  110. if (ulCount == 0)
  111. {
  112. // Absolute or Escape Mode.
  113. switch (ulNext)
  114. {
  115. case 0:
  116. // New Line
  117. RLE_NextLine(PBYTE, pjDst, lOutCol);
  118. if (RLE_PastTopEdge)
  119. {
  120. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  121. return(TRUE);
  122. }
  123. break;
  124. case 1:
  125. // End of the bitmap
  126. return(FALSE);
  127. case 2:
  128. /* Positional Delta.
  129. * The delta values live in the next two source bytes
  130. */
  131. // Outta here if we can't get two more bytes
  132. if (RLE_SourceExhausted(2))
  133. return(FALSE);
  134. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  135. RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
  136. if (RLE_PastTopEdge)
  137. {
  138. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  139. return(TRUE);
  140. }
  141. break;
  142. default:
  143. /* Absolute Mode.
  144. * The run length is stored in <ulNext>, <ulCount> is used to
  145. * hold left and right clip amounts.
  146. */
  147. // Outta here if the bytes aren't in the source
  148. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  149. return(FALSE);
  150. RLE4_AlignToWord(pjSrc, ulNext);
  151. if (RLE_InVisibleRect(ulNext, lOutCol))
  152. {
  153. // Left Side Clipping
  154. if (lOutCol < (LONG)ulDstLeft)
  155. {
  156. ulCount = ulDstLeft - lOutCol;
  157. ulNext -= ulCount;
  158. lOutCol += ulCount;
  159. pjSrc += (ulCount >> 1);
  160. // Force the Source Run to a byte boundary
  161. if (bIsOdd(ulCount))
  162. {
  163. jSource = *pjSrc++;
  164. pjDst[lOutCol] =
  165. (BYTE) pulXlate[GetLowNybble(jSource)];
  166. lOutCol++;
  167. ulNext--;
  168. }
  169. }
  170. // Right Side Clipping.
  171. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  172. {
  173. ulCount = (lOutCol + ulNext) - ulDstRight;
  174. ulNext -= ulCount;
  175. }
  176. else
  177. ulCount = 0;
  178. // Slap the bits on. -- this is the funky-doodle stuff.
  179. bExtraByte = (BOOL) bIsOdd(ulNext);
  180. ulNext >>= 1;
  181. // Write complete bytes from the source
  182. while (ulNext)
  183. {
  184. jSource = *pjSrc++;
  185. RLE4_MakeColourBlock(jSource, ajColours, BYTE,
  186. pulXlate);
  187. pjDst[lOutCol] = ajColours[0];
  188. pjDst[lOutCol+1] = ajColours[1];
  189. lOutCol += 2;
  190. ulNext--;
  191. }
  192. // Account for a partial source byte in the run
  193. if (bExtraByte)
  194. {
  195. jSource = *pjSrc++;
  196. pjDst[lOutCol] =
  197. (BYTE) pulXlate[GetHighNybble(jSource)];
  198. lOutCol++;
  199. pjSrc += (ulCount >> 1); // Clip Adjustment
  200. }
  201. else
  202. pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
  203. // Adjust the column for the right side clipping.
  204. lOutCol += ulCount;
  205. }
  206. else
  207. {
  208. /* Not on a visible scanline.
  209. * Adjust our x output position and source pointer.
  210. */
  211. lOutCol += ulNext;
  212. pjSrc += (ulNext + 1) >> 1;
  213. } /* if */
  214. // Pad so the run ends on a WORD boundary
  215. RLE4_FixAlignment(pjSrc)
  216. } /* switch */
  217. }
  218. else
  219. {
  220. /* Encoded Mode
  221. * The run length is stored in <ulCount>, <ulClipMargin> is used
  222. * to hold left and right clip amounts.
  223. */
  224. if (RLE_InVisibleRect(ulCount, lOutCol))
  225. {
  226. // Left Side Clipping
  227. if (lOutCol < (LONG)ulDstLeft)
  228. {
  229. ulClipMargin = ulDstLeft - lOutCol;
  230. ulCount -= ulClipMargin;
  231. lOutCol += ulClipMargin;
  232. }
  233. // Right Side Clipping
  234. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  235. {
  236. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  237. ulCount -= ulClipMargin;
  238. }
  239. else
  240. ulClipMargin = 0;
  241. // Setup for the run
  242. bExtraByte = (BOOL) bIsOdd(ulCount);
  243. ulCount >>= 1;
  244. RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
  245. // Write it
  246. while (ulCount)
  247. {
  248. pjDst[lOutCol] = ajColours[0];
  249. pjDst[lOutCol+1] = ajColours[1];
  250. lOutCol += 2;
  251. ulCount--;
  252. }
  253. /* Write the extra byte from an odd run length */
  254. if (bExtraByte)
  255. {
  256. pjDst[lOutCol] = ajColours[0];
  257. lOutCol++;
  258. }
  259. // Adjust for the right side clipping.
  260. lOutCol += ulClipMargin;
  261. }
  262. else
  263. {
  264. /* Not on a visible scanline. Adjust our x output position */
  265. lOutCol += ulCount;
  266. } /* if */
  267. } /* if */
  268. } /* LOOP_FOREVER */
  269. } /* bSrcCopySRLE4D8 */
  270. /********************************Public*Routine****************************\
  271. * bSrcCopySRLE4D1
  272. *
  273. * Secure RLE blting to a 1 BPP DIB that does clipping and won't die or
  274. * write somewhere it shouldn't if given bad data.
  275. *
  276. * History:
  277. * 5 Feb 1992 - Andrew Milton (w-andym):
  278. * Added clip support.
  279. * 22 Jan 1992 - Andrew Milton (w-andym): Creation.
  280. *
  281. \**************************************************************************/
  282. /* Local Macros ***********************************************************/
  283. /* NOTE: In the Escape Modes, the current working byte must be
  284. * written to destination before the escape is executed.
  285. * These writes look unpleasant because we have to mask
  286. * current destination contents onto the working byte when
  287. * it is written. To such an end, the below macro...
  288. */
  289. #define RLE4to1_WritePartial(DstPtr, OutByte, OutColumn, WritePos) \
  290. if (RLE_RowVisible && (jBitPos = (BYTE) (OutColumn) & 7)) \
  291. { \
  292. if (RLE_ColVisible(OutColumn)) \
  293. DstPtr[WritePos] = OutByte | \
  294. ((~ajBits[jBitPos]) & DstPtr[WritePos]); \
  295. else \
  296. if (RLE_PastRightEdge(OutColumn)) \
  297. DstPtr[ulRightWritePos] = OutByte | \
  298. (DstPtr[ulRightWritePos] & jRightMask); \
  299. } \
  300. /* Converts an output column to a bitnumber in the working byte */
  301. #define ColToBitPos(col) (7 - (BYTE)((col) & 7))
  302. /* Lookup tables for bit patterns *****************************************/
  303. static BYTE
  304. ajPosMask[] = // The i'th entry contains a byte with the i'th bit set
  305. {
  306. 0x01, 0x02, 0x04, 0x08,
  307. 0x10, 0x20, 0x40, 0x80, 0x00
  308. };
  309. static BYTE
  310. ajBits[] = // The i'th entry contains a byte with the high i bits set
  311. {
  312. 0x00, 0x80, 0xC0, 0xE0, 0xF0,
  313. 0xF8, 0xFC, 0xFE, 0xFF
  314. };
  315. static BYTE
  316. ajBitPatterns[] = // The four possible full byte bit patterns of a packed colour
  317. {
  318. 0x00, 0x55, 0xAA, 0xFF
  319. };
  320. /* And now the function ***************************************************/
  321. BOOL
  322. bSrcCopySRLE4D1(
  323. PBLTINFO psb)
  324. {
  325. // Common RLE Initialization
  326. RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol,
  327. pulXlate);
  328. RLE_AssertValid(psb);
  329. RLE_FetchVisibleRect(psb);
  330. RLE_SetStartPos(psb, lOutCol);
  331. // Outta here if we start past the top edge. Don't need to save our position.
  332. if (RLE_PastTopEdge)
  333. return(TRUE); // Must have bits left in the bitmap since we haven't
  334. // consumed any.
  335. // Extra Variables
  336. BYTE jWorking; // Hold area to build a byte for output
  337. ULONG ulWritePos; // Write position off <pjDst> into the destination
  338. ULONG ulLeftWritePos; // Leftmost write position
  339. BYTE jLeftMask; // Bitmask for taking bytes off the left edge
  340. ULONG ulRightWritePos; // Rightmost write position
  341. BYTE jRightMask; // Bitmask for taking bytes off the right edge
  342. BYTE jBitPos; // Bit number of the next write into <jWorking>
  343. BYTE jBitPosMask; // Bitmask with the <jBitPos>th bit set.
  344. ULONG ulCompBytes; // Number of full bytes in an Encoded run.
  345. ULONG ulClipMargin; // Number of bytes clipped off the right side of a run
  346. BYTE jSource; // Packed RLE 4 colour code
  347. BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
  348. BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
  349. UINT i=0, j=0;
  350. // Our Initialization
  351. ulLeftWritePos = (ULONG)(ulDstLeft >> 3);
  352. jLeftMask = ajBits[ulDstLeft % 8];
  353. ulRightWritePos = (ULONG) (ulDstRight >> 3);
  354. jRightMask = ~ajBits[(ulDstRight % 8)];
  355. /* Fetch first working byte from the source. Yes, this is ugly.
  356. * We cannot assume we are at a left edge because the complex clipping
  357. * case could resume an RLE in the middle of its bitmap. We cannot do
  358. * a simple bounds check like RLE 8 to 4 because of bitmasking. Argh.
  359. */
  360. ulWritePos = lOutCol >> 3;
  361. if (RLE_RowVisible)
  362. {
  363. if (RLE_ColVisible(lOutCol))
  364. jWorking = pjDst[ulWritePos] & ajBits[lOutCol & 7];
  365. else
  366. {
  367. if (RLE_PastRightEdge(lOutCol))
  368. jWorking = pjDst[ulRightWritePos];
  369. else
  370. jWorking = pjDst[ulLeftWritePos] & jLeftMask;
  371. }
  372. }
  373. // Diddle the translation table
  374. for (i = 1, j = 1; i < 16; i+=1, j ^= 1) pulXlate[i] = j;
  375. // Main Process loop
  376. LOOP_FOREVER
  377. {
  378. // Outta here if we can't get two more bytes
  379. if (RLE_SourceExhausted(2))
  380. return(FALSE);
  381. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  382. ulWritePos = lOutCol >> 3;
  383. if (ulCount == 0)
  384. {
  385. // Absolute or Escape Mode
  386. switch (ulNext)
  387. {
  388. case 0:
  389. // New Line.
  390. RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  391. RLE_NextLine(PBYTE, pjDst, lOutCol);
  392. if (RLE_PastTopEdge)
  393. {
  394. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  395. return(TRUE);
  396. }
  397. if (RLE_RowVisible)
  398. jWorking = pjDst[ulLeftWritePos] & jLeftMask;
  399. break;
  400. case 1:
  401. // End of the bitmap.
  402. RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  403. return(FALSE);
  404. case 2:
  405. // Positional Delta
  406. RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  407. // Outta here if we can't get the delta values
  408. if (RLE_SourceExhausted(2))
  409. return(FALSE);
  410. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  411. RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
  412. if (RLE_PastTopEdge)
  413. {
  414. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  415. return(TRUE);
  416. }
  417. // Fetch a new working byte off the destination
  418. ulWritePos = lOutCol >> 3;
  419. if (RLE_ColVisible(lOutCol))
  420. jWorking = pjDst[ulWritePos] & ajBits[lOutCol & 7];
  421. else
  422. if (RLE_PastRightEdge(lOutCol))
  423. jWorking = pjDst[ulRightWritePos];
  424. else
  425. jWorking = pjDst[ulLeftWritePos] & jLeftMask;
  426. break;
  427. default:
  428. /* Absolute Mode.
  429. * The run length is stored in <ulNext>, <ulCount> is used to
  430. * hold left and right clip amounts.
  431. */
  432. // Outta here if the bytes aren't in the source
  433. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  434. return(FALSE);
  435. RLE4_AlignToWord(pjSrc, ulNext);
  436. if (RLE_InVisibleRect(ulNext, lOutCol))
  437. {
  438. // Left side clipping
  439. if (lOutCol < (LONG)ulDstLeft)
  440. {
  441. ulCount = ulDstLeft - lOutCol;
  442. ulNext -= ulCount;
  443. lOutCol += ulCount;
  444. ulWritePos = lOutCol >> 3;
  445. pjSrc += (ulCount >> 1);
  446. jBitPos = (BYTE) ColToBitPos(lOutCol);
  447. jBitPosMask = ajPosMask[jBitPos]; // Always non-zero.
  448. // Force the source to a byte boundary
  449. if (bIsOdd(ulCount))
  450. {
  451. jSource = (BYTE)
  452. pulXlate[GetLowNybble(*pjSrc++)];
  453. if (jSource)
  454. jWorking |= jBitPosMask;
  455. jBitPosMask >>= 1;
  456. lOutCol++;
  457. ulNext--;
  458. }
  459. }
  460. else
  461. {
  462. jBitPos = (BYTE) ColToBitPos(lOutCol);
  463. jBitPosMask = ajPosMask[jBitPos]; // Always non-zero.
  464. }
  465. // Right side clipping
  466. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  467. {
  468. ulCount = (lOutCol + ulNext) - ulDstRight;
  469. ulNext -= ulCount;
  470. }
  471. else
  472. ulCount = 0;
  473. // Run Initialization
  474. bExtraByte = (BOOL) bIsOdd(ulNext);
  475. lOutCol += ulNext;
  476. // Slap the bits on. -- this is the funky-doodle stuff.
  477. i = 0; // Source read toggle.
  478. do {
  479. // Fill the working byte
  480. while(jBitPosMask && ulNext)
  481. {
  482. if (!i)
  483. {
  484. jSource = *pjSrc++;
  485. RLE4_MakeColourBlock(jSource, ajColours,
  486. BYTE, pulXlate);
  487. }
  488. if (ajColours[i])
  489. jWorking |= jBitPosMask;
  490. jBitPosMask >>= 1;
  491. ulNext--;
  492. i ^= 1;
  493. }
  494. // Write it
  495. if (!(jBitPosMask))
  496. {
  497. pjDst[ulWritePos] = jWorking;
  498. ulWritePos++;
  499. jBitPosMask = 0x80;
  500. jWorking = 0;
  501. }
  502. } while (ulNext);
  503. // Adjust for the right side clipping.
  504. pjSrc += bExtraByte ? (ulCount >> 1) :
  505. ((ulCount + 1) >> 1);
  506. lOutCol += ulCount;
  507. }
  508. else
  509. {
  510. /* Not on a visible scanline.
  511. * Adjust our x output position and source pointer.
  512. */
  513. lOutCol += ulNext;
  514. pjSrc += ((ulNext + 1) >> 1);
  515. } /* if */
  516. // Fix up if this run was not WORD aligned.
  517. RLE4_FixAlignment(pjSrc);
  518. } /* switch */
  519. }
  520. else
  521. {
  522. /* Encoded Mode
  523. * The run length is stored in <ulCount>, <ulClipMargin> is used
  524. * to hold left and right clip amounts.
  525. */
  526. if (RLE_InVisibleRect(ulCount, lOutCol))
  527. {
  528. // Left side clipping
  529. if (lOutCol < (LONG)ulDstLeft)
  530. {
  531. ulClipMargin = ulDstLeft - lOutCol;
  532. ulCount -= ulClipMargin;
  533. lOutCol += ulClipMargin;
  534. ulWritePos = lOutCol >> 3;
  535. }
  536. // Right side clipping
  537. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  538. {
  539. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  540. ulCount -= ulClipMargin;
  541. }
  542. else
  543. ulClipMargin = 0;
  544. // Initialize for the run
  545. RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
  546. jSource = ajBitPatterns[2*ajColours[0] + ajColours[1]];
  547. // jSource |= ((jSource << 2) |
  548. // (jSource << 4) |
  549. // (jSource << 6));
  550. jBitPos = (BYTE) ColToBitPos(lOutCol);
  551. jBitPosMask = ajPosMask[jBitPos];
  552. ulCompBytes = (ulCount < (ULONG)jBitPos + 1) ? 0 :
  553. ((BYTE)ulCount - jBitPos - 1) >> 3;
  554. lOutCol += ulCount;
  555. ulCount -= (ulCompBytes << 3);
  556. // Deal with a partial byte on the left
  557. if (jBitPos >= (LONG) ulCount)
  558. {
  559. // Will not fill the working byte
  560. jSource &= ajBits[ulCount];
  561. jWorking |= (BYTE)(jSource >> (7-jBitPos));
  562. jBitPos -= (BYTE)ulCount;
  563. ulCount = 0;
  564. }
  565. else
  566. {
  567. // Will fill the working byte
  568. jWorking |= (jSource & ajBits[jBitPos + 1])
  569. >> (7-jBitPos);
  570. pjDst[ulWritePos] = jWorking;
  571. if (!bIsOdd(jBitPos))
  572. jSource = RollLeft(jSource);
  573. ulWritePos++;
  574. jWorking = 0;
  575. ulCount -= (jBitPos + 1);
  576. jBitPos = 7;
  577. }
  578. // Deal with complete byte output
  579. if (ulCompBytes)
  580. {
  581. for (i = 0; i < ulCompBytes; i++)
  582. pjDst[ulWritePos + i] = jSource;
  583. ulWritePos += ulCompBytes;
  584. jBitPos = 7;
  585. jWorking = 0;
  586. }
  587. // Deal with the right side partial byte
  588. if (ulCount)
  589. jWorking |= (ajBits[ulCount] & jSource);
  590. // Adjust for the right side clipping.
  591. lOutCol += ulClipMargin;
  592. }
  593. else
  594. {
  595. /* Not on a visible scanline.
  596. * Adjust our x output position and source pointer.
  597. */
  598. lOutCol += ulCount;
  599. } /* if */
  600. } /* if */
  601. } /* LOOP_FOREVER */
  602. } /* bSrcCopySRLE4D1 */
  603. /******************************Public*Routine*****************************
  604. ** bSrcCopySRLE4D4
  605. *
  606. * Secure RLE blting to a 4 BPP DIB that does clipping and won't die or
  607. * write somewhere it shouldn't if given bad data.
  608. *
  609. * History:
  610. * 5 Feb 1992 - Andrew Milton (w-andym):
  611. * Added clip support.
  612. *
  613. * 24 Jan 1992 - Andrew Milton (w-andym): Creation.
  614. *
  615. \**************************************************************************/
  616. /* NOTE: In the Escape Modes, the current working byte must be
  617. * written to destination before the escape is executed.
  618. * To this end, the below macro...
  619. */
  620. #define RLE4to4_WritePartial(DstPtr, OutByte, OutColumn, WritePos) \
  621. if (RLE_RowVisible) \
  622. { \
  623. if (RLE_ColVisible(OutColumn) && bIsOdd(OutColumn)) \
  624. { \
  625. SetLowNybble(OutByte, DstPtr[WritePos]); \
  626. DstPtr[WritePos] = OutByte; \
  627. } \
  628. else \
  629. { \
  630. if (bRightPartial && RLE_PastRightEdge(OutColumn)) \
  631. { \
  632. SetLowNybble(OutByte, DstPtr[ulRightWritePos]); \
  633. DstPtr[ulRightWritePos] = OutByte; \
  634. } \
  635. } \
  636. } \
  637. BOOL
  638. bSrcCopySRLE4D4(
  639. PBLTINFO psb)
  640. {
  641. // Common RLE Initialization
  642. RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext,
  643. lOutCol, pulXlate);
  644. RLE_AssertValid(psb);
  645. RLE_FetchVisibleRect(psb);
  646. RLE_SetStartPos(psb, lOutCol);
  647. // Outta here if we start past the top edge. Don't need to save our position.
  648. if (RLE_PastTopEdge)
  649. return(TRUE); // Must have bits left in the bitmap since we haven't
  650. // consumed any.
  651. // Extra Variables
  652. BOOL bRightPartial; // TRUE when a visible row ends in a partial byte
  653. BYTE jWorking; // Hold area to build a byte for output
  654. ULONG ulWritePos; // Write position off <pjDst> into the destination
  655. ULONG ulLeftWritePos; // Leftmost write position
  656. ULONG ulRightWritePos; // Rightmost write position
  657. BYTE jSource; // Packed RLE 4 colour code
  658. BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
  659. // Our Initialization
  660. ulLeftWritePos = ulDstLeft >> 1;
  661. ulRightWritePos = ulDstRight >> 1;
  662. bRightPartial = (BOOL) bIsOdd(ulDstRight);
  663. // Fetch our inital working byte
  664. ulWritePos = lOutCol >> 1;
  665. if (RLE_RowVisible)
  666. jWorking = pjDst[BoundsCheck(ulLeftWritePos, ulRightWritePos,
  667. ulWritePos)];
  668. // Main processing loop
  669. LOOP_FOREVER
  670. {
  671. ulWritePos = lOutCol >> 1;
  672. // Outta here if we can't get two more bytes
  673. if (RLE_SourceExhausted(2))
  674. return(FALSE);
  675. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  676. if (ulCount == 0)
  677. {
  678. // Absolute or Escape Mode.
  679. switch (ulNext)
  680. {
  681. case 0:
  682. // New Line
  683. RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  684. RLE_NextLine(PBYTE, pjDst, lOutCol);
  685. if (RLE_PastTopEdge)
  686. {
  687. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  688. return(TRUE);
  689. }
  690. if (RLE_RowVisible)
  691. jWorking = pjDst[ulLeftWritePos];
  692. break;
  693. case 1:
  694. // End of bitmap
  695. RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  696. return(FALSE);
  697. case 2:
  698. // Positional Delta
  699. RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
  700. // Outta here if we can't get the delta values
  701. if (RLE_SourceExhausted(2))
  702. return(FALSE);
  703. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  704. RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
  705. if (RLE_PastTopEdge)
  706. {
  707. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  708. return(TRUE);
  709. }
  710. // Read initial working byte
  711. ulWritePos = lOutCol >> 1;
  712. jWorking =
  713. pjDst[BoundsCheck(ulLeftWritePos, ulRightWritePos,
  714. ulWritePos)];
  715. break;
  716. default:
  717. // Absolute Mode
  718. // Outta here if the bytes aren't in the source
  719. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  720. return(FALSE);
  721. RLE4_AlignToWord(pjSrc, ulNext);
  722. if (RLE_InVisibleRect(ulNext, lOutCol))
  723. {
  724. // Left Side Clipping. Lots 'o stuff happenin'
  725. if (lOutCol < (LONG)ulDstLeft)
  726. {
  727. ulCount = ulDstLeft - lOutCol;
  728. lOutCol = ulDstLeft;
  729. ulWritePos = ulDstLeft >> 1;
  730. ulNext -= ulCount;
  731. pjSrc += (ulCount >> 1);
  732. // Align the source run to a byte boundary
  733. if (bIsOdd(ulCount))
  734. {
  735. jSource = (BYTE) pulXlate[GetLowNybble(*pjSrc++)];
  736. if (bIsOdd(lOutCol))
  737. {
  738. SetLowNybble(jWorking, jSource);
  739. pjDst[ulWritePos] = jWorking;
  740. ulWritePos++;
  741. }
  742. else
  743. SetHighNybble(jWorking, jSource);
  744. lOutCol++;
  745. ulNext--;
  746. // Deal with the special case only one byte is visible
  747. if (!ulNext)
  748. {
  749. RLE4_FixAlignment(pjSrc);
  750. continue;
  751. }
  752. }
  753. }
  754. // Right Side Clipping
  755. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  756. {
  757. ulCount = (lOutCol + ulNext) - ulDstRight;
  758. ulNext = ulDstRight - lOutCol;
  759. }
  760. else
  761. ulCount = 0;
  762. // Write the Run
  763. ASSERTGDI(lOutCol < (LONG) ulDstRight,
  764. "No longer visible\n");
  765. if (ulNext != 0)
  766. {
  767. if (bIsOdd(lOutCol))
  768. {
  769. // Case 1: Source & Dest misaligned w.r.t. bytes
  770. lOutCol += ulNext;
  771. jSource = *pjSrc++;
  772. RLE4_MakeColourBlock(jSource, ajColours,
  773. BYTE, pulXlate);
  774. SetLowNybble(jWorking, ajColours[0]);
  775. pjDst[ulWritePos] = jWorking;
  776. ulWritePos++;
  777. ulNext--;
  778. ulNext >>= 1;
  779. while (ulNext)
  780. {
  781. SetHighNybble(jWorking, ajColours[1]);
  782. jSource = *pjSrc++;
  783. RLE4_MakeColourBlock(jSource, ajColours,
  784. BYTE, pulXlate);
  785. SetLowNybble(jWorking, ajColours[0]);
  786. pjDst[ulWritePos] = jWorking;
  787. ulWritePos++;
  788. ulNext--;
  789. } /* while */
  790. /* Account for the right side partial byte
  791. * and do the right clip adjustment on the source
  792. */
  793. if (bIsOdd(lOutCol))
  794. {
  795. SetHighNybble(jWorking, ajColours[1]);
  796. pjSrc += ((ulCount + 1) >> 1);
  797. }
  798. else
  799. {
  800. pjSrc += (ulCount >> 1);
  801. }
  802. }
  803. else
  804. {
  805. // Case 2: Source & Dest aligned on byte boundaries
  806. lOutCol += ulNext;
  807. ulNext >>= 1;
  808. while (ulNext)
  809. {
  810. jSource = *pjSrc++;
  811. RLE4_MakeColourBlock(jSource, ajColours,
  812. BYTE, pulXlate);
  813. jWorking = BuildByte(ajColours[0], ajColours[1]);
  814. pjDst[ulWritePos] = jWorking;
  815. ulWritePos++;
  816. ulNext--;
  817. } /* while */
  818. /* Account for the right side partial byte
  819. * and do the right clip adjustment on the source
  820. */
  821. if (bIsOdd(lOutCol))
  822. {
  823. jSource = GetHighNybble(*pjSrc++);
  824. SetHighNybble(jWorking,
  825. (BYTE)pulXlate[(ULONG)jSource]);
  826. pjSrc += (ulCount >> 1);
  827. }
  828. else
  829. {
  830. pjSrc += ((ulCount + 1) >> 1);
  831. }
  832. }
  833. }
  834. else
  835. {
  836. /* Do the right clip adjustment on the source
  837. */
  838. pjSrc += ((ulCount + 1) >> 1);
  839. }
  840. lOutCol += ulCount;
  841. }
  842. else
  843. {
  844. /* Not on a visible scanline.
  845. * Adjust our x output position and source pointer.
  846. */
  847. lOutCol += ulNext;
  848. pjSrc += ((ulNext + 1) >> 1);
  849. } /* if */
  850. // Fix up if this run was not WORD aligned.
  851. RLE4_FixAlignment(pjSrc);
  852. } /* switch */
  853. }
  854. else
  855. {
  856. // Encoded Mode
  857. if (RLE_InVisibleRect(ulCount, lOutCol))
  858. {
  859. ULONG ulClipMargin = 0;
  860. // Left side clipping
  861. if (lOutCol < (LONG)ulDstLeft)
  862. {
  863. ulClipMargin = ulDstLeft - lOutCol;
  864. lOutCol = ulDstLeft;
  865. ulWritePos = ulDstLeft >> 1;
  866. ulCount -= ulClipMargin;
  867. }
  868. // Right side clipping
  869. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  870. {
  871. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  872. ulCount = ulDstRight - lOutCol;
  873. }
  874. else
  875. ulClipMargin = 0;
  876. RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
  877. // Align the destination to a byte boundary
  878. if (bIsOdd(lOutCol))
  879. {
  880. SetLowNybble(jWorking, ajColours[0]);
  881. pjDst[ulWritePos] = jWorking;
  882. ulWritePos++;
  883. lOutCol++;
  884. ulCount--;
  885. SwapValues(ajColours[0], ajColours[1]);
  886. }
  887. lOutCol += ulCount;
  888. // Run initialization
  889. ulCount >>= 1;
  890. jWorking = BuildByte(ajColours[0], ajColours[1]);
  891. // Write complete bytes
  892. while(ulCount)
  893. {
  894. pjDst[ulWritePos] = jWorking;
  895. ulWritePos++;
  896. ulCount--;
  897. }
  898. // Account for writing a partial byte on the right side
  899. if (bIsOdd(lOutCol))
  900. SetHighNybble(jWorking, ajColours[0]);
  901. // Adjust for the right side clipping.
  902. lOutCol += ulClipMargin;
  903. }
  904. else
  905. {
  906. // Not on a visible scanline. Adjust our x output position
  907. lOutCol += ulCount;
  908. } /* if */
  909. } /* if */
  910. } /* LOOP_FOREVER */
  911. } /* bSrcCopySRLE4D4 */
  912. /******************************Public*Routine******************************\
  913. * bSrcCopySRLE4D16
  914. *
  915. * Secure RLE blting to a 16 BPP DIB that does clipping and won't die or
  916. * write somewhere it shouldn't if given bad data.
  917. *
  918. * History:
  919. * 28 Feb 1992 - Andrew Milton (w-andym): Creation.
  920. *
  921. \**************************************************************************/
  922. BOOL
  923. bSrcCopySRLE4D16(
  924. PBLTINFO psb)
  925. {
  926. // Common RLE Initialization
  927. RLE_InitVars(psb, pjSrc, pwDst, PWORD, ulCount, ulNext, lOutCol,
  928. pulXlate);
  929. RLE_AssertValid(psb);
  930. RLE_FetchVisibleRect(psb);
  931. RLE_SetStartPos(psb, lOutCol);
  932. // Outta here if we start past the top edge. Don't need to save our position.
  933. if (RLE_PastTopEdge)
  934. return(TRUE); // Must have bits left in the bitmap since we haven't
  935. // consumed any.
  936. // Extra Variables
  937. BYTE jSource; // Packed RLE 4 colour code
  938. WORD awColours[2]; // Destination for unpacking an RLE 4 code
  939. BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
  940. // Main process loop
  941. LOOP_FOREVER
  942. {
  943. // Outta here if we can't get two more bytes
  944. if (RLE_SourceExhausted(2))
  945. return(FALSE);
  946. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  947. if (ulCount == 0)
  948. {
  949. // Absolute or Escape Mode
  950. switch (ulNext)
  951. {
  952. case 0:
  953. // New Line
  954. RLE_NextLine(PWORD, pwDst, lOutCol);
  955. if (RLE_PastTopEdge)
  956. {
  957. RLE_SavePosition(psb, pjSrc, pwDst, lOutCol);
  958. return(TRUE);
  959. }
  960. break;
  961. case 1:
  962. // End of the Bitmap.
  963. return(FALSE);
  964. case 2:
  965. /* Positional Delta.
  966. * The delta values live in the next two source bytes
  967. */
  968. // Outta here if we can't get the delta values
  969. if (RLE_SourceExhausted(2))
  970. return(FALSE);
  971. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  972. RLE_PosDelta(pwDst, lOutCol, ulCount, ulNext);
  973. if (RLE_PastTopEdge)
  974. {
  975. RLE_SavePosition(psb, pjSrc, pwDst, lOutCol);
  976. return(TRUE);
  977. }
  978. break;
  979. default:
  980. /* Absolute Mode.
  981. * The run length is stored in <ulNext>, <ulCount> is used to
  982. * hold left and right clip amounts.
  983. */
  984. // Outta here if the bytes aren't in the source
  985. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  986. return(FALSE);
  987. RLE4_AlignToWord(pjSrc, ulNext);
  988. if (RLE_InVisibleRect(ulNext, lOutCol))
  989. {
  990. // Left side clipping
  991. if (lOutCol < (LONG)ulDstLeft)
  992. {
  993. ulCount = ulDstLeft - lOutCol;
  994. lOutCol = ulDstLeft;
  995. ulNext -= ulCount;
  996. pjSrc += (ulCount >> 1);
  997. // Align the source run to a byte boundary
  998. if (bIsOdd(ulCount))
  999. {
  1000. jSource = (BYTE) *pjSrc++;
  1001. pwDst[lOutCol] =
  1002. (WORD) pulXlate[GetLowNybble(jSource)];
  1003. lOutCol++;
  1004. ulNext--;
  1005. }
  1006. }
  1007. // Right side clipping
  1008. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  1009. {
  1010. ulCount = (lOutCol + ulNext) - ulDstRight;
  1011. ulNext -= ulCount;
  1012. }
  1013. else
  1014. ulCount = 0;
  1015. // Slap the bits on. -- this is the funky-doodle stuff.
  1016. bExtraByte = (BOOL) bIsOdd(ulNext);
  1017. ulNext >>= 1;
  1018. // Deal with complete source bytes
  1019. while (ulNext)
  1020. {
  1021. jSource = *pjSrc++;
  1022. RLE4_MakeColourBlock(jSource, awColours, WORD,
  1023. pulXlate);
  1024. pwDst[lOutCol] = awColours[0];
  1025. pwDst[lOutCol+1] = awColours[1];
  1026. lOutCol += 2;
  1027. ulNext--;
  1028. }
  1029. // Account for right partial byte in the source */
  1030. if (bExtraByte)
  1031. {
  1032. jSource = *pjSrc++;
  1033. RLE4_MakeColourBlock(jSource, awColours, WORD,
  1034. pulXlate);
  1035. pwDst[lOutCol] = awColours[0];
  1036. lOutCol++;
  1037. pjSrc += (ulCount >> 1); // Clip Adjustment
  1038. }
  1039. else
  1040. pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
  1041. // Adjust the column for the right side clipping.
  1042. lOutCol += ulCount;
  1043. }
  1044. else
  1045. {
  1046. /* Not on a visible scanline.
  1047. * Adjust our x output position and source pointer.
  1048. */
  1049. lOutCol += ulNext;
  1050. pjSrc += (ulNext + 1) >> 1;
  1051. } /* if */
  1052. // Fix up if this run was not WORD aligned.
  1053. RLE4_FixAlignment(pjSrc)
  1054. } /* switch */
  1055. }
  1056. else
  1057. {
  1058. /* Encoded Mode
  1059. * The run length is stored in <ulCount>, <ulClipMargin> is used
  1060. * to hold left and right clip amounts.
  1061. */
  1062. if (RLE_InVisibleRect(ulCount, lOutCol))
  1063. {
  1064. ULONG ulClipMargin = 0;
  1065. // Left side clipping
  1066. if (lOutCol < (LONG)ulDstLeft)
  1067. {
  1068. ulClipMargin = ulDstLeft - lOutCol;
  1069. lOutCol = ulDstLeft;
  1070. ulCount -= ulClipMargin;
  1071. }
  1072. // Right side clipping
  1073. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  1074. {
  1075. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  1076. ulCount -= ulClipMargin;
  1077. }
  1078. else
  1079. ulClipMargin = 0;
  1080. // Run initialization
  1081. bExtraByte = (BOOL) bIsOdd(ulCount);
  1082. ulCount >>= 1;
  1083. RLE4_MakeColourBlock(ulNext, awColours, WORD, pulXlate);
  1084. // Write the run
  1085. while (ulCount)
  1086. {
  1087. pwDst[lOutCol] = awColours[0];
  1088. pwDst[lOutCol+1] = awColours[1];
  1089. lOutCol += 2;
  1090. ulCount --;
  1091. }
  1092. // ... and an extra byte for an odd run length
  1093. if (bExtraByte)
  1094. {
  1095. pwDst[lOutCol] = awColours[0];
  1096. lOutCol++;
  1097. }
  1098. // Adjust for the right side clipping.
  1099. lOutCol += ulClipMargin;
  1100. }
  1101. else
  1102. {
  1103. /* Not on a visible scanline.
  1104. * Adjust our x output position
  1105. */
  1106. lOutCol += ulCount;
  1107. } /* if */
  1108. } /* if */
  1109. } /* LOOP_FOREVER */
  1110. } /* bSrcCopySRLE4D16 */
  1111. /******************************Public*Routine*****************************
  1112. ** bSrcCopySRLE4D24
  1113. *
  1114. * Secure RLE blting to a 24 BPP DIB that does clipping and won't die or
  1115. * write somewhere it shouldn't if given bad data.
  1116. *
  1117. * History:
  1118. * 28 Feb 1992 - Andrew Milton (w-andym): Creation.
  1119. *
  1120. \**************************************************************************/
  1121. #define RLE_24BitWrite(DstPtr, BytePos, Colour) \
  1122. DstPtr[BytePos] = (BYTE)Colour; \
  1123. DstPtr[BytePos+1] = (BYTE)(Colour >> 8); \
  1124. DstPtr[BytePos+2] = (BYTE)(Colour >> 16); \
  1125. BytePos += 3; \
  1126. BOOL
  1127. bSrcCopySRLE4D24(
  1128. PBLTINFO psb)
  1129. {
  1130. // Common RLE Initialization
  1131. RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol, pulXlate);
  1132. RLE_AssertValid(psb);
  1133. RLE_FetchVisibleRect(psb);
  1134. RLE_SetStartPos(psb, lOutCol);
  1135. // Outta here if we start past the top edge. Don't need to save our position.
  1136. if (RLE_PastTopEdge)
  1137. return(TRUE); // Must have bits left in the bitmap since we haven't
  1138. // consumed any.
  1139. // Extra Variables
  1140. ULONG ulWritePos; // Write position off <pjDst> into the destination
  1141. BYTE jSource; // Packed RLE 4 colour code
  1142. DWORD adwColours[2]; // Destination for unpacking an RLE 4 code
  1143. BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
  1144. ULONG ulClipMargin; // Number of bytes clipped off an Encoded run
  1145. // Main process loop
  1146. LOOP_FOREVER
  1147. {
  1148. // Outta here if we can't get two more bytes
  1149. if (RLE_SourceExhausted(2))
  1150. return(FALSE);
  1151. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  1152. if (ulCount == 0)
  1153. {
  1154. // Absolute or Escape Mode
  1155. switch (ulNext)
  1156. {
  1157. case 0:
  1158. // New line
  1159. RLE_NextLine(PBYTE, pjDst, lOutCol);
  1160. if (RLE_PastTopEdge)
  1161. {
  1162. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  1163. return(TRUE);
  1164. }
  1165. break;
  1166. case 1:
  1167. // End of the Bitmap
  1168. return(FALSE);
  1169. case 2:
  1170. /* Positional Delta.
  1171. * The delta values live in the next two source bytes
  1172. */
  1173. // Outta here if we can't get two more bytes
  1174. if (RLE_SourceExhausted(2))
  1175. return(FALSE);
  1176. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  1177. RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
  1178. if (RLE_PastTopEdge)
  1179. {
  1180. RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
  1181. return(TRUE);
  1182. }
  1183. break;
  1184. default:
  1185. /* Absolute Mode.
  1186. * The run length is stored in <ulNext>, <ulCount> is used to
  1187. * hold left and right clip amounts.
  1188. */
  1189. // Outta here if the bytes aren't in the source
  1190. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  1191. return(FALSE);
  1192. RLE4_AlignToWord(pjSrc, ulNext);
  1193. if (RLE_InVisibleRect(ulNext, lOutCol))
  1194. {
  1195. // Left side clipping
  1196. if (lOutCol < (LONG)ulDstLeft)
  1197. {
  1198. ulCount = ulDstLeft - lOutCol;
  1199. lOutCol = ulDstLeft;
  1200. ulNext -= ulCount;
  1201. ulWritePos = 3*lOutCol;
  1202. pjSrc += (ulCount >> 1);
  1203. // Align the Source run to a byte boundary
  1204. if (bIsOdd(ulCount))
  1205. {
  1206. adwColours[0] = pulXlate[GetLowNybble(*pjSrc++)];
  1207. RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
  1208. lOutCol++;
  1209. ulNext--;
  1210. }
  1211. }
  1212. else
  1213. ulWritePos = 3*lOutCol;
  1214. // Right side clipping
  1215. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  1216. {
  1217. ulCount = (lOutCol + ulNext) - ulDstRight;
  1218. ulNext -= ulCount;
  1219. }
  1220. else
  1221. ulCount = 0;
  1222. // Run Initialization.
  1223. bExtraByte = (BOOL) bIsOdd(ulNext);
  1224. lOutCol += ulNext;
  1225. ulNext >>= 1;
  1226. // Write complete bytes from the source
  1227. while (ulNext)
  1228. {
  1229. jSource = *pjSrc++;
  1230. RLE4_MakeColourBlock(jSource, adwColours, DWORD,
  1231. pulXlate);
  1232. RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
  1233. RLE_24BitWrite(pjDst, ulWritePos, adwColours[1]);
  1234. ulNext--;
  1235. }
  1236. // Account for a right partial byte in the source
  1237. if (bExtraByte)
  1238. {
  1239. adwColours[0] = pulXlate[GetHighNybble(*pjSrc++)];
  1240. RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
  1241. pjSrc += (ulCount >> 1); // Clip Adjustment
  1242. }
  1243. else
  1244. pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
  1245. // Adjust the column for the right side clipping.
  1246. lOutCol += ulCount;
  1247. }
  1248. else
  1249. {
  1250. /* Not on a visible scanline.
  1251. * Adjust our x output position and source pointer.
  1252. */
  1253. lOutCol += ulNext;
  1254. pjSrc += (ulNext + 1) >> 1;
  1255. } /* if */
  1256. // Fix up if this run was not WORD aligned.
  1257. RLE4_FixAlignment(pjSrc)
  1258. } /* switch */
  1259. }
  1260. else
  1261. {
  1262. /* Encoded Mode
  1263. * The run length is stored in <ulCount>, <ulClipMargin> is used
  1264. * to hold left and right clip amounts.
  1265. */
  1266. if (RLE_InVisibleRect(ulCount, lOutCol))
  1267. {
  1268. // Left side clipping
  1269. if (lOutCol < (LONG)ulDstLeft)
  1270. {
  1271. ulClipMargin = ulDstLeft - lOutCol;
  1272. lOutCol = ulDstLeft;
  1273. ulCount -= ulClipMargin;
  1274. }
  1275. // Right side clipping
  1276. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  1277. {
  1278. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  1279. ulCount -= ulClipMargin;
  1280. }
  1281. else
  1282. ulClipMargin = 0;
  1283. // Run initialization
  1284. ulWritePos = 3*lOutCol;
  1285. lOutCol += ulCount;
  1286. bExtraByte = (BOOL) bIsOdd(ulCount);
  1287. ulCount >>= 1;
  1288. RLE4_MakeColourBlock(ulNext, adwColours, DWORD, pulXlate);
  1289. // Write the run
  1290. while (ulCount)
  1291. {
  1292. RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
  1293. RLE_24BitWrite(pjDst, ulWritePos, adwColours[1]);
  1294. ulCount --;
  1295. }
  1296. // Write the extra byte from an odd run length
  1297. if (bExtraByte)
  1298. {
  1299. RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
  1300. }
  1301. // Adjust for the right side clipping.
  1302. lOutCol += ulClipMargin;
  1303. }
  1304. else
  1305. {
  1306. /* Not on a visible scanline.
  1307. * Adjust our x output position
  1308. */
  1309. lOutCol += ulCount;
  1310. } /* if */
  1311. } /* if */
  1312. } /* LOOP_FOREVER */
  1313. } /* bSrcCopySRLE4D24 */
  1314. /******************************Public*Routine*****************************
  1315. ** bSrcCopySRLE4D32
  1316. *
  1317. * Secure RLE blting to a 32 BPP DIB that does clipping and won't die or
  1318. * write somewhere it shouldn't if given bad data.
  1319. *
  1320. * History:
  1321. * 28 Feb 1992 - Andrew Milton (w-andym): Creation.
  1322. *
  1323. \**************************************************************************/
  1324. BOOL
  1325. bSrcCopySRLE4D32(
  1326. PBLTINFO psb)
  1327. {
  1328. // Common RLE Initialization
  1329. RLE_InitVars(psb, pjSrc, pdwDst, PDWORD, ulCount, ulNext,
  1330. lOutCol, pulXlate);
  1331. RLE_AssertValid(psb);
  1332. RLE_FetchVisibleRect(psb);
  1333. RLE_SetStartPos(psb, lOutCol);
  1334. // Outta here if we start past the top edge. Don't need to save our position.
  1335. if (RLE_PastTopEdge)
  1336. return(TRUE); // Must have bits left in the bitmap since we haven't
  1337. // consumed any.
  1338. // Extra Variables
  1339. BYTE jSource; // Packed RLE 4 colour code
  1340. DWORD adwColours[2]; // Destination for unpacking an RLE 4 code
  1341. BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
  1342. ULONG ulClipMargin; // Number of bytes clipped off an Encoded run
  1343. // Main processing loop
  1344. LOOP_FOREVER
  1345. {
  1346. // Outta here if we can't get two more bytes
  1347. if (RLE_SourceExhausted(2))
  1348. return(FALSE);
  1349. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  1350. if (ulCount == 0)
  1351. {
  1352. // Absolute or Escape Mode
  1353. switch (ulNext)
  1354. {
  1355. case 0:
  1356. // New line
  1357. RLE_NextLine(PDWORD, pdwDst, lOutCol);
  1358. if (RLE_PastTopEdge)
  1359. {
  1360. RLE_SavePosition(psb, pjSrc, pdwDst, lOutCol);
  1361. return(TRUE);
  1362. }
  1363. break;
  1364. case 1:
  1365. // End of the Bitmap
  1366. return(FALSE);
  1367. case 2:
  1368. /* Positional Delta.
  1369. * The delta values live in the next two source bytes
  1370. */
  1371. // Outta here if we can't get two more bytes
  1372. if (RLE_SourceExhausted(2))
  1373. return(FALSE);
  1374. RLE_GetNextCode(pjSrc, ulCount, ulNext);
  1375. RLE_PosDelta(pdwDst, lOutCol, ulCount, ulNext);
  1376. if (RLE_PastTopEdge)
  1377. {
  1378. RLE_SavePosition(psb, pjSrc, pdwDst, lOutCol);
  1379. return(TRUE);
  1380. }
  1381. break;
  1382. default:
  1383. // Absolute Mode
  1384. // Outta here if the bytes aren't in the source
  1385. if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
  1386. return(FALSE);
  1387. RLE4_AlignToWord(pjSrc, ulNext);
  1388. if (RLE_InVisibleRect(ulNext, lOutCol))
  1389. {
  1390. // Left side clipping
  1391. if (lOutCol < (LONG)ulDstLeft)
  1392. {
  1393. ulCount = ulDstLeft - lOutCol;
  1394. lOutCol = ulDstLeft;
  1395. ulNext -= ulCount;
  1396. pjSrc += (ulCount >> 1);
  1397. // Align the source run to a byte boundary
  1398. if (bIsOdd(ulCount))
  1399. {
  1400. jSource = (BYTE) *pjSrc++;
  1401. pdwDst[lOutCol] =
  1402. (DWORD) pulXlate[GetLowNybble(jSource)];
  1403. lOutCol++;
  1404. ulNext--;
  1405. }
  1406. }
  1407. // Right side clipping
  1408. if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
  1409. {
  1410. ulCount = (lOutCol + ulNext) - ulDstRight;
  1411. ulNext -= ulCount;
  1412. }
  1413. else
  1414. ulCount = 0;
  1415. // Slap the bits on. -- this is the funky-doodle stuff.
  1416. bExtraByte = (BOOL) bIsOdd(ulNext);
  1417. ulNext >>= 1;
  1418. // Write complete bytes from the source
  1419. while (ulNext)
  1420. {
  1421. jSource = *pjSrc++;
  1422. RLE4_MakeColourBlock(jSource, adwColours, DWORD,
  1423. pulXlate);
  1424. pdwDst[lOutCol] = adwColours[0];
  1425. pdwDst[lOutCol+1] = adwColours[1];
  1426. lOutCol += 2;
  1427. ulNext--;
  1428. }
  1429. // Account for a right partial byte in the source
  1430. if (bExtraByte)
  1431. {
  1432. jSource = *pjSrc++;
  1433. RLE4_MakeColourBlock(jSource, adwColours, DWORD,
  1434. pulXlate);
  1435. pdwDst[lOutCol] = adwColours[0];
  1436. lOutCol++;
  1437. pjSrc += (ulCount >> 1); // Clip Adjustment
  1438. }
  1439. else
  1440. pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
  1441. // Adjust the column for the right side clipping.
  1442. lOutCol += ulCount;
  1443. }
  1444. else
  1445. {
  1446. /* Not on a visible scanline.
  1447. * Adjust our x output position and source pointer.
  1448. */
  1449. lOutCol += ulNext;
  1450. pjSrc += (ulNext + 1) >> 1;
  1451. } /* if */
  1452. // Fix up if this run was not WORD aligned.
  1453. RLE4_FixAlignment(pjSrc);
  1454. } /* switch */
  1455. }
  1456. else
  1457. {
  1458. /* Encoded Mode
  1459. * The run length is stored in <ulCount>, <ulClipMargin> is used
  1460. * to hold left and right clip amounts.
  1461. */
  1462. if (RLE_InVisibleRect(ulCount, lOutCol))
  1463. {
  1464. // Left side clipping
  1465. if (lOutCol < (LONG)ulDstLeft)
  1466. {
  1467. ulClipMargin = ulDstLeft - lOutCol;
  1468. lOutCol = ulDstLeft;
  1469. ulCount -= ulClipMargin;
  1470. }
  1471. // Right side clipping
  1472. if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
  1473. {
  1474. ulClipMargin = (lOutCol + ulCount) - ulDstRight;
  1475. ulCount -= ulClipMargin;
  1476. }
  1477. else
  1478. ulClipMargin = 0;
  1479. // Run Initialization.
  1480. bExtraByte = (BOOL) bIsOdd(ulCount);
  1481. ulCount >>= 1;
  1482. RLE4_MakeColourBlock(ulNext, adwColours, DWORD, pulXlate);
  1483. // Write the run
  1484. while (ulCount)
  1485. {
  1486. pdwDst[lOutCol] = adwColours[0];
  1487. pdwDst[lOutCol+1] = adwColours[1];
  1488. lOutCol += 2;
  1489. ulCount --;
  1490. }
  1491. // Write the extra byte from an odd run length
  1492. if (bExtraByte)
  1493. {
  1494. pdwDst[lOutCol] = adwColours[0];
  1495. lOutCol++;
  1496. }
  1497. // Adjust for the right side clipping.
  1498. lOutCol += ulClipMargin;
  1499. }
  1500. else
  1501. {
  1502. /* Not on a visible scanline.
  1503. * Adjust our x output position
  1504. */
  1505. lOutCol += ulCount;
  1506. } /* if */
  1507. } /* if */
  1508. } /* LOOP_FOREVER */
  1509. } /* bSrcCopySRLE4D32 */
  1510. /*******************************Public*Routine*****************************\
  1511. * WriteEncoded4
  1512. *
  1513. * A helper function for EncodeRLE4. Writes a run of bytes in encoded format.
  1514. *
  1515. * Created: 28 Oct 92 @ 14:00
  1516. *
  1517. * Author: Gerrit van Wingerden [gerritv]
  1518. *
  1519. \**************************************************************************/
  1520. int WriteEncoded4( BYTE bValue, BYTE *pbTarget, UINT uiLength,
  1521. BYTE *pbEndOfBuffer )
  1522. {
  1523. if( pbTarget == NULL )
  1524. return(2);
  1525. if( pbTarget + 2 > pbEndOfBuffer )
  1526. return(0);
  1527. *pbTarget++ = (BYTE) uiLength;
  1528. *pbTarget++ = bValue;
  1529. return(2);
  1530. }
  1531. /*******************************Public*Routine*****************************\
  1532. * WriteAbsolute4
  1533. *
  1534. * A helper function for EncodeRLE4. Writes a run of bytes in absolute format.
  1535. *
  1536. * Created: 28 Oct 92 @ 14:00
  1537. *
  1538. * Author: Gerrit van Wingerden [gerritv]
  1539. *
  1540. \**************************************************************************/
  1541. int WriteAbsolute4( BYTE *pbRunStart, BYTE *pbTarget, int cRunLength,
  1542. BYTE *pbEndOfBuffer )
  1543. {
  1544. int iRet;
  1545. if( cRunLength < 3 )
  1546. {
  1547. iRet = 2;
  1548. }
  1549. else
  1550. {
  1551. if( ( cRunLength + 1 ) & 0x02 )
  1552. {
  1553. iRet = (( cRunLength + 1 ) >> 1) + 3;
  1554. }
  1555. else
  1556. {
  1557. iRet = (( cRunLength + 1 ) >> 1) + 2;
  1558. }
  1559. }
  1560. if( pbTarget == NULL )
  1561. return(iRet);
  1562. if( pbTarget + iRet > pbEndOfBuffer )
  1563. return(0);
  1564. if( cRunLength < 3 )
  1565. {
  1566. *pbTarget++ = (BYTE) cRunLength;
  1567. *pbTarget = *pbRunStart;
  1568. return(2);
  1569. }
  1570. *pbTarget++ = 0;
  1571. *pbTarget++ = (BYTE) cRunLength;
  1572. RtlMoveMemory( pbTarget, pbRunStart, ( cRunLength + 1 ) >> 1 );
  1573. pbTarget += ( cRunLength + 1 ) >> 1;
  1574. if( ( cRunLength + 1 ) & 0x02 )
  1575. {
  1576. *pbTarget++ = 0;
  1577. return( iRet );
  1578. }
  1579. else
  1580. return( iRet );
  1581. }
  1582. /*******************************Public*Routine*****************************\
  1583. * EncodeRLE4
  1584. *
  1585. * Encodes a bitmap into RLE4 format and returns the length of the of the
  1586. * encoded format. If the source is NULL it just returns the length of
  1587. * the format. If the encoded output turns out to be longer than cBufferSize
  1588. * the functions stops encoding.
  1589. *
  1590. * History:
  1591. * 28 Oct 1992 Gerrit van Wingerden [gerritv] : creation
  1592. * 15 Mar 1993 Stephan J. Zachwieja [szach] : return 0 if buffer too small
  1593. *
  1594. \**************************************************************************/
  1595. int EncodeRLE4( BYTE *pbSource, BYTE *pbTarget, UINT uiWidth, UINT cNumLines,
  1596. UINT cBufferSize )
  1597. {
  1598. UINT cLineCount, uiLineWidth;
  1599. BYTE bLastByte,bCurChar;
  1600. BYTE *pbRunStart;
  1601. BYTE *pbLineEnd;
  1602. BYTE *pbEndOfBuffer;
  1603. BYTE *pbCurPos;
  1604. INT cCurrentRunLength;
  1605. INT iMode, cTemp;
  1606. UINT cTotal = 0;
  1607. pbEndOfBuffer = pbTarget + cBufferSize;
  1608. // Compute width of line in bytes rounded to a DWORD boundary
  1609. uiLineWidth = ( ( uiWidth + 7 ) >> 3 ) << 2 ;
  1610. for( cLineCount = 0; cLineCount < cNumLines; cLineCount ++ )
  1611. {
  1612. pbRunStart = pbSource + uiLineWidth * cLineCount;
  1613. bLastByte = *pbRunStart;
  1614. pbLineEnd = pbRunStart + ( ( uiWidth + 1 ) >> 1 );
  1615. iMode = RLE_START;
  1616. cCurrentRunLength = 2;
  1617. for(pbCurPos = pbRunStart+1;pbCurPos <= pbLineEnd; pbCurPos += 1)
  1618. {
  1619. // We won't really encode the value at *pbLineEnd since it points
  1620. // past the end of the scan so it doesn't matter what value we use.
  1621. // However, it is important not to reference it since it may point
  1622. // past the end of the buffer which can be uncommited memory.
  1623. if( pbCurPos == pbLineEnd )
  1624. {
  1625. bCurChar = 0xFF;
  1626. }
  1627. else
  1628. {
  1629. bCurChar = *pbCurPos;
  1630. }
  1631. switch( iMode )
  1632. {
  1633. case RLE_START:
  1634. iMode = ( bCurChar == bLastByte ) ? RLE_ENCODED : RLE_ABSOLUTE;
  1635. bLastByte = bCurChar;
  1636. break;
  1637. case RLE_ABSOLUTE:
  1638. // There are two ways that this run could be over. We could have exceeded the
  1639. // maximum length 0xFE ( since this algorithm works with bytes ), or there
  1640. // could be a switch into absolute mode.
  1641. if( ( bCurChar == bLastByte ) ||
  1642. ( cCurrentRunLength == 0xFE ) )
  1643. {
  1644. int iOffset;
  1645. if( cCurrentRunLength == 0xFE )
  1646. {
  1647. // If this is the end of the line and there is and odd line length, ignore the
  1648. // last nibble of the the final byte.
  1649. if( (pbCurPos == pbLineEnd ) && ( uiWidth & 0x01 ))
  1650. iOffset = 1;
  1651. else
  1652. iOffset = 0;
  1653. iMode = RLE_START;
  1654. }
  1655. else
  1656. {
  1657. iOffset = 2;
  1658. iMode = RLE_ENCODED;
  1659. }
  1660. cTemp = WriteAbsolute4(pbRunStart, pbTarget,
  1661. cCurrentRunLength - iOffset, pbEndOfBuffer);
  1662. // if pbTarget is not NULL and cTemp is zero then
  1663. // the buffer is too small to hold encoded data
  1664. if(pbTarget != NULL) {
  1665. if (cTemp == 0) return(0);
  1666. pbTarget += cTemp;
  1667. }
  1668. cTotal += cTemp;
  1669. pbRunStart = pbCurPos;
  1670. cCurrentRunLength = iOffset;
  1671. }
  1672. bLastByte = bCurChar;
  1673. break;
  1674. case RLE_ENCODED:
  1675. if( ( bCurChar != bLastByte ) ||
  1676. ( cCurrentRunLength == 0xFE ) )
  1677. {
  1678. // Don't include last nibble if the width of the scan line is odd and this
  1679. // this is the last byte.
  1680. if( (pbCurPos == pbLineEnd ) && ( uiWidth & 0x01 ))
  1681. cCurrentRunLength -= 1;
  1682. cTemp = WriteEncoded4(bLastByte,
  1683. pbTarget, cCurrentRunLength, pbEndOfBuffer);
  1684. // if pbTarget is not NULL and cTemp is zero then
  1685. // the buffer is too small to hold encoded data
  1686. if(pbTarget != NULL) {
  1687. if (cTemp == 0) return(0);
  1688. pbTarget += cTemp;
  1689. }
  1690. cTotal += cTemp;
  1691. bLastByte = bCurChar;
  1692. pbRunStart = pbCurPos;
  1693. cCurrentRunLength = 0;
  1694. iMode = RLE_START ;
  1695. }
  1696. }
  1697. cCurrentRunLength += 2;
  1698. }
  1699. if( cCurrentRunLength > 3 )
  1700. {
  1701. // Don't include last nibble if the width of the scan line is odd and this
  1702. // this is the last byte.
  1703. if( uiWidth & 0x01 )
  1704. cCurrentRunLength -= 1;
  1705. // if pbTarget is not NULL and cTemp is zero then
  1706. // the buffer is too small to hold encoded data
  1707. if(iMode == RLE_ABSOLUTE)
  1708. cTemp = WriteAbsolute4(pbRunStart, pbTarget,
  1709. cCurrentRunLength - 2, pbEndOfBuffer);
  1710. else {
  1711. cTemp = WriteEncoded4(bLastByte, pbTarget,
  1712. cCurrentRunLength - 2, pbEndOfBuffer);
  1713. }
  1714. if (pbTarget != NULL) {
  1715. if (cTemp == 0) return(0);
  1716. pbTarget += cTemp;
  1717. }
  1718. cTotal += cTemp;
  1719. }
  1720. if( pbTarget <= pbEndOfBuffer )
  1721. cTotal += 2;
  1722. if( pbTarget != NULL )
  1723. {
  1724. *((WORD *) pbTarget) = 0;
  1725. pbTarget += 2;
  1726. }
  1727. }
  1728. // Write "End of bitmap" at the end so we're win31 compatible.
  1729. if( pbTarget == NULL )
  1730. return(cTotal + 2);
  1731. if( pbTarget + 2 > pbEndOfBuffer )
  1732. return(0);
  1733. *pbTarget++ = 0;
  1734. *pbTarget++ = 1;
  1735. return(cTotal + 2);
  1736. }