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.
477 lines
12 KiB
477 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1990-2003 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
|
|
|
|
|
|
[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
|
|
|
|
|
|
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
|
|
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
|
|
|
|
|
|
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
|
|
|
|
24-Dec-1993 Fri 04:58:24 updated
|
|
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);
|
|
}
|