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.

506 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. --*/
  4. // NTRAID#NTBUG9-553896-2002/03/19-yasuho-: mandatory changes
  5. #include "pdev.h"
  6. #include "lgcomp.h"
  7. //
  8. // File: LGCOMP.C
  9. //
  10. // Implementations of LG compression algprithms on the
  11. // LG "Raster 1" printers.
  12. //
  13. // printer command:
  14. // <9B>I{type}#{compressed data length}{compressed data}
  15. //
  16. // type can be:
  17. // <01> RLE
  18. // <02> MHE
  19. //
  20. // For MHE debugging.
  21. #define MHEDEBUG 0
  22. //#define MHEDEBUG 1
  23. //#define MHEDEBUGPATTERN 0x81
  24. #define MHEDEBUGPATTERN 0xff
  25. //
  26. // LG RLE compression. See comments for the details.
  27. //
  28. // You MUST call this function with @pOutBuf is NULL at first.
  29. // Then you can get the enough size of @pOutBuf by the return value.
  30. // Then you should make sure if the buffer size is enough.
  31. // Then call this function again with the actual pointer of @pOutBuf.
  32. INT
  33. LGCompRLE(
  34. PBYTE pOutBuf,
  35. PBYTE pSrcBuf, DWORD iSrcBuf,
  36. INT iMode)
  37. {
  38. PBYTE pMaxSrcBuf = pSrcBuf + iSrcBuf;
  39. INT iOutLen = 0, iRun;
  40. BYTE jTemp;
  41. PBYTE pSize;
  42. // Embedd print command if requested.
  43. if (iMode == 1) {
  44. // LG Raster 1
  45. if (pOutBuf) {
  46. *pOutBuf++ = (BYTE)'\x9B';
  47. *pOutBuf++ = (BYTE)'I';
  48. *pOutBuf++ = COMP_RLE;
  49. pSize = pOutBuf++;
  50. pOutBuf++;
  51. }
  52. iOutLen += 5;
  53. }
  54. while (pSrcBuf < pMaxSrcBuf) {
  55. // Get Run length.
  56. jTemp = *pSrcBuf;
  57. for (iRun = 1; pSrcBuf + iRun < pMaxSrcBuf; iRun++) {
  58. if (*(pSrcBuf + iRun) != jTemp)
  59. break;
  60. }
  61. // iRun == N means N consective bytes
  62. // of the same value exists.
  63. if (iRun > 1) {
  64. // Run > 1.
  65. while (iRun >= 0x82) {
  66. iRun -= 0x82;
  67. iOutLen += 2;
  68. if (pOutBuf) {
  69. // Mark <- 0x80,
  70. // length = 0x82.
  71. *pOutBuf++ = 0x80;
  72. *pOutBuf++ = jTemp;
  73. }
  74. pSrcBuf += 0x82;
  75. }
  76. // iRun less than 3 will be output as "copy" block.
  77. if (iRun >= 3) {
  78. iOutLen += 2;
  79. if (pOutBuf) {
  80. // Mark <- 0x81 to 0xff,
  81. // length = 0x81 to 3.
  82. *pOutBuf++ = (0x102 - iRun);
  83. *pOutBuf++ = jTemp;
  84. }
  85. }
  86. else if (iRun > 0) {
  87. iOutLen += (1 + iRun);
  88. if (pOutBuf) {
  89. *pOutBuf++ = (iRun - 1);
  90. memcpy(pOutBuf, pSrcBuf, iRun);
  91. pOutBuf += iRun;
  92. }
  93. }
  94. pSrcBuf += iRun;
  95. // Go to the next around.
  96. continue;
  97. }
  98. // Get "different" Run length. We already know
  99. // pSrcBuf[0] != pSrcBuf[1].
  100. for (iRun = 1; pSrcBuf + iRun < pMaxSrcBuf; iRun++) {
  101. if ((pSrcBuf + iRun + 1 < pMaxSrcBuf) &&
  102. (*(pSrcBuf + iRun) == *(pSrcBuf + iRun + 1))) {
  103. break;
  104. }
  105. }
  106. for (; iRun >= 0x80; iRun -= 0x80) {
  107. iOutLen += (1 + 0x80);
  108. if (pOutBuf) {
  109. // Mark <- 0x7f,
  110. // copy = 0x80.
  111. *pOutBuf++ = 0x7f;
  112. memcpy(pOutBuf, pSrcBuf, 0x80);
  113. pOutBuf += 0x80;
  114. }
  115. pSrcBuf += 0x80;
  116. }
  117. if (iRun > 0) {
  118. iOutLen += (1 + iRun);
  119. if (pOutBuf) {
  120. // Mark <- 0x7e to 0,
  121. // copy = 0x7f to 1.
  122. *pOutBuf++ = (iRun - 1);
  123. memcpy(pOutBuf, pSrcBuf, iRun);
  124. pOutBuf += iRun;
  125. }
  126. pSrcBuf += iRun;
  127. }
  128. }
  129. // Embed size information if requested.
  130. if (iMode == 1) {
  131. if (pOutBuf) {
  132. *pSize++ = (BYTE)((iOutLen - 5) >> 8);
  133. *pSize++ = (BYTE)(iOutLen - 5);
  134. }
  135. }
  136. return iOutLen;
  137. }
  138. //
  139. // MHE compression. See comments for the details.
  140. //
  141. typedef struct {
  142. DWORD cswd; /* compressing signed word */
  143. INT vbln; /* cswd's valid bits length, count from MSB */
  144. } ENCfm; /* ENC. form */
  145. ENCfm pWhiteTermTbl[64] = { /* Terminating Code Table (White)*/
  146. {0x35000000, 8},{0x1c000000, 6},{0x70000000, 4},{0x80000000, 4},
  147. {0xb0000000, 4},{0xc0000000, 4},{0xe0000000, 4},{0xf0000000, 4},
  148. {0x98000000, 5},{0xa0000000, 5},{0x38000000, 5},{0x40000000, 5},
  149. {0x20000000, 6},{0x0c000000, 6},{0xd0000000, 6},{0xd4000000, 6},
  150. {0xa8000000, 6},{0xac000000, 6},{0x4e000000, 7},{0x18000000, 7},
  151. {0x10000000, 7},{0x2e000000, 7},{0x06000000, 7},{0x08000000, 7},
  152. {0x50000000, 7},{0x56000000, 7},{0x26000000, 7},{0x48000000, 7},
  153. {0x30000000, 7},{0x02000000, 8},{0x03000000, 8},{0x1a000000, 8},
  154. {0x1b000000, 8},{0x12000000, 8},{0x13000000, 8},{0x14000000, 8},
  155. {0x15000000, 8},{0x16000000, 8},{0x17000000, 8},{0x28000000, 8},
  156. {0x29000000, 8},{0x2a000000, 8},{0x2b000000, 8},{0x2c000000, 8},
  157. {0x2d000000, 8},{0x04000000, 8},{0x05000000, 8},{0x0a000000, 8},
  158. {0x0b000000, 8},{0x52000000, 8},{0x53000000, 8},{0x54000000, 8},
  159. {0x55000000, 8},{0x24000000, 8},{0x25000000, 8},{0x58000000, 8},
  160. {0x59000000, 8},{0x5a000000, 8},{0x5b000000, 8},{0x4a000000, 8},
  161. {0x4b000000, 8},{0x32000000, 8},{0x33000000, 8},{0x34000000, 8}
  162. };
  163. ENCfm pBlackTermTbl[64] = { /* Terminating Code Table (Black) */
  164. {0x0dc00000, 10},{0x40000000, 3},{0xc0000000, 2},{0x80000000, 2},
  165. {0x60000000, 3},{0x30000000, 4},{0x20000000, 4},{0x18000000, 5},
  166. {0x14000000, 6},{0x10000000, 6},{0x08000000, 7},{0x0a000000, 7},
  167. {0x0e000000, 7},{0x04000000, 8},{0x07000000, 8},{0x0c000000, 9},
  168. {0x05c00000, 10},{0x06000000, 10},{0x02000000, 10},{0x0ce00000, 11},
  169. {0x0d000000, 11},{0x0d800000, 11},{0x06e00000, 11},{0x05000000, 11},
  170. {0x02e00000, 11},{0x03000000, 11},{0x0ca00000, 12},{0x0cb00000, 12},
  171. {0x0cc00000, 12},{0x0cd00000, 12},{0x06800000, 12},{0x06900000, 12},
  172. {0x06a00000, 12},{0x06b00000, 12},{0x0d200000, 12},{0x0d300000, 12},
  173. {0x0d400000, 12},{0x0d500000, 12},{0x0d600000, 12},{0x0d700000, 12},
  174. {0x06c00000, 12},{0x06d00000, 12},{0x0da00000, 12},{0x0db00000, 12},
  175. {0x05400000, 12},{0x05500000, 12},{0x05600000, 12},{0x05700000, 12},
  176. {0x06400000, 12},{0x06500000, 12},{0x05200000, 12},{0x05300000, 12},
  177. {0x02400000, 12},{0x03700000, 12},{0x03800000, 12},{0x02700000, 12},
  178. {0x02800000, 12},{0x05800000, 12},{0x05900000, 12},{0x02b00000, 12},
  179. {0x02c00000, 12},{0x05a00000, 12},{0x06600000, 12},{0x06700000, 12}
  180. };
  181. ENCfm pWhiteMkupTbl[41] = { /* Make-up Code Table (White) */
  182. {0x00100000, 12},{0xd8000000, 5},{0x90000000, 5},{0x5c000000, 6},
  183. {0x6e000000, 7},{0x36000000, 8},{0x37000000, 8},{0x64000000, 8},
  184. {0x65000000, 8},{0x68000000, 8},{0x67000000, 8},{0x66000000, 9},
  185. {0x66800000, 9},{0x69000000, 9},{0x69800000, 9},{0x6a000000, 9},
  186. {0x6a800000, 9},{0x6b000000, 9},{0x6b800000, 9},{0x6c000000, 9},
  187. {0x6c800000, 9},{0x6d000000, 9},{0x6d800000, 9},{0x4c000000, 9},
  188. {0x4c800000, 9},{0x4d000000, 9},{0x60000000, 6},{0x4d800000, 9},
  189. {0x01000000, 11},{0x01800000, 11},{0x01a00000, 11},{0x01200000, 12},
  190. {0x01300000, 12},{0x01400000, 12},{0x01500000, 12},{0x01600000, 12},
  191. {0x01700000, 12},{0x01c00000, 12},{0x01d00000, 12},{0x01e00000, 12},
  192. {0x01f00000, 12}
  193. };
  194. ENCfm pBlackMkupTbl[41] = { /* Make-up Code Table (Black) */
  195. {0x00100000, 12},{0x03c00000, 10},{0x0c800000, 12},{0x0c900000, 12},
  196. {0x05b00000, 12},{0x03300000, 12},{0x03400000, 12},{0x03500000, 12},
  197. {0x03600000, 13},{0x03680000, 13},{0x02500000, 13},{0x02580000, 13},
  198. {0x02600000, 13},{0x02680000, 13},{0x03900000, 13},{0x03980000, 13},
  199. {0x03a00000, 13},{0x03a80000, 13},{0x03b00000, 13},{0x03b80000, 13},
  200. {0x02900000, 13},{0x02980000, 13},{0x02a00000, 13},{0x02a80000, 13},
  201. {0x02d00000, 13},{0x02d80000, 13},{0x03200000, 13},{0x03280000, 13},
  202. {0x01000000, 11},{0x01800000, 11},{0x01a00000, 11},{0x01200000, 12},
  203. {0x01300000, 12},{0x01400000, 12},{0x01500000, 12},{0x01600000, 12},
  204. {0x01700000, 12},{0x01c00000, 12},{0x01d00000, 12},{0x01e00000, 12},
  205. {0x01f00000, 12}
  206. };
  207. #define DIV8(k) ((k) >> 3)
  208. #define MOD8(k) ((k) & 7)
  209. #define MUL8(k) ((k) << 3)
  210. #define DIV64(k) ((k) >> 6)
  211. #define MOD64(k) ((k) & 63)
  212. BOOL
  213. ScanBits(
  214. PBYTE pSrc,
  215. INT iOffset,
  216. DWORD dwMaxSrc,
  217. PDWORD pdwRunLength
  218. )
  219. {
  220. BOOL bBlack;
  221. BYTE jTemp, jMask;
  222. PBYTE pMaxSrc = pSrc + dwMaxSrc;
  223. INT k;
  224. DWORD dwRunLength = 0;
  225. // The 1st byte.
  226. jTemp = *pSrc++;
  227. #if MHEDEBUG
  228. jTemp = MHEDEBUGPATTERN;
  229. #endif // MHEDEBUG
  230. bBlack = ((jTemp & (0x80 >> iOffset)) != 0);
  231. if (!bBlack) {
  232. jTemp = ~jTemp;
  233. }
  234. // fill previous bits.
  235. jTemp |= ~(0xff >> iOffset);
  236. // ...interlim bytes.
  237. jMask = 0xff;
  238. for (; pSrc < pMaxSrc; pSrc++) {
  239. if (jTemp != jMask)
  240. break;
  241. dwRunLength += 8;
  242. jTemp = *pSrc;
  243. #if MHEDEBUG
  244. jTemp = MHEDEBUGPATTERN;
  245. #endif // MHEDEBUG
  246. if (!bBlack) {
  247. jTemp = ~jTemp;
  248. }
  249. }
  250. // The last byte.
  251. jMask = ~0x80;
  252. for (k = 0; k < 8; k++) {
  253. if ((jTemp | jMask) != 0xff)
  254. break;
  255. jMask >>= 1;
  256. }
  257. dwRunLength += k;
  258. // Return results to the caller.
  259. *pdwRunLength = (dwRunLength - iOffset);
  260. return bBlack;
  261. }
  262. VOID
  263. CopyBits(
  264. PBYTE pBuffer,
  265. INT iOffset,
  266. DWORD dwPattern,
  267. INT iPatternLength
  268. )
  269. {
  270. INT iNumberOfBytes, k;
  271. DWORD dwTemp;
  272. // Decide how many bytes we are to modify.
  273. iNumberOfBytes = DIV8(iOffset + iPatternLength + 7);
  274. // Make the pattern mask.
  275. dwPattern >>= iOffset;
  276. // Read in a byte if necessary.
  277. if (iOffset > 0) {
  278. dwTemp = (*pBuffer << 24);
  279. dwTemp &= ~((DWORD)~0 >> iOffset);
  280. }
  281. else {
  282. dwTemp = 0;
  283. }
  284. dwTemp |= dwPattern;
  285. // Write back.
  286. for (k = 3; k >= iNumberOfBytes; k--) {
  287. dwTemp >>= 8;
  288. }
  289. for (; k >= 0; k--) {
  290. *(pBuffer + k) = (BYTE)(dwTemp & 0xff);
  291. dwTemp >>= 8;
  292. }
  293. }
  294. // You MUST call this function with @pOutBuf is NULL at first.
  295. // Then you can get the enough size of @pOutBuf by the return value.
  296. // Then you should make sure if the buffer size is enough.
  297. // Then call this function again with the actual pointer of @pOutBuf.
  298. INT
  299. LGCompMHE(
  300. PBYTE pBuf,
  301. PBYTE pSrcBuf,
  302. DWORD dwMaxSrcBuf,
  303. INT iMode)
  304. {
  305. DWORD dwSrcOffset = 0;
  306. DWORD dwOffset = 0;
  307. ENCfm *pMkupTbl, *pTermTbl;
  308. DWORD dwRunLength;
  309. INT k;
  310. BOOL bBlack;
  311. DWORD dwMaxSrcOffset = MUL8(dwMaxSrcBuf);
  312. PBYTE pSize;
  313. DWORD dwLength;
  314. // Embed print command if requested.
  315. if (iMode == 1) {
  316. // LG Raster 1
  317. if (pBuf) {
  318. *(pBuf) = (BYTE)'\x9B';
  319. *(pBuf + 1) = (BYTE)'I';
  320. *(pBuf + 2) = COMP_MHE;
  321. pSize = (pBuf + 3);
  322. // 1 byte more.
  323. }
  324. dwOffset += 40;
  325. }
  326. while (dwSrcOffset < dwMaxSrcOffset) {
  327. bBlack = ScanBits(
  328. (pSrcBuf + DIV8(dwSrcOffset)),
  329. MOD8(dwSrcOffset),
  330. DIV8(dwMaxSrcOffset - dwSrcOffset + 7),
  331. &dwRunLength);
  332. VERBOSE(("LGCompMHE: %d, %d, %d (%d / %d)\n",
  333. dwOffset, dwRunLength, bBlack,
  334. dwSrcOffset, dwMaxSrcOffset));
  335. if (dwSrcOffset == 0 && bBlack) {
  336. // The 1st code in the data must be white encoding data.
  337. // So, we will insert "0 byte white run" record when the
  338. // data does not begin with white.
  339. dwLength = pWhiteTermTbl[0].vbln;
  340. if (pBuf) {
  341. CopyBits(
  342. (pBuf + DIV8(dwOffset)),
  343. MOD8(dwOffset),
  344. pWhiteTermTbl[0].cswd,
  345. dwLength);
  346. }
  347. dwOffset += dwLength;
  348. }
  349. if (dwRunLength >= 2624) {
  350. if (pBuf) {
  351. CopyBits(
  352. (pBuf + DIV8(dwOffset)),
  353. MOD8(dwOffset),
  354. 0x01f00000, 12);
  355. }
  356. dwOffset += 12;
  357. if (bBlack) {
  358. if (pBuf) {
  359. CopyBits(
  360. (pBuf + DIV8(dwOffset)),
  361. MOD8(dwOffset),
  362. 0x06700000, 12);
  363. }
  364. dwOffset += 12;
  365. if (pBuf) {
  366. CopyBits(
  367. (pBuf + DIV8(dwOffset)),
  368. MOD8(dwOffset),
  369. 0x35000000, 8);
  370. }
  371. dwOffset += 8;
  372. }
  373. else {
  374. if (pBuf) {
  375. CopyBits(
  376. (pBuf + DIV8(dwOffset)),
  377. MOD8(dwOffset),
  378. 0x34000000, 8);
  379. }
  380. dwOffset += 8;
  381. if (pBuf) {
  382. CopyBits(
  383. (pBuf + DIV8(dwOffset)),
  384. MOD8(dwOffset),
  385. 0x0dc00000, 10);
  386. }
  387. dwOffset += 10;
  388. }
  389. dwRunLength -= 2623;
  390. }
  391. if (bBlack) {
  392. pMkupTbl = pBlackMkupTbl;
  393. pTermTbl = pBlackTermTbl;
  394. }
  395. else {
  396. pMkupTbl = pWhiteMkupTbl;
  397. pTermTbl = pWhiteTermTbl;
  398. }
  399. if (dwRunLength >= 64) {
  400. dwLength = pMkupTbl[DIV64(dwRunLength)].vbln;
  401. if (pBuf) {
  402. CopyBits((pBuf + DIV8(dwOffset)),
  403. MOD8(dwOffset),
  404. pMkupTbl[DIV64(dwRunLength)].cswd,
  405. dwLength);
  406. }
  407. dwOffset += dwLength;
  408. }
  409. dwLength = pTermTbl[MOD64(dwRunLength)].vbln;
  410. if (pBuf) {
  411. CopyBits(
  412. (pBuf + DIV8(dwOffset)),
  413. MOD8(dwOffset),
  414. pTermTbl[MOD64(dwRunLength)].cswd,
  415. dwLength);
  416. }
  417. dwOffset += dwLength;
  418. // Next
  419. dwSrcOffset += dwRunLength;
  420. }
  421. // Convert unit into # of bytes.
  422. dwOffset = DIV8(dwOffset + 7);
  423. // Embed size information if requested.
  424. if (iMode == 1) {
  425. if (pBuf) {
  426. *pSize++ = (BYTE)((dwOffset - 5) >> 8);
  427. *pSize++ = (BYTE)(dwOffset - 5);
  428. }
  429. }
  430. return (INT)dwOffset;
  431. }