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.

818 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. htbmp1.c
  5. Abstract:
  6. This module contains functions used to output halftoned 1BPP bitmaps
  7. to the target device. Rotation is also handled here.
  8. Author:
  9. 21-Dec-1993 Tue 21:35:56 created
  10. [Environment:]
  11. GDI Device Driver - Plotter.
  12. [Notes:]
  13. Revision History:
  14. 10-Feb-1994 Thu 16:52:55 updated
  15. Remove pDrvHTInfo->PalXlate[] reference, all monochrome bitmap will
  16. be sent as index 0/1 color pal set before hand (in OutputHTBitmap)
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #define DBG_PLOTFILENAME DbgHTBmp1
  21. #define DBG_OUTPUT1BPP 0x00000001
  22. #define DBG_OUTPUT1BPP_ROT 0x00000002
  23. #define DBG_JOBCANCEL 0x00000004
  24. #define DBG_SHOWSCAN 0x80000000
  25. DEFINE_DBGVAR(0);
  26. #define HTBIF_MONO_BA (HTBIF_FLIP_MONOBITS | HTBIF_BA_PAD_1)
  27. //
  28. // Very useful macro for outputing scan line in a text representation to
  29. // the debug output stream.
  30. //
  31. #define SHOW_SCAN \
  32. { \
  33. if (DBG_PLOTFILENAME & DBG_SHOWSCAN) { \
  34. \
  35. LPBYTE pbCur; \
  36. UINT cx; \
  37. UINT x; \
  38. UINT Size; \
  39. BYTE bData; \
  40. BYTE Mask; \
  41. BYTE Buf[128]; \
  42. \
  43. pbCur = pbScanSrc; \
  44. Mask = 0; \
  45. \
  46. if ((cx = RTLScans.cxBytes << 3) >= sizeof(Buf)) { \
  47. \
  48. cx = sizeof(Buf) - 1; \
  49. } \
  50. \
  51. for (Size = x = 0; x < cx; x++) { \
  52. \
  53. if (!(Mask >>= 1)) { \
  54. \
  55. Mask = 0x80; \
  56. bData = *pbCur++; \
  57. } \
  58. \
  59. Buf[Size++] = (BYTE)((bData & Mask) ? 178 : 176); \
  60. } \
  61. \
  62. Buf[Size] = '\0'; \
  63. DBGP((Buf)); \
  64. } \
  65. }
  66. //
  67. // To Use OUT_ONE_1BPP_SCAN, the following variables must be set ahead of time
  68. //
  69. // HTBmpInfo - The whole structure with bitmap info set
  70. // cxDestBytes - Total size of destination scan line buffer per plane
  71. //
  72. // This macro will directly return a FALSE if a CANCEL JOB is detected in
  73. // the PDEV
  74. //
  75. // This function will only allowe the pbScanSrc passed = HTBmpInfo.pScanBuf
  76. //
  77. // 21-Mar-1994 Mon 17:00:21 updated
  78. // If we shift to to the left then we will only load last source if
  79. // we have a valid last source line.
  80. //
  81. #define OUT_ONE_1BPP_SCAN \
  82. { \
  83. LPBYTE pbTempS; \
  84. \
  85. if (LShift) { \
  86. \
  87. BYTE b0; \
  88. INT SL; \
  89. INT SR; \
  90. \
  91. pbTempS = HTBmpInfo.pScanBuf; \
  92. Loop = RTLScans.cxBytes; \
  93. \
  94. if ((SL = LShift) > 0) { \
  95. \
  96. b0 = *pbScanSrc++; \
  97. SR = 8 - SL; \
  98. \
  99. while (Loop--) { \
  100. \
  101. *pbTempS = (b0 << SL); \
  102. \
  103. if ((Loop) || (FullSrc)) { \
  104. \
  105. *pbTempS++ |= ((b0 = *pbScanSrc++) >> SR); \
  106. } \
  107. } \
  108. \
  109. } else { \
  110. \
  111. SR = -SL; \
  112. SL = 8 - SR; \
  113. b0 = 0; \
  114. \
  115. while (Loop--) { \
  116. \
  117. *pbTempS = (b0 << SL); \
  118. *pbTempS++ |= ((b0 = *pbScanSrc++) >> SR); \
  119. } \
  120. } \
  121. \
  122. pbScanSrc = HTBmpInfo.pScanBuf; \
  123. } \
  124. \
  125. if (HTBmpInfo.Flags & HTBIF_FLIP_MONOBITS) { \
  126. \
  127. pbTempS = (LPBYTE)pbScanSrc; \
  128. Loop = RTLScans.cxBytes; \
  129. \
  130. while (Loop--) { \
  131. \
  132. *pbTempS++ ^= 0xFF; \
  133. } \
  134. } \
  135. \
  136. if (HTBmpInfo.Flags & HTBIF_BA_PAD_1) { \
  137. \
  138. *(pbScanSrc ) |= MaskBA[0]; \
  139. *(pbScanSrc + MaskIdx) |= MaskBA[1]; \
  140. \
  141. } else { \
  142. \
  143. *(pbScanSrc ) &= MaskBA[0]; \
  144. *(pbScanSrc + MaskIdx) &= MaskBA[1]; \
  145. } \
  146. \
  147. OutputRTLScans(HTBmpInfo.pPDev, \
  148. pbScanSrc, \
  149. NULL, \
  150. NULL, \
  151. &RTLScans); \
  152. }
  153. BOOL
  154. FillRect1bppBmp(
  155. PHTBMPINFO pHTBmpInfo,
  156. BYTE FillByte,
  157. BOOL Pad1,
  158. BOOL Rotate
  159. )
  160. /*++
  161. Routine Description:
  162. This function fills a 1BPP bitmap with the passed mode.
  163. Arguments:
  164. pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this
  165. fuction to output the bitmap
  166. FillByte - Byte to be filled
  167. Pad1 - TRUE if need to pad 1 bit else 0 bit
  168. Rotate - TRUE if bitmap should be rotated
  169. Return Value:
  170. TRUE if sucessful otherwise a FALSE is returned
  171. Author:
  172. 06-Apr-1994 Wed 14:34:28 created
  173. For Fill the area 0,1 or inversion, so we will get away of some device
  174. 600 byte alignment problem
  175. Revision History:
  176. --*/
  177. {
  178. LPBYTE pbScanSrc;
  179. HTBMPINFO HTBmpInfo;
  180. RTLSCANS RTLScans;
  181. DWORD FullSrc;
  182. DWORD Loop;
  183. INT LShift;
  184. UINT MaskIdx;
  185. BYTE MaskBA[2];
  186. HTBmpInfo = *pHTBmpInfo;
  187. LShift = 0;
  188. //
  189. // Mode <0: Invert Bits (Pad 0 : XOR)
  190. // =0: Fill All ZERO (Pad 1 : AND)
  191. // >0: Fill All Ones (Pad 0 : OR)
  192. //
  193. if (Rotate) {
  194. HTBmpInfo.szlBmp.cx = pHTBmpInfo->szlBmp.cy;
  195. HTBmpInfo.szlBmp.cy = pHTBmpInfo->szlBmp.cx;
  196. FullSrc = (DWORD)(HTBmpInfo.rclBmp.top & 0x07);
  197. } else {
  198. FullSrc = (DWORD)(HTBmpInfo.rclBmp.left & 0x07);
  199. }
  200. HTBmpInfo.Flags = (BYTE)((Pad1) ? HTBIF_BA_PAD_1 : 0);
  201. //
  202. // Some devices require that the scanlines produced be byte aligned,
  203. // not allowing us to simply position to the correct coordinate, and
  204. // output the scan line. Instead we must determine the nearest byte
  205. // aligned starting coordinate, and shift the resulting scan line
  206. // accordingly. Finally we must output the shifted scan line, in such
  207. // a way as to not affect the padding area (if possible).
  208. //
  209. if (NEED_BYTEALIGN(HTBmpInfo.pPDev)) {
  210. //
  211. // Now we must shift either left or right, depending on the rclBmp.left
  212. // location.
  213. //
  214. HTBmpInfo.szlBmp.cx += FullSrc;
  215. //
  216. // Determine the correct mask byte to use, so we only affect bits
  217. // in the original position (not ones we are forced to shift
  218. // to in order to overcome device positioning limitations.
  219. //
  220. MaskIdx = (UINT)FullSrc;
  221. MaskBA[0] = (BYTE)((MaskIdx) ? ((0xFF >> MaskIdx) ^ 0xFF) : 0);
  222. if (MaskIdx = (INT)(HTBmpInfo.szlBmp.cx & 0x07)) {
  223. //
  224. // Increase cx so that it covers the last full byte, this way the
  225. // compression will not try to clear it
  226. //
  227. MaskBA[1] = (BYTE)(0xFF >> MaskIdx);
  228. HTBmpInfo.szlBmp.cx += (8 - MaskIdx);
  229. } else {
  230. MaskBA[1] = 0;
  231. }
  232. if (HTBmpInfo.Flags & HTBIF_BA_PAD_1) {
  233. PLOTDBG(DBG_OUTPUT1BPP,
  234. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=1: OR %02lx:%02lx",
  235. MaskBA[0], MaskBA[1]));
  236. } else {
  237. MaskBA[0] ^= 0xFF;
  238. MaskBA[1] ^= 0xFF;
  239. PLOTDBG(DBG_OUTPUT1BPP,
  240. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=0: AND %02lx:%02lx",
  241. MaskBA[0], MaskBA[1]));
  242. }
  243. } else {
  244. HTBmpInfo.Flags &= ~(HTBIF_MONO_BA);
  245. MaskBA[0] =
  246. MaskBA[1] = 0xFF;
  247. }
  248. //
  249. // If we are shifting to the left then we might have SRC BYTES <= DST BYTES
  250. // so we need to make sure we do not read the extra byte.
  251. // This guarantees we will never OVERREAD the source.
  252. //
  253. EnterRTLScans(HTBmpInfo.pPDev,
  254. &RTLScans,
  255. HTBmpInfo.szlBmp.cx,
  256. HTBmpInfo.szlBmp.cy,
  257. TRUE);
  258. FullSrc = 0;
  259. MaskIdx = RTLScans.cxBytes - 1;
  260. #if DBG
  261. if (DBG_PLOTFILENAME & DBG_SHOWSCAN) {
  262. DBGP(("\n\n"));
  263. }
  264. #endif
  265. //
  266. // Stay in a loop processing the source till we are done.
  267. //
  268. while (RTLScans.Flags & RTLSF_MORE_SCAN) {
  269. FillMemory(pbScanSrc = HTBmpInfo.pScanBuf,
  270. RTLScans.cxBytes,
  271. FillByte);
  272. OUT_ONE_1BPP_SCAN;
  273. #if DBG
  274. SHOW_SCAN;
  275. #endif
  276. }
  277. ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
  278. return(TRUE);
  279. }
  280. BOOL
  281. Output1bppHTBmp(
  282. PHTBMPINFO pHTBmpInfo
  283. )
  284. /*++
  285. Routine Description:
  286. This function outputs a 1 bpp halftoned bitmap
  287. Arguments:
  288. pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this
  289. fuction to output the bitmap
  290. Return Value:
  291. TRUE if sucessful otherwise a FALSE is returned
  292. Author:
  293. Created JB
  294. 21-Dec-1993 Tue 16:05:08 Updated
  295. Re-write to make it take HTBMPINFO
  296. 23-Dec-1993 Thu 22:47:45 updated
  297. We must check if the source bit 1 is BLACK, if not then we need to
  298. flip it
  299. 25-Jan-1994 Tue 17:32:36 updated
  300. Fixed dwFlipCount mis-computation from DW_ALIGN(cxDestBytes) to
  301. (DWORD)(DW_ALIGN(7cxDestBytes) >> 2);
  302. 22-Feb-1994 Tue 14:54:42 updated
  303. Using RTLScans data structure
  304. 16-Mar-1994 Wed 16:54:59 updated
  305. Updated so we do not copy to the temp. buffer anymore, the masking
  306. of last source byte problem in OutputRTLScans() will be smart enough
  307. to put the original byte back after the masking
  308. Revision History:
  309. --*/
  310. {
  311. LPBYTE pbScanSrc;
  312. HTBMPINFO HTBmpInfo;
  313. RTLSCANS RTLScans;
  314. DWORD FullSrc;
  315. DWORD Loop;
  316. INT LShift;
  317. UINT MaskIdx;
  318. BYTE MaskBA[2];
  319. HTBmpInfo = *pHTBmpInfo;
  320. HTBmpInfo.pScan0 += (HTBmpInfo.OffBmp.x >> 3);
  321. LShift = (INT)(HTBmpInfo.OffBmp.x & 0x07);
  322. Loop = (DWORD)((HTBmpInfo.szlBmp.cx + (LONG)LShift + 7) >> 3);
  323. if (NEED_BYTEALIGN(HTBmpInfo.pPDev)) {
  324. //
  325. // Based on some devices requiring byte aligned coordinates for
  326. // outputing graphics, we have to handle that situation now.
  327. // We do this by finding the closest byte aligned position,
  328. // then shifting, masking and padding to effect the corect pixels
  329. // on the target device.
  330. //
  331. FullSrc = (INT)(HTBmpInfo.rclBmp.left & 0x07);
  332. HTBmpInfo.szlBmp.cx += FullSrc;
  333. LShift -= FullSrc;
  334. //
  335. // Check and compute masking since we are handling the byte align
  336. // requirement of the target device.
  337. //
  338. MaskIdx = (UINT)FullSrc;
  339. MaskBA[0] = (BYTE)((MaskIdx) ? ((0xFF >> MaskIdx) ^ 0xFF) : 0);
  340. if (MaskIdx = (INT)(HTBmpInfo.szlBmp.cx & 0x07)) {
  341. //
  342. // Increase cx so that it covers the last byte, this way the
  343. // compression will not try to clear it
  344. //
  345. MaskBA[1] = (BYTE)(0xFF >> MaskIdx);
  346. HTBmpInfo.szlBmp.cx += (8 - MaskIdx);
  347. } else {
  348. MaskBA[1] = 0;
  349. }
  350. if (HTBmpInfo.Flags & HTBIF_BA_PAD_1) {
  351. PLOTDBG(DBG_OUTPUT1BPP,
  352. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=1: OR %02lx:%02lx",
  353. MaskBA[0], MaskBA[1]));
  354. } else {
  355. MaskBA[0] ^= 0xFF;
  356. MaskBA[1] ^= 0xFF;
  357. PLOTDBG(DBG_OUTPUT1BPP,
  358. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=0: AND %02lx:%02lx",
  359. MaskBA[0], MaskBA[1]));
  360. }
  361. } else {
  362. HTBmpInfo.Flags &= ~(HTBIF_MONO_BA);
  363. MaskBA[0] =
  364. MaskBA[1] = 0xFF;
  365. }
  366. PLOTDBG(DBG_OUTPUT1BPP, ("Output1bppHTBmp: LShift=%d", LShift));
  367. //
  368. // If we are shifting to the left then we might have SRC BYTES <= DST BYTES
  369. // so we need to make sure we do not read the extra byte.
  370. // This guarantees we will never OVERREAD the source.
  371. //
  372. EnterRTLScans(HTBmpInfo.pPDev,
  373. &RTLScans,
  374. HTBmpInfo.szlBmp.cx,
  375. HTBmpInfo.szlBmp.cy,
  376. TRUE);
  377. FullSrc = ((LShift > 0) && (Loop >= RTLScans.cxBytes)) ? 1 : 0;
  378. MaskIdx = RTLScans.cxBytes - 1;
  379. #if DBG
  380. if (DBG_PLOTFILENAME & DBG_SHOWSCAN) {
  381. DBGP(("\n\n"));
  382. }
  383. #endif
  384. while (RTLScans.Flags & RTLSF_MORE_SCAN) {
  385. if (LShift) {
  386. pbScanSrc = HTBmpInfo.pScan0;
  387. } else {
  388. //
  389. // Make copy if we do not shift it to temp buffer, so we always
  390. // output from temp buffer
  391. //
  392. CopyMemory(pbScanSrc = HTBmpInfo.pScanBuf,
  393. HTBmpInfo.pScan0,
  394. RTLScans.cxBytes);
  395. }
  396. HTBmpInfo.pScan0 += HTBmpInfo.Delta;
  397. OUT_ONE_1BPP_SCAN;
  398. #if DBG
  399. SHOW_SCAN;
  400. #endif
  401. }
  402. ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
  403. return(TRUE);
  404. }
  405. BOOL
  406. Output1bppRotateHTBmp(
  407. PHTBMPINFO pHTBmpInfo
  408. )
  409. /*++
  410. Routine Description:
  411. This function outputs a 1 bpp halftoned bitmap and rotates it to the left
  412. as illustrated
  413. cx Org ---- +X -->
  414. +-------+ | @------------+
  415. | | | | |
  416. | ***** | | | * |
  417. c| * | | * c|
  418. y| * | +Y | ******* y|
  419. | * | | * |
  420. | * | | | * |
  421. | * | V | |
  422. | * | +------------+
  423. +-------+
  424. Arguments:
  425. pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this
  426. function to output the bitmap
  427. Return Value:
  428. TRUE if sucessful otherwise a FALSE is returned
  429. Author:
  430. Created JB
  431. 21-Dec-1993 Tue 16:05:08 Updated
  432. Re-write to make it take HTBMPINFO
  433. 23-Dec-1993 Thu 22:47:45 updated
  434. We must check if the source bit 1 is BLACK, if not then we need to
  435. flip it, we will flip using DWORD mode and only do it at time we
  436. have transpos the buffer.
  437. 25-Jan-1994 Tue 17:32:36 updated
  438. Fixed dwFlipCount mis-computation from (TPInfo.cbDestScan << 1) to
  439. (TPInfo.cbDestScan >> 2)
  440. 22-Feb-1994 Tue 14:54:42 updated
  441. Using RTLScans data structure
  442. Revision History:
  443. --*/
  444. {
  445. LPBYTE pbCurScan;
  446. LPBYTE pbScanSrc;
  447. HTBMPINFO HTBmpInfo;
  448. RTLSCANS RTLScans;
  449. TPINFO TPInfo;
  450. DWORD FullSrc;
  451. DWORD EndX;
  452. DWORD Loop;
  453. INT LShift;
  454. UINT MaskIdx;
  455. BYTE MaskBA[2];
  456. //
  457. // EndX is the pixel we will start reading from in the X direction. We must
  458. // setup the varialbe before we call OUT_1BMP_SETUP, also set LShift to 0
  459. // because we will never left shift in this mode.
  460. //
  461. HTBmpInfo = *pHTBmpInfo;
  462. EndX = (DWORD)(HTBmpInfo.OffBmp.x + HTBmpInfo.szlBmp.cx - 1);
  463. HTBmpInfo.pScan0 += (EndX >> 3);
  464. LShift = 0;
  465. FullSrc =
  466. TPInfo.DestXStart = 0;
  467. TPInfo.cySrc = HTBmpInfo.szlBmp.cy;
  468. //
  469. // Since we are having to rotate anyway, in this model, we will correctly
  470. // identify the x coordinate to be bytealigned, and have the correct
  471. // LShift amount after the rotation (taking into account). This way, we
  472. // don't have to addionally shift.
  473. //
  474. if (NEED_BYTEALIGN(HTBmpInfo.pPDev)) {
  475. //
  476. // In order for us to start at the correct offset, the TPInfo.DestXStart
  477. // will be set to the correct location. When we rotate to the right,
  478. // the original rclBmp.top is the left offset for the RTL coordinate in
  479. // the target device.
  480. //
  481. TPInfo.DestXStart = (DWORD)(HTBmpInfo.rclBmp.top & 0x07);
  482. HTBmpInfo.szlBmp.cy += TPInfo.DestXStart;
  483. //
  484. // Create the correct mask for the byte aligned mode. This way,
  485. // we don't affect pixels that fall into the area we send data
  486. // to in order to take into account the byte aligned position change.
  487. //
  488. MaskIdx = (UINT)TPInfo.DestXStart;
  489. MaskBA[0] = (BYTE)((MaskIdx) ? ((0xFF >> MaskIdx) ^ 0xFF) : 0);
  490. if (MaskIdx = (INT)(HTBmpInfo.szlBmp.cy & 0x07)) {
  491. //
  492. // Increase cx so that it cover the last full byte, this way the
  493. // compression in effect will not try to clear it
  494. //
  495. MaskBA[1] = (BYTE)(0xFF >> MaskIdx);
  496. HTBmpInfo.szlBmp.cy += (8 - MaskIdx);
  497. } else {
  498. MaskBA[1] = 0;
  499. }
  500. if (HTBmpInfo.Flags & HTBIF_BA_PAD_1) {
  501. PLOTDBG(DBG_OUTPUT1BPP,
  502. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=1: OR %02lx:%02lx",
  503. MaskBA[0], MaskBA[1]));
  504. } else {
  505. MaskBA[0] ^= 0xFF;
  506. MaskBA[1] ^= 0xFF;
  507. PLOTDBG(DBG_OUTPUT1BPP,
  508. ("Output1bppHTBmp: BYTE ALIGN: MaskBA=0: AND %02lx:%02lx",
  509. MaskBA[0], MaskBA[1]));
  510. }
  511. } else {
  512. HTBmpInfo.Flags &= ~(HTBIF_MONO_BA);
  513. MaskBA[0] =
  514. MaskBA[1] = 0xFF;
  515. }
  516. EnterRTLScans(HTBmpInfo.pPDev,
  517. &RTLScans,
  518. HTBmpInfo.szlBmp.cy,
  519. HTBmpInfo.szlBmp.cx,
  520. TRUE);
  521. MaskIdx = RTLScans.cxBytes - 1;
  522. TPInfo.pPDev = HTBmpInfo.pPDev;
  523. TPInfo.pSrc = HTBmpInfo.pScan0;
  524. TPInfo.pDest = HTBmpInfo.pRotBuf;
  525. TPInfo.cbSrcScan = HTBmpInfo.Delta;
  526. TPInfo.cbDestScan = DW_ALIGN(RTLScans.cxBytes);
  527. PLOTASSERT(1, "The RotBuf size is too small (%ld)",
  528. (DWORD)(TPInfo.cbDestScan << 3) <= HTBmpInfo.cRotBuf,
  529. HTBmpInfo.cRotBuf);
  530. //
  531. // We will always do the first transpose and set the correct pbCurScan
  532. // first. We will make EndX the loop counter and increment it by one
  533. // first. We do this because we increment pbCurScan in the inner loop.
  534. // We use (6 - EndX++) based on the fact we are rotating 90 degrees to the
  535. // right. The first scan line is EndX == 7 , the second is at EndX == 6 and
  536. // so forth. We use 6, in order to go back one extra scan line so that the
  537. // inner loop will do pbCurScan += TPInfo.cbNextScan will cancel the effect
  538. // the first time around (since we incremented to accomodate). The EndX++
  539. // is needed for the same reason, since we do an EndX-- in the inner loop.
  540. //
  541. //
  542. // Win64 fix: Increase a pointer with a INT_PTR quantity.
  543. //
  544. EndX &= 0x07;
  545. pbCurScan = TPInfo.pDest + (INT_PTR)((6 - (INT_PTR)EndX++) * TPInfo.cbDestScan);
  546. TransPos1BPP(&TPInfo);
  547. #if DBG
  548. if (DBG_PLOTFILENAME & DBG_SHOWSCAN) {
  549. DBGP(("\n\n"));
  550. }
  551. #endif
  552. while (RTLScans.Flags & RTLSF_MORE_SCAN) {
  553. //
  554. // Do the transpose only if the source goes into the new byte position.
  555. // After the transpose (right 90 degrees) the TPInfo.pDest now points
  556. // to the first scan line and TPInfo.pDest + TPInfo.cbDestScan has the
  557. // 2nd scan line and so forth.
  558. //
  559. if (EndX--) {
  560. //
  561. // Still not finished the rotated buffer's scan line yet so
  562. // increment the pbScanSrc to the next scan line
  563. //
  564. pbCurScan += TPInfo.cbDestScan;
  565. } else {
  566. TransPos1BPP(&TPInfo);
  567. //
  568. // Point to the first scan line in the rotated direction by
  569. // computing correctly by the TRANSPOS function, even if we
  570. // rotated left.
  571. //
  572. EndX = 7;
  573. pbCurScan = TPInfo.pDest;
  574. }
  575. //
  576. // Output one 1bpp scan line and handle shift control
  577. //
  578. pbScanSrc = pbCurScan;
  579. OUT_ONE_1BPP_SCAN;
  580. #if DBG
  581. SHOW_SCAN;
  582. #endif
  583. }
  584. ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
  585. return(TRUE);
  586. }