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.

1481 lines
40 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. raster.c
  5. Abstract:
  6. Functions to scan a bitmap for white regions.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 12/15/96 -alvins-
  11. Created (mostly stolen from Lindsayh)
  12. --*/
  13. #include "raster.h"
  14. #include "rmrender.h"
  15. /*
  16. * The following union allows machine independent conversion from
  17. * DWORDS to BYTES.
  18. */
  19. typedef union
  20. {
  21. DWORD dw; /* Data as a DWORD */
  22. BYTE b[ DWBYTES ]; /* Data as bytes */
  23. } UBDW;
  24. /*
  25. * Following array is used to test the leftover bits from scanning. The
  26. * rational is that only some of the bits in the last word are part
  27. * of the bitmap, so only they must be tested. It is initialised at
  28. * DLL initialisation time.
  29. * NOTE: There are 33 entries in this array: This is intentional!
  30. * Depending upon circumstances, either the 0 or 32nd entry will be
  31. * used for a dword that is all ones.
  32. *
  33. **** THIS ARRAY IS NOW DYNAMICALLY ALLOCATED IN bSkipInit(). ************
  34. */
  35. #define TABLE_SIZE ((DWBITS + 1) * sizeof( DWORD ))
  36. /*
  37. * RGB_WHITE is the bit pattern found in a white entry for an RGB format
  38. * 4 bits per pel bitmap. This is the only special case required when
  39. * scanning the source bitmap for white. In all other cases (monochrome
  40. * and CMY), white is represented by a 0 nibble.
  41. */
  42. #define RGB_WHITE 0x77777777
  43. /*
  44. * Also want to know about the 8 bit per pel white index.
  45. */
  46. #define BPP8_WHITE 0xffffffff
  47. /*
  48. * Define BPP values for clarify
  49. */
  50. #define BPP1 1
  51. #define BPP4 4
  52. #define BPP8 8
  53. #define BPP24 24
  54. //*****************************************************
  55. BOOL
  56. bSkipInit(
  57. PDEV *pPDev
  58. )
  59. /*++
  60. Routine Description:
  61. The job here is to initialise the table that is used to mask off
  62. the unused bits in a scanline. All scanlines are DWORD aligned,
  63. and we take advantage of that fact when looking for white space.
  64. However, the last DWORD may not be completely used, so we have
  65. a masking table used to check only those bits of interest.
  66. The table depends upon byte ordering within words, and this is
  67. machine dependent, so we generate the table. This provides
  68. machine independence, since the machine that is going to use
  69. the table generates it! This function is called when the DLL
  70. is loaded, so we are not called often.
  71. The union 'u' provides the mapping between BYTES and DWORDS,
  72. and so is the key to this function. The union is initialised
  73. using the BYTE array, but it stored in memory using the DWORD.
  74. Arguments:
  75. pPDev Pointer to PDEV structure
  76. Return Value:
  77. TRUE for success and FALSE for failure
  78. --*/
  79. {
  80. register int iIndex;
  81. register DWORD *pdw;
  82. UBDW u; /* The magic union */
  83. PRASTERPDEV pRPDev = pPDev->pRasterPDEV;
  84. u.dw = 0;
  85. if( !(pRPDev->pdwBitMask = (DWORD *)MemAlloc( TABLE_SIZE )) )
  86. return FALSE;
  87. pdw = pRPDev->pdwBitMask;
  88. for( iIndex = 0; iIndex < DWBITS; ++iIndex )
  89. {
  90. *pdw++ = u.dw;
  91. /* The left most bit in the scan line is the MSB of the byte */
  92. u.b[ iIndex / BBITS ] |= 1 << (BBITS - 1 - (iIndex & (BBITS - 1)));
  93. }
  94. /* ALL bits are involved in the last one */
  95. *pdw = (DWORD)~0;
  96. return TRUE;
  97. }
  98. //*******************************************************
  99. BOOL
  100. bIsBandWhite(
  101. DWORD *pdwBitsIn,
  102. RENDER *pRData,
  103. int iWhiteIndex
  104. )
  105. /*++
  106. Routine Description:
  107. Scan a band of the bitmap, and return TRUE if it is
  108. all WHITE, else FALSE. This is used to decide whether a
  109. band should be sent to the printer. This routine also
  110. masks off the unused bits at the end of each scan line.
  111. Arguments:
  112. pdwBitsIn Pointer to area to scan for white
  113. pRData Pointer to RENDER structure
  114. iWhiteIndex White value to compare against, only
  115. included here for functional compatibility
  116. Return Value:
  117. TRUE if entire bitmap is white, else FALSE
  118. --*/
  119. {
  120. register DWORD *pdwBits;
  121. register DWORD *pdwLim;
  122. int iLines; /* Number of scan lines to check */
  123. DWORD dwMask; /* Mask to zap the trailing bits */
  124. BOOL bRet;
  125. //Always TRUE for Txtonly as we don't want to send any graphics.
  126. if(pRData->PrinterType == PT_TTY)
  127. return TRUE;
  128. /*
  129. * As a speed optimisation, scan the bits in DWORD size clumps.
  130. * This substantially reduces the number of iterations and memory
  131. * references required. There will usually be some trailing
  132. * bits; these are handled individually - if we get that far.
  133. */
  134. /* Mask to clear last few bits of scanline, if not full DWORD */
  135. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  136. if( dwMask == 0 )
  137. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  138. iLines = pRData->iTransHigh;
  139. bRet = TRUE;
  140. while( --iLines >= 0 )
  141. {
  142. /* Calculate the starting address for this scan */
  143. pdwBits = pdwBitsIn;
  144. /* pDWLim is the DWORD past the data of interest - not used */
  145. pdwLim = pdwBits + pRData->cDWLine;
  146. /* Clear out undefined bits at end of line */
  147. *(pdwLim - 1) &= dwMask;
  148. /* Need to continue masking regardless */
  149. if (bRet)
  150. {
  151. while (*pdwBits == 0 && ++pdwBits < pdwLim);
  152. if( pdwBits < pdwLim )
  153. bRet = FALSE;
  154. }
  155. /* Onto the next scan line */
  156. pdwBitsIn += pRData->cDWLine * pRData->iInterlace;
  157. }
  158. return bRet;
  159. }
  160. //**********************************************************
  161. BOOL
  162. bIsLineWhite(
  163. register DWORD *pdwBits,
  164. register RENDER *pRData,
  165. int iWhiteIndex
  166. )
  167. /*++
  168. Routine Description:
  169. Scan a horizontal row of the bitmap, and return TRUE if it is
  170. all WHITE, else FALSE. This is used to decide whether a
  171. scan line should be sent to the printer. This routine also
  172. masks off the unused bits at the end of each scan line.
  173. Arguments:
  174. pdwBits Pointer to area to scan for white
  175. pRData Pointer to RENDER structure
  176. iWhiteIndex White value to compare against, only
  177. included here for functional compatibility
  178. Return Value:
  179. TRUE if entire bitmap is white, else FALSE
  180. --*/
  181. {
  182. register DWORD *pdwLim;
  183. DWORD dwMask; /* Mask to zap the trailing bits */
  184. //Always TRUE for Txtonly as we don't want to send any graphics.
  185. if(pRData->PrinterType == PT_TTY)
  186. return TRUE;
  187. /*
  188. * As a speed optimisation, scan the bits in DWORD size clumps.
  189. * This substantially reduces the number of iterations and memory
  190. * references required. There will ususally be some trailing
  191. * bits; these are handled individually - if we get that far.
  192. */
  193. /* Mask to clear last few bits of scanline, if not full DWORD */
  194. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  195. if( dwMask == 0 )
  196. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  197. /* pDWLim is the DWORD past the data of interest - not used */
  198. pdwLim = pdwBits + pRData->cDWLine;
  199. /* Clear out undefined bits at end of line */
  200. *(pdwLim - 1) &= dwMask;
  201. while (*pdwBits == 0 && ++pdwBits < pdwLim);
  202. if( pdwBits < pdwLim )
  203. return FALSE;
  204. return TRUE;
  205. }
  206. //**********************************************************
  207. BOOL
  208. bIsNegatedLineWhite(
  209. DWORD *pdwBits,
  210. RENDER *pRData,
  211. int iWhiteIndex
  212. )
  213. /*++
  214. Routine Description:
  215. Scan a horizontal row of the bitmap, and return TRUE if it is
  216. all WHITE, else FALSE. This is used to decide whether a
  217. scan line should be sent to the printer. This routine also
  218. masks off the unused bits at the end of each scan line.
  219. Arguments:
  220. pdwBits Pointer to area to scan for white
  221. pRData Pointer to RENDER structure
  222. iWhiteIndex White value to compare against, only
  223. included here for functional compatibility
  224. Return Value:
  225. TRUE if entire bitmap is white, else FALSE
  226. --*/
  227. {
  228. DWORD *pdwLim;
  229. int iCnt;
  230. DWORD dwMask; /* Mask to zap the trailing bits */
  231. //Always TRUE for Txtonly as we don't want to send any graphics.
  232. if(pRData->PrinterType == PT_TTY)
  233. return TRUE;
  234. /*
  235. * As a speed optimisation, scan the bits in DWORD size clumps.
  236. * This substantially reduces the number of iterations and memory
  237. * references required. There will ususally be some trailing
  238. * bits; these are handled individually - if we get that far.
  239. */
  240. /* Mask to clear last few bits of scanline, if not full DWORD */
  241. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  242. if( dwMask == 0 )
  243. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  244. /* Clear out undefined bits at end of line */
  245. pdwBits[pRData->cDWLine-1] |= ~dwMask;
  246. //
  247. // For performance we test 4 dwords at a time for white
  248. //
  249. pdwLim = pdwBits;
  250. iCnt = pRData->cDWLine >> 2;
  251. while (--iCnt >= 0)
  252. {
  253. if ((pdwBits[0] & pdwBits[1] & pdwBits[2] & pdwBits[3]) != -1)
  254. goto InvertTheBits;
  255. pdwBits += 4;
  256. }
  257. //
  258. // test any left over dwords for white
  259. //
  260. iCnt = pRData->cDWLine & 3;
  261. while (--iCnt >= 0)
  262. {
  263. if (*pdwBits != -1)
  264. goto InvertTheBits;
  265. pdwBits++;
  266. }
  267. return TRUE;
  268. //
  269. // if this isn't a white line we need to invert the bits
  270. //
  271. InvertTheBits:
  272. dwMask = (DWORD)(pdwBits - pdwLim);
  273. ZeroMemory (pdwLim,dwMask*DWBYTES);
  274. vInvertBits(pdwBits,pRData->cDWLine-dwMask);
  275. return FALSE;
  276. }
  277. //***************************************************
  278. BOOL
  279. bIsRGBBandWhite (
  280. DWORD *pdwBitsIn,
  281. RENDER *pRData,
  282. int iWhiteIndex
  283. )
  284. /*++
  285. Routine Description:
  286. Scan a band of the bitmap, and return TRUE if it is
  287. all WHITE, else FALSE. This is used to decide whether a
  288. band should be sent to the printer.
  289. Arguments:
  290. pdwBitsIn Pointer to area to scan for white
  291. pRData Pointer to RENDER structure
  292. iWhiteIndex White value to compare against
  293. included here for functional compatibility
  294. Return Value:
  295. TRUE if entire bitmap is white, else FALSE
  296. --*/
  297. {
  298. register DWORD *pdwBits;
  299. register DWORD *pdwLim;
  300. int iLines; /* Number of scan lines to check */
  301. DWORD dwMask; /* Mask to zap the trailing bits */
  302. /*
  303. * As a speed optimisation, scan the bits in DWORD size clumps.
  304. * This substantially reduces the number of iterations and memory
  305. * references required. There will ususally be some trailing
  306. * bits; these are handled individually - if we get that far.
  307. */
  308. /* Mask to clear last few bits of scanline, if not full DWORD */
  309. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  310. if( dwMask == 0 )
  311. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  312. iLines = pRData->iTransHigh;
  313. while( --iLines >= 0 )
  314. {
  315. /* Calculate the starting address for this scan */
  316. pdwBits = pdwBitsIn;
  317. /* pDWLim is the DWORD past the data of interest - not used */
  318. pdwLim = pdwBits + pRData->cDWLine;
  319. /* Clear out undefined bits at end of line */
  320. *(pdwLim - 1) &= dwMask;
  321. *(pdwLim - 1) |= ~dwMask & RGB_WHITE;
  322. /*
  323. * NOTE: This test is more complex than needed because the
  324. * engine ignores palette entries when doing BLTs. The WHITENESS
  325. * rop sets all bits to 1. Hence, we choose to ignore the
  326. * MSB in the comparison: this means we detect white space
  327. * with an illegal palette entry. This makes GDI people happy,
  328. * but not me.
  329. */
  330. do {
  331. if ((*pdwBits & RGB_WHITE) != RGB_WHITE)
  332. return FALSE;
  333. } while (++pdwBits < pdwLim);
  334. /* Onto the next scan line */
  335. pdwBitsIn += pRData->cDWLine * pRData->iInterlace;
  336. }
  337. return TRUE;
  338. }
  339. //*******************************************************
  340. BOOL
  341. bIsRGBLineWhite (
  342. register DWORD *pdwBits,
  343. RENDER *pRData,
  344. int iWhiteIndex
  345. )
  346. /*++
  347. Routine Description:
  348. Scan a single row of the bitmap, and return TRUE if it is
  349. all WHITE, else FALSE. This is used to decide whether a
  350. band should be sent to the printer.
  351. Arguments:
  352. pdwBitsIn Pointer to area to scan for white
  353. pRData Pointer to RENDER structure
  354. iWhiteIndex White value to compare against
  355. included here for functional compatibility
  356. Return Value:
  357. TRUE if entire bitmap is white, else FALSE
  358. --*/
  359. {
  360. DWORD dwCnt;
  361. DWORD dwMask; /* Mask to zap the trailing bits */
  362. /*
  363. * As a speed optimisation, scan the bits in DWORD size clumps.
  364. * This substantially reduces the number of iterations and memory
  365. * references required. There will ususally be some trailing
  366. * bits; these are handled individually - if we get that far.
  367. */
  368. /* Mask to clear last few bits of scanline, if not full DWORD */
  369. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  370. if( dwMask == 0 )
  371. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  372. /* Clear out undefined bits at end of line */
  373. dwCnt = pRData->cDWLine;
  374. pdwBits[dwCnt-1] &= dwMask;
  375. pdwBits[dwCnt-1] |= ~dwMask & RGB_WHITE;
  376. // test four dwords at a time
  377. //
  378. while (dwCnt >= 4)
  379. {
  380. if ((*pdwBits & pdwBits[1] & pdwBits[2] & pdwBits[3] & RGB_WHITE) != RGB_WHITE)
  381. return FALSE;
  382. pdwBits += 4;
  383. dwCnt -= 4;
  384. }
  385. while (dwCnt--)
  386. {
  387. if ((*pdwBits & RGB_WHITE) != RGB_WHITE)
  388. return FALSE;
  389. pdwBits++;
  390. }
  391. return TRUE;
  392. }
  393. //**********************************************************
  394. BOOL
  395. bIs8BPPBandWhite (
  396. DWORD *pdwBitsIn,
  397. RENDER *pRData,
  398. int iWhiteIndex
  399. )
  400. /*++
  401. Routine Description:
  402. Scan a band of the bitmap, and return TRUE if it is
  403. all WHITE, else FALSE. This is used to decide whether a
  404. band should be sent to the printer.
  405. Arguments:
  406. pdwBitsIn Pointer to area to scan for white
  407. pRData Pointer to RENDER structure
  408. iWhiteIndex White value to compare against
  409. Return Value:
  410. TRUE if entire bitmap is white, else FALSE
  411. --*/
  412. {
  413. register DWORD *pdwBits;
  414. register DWORD *pdwLim;
  415. int iLines; /* Number of scan lines to check */
  416. DWORD dwMask; /* Mask to zap the trailing bits */
  417. DWORD dwWhiteIndex;
  418. dwWhiteIndex = (DWORD)iWhiteIndex;
  419. /*
  420. * As a speed optimisation, scan the bits in DWORD size clumps.
  421. * This substantially reduces the number of iterations and memory
  422. * references required. There will ususally be some trailing
  423. * bits; these are handled individually - if we get that far.
  424. */
  425. /* Mask to clear last few bits of scanline, if not full DWORD */
  426. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  427. if( dwMask == 0 )
  428. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  429. iLines = pRData->iTransHigh;
  430. /*
  431. * Need to set up the white index to be a dword multiple.
  432. * iwhiteIndex looks like 0x000000ff but the comparison
  433. * is done on dword boundaries so a stream of white looks
  434. * like 0xffffffff.
  435. */
  436. dwWhiteIndex |= dwWhiteIndex << 8;
  437. dwWhiteIndex |= dwWhiteIndex << 16;
  438. while( --iLines >= 0 )
  439. {
  440. /* Calculate the starting address for this scan */
  441. pdwBits = pdwBitsIn;
  442. /* pDWLim is the DWORD past the data of interest - not used */
  443. pdwLim = pdwBits + pRData->cDWLine;
  444. /* Clear out undefined bits at end of line */
  445. *(pdwLim - 1) &= dwMask;
  446. *(pdwLim - 1) |= ~dwMask & dwWhiteIndex;
  447. while(*pdwBits == dwWhiteIndex && ++pdwBits < pdwLim);
  448. if( pdwBits < pdwLim )
  449. return FALSE;
  450. /* Onto the next scan line */
  451. pdwBitsIn += pRData->cDWLine * pRData->iInterlace;
  452. }
  453. return TRUE;
  454. }
  455. //**********************************************************
  456. BOOL
  457. bIs8BPPLineWhite (
  458. DWORD *pdwBits,
  459. RENDER *pRData,
  460. int iWhiteIndex
  461. )
  462. /*++
  463. Routine Description:
  464. Scan a single row of the bitmap, and return TRUE if it is
  465. all WHITE, else FALSE. This is used to decide whether a
  466. band should be sent to the printer.
  467. Arguments:
  468. pdwBits Pointer to area to scan for white
  469. pRData Pointer to RENDER structure
  470. iWhiteIndex White value to compare against
  471. Return Value:
  472. TRUE if entire bitmap is white, else FALSE
  473. --*/
  474. {
  475. register DWORD *pdwLim;
  476. DWORD dwMask; /* Mask to zap the trailing bits */
  477. DWORD dwWhiteIndex;
  478. dwWhiteIndex = (DWORD)iWhiteIndex;
  479. /*
  480. * Need to set up the white index to be a dword multiple.
  481. * iwhiteIndex looks like 0x000000ff but the comparison
  482. * is done on dword boundaries so a stream of white looks
  483. * like 0xffffffff.
  484. */
  485. dwWhiteIndex |= dwWhiteIndex << 8;
  486. dwWhiteIndex |= dwWhiteIndex << 16;
  487. /*
  488. * As a speed optimisation, scan the bits in DWORD size clumps.
  489. * This substantially reduces the number of iterations and memory
  490. * references required. There will ususally be some trailing
  491. * bits; these are handled individually - if we get that far.
  492. */
  493. /* Mask to clear last few bits of scanline, if not full DWORD */
  494. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  495. if( dwMask == 0 )
  496. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  497. /* pDWLim is the DWORD past the data of interest - not used */
  498. pdwLim = pdwBits + pRData->cDWLine;
  499. /* Clear out undefined bits at end of line */
  500. *(pdwLim - 1) &= dwMask;
  501. *(pdwLim - 1) |= ~dwMask & dwWhiteIndex;
  502. while(*pdwBits == dwWhiteIndex && ++pdwBits < pdwLim);
  503. if( pdwBits < pdwLim )
  504. return FALSE;
  505. return TRUE;
  506. }
  507. //**********************************************************
  508. BOOL
  509. bIs24BPPBandWhite (
  510. DWORD *pdwBitsIn,
  511. RENDER *pRData,
  512. int iWhiteIndex
  513. )
  514. /*++
  515. Routine Description:
  516. Scan a band of the bitmap, and return TRUE if it is
  517. all WHITE, else FALSE. This is used to decide whether a
  518. band should be sent to the printer.
  519. Arguments:
  520. pdwBitsIn Pointer to area to scan for white
  521. pRData Pointer to RENDER structure
  522. iWhiteIndex White value to compare against
  523. included here for functional compatibility
  524. Return Value:
  525. TRUE if entire bitmap is white, else FALSE
  526. --*/
  527. {
  528. register DWORD *pdwBits;
  529. register DWORD *pdwLim;
  530. int iLines; /* Number of scan lines to check */
  531. DWORD dwMask; /* Mask to zap the trailing bits */
  532. DWORD dwWhiteIndex;
  533. dwWhiteIndex = (DWORD)iWhiteIndex;
  534. dwWhiteIndex |= dwWhiteIndex << 8;
  535. /*
  536. * As a speed optimisation, scan the bits in DWORD size clumps.
  537. * This substantially reduces the number of iterations and memory
  538. * references required. There will ususally be some trailing
  539. * bits; these are handled individually - if we get that far.
  540. */
  541. /* Mask to clear last few bits of scanline, if not full DWORD */
  542. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  543. if( dwMask == 0 )
  544. dwMask = (DWORD)~0; /* Size is DWORD multiple */
  545. iLines = pRData->iTransHigh;
  546. while( --iLines >= 0 )
  547. {
  548. /* Calculate the starting address for this scan */
  549. pdwBits = pdwBitsIn;
  550. /* pDWLim is the DWORD past the data of interest - not used */
  551. pdwLim = pdwBits + pRData->cDWLine;
  552. /* Clear out undefined bits at end of line */
  553. *(pdwLim - 1) &= dwMask;
  554. *(pdwLim - 1) |= ~dwMask & BPP8_WHITE;
  555. /*
  556. * NOTE: This test is more complex than needed because the
  557. * engine ignores palette entries when doing BLTs. The WHITENESS
  558. * rop sets all bits to 1. Hence, we choose to ignore the
  559. * MSB in the comparison: this means we detect white space
  560. * with an illegal palette entry. This makes GDI people happy,
  561. * but not me.
  562. */
  563. while(*pdwBits == dwWhiteIndex && ++pdwBits < pdwLim);
  564. if( pdwBits < pdwLim )
  565. return FALSE;
  566. /* Onto the next scan line */
  567. pdwBitsIn += pRData->cDWLine * pRData->iInterlace;
  568. }
  569. return TRUE;
  570. }
  571. //*******************************************************
  572. BOOL
  573. bIs24BPPLineWhite (
  574. register DWORD *pdwBits,
  575. RENDER *pRData,
  576. int iWhiteIndex
  577. )
  578. /*++
  579. Routine Description:
  580. Scan a single row of the bitmap, and return TRUE if it is
  581. all WHITE, else FALSE. This is used to decide whether a
  582. band should be sent to the printer.
  583. Arguments:
  584. pdwBitsIn Pointer to area to scan for white
  585. pRData Pointer to RENDER structure
  586. iWhiteIndex White value to compare against
  587. included here for functional compatibility
  588. Return Value:
  589. TRUE if entire bitmap is white, else FALSE
  590. --*/
  591. {
  592. DWORD dwMask; /* Mask to zap the trailing bits */
  593. LONG iLimit = pRData->cDWLine;
  594. /* Mask to clear last few bits of scanline, if not full DWORD */
  595. dwMask = *(pRData->pdwBitMask + (pRData->cBLine % DWBITS));
  596. if( dwMask != 0 )
  597. {
  598. /* Clear out undefined bits at end of line */
  599. pdwBits[iLimit-1] &= dwMask;
  600. pdwBits[iLimit-1] |= ~dwMask & BPP8_WHITE;
  601. }
  602. /*
  603. * As a speed optimisation, scan the bits in 4 DWORD size clumps.
  604. * This substantially reduces the number of iterations and memory
  605. * references required. First we will test the odd dwords.
  606. */
  607. while (iLimit & 3)
  608. {
  609. iLimit--;
  610. if (*pdwBits++ != ~0)
  611. return FALSE;
  612. }
  613. iLimit >>= 2;
  614. while (--iLimit >= 0)
  615. {
  616. pdwBits += 4;
  617. if ((pdwBits[-4] & pdwBits[-3] & pdwBits[-2] & pdwBits[-1]) != BPP8_WHITE)
  618. return FALSE;
  619. }
  620. return TRUE;
  621. }
  622. //*******************************************************
  623. BOOL
  624. bIs1BPPRegionWhite(
  625. DWORD *pdwBitsIn,
  626. RENDER *pRData,
  627. RECTL *pRect
  628. )
  629. /*++
  630. Routine Description:
  631. This function scans a specific region of the bitmap and returns
  632. TRUE if it is all white, else FALSE.
  633. Arguments:
  634. pdwBitsIn Pointer to area to scan for white
  635. pRData Pointer to RENDER structure
  636. pRect Pointer to RECT structure describing the
  637. region of the bitmap to test for white
  638. Return Value:
  639. TRUE if region is all white else false
  640. --*/
  641. {
  642. DWORD *pdwBits;
  643. int iLines; /* Number of scan lines to check */
  644. int iWords; // number of words to check per line
  645. DWORD dwEndMask; /* Mask to zap the trailing bits */
  646. DWORD dwBegMask; // mask to zap leading bits
  647. /*
  648. * As a speed optimisation, scan the bits in DWORD size clumps.
  649. * This substantially reduces the number of iterations and memory
  650. * references required. There will ususally be some leading and
  651. * trailing bits which are handled individually
  652. */
  653. /* Mask to clear last few bits of scanline, if not full DWORD */
  654. dwEndMask = *(pRData->pdwBitMask + (pRect->right % DWBITS));
  655. dwBegMask = ~(*(pRData->pdwBitMask + (pRect->left % DWBITS)));
  656. if( dwEndMask == 0 )
  657. dwEndMask = (DWORD)~0; /* Size is DWORD multiple */
  658. iLines = pRect->bottom - pRect->top;
  659. // calculate offset in buffer for top and left offsets
  660. pdwBitsIn += (pRData->cDWLine * pRect->top) + (pRect->left / DWBITS);
  661. // calculate number of words to test
  662. iWords = ((pRect->right + DWBITS - 1) / DWBITS) - (pRect->left / DWBITS);
  663. // if only 1 dword combine begin and end masks
  664. if (iWords == 0)
  665. {
  666. dwBegMask &= dwEndMask;
  667. }
  668. iWords--;
  669. while( --iLines >= 0 )
  670. {
  671. /* Calculate the starting address for this scan */
  672. pdwBits = pdwBitsIn;
  673. //* test beginning dword
  674. if (~(*pdwBits) & dwBegMask)
  675. return FALSE;
  676. pdwBits++;
  677. //* test remaining dwords if necessary
  678. if (iWords >= 0) {
  679. if (iWords > 0)
  680. {
  681. int iCnt = iWords;
  682. if (iCnt & 1)
  683. {
  684. if (pdwBits[0] != ~0)
  685. return FALSE;
  686. pdwBits++;
  687. }
  688. if (iCnt & 2)
  689. {
  690. if ((pdwBits[0] & pdwBits[1]) != ~0)
  691. return FALSE;
  692. pdwBits += 2;
  693. }
  694. while ((iCnt -= 4) >= 0)
  695. {
  696. if ((pdwBits[0] & pdwBits[1] & pdwBits[2] & pdwBits[3]) != ~0)
  697. return FALSE;
  698. pdwBits += 4;
  699. }
  700. }
  701. //* test last dword
  702. if (~(*pdwBits) & dwEndMask)
  703. return FALSE;
  704. }
  705. /* Onto the next scan line */
  706. pdwBitsIn += pRData->cDWLine;
  707. }
  708. return TRUE;
  709. }
  710. //**************************************************
  711. BOOL
  712. bIs4BPPRegionWhite(
  713. DWORD *pdwBitsIn,
  714. RENDER *pRData,
  715. RECTL *pRect
  716. )
  717. /*++
  718. Routine Description:
  719. This function scans a specific region of the bitmap and returns
  720. TRUE if it is all white, else FALSE.
  721. Arguments:
  722. pdwBitsIn Pointer to area to scan for white
  723. pRData Pointer to RENDER structure
  724. pRect Pointer to RECT structure describing the
  725. region of the bitmap to test for white
  726. Return Value:
  727. TRUE if region is all white else false
  728. --*/
  729. {
  730. DWORD *pdwBits;
  731. int iLines; /* Number of scan lines to check */
  732. int iWords; // number of words to check per line
  733. int iRight;
  734. int iLeft;
  735. DWORD dwEndMask; /* Mask to zap the trailing bits */
  736. DWORD dwBegMask; // mask to zap leading bits
  737. /*
  738. * As a speed optimisation, scan the bits in DWORD size clumps.
  739. * This substantially reduces the number of iterations and memory
  740. * references required. There will ususally be some leading and
  741. * trailing bits which are handled individually
  742. */
  743. //* Adjust horizontal positions by BPP
  744. iRight = pRect->right * BPP4;
  745. iLeft = pRect->left * BPP4;
  746. //* Mask to clear first and last bits of scanline, if not full DWORD
  747. //*
  748. dwEndMask = *(pRData->pdwBitMask + (iRight % DWBITS));
  749. dwBegMask = ~(*(pRData->pdwBitMask + (iLeft % DWBITS)));
  750. if( dwEndMask == 0 )
  751. dwEndMask = (DWORD)~0; /* Size is DWORD multiple */
  752. iLines = pRect->bottom - pRect->top;
  753. // calculate offset in buffer for top and left offsets
  754. pdwBitsIn += (pRData->cDWLine * pRect->top) + (iLeft / DWBITS);
  755. // calculate number of words to test
  756. iWords = ((iRight + DWBITS - 1) / DWBITS) - (iLeft / DWBITS);
  757. // if only 1 dword combine begin and end masks
  758. if (iWords == 0)
  759. dwBegMask &= dwEndMask;
  760. //* MSB of each pixel is ignored so combine with pixel mask
  761. //* see bIsRGBLineWhite for why MSB is ignored
  762. dwEndMask &= RGB_WHITE;
  763. dwBegMask &= RGB_WHITE;
  764. iWords--;
  765. while( --iLines >= 0 )
  766. {
  767. /* Calculate the starting address for this scan */
  768. pdwBits = pdwBitsIn;
  769. //* test beginning dword
  770. if ((*pdwBits & dwBegMask) != dwBegMask)
  771. return FALSE;
  772. pdwBits++;
  773. //* test remaining dwords if necessary
  774. if (iWords >= 0) {
  775. if (iWords > 0)
  776. {
  777. DWORD dwTmp = RGB_WHITE;
  778. int iCnt = iWords;
  779. while (iCnt & 3)
  780. {
  781. dwTmp &= *pdwBits++;
  782. iCnt--;
  783. }
  784. iCnt >>= 2;
  785. while (--iCnt >= 0)
  786. {
  787. dwTmp &= pdwBits[0];
  788. dwTmp &= pdwBits[1];
  789. dwTmp &= pdwBits[2];
  790. dwTmp &= pdwBits[3];
  791. pdwBits += 4;
  792. }
  793. if (dwTmp != RGB_WHITE)
  794. return FALSE;
  795. }
  796. //* test last dword
  797. if ((*pdwBits & dwEndMask) != dwEndMask)
  798. return FALSE;
  799. }
  800. /* Onto the next scan line */
  801. pdwBitsIn += pRData->cDWLine;
  802. }
  803. return TRUE;
  804. }
  805. //**************************************************
  806. BOOL
  807. bIs8BPPRegionWhite(
  808. DWORD *pdwBitsIn,
  809. RENDER *pRData,
  810. RECTL *pRect,
  811. int iWhiteIndex
  812. )
  813. /*++
  814. Routine Description:
  815. This function scans a specific region of the bitmap and returns
  816. TRUE if it is all white, else FALSE.
  817. Arguments:
  818. pdwBitsIn Pointer to area to scan for white
  819. pRData Pointer to RENDER structure
  820. pRect Pointer to RECT structure describing the
  821. region of the bitmap to test for white
  822. Return Value:
  823. TRUE if region is all white else false
  824. --*/
  825. {
  826. DWORD *pdwBits;
  827. int iLines; /* Number of scan lines to check */
  828. int iWords; // number of words to check per line
  829. int iRight;
  830. int iLeft;
  831. DWORD dwEndMask; /* Mask to zap the trailing bits */
  832. DWORD dwBegMask; // mask to zap leading bits
  833. DWORD dwWhiteIndex;
  834. //* calculate WhiteIndex for 4 bytes at a time
  835. dwWhiteIndex = (DWORD)iWhiteIndex;
  836. dwWhiteIndex |= dwWhiteIndex << 8;
  837. dwWhiteIndex |= dwWhiteIndex << 16;
  838. //* Adjust horizontal positions by BPP
  839. iRight = pRect->right * BPP8;
  840. iLeft = pRect->left * BPP8;
  841. //* Mask to clear first and last bits of scanline, if not full DWORD
  842. //*
  843. dwEndMask = *(pRData->pdwBitMask + (iRight % DWBITS));
  844. dwBegMask = ~(*(pRData->pdwBitMask + (iLeft % DWBITS)));
  845. if( dwEndMask == 0 )
  846. dwEndMask = (DWORD)~0; /* Size is DWORD multiple */
  847. iLines = pRect->bottom - pRect->top;
  848. // calculate offset in buffer for top and left offsets
  849. pdwBitsIn += (pRData->cDWLine * pRect->top) + (iLeft / DWBITS);
  850. // calculate number of words to test
  851. iWords = ((iRight + DWBITS - 1) / DWBITS) - (iLeft / DWBITS);
  852. // if only 1 dword combine begin and end masks
  853. if (iWords == 0)
  854. dwBegMask &= dwEndMask;
  855. iWords--;
  856. while( --iLines >= 0 )
  857. {
  858. /* Calculate the starting address for this scan */
  859. pdwBits = pdwBitsIn;
  860. //* test beginning dword
  861. if ((*pdwBits & dwBegMask) != (dwWhiteIndex & dwBegMask))
  862. return FALSE;
  863. pdwBits++;
  864. //* test remaining dwords if necessary
  865. if (iWords >= 0) {
  866. if (iWords > 0)
  867. {
  868. int iCnt = iWords;
  869. do {
  870. if (*pdwBits != dwWhiteIndex)
  871. return FALSE;
  872. pdwBits++;
  873. } while (--iCnt);
  874. }
  875. //* test last dword
  876. if ((*pdwBits & dwEndMask) != (dwWhiteIndex & dwEndMask))
  877. return FALSE;
  878. }
  879. /* Onto the next scan line */
  880. pdwBitsIn += pRData->cDWLine;
  881. }
  882. return TRUE;
  883. }
  884. //****************************************************
  885. BOOL
  886. bIs24BPPRegionWhite(
  887. DWORD *pdwBitsIn,
  888. RENDER *pRData,
  889. RECTL *pRect
  890. )
  891. /*++
  892. Routine Description:
  893. This function scans a specific region of the bitmap and returns
  894. TRUE if it is all white, else FALSE.
  895. Arguments:
  896. pdwBitsIn Pointer to area to scan for white
  897. pRData Pointer to RENDER structure
  898. pRect Pointer to RECT structure describing the
  899. region of the bitmap to test for white
  900. Return Value:
  901. TRUE if region is all white else false
  902. --*/
  903. {
  904. DWORD *pdwBits;
  905. int iLines; // Number of scan lines to check */
  906. int iWords; // number of words to check per line
  907. int iRight;
  908. int iLeft;
  909. DWORD dwEndMask; // Mask to zap the trailing bits */
  910. DWORD dwBegMask; // mask to zap leading bits
  911. //* Adjust horizontal positions by BPP
  912. iRight = pRect->right * BPP24;
  913. iLeft = pRect->left * BPP24;
  914. //* Mask to clear first and last bits of scanline, if not full DWORD
  915. //*
  916. dwEndMask = *(pRData->pdwBitMask + (iRight % DWBITS));
  917. dwBegMask = ~(*(pRData->pdwBitMask + (iLeft % DWBITS)));
  918. if( dwEndMask == 0 )
  919. dwEndMask = (DWORD)~0; /* Size is DWORD multiple */
  920. iLines = pRect->bottom - pRect->top;
  921. // calculate offset in buffer for top and left offsets
  922. pdwBitsIn += (pRData->cDWLine * pRect->top) + (iLeft / DWBITS);
  923. // calculate number of words to test
  924. iWords = ((iRight + DWBITS - 1) / DWBITS) - (iLeft / DWBITS);
  925. // if only 1 dword combine begin and end masks
  926. if (iWords == 0)
  927. dwBegMask &= dwEndMask;
  928. iWords--;
  929. while( --iLines >= 0 )
  930. {
  931. /* Calculate the starting address for this scan */
  932. pdwBits = pdwBitsIn;
  933. //* test beginning dword
  934. if ((*pdwBits & dwBegMask) != dwBegMask)
  935. return FALSE;
  936. pdwBits++;
  937. //* test remaining dwords if necessary
  938. if (iWords >= 0) {
  939. if (iWords > 0)
  940. {
  941. int iCnt = iWords;
  942. while (iCnt & 3)
  943. {
  944. if (*pdwBits != ~0)
  945. return FALSE;
  946. pdwBits++;
  947. iCnt--;
  948. }
  949. iCnt >>= 2;
  950. while (--iCnt >= 0)
  951. {
  952. if ((pdwBits[0] & pdwBits[1] & pdwBits[2] & pdwBits[3]) != ~0)
  953. return FALSE;
  954. pdwBits += 4;
  955. }
  956. }
  957. //* test last dword
  958. if ((*pdwBits & dwEndMask) != dwEndMask)
  959. return FALSE;
  960. }
  961. /* Onto the next scan line */
  962. pdwBitsIn += pRData->cDWLine;
  963. }
  964. return TRUE;
  965. }
  966. //*********************************************************
  967. BOOL
  968. bIsRegionWhite(
  969. SURFOBJ *pso,
  970. RECTL *pRect
  971. )
  972. /*++
  973. Routine Description:
  974. This routine determines whether a given region of the
  975. shadow bitmap is white.
  976. Arguments:
  977. pPDev - Pointer to PDEV.
  978. pRect - Pointer to clip window within shadow bitmap
  979. Return Value:
  980. TRUE - for success
  981. FALSE - for failure
  982. Note:
  983. 01-07-97: Created by alvins
  984. --*/
  985. {
  986. PDEV *pPDev = (PDEV *)pso->dhpdev;
  987. PRASTERPDEV pRPDev = (PRASTERPDEV)pPDev->pRasterPDEV;
  988. RENDER *pRD;
  989. RECTL Rectl;
  990. int y1,y2;
  991. // If the render structure hasn't been initialize how can
  992. // there have been data drawn in it. Also check the dirty flag
  993. if (!(pPDev->fMode & PF_SURFACE_USED) || pRPDev == NULL)
  994. return TRUE;
  995. pRD = pRPDev->pvRenderData;
  996. if (pRD == NULL)
  997. return TRUE;
  998. // lets make sure these values are positive
  999. // and there's still something to test
  1000. //
  1001. Rectl.left = pRect->left > 0 ? pRect->left : 0;
  1002. Rectl.top = pRect->top > 0 ? pRect->top : 0;
  1003. Rectl.right = pRect->right > 0 ? pRect->right : 0;
  1004. Rectl.bottom = pRect->bottom > 0 ? pRect->bottom : 0;
  1005. if (Rectl.left == Rectl.right || Rectl.top == Rectl.bottom)
  1006. return TRUE;
  1007. // if not surface then also assume all white
  1008. if (pso->iType != STYPE_BITMAP)
  1009. return TRUE;
  1010. // need to actually check data at this point
  1011. y1 = Rectl.top / LINESPERBLOCK;
  1012. y2 = (Rectl.bottom-1) / LINESPERBLOCK;
  1013. while (y1 <= y2)
  1014. {
  1015. RECTL tRectl = Rectl;
  1016. if (pPDev->pbRasterScanBuf == NULL || pPDev->pbRasterScanBuf[y1])
  1017. {
  1018. // test a block at a time if we've block erased the surface
  1019. //
  1020. if (pPDev->pbRasterScanBuf)
  1021. {
  1022. if ((y1*LINESPERBLOCK) > tRectl.top)
  1023. tRectl.top = y1 * LINESPERBLOCK;
  1024. y1++;
  1025. if ((y1*LINESPERBLOCK) < tRectl.bottom)
  1026. tRectl.bottom = y1 * LINESPERBLOCK;
  1027. }
  1028. // surface is not block erased so make this last loop
  1029. //
  1030. else
  1031. y1 = y2+1;
  1032. switch (pRD->iBPP)
  1033. {
  1034. case 1:
  1035. if (!bIs1BPPRegionWhite(pso->pvBits,pRD,&tRectl))
  1036. return FALSE;
  1037. break;
  1038. case 4:
  1039. if (!bIs4BPPRegionWhite(pso->pvBits,pRD,&tRectl))
  1040. return FALSE;
  1041. break;
  1042. case 8:
  1043. if (!bIs8BPPRegionWhite(pso->pvBits,pRD,&tRectl,pRPDev->pPalData->iWhiteIndex))
  1044. return FALSE;
  1045. break;
  1046. case 24:
  1047. if (!bIs24BPPRegionWhite(pso->pvBits,pRD,&tRectl))
  1048. return FALSE;
  1049. break;
  1050. // if I don't recognize the format, I'll assume its empty
  1051. default:
  1052. return TRUE;
  1053. }
  1054. }
  1055. else
  1056. y1++;
  1057. }
  1058. return TRUE;
  1059. }
  1060. //*******************************************************
  1061. BOOL
  1062. bIsNeverWhite (
  1063. register DWORD *pdwBits,
  1064. RENDER *pRData,
  1065. int iWhiteIndex
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This function always returns FALSE and exists only to provide
  1070. a common function call format for all the IsWhite Line/Band
  1071. functions.
  1072. Arguments:
  1073. pdwBitsIn Pointer to area to scan for white
  1074. pRData Pointer to RENDER structure
  1075. iWhiteIndex White value to compare against
  1076. Return Value:
  1077. FALSE
  1078. --*/
  1079. {
  1080. return FALSE;
  1081. }
  1082. //******************************************************
  1083. int
  1084. iStripBlanks(
  1085. BYTE *pbOut,
  1086. BYTE *pbIn,
  1087. int iLeft,
  1088. int iRight,
  1089. int iHeight,
  1090. int iWidth
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. This function strips already identified white space
  1095. from the buffer.
  1096. Arguments:
  1097. pbOut Pointer to output buffer
  1098. pbIn Pointer source buffer
  1099. iLeft First non-white leading byte
  1100. iRight First white trailing byte
  1101. iHeight Number of scanlines
  1102. iWidth Width of source scanlines
  1103. Return Value:
  1104. Number of bytes in new buffer
  1105. --*/
  1106. {
  1107. int i,j;
  1108. BYTE * pbSrc;
  1109. BYTE * pbTgt;
  1110. int iDelta;
  1111. iDelta = iRight - iLeft;
  1112. pbTgt = pbOut;
  1113. pbSrc = pbIn+iLeft;
  1114. for (i = 0; i < iHeight; i++)
  1115. {
  1116. CopyMemory(pbTgt,pbSrc,iDelta);
  1117. pbTgt += iDelta;
  1118. pbSrc += iWidth;
  1119. }
  1120. return (iDelta * iHeight);
  1121. }