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.

438 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. htbmp4.c
  5. Abstract:
  6. This module contains functions to output halftoned 4 bit per pel (4 BPP)
  7. bitmaps to the target device.
  8. Author:
  9. 21-Dec-1993 Tue 21:32:26 created
  10. [Environment:]
  11. GDI Device Driver - Plotter.
  12. [Notes:]
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #define DBG_PLOTFILENAME DbgHTBmp4
  18. #define DBG_OUTPUT4BPP 0x00000001
  19. #define DBG_OUTPUT4BPP_ROT 0x00000002
  20. #define DBG_JOBCANCEL 0x00000004
  21. DEFINE_DBGVAR(0);
  22. //
  23. // To Use OUT_ONE_4BPP_SCAN, the following variables must be set before hand:
  24. //
  25. // HTBmpInfo - The whole structure copied down
  26. // pbScanSrc - LPBYTE for getting the source scan line buffer
  27. // pbScanR0 - Red destination scan line buffer pointer
  28. // pbScanG0 - Green destination scan line buffer pointer
  29. // pbScanB0 - Blue destination scan line buffer pointer
  30. // RTLScans.cxBytes- Total size of destination scan line buffer per plane
  31. // pHTXB - Computed HTXB xlate table in pPDev
  32. //
  33. // This macro will always assume the pbScanSrc is DWORD aligned. This
  34. // makes the inner loop go faster since we only need to move the source once
  35. // for all raster planes.
  36. //
  37. // This macro will directly return a FALSE if a CANCEL JOB is detected during
  38. // procesing.
  39. //
  40. // This will output directly to RTL.
  41. //
  42. //
  43. #define OUT_ONE_4BPP_SCAN \
  44. { \
  45. LPBYTE pbScanR = pbScanR0; \
  46. LPBYTE pbScanG = pbScanG0; \
  47. LPBYTE pbScanB = pbScanB0; \
  48. DWORD LoopHTXB = RTLScans.cxBytes; \
  49. HTXB htXB; \
  50. \
  51. while (LoopHTXB--) { \
  52. \
  53. P4B_TO_3P_DW(htXB.dw, pHTXB, pbScanSrc); \
  54. \
  55. *pbScanR++ = HTXB_R(htXB); \
  56. *pbScanG++ = HTXB_G(htXB); \
  57. *pbScanB++ = HTXB_B(htXB); \
  58. } \
  59. \
  60. OutputRTLScans(HTBmpInfo.pPDev, \
  61. pbScanR0, \
  62. pbScanG0, \
  63. pbScanB0, \
  64. &RTLScans); \
  65. }
  66. BOOL
  67. Output4bppHTBmp(
  68. PHTBMPINFO pHTBmpInfo
  69. )
  70. /*++
  71. Routine Description:
  72. This function outputs a 4 bpp halftoned bitmap
  73. Arguments:
  74. pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this
  75. fuction to output the bitmap
  76. Return Value:
  77. TRUE if sucessful otherwise a FALSE is returned
  78. Author:
  79. Created
  80. 18-Jan-1994 Tue 16:05:08 Updated
  81. Changed ASSERT to look at pHTBmpInfo instead of HTBmpInfo
  82. 21-Dec-1993 Tue 16:05:08 Updated
  83. Re-write to make it take HTBMPINFO
  84. 16-Mar-1994 Wed 16:54:59 updated
  85. Updated so we do not copy to the temp. buffer anymore, the masking
  86. of last source byte problem in OutputRTLScans() will be smart enough
  87. to put the original byte back after the masking
  88. Revision History:
  89. --*/
  90. {
  91. LPBYTE pbScanSrc;
  92. PHTXB pHTXB;
  93. LPBYTE pbScanR0;
  94. LPBYTE pbScanG0;
  95. LPBYTE pbScanB0;
  96. HTBMPINFO HTBmpInfo;
  97. RTLSCANS RTLScans;
  98. DWORD LShiftCount;
  99. PLOTASSERT(1, "Output4bppHTBmp: No DWORD align buffer (pRotBuf)",
  100. pHTBmpInfo->pRotBuf, 0);
  101. HTBmpInfo = *pHTBmpInfo;
  102. EnterRTLScans(HTBmpInfo.pPDev,
  103. &RTLScans,
  104. HTBmpInfo.szlBmp.cx,
  105. HTBmpInfo.szlBmp.cy,
  106. FALSE);
  107. pHTXB = ((PDRVHTINFO)HTBmpInfo.pPDev->pvDrvHTData)->pHTXB;
  108. HTBmpInfo.pScan0 += (HTBmpInfo.OffBmp.x >> 1);
  109. pbScanR0 = HTBmpInfo.pScanBuf;
  110. pbScanG0 = pbScanR0 + RTLScans.cxBytes;
  111. pbScanB0 = pbScanG0 + RTLScans.cxBytes;
  112. PLOTASSERT(1, "The ScanBuf size is too small (%ld)",
  113. (RTLScans.cxBytes * 3) <= HTBmpInfo.cScanBuf, HTBmpInfo.cScanBuf);
  114. PLOTASSERT(1, "The RotBuf size is too small (%ld)",
  115. (DWORD)((HTBmpInfo.szlBmp.cx + 1) >> 1) <= HTBmpInfo.cRotBuf,
  116. HTBmpInfo.cRotBuf);
  117. if (HTBmpInfo.OffBmp.x & 0x01) {
  118. //
  119. // We must shift one nibble to the left now
  120. //
  121. LShiftCount = (DWORD)HTBmpInfo.szlBmp.cx;
  122. PLOTDBG(DBG_OUTPUT4BPP,
  123. ("Output4bppHTBmp: Must SHIFT LEFT 1 NIBBLE To align"));
  124. } else {
  125. LShiftCount = 0;
  126. }
  127. //
  128. // We must be very careful not to read past the end of the source buffer.
  129. // This could happen if we pbScanSrc is not DWORD aligned, since this
  130. // will cause the last conversion macro to load all 4 bytes. To resolve
  131. // this we can either copy the source buffer to a DWORD aligned temporary
  132. // location, or handle the last incomplete DWORD differently. This only
  133. // occurs when the bitmap is NOT rotated, and (pbScanSrc & 0x03).
  134. //
  135. while (RTLScans.Flags & RTLSF_MORE_SCAN) {
  136. //
  137. // This is the final source for this scan line
  138. //
  139. if (LShiftCount) {
  140. LPBYTE pbTmp;
  141. DWORD PairCount;
  142. BYTE b0;
  143. BYTE b1;
  144. pbTmp = HTBmpInfo.pScan0;
  145. b1 = *pbTmp;
  146. pbScanSrc = HTBmpInfo.pRotBuf;
  147. PairCount = LShiftCount;
  148. while (PairCount > 1) {
  149. b0 = b1;
  150. b1 = *pbTmp++;
  151. *pbScanSrc++ = (BYTE)((b0 << 4) | (b1 >> 4));
  152. PairCount -= 2;
  153. }
  154. if (PairCount) {
  155. //
  156. // If we have the last nibble to do then make it 0xF0 nibble,
  157. // so we only look at the bits of interest.
  158. //
  159. *pbScanSrc = (BYTE)(b1 << 4);
  160. }
  161. //
  162. // Reset this pointer back to the final shifted source buffer
  163. //
  164. pbScanSrc = HTBmpInfo.pRotBuf;
  165. } else {
  166. pbScanSrc = HTBmpInfo.pScan0;
  167. }
  168. //
  169. // Output one 4 bpp scan line (3 planes)
  170. //
  171. OUT_ONE_4BPP_SCAN;
  172. //
  173. // advance source bitmap buffer pointer to next scan line
  174. //
  175. HTBmpInfo.pScan0 += HTBmpInfo.Delta;
  176. }
  177. //
  178. // The caller will send END GRAPHIC command if we return TRUE, thus
  179. // completing the RTL graphic command.
  180. //
  181. ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
  182. return(TRUE);
  183. }
  184. BOOL
  185. Output4bppRotateHTBmp(
  186. PHTBMPINFO pHTBmpInfo
  187. )
  188. /*++
  189. Routine Description:
  190. This function outputs a 4 bpp halftoned bitmap and rotates it to the left
  191. as illustrated
  192. cx Org ---- +X -->
  193. +-------+ | @------------+
  194. | | | | |
  195. | ***** | | | * |
  196. c| * | | * c|
  197. y| * | +Y | ******* y|
  198. | * | | * |
  199. | * | | | * |
  200. | * | V | |
  201. | * | +------------+
  202. +-------+
  203. Arguments:
  204. pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this
  205. fuction to output the bitmap
  206. Return Value:
  207. TRUE if sucessful otherwise a FALSE is returned
  208. Author:
  209. 21-Dec-1993 Tue 16:05:08 Updated
  210. Re-write to make it take an HTBMPINFO structure.
  211. Created
  212. Revision History:
  213. --*/
  214. {
  215. LPBYTE pbScanSrc;
  216. LPBYTE pb2ndScan;
  217. PHTXB pHTXB;
  218. LPBYTE pbScanR0;
  219. LPBYTE pbScanG0;
  220. LPBYTE pbScanB0;
  221. HTBMPINFO HTBmpInfo;
  222. RTLSCANS RTLScans;
  223. TPINFO TPInfo;
  224. DWORD EndX;
  225. //
  226. // The EndX is the pixel we will start reading in the X direction, we must
  227. // setup the variable correctly before we call OUT_4BPP_SETUP.
  228. //
  229. HTBmpInfo = *pHTBmpInfo;
  230. EnterRTLScans(HTBmpInfo.pPDev,
  231. &RTLScans,
  232. HTBmpInfo.szlBmp.cy,
  233. HTBmpInfo.szlBmp.cx,
  234. FALSE);
  235. pHTXB = ((PDRVHTINFO)HTBmpInfo.pPDev->pvDrvHTData)->pHTXB;
  236. EndX = (DWORD)(HTBmpInfo.OffBmp.x + HTBmpInfo.szlBmp.cx - 1);
  237. HTBmpInfo.pScan0 += (EndX >> 1);
  238. pbScanR0 = HTBmpInfo.pScanBuf;
  239. pbScanG0 = pbScanR0 + RTLScans.cxBytes;
  240. pbScanB0 = pbScanG0 + RTLScans.cxBytes;
  241. PLOTASSERT(1, "The ScanBuf size is too small (%ld)",
  242. (RTLScans.cxBytes * 3) <= HTBmpInfo.cScanBuf, HTBmpInfo.cScanBuf);
  243. //
  244. // after the transpose of the source bitmap into two scanlines the rotated
  245. // buffer will always start from the high nibble, we will never have
  246. // an odd src X position.
  247. // We assume rotation is always to the right 90 degree
  248. //
  249. TPInfo.pPDev = HTBmpInfo.pPDev;
  250. TPInfo.pSrc = HTBmpInfo.pScan0;
  251. TPInfo.pDest = HTBmpInfo.pRotBuf;
  252. TPInfo.cbSrcScan = HTBmpInfo.Delta;
  253. TPInfo.cbDestScan = (LONG)((HTBmpInfo.szlBmp.cy + 1) >> 1);
  254. TPInfo.cbDestScan = (LONG)DW_ALIGN(TPInfo.cbDestScan);
  255. TPInfo.cySrc = HTBmpInfo.szlBmp.cy;
  256. TPInfo.DestXStart = 0;
  257. PLOTASSERT(1, "The RotBuf size is too small (%ld)",
  258. (DWORD)(TPInfo.cbDestScan << 1) <= HTBmpInfo.cRotBuf,
  259. HTBmpInfo.cRotBuf);
  260. //
  261. // Compute the 2nd scan pointer once, rather than every time in the
  262. // loop.
  263. //
  264. pb2ndScan = TPInfo.pDest + TPInfo.cbDestScan;
  265. //
  266. // If we are in an even position do the first transpose once, outside the
  267. // loop, so we don't have to check this state for ever pass through the
  268. // loop. If we do the transpose, TPInfo.pSrc, will be decremented by one,
  269. // and pointing to the correct position.
  270. //
  271. if (!(EndX &= 0x01)) {
  272. TransPos4BPP(&TPInfo);
  273. }
  274. while (RTLScans.Flags & RTLSF_MORE_SCAN) {
  275. //
  276. // Do the transpose, only if the source goes into the new byte position.
  277. // After the transpose (right 90 degrees) the TPInfo.pDest will point
  278. // to the first scan line and TPInfo.pDest + TPInfo.cbDestScan will be
  279. // the second scan line.
  280. //
  281. if (EndX ^= 0x01) {
  282. pbScanSrc = pb2ndScan;
  283. } else {
  284. TransPos4BPP(&TPInfo);
  285. //
  286. // Point to the first scan line in the rotated direction. This
  287. // will be computed correctly by the TRANSPOSE function, even
  288. // if we rotated left.
  289. //
  290. pbScanSrc = TPInfo.pDest;
  291. }
  292. //
  293. // Output one 4bpp scan line (in 3 plane format)
  294. //
  295. OUT_ONE_4BPP_SCAN;
  296. }
  297. //
  298. // The caller will send the END GRAPHIC command if we return TRUE, thus
  299. // completing the RTL graphic command.
  300. //
  301. ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
  302. return(TRUE);
  303. }