|
|
/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
htbmp4.c
Abstract:
This module contains functions to output halftoned 4 bit per pel (4 BPP) bitmaps to the target device.
Author:
21-Dec-1993 Tue 21:32:26 created
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgHTBmp4
#define DBG_OUTPUT4BPP 0x00000001
#define DBG_OUTPUT4BPP_ROT 0x00000002
#define DBG_JOBCANCEL 0x00000004
DEFINE_DBGVAR(0);
//
// To Use OUT_ONE_4BPP_SCAN, the following variables must be set before hand:
//
// HTBmpInfo - The whole structure copied down
// pbScanSrc - LPBYTE for getting the source scan line buffer
// pbScanR0 - Red destination scan line buffer pointer
// pbScanG0 - Green destination scan line buffer pointer
// pbScanB0 - Blue destination scan line buffer pointer
// RTLScans.cxBytes- Total size of destination scan line buffer per plane
// pHTXB - Computed HTXB xlate table in pPDev
//
// This macro will always assume the pbScanSrc is DWORD aligned. This
// makes the inner loop go faster since we only need to move the source once
// for all raster planes.
//
// This macro will directly return a FALSE if a CANCEL JOB is detected during
// procesing.
//
// This will output directly to RTL.
//
//
#define OUT_ONE_4BPP_SCAN \
{ \ LPBYTE pbScanR = pbScanR0; \ LPBYTE pbScanG = pbScanG0; \ LPBYTE pbScanB = pbScanB0; \ DWORD LoopHTXB = RTLScans.cxBytes; \ HTXB htXB; \ \ while (LoopHTXB--) { \ \ P4B_TO_3P_DW(htXB.dw, pHTXB, pbScanSrc); \ \ *pbScanR++ = HTXB_R(htXB); \ *pbScanG++ = HTXB_G(htXB); \ *pbScanB++ = HTXB_B(htXB); \ } \ \ OutputRTLScans(HTBmpInfo.pPDev, \ pbScanR0, \ pbScanG0, \ pbScanB0, \ &RTLScans); \ }
BOOL Output4bppHTBmp( PHTBMPINFO pHTBmpInfo )
/*++
Routine Description:
This function outputs a 4 bpp halftoned bitmap
Arguments:
pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this fuction to output the bitmap
Return Value:
TRUE if sucessful otherwise a FALSE is returned
Author:
Created
18-Jan-1994 Tue 16:05:08 Updated Changed ASSERT to look at pHTBmpInfo instead of HTBmpInfo
21-Dec-1993 Tue 16:05:08 Updated Re-write to make it take HTBMPINFO
16-Mar-1994 Wed 16:54:59 updated Updated so we do not copy to the temp. buffer anymore, the masking of last source byte problem in OutputRTLScans() will be smart enough to put the original byte back after the masking
Revision History:
--*/
{ LPBYTE pbScanSrc; PHTXB pHTXB; LPBYTE pbScanR0; LPBYTE pbScanG0; LPBYTE pbScanB0; HTBMPINFO HTBmpInfo; RTLSCANS RTLScans; DWORD LShiftCount;
PLOTASSERT(1, "Output4bppHTBmp: No DWORD align buffer (pRotBuf)", pHTBmpInfo->pRotBuf, 0); HTBmpInfo = *pHTBmpInfo;
EnterRTLScans(HTBmpInfo.pPDev, &RTLScans, HTBmpInfo.szlBmp.cx, HTBmpInfo.szlBmp.cy, FALSE);
pHTXB = ((PDRVHTINFO)HTBmpInfo.pPDev->pvDrvHTData)->pHTXB; HTBmpInfo.pScan0 += (HTBmpInfo.OffBmp.x >> 1); pbScanR0 = HTBmpInfo.pScanBuf; pbScanG0 = pbScanR0 + RTLScans.cxBytes; pbScanB0 = pbScanG0 + RTLScans.cxBytes;
PLOTASSERT(1, "The ScanBuf size is too small (%ld)", (RTLScans.cxBytes * 3) <= HTBmpInfo.cScanBuf, HTBmpInfo.cScanBuf);
PLOTASSERT(1, "The RotBuf size is too small (%ld)", (DWORD)((HTBmpInfo.szlBmp.cx + 1) >> 1) <= HTBmpInfo.cRotBuf, HTBmpInfo.cRotBuf);
if (HTBmpInfo.OffBmp.x & 0x01) {
//
// We must shift one nibble to the left now
//
LShiftCount = (DWORD)HTBmpInfo.szlBmp.cx;
PLOTDBG(DBG_OUTPUT4BPP, ("Output4bppHTBmp: Must SHIFT LEFT 1 NIBBLE To align"));
} else {
LShiftCount = 0; }
//
// We must be very careful not to read past the end of the source buffer.
// This could happen if we pbScanSrc is not DWORD aligned, since this
// will cause the last conversion macro to load all 4 bytes. To resolve
// this we can either copy the source buffer to a DWORD aligned temporary
// location, or handle the last incomplete DWORD differently. This only
// occurs when the bitmap is NOT rotated, and (pbScanSrc & 0x03).
//
while (RTLScans.Flags & RTLSF_MORE_SCAN) {
//
// This is the final source for this scan line
//
if (LShiftCount) {
LPBYTE pbTmp; DWORD PairCount; BYTE b0; BYTE b1;
pbTmp = HTBmpInfo.pScan0; b1 = *pbTmp; pbScanSrc = HTBmpInfo.pRotBuf; PairCount = LShiftCount;
while (PairCount > 1) {
b0 = b1; b1 = *pbTmp++; *pbScanSrc++ = (BYTE)((b0 << 4) | (b1 >> 4)); PairCount -= 2; }
if (PairCount) {
//
// If we have the last nibble to do then make it 0xF0 nibble,
// so we only look at the bits of interest.
//
*pbScanSrc = (BYTE)(b1 << 4); }
//
// Reset this pointer back to the final shifted source buffer
//
pbScanSrc = HTBmpInfo.pRotBuf;
} else {
pbScanSrc = HTBmpInfo.pScan0; }
//
// Output one 4 bpp scan line (3 planes)
//
OUT_ONE_4BPP_SCAN;
//
// advance source bitmap buffer pointer to next scan line
//
HTBmpInfo.pScan0 += HTBmpInfo.Delta; }
//
// The caller will send END GRAPHIC command if we return TRUE, thus
// completing the RTL graphic command.
//
ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
return(TRUE); }
BOOL Output4bppRotateHTBmp( PHTBMPINFO pHTBmpInfo )
/*++
Routine Description:
This function outputs a 4 bpp halftoned bitmap and rotates it to the left as illustrated
cx Org ---- +X --> +-------+ | @------------+ | | | | | | ***** | | | * | c| * | | * c| y| * | +Y | ******* y| | * | | * | | * | | | * | | * | V | | | * | +------------+ +-------+
Arguments:
pHTBmpInfo - Pointer to the HTBMPINFO data structure set up for this fuction to output the bitmap
Return Value:
TRUE if sucessful otherwise a FALSE is returned
Author:
21-Dec-1993 Tue 16:05:08 Updated Re-write to make it take an HTBMPINFO structure.
Created
Revision History:
--*/
{ LPBYTE pbScanSrc; LPBYTE pb2ndScan; PHTXB pHTXB; LPBYTE pbScanR0; LPBYTE pbScanG0; LPBYTE pbScanB0; HTBMPINFO HTBmpInfo; RTLSCANS RTLScans; TPINFO TPInfo; DWORD EndX;
//
// The EndX is the pixel we will start reading in the X direction, we must
// setup the variable correctly before we call OUT_4BPP_SETUP.
//
HTBmpInfo = *pHTBmpInfo;
EnterRTLScans(HTBmpInfo.pPDev, &RTLScans, HTBmpInfo.szlBmp.cy, HTBmpInfo.szlBmp.cx, FALSE);
pHTXB = ((PDRVHTINFO)HTBmpInfo.pPDev->pvDrvHTData)->pHTXB; EndX = (DWORD)(HTBmpInfo.OffBmp.x + HTBmpInfo.szlBmp.cx - 1); HTBmpInfo.pScan0 += (EndX >> 1); pbScanR0 = HTBmpInfo.pScanBuf; pbScanG0 = pbScanR0 + RTLScans.cxBytes; pbScanB0 = pbScanG0 + RTLScans.cxBytes;
PLOTASSERT(1, "The ScanBuf size is too small (%ld)", (RTLScans.cxBytes * 3) <= HTBmpInfo.cScanBuf, HTBmpInfo.cScanBuf);
//
// after the transpose of the source bitmap into two scanlines the rotated
// buffer will always start from the high nibble, we will never have
// an odd src X position.
// We assume rotation is always to the right 90 degree
//
TPInfo.pPDev = HTBmpInfo.pPDev; TPInfo.pSrc = HTBmpInfo.pScan0; TPInfo.pDest = HTBmpInfo.pRotBuf; TPInfo.cbSrcScan = HTBmpInfo.Delta; TPInfo.cbDestScan = (LONG)((HTBmpInfo.szlBmp.cy + 1) >> 1); TPInfo.cbDestScan = (LONG)DW_ALIGN(TPInfo.cbDestScan); TPInfo.cySrc = HTBmpInfo.szlBmp.cy; TPInfo.DestXStart = 0;
PLOTASSERT(1, "The RotBuf size is too small (%ld)", (DWORD)(TPInfo.cbDestScan << 1) <= HTBmpInfo.cRotBuf, HTBmpInfo.cRotBuf);
//
// Compute the 2nd scan pointer once, rather than every time in the
// loop.
//
pb2ndScan = TPInfo.pDest + TPInfo.cbDestScan;
//
// If we are in an even position do the first transpose once, outside the
// loop, so we don't have to check this state for ever pass through the
// loop. If we do the transpose, TPInfo.pSrc, will be decremented by one,
// and pointing to the correct position.
//
if (!(EndX &= 0x01)) {
TransPos4BPP(&TPInfo); }
while (RTLScans.Flags & RTLSF_MORE_SCAN) {
//
// Do the transpose, only if the source goes into the new byte position.
// After the transpose (right 90 degrees) the TPInfo.pDest will point
// to the first scan line and TPInfo.pDest + TPInfo.cbDestScan will be
// the second scan line.
//
if (EndX ^= 0x01) {
pbScanSrc = pb2ndScan;
} else {
TransPos4BPP(&TPInfo);
//
// Point to the first scan line in the rotated direction. This
// will be computed correctly by the TRANSPOSE function, even
// if we rotated left.
//
pbScanSrc = TPInfo.pDest; }
//
// Output one 4bpp scan line (in 3 plane format)
//
OUT_ONE_4BPP_SCAN; }
//
// The caller will send the END GRAPHIC command if we return TRUE, thus
// completing the RTL graphic command.
//
ExitRTLScans(HTBmpInfo.pPDev, &RTLScans);
return(TRUE); }
|