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.

1382 lines
76 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* abccom.c */
  4. /* */
  5. /* Copyright (c) Data Connection Limited 1998 */
  6. /* */
  7. /* */
  8. /* Bitmap compression routine and macros for 16 and 24bpp protocol */
  9. /* */
  10. /****************************************************************************/
  11. /****************************************************************************/
  12. /* We override the following macros to provide 16bpp/24bpp versions */
  13. /* */
  14. /* RUNSINGLE_NRM */
  15. /* RunDouble */
  16. /* RUNFGBG */
  17. /* SETFGPEL */
  18. /* ENCODE_SET_ORDER_MEGA */
  19. /* ENCODE_SET_ORDER_FGBG */
  20. /* ENCODEFGBG */
  21. /****************************************************************************/
  22. #ifdef BC_TRACE
  23. #define BCTRACE TRC_DBG
  24. #else
  25. #define BCTRACE(string)
  26. #endif
  27. /****************************************************************************/
  28. /* RUNSINGLE_NRM */
  29. /* */
  30. /* Determine the length of the current run */
  31. /* */
  32. /* RunSingle may only be called if the buffer has at least four */
  33. /* consecutive identical pixels from the start position */
  34. /* */
  35. /* length is the number of bytes we should search */
  36. /* result is the number of pixels found in the run */
  37. /****************************************************************************/
  38. #undef RUNSINGLE_NRM
  39. #define RUNSINGLE_NRM(buffer, length, result) \
  40. { \
  41. BYTE * buf = buffer + (BC_PIXEL_LEN * 4); \
  42. BYTE * endbuf = buffer + length - (BC_PIXEL_LEN * 4); \
  43. BC_PIXEL tmpPixel = BC_GET_PIXEL(buf - BC_PIXEL_LEN); \
  44. \
  45. result = 4; \
  46. while (((buf + (BC_PIXEL_LEN - 1)) < endbuf) && \
  47. (BC_GET_PIXEL(buf) == tmpPixel)) \
  48. { \
  49. result++; \
  50. buf += BC_PIXEL_LEN; \
  51. } \
  52. }
  53. /****************************************************************************/
  54. /* RunDouble */
  55. /* */
  56. /* Determine the length of the current run of paired bytes */
  57. /* */
  58. /* length is the number of bytes we should search */
  59. /* result is the number of pixels found in the run */
  60. /****************************************************************************/
  61. #undef RunDouble
  62. #define RunDouble(buffer, length, result) \
  63. { \
  64. int len = ((short)length); \
  65. BYTE * buf = buffer; \
  66. BC_PIXEL testPel1 = BC_GET_PIXEL(buf); \
  67. BC_PIXEL testPel2 = BC_GET_PIXEL(buf + BC_PIXEL_LEN); \
  68. result = 0; \
  69. while(len > BC_PIXEL_LEN) \
  70. { \
  71. if (BC_GET_PIXEL(buf) != testPel1) \
  72. { \
  73. break; \
  74. } \
  75. \
  76. BC_TO_NEXT_PIXEL(buf); \
  77. \
  78. if (BC_GET_PIXEL(buf) != testPel2) \
  79. { \
  80. break; \
  81. } \
  82. \
  83. BC_TO_NEXT_PIXEL(buf); \
  84. \
  85. result += 2; \
  86. len -= (BC_PIXEL_LEN * 2); \
  87. } \
  88. }
  89. /****************************************************************************/
  90. /* RUNFGBG */
  91. /* */
  92. /* Determine the length of the run of bytes that consist */
  93. /* only of black or a single FG color */
  94. /* We exit the loop when */
  95. /* - the next character is not a fg or bg color */
  96. /* - we hit a run of 24 of the FG or BG color when result is an exact */
  97. /* multiple of eight (we'll be creating a bitmask of result bits long, */
  98. /* hence this calculation) */
  99. /* */
  100. /* length is the number of bytes we should search */
  101. /* result is the number of pixels in the run */
  102. /* work is a BC_PIXEL for us to leave the fgPel in */
  103. /****************************************************************************/
  104. #undef RUNFGBG
  105. #define RUNFGBG(buffer, length, result, work) \
  106. { \
  107. BYTE * buf = buffer; \
  108. BYTE * endbuf = buffer + length; \
  109. int ii; \
  110. BOOLEAN exitWhile = FALSE; \
  111. BC_PIXEL tmpPixel; \
  112. result = 0; \
  113. work = BC_GET_PIXEL(buf); \
  114. while(!exitWhile) \
  115. { \
  116. BC_TO_NEXT_PIXEL(buf); \
  117. result++; \
  118. if (buf >= endbuf) \
  119. { \
  120. break; \
  121. } \
  122. \
  123. tmpPixel = BC_GET_PIXEL(buf); \
  124. if ((tmpPixel != work) && (tmpPixel != (BC_PIXEL)0)) \
  125. { \
  126. break; \
  127. } \
  128. \
  129. if ((result & 0x0007) == 0) \
  130. { \
  131. /***********************************************************/\
  132. /* Check for 24 consecutive identical pixels starting at */\
  133. /* buf */\
  134. /* */\
  135. /* We wouldn't have got this far unless */\
  136. /* - the value we're checking for is 'work' */\
  137. /* - the pixel at buf already contains 'work' */\
  138. /***********************************************************/\
  139. if ((buf + (24 * BC_PIXEL_LEN)) < endbuf) \
  140. { \
  141. for (ii = BC_PIXEL_LEN; \
  142. ii < (24 * BC_PIXEL_LEN); \
  143. ii += BC_PIXEL_LEN) \
  144. { \
  145. if (BC_GET_PIXEL(buf + ii) != work) \
  146. { \
  147. break; \
  148. } \
  149. \
  150. /***************************************************/\
  151. /* Found them! Break out of the while loop. */\
  152. /***************************************************/\
  153. exitWhile = TRUE; \
  154. } \
  155. } \
  156. } \
  157. } \
  158. }
  159. /****************************************************************************/
  160. /* SETFGPEL */
  161. /* */
  162. /* Set up a new value in fgPel. We don't calculate a shift as ENCODEFGBG */
  163. /* doesn't need it in the 16/24bpp implementation. */
  164. /* */
  165. /* This is the hi-res version of SETFGCHAR. As the macros are named */
  166. /* differently we will only need to undef this one on the second pass, */
  167. /* hence the #ifdef/#endif surrounding it */
  168. /****************************************************************************/
  169. #ifdef SETFGPEL
  170. #undef SETFGPEL
  171. #endif
  172. #define SETFGPEL(newPel, curPel) \
  173. curPel = (BC_PIXEL)newPel;
  174. /****************************************************************************/
  175. /* ENCODE_SET_ORDER_MEGA */
  176. /* */
  177. /* Encode a combined order and set fg color */
  178. /****************************************************************************/
  179. #undef ENCODE_SET_ORDER_MEGA
  180. #define ENCODE_SET_ORDER_MEGA(buffer, \
  181. order_code, \
  182. length, \
  183. mega_order_code, \
  184. DEF_LENGTH_ORDER, \
  185. DEF_LENGTH_LONG_ORDER) \
  186. if (length <= DEF_LENGTH_ORDER) \
  187. { \
  188. *buffer++ = (BYTE)((BYTE)order_code | (BYTE)length); \
  189. } \
  190. else \
  191. { \
  192. if (length <= DEF_LENGTH_LONG_ORDER) \
  193. { \
  194. *buffer++ = (BYTE)order_code; \
  195. *buffer++ = (BYTE)(length-DEF_LENGTH_ORDER-1); \
  196. } \
  197. else \
  198. { \
  199. *buffer++ = (BYTE)mega_order_code; \
  200. *(PUINT16_UA)(buffer) = (TSUINT16)length; \
  201. buffer += 2; \
  202. } \
  203. } \
  204. BC_SET_PIXEL(buffer, fgPel); \
  205. BC_TO_NEXT_PIXEL(buffer);
  206. /****************************************************************************/
  207. /* Encode a combined order and set fg color for a special FGBG image */
  208. /****************************************************************************/
  209. #undef ENCODE_SET_ORDER_MEGA_FGBG
  210. #define ENCODE_SET_ORDER_MEGA_FGBG(buffer, \
  211. order_code, \
  212. length, \
  213. mega_order_code, \
  214. DEF_LENGTH_ORDER, \
  215. DEF_LENGTH_LONG_ORDER) \
  216. if (((length & 0x0007) == 0) && \
  217. (length <= DEF_LENGTH_ORDER)) \
  218. { \
  219. *buffer++ = (BYTE)((BYTE)order_code | (BYTE)(length/8)); \
  220. } \
  221. else \
  222. { \
  223. if (length <= DEF_LENGTH_LONG_ORDER) \
  224. { \
  225. *buffer++ = (BYTE)order_code; \
  226. *buffer++ = (BYTE)(length-1); \
  227. } \
  228. else \
  229. { \
  230. *buffer++ = (BYTE)mega_order_code; \
  231. *(PUINT16_UA)(buffer) = (TSUINT16)length; \
  232. buffer += 2; \
  233. } \
  234. } \
  235. BC_SET_PIXEL(buffer, fgPel); \
  236. BC_TO_NEXT_PIXEL(buffer);
  237. /****************************************************************************/
  238. /* ENCODEFGBG */
  239. /* */
  240. /* Encode 8 pixels of FG and black into a one byte bitmap representation. */
  241. /* */
  242. /* We start reading at xorbuf[srcOffset] and don't try to be clever. */
  243. /* */
  244. /* We encode a row of pixels abcdefgh as a bitmask thus: */
  245. /* */
  246. /* bit 7 6 5 4 3 2 1 0 */
  247. /* pel h g f e d c b a */
  248. /* */
  249. /* where 7 is the most significant bit. */
  250. /* */
  251. /****************************************************************************/
  252. #undef ENCODEFGBG
  253. #define ENCODEFGBG(result) \
  254. { \
  255. BYTE * buf = xorbuf + srcOffset; \
  256. \
  257. result = 0; \
  258. \
  259. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  260. { \
  261. result |= 0x01; \
  262. } \
  263. BC_TO_NEXT_PIXEL(buf); \
  264. \
  265. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  266. { \
  267. result |= 0x02; \
  268. } \
  269. BC_TO_NEXT_PIXEL(buf); \
  270. \
  271. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  272. { \
  273. result |= 0x04; \
  274. } \
  275. BC_TO_NEXT_PIXEL(buf); \
  276. \
  277. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  278. { \
  279. result |= 0x08; \
  280. } \
  281. BC_TO_NEXT_PIXEL(buf); \
  282. \
  283. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  284. { \
  285. result |= 0x10; \
  286. } \
  287. BC_TO_NEXT_PIXEL(buf); \
  288. \
  289. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  290. { \
  291. result |= 0x20; \
  292. } \
  293. BC_TO_NEXT_PIXEL(buf); \
  294. \
  295. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  296. { \
  297. result |= 0x40; \
  298. } \
  299. BC_TO_NEXT_PIXEL(buf); \
  300. \
  301. if (BC_GET_PIXEL(buf) != (BC_PIXEL)0) \
  302. { \
  303. result |= 0x80; \
  304. } \
  305. BC_TO_NEXT_PIXEL(buf); \
  306. }
  307. /****************************************************************************/
  308. /* Compress function starts here */
  309. /****************************************************************************/
  310. /****************************************************************************/
  311. /* */
  312. /* BYTE * pSrc, */
  313. /* BYTE * pDst, */
  314. /* unsigned numBytes, total bytes in image */
  315. /* unsigned rowDelta, scanline length in bytes */
  316. /* unsigned dstBufferSize, */
  317. /* unsigned * xorbuf, */
  318. /* MATCH * match */
  319. /* */
  320. /****************************************************************************/
  321. {
  322. int i;
  323. unsigned srcOffset;
  324. unsigned matchindex;
  325. unsigned bestRunLength;
  326. unsigned nextRunLength;
  327. unsigned runLength;
  328. unsigned bestFGRunLength;
  329. unsigned checkFGBGLength;
  330. unsigned scanCount;
  331. BOOLEAN firstLine;
  332. unsigned saveNumBytes;
  333. BYTE bestRunType = 0;
  334. BYTE * destbuf = pDst;
  335. BC_PIXEL fgPel = BC_DEFAULT_FGPEL;
  336. BC_PIXEL fgPelWork = BC_DEFAULT_FGPEL;
  337. BOOLEAN inColorRun = FALSE;
  338. unsigned compressedLength = 0;
  339. BC_PIXEL pixelA;
  340. BC_PIXEL pixelB;
  341. DC_BEGIN_FN(BC_FN_NAME);
  342. /************************************************************************/
  343. /* Validate the line length */
  344. /************************************************************************/
  345. if ((numBytes < rowDelta) ||
  346. (rowDelta & 0x0003) || (numBytes & 0x0003) ||
  347. ((numBytes % BC_PIXEL_LEN) != 0))
  348. {
  349. TRC_ALT((TB, "Lines must be a multiple of 4 pels and there must be"
  350. " a whole number of pixels in the buffer"
  351. " (numBytes = %d, rowDelta = %d)", numBytes, rowDelta));
  352. DC_QUIT;
  353. }
  354. /************************************************************************/
  355. /* The first line of the XORBUF is identical to the first line of the */
  356. /* source buffer. Set it up. */
  357. /************************************************************************/
  358. memcpy(xorbuf, pSrc, rowDelta);
  359. /************************************************************************/
  360. /* The remaining lines in the XORBUF are the XOR against the previous */
  361. /* line. Calculate the rest of the XOR buffer. */
  362. /* */
  363. /* Note that this calculation is NOT pel-size dependent */
  364. /************************************************************************/
  365. {
  366. BYTE * srcbuf = pSrc + rowDelta;
  367. unsigned srclen = numBytes - rowDelta;
  368. UINT32 * dwdest = (UINT32 *)(xorbuf + rowDelta);
  369. while (srclen >= 8)
  370. {
  371. *dwdest++ = *((PUINT32)srcbuf) ^ *((PUINT32)(srcbuf - rowDelta));
  372. srcbuf += 4;
  373. *dwdest++ = *((PUINT32)srcbuf) ^ *((PUINT32)(srcbuf - rowDelta));
  374. srcbuf += 4;
  375. srclen -= 8;
  376. }
  377. if (srclen)
  378. {
  379. // Since we're 4-byte aligned we can only have a single DWORD
  380. // remaining.
  381. *dwdest = *((PUINT32)srcbuf) ^ *((PUINT32)(srcbuf - rowDelta));
  382. }
  383. }
  384. /************************************************************************/
  385. /* Loop processing the input */
  386. /* We perform the loop twice, the first time for the non-xor portion */
  387. /* of the buffer and the second for the XOR portion */
  388. /* */
  389. /* Note that we start the run at a match index of 2 to avoid having */
  390. /* to special case the startup condition in some of the match */
  391. /* merging code */
  392. /************************************************************************/
  393. srcOffset = 0;
  394. firstLine = TRUE;
  395. match[0].type = 0;
  396. match[1].type = 0;
  397. matchindex = 2;
  398. saveNumBytes = numBytes;
  399. /************************************************************************/
  400. /* On the first iteration numBytes stores the length of a scanline, on */
  401. /* the second the total number of bytes. */
  402. /* */
  403. /* srcOffset is the position we are currently examining. */
  404. /************************************************************************/
  405. numBytes = rowDelta;
  406. for (scanCount = 0; scanCount < 2; scanCount++)
  407. {
  408. while (srcOffset < numBytes)
  409. {
  410. /****************************************************************/
  411. /* Give up if we are nearing the end of the match array */
  412. /****************************************************************/
  413. if (matchindex >= 8192)
  414. {
  415. DC_QUIT;
  416. }
  417. /****************************************************************/
  418. /* Start a while loop to allow a more structured break when we */
  419. /* hit the first run type we want to encode (We can't afford */
  420. /* the overheads of a function call to provide the scope here.) */
  421. /****************************************************************/
  422. while (TRUE)
  423. {
  424. bestRunLength = 0;
  425. bestFGRunLength = 0;
  426. /************************************************************/
  427. /* If we are hitting the end of the buffer then just take */
  428. /* color characters now - take them one at a time so that */
  429. /* lossy encoding still works. We will only hit this */
  430. /* condition if we break out of a run just before the end */
  431. /* of the buffer, so this should not be too common a */
  432. /* situation, which is good given that we are encoding the */
  433. /* final 6 pixels uncompressed. */
  434. /************************************************************/
  435. if (srcOffset + (6 * BC_PIXEL_LEN) >= numBytes)
  436. {
  437. bestRunType = IMAGE_COLOR;
  438. bestRunLength = 1;
  439. break;
  440. }
  441. /************************************************************/
  442. /* First do the scans on the XOR buffer. Look for a */
  443. /* character run or a BG run. Note that if there is no row */
  444. /* delta then xorbuf actually points to the normal buffer. */
  445. /* We must do the test independent of how long the run */
  446. /* might be because even for a 1 pel BG run our later logic */
  447. /* requires that we detect it separately. This code is */
  448. /* absolute main path so fastpath as much as possible. In */
  449. /* particular detect short bg runs early and allow */
  450. /* RunSingle to presuppose at least 4 matching bytes */
  451. /************************************************************/
  452. if (BC_GET_PIXEL(xorbuf + srcOffset) == (BC_PIXEL)0)
  453. {
  454. /********************************************************/
  455. /* First pixel is 0, so look for BG runs */
  456. /********************************************************/
  457. if (((srcOffset + BC_PIXEL_LEN) >= numBytes) ||
  458. (BC_GET_PIXEL(xorbuf + srcOffset + BC_PIXEL_LEN) !=
  459. (BC_PIXEL)0))
  460. {
  461. /****************************************************/
  462. /* One pixel BG run */
  463. /****************************************************/
  464. bestRunType = RUN_BG;
  465. bestRunLength = 1;
  466. if (!inColorRun)
  467. {
  468. break;
  469. }
  470. }
  471. else if (((srcOffset + (BC_PIXEL_LEN * 2)) >= numBytes) ||
  472. (BC_GET_PIXEL(xorbuf +
  473. srcOffset +
  474. (BC_PIXEL_LEN * 2)) != (BC_PIXEL)0))
  475. {
  476. /****************************************************/
  477. /* Two pixel BG run */
  478. /****************************************************/
  479. bestRunType = RUN_BG;
  480. bestRunLength = 2;
  481. if (!inColorRun)
  482. {
  483. break;
  484. }
  485. }
  486. else if (((srcOffset + (BC_PIXEL_LEN * 3)) >= numBytes) ||
  487. (BC_GET_PIXEL(xorbuf +
  488. srcOffset +
  489. (BC_PIXEL_LEN * 3)) != (BC_PIXEL)0))
  490. {
  491. /****************************************************/
  492. /* Three pixel BG run */
  493. /****************************************************/
  494. bestRunType = RUN_BG;
  495. bestRunLength = 3;
  496. if (!inColorRun)
  497. {
  498. break;
  499. }
  500. }
  501. else
  502. {
  503. /****************************************************/
  504. /* Four or more pixel BG run */
  505. /****************************************************/
  506. RUNSINGLE_NRM(xorbuf + srcOffset,
  507. numBytes - srcOffset,
  508. bestFGRunLength);
  509. CHECK_BEST_RUN(RUN_BG,
  510. bestFGRunLength,
  511. bestRunLength,
  512. bestRunType);
  513. if (!inColorRun)
  514. {
  515. break;
  516. }
  517. }
  518. }
  519. else
  520. {
  521. /********************************************************/
  522. /* First pixel is non-zero, so look for FG runs */
  523. /********************************************************/
  524. /********************************************************/
  525. /* No point in starting if FG run less than 4 bytes so */
  526. /* check the first dword as quickly as possible Note */
  527. /* that we don't need to check for an end-buffer */
  528. /* condition here because our XOR buffer always has */
  529. /* some free space at the end and the RUNSINGLE_NRM */
  530. /* will break at the correct place */
  531. /********************************************************/
  532. BC_PIXEL tmpPixel = BC_GET_PIXEL(xorbuf + srcOffset);
  533. if ( (tmpPixel ==
  534. BC_GET_PIXEL(xorbuf + srcOffset + BC_PIXEL_LEN)) &&
  535. (tmpPixel ==
  536. BC_GET_PIXEL(xorbuf +
  537. srcOffset +
  538. (BC_PIXEL_LEN * 2))) &&
  539. (tmpPixel ==
  540. BC_GET_PIXEL(xorbuf +
  541. srcOffset +
  542. (BC_PIXEL_LEN * 3))) )
  543. {
  544. RUNSINGLE_NRM(xorbuf + srcOffset,
  545. numBytes - srcOffset,
  546. bestFGRunLength);
  547. /****************************************************/
  548. /* Don't permit a short FG run to prevent a FGBG */
  549. /* image from starting up. Only take if >= 5 */
  550. /****************************************************/
  551. if (bestFGRunLength > 5)
  552. {
  553. CHECK_BEST_RUN(RUN_FG,
  554. bestFGRunLength,
  555. bestRunLength,
  556. bestRunType);
  557. }
  558. }
  559. }
  560. /************************************************************/
  561. /* Look for color runs and dithered runs. */
  562. /* */
  563. /* Start by checking for the pattern */
  564. /* A B A B A B */
  565. /* */
  566. /* If we find it, then if A == B, it's a color run else */
  567. /* it's a dithered run. */
  568. /* */
  569. /* Look for sequences in the non XOR buffer In this case we */
  570. /* insist upon a run of at least 6 pels */
  571. /************************************************************/
  572. pixelA = BC_GET_PIXEL(pSrc + srcOffset);
  573. pixelB = BC_GET_PIXEL(pSrc + srcOffset + BC_PIXEL_LEN);
  574. if ( (pixelA ==
  575. BC_GET_PIXEL(pSrc + srcOffset + (BC_PIXEL_LEN * 2))) &&
  576. (pixelA ==
  577. BC_GET_PIXEL(pSrc + srcOffset + (BC_PIXEL_LEN * 4))) &&
  578. (pixelB ==
  579. BC_GET_PIXEL(pSrc + srcOffset + (BC_PIXEL_LEN * 3))) &&
  580. (pixelB ==
  581. BC_GET_PIXEL(pSrc + srcOffset + (BC_PIXEL_LEN * 5))) )
  582. {
  583. /********************************************************/
  584. /* Now do the scan on the normal buffer for a character */
  585. /* run Don't bother if first line because we will have */
  586. /* found it already in the XOR buffer, since we just */
  587. /* copy pSrc to xorbuf for the first line */
  588. /********************************************************/
  589. if (pixelA == pixelB)
  590. {
  591. if (!firstLine)
  592. {
  593. RUNSINGLE_NRM(pSrc + srcOffset,
  594. numBytes - srcOffset,
  595. nextRunLength);
  596. if (nextRunLength > 5)
  597. {
  598. CHECK_BEST_RUN(RUN_COLOR,
  599. nextRunLength,
  600. bestRunLength,
  601. bestRunType);
  602. }
  603. }
  604. }
  605. else
  606. {
  607. /****************************************************/
  608. /* Look for a dither on the nrm buffer. Dithers */
  609. /* are not very efficient for short runs so only */
  610. /* take if 8 or longer */
  611. /****************************************************/
  612. RunDouble(pSrc + srcOffset,
  613. numBytes - srcOffset,
  614. nextRunLength);
  615. if (nextRunLength > 9)
  616. {
  617. CHECK_BEST_RUN(RUN_DITHER,
  618. nextRunLength,
  619. bestRunLength,
  620. bestRunType);
  621. }
  622. }
  623. }
  624. /************************************************************/
  625. /* If nothing so far then look for a FGBG run (The 6 is */
  626. /* carefully tuned!) */
  627. /************************************************************/
  628. if (bestRunLength < 6)
  629. {
  630. /********************************************************/
  631. /* But first look for a single fg bit breaking up a BG */
  632. /* run. If so then encode a BG run. Careful of the */
  633. /* enforced BG run break across the first line */
  634. /* non-XOR/XOR boundary. */
  635. /* */
  636. /* So... */
  637. /* - check that the next four pixels are 0 (BG) */
  638. /* - check that the pel in the middle is the fgPel */
  639. /* - check that the previous run code is indeed RUN_BG */
  640. /* - check for the break over the boundary */
  641. /********************************************************/
  642. if ( (BC_GET_PIXEL(xorbuf +
  643. srcOffset +
  644. BC_PIXEL_LEN) == (BC_PIXEL)0) &&
  645. (BC_GET_PIXEL(xorbuf +
  646. srcOffset +
  647. (BC_PIXEL_LEN * 2)) == (BC_PIXEL)0) &&
  648. (BC_GET_PIXEL(xorbuf +
  649. srcOffset +
  650. (BC_PIXEL_LEN * 3)) == (BC_PIXEL)0) &&
  651. (BC_GET_PIXEL(xorbuf +
  652. srcOffset +
  653. (BC_PIXEL_LEN * 4)) == (BC_PIXEL)0) &&
  654. (BC_GET_PIXEL(xorbuf + srcOffset) == fgPel) &&
  655. (match[matchindex-1].type == RUN_BG) &&
  656. (srcOffset != (TSUINT16)rowDelta))
  657. {
  658. RUNSINGLE_NRM(xorbuf + srcOffset + BC_PIXEL_LEN,
  659. numBytes - srcOffset - BC_PIXEL_LEN,
  660. nextRunLength);
  661. nextRunLength++;
  662. CHECK_BEST_RUN(RUN_BG_PEL,
  663. nextRunLength,
  664. bestRunLength,
  665. bestRunType);
  666. }
  667. else
  668. {
  669. /****************************************************/
  670. /* If we have not found a run then look for a FG/BG */
  671. /* image. The disruptive effect of a short FGBG */
  672. /* run bandwidth and CPU is such that it is worth */
  673. /* preventing one unless we are certain of the */
  674. /* benefits. However, if the alternative is a */
  675. /* color run then allow a lower value. */
  676. /****************************************************/
  677. BCTRACE((TB, "FGBG: Checking %d bytes",
  678. numBytes - srcOffset));
  679. RUNFGBG(xorbuf + srcOffset,
  680. numBytes - srcOffset,
  681. nextRunLength,
  682. fgPelWork);
  683. checkFGBGLength = 48;
  684. if (fgPelWork == fgPel)
  685. {
  686. /************************************************/
  687. /* Cool: we don't need to issue a SET directive */
  688. /* as the fgPel is correct. */
  689. /************************************************/
  690. checkFGBGLength -= 16;
  691. }
  692. if ((nextRunLength & 0x0007) == 0)
  693. {
  694. /************************************************/
  695. /* Our bitmask will fit in an exact number of */
  696. /* bytes. This is a Good Thing. */
  697. /************************************************/
  698. checkFGBGLength -= 8;
  699. }
  700. BCTRACE((TB, "FGBG: resulting run %d, checklen %d ",
  701. nextRunLength, checkFGBGLength ));
  702. if (nextRunLength >= checkFGBGLength)
  703. {
  704. CHECK_BEST_RUN(IMAGE_FGBG,
  705. nextRunLength,
  706. bestRunLength,
  707. bestRunType);
  708. BCTRACE((TB, "FGBG: resulting best run %d, type %d",
  709. bestRunLength, bestRunType ));
  710. }
  711. }
  712. }
  713. /************************************************************/
  714. /* If nothing useful so far then allow a short run, if any. */
  715. /* Don't do this if we are accumulating a color run because */
  716. /* it will really screw up GDC compression if we allow lots */
  717. /* of little runs. Also require that it is a regular short */
  718. /* run, rather than one that disturbs the fgPel. */
  719. /************************************************************/
  720. if (!inColorRun)
  721. {
  722. if (bestRunLength < 6)
  723. {
  724. if ((bestFGRunLength > 4) &&
  725. (BC_GET_PIXEL(xorbuf + srcOffset) == fgPel))
  726. {
  727. /************************************************/
  728. /* We mustn't merge with the previous code */
  729. /* if we have just crossed the non-XOR/XOR */
  730. /* boundary. */
  731. /************************************************/
  732. if ((match[matchindex-1].type == RUN_FG) &&
  733. (srcOffset != rowDelta))
  734. {
  735. match[matchindex-1].length += bestFGRunLength;
  736. srcOffset += (bestFGRunLength * BC_PIXEL_LEN);
  737. continue;
  738. }
  739. else
  740. {
  741. bestRunLength = bestFGRunLength;
  742. bestRunType = RUN_FG;
  743. }
  744. }
  745. else
  746. {
  747. /************************************************/
  748. /* If we decided to take a run earlier then */
  749. /* allow it now. (May be a short BG run, for */
  750. /* example) If nothing so far then take color */
  751. /* image) */
  752. /************************************************/
  753. if (bestRunLength == 0)
  754. {
  755. bestRunType = IMAGE_COLOR;
  756. bestRunLength = 1;
  757. }
  758. }
  759. }
  760. }
  761. else if ((bestRunLength < 6) ||
  762. ((bestRunType != RUN_BG) && (bestRunLength < 8)))
  763. {
  764. bestRunType = IMAGE_COLOR;
  765. bestRunLength = 1;
  766. }
  767. break;
  768. }
  769. /****************************************************************/
  770. /* When we get here we have found the best run. Now check for */
  771. /* various amalamation conditions with the previous run type. */
  772. /* Note that we may already have done amalgamation of short */
  773. /* runs, but we had to do multiple samples for the longer runs */
  774. /* so we repeat the checks here */
  775. /****************************************************************/
  776. /****************************************************************/
  777. /* If we are encoding a color run then */
  778. /* - combine it with an existing run if possible */
  779. /****************************************************************/
  780. if (bestRunType == IMAGE_COLOR)
  781. {
  782. /************************************************************/
  783. /* Flag that we are within a color run */
  784. /************************************************************/
  785. inColorRun = TRUE;
  786. /************************************************************/
  787. /* Merge the color run immediately, if possible */
  788. /************************************************************/
  789. if (match[matchindex-1].type == IMAGE_COLOR)
  790. {
  791. match[matchindex-1].length += bestRunLength;
  792. srcOffset += (bestRunLength * BC_PIXEL_LEN);
  793. continue;
  794. }
  795. }
  796. else
  797. {
  798. /************************************************************/
  799. /* We are no longer encoding a COLOR_IMAGE of any kind */
  800. /************************************************************/
  801. inColorRun = FALSE;
  802. /************************************************************/
  803. /* Keep track of the fg Color. The macro that searches for */
  804. /* FGBG runs leaves the character in fgPelWork. */
  805. /************************************************************/
  806. if (bestRunType == RUN_FG)
  807. {
  808. fgPel = BC_GET_PIXEL(xorbuf + srcOffset);
  809. }
  810. else if (bestRunType == IMAGE_FGBG)
  811. {
  812. fgPel = fgPelWork;
  813. }
  814. }
  815. /****************************************************************/
  816. /* If we can amalgamate the entry then do so without creating a */
  817. /* new array entry insertion. Our search for FGBG runs is */
  818. /* dependent upon that type of run being amalgamated because we */
  819. /* break every 64 characters so that our mode switch detection */
  820. /* works OK. */
  821. /* */
  822. /* Take care not to merge across the non-xor/xor boundary */
  823. /****************************************************************/
  824. if (srcOffset == (TSUINT16)rowDelta)
  825. {
  826. /************************************************************/
  827. /* Just bump the source offset */
  828. /************************************************************/
  829. srcOffset += (bestRunLength * BC_PIXEL_LEN);
  830. }
  831. else
  832. {
  833. /************************************************************/
  834. /* Bump srcOffset and try a merge */
  835. /************************************************************/
  836. srcOffset += (bestRunLength * BC_PIXEL_LEN);
  837. /************************************************************/
  838. /* The simpler merges are where the types are identical */
  839. /************************************************************/
  840. if (bestRunType == match[matchindex-1].type)
  841. {
  842. /********************************************************/
  843. /* COLOR IMAGES and BG images are trivial */
  844. /********************************************************/
  845. if (bestRunType == RUN_BG)
  846. {
  847. match[matchindex-1].length += bestRunLength;
  848. continue;
  849. }
  850. /********************************************************/
  851. /* FG runs and FGBG images merge if fgPels match */
  852. /********************************************************/
  853. if (((bestRunType == RUN_FG) ||
  854. (bestRunType == IMAGE_FGBG)) &&
  855. (fgPel == match[matchindex-1].fgPel))
  856. {
  857. match[matchindex-1].length += bestRunLength;
  858. BCTRACE((TB, "Merged %u with preceding, giving %u",
  859. match[matchindex-1].type,
  860. match[matchindex-1].length));
  861. continue;
  862. }
  863. }
  864. /************************************************************/
  865. /* BG RUNs merge with LOSSY odd lines It is important that */
  866. /* we do this merging because otherwise we will get */
  867. /* inadvertent pel insertion due to the broken BG runs. */
  868. /************************************************************/
  869. if ((bestRunType == RUN_BG) &&
  870. ((match[matchindex-1].type == RUN_BG) ||
  871. (match[matchindex-1].type == RUN_BG_PEL)))
  872. {
  873. match[matchindex-1].length += bestRunLength;
  874. continue;
  875. }
  876. /************************************************************/
  877. /* If it is a normal FGBG run which follows a short BG run */
  878. /* then it is better to merge them. */
  879. /************************************************************/
  880. if ((bestRunType == IMAGE_FGBG) &&
  881. (match[matchindex-1].type == RUN_BG) &&
  882. (match[matchindex-1].length < 8))
  883. {
  884. match[matchindex-1].type = IMAGE_FGBG;
  885. match[matchindex-1].length += bestRunLength;
  886. match[matchindex-1].fgPel = fgPel;
  887. BCTRACE((TB, "Merged FGBG with preceding BG run -> %u",
  888. match[matchindex-1].length));
  889. continue;
  890. }
  891. /************************************************************/
  892. /* If it is a BG run following a FGBG run then merge in the */
  893. /* pels to make the FGBG a multiple of 8 bits. The if the */
  894. /* remaining BG run is < 16 merge it in also otherwise just */
  895. /* write the shortened BG run */
  896. /************************************************************/
  897. if (((bestRunType == RUN_BG) ||
  898. (bestRunType == RUN_BG_PEL)) &&
  899. (match[matchindex-1].type == IMAGE_FGBG) &&
  900. (match[matchindex-1].length & 0x0007))
  901. {
  902. /********************************************************/
  903. /* mergelen is the number of pixels we want to merge. */
  904. /********************************************************/
  905. unsigned mergelen = 8 -
  906. (match[matchindex-1].length & 0x0007);
  907. if (mergelen > bestRunLength)
  908. {
  909. mergelen = bestRunLength;
  910. }
  911. match[matchindex-1].length += mergelen;
  912. bestRunLength -= mergelen;
  913. BCTRACE((TB, "Added %u pels to FGBG giving %u leaving %u",
  914. mergelen, match[matchindex-1].length,bestRunLength));
  915. if (bestRunLength < 9)
  916. {
  917. match[matchindex-1].length += bestRunLength;
  918. BCTRACE((TB, "Merged BG with preceding FGBG gives %u",
  919. match[matchindex-1].length));
  920. continue;
  921. }
  922. }
  923. /************************************************************/
  924. /* Finally, if it is a color run spanning any kind of */
  925. /* single pel entity then merge that last two entries. */
  926. /************************************************************/
  927. if ((bestRunType == IMAGE_COLOR) &&
  928. (match[matchindex-2].type == IMAGE_COLOR) &&
  929. (match[matchindex-1].length == 1))
  930. {
  931. match[matchindex-2].length += bestRunLength + 1;
  932. matchindex--;
  933. BCTRACE((TB, "Merged color with preceding color gives %u",
  934. match[matchindex-1].length));
  935. continue;
  936. }
  937. }
  938. /****************************************************************/
  939. /* Handle runs that will not amalgamate by adding a new array */
  940. /* entry */
  941. /****************************************************************/
  942. match[matchindex].type = bestRunType;
  943. match[matchindex].length = bestRunLength;
  944. match[matchindex].fgPel = fgPel;
  945. BCTRACE((TB, "Best run of type %u (index %u) has length %u",
  946. match[matchindex-1].type,
  947. matchindex-1,
  948. match[matchindex-1].length));
  949. BCTRACE((TB, "Trying run of type %u (index %u) length %u",
  950. match[matchindex].type,
  951. matchindex,
  952. match[matchindex].length));
  953. matchindex++;
  954. }
  955. /********************************************************************/
  956. /* If we have just done our scan of the first line then now do the */
  957. /* rest of the buffer. Reset our saved pel count. */
  958. /********************************************************************/
  959. numBytes = saveNumBytes;
  960. firstLine = FALSE;
  961. }
  962. /************************************************************************/
  963. /* END OF INITIAL TWO PASS SCAN OF THE INPUT */
  964. /************************************************************************/
  965. /************************************************************************/
  966. /* Now do the encoding */
  967. /************************************************************************/
  968. srcOffset = 0;
  969. firstLine = TRUE;
  970. fgPel = BC_DEFAULT_FGPEL;
  971. for (i = 2; i < (int)matchindex; i++)
  972. {
  973. /********************************************************************/
  974. /* First check for our approaching the end of the destination */
  975. /* buffer and get out if this is the case. We allow for the */
  976. /* largest general run order (a mega-mega set run = 3 bytes + pixel */
  977. /* length). Orders which may be larger are checked within the case */
  978. /* arm */
  979. /********************************************************************/
  980. if ((unsigned)(destbuf - pDst + 3 + BC_PIXEL_LEN) > dstBufferSize)
  981. {
  982. /****************************************************************/
  983. /* We are about to blow it so just get out */
  984. /****************************************************************/
  985. DC_QUIT;
  986. }
  987. /********************************************************************/
  988. /* While we are encoding the first line keep checking for the end */
  989. /* of line to switch encoding states */
  990. /********************************************************************/
  991. if (firstLine)
  992. {
  993. if (srcOffset >= rowDelta)
  994. {
  995. firstLine = FALSE;
  996. }
  997. }
  998. switch (match[i].type)
  999. {
  1000. /************************************************************/
  1001. /* BG_RUN, FG_RUN, COLOR, PACKED COLOR and FGBG are normal */
  1002. /* precision codes */
  1003. /************************************************************/
  1004. case RUN_BG:
  1005. case RUN_BG_PEL:
  1006. ENCODE_ORDER_MEGA(destbuf,
  1007. CODE_BG_RUN,
  1008. match[i].length,
  1009. CODE_MEGA_MEGA_BG_RUN,
  1010. MAX_LENGTH_ORDER,
  1011. MAX_LENGTH_LONG_ORDER);
  1012. BCTRACE((TB, "BG_RUN %u",match[i].length));
  1013. srcOffset += (match[i].length * BC_PIXEL_LEN);
  1014. break;
  1015. case RUN_FG:
  1016. /************************************************************/
  1017. /* If the fg char is not yet set then encode a set+run code */
  1018. /************************************************************/
  1019. if (fgPel != match[i].fgPel)
  1020. {
  1021. SETFGPEL(match[i].fgPel, fgPel);
  1022. /********************************************************/
  1023. /* Encode the order */
  1024. /********************************************************/
  1025. ENCODE_SET_ORDER_MEGA(destbuf,
  1026. CODE_SET_FG_FG_RUN,
  1027. match[i].length,
  1028. CODE_MEGA_MEGA_SET_FG_RUN,
  1029. MAX_LENGTH_ORDER_LITE,
  1030. MAX_LENGTH_LONG_ORDER_LITE);
  1031. BCTRACE((TB, "SET_FG_FG_RUN %u",match[i].length));
  1032. srcOffset += (match[i].length * BC_PIXEL_LEN);
  1033. }
  1034. else
  1035. {
  1036. ENCODE_ORDER_MEGA(destbuf,
  1037. CODE_FG_RUN,
  1038. match[i].length,
  1039. CODE_MEGA_MEGA_FG_RUN,
  1040. MAX_LENGTH_ORDER,
  1041. MAX_LENGTH_LONG_ORDER);
  1042. BCTRACE((TB, "FG_RUN %u",match[i].length));
  1043. srcOffset += (match[i].length * BC_PIXEL_LEN);
  1044. }
  1045. break;
  1046. case IMAGE_FGBG:
  1047. /************************************************************/
  1048. /* IMAGE_FGBG */
  1049. /************************************************************/
  1050. runLength = match[i].length;
  1051. /************************************************************/
  1052. /* First check for our approaching the end of the */
  1053. /* destination buffer and get out if this is the case. */
  1054. /* */
  1055. /* The IMAGE_FGBG consists of a set of byte-long bit masks */
  1056. /* designed to hold runLength bits. */
  1057. /************************************************************/
  1058. if ((destbuf - pDst + ((runLength+7)/8) + 3 + BC_PIXEL_LEN)
  1059. > dstBufferSize)
  1060. {
  1061. /********************************************************/
  1062. /* We are about to blow it so just get out */
  1063. /********************************************************/
  1064. DC_QUIT;
  1065. }
  1066. if (fgPel != match[i].fgPel)
  1067. {
  1068. /********************************************************/
  1069. /* We need to include a SET directive as fgPel has */
  1070. /* changed */
  1071. /********************************************************/
  1072. SETFGPEL(match[i].fgPel, fgPel);
  1073. ENCODE_SET_ORDER_MEGA_FGBG(destbuf,
  1074. CODE_SET_FG_FG_BG,
  1075. runLength,
  1076. CODE_MEGA_MEGA_SET_FGBG,
  1077. MAX_LENGTH_FGBG_ORDER_LITE,
  1078. MAX_LENGTH_LONG_FGBG_ORDER);
  1079. BCTRACE((TB, "SET_FG_FG_BG %u, fgPel %06lx",
  1080. match[i].length, fgPel));
  1081. /********************************************************/
  1082. /* For every eight pixels... */
  1083. /********************************************************/
  1084. while (runLength >= 8)
  1085. {
  1086. ENCODEFGBG(*destbuf);
  1087. BCTRACE((TB, "Encoded as %08lx", *destbuf));
  1088. destbuf++;
  1089. srcOffset += (8 * BC_PIXEL_LEN);
  1090. runLength -= 8;
  1091. }
  1092. if (runLength)
  1093. {
  1094. ENCODEFGBG(*destbuf);
  1095. /****************************************************/
  1096. /* Keep the final partial byte clean to help GDC */
  1097. /* packing */
  1098. /****************************************************/
  1099. *destbuf &= ((0x01 << runLength) - 1);
  1100. destbuf++;
  1101. srcOffset += (runLength * BC_PIXEL_LEN);
  1102. }
  1103. }
  1104. else
  1105. {
  1106. /********************************************************/
  1107. /* fgPel is already the correct value */
  1108. /********************************************************/
  1109. if (runLength == 8)
  1110. {
  1111. BYTE fgbgChar;
  1112. /****************************************************/
  1113. /* See if it is one of the high probability bytes */
  1114. /****************************************************/
  1115. ENCODEFGBG(fgbgChar);
  1116. /****************************************************/
  1117. /* Check for single byte encoding of FGBG images */
  1118. /****************************************************/
  1119. switch (fgbgChar)
  1120. {
  1121. case SPECIAL_FGBG_CODE_1:
  1122. *destbuf++ = CODE_SPECIAL_FGBG_1;
  1123. BCTRACE((TB, "SPECIAL FGBG_1"));
  1124. break;
  1125. case SPECIAL_FGBG_CODE_2:
  1126. *destbuf++ = CODE_SPECIAL_FGBG_2;
  1127. BCTRACE((TB, "SPECIAL FGBG_2"));
  1128. break;
  1129. default:
  1130. ENCODE_ORDER_MEGA_FGBG(destbuf,
  1131. CODE_FG_BG_IMAGE,
  1132. runLength,
  1133. CODE_MEGA_MEGA_FGBG,
  1134. MAX_LENGTH_FGBG_ORDER,
  1135. MAX_LENGTH_LONG_FGBG_ORDER);
  1136. *destbuf++ = fgbgChar;
  1137. break;
  1138. }
  1139. srcOffset += (8 * BC_PIXEL_LEN);
  1140. }
  1141. else
  1142. {
  1143. /****************************************************/
  1144. /* Encode as standard FGBG */
  1145. /****************************************************/
  1146. ENCODE_ORDER_MEGA_FGBG(destbuf,
  1147. CODE_FG_BG_IMAGE,
  1148. runLength,
  1149. CODE_MEGA_MEGA_FGBG,
  1150. MAX_LENGTH_FGBG_ORDER,
  1151. MAX_LENGTH_LONG_FGBG_ORDER);
  1152. BCTRACE((TB, "FG_BG %u",match[i].length));
  1153. while (runLength >= 8)
  1154. {
  1155. ENCODEFGBG(*destbuf);
  1156. destbuf++;
  1157. srcOffset += (8 * BC_PIXEL_LEN);
  1158. runLength -= 8;
  1159. }
  1160. if (runLength)
  1161. {
  1162. /************************************************/
  1163. /* Keep the final partial byte clean to help */
  1164. /* GDC packing */
  1165. /************************************************/
  1166. ENCODEFGBG(*destbuf);
  1167. *destbuf &= ((0x01 << runLength) - 1);
  1168. destbuf++;
  1169. srcOffset += (runLength * BC_PIXEL_LEN);
  1170. }
  1171. }
  1172. }
  1173. break;
  1174. case RUN_COLOR:
  1175. /************************************************************/
  1176. /* COLOR RUN */
  1177. /************************************************************/
  1178. ENCODE_ORDER_MEGA(destbuf,
  1179. CODE_COLOR_RUN,
  1180. match[i].length,
  1181. CODE_MEGA_MEGA_COLOR_RUN,
  1182. MAX_LENGTH_ORDER,
  1183. MAX_LENGTH_LONG_ORDER);
  1184. BCTRACE((TB, "COLOR_RUN %u",match[i].length));
  1185. BC_SET_PIXEL(destbuf, BC_GET_PIXEL(pSrc + srcOffset));
  1186. BC_TO_NEXT_PIXEL(destbuf);
  1187. srcOffset += (match[i].length * BC_PIXEL_LEN);
  1188. break;
  1189. case RUN_DITHER:
  1190. /************************************************************/
  1191. /* DITHERED RUN */
  1192. /************************************************************/
  1193. {
  1194. unsigned ditherlen = match[i].length/2;
  1195. ENCODE_ORDER_MEGA(destbuf,
  1196. CODE_DITHERED_RUN,
  1197. ditherlen,
  1198. CODE_MEGA_MEGA_DITHER,
  1199. MAX_LENGTH_ORDER_LITE,
  1200. MAX_LENGTH_LONG_ORDER_LITE);
  1201. BCTRACE((TB, "DITHERED_RUN %u",match[i].length));
  1202. /********************************************************/
  1203. /* First check for our approaching the end of the */
  1204. /* destination buffer and get out if this is the case. */
  1205. /********************************************************/
  1206. if ((unsigned)(destbuf - pDst + (2 * BC_PIXEL_LEN))
  1207. > dstBufferSize)
  1208. {
  1209. /****************************************************/
  1210. /* We are about to blow it so just get out */
  1211. /****************************************************/
  1212. DC_QUIT;
  1213. }
  1214. /********************************************************/
  1215. /* Put the two pixels to dither with into the output */
  1216. /* buffer */
  1217. /********************************************************/
  1218. BC_SET_PIXEL(destbuf, BC_GET_PIXEL(pSrc + srcOffset));
  1219. BC_TO_NEXT_PIXEL(destbuf);
  1220. BC_SET_PIXEL(destbuf,
  1221. BC_GET_PIXEL(pSrc + srcOffset + BC_PIXEL_LEN));
  1222. BC_TO_NEXT_PIXEL(destbuf);
  1223. srcOffset += (match[i].length * BC_PIXEL_LEN);
  1224. }
  1225. break;
  1226. case IMAGE_COLOR:
  1227. /************************************************************/
  1228. /* IMAGE_COLOR */
  1229. /************************************************************/
  1230. /************************************************************/
  1231. /* A length of 1 can possibly be encoded as a single */
  1232. /* "BLACK" or "WHITE" */
  1233. /************************************************************/
  1234. if (match[i].length == 1)
  1235. {
  1236. if (BC_GET_PIXEL(pSrc + srcOffset) == (BC_PIXEL)0)
  1237. {
  1238. *destbuf++ = CODE_BLACK;
  1239. srcOffset += BC_PIXEL_LEN;
  1240. BCTRACE((TB, "CODE_BLACK"));
  1241. break;
  1242. }
  1243. if (BC_GET_PIXEL(pSrc + srcOffset) == BC_DEFAULT_FGPEL)
  1244. {
  1245. *destbuf++ = CODE_WHITE;
  1246. srcOffset += BC_PIXEL_LEN;
  1247. BCTRACE((TB, "CODE_WHITE"));
  1248. break;
  1249. }
  1250. }
  1251. ENCODE_ORDER_MEGA(destbuf,
  1252. CODE_COLOR_IMAGE,
  1253. match[i].length,
  1254. CODE_MEGA_MEGA_CLR_IMG,
  1255. MAX_LENGTH_ORDER,
  1256. MAX_LENGTH_LONG_ORDER);
  1257. BCTRACE((TB, "COLOR_IMAGE %u",match[i].length));
  1258. /************************************************************/
  1259. /* First check for our approaching the end of the */
  1260. /* destination buffer and get out if this is the case. */
  1261. /************************************************************/
  1262. if ((destbuf - pDst + (match[i].length * BC_PIXEL_LEN))
  1263. > dstBufferSize)
  1264. {
  1265. /********************************************************/
  1266. /* We are about to blow it so just get out */
  1267. /********************************************************/
  1268. DC_QUIT;
  1269. }
  1270. /************************************************************/
  1271. /* Now just copy the data over */
  1272. /************************************************************/
  1273. memcpy(destbuf,
  1274. pSrc + srcOffset,
  1275. match[i].length * BC_PIXEL_LEN);
  1276. destbuf += match[i].length * BC_PIXEL_LEN;
  1277. srcOffset += match[i].length * BC_PIXEL_LEN;
  1278. break;
  1279. default:
  1280. {
  1281. TRC_ERR((TB, "Invalid run type %u",match[i].type));
  1282. }
  1283. }
  1284. }
  1285. /************************************************************************/
  1286. /* return the size of the compressed buffer */
  1287. /************************************************************************/
  1288. compressedLength = (unsigned)(destbuf - pDst);
  1289. DC_EXIT_POINT:
  1290. DC_END_FN();
  1291. return compressedLength;
  1292. }