572 lines
15 KiB
C
572 lines
15 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-1999 Microsoft Corporation
|
||
|
||
|
||
Module Name:
|
||
|
||
transpos.c
|
||
|
||
|
||
Abstract:
|
||
|
||
This module implements the functions for transposing an 8BPP, 4BPP and
|
||
1BPP bitmap. There is also a helper function for building a table which
|
||
speeds some of the rotation logic.
|
||
|
||
Author:
|
||
|
||
22-Dec-1993 Wed 13:09:11 created -by- DC
|
||
|
||
|
||
[Environment:]
|
||
|
||
GDI Device Driver - Plotter.
|
||
|
||
|
||
[Notes:]
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#define DBG_PLOTFILENAME DbgTransPos
|
||
|
||
#define DBG_BUILD_TP8x8 0x00000001
|
||
#define DBG_TP_1BPP 0x00000002
|
||
#define DBG_TP_4BPP 0x00000004
|
||
|
||
DEFINE_DBGVAR(0);
|
||
|
||
|
||
|
||
//
|
||
// Private #defines and data structures for use only in this module.
|
||
//
|
||
|
||
#define ENTRY_TP8x8 256
|
||
#define SIZE_TP8x8 (sizeof(DWORD) * 2 * ENTRY_TP8x8)
|
||
|
||
|
||
|
||
LPDWORD
|
||
Build8x8TransPosTable(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function build the 8x8 transpos table for use later in transposing
|
||
1bpp.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
Author:
|
||
|
||
22-Dec-1993 Wed 14:19:50 created -by- DC
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
LPDWORD pdwTP8x8;
|
||
|
||
|
||
//
|
||
// We now build the table which will represent the data for doing a
|
||
// rotation. Basically for each combination of bits in the byte, we
|
||
// build the equivalent 8 byte rotation for those bits. The 1st byte
|
||
// of the translated bytes are mapped to the 0x01 bit of the source and
|
||
// the last byte is mapped to the 0x80 bit.
|
||
|
||
|
||
|
||
if (pdwTP8x8 = (LPDWORD)LocalAlloc(LPTR, SIZE_TP8x8)) {
|
||
|
||
LPBYTE pbData = (LPBYTE)pdwTP8x8;
|
||
WORD Entry;
|
||
WORD Bits;
|
||
|
||
//
|
||
// Now start buiding the table, for each entry we expand each bit
|
||
// in the byte to the rotate byte value.
|
||
//
|
||
|
||
for (Entry = 0; Entry < ENTRY_TP8x8; Entry++) {
|
||
|
||
//
|
||
// For each of bit combinations in the byte, we will examine each
|
||
// bit from bit 0 to bit 7, and set each of the trasposed bytes to
|
||
// either 1 (bit set) or 0 (bit clear)
|
||
//
|
||
|
||
Bits = (WORD)Entry | (WORD)0xff00;
|
||
|
||
while (Bits & 0x0100) {
|
||
|
||
*pbData++ = (BYTE)(Bits & 0x01);
|
||
Bits >>= 1;
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
PLOTERR(("Build8x8TransPosTable: LocalAlloc(SIZE_TP8x8=%ld) failed",
|
||
SIZE_TP8x8));
|
||
}
|
||
|
||
return(pdwTP8x8);
|
||
}
|
||
|
||
|
||
|
||
|
||
BOOL
|
||
TransPos8BPP(
|
||
PTPINFO pTPInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function rotates a 4bpp source to a 4bpp destination
|
||
|
||
Arguments:
|
||
|
||
pTPINFO - Pointer to the TPINFO to describe how to do transpos, the fields
|
||
must be set to following:
|
||
|
||
pPDev: Pointer to the PDEV
|
||
pSrc: Pointer to the source bitmap starting point
|
||
pDest Pointer to the destination bitmap location which stores the
|
||
transpos result starting from the fist destination scan line
|
||
in the rotated direction (rotating right will have the low
|
||
nibble source byte as the first destination scan line.
|
||
cbSrcScan: Count to be added to advance to then next source bitmap line
|
||
cbDestScan: Count to be added to advance to the high nibble of the
|
||
destination bitmap line
|
||
cySrc Total source lines to be processed
|
||
DestXStart: not used, Ignored
|
||
|
||
|
||
NOTE: 1. The size of buffer area pointed by pDestL must have at least
|
||
(((cySrc + 1) / 2) * 2) size in bytes, and ABS(DestDelta)
|
||
must be at least half of that size.
|
||
|
||
2. Unused last destination byte will be padded with 0
|
||
|
||
Current transposition assumes the bitmap is rotated to the right, if caller
|
||
wants to rotate the bitmap to the left then you must first call the macro
|
||
ROTLEFT_4BPP_TPIINFO(pTPInfo)
|
||
|
||
|
||
Return Value:
|
||
|
||
TRUE if sucessful, FALSE if failed.
|
||
|
||
if sucessful the pTPInfo->pSrc will automatically be
|
||
|
||
1. Incremented by one (1) if cbDestScan is negative (Rotated left 90 degree)
|
||
2. Decremented by one (1) if cbDestScan is positive (Rotated right 90 degree)
|
||
|
||
Author:
|
||
|
||
22-Dec-1993 Wed 13:11:30 created -by- DC
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pSrc;
|
||
LPBYTE pDest;
|
||
LONG cbSrcScan;
|
||
DWORD cySrc;
|
||
|
||
|
||
PLOTASSERT(1, "cbDestScan is not big enough (%ld)",
|
||
(DWORD)(ABS(pTPInfo->cbDestScan)) >=
|
||
(DWORD)(((pTPInfo->cySrc) + 1) >> 1), pTPInfo->cbDestScan);
|
||
|
||
//
|
||
// This is a simple 1x1 8bpp transpose, pSrc will start with one scan line
|
||
// less so the inner loop can be clearly written.
|
||
//
|
||
|
||
cbSrcScan = pTPInfo->cbSrcScan;
|
||
pSrc = pTPInfo->pSrc - cbSrcScan;
|
||
pDest = pTPInfo->pDest;
|
||
cySrc = pTPInfo->cySrc;
|
||
|
||
while (cySrc--) {
|
||
|
||
*pDest++ = *(pSrc += cbSrcScan);
|
||
}
|
||
|
||
pTPInfo->pSrc += (INT)((pTPInfo->cbDestScan > 0) ? -1 : 1);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
|
||
|
||
BOOL
|
||
TransPos4BPP(
|
||
PTPINFO pTPInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function rotates a 4bpp source to a 4bpp destination
|
||
|
||
Arguments:
|
||
|
||
pTPINFO - Pointer to the TPINFO to describe how to do transpose, the fields
|
||
must be set to following
|
||
|
||
pPDev: Pointer to the PDEV
|
||
pSrc: Pointer to the soruce bitmap starting point
|
||
pDest Pointer to the destination bitmap location which stores the
|
||
transpos result starting from the fist destination scan
|
||
line in the rotated direction (rotating right will have
|
||
low nibble source bytes as the first destination scan line)
|
||
cbSrcScan: Count to be added to advance to next source bitmap line
|
||
cbDestScan: Count to be added to advance to the high nibble destination
|
||
bitmap line
|
||
cySrc Total source lines to be processed
|
||
DestXStart: not used, Ignored
|
||
|
||
|
||
NOTE: 1. The size of buffer area pointed to by pDestL must have at least
|
||
(((cySrc + 1) / 2) * 2) size in bytes, and ABS(DestDelta)
|
||
must at least half of that size.
|
||
|
||
2. Unused last destination byte will be padded with 0
|
||
|
||
Current transposition assumes the bitmap is rotated to the right, if caller
|
||
wants to rotate the bitmap to the left then you must first call the macro
|
||
ROTLEFT_4BPP_TPIINFO(pTPInfo)
|
||
|
||
|
||
Return Value:
|
||
|
||
TRUE if sucessful, FALSE if failed.
|
||
|
||
if sucessful the pTPInfo->pSrc will be automatically:
|
||
|
||
1. Incremented by one (1) if cbDestScan is negative (Rotated left 90 degree)
|
||
2. Decremented by one (1) if cbDestScan is positive (Rotated right 90 degree)
|
||
|
||
Author:
|
||
|
||
22-Dec-1993 Wed 13:11:30 created -by- DC
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pSrc;
|
||
LPBYTE pDest1st;
|
||
LPBYTE pDest2nd;
|
||
LONG cbSrcScan;
|
||
DWORD cySrc;
|
||
BYTE b0;
|
||
BYTE b1;
|
||
|
||
|
||
PLOTASSERT(1, "cbDestScan is not big enough (%ld)",
|
||
(DWORD)(ABS(pTPInfo->cbDestScan)) >=
|
||
(DWORD)(((pTPInfo->cySrc) + 1) >> 1), pTPInfo->cbDestScan);
|
||
|
||
//
|
||
// This is a simple 2x2 4bpp transpos, we will transpos only up to cySrc
|
||
// if cySrc is an odd number then the last destination low nibble is set
|
||
// padded with 0
|
||
//
|
||
// Scan 0 - Src0_H Src0_L pNibbleL - Src0_L Src1_L Src2_L Src3_L
|
||
// Scan 1 - Src1_H Src1_L ----> pNibbleH - Src0_H Src1_H Src2_H Src3_H
|
||
// Scan 2 - Src2_H Src2_L
|
||
// Scan 3 - Src3_H Src3_L
|
||
//
|
||
//
|
||
|
||
pSrc = pTPInfo->pSrc;
|
||
cbSrcScan = pTPInfo->cbSrcScan;
|
||
pDest1st = pTPInfo->pDest;
|
||
pDest2nd = pDest1st + pTPInfo->cbDestScan;
|
||
cySrc = pTPInfo->cySrc;
|
||
|
||
//
|
||
// Compute the transpose, leaving the last scan line for later. This
|
||
// way we don't pollute the loop with having to check if its the last
|
||
// line.
|
||
//
|
||
|
||
while (cySrc > 1) {
|
||
|
||
//
|
||
// Compose two input scan line buffers from the input scan buffer
|
||
// by reading in the Y direction
|
||
//
|
||
|
||
b0 = *pSrc;
|
||
b1 = *(pSrc += cbSrcScan);
|
||
*pDest1st++ = (BYTE)((b0 << 4) | (b1 & 0x0f));
|
||
*pDest2nd++ = (BYTE)((b1 >> 4) | (b0 & 0xf0));
|
||
|
||
pSrc += cbSrcScan;
|
||
cySrc -= 2;
|
||
}
|
||
|
||
//
|
||
// Deal with last odd source scan line
|
||
//
|
||
|
||
if (cySrc > 0) {
|
||
|
||
b0 = *pSrc;
|
||
*pDest1st = (BYTE)(b0 << 4);
|
||
*pDest2nd = (BYTE)(b0 & 0xf0);
|
||
}
|
||
|
||
pTPInfo->pSrc += (INT)((pTPInfo->cbDestScan > 0) ? -1 : 1);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
BOOL
|
||
TransPos1BPP(
|
||
PTPINFO pTPInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function rotates a 1bpp source to 1bpp destination.
|
||
|
||
Arguments:
|
||
|
||
pTPINFO - Pointer to the TPINFO to describe how to do the transpose, the
|
||
fields must be set to the following:
|
||
|
||
pPDev: Pointer to the PDEV
|
||
pSrc: Pointer to the soruce bitmap starting point
|
||
pDest Pointer to the destination bitmap location which stores the
|
||
transpos result starting from the fist destination scan
|
||
line in the rotated direction (rotating right will have
|
||
0x01 source bit as first destination scan line)
|
||
cbSrcScan: Count to be added to advance to next source bitmap line
|
||
cbDestScan: Count to be added to advance to the next destination line
|
||
cySrc Total source lines to be processed
|
||
DestXStart Specifies where the transposed destination buffer starts,
|
||
in bit position. It is computed as DestXStart % 8. 0 means
|
||
it starts at the top bit (0x80), 1 means the next bit (0x40)
|
||
and so forth.
|
||
|
||
NOTE:
|
||
|
||
1. The ABS(DestDelta) must be large enough to accomodate the
|
||
transposed scan line. The size depends on cySrc and DestXStart,
|
||
the mimimum size must at least be of the size:
|
||
|
||
MinSize = (cySrc + (DestXStart % 8) + 7) / 8
|
||
|
||
2. The size of the buffer are pointed to by pDest must have at
|
||
least ABS(DestDelta) * 8 bytes, if cySrc >= 8, or
|
||
ABS(DestDelta) * cySrc if cySrc is less than 8.
|
||
|
||
|
||
3. Unused last byte destinations are padded with 0
|
||
|
||
|
||
Current transposition assumes the bitmap is rotated to the right, if caller
|
||
wants to rotate the bitmap to the left then you must first call the macro
|
||
ROTLEFT_1BPP_TPIINFO(pTPInfo)
|
||
|
||
|
||
Return Value:
|
||
|
||
TRUE if sucessful FALSE if failed
|
||
|
||
if sucessful the pTPInfo->pSrc will be automatically
|
||
|
||
1. Incremented by one (1) if cbDestScan is negative (Rotated left 90 degree)
|
||
2. Decremented by one (1) if cbDestScan is positive (Rotated right 90 degree)
|
||
|
||
Author:
|
||
|
||
22-Dec-1993 Wed 13:46:01 created -by- DC
|
||
|
||
24-Dec-1993 Fri 04:58:24 updated -by- DC
|
||
Fixed the RemainBits problem, we have to shift final data left if the
|
||
cySrc is already exhausted and RemainBits is not zero.
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
LPDWORD pdwTP8x8;
|
||
LPBYTE pSrc;
|
||
TPINFO TPInfo;
|
||
INT RemainBits;
|
||
INT cbNextDest;
|
||
union {
|
||
BYTE b[8];
|
||
DWORD dw[2];
|
||
} TPData;
|
||
|
||
|
||
|
||
TPInfo = *pTPInfo;
|
||
TPInfo.DestXStart &= 0x07;
|
||
|
||
PLOTASSERT(1, "cbDestScan is not big enough (%ld)",
|
||
(DWORD)(ABS(TPInfo.cbDestScan)) >=
|
||
(DWORD)((TPInfo.cySrc + TPInfo.DestXStart + 7) >> 3),
|
||
TPInfo.cbDestScan);
|
||
//
|
||
// Make sure we have the required transpose translate table. If we don't
|
||
// get one built.
|
||
//
|
||
|
||
if (!(pdwTP8x8 = (LPDWORD)pTPInfo->pPDev->pTransPosTable)) {
|
||
|
||
if (!(pdwTP8x8 = Build8x8TransPosTable())) {
|
||
|
||
PLOTERR(("TransPos1BPP: Build 8x8 transpos table failed"));
|
||
return(FALSE);
|
||
}
|
||
|
||
pTPInfo->pPDev->pTransPosTable = (LPVOID)pdwTP8x8;
|
||
}
|
||
|
||
//
|
||
// set up all required parameters, and start TPData with 0s
|
||
//
|
||
|
||
pSrc = TPInfo.pSrc;
|
||
RemainBits = (INT)(7 - TPInfo.DestXStart);
|
||
cbNextDest = (INT)((TPInfo.cbDestScan > 0) ? 1 : -1);
|
||
TPData.dw[0] =
|
||
TPData.dw[1] = 0;
|
||
|
||
while (TPInfo.cySrc--) {
|
||
|
||
LPDWORD pdwTmp;
|
||
LPBYTE pbTmp;
|
||
|
||
//
|
||
// Translate a byte to 8 bytes with each bit corresponding to each byte
|
||
// each byte is shifted to the left by 1 before combining with the new
|
||
// bit.
|
||
//
|
||
|
||
pdwTmp = pdwTP8x8 + ((UINT)*pSrc << 1);
|
||
TPData.dw[0] = (TPData.dw[0] << 1) | *(pdwTmp + 0);
|
||
TPData.dw[1] = (TPData.dw[1] << 1) | *(pdwTmp + 1);
|
||
pSrc += TPInfo.cbSrcScan;
|
||
|
||
//
|
||
// Check to see if we are done with source scan lines. If this is the
|
||
// case we need to possible shift the transposed scan lines by the
|
||
// apropriate number based on RemainBits.
|
||
//
|
||
|
||
if (!TPInfo.cySrc) {
|
||
|
||
//
|
||
// We are done, check to see if we need to shift the resultant
|
||
// transposed scan lines.
|
||
//
|
||
|
||
if (RemainBits) {
|
||
|
||
TPData.dw[0] <<= RemainBits;
|
||
TPData.dw[1] <<= RemainBits;
|
||
|
||
RemainBits = 0;
|
||
}
|
||
}
|
||
|
||
if (RemainBits--) {
|
||
|
||
NULL;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Save the current result to the output destination scan buffer.
|
||
// Unwind the processing, to give the compiler a chance to generate
|
||
// some fast code, rather that relying on a while loop.
|
||
//
|
||
|
||
*(pbTmp = TPInfo.pDest ) = TPData.b[0];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[1];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[2];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[3];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[4];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[5];
|
||
*(pbTmp += TPInfo.cbDestScan) = TPData.b[6];
|
||
*(pbTmp + TPInfo.cbDestScan) = TPData.b[7];
|
||
|
||
//
|
||
// Reset RemainBits back to 7, TPData back to 0 and and advance to
|
||
// the next destination
|
||
//
|
||
|
||
RemainBits = 7;
|
||
TPData.dw[0] =
|
||
TPData.dw[1] = 0;
|
||
TPInfo.pDest += cbNextDest;
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// Since we succeded in transposing the bitmap, the next source byte
|
||
// location must be incremented or decremented by one.
|
||
//
|
||
// The cbNextDest is 1 if the bitmap is rotated to the right 90 degrees, so
|
||
// we want to decrement by 1.
|
||
//
|
||
// The cbNextDest is -1 if the bitmap is rotated to the right 90 degrees, so
|
||
// we want to increment by 1.
|
||
//
|
||
|
||
pTPInfo->pSrc -= cbNextDest;
|
||
|
||
return(TRUE);
|
||
}
|
||
|