Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1813 lines
49 KiB

/*++
Copyright (c) 1990-1991 Microsoft Corporation
Module Name:
htrender.c
Abstract:
This module contains all low levels halftone rendering functions.
Author:
22-Jan-1991 Tue 12:49:03 created -by- Daniel Chou (danielc)
[Environment:]
GDI Device Driver - Halftone.
[Notes:]
Revision History:
--*/
#define DBGP_VARNAME dbgpHTRender
#include "htp.h"
#include "htmapclr.h"
#include "htstret.h"
#include "htpat.h"
#include "htgetbmp.h"
#include "htsetbmp.h"
#include "htrender.h"
#include "limits.h"
#define DBGP_CALLBACK 0x0001
#define DBGP_RENDERFUNCS 0x0002
#define DBGP_FREE_MEM 0x0004
#define DBGP_BFINFO 0x0008
DEF_DBGPVAR(BIT_IF(DBGP_CALLBACK, 0) |
BIT_IF(DBGP_RENDERFUNCS, 0) |
BIT_IF(DBGP_FREE_MEM, 0) |
BIT_IF(DBGP_BFINFO, 0))
extern RGBORDER RGBOrderTable[PRIMARY_ORDER_MAX + 1];
#if DBG
CHAR *pBMFName[] = { "BMF_DEVICE",
"BMF_1BPP",
"BMF_4BPP",
"BMF_8BPP",
"BMF_16BPP",
"BMF_24BPP",
"BMF_32BPP",
"BMF_64BPP",
"BMF_4RLE",
"BMF_8RLE" };
CHAR *pCallBackModeStr[] = { "SRC <-- ",
"MASK <-- ",
"DEST <-- ",
" DEST -->",
"XLAT <--->" };
CHAR *pInFuncName[] = { "BMF1_ToPrimMono",
"BMF4_ToPrimMono",
"BMF8_ToPrimMono",
"BMF1_ToPrimColor",
"BMF4_ToPrimColor",
"BMF8_ToPrimColor",
"BMF16_xx0_ToPrimMono",
"BMF16_xyz_ToPrimMono",
"BMF16_xx0_ToPrimColorGRAY",
"BMF16_xyz_ToPrimColorGRAY",
"BMF16_ToPrimColor",
"BMF24_888_ToPrimMono",
"BMF24_888_ToPrimColorGRAY",
"BMF24_888_ToPrimColor",
"BMF32_xx0_ToPrimMono",
"BMF32_xyz_ToPrimMono",
"BMF32_xx0_ToPrimColorGRAY",
"BMF32_xyz_ToPrimColorGRAY",
"BMF32_ToPrimColor" };
CHAR *OutputFuncStr[] = { "SingleCountOutputTo3Planes",
"VarCountOutputTo3Planes",
"SingleCountOutputTo1BPP",
"VarCountOutputTo1BPP",
"SingleCountOutputTo4BPP",
"VarCountOutputTo4BPP",
"SingleCountOutputToVGA16",
"VarCountOutputToVGA16",
"SingleCountOutputToVGA256",
"VarCountOutputToVGA256",
"SingleCountOutputTo16BPP_555",
"VarCountOutputTo16BPP_555" };
#endif
#define MASK_DEST_EDGE(pD, pS, Mask) \
*(pD)=(BYTE)((BYTE)(*(pD)&(Mask))|(BYTE)(*(pS)&(BYTE)~(Mask)))
#define COPY_FULLBYTES(pD, pS, Size) { INT SizeCopied; \
while ((Size)) { \
SizeCopied=(LONG)(((Size)>(LONG)(INT_MAX))?INT_MAX:(Size)); \
CopyMemory((pD), (pS), SizeCopied); \
(pD)+=SizeCopied; (pS)+=SizeCopied; (Size)-=SizeCopied; }}
#define BF_INPUTFUNC_START (((BMF_32BPP - BMF_1BPP + 1) * 2) + \
(BMF_32BPP - BMF_16BPP + 1))
static INPUTFUNC InputFuncTable[] = {
(INPUTFUNC)BMF1_ToPrimMono,
(INPUTFUNC)BMF4_ToPrimMono,
(INPUTFUNC)BMF8_ToPrimMono,
(INPUTFUNC)BMF1_ToPrimColor,
(INPUTFUNC)BMF4_ToPrimColor,
(INPUTFUNC)BMF8_ToPrimColor,
(INPUTFUNC)BMF16_xx0_ToPrimMono,
(INPUTFUNC)BMF16_xyz_ToPrimMono,
(INPUTFUNC)BMF16_xx0_ToPrimColorGRAY,
(INPUTFUNC)BMF16_xyz_ToPrimColorGRAY,
(INPUTFUNC)BMF16_ToPrimColor,
(INPUTFUNC)BMF24_888_ToPrimMono,
(INPUTFUNC)BMF24_888_ToPrimColorGRAY,
(INPUTFUNC)BMF24_888_ToPrimColor,
(INPUTFUNC)BMF32_xx0_ToPrimMono,
(INPUTFUNC)BMF32_xyz_ToPrimMono,
(INPUTFUNC)BMF32_xx0_ToPrimColorGRAY,
(INPUTFUNC)BMF32_xyz_ToPrimColorGRAY,
(INPUTFUNC)BMF32_ToPrimColor
};
static OUTPUTFUNC OutputFuncTable[] = {
(OUTPUTFUNC)SingleCountOutputTo3Planes,
(OUTPUTFUNC)VarCountOutputTo3Planes,
(OUTPUTFUNC)SingleCountOutputTo1BPP,
(OUTPUTFUNC)VarCountOutputTo1BPP,
(OUTPUTFUNC)SingleCountOutputTo4BPP,
(OUTPUTFUNC)VarCountOutputTo4BPP,
(OUTPUTFUNC)SingleCountOutputToVGA16,
(OUTPUTFUNC)VarCountOutputToVGA16,
(OUTPUTFUNC)SingleCountOutputToVGA256,
(OUTPUTFUNC)VarCountOutputToVGA256,
(OUTPUTFUNC)SingleCountOutputTo16BPP_555,
(OUTPUTFUNC)VarCountOutputTo16BPP_555
};
LONG
HTENTRY
HalftoneBitmap(
PHR_HEADER pHR_Header
)
/*++
Routine Description:
This function read the 1/4/8/24 bits per pel source bitmap and composed it
(compress or expand if necessary) into PRIMCOLOR data structures array for
later halftone rendering.
Arguments:
pHalftoneRender - Pointer to the HALFTONERENDER data structure.
Return Value:
The return value will be < 0 if an error encountered else it will be
1L.
Author:
24-Jan-1991 Thu 11:47:08 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
HALFTONERENDER HR;
LPBYTE pCurPat;
LONG Result;
DWORD SizePatYBand;
LPWORD pAbort;
UINT *pYLines;
UINT Lines[3];
UINT Loop;
UINT PatCurY;
UINT PatYWrapCount;
WORD Abort = 0;
BOOL HasSrcMask;
//
// Set debug timer if we need to compute the halftone render elapse time
//
DBG_ELAPSETIME(&pHR_Header->DbgTimer);
//========================================================================
// Start of halftone render various parameters setup
//========================================================================
#if 0
DBGP("HR = %u bytes + DEVCLRADJ = %u bytes = %u bytes"
ARGU(sizeof(HALFTONERENDER))
ARGU(sizeof(DEVCLRADJ))
ARGU(sizeof(HALFTONERENDER) + sizeof(DEVCLRADJ)));
#endif
ZeroMemory((LPBYTE)&HR, sizeof(HALFTONERENDER));
HR.HR_Header = *pHR_Header;
HR.HTCallBackFunction = HR.HR_Header.pDeviceColorInfo->HTCallBackFunction;
//
// Validate HTSurfaceInfo and set the CBParams accordingly, the QUERY_SRC
// must done after the QUERY_DEST is done, so we will know how to composed
// the source
//
if ((Result = ValidateHTSI(&HR, HTCALLBACK_QUERY_DEST)) < 0) {
return(Result);
}
if ((Result = ValidateHTSI(&HR, HTCALLBACK_QUERY_SRC_MASK)) < 0) {
return(Result);
}
if ((Result = ValidateHTSI(&HR, HTCALLBACK_QUERY_SRC)) < 0) {
return(Result);
}
//
// Setup stretch information first
//
if (((Result = RenderStretchSetup(&HR)) <= 0L) ||
((Result = CreateDyesColorMappingTable((PHALFTONERENDER)&HR)) <= 0L) ||
((Result = CachedHalftonePattern((PHALFTONERENDER)&HR)) <= 0L)) {
FreeHRMemory((PHALFTONERENDER)&HR);
return(Result);
}
//
// If not Pattern Solid Fill then figure out the source/destination bitmap
// input/output functions and also initialize all input/output bitmap's
// function parameters
//
HR.InFuncInfo.ColorInfoIncrement = HR.XStretch.ColorInfoIncrement;
HR.InFuncInfo.BMF1BPP1stShift = HR.XStretch.BMF1BPPOffsetByteBitShift;
HR.InFuncInfo.Flags = (BYTE)(((HR.XStretch.Flags &
SIF_GET_FIRST_SOURCE_BYTE) ?
IFIF_GET_FIRST_BYTE : 0x00) |
((HR.InputSI.Flags &
ISIF_HAS_SRC_MASK) ?
IFIF_HAS_SRC_MASK : 0x00) |
((HR.XStretch.StretchMode ==
(BYTE)STRETCH_MODE_COMPRESSED) ?
0x00 : IFIF_XCOUNT_IS_ONE));
HR.OutFuncInfo.UnUsed = (WORD)(HR.YStretch.PatternAlign & 0x01);
HR.OutFuncInfo.PatWidthBytes = HR.OutputSI.Pattern.WidthBytes;
HR.SrcMaskInfo.FirstSrcMaskSkips = HR.XStretch.FirstSrcMaskSkips;
HR.SrcMaskInfo.SourceMask = HR.XStretch.SrcMaskOffsetMask;
if (HR.OutputSI.DestCBParams.SurfaceFormat == BMF_1BPP) {
HR.SrcMaskInfo.OffsetCount = (BYTE)offsetof(PRIMMONO_COUNT, Count);
HR.SrcMaskInfo.OffsetPrim1 = (BYTE)offsetof(PRIMMONO_COUNT, Mono.Prim1);
} else {
HR.SrcMaskInfo.OffsetCount = (BYTE)offsetof(PRIMCOLOR_COUNT, Count);
HR.SrcMaskInfo.OffsetPrim1 = (BYTE)offsetof(PRIMCOLOR_COUNT, Color.Prim1);
}
if (HR.InFuncInfo.Flags & IFIF_XCOUNT_IS_ONE) {
HR.SrcMaskInfo.OffsetCount = SMI_XCOUNT_IS_ONE;
}
HR.SrcMaskInfo.ColorInfoIncrement = HR.XStretch.ColorInfoIncrement;
HR.SrcMaskInfo.StretchSize = HR.XStretch.Ratio.StretchSize;
//
// If we need to translate a 32-bit pel format to a 24-bit pel RGB
// format then we need to use BMF_24BPPToPrimXXX function
//
HR.InputFunc = InputFuncTable[HR.BFInfo.InFuncIndex];
DBGP_IF(DBGP_RENDERFUNCS, DBGP("Bitmap INPUT Functions: %s"
ARG(pInFuncName[HR.BFInfo.InFuncIndex])));
switch(HR.OutputSI.DestCBParams.SurfaceFormat) {
case BMF_1BPP_3PLANES:
Loop = 0;
break;
case BMF_1BPP:
Loop = 2;
break;
case BMF_4BPP:
Loop = 4;
break;
case BMF_4BPP_VGA16:
Loop = 6;
break;
case BMF_8BPP_VGA256:
Loop = 8;
break;
case BMF_16BPP_555:
Loop = 10;
break;
}
if (HR.XStretch.StretchMode == STRETCH_MODE_EXPANDED) {
++Loop;
}
HR.OutputFunc = OutputFuncTable[Loop];
DBGP_IF(DBGP_RENDERFUNCS, DBGP("Bitmap OUTPUT Functions: %s"
ARG(OutputFuncStr[Loop])));
//========================================================================
// End of halftone render various parameters setup
//========================================================================
ASSERT((STRETCH_MODE_ONE_TO_ONE == 0) &&
(STRETCH_MODE_COMPRESSED == 1) &&
(STRETCH_MODE_EXPANDED == 2));
SizePatYBand = (DWORD)HR.OutputSI.DestCBParams.BytesPerScanLine *
(DWORD)HR.OutputSI.Pattern.Height;
//
// Assume one-to-one ratio
//
Lines[STRETCH_MODE_ONE_TO_ONE] =
Lines[STRETCH_MODE_COMPRESSED] =
Lines[STRETCH_MODE_EXPANDED ] = 1;
pYLines = (UINT *)&Lines[HR.YStretch.StretchMode];
*pYLines = (UINT)HR.YStretch.Ratio.First;
pCurPat = HR.OutputSI.Pattern.pCachedPattern;
PatCurY = (UINT)HR.OutputSI.Pattern.Height;
HasSrcMask = (BOOL)(HR.InputSI.Flags & ISIF_HAS_SRC_MASK);
pAbort = HR.HR_Header.pBitbltParams->pAbort;
while (HR.YStretch.Ratio.StretchSize--) {
if ((pAbort) && (*pAbort)) {
return(HTERR_HALFTONE_INTERRUPTTED);
}
//
// Make it temp stopper, so that input function will not run over
// by one
//
if (HasSrcMask) {
HR.CAOTBAInfo.Flags |= (BYTE)CAOTBAF_COPY;
Loop = Lines[STRETCH_MODE_COMPRESSED];
while (Loop--) {
if (!QUERIED_CBSCANLINES(HR.InputSI.SrcMaskCBParams)) {
if ((Result = DoHTCallBack(HTCALLBACK_QUERY_SRC_MASK,
&HR)) <= 0) {
return(Result);
}
}
CopyAndOrTwoByteArray(HR.InputSI.pSrcMaskLine,
HR.InputSI.SrcMaskCBParams.pPlane,
HR.CAOTBAInfo);
NEXT_SCANLINE(HR.InputSI.SrcMaskCBParams);
HR.CAOTBAInfo.Flags &= (BYTE)~CAOTBAF_COPY;
}
SetSourceMaskToPrim1(HR.InputSI.pSrcMaskLine,
HR.pColorInfo[PCI_INPUT_INDEX],
HR.SrcMaskInfo);
}
Loop = Lines[STRETCH_MODE_COMPRESSED];
while (--Loop) {
if (!QUERIED_CBSCANLINES(HR.InputSI.SrcCBParams)) {
if ((Result = DoHTCallBack(HTCALLBACK_QUERY_SRC, &HR)) <= 0) {
return(Result);
}
}
NEXT_SCANLINE(HR.InputSI.SrcCBParams);
}
if (!QUERIED_CBSCANLINES(HR.InputSI.SrcCBParams)) {
if ((Result = DoHTCallBack(HTCALLBACK_QUERY_SRC, &HR)) <= 0) {
return(Result);
}
}
HR.InputFunc(HR.InputSI.SrcCBParams.pPlane,
(PPRIMMONO_COUNT)HR.pColorInfo[PCI_INPUT_INDEX],
(LPBYTE)HR.InputSI.pPrimMappingTable,
HR.InFuncInfo);
NEXT_SCANLINE(HR.InputSI.SrcCBParams);
//
// Doing output now, we must releas old input stopper at here
//
PatYWrapCount = (UINT)HR.OutputSI.Pattern.Height;
Loop = Lines[STRETCH_MODE_EXPANDED];
while (Loop--) {
if (!QUERIED_CBSCANLINES(HR.OutputSI.DestCBParams)) {
if ((Result = DoHTCallBack(HTCALLBACK_QUERY_DEST, &HR)) <= 0) {
return(Result);
}
//
// Must reset it, so we do not duplicate on the destination
// which already flushed.
//
PatYWrapCount = (UINT)HR.OutputSI.Pattern.Height;
}
if (PatYWrapCount) {
--PatYWrapCount;
HR.OutputFunc((PPRIMCOLOR_COUNT)HR.pColorInfo[PCI_HEAP_INDEX],
HR.OutputSI.DestCBParams.pPlane,
pCurPat,
HR.OutFuncInfo);
} else {
LPBYTE pPlane = HR.OutputSI.DestCBParams.pPlane;
LPBYTE pPlaneCopy;
LPBYTE pPlaneLast;
INT PlaneCount = (INT)HR.OutputSI.TotalDestPlanes;
LONG DestFullByteSize;
while (PlaneCount--) {
pPlaneLast = (pPlaneCopy = pPlane) - SizePatYBand;
if (HR.XStretch.DestEdge.FirstByteMask) {
MASK_DEST_EDGE(pPlaneCopy,
pPlaneLast,
HR.XStretch.DestEdge.FirstByteMask);
++pPlaneLast;
++pPlaneCopy;
}
if (DestFullByteSize = HR.XStretch.DestFullByteSize) {
COPY_FULLBYTES(pPlaneCopy,
pPlaneLast,
DestFullByteSize);
}
if (HR.XStretch.DestEdge.LastByteMask) {
MASK_DEST_EDGE(pPlaneCopy,
pPlaneLast,
HR.XStretch.DestEdge.LastByteMask);
}
pPlane += HR.OutFuncInfo.BytesPerPlane;
}
}
HR.OutFuncInfo.UnUsed ^= 0x01;
NEXT_SCANLINE(HR.OutputSI.DestCBParams);
if (--PatCurY) {
pCurPat += HR.OutputSI.Pattern.WidthBytes;
} else {
pCurPat = HR.OutputSI.Pattern.pCachedPattern;
PatCurY = (UINT)HR.OutputSI.Pattern.Height;
}
}
//
// Figure out next stretch's composition
//
if (HR.YStretch.Ratio.StretchSize <= 1) {
*pYLines = (UINT)HR.YStretch.Ratio.Last;
} else if (HR.YStretch.Ratio.Single) {
*pYLines = (UINT)HR.YStretch.Ratio.Single;
} else {
if ((HR.YStretch.Ratio.Error += HR.YStretch.Ratio.Add) >= 0) {
HR.YStretch.Ratio.Error -= HR.YStretch.Ratio.Sub;
*pYLines = (UINT)HR.YStretch.Ratio.MaxFactor;
} else {
*pYLines = (UINT)HR.YStretch.Ratio.MinFactor;
}
}
}
return(DoHTCallBack(HTCALLBACK_SET_DEST, &HR));
}
LONG
HTENTRY
DoHTCallBack(
UINT HTCallBackMode,
PHALFTONERENDER pHR
)
/*++
Routine Description:
This function calcuate the halftone callback parameters and callback to
the caller for query source/destination or set the destination.
Arguments:
HTCallBackMode - Specified the halftone callback mode, it can be one
of the following
HTCALLBACK_QUERY_SRC
HTCALLBACK_QUERY_SRC_MASK
HTCALLBACK_QUERY_DEST
HTCALLBACK_SET_DEST
The HTCALLBACK_SET_DEST must be the very last call
to this function, other query destination calls will
automatically set the destination if necessary.
pHR - Pointer to the HALFTONERENDER data structure.
Return Value:
If the return value is less than 1L then it indicate an error code (ie.
HTERR_xxxxx) otherwise it return 1L to indicate function sucessful.
NOTE: 1) The AvailableScanLines (QUERIED_CBSCANLINES(CBParams)) will be
decrement by 1 to fit into caller's post decrement schemes, if
the caller's functions changed then this decrement by 1 may need
to changed.
2) If an error occurred or last SET_DEST is called then the
FreeHRMemory() is caller to release all memory associate with the
halftone rendering process.
3) The last HTCALLBACK_SET_DEST call return the total destination
scan lines queried from this function.
Author:
23-Apr-1992 Thu 20:01:55 updated -by- Daniel Chou (danielc)
changed 'CHAR' type to 'SHORT' type, this will make sure if compiled
under MIPS the default 'unsigned char' will not affect the signed
operation.
14-Feb-1991 Thu 09:51:54 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PHTCALLBACKPARAMS pCBParams;
HTCALLBACKPARAMS CBParams;
PHTCALLBACKPARAMS pSetDestCBParams = NULL;
LONG BytesPerScanLine;
LONG ByteOffset;
WORD ScanCount;
BOOL DirBackward;
static SHORT ErrorCodes[] = { HTERR_QUERY_SRC_BITMAP_FAILED,
HTERR_QUERY_SRC_MASK_FAILED,
HTERR_QUERY_DEST_BITMAP_FAILED };
switch(HTCallBackMode) {
case HTCALLBACK_QUERY_SRC:
pCBParams = &(pHR->InputSI.SrcCBParams);
ByteOffset = pHR->XStretch.SrcByteOffset;
break;
case HTCALLBACK_QUERY_SRC_MASK:
pCBParams = &(pHR->InputSI.SrcMaskCBParams);
ByteOffset = pHR->XStretch.SrcMaskByteOffset;
break;
case HTCALLBACK_QUERY_DEST:
case HTCALLBACK_SET_DEST:
if (pHR->OutputSI.DestCBParams.MaximumQueryScanLines) {
pSetDestCBParams = &(pHR->OutputSI.SetDestCBParams);
if (pSetDestCBParams->CallBackMode == HTCALLBACK_QUERY_DEST) {
//
// Not first time
//
pSetDestCBParams->CallBackMode = HTCALLBACK_SET_DEST;
DBGP_IF(DBGP_CALLBACK,
DBGP(" %s %4ld-%4ld (%4ld/%4ld) %p"
ARG(pCallBackModeStr[HTCALLBACK_SET_DEST])
ARGDW(pSetDestCBParams->ScanStart)
ARGDW(pSetDestCBParams->ScanStart +
pSetDestCBParams->ScanCount - 1)
ARGDW(pSetDestCBParams->ScanCount)
ARGDW(pSetDestCBParams->RemainedSize)
ARGDW(pSetDestCBParams->pPlane)));
if (!pHR->HTCallBackFunction(pSetDestCBParams)) {
FreeHRMemory(pHR);
return(HTERR_SET_DEST_BITMAP_FAILED);
}
}
}
if (HTCallBackMode == HTCALLBACK_SET_DEST) {
return((FreeHRMemory(pHR)) ? (LONG)pHR->YStretch.DestExtend :
(LONG)HTERR_CANNOT_DEALLOCATE_MEMORY);
}
pCBParams = &(pHR->OutputSI.DestCBParams);
ByteOffset = pHR->XStretch.DestByteOffset;
}
CBParams = *pCBParams;
if (CBParams.RemainedSize <= 0) {
ASSERT(CBParams.RemainedSize > 0);
return(INTERR_STRETCH_NEG_OVERHANG);
}
if (!(ScanCount = CBParams.MaximumQueryScanLines)) {
--ScanCount;
}
if ((LONG)ScanCount > CBParams.RemainedSize) {
ScanCount = (WORD)CBParams.RemainedSize;
}
//
// NOTE: The CBParams.BytesPerScanLine may be negative, it is total bytes
// to next scan line so if the target surface is going backward then
// this value will be negative, when callback to the caller we will
// always make this value is a total bytes of one scan line. (> 0)
//
if (DirBackward = (BOOL)(CBParams.BytesPerScanLine < 0)) {
CBParams.ScanStart -= (LONG)(ScanCount - 1);
CBParams.BytesPerScanLine = -CBParams.BytesPerScanLine;
}
BytesPerScanLine = CBParams.BytesPerScanLine;
ASSERTMSG("Scan Start is less than 0", CBParams.ScanStart >= 0);
//
// Say we asking this many scan lines
//
CBParams.ScanCount = ScanCount;
if (pSetDestCBParams) {
*pSetDestCBParams = CBParams; // snap shot
}
if (CBParams.MaximumQueryScanLines) {
LONG RemainedSize = CBParams.RemainedSize; // remember these
LONG ScanStart = CBParams.ScanStart;
if (!pHR->HTCallBackFunction((PHTCALLBACKPARAMS)&CBParams)) {
FreeHRMemory(pHR);
return((LONG)ErrorCodes[HTCallBackMode]);
}
if (CBParams.ScanCount != ScanCount) {
DBGP_IF(DBGP_CALLBACK,
DBGP("Return DIFF ScanCount=%ld (%ld), ScanStart=%ld (%ld)"
ARGDW(CBParams.ScanCount)
ARGDW(ScanCount)
ARGDW(CBParams.ScanStart)
ARGDW(ScanStart)));
//
// Make sure 'ScanStart' still valid
//
if (DirBackward) {
ScanStart -= (LONG)CBParams.ScanCount - (LONG)ScanCount;
pCBParams->ScanStart = ScanStart;
}
if ((!CBParams.ScanCount) ||
((LONG)CBParams.ScanCount > RemainedSize) ||
(ScanStart < 0) ||
(CBParams.ScanStart != ScanStart)) {
FreeHRMemory(pHR);
return(HTERR_QUERY_DEST_BITMAP_FAILED);
}
ScanCount = CBParams.ScanCount;
if (pSetDestCBParams) {
pSetDestCBParams->ScanStart = ScanStart;
pSetDestCBParams->ScanCount = ScanCount;
}
}
} else {
//
// Since we did not callback, we must calulate the correct starting
// address, to do that we just add in the starting offset to the
// current scan line byte offset, note: we will never do a set
// destination if the destination were never queried.
//
ByteOffset += CBParams.ScanStart * BytesPerScanLine;
}
//
// The reason for minus 1 is that the caller is inside the loop and it
// do a post decrement to the AvailableScanLines so when we returned it
// should decrement by 1 to fit into post decrement schemes.
//
pCBParams->ScanCount = ScanCount - (WORD)1;
pCBParams->RemainedSize -= (LONG)ScanCount;
if (pSetDestCBParams) {
pSetDestCBParams->pPlane = CBParams.pPlane;
}
if (DirBackward) {
ByteOffset += (LONG)(ScanCount - 1) * BytesPerScanLine;
pCBParams->ScanStart -= (LONG)ScanCount;
} else {
pCBParams->ScanStart += (LONG)ScanCount;
}
pCBParams->pPlane = CBParams.pPlane + ByteOffset;
DBGP_IF(DBGP_CALLBACK,
DBGP("%s%s %4ld-%4ld (%4ld/%4ld) %p"
ARG((pCBParams->MaximumQueryScanLines) ? " " : "*")
ARG(pCallBackModeStr[CBParams.CallBackMode])
ARGDW(CBParams.ScanStart)
ARGDW(CBParams.ScanStart + CBParams.ScanCount - 1)
ARGDW(CBParams.ScanCount)
ARGDW(pCBParams->RemainedSize)
ARGDW(pCBParams->pPlane)));
return(1L);
}
BOOL
HTENTRY
FreeHRMemory(
PHALFTONERENDER pHalftoneRender
)
/*++
Routine Description:
This function free all the allocated memory which its pointer stored in
the HALFTONERENDER data structure.
Arguments:
pHalftoneRender - pointer to the HALFTONERENDER data structure
Return Value:
True if all the memory deallocated, or false if can not freed the allocated
memory
Author:
20-Feb-1991 Wed 12:10:13 created -by- Daniel Chou (danielc)
02-Feb-1994 Wed 18:39:24 updated -by- Daniel Chou (danielc)
Re-write so that after it free the memory it will NULL out the pointer
Revision History:
--*/
{
LPBYTE pMem;
BOOL Ok = TRUE;
//
// Free all allocated memories
//
if (pMem = (LPBYTE)pHalftoneRender->pColorInfo[PCI_HEAP_INDEX]) {
if (HTLocalFree((HLOCAL)pMem)) {
Ok = FALSE;
DBGP("FreeMemory: Cannot deallocate PCI_HEAP_INDEX");
} else {
pHalftoneRender->pColorInfo[PCI_HEAP_INDEX] = NULL;
}
}
if (pMem = (LPBYTE)pHalftoneRender->InputSI.pSrcMaskLine) {
if (HTLocalFree((HLOCAL)pMem)) {
Ok = FALSE;
DBGP("FreeMemory: Cannot deallocate pSrcMaskLine");
} else {
pHalftoneRender->InputSI.pSrcMaskLine = NULL;
}
}
if (pMem = (LPBYTE)pHalftoneRender->OutputSI.Pattern.pCachedPattern) {
if (HTLocalFree((HLOCAL)pMem)) {
Ok = FALSE;
DBGP("FreeMemory: Cannot deallocate pCachedPattern");
} else {
pHalftoneRender->OutputSI.Pattern.pCachedPattern = NULL;
}
}
if (pMem = (LPBYTE)pHalftoneRender->InputSI.pPrimMappingTable) {
if (HTLocalFree((HLOCAL)pMem)) {
Ok = FALSE;
DBGP("FreeMemory: Cannot deallocate pPrimMappingTable");
} else {
pHalftoneRender->InputSI.pPrimMappingTable = NULL;
}
}
return(Ok);
}
BOOL
HTENTRY
ValidateRGBBitFields(
PBFINFO pBFInfo
)
/*++
Routine Description:
This function determined the RGB primary order from the RGB bit fields
Arguments:
pBFInfo - Pointer to the BFINFO data structure, following field must
set before the call
BitsRGB[0] = Red Bits
BitsRGB[1] = Green Bits
BitsRGB[2] = Blue Bits
BitmapFormat = BMF_16BPP/BMF_24BPP/BMF_32BPP
RGB1stBit = Specifed PRIMARY_ORDER_xxx ONLY for BMF_1BPP,
BMF_4BPP, BMF_8BPP, BMF_24BPP
requested order.
Return Value:
FALSE if BitsRGB[] or BitmapFormat passed are not valid
else TRUE and following fields are returned
BitsRGB[] - corrected mask bits
BitmapFormat - BMF_16BPP/BMF_24BPP/BMF_32BPP
Flags - BFIF_xxxx
SizeLUT - Size of LUT table
BitStart[] - Starting bits for each of RGB
BitCount[] - Bits Count for each of RGB
RGBOrder - Current RGB order, for BMF_1BPP, BMF_4BPP, BMF_8BPP
and BMF_24BPP the RGBOrder.Index must specified a
PRIMARY_ORDER_xxx, for BMF_16BPP, BMF_32BPP the
RGBOrder.Index will be set by this function
RGB1stBit - The bit start for first on bit in BitsRGB[]
GrayShr[] - The right shift count so that most significant bit
of each RGB color is aligned to bit 7 if the total
bit count of RGB is greater than 8 otherwise this
value is 0, it is used when construct the monochrome
Y value.
Author:
03-Mar-1993 Wed 12:33:22 created -by- Daniel Chou (danielc)
Revision History:
06-Apr-1993 Tue 12:15:58 updated -by- Daniel Chou (danielc)
Add 24bpp support for any other order than BGR
--*/
{
BFINFO BFInfo = *pBFInfo;
DWORD PrimBits;
INT Index;
INT GrayShr[3];
BYTE BitCount;
BYTE BitStart;
BFInfo.Flags &= (BFIF_MONO_OUTPUT | BFIF_DEST_1BPP);
BFInfo.SizeLUT = (WORD)LUTSIZE_MONO;
BFInfo.GrayShr[0] =
BFInfo.GrayShr[1] =
BFInfo.GrayShr[2] = 0;
switch (BFInfo.BitmapFormat) {
case BMF_1BPP:
case BMF_4BPP:
case BMF_8BPP:
case BMF_24BPP:
BFInfo.RGBOrder = RGBOrderTable[BFInfo.RGBOrder.Index];
BFInfo.BitCount[0] =
BFInfo.BitCount[1] =
BFInfo.BitCount[2] = 8;
PrimBits = (DWORD)0x000000ff;
BitStart = 0;
for (Index = 0; Index < 3; Index++) {
BitCount = BFInfo.RGBOrder.Order[Index];
BFInfo.BitsRGB[BitCount] = PrimBits;
BFInfo.BitStart[BitCount] = BitStart;
PrimBits <<= 8;
BitStart += 8;
}
if (BFInfo.BitmapFormat == BMF_24BPP) {
if (BFInfo.Flags & BFIF_DEST_1BPP) {
BFInfo.InFuncIndex = (BYTE)IDXIF_BMF24BPP_START;
} else if (BFInfo.Flags & BFIF_MONO_OUTPUT) {
BFInfo.InFuncIndex = (BYTE)(IDXIF_BMF24BPP_START + 1);
} else {
BFInfo.SizeLUT = (WORD)LUTSIZE_CLR_24BPP;
BFInfo.InFuncIndex = (BYTE)(IDXIF_BMF24BPP_START + 2);
}
} else {
BFInfo.SizeLUT = 0;
BFInfo.InFuncIndex = (BYTE)((IDXIF_BMF1BPP_START) +
(BFInfo.BitmapFormat - BMF_1BPP) +
((BFInfo.Flags & BFIF_DEST_1BPP) ? 0 :
3));
}
break;
case BMF_16BPP:
BFInfo.BitsRGB[0] &= 0xffff;
BFInfo.BitsRGB[1] &= 0xffff;
BFInfo.BitsRGB[2] &= 0xffff;
//
// FALL THROUGH to compute
//
case BMF_32BPP:
//
// The bit fields cannot be overlaid
//
if (!(BFInfo.BitsRGB[0] | BFInfo.BitsRGB[1] | BFInfo.BitsRGB[2])) {
DBGP_IF(DBGP_BFINFO, DBGP("ERROR: BitsRGB[] all zeros"));
return(FALSE);
}
if ((BFInfo.BitsRGB[0] & BFInfo.BitsRGB[1]) ||
(BFInfo.BitsRGB[0] & BFInfo.BitsRGB[2]) ||
(BFInfo.BitsRGB[1] & BFInfo.BitsRGB[2])) {
DBGP_IF(DBGP_BFINFO,
DBGP("ERROR: BitsRGB[] Overlay: %08lx:%08lx:%08lx"
ARGDW(BFInfo.BitsRGB[0])
ARGDW(BFInfo.BitsRGB[1])
ARGDW(BFInfo.BitsRGB[2])));
return(FALSE);
}
//
// Now Check the bit count, we will allowed bit count to be 0
//
for (Index = 0; Index < 3; Index++) {
BitStart =
BitCount = 0;
if (PrimBits = BFInfo.BitsRGB[Index]) {
while (!(PrimBits & 0x01)) {
PrimBits >>= 1; // get to the first bit
++BitStart;
}
do {
++BitCount;
} while ((PrimBits >>= 1) & 0x01);
if (PrimBits) {
//
// The bit fields is not contiguous
//
DBGP_IF(DBGP_BFINFO,
DBGP("ERROR: BitsRGB[%u]=%08lx is not contiguous"
ARGU(Index)
ARGDW(BFInfo.BitsRGB[Index])));
return(FALSE);
}
}
if ((GrayShr[Index] = ((INT)BitCount - BF_GRAY_BITS)) < 0) {
GrayShr[Index] = BitStart;
} else {
GrayShr[Index] += BitStart;
}
BFInfo.BitStart[Index] = BitStart;
BFInfo.BitCount[Index] = BitCount;
if (!BitCount) {
DBGP_IF(DBGP_BFINFO,
DBGP("WARNING: BitsRGB[%u] is ZERO"
ARGU(Index)));
}
}
//
// Check what primary order is this
//
if ((BFInfo.BitsRGB[0] >= BFInfo.BitsRGB[1]) &&
(BFInfo.BitsRGB[0] >= BFInfo.BitsRGB[2])) {
Index = (INT)((BFInfo.BitsRGB[1] > BFInfo.BitsRGB[2]) ?
PRIMARY_ORDER_RGB : PRIMARY_ORDER_RBG);
} else if ((BFInfo.BitsRGB[1] >= BFInfo.BitsRGB[0]) &&
(BFInfo.BitsRGB[1] >= BFInfo.BitsRGB[2])) {
Index = (INT)((BFInfo.BitsRGB[0] > BFInfo.BitsRGB[2]) ?
PRIMARY_ORDER_GRB : PRIMARY_ORDER_GBR);
} else {
Index = (INT)((BFInfo.BitsRGB[0] > BFInfo.BitsRGB[1]) ?
PRIMARY_ORDER_BRG : PRIMARY_ORDER_BGR);
}
BFInfo.RGBOrder = RGBOrderTable[Index];
BFInfo.RGB1stBit = BFInfo.BitStart[BFInfo.RGBOrder.Order[2]];
//
// Find out if Bit fields is a xx0 type of format for GrayShr[]
//
if (BFInfo.Flags & (BFIF_MONO_OUTPUT | BFIF_DEST_1BPP)) {
if ((BFInfo.BitCount[0] == BFInfo.BitCount[1]) &&
(BFInfo.BitCount[0] == BFInfo.BitCount[2]) &&
((BFInfo.BitCount[0] + BFInfo.RGB1stBit) <= BF_GRAY_BITS)) {
BFInfo.Flags |= BFIF_GRAY_XX0;
BFInfo.GrayShr[0] = (BYTE)BFInfo.BitCount[0];
} else {
BFInfo.GrayShr[0] = (BYTE)GrayShr[BFInfo.RGBOrder.Order[2]];
BFInfo.GrayShr[1] = (BYTE)GrayShr[BFInfo.RGBOrder.Order[1]];
BFInfo.GrayShr[2] = (BYTE)GrayShr[BFInfo.RGBOrder.Order[0]];
}
}
BFInfo.InFuncIndex = (BYTE)((BFInfo.BitmapFormat == BMF_16BPP) ?
IDXIF_BMF16BPP_START :
IDXIF_BMF32BPP_START);
if (BFInfo.Flags & BFIF_DEST_1BPP) {
BFInfo.InFuncIndex += (BFInfo.Flags & BFIF_GRAY_XX0) ? 0 : 1;
} else if (BFInfo.Flags & BFIF_MONO_OUTPUT) {
BFInfo.InFuncIndex += (BFInfo.Flags & BFIF_GRAY_XX0) ? 2 : 3;
} else {
BFInfo.SizeLUT = (WORD)((BFInfo.BitmapFormat == BMF_16BPP) ?
LUTSIZE_CLR_16BPP :
LUTSIZE_CLR_32BPP);
BFInfo.InFuncIndex += 4;
}
break;
default:
DBGP_IF(DBGP_BFINFO,
DBGP("ERROR: Invalid BFInfo.BitmapFormat %u"
ARGU(pBFInfo->BitmapFormat)));
return(FALSE);
}
//
// Put it back to return to the caller
//
*pBFInfo = BFInfo;
//
// Output some helpful information
//
DBGP_IF(DBGP_BFINFO,
DBGP("============ BFINFO ================");
DBGP(" BitsRGB[] = 0x%08lx:0x%08lx:0x%08lx"
ARGDW(pBFInfo->BitsRGB[0])
ARGDW(pBFInfo->BitsRGB[1])
ARGDW(pBFInfo->BitsRGB[2]));
DBGP("BitmapFormat = %u [%s]"
ARGU(pBFInfo->BitmapFormat)
ARG(pBMFName[pBFInfo->BitmapFormat]));
DBGP(" SizeLUT = %u" ARGU(pBFInfo->SizeLUT));
DBGP(" Flags = 0x%02x %s%s%s"
ARGU(pBFInfo->Flags)
ARG((pBFInfo->Flags & BFIF_DEST_1BPP) ?
"BFIF_DEST_1BPP | " : "")
ARG((pBFInfo->Flags & BFIF_MONO_OUTPUT) ?
"BFIF_MONO_OUTPUT | " : "")
ARG((pBFInfo->Flags & BFIF_GRAY_XX0) ?
"BFIF_GRAY_XX0" : ""));
DBGP("InFuncIndex = %u [%s]"
ARGU(pBFInfo->InFuncIndex)
ARG(pInFuncName[pBFInfo->InFuncIndex]));
DBGP(" RGBOrder[] = %2u - %2u:%2u:%2u"
ARGU(pBFInfo->RGBOrder.Index)
ARGU(pBFInfo->RGBOrder.Order[0])
ARGU(pBFInfo->RGBOrder.Order[1])
ARGU(pBFInfo->RGBOrder.Order[2]));
DBGP(" RGB1stBit = %u" ARGU(pBFInfo->RGB1stBit));
DBGP(" BitStart[] = %2u:%2u:%2u"
ARGU(pBFInfo->BitStart[0])
ARGU(pBFInfo->BitStart[1])
ARGU(pBFInfo->BitStart[2]));
DBGP(" BitCount[] = %2u:%2u:%2u"
ARGU(pBFInfo->BitCount[0])
ARGU(pBFInfo->BitCount[1])
ARGU(pBFInfo->BitCount[2]));
DBGP(" GrayShr[] = %2u:%2u:%2u"
ARGU(pBFInfo->GrayShr[0])
ARGU(pBFInfo->GrayShr[1])
ARGU(pBFInfo->GrayShr[2])));
return(TRUE);
}
LONG
HTENTRY
ValidateHTSI(
PHALFTONERENDER pHR,
UINT HTCallBackMode
)
/*++
Routine Description:
This function read the HTSurfaceInfo and set it to the pHTCBParams
Arguments:
pHR - ponter to HALFTONERENDER data structure
HTCallBackMode - HTCALLBACK_xxxx mode
Return Value:
>= 0 - Sucessful
< 0 - HTERR_xxxx error codes
Author:
28-Jan-1991 Mon 09:55:53 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPDWORD pBitsRGB;
PHTSURFACEINFO pHTSI;
PHTCALLBACKPARAMS pHTCBParams;
HTSURFACEINFO HTSurfaceInfo;
HTCALLBACKPARAMS HTCBParams;
COLORTRIAD ColorTriad;
DWORD MaxColors;
BYTE MaxBytesPerEntry;
ZeroMemory(&HTCBParams, sizeof(HTCALLBACKPARAMS));
switch(HTCallBackMode) {
case HTCALLBACK_QUERY_SRC_MASK:
if (pHTSI = pHR->HR_Header.pSrcMaskSI) {
HTSurfaceInfo = *pHTSI;
if (HTSurfaceInfo.SurfaceFormat != BMF_1BPP) {
return(HTERR_INVALID_SRC_MASK_FORMAT);
}
pHTCBParams = &(pHR->InputSI.SrcMaskCBParams);
pHR->InputSI.Flags |= ISIF_HAS_SRC_MASK;
} else {
return(0);
}
break;
case HTCALLBACK_QUERY_DEST:
if (!(pHTSI = pHR->HR_Header.pDestSI)) {
return(HTERR_NO_DEST_HTSURFACEINFO);
}
HTSurfaceInfo = *pHTSI;
pHTCBParams = &(pHR->OutputSI.DestCBParams);
pHR->OutFuncInfo.BytesPerPlane = 0;
pHR->OutputSI.TotalDestPlanes = 1;
switch(HTSurfaceInfo.SurfaceFormat) {
case BMF_1BPP:
pHR->BFInfo.Flags |= BFIF_DEST_1BPP;
break;
case BMF_1BPP_3PLANES:
pHR->OutFuncInfo.BytesPerPlane = (DWORD)HTSurfaceInfo.BytesPerPlane;
pHR->OutputSI.TotalDestPlanes = 3;
break;
case BMF_8BPP_VGA256:
//
// Check if we have xlate table for the 8bpp device
//
if (HTSurfaceInfo.pColorTriad) {
ColorTriad = *(HTSurfaceInfo.pColorTriad);
if ((ColorTriad.pColorTable) &&
(ColorTriad.ColorTableEntries == 256) &&
(ColorTriad.PrimaryValueMax == 255) &&
(ColorTriad.BytesPerEntry == 1) &&
(ColorTriad.Type == COLOR_TYPE_RGB)) {
pHR->OutFuncInfo.BytesPerPlane =
(DWORD)ColorTriad.pColorTable;
}
}
break;
case BMF_4BPP:
case BMF_4BPP_VGA16:
case BMF_16BPP_555:
break;
default:
return(HTERR_INVALID_DEST_FORMAT);
}
if (pHR->HR_Header.pDevClrAdj->PrimAdj.Flags & DCA_MONO_ONLY) {
pHR->BFInfo.Flags |= BFIF_MONO_OUTPUT;
}
pHR->OutputSI.SetDestCBParams.CallBackMode = HTCALLBACK_SET_DEST;
break;
case HTCALLBACK_QUERY_SRC:
if (!(pHTSI = pHR->HR_Header.pSrcSI)) {
return(HTERR_NO_SRC_HTSURFACEINFO);
}
HTSurfaceInfo = *pHTSI;
if (!HTSurfaceInfo.pColorTriad) {
return(HTERR_NO_SRC_COLORTRIAD);
}
ColorTriad = *(HTSurfaceInfo.pColorTriad);
pHTCBParams = &(pHR->InputSI.SrcCBParams);
//
// We will accept other color type (ie. YIQ/XYZ/LAB/LUV) when graphic
// system has type defined for the api, currently halftone can handle
// all these types for 16bpp/24bpp/32bpp sources.
//
if (ColorTriad.Type > COLOR_TYPE_MAX) {
return(HTERR_INVALID_COLOR_TYPE);
}
MaxColors = 0;
MaxBytesPerEntry = 4;
pHR->BFInfo.RGBOrder.Index = (BYTE)ColorTriad.PrimaryOrder;
switch(pHR->BFInfo.BitmapFormat = (WORD)HTSurfaceInfo.SurfaceFormat) {
case BMF_1BPP:
MaxColors = 2;
break;
case BMF_4BPP:
MaxColors = 16;
break;
case BMF_8BPP:
MaxColors = 256;
break;
case BMF_16BPP:
MaxBytesPerEntry = 2; // and fall through
case BMF_32BPP:
//
// 16BPP/32BPP bit fields type of input the parameter of
// COLORTRIAD must
//
// Type = COLOR_TYPE_RGB
// BytesPerPrimary = 0
// BytesPerEntry = (16BPP=2, 32BPP=4)
// PrimaryOrder = *Ignored*
// PrimaryValueMax = *Ignored*
// ColorTableEntries = 3
// pColorTable = Point to 3 DWORD RGB bit masks
//
if ((ColorTriad.Type != COLOR_TYPE_RGB) ||
(ColorTriad.BytesPerPrimary != 0) ||
(ColorTriad.BytesPerEntry != MaxBytesPerEntry) ||
(ColorTriad.ColorTableEntries != 3) ||
((pBitsRGB = (LPDWORD)ColorTriad.pColorTable) == NULL)) {
return(HTERR_INVALID_COLOR_TABLE);
}
pHR->BFInfo.BitsRGB[0] = *(pBitsRGB + 0);
pHR->BFInfo.BitsRGB[1] = *(pBitsRGB + 1);
pHR->BFInfo.BitsRGB[2] = *(pBitsRGB + 2);
break;
case BMF_24BPP:
//
// 24BPP must has COLORTRIAD as
//
// Type = COLOR_TYPE_xxxx
// BytesPerPrimary = 1
// BytesPerEntry = 3;
// PrimaryOrder = PRIMARY_ORDER_xxxx
// PrimaryValueMax = 255
// ColorTableEntries = *Ignorde*
// pColorTable = *Ignored*
//
if ((ColorTriad.Type != COLOR_TYPE_RGB) ||
(ColorTriad.BytesPerPrimary != 1) ||
(ColorTriad.BytesPerEntry != 3) ||
(ColorTriad.PrimaryOrder > PRIMARY_ORDER_MAX) ||
(ColorTriad.PrimaryValueMax != 255)) {
return(HTERR_INVALID_COLOR_ENTRY_SIZE);
}
break;
default:
return(HTERR_INVALID_SRC_FORMAT);
}
//
// This is a source surface, let's check the color table format
//
if (MaxColors) {
if ((ColorTriad.BytesPerPrimary != 1) &&
(ColorTriad.BytesPerPrimary != 2) &&
(ColorTriad.BytesPerPrimary != 4)) {
return(HTERR_INVALID_COLOR_TABLE_SIZE);
}
if ((UINT)ColorTriad.BytesPerEntry <
((UINT)((UINT)ColorTriad.BytesPerPrimary << 1) +
(UINT)ColorTriad.BytesPerPrimary)) {
return(HTERR_INVALID_COLOR_ENTRY_SIZE);
}
if (ColorTriad.PrimaryOrder > PRIMARY_ORDER_MAX) {
return(HTERR_INVALID_PRIMARY_ORDER);
}
if (!ColorTriad.pColorTable) {
return(HTERR_INVALID_COLOR_TABLE);
}
if ((ColorTriad.ColorTableEntries > MaxColors) ||
(!ColorTriad.ColorTableEntries)) {
return(HTERR_INVALID_COLOR_TABLE_SIZE);
}
if ((ColorTriad.BytesPerPrimary != 1) ||
(ColorTriad.PrimaryValueMax != 255)) {
return(HTERR_INVALID_PRIMARY_VALUE_MAX);
}
}
if (!ValidateRGBBitFields(&(pHR->BFInfo))) {
return(HTERR_INVALID_COLOR_TABLE);
}
break;
}
HTCBParams.hSurface = HTSurfaceInfo.hSurface;
HTCBParams.Flags = HTSurfaceInfo.Flags;
HTCBParams.SurfaceFormat = HTSurfaceInfo.SurfaceFormat;
HTCBParams.CallBackMode = (BYTE)HTCallBackMode;
HTCBParams.BytesPerScanLine =
ComputeBytesPerScanLine((WORD)HTSurfaceInfo.SurfaceFormat,
(WORD)HTSurfaceInfo.ScanLineAlignBytes,
HTSurfaceInfo.Width);
if (!(HTCBParams.MaximumQueryScanLines =
HTSurfaceInfo.MaximumQueryScanLines)) {
HTCBParams.pPlane = HTSurfaceInfo.pPlane;
}
HTCBParams.HTCB_TEMP_WIDTH = HTSurfaceInfo.Width;
HTCBParams.HTCB_TEMP_HEIGHT = HTSurfaceInfo.Height;
*pHTCBParams = HTCBParams;
return(1);
}
LONG
HTENTRY
ComputeBytesPerScanLine(
WORD SurfaceFormat,
WORD AlignmentBytes,
DWORD WidthInPel
)
/*++
Routine Description:
This function calculate total bytes needed for a single scan line in the
bitmap according to its format and alignment requirement.
Arguments:
SurfaceFormat - Surface format of the bitmap, this is must one of the
standard format which defined as SURFACE_FORMAT_xxx
AlignmentBytes - This is the alignment bytes requirement for one scan
line, this number can be range from 0 to 65535, some
common ones are:
0, 1 - Alignment in 8-bit boundary (BYTE)
2 - Alignment in 16-bit boundary (WORD)
3 - Alignment in 24-bit boundary
4 - Alignment in 32-bit boundary (DWORD)
8 - Alignment in 64-bit boundary (QWROD)
WidthInPel - Total Pels per scan line in the bitmap.
Return Value:
The return value is the total bytes in one scan line if it is greater than
zero, some error conditions may be exists when the return value is less
than or equal to 0.
Return Value == 0 - The WidthInPel is <= 0
Return Value < 0 - Invalid Surface format is passed.
Author:
14-Feb-1991 Thu 10:03:35 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LONG BytesPerScanLine;
WORD OverhangBytes;
if (WidthInPel <= 0L) {
return(0L);
}
switch (SurfaceFormat) {
case BMF_1BPP:
case BMF_1BPP_3PLANES:
BytesPerScanLine = (WidthInPel + 7L) >> 3;
break;
case BMF_4BPP_VGA16:
case BMF_4BPP:
BytesPerScanLine = ++WidthInPel >> 1;
break;
case BMF_8BPP_VGA256:
case BMF_8BPP:
BytesPerScanLine = WidthInPel;
break;
case BMF_16BPP:
case BMF_16BPP_555:
BytesPerScanLine = WidthInPel << 1;
break;
case BMF_24BPP:
BytesPerScanLine = WidthInPel + (WidthInPel << 1);
break;
case BMF_32BPP:
BytesPerScanLine = WidthInPel << 2;
break;
default:
return(-1L);
}
if ((AlignmentBytes <= 1) ||
(!(OverhangBytes = (WORD)(BytesPerScanLine % (LONG)AlignmentBytes)))) {
return(BytesPerScanLine);
} else {
return(BytesPerScanLine + (LONG)AlignmentBytes - (LONG)OverhangBytes);
}
}