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.
 
 
 
 
 
 

2658 lines
77 KiB

/*++
Copyright (c) 1990-1991 Microsoft Corporation
Module Name:
htstret.c
Abstract:
This module contains stretching functions to setup the parameters for
compress or expanding the bitmap.
Author:
24-Jan-1991 Thu 10:08:11 created -by- Daniel Chou (danielc)
[Environment:]
GDI Device Driver - Halftone.
[Notes:]
Revision History:
--*/
#define DBGP_VARNAME dbgpHTStret
#include "htp.h"
#include "htmapclr.h"
#include "htrender.h"
#include "htstret.h"
#include "limits.h"
#define DBGP_EXP0 0x0001
#define DBGP_EXP1 0x0002
#define DBGP_STRETCH 0x0004
#define DBGP_SETUP0 0x0008
#define DBGP_BANDRECT 0x0010
#define DBGP_PATBRUSH 0x0020
#define DBGP_PRIMCOUNT 0x0040
DEF_DBGPVAR(BIT_IF(DBGP_EXP0, 0) |
BIT_IF(DBGP_EXP1, 0) |
BIT_IF(DBGP_STRETCH, 0) |
BIT_IF(DBGP_SETUP0, 0) |
BIT_IF(DBGP_BANDRECT, 0) |
BIT_IF(DBGP_PATBRUSH, 0) |
BIT_IF(DBGP_PRIMCOUNT, 0))
#define SRCIDX_2_DESTIDX(Idx, Min, Add, SubDiv2, Sub) \
(((Idx) * (Min))+((((Idx) * (Add)) + (SubDiv2)) / (Sub)))
#define DESTIDX_2_SRCIDX(Idx, SrcRatio, DestRatio) \
((((Idx)*(SrcRatio))+((SrcRatio)/2)) / (DestRatio))
#define GET_RATIO_ERR(RatioVar, SizeVar, RatioError, Idx, Min, Max, RatioSub) \
if (((RatioVar)=(RatioError)+(((Idx)*(Max)) % (RatioSub))) < 0) \
{ (SizeVar)=(Min); } \
else { (SizeVar)=(Max); (RatioVar)-=(RatioSub); }
//
// Local structure
//
typedef struct _EXPINFO {
DWORD SrcRatio;
DWORD DestRatio;
LONG RatioAdd;
DWORD INTRatio;
} EXPINFO, *PEXPINFO;
typedef struct _EXPDATA {
DWORD IdxL;
DWORD IdxR;
LONG RatioErr;
} EXPDATA, *PEXPDATA;
VOID
HTENTRY
SetCompressRepeatCount(
PSTRETCHINFO pStretchInfo,
LPBYTE pPrimCount,
DWORD pPrimCountSize,
DESTEDGEINFO DestEdge,
SCRCDATA SCRCData,
CSDATA CSData
)
/*++
Routine Description:
This funciton compute and set the compress/repeat count in the data
structure array pointed by pPrimCount, the pPrimCount can be pointed to
any type of data structure, and it will set the byte count to the last
byte field within each data structure entry.
Arguments:
pStretchInfo - Pointer to the STRETCHINFO data structure.
pPrimCount - Pointer to the PRIMMONO_COUNT/PPRIMCOLOR_COUNT data
structure array
pPrimCountSize - Size in bytes pointed by pPrimCount
DestEdge - DESTEDGEINFO data structure.
SCRCData - SCRCDATA local data structure.
Return Value:
No return value for this function.
Author:
28-Jan-1991 Mon 22:28:56 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
STRETCHRATIO StretchRatio = pStretchInfo->Ratio;
LPWORD pCount;
UINT SizePerEntry;
DEFDBGVAR(LONG, DbgTotalPels)
DEFDBGVAR(BOOL, DbgNotEven)
//
// pCount Point to the first one after the STOPPER,
//
SizePerEntry = (INT)SCRCData.SizePerEntry;
pCount = (LPWORD)(pPrimCount + (UINT)SCRCData.OffsetCount);
//
// The First/Last Extra stretch is the stopper and its count is the
// First/Last skip mask for the destination.
//
SETDBGVAR(DbgTotalPels, (LONG)(DestEdge.FirstByteSkipPels +
StretchRatio.First));
//
// First we must reset everything to zero, then initialize the first/last
// stretch to 0xff
//
ZeroMemory(pPrimCount, pPrimCountSize);
FillMemory(pPrimCount, SizePerEntry, PRIM_INVALID_DENSITY);
*pCount = (WORD)DestEdge.FirstByteSkipPels; // if zero then no mask
(LPBYTE)pCount += SizePerEntry; // goto next one
//
// Starting the first stretch ratio, the pCount is point to to the last
// data structure, and StretchSize is current remainding stretch size
//
*pCount = StretchRatio.First;
(LPBYTE)pCount += SizePerEntry; // goto next one
//
// If we only have 1 stretch, then it will never have last one, at here
// we will check if we have FIRST BODY LAST, the body only exist if
// the total stretch size is greater than 2, otherwise the FIRST/LAST
// already computed.
//
if (--StretchRatio.StretchSize > 1) {
--StretchRatio.StretchSize;
if (StretchRatio.Single) { // easy one
while (StretchRatio.StretchSize--) {
*pCount = (WORD)StretchRatio.Single;
(LPBYTE)pCount += SizePerEntry; // goto next one
SETDBGVAR(DbgTotalPels+, (LONG)StretchRatio.Single);
}
} else {
while (StretchRatio.StretchSize--) {
if ((StretchRatio.Error += StretchRatio.Add) >= 0) {
StretchRatio.Error -= StretchRatio.Sub;
*pCount = (WORD)StretchRatio.MaxFactor;
(LPBYTE)pCount += SizePerEntry; // goto next one
SETDBGVAR(DbgTotalPels+, (LONG)StretchRatio.MaxFactor);
} else {
*pCount = (WORD)StretchRatio.MinFactor;
(LPBYTE)pCount += SizePerEntry; // goto next one
SETDBGVAR(DbgTotalPels+, (LONG)StretchRatio.MinFactor);
}
}
}
StretchRatio.StretchSize = 1; // the last one
}
//
// Check if we have LAST one
//
if (StretchRatio.StretchSize) {
*pCount = (WORD)StretchRatio.Last;
(LPBYTE)pCount += SizePerEntry; // goto next one
SETDBGVAR(DbgTotalPels+, (LONG)StretchRatio.Last);
}
//
// The pCount must now at last stretch, check if so
//
pPrimCount += pPrimCountSize - SizePerEntry;
ASSERTMSG("SetCompressRepeatCount: LastSkipPels Location DOES NOT AGREE",
(pPrimCount + SCRCData.OffsetCount) == (LPBYTE)pCount);
//
// Set Last stretch to all 0xff, then set it count to the lastbyte mask
//
FillMemory(pPrimCount, SizePerEntry, PRIM_INVALID_DENSITY);
*pCount = (WORD)DestEdge.LastByteSkipPels; // if zero then no mask
#if DBG
if ((CSData.DestFormat != BMF_8BPP_VGA256) &&
(CSData.DestFormat != BMF_16BPP_555)) {
if (pStretchInfo->StretchMode == STRETCH_MODE_EXPANDED) {
DbgTotalPels += (LONG)DestEdge.LastByteSkipPels;
} else {
DbgTotalPels = (LONG)pStretchInfo->Ratio.StretchSize +
(LONG)DestEdge.FirstByteSkipPels +
(LONG)DestEdge.LastByteSkipPels;
}
DbgNotEven = (BOOL)
(DbgTotalPels & ((SizePerEntry == sizeof(PRIMMONO_COUNT)) ? 7 : 1));
if (DbgNotEven) {
DBGP("FirstSkip=%ld, LastSkip=%ld, First=%ld, Last=%ld"
ARGDW(DestEdge.FirstByteSkipPels)
ARGDW(DestEdge.LastByteSkipPels)
ARGDW(StretchRatio.First)
ARGDW(StretchRatio.Last));
DBGP("TotalPels = %ld" ARGDW(DbgTotalPels));
ASSERTMSG("Destination total Pels does not aligned", 0);
}
}
#endif
}
#ifdef EXP_DBG
VOID
EXP_AssertMsg(
DWORD Lines,
DWORD VarA,
DWORD VarB,
LPBYTE pVarA,
LPBYTE pVarB
)
{
DBGP("* #%4ld, %s (%ld) != %s (%ld)"
ARGDW(Lines)
ARG(pVarA)
ARGDW(VarA)
ARG(pVarB)
ARG(VarB));
}
#define EXP_ASSERT(va,vb) \
if ((DWORD)(va) != (DWORD)(vb)) { \
EXP_AssertMsg(__LINE__,(va),(vb), #va, #vb); }
#else
#define EXP_ASSERT(va,vb)
#endif
DWORD
HTENTRY
EXP_SrcToDest(
DWORD SrcIdx,
PEXPDATA pExpData,
PEXPINFO pExpInfo
)
/*++
Routine Description:
This function take zero based source index and compute the expansion
converage zero based indices (left/right) on the destination surface
Arguments:
SrcIndex - Zero based source index number
pExpData - The data will be returned from this fucntion
pExpInfo - source->destination expansion information
Return Value:
The return value is the left side (start index) of the destination coverage.
the return value of IdxL is inclusive and IdxR is exclusive.
Author:
18-Jun-1993 Fri 12:04:31 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
EXPINFO EI = *pExpInfo;
EXPDATA ED;
DWORD SrcMulDestR;
//
// Firstable we check if source/destination has same ratio (1:1), if yes
// then we really do not need to compute at all
//
if (EI.SrcRatio == EI.DestRatio) {
ED.IdxL = SrcIdx;
ED.IdxR = SrcIdx + 1;
ED.RatioErr = -(LONG)EI.SrcRatio;
DBGP_IF(DBGP_EXP0,
DBGP("EXP_SrcToDest(%ld) -> (SAME RATIO %ld) = (%ld - %ld)"
ARGDW(SrcIdx) ARGDW(EI.SrcRatio)
ARGDW(ED.IdxL) ARGDW(ED.IdxR)));
} else {
SrcMulDestR = SrcIdx * EI.DestRatio;
ED.IdxL = (DWORD)(SrcMulDestR / EI.SrcRatio);
ED.RatioErr = (LONG)((SrcMulDestR - (EI.SrcRatio * ED.IdxL)) << 1);
if ((ED.RatioErr -= (LONG)EI.SrcRatio) >= 0) {
++ED.IdxL;
ED.RatioErr -= (LONG)(EI.SrcRatio << 1);
}
ED.IdxR = ED.IdxL + EI.INTRatio;
if ((ED.RatioErr += EI.RatioAdd) >= 0) {
++ED.IdxR;
ED.RatioErr -= (LONG)(EI.SrcRatio << 1);
}
DBGP_IF(DBGP_EXP0,
DBGP("EXP_SrcToDest(%ld) -> (RATIO %ld->%ld) = (%ld - %ld) Err=%ld"
ARGDW(SrcIdx) ARGDW(EI.SrcRatio) ARGDW(EI.DestRatio)
ARGDW(ED.IdxL) ARGDW(ED.IdxR) ARGDW(ED.RatioErr)));
}
*pExpData = ED;
return(ED.IdxL);
}
DWORD
HTENTRY
EXP_DestToSrc(
DWORD DestIdx,
PEXPDATA pExpData,
PEXPINFO pExpInfo
)
/*++
Routine Description:
This function take zero based destination index and compute the un-expanded
zero based source index.
Arguments:
DestIndex - Zero based destination index number
pExpData - The data will be returned from this fucntion
pExpInfo - source->destination expansion information
Return Value:
The return value is the source index which cover this destination index.
the return value of IdxL is inclusive and IdxR is exclusive.
Author:
18-Jun-1993 Fri 12:04:31 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
EXPINFO EI = *pExpInfo;
EXPDATA ED;
LONG RatioMin;
DWORD SrcIdx;
//
// Firstable we check if source/destination has same ratio (1:1), if yes
// then we really do not need to compute at all
//
if (EI.SrcRatio == EI.DestRatio) {
SrcIdx =
ED.IdxL = DestIdx;
ED.IdxR = SrcIdx + 1;
ED.RatioErr = -(LONG)EI.SrcRatio;
DBGP_IF(DBGP_EXP0,
DBGP("EXP_DestToSrc(%ld) [%ld-%ld] --> (SAME RATIO %ld) = (%ld)"
ARGDW(DestIdx)
ARGDW(ED.IdxL) ARGDW(ED.IdxR)
ARGDW(EI.SrcRatio)
ARGDW(SrcIdx)));
} else {
SrcIdx = (DWORD)((DestIdx * EI.SrcRatio) / EI.DestRatio);
EXP_SrcToDest(SrcIdx, &ED, &EI);
if (DestIdx < ED.IdxL) {
--SrcIdx;
ED.IdxR = ED.IdxL;
RatioMin = (LONG)(EI.DestRatio << 1);
if ((ED.RatioErr -= EI.RatioAdd) < -RatioMin) {
ED.RatioErr += RatioMin;
}
if ((ED.RatioErr - EI.RatioAdd) < -RatioMin) {
ED.IdxL = ED.IdxR - EI.INTRatio - 1;
} else {
ED.IdxL = ED.IdxR - EI.INTRatio;
}
} else if (DestIdx >= ED.IdxR) {
++SrcIdx;
ED.IdxL = ED.IdxR;
if ((ED.RatioErr += EI.RatioAdd) >= 0) {
ED.RatioErr -= (LONG)(EI.SrcRatio << 1);
ED.IdxR = ED.IdxL + EI.INTRatio + 1;
} else {
ED.IdxR = ED.IdxL + EI.INTRatio;
}
}
DBGP_IF(DBGP_EXP0,
DBGP("EXP_DestToSrc(%ld) [%ld-%ld] -> (RATIO %ld->%ld) = (%ld) Err=%ld"
ARGDW(DestIdx)
ARGDW(ED.IdxL) ARGDW(ED.IdxR)
ARGDW(EI.SrcRatio) ARGDW(EI.DestRatio)
ARGDW(SrcIdx)
ARGDW(ED.RatioErr)));
}
*pExpData= ED;
return(SrcIdx);
}
#ifndef USE_OLD_CAL_EXP
LONG
HTENTRY
CalculateExpansion(
PEXPANDCOMPRESS pExpandCompress,
PSTRETCHINFO pStretchInfo
)
/*++
Routine Description:
This funciton calculate the expansion factors, source offset, extend and
allocate the stretch bit masks if necessary.
Arguments:
pExpandCompress - pointer to EXPAANDCOMPRESS data structures
pStretchInfo - pointer to the STRETCHINFO data structure.
Return Value:
A negative number indicate failue.
HTERR_INSUFFICIENT_MEMORY - if memory allocation errors occurred.
else - the total PRIMCOLOR/PRIMMONO data structures
allocated, a zero indicate that destination
is fully clipped.
following data structure fields are filled by this function
pStretchInfo->Ratio
pExpandCompress->SrcSkip
pExpandCompress->SrcExtend
pExpandCompress->DestSkip
pExpandCompress->DestExtend
Author:
28-Jan-1991 Mon 22:28:56 created -by- Daniel Chou (danielc)
Revision History:
28-Jan-1992 Tue 14:51:22 updated -by- Daniel Chou (danielc)
Fixed SrcEnd/DestEnd, one of these may be changed by exausted either
source or destination.
10-Jun-1993 Thu 10:50:22 updated -by- Daniel Chou (danielc)
Rewirte to fixed the GP bug when stretch size is zero, now run quicker
and cleaner.
18-Jun-1993 Fri 11:58:10 updated -by- Daniel Chou (danielc)
Fixes bug# 13885, which should be
} else if (DestR <= ED.IdxL) {
NOT
} else if (DestR < ED.IdxL) {
--*/
{
EXPANDCOMPRESS EC;
STRETCHRATIO Ratio;
EXPINFO EI;
EXPDATA ED;
EXPDATA LeftED;
LONG StretchSize;
DWORD SrcL;
DWORD DestL;
DWORD SrcR;
DWORD DestR;
//
// Firstable make sure we get the good data
//
EC = *pExpandCompress;
if ((EC.SrcRatio <= 0) ||
(EC.DestRatio <= 0) ||
(EC.DestRatio < EC.SrcRatio) ||
(EC.SrcReadSize <= 0) ||
(EC.DestReadSize <= 0)) {
DBGP_IF(DBGP_EXP1,
DBGP("\nExpansion: STRETCH SIZE = 0, TOTALLY CLIPPED"));
return(0); // completely clipped
}
if ((EC.SrcOverhang < 0) || (EC.DestOverhang < 0)) {
ASSERT(EC.SrcOverhang >= 0);
ASSERT(EC.DestOverhang >= 0);
return(INTERR_STRETCH_NEG_OVERHANG);
}
//
// Start checking the visible region and stretch ratio for the src/dest
//
EI.SrcRatio = (DWORD)EC.SrcRatio;
EI.DestRatio = (DWORD)EC.DestRatio;
EI.INTRatio = (DWORD)(EC.DestRatio / EC.SrcRatio);
EI.RatioAdd = (DWORD)((EC.DestRatio % EC.SrcRatio) << 1);
//
// Find out the left side src/dest visible region limit
//
// *** REMEMBER: IdxL is inclusive, and IdxR is exclusive
//
SrcL = EC.SrcOverhang;
DestL = EC.DestOverhang;
EXP_SrcToDest(SrcL, &ED, &EI);
if (DestL < ED.IdxL) {
DestL = ED.IdxL; // move into first visible source
} else if (DestL >= ED.IdxR) {
SrcL = EXP_DestToSrc(DestL, &ED, &EI);
}
LeftED = ED;
//
// Find out the right side src/dest visible region limit
//
// *** REMEMBER: IdxL is inclusive, and IdxR is exclusive
//
SrcR = EC.SrcOverhang + EC.SrcReadSize;
DestR = EC.DestOverhang + EC.DestReadSize;
EXP_SrcToDest(SrcR - 1, &ED, &EI);
if (DestR > ED.IdxR) {
DestR = ED.IdxR; // move into last visible source
} else if (DestR <= ED.IdxL) {
SrcR = EXP_DestToSrc(DestR - 1, &ED, &EI) + 1;
}
//
// We done all the src/dest left/right computation, now check if src/dest
// still visible
//
if ((StretchSize = (LONG)SrcR - (LONG)SrcL) <= 0) {
DBGP_IF(DBGP_EXP1,
DBGP("\nExpansion: STRETCH SIZE = 0, TOTALLY CLIPPED"));
EXP_ASSERT(pStretchInfo->Ratio.StretchSize, 0);
return(0);
} else if (StretchSize > STRETCH_MAX_SIZE) {
ASSERTMSG("StretchSize > STRETCH_MAX_SIZE, failed the call", FALSE);
return(HTERR_STRETCH_RATIO_TOO_BIG);
} else {
EXP_ASSERT(EC.SrcSkip , SrcL);
EXP_ASSERT(EC.SrcExtend , (SrcR - SrcL));
EXP_ASSERT(EC.DestSkip , DestL);
EXP_ASSERT(EC.DestExtend, (DestR - DestL));
pExpandCompress->SrcSkip =
EC.SrcSkip = (LONG)SrcL;
pExpandCompress->SrcExtend =
EC.SrcExtend = (LONG)(SrcR - SrcL);
pExpandCompress->DestSkip =
EC.DestSkip = (LONG)DestL;
pExpandCompress->DestExtend =
EC.DestExtend = (LONG)(DestR - DestL);
if (StretchSize > EC.DestExtend) {
ASSERTMSG("StretchSize > EC.DestExtend, failed the call", FALSE);
return(HTERR_STRETCH_RATIO_TOO_BIG);
}
if ((Ratio.StretchSize = (WORD)StretchSize) == 1) {
Ratio.First = (WORD)EC.DestExtend;
Ratio.Last = 0;
} else {
Ratio.First = (WORD)(LeftED.IdxR - DestL);
Ratio.Last = (WORD)(DestR - ED.IdxL);
}
Ratio.Error = (LONG)LeftED.RatioErr;
Ratio.MinFactor =
Ratio.MaxFactor = (WORD)EI.INTRatio;
Ratio.Sub = (LONG)(EC.SrcRatio << 1);
if (Ratio.Add = (LONG)EI.RatioAdd) {
Ratio.Single = 0;
++Ratio.MaxFactor;
} else {
Ratio.Single = Ratio.MinFactor;
}
EXP_ASSERT(pStretchInfo->Ratio.StretchSize, Ratio.StretchSize);
EXP_ASSERT(pStretchInfo->Ratio.First , Ratio.First);
EXP_ASSERT(pStretchInfo->Ratio.Single , Ratio.Single);
EXP_ASSERT(pStretchInfo->Ratio.Last , Ratio.Last);
EXP_ASSERT(pStretchInfo->Ratio.MinFactor , Ratio.MinFactor);
EXP_ASSERT(pStretchInfo->Ratio.MaxFactor , Ratio.MaxFactor);
EXP_ASSERT(pStretchInfo->Ratio.Error , Ratio.Error);
EXP_ASSERT(pStretchInfo->Ratio.Sub , Ratio.Sub);
EXP_ASSERT(pStretchInfo->Ratio.Add , Ratio.Add);
//
// Save it back
//
pStretchInfo->Ratio = Ratio;
//
// Show some usful output if desired
//
DBGP_IF(DBGP_EXP1,
DBGP("\nNewCalculateExpansion:");
DBGP(" SrcRatio = %ld" ARGDW(EC.SrcRatio));
DBGP(" DestRatio = %ld" ARGDW(EC.DestRatio));
DBGP(" SrcOverhang = %ld" ARGDW(EC.SrcOverhang));
DBGP(" SrcReadSize = %ld" ARGDW(EC.SrcReadSize));
DBGP("DestOverhang = %ld" ARGDW(EC.DestOverhang));
DBGP("DestReadSize = %ld" ARGDW(EC.DestReadSize));
DBGP(" SrcSkip = %ld" ARGDW(EC.SrcSkip));
DBGP(" SrcExtend = %ld" ARGDW(EC.SrcExtend));
DBGP(" DestSkip = %ld" ARGDW(EC.DestSkip));
DBGP(" DestExtend = %ld" ARGDW(EC.DestExtend));
DBGP("Stretch SIZE = %ld" ARGDW(StretchSize));
DBGP(" First = %u" ARGW(Ratio.First));
DBGP(" Single = %u" ARGW(Ratio.Single));
DBGP(" Last = %u" ARGW(Ratio.Last));
DBGP(" MinFactor = %u" ARGW(Ratio.MinFactor));
DBGP(" MaxFactor = %u" ARGW(Ratio.MaxFactor));
DBGP(" RatioErr = %ld" ARGL(Ratio.Error));
DBGP(" RatioSub = %ld" ARGW(Ratio.Sub));
DBGP(" RatioAdd = %ld\n" ARGW(Ratio.Add));
);
return(StretchSize);
}
}
#else
LONG
HTENTRY
CalculateExpansion(
PEXPANDCOMPRESS pExpandCompress,
PSTRETCHINFO pStretchInfo
)
/*++
Routine Description:
This funciton calculate the expansion factors, source offset, extend and
allocate the stretch bit masks if necessary.
Arguments:
pExpandCompress - pointer to EXPAANDCOMPRESS data structures
pStretchInfo - pointer to the STRETCHINFO data structure.
Return Value:
A negative number indicate failue.
HTERR_INSUFFICIENT_MEMORY - if memory allocation errors occurred.
else - the total PRIMCOLOR/PRIMMONO data structures
allocated, a zero indicate that destination
is fully clipped.
following data structure fields are filled by this function
pStretchInfo->Ratio
pExpandCompress->SrcSkip
pExpandCompress->SrcExtend
pExpandCompress->DestSkip
pExpandCompress->DestExtend
Author:
28-Jan-1991 Mon 22:28:56 created -by- Daniel Chou (danielc)
Revision History:
28-Jan-1992 Tue 14:51:22 updated -by- Daniel Chou (danielc)
Fixed SrcEnd/DestEnd, one of these may be changed by exausted either
source or destination.
--*/
{
EXPANDCOMPRESS EC;
LONG SingleCount;
LONG FirstCount;
LONG LastCount;
LONG MinINTRatio;
LONG MaxINTRatio;
LONG DestBlkSize;
LONG FirstRatioError;
LONG RatioError;
LONG RatioSub;
LONG RatioAdd;
LONG StretchSize;
LONG CurSrcIdx;
LONG CurDestIdx;
LONG SrcEndChkIdx;
LONG DestEndChkIdx;
EXPDATA ED;
EXPINFO EI;
DWORD xSrc;
EC = *pExpandCompress;
if ((EC.SrcRatio <= 0) ||
(EC.DestRatio <= 0) ||
(EC.DestRatio < EC.SrcRatio) ||
(EC.SrcReadSize <= 0) ||
(EC.DestReadSize <= 0)) {
return(0); // completely clipped
}
if ((EC.SrcOverhang < 0) || (EC.DestOverhang < 0)) {
return(INTERR_STRETCH_NEG_OVERHANG);
}
SingleCount =
MinINTRatio =
MaxINTRatio = EC.DestRatio / (RatioSub = EC.SrcRatio);
if (RatioAdd = EC.DestRatio % EC.SrcRatio) {
//
// Not even expansion
//
SingleCount = 0;
++MaxINTRatio;
} else {
SingleCount = MinINTRatio;
}
if (MaxINTRatio > STRETCH_MAX_SIZE) {
return(HTERR_STRETCH_RATIO_TOO_BIG);
}
RatioError =
FirstRatioError = -RatioSub;
pStretchInfo->Ratio.Sub = (RatioSub += RatioSub);
pStretchInfo->Ratio.Add = (RatioAdd += RatioAdd);
pStretchInfo->Ratio.MinFactor = (WORD)MinINTRatio;
pStretchInfo->Ratio.MaxFactor = (WORD)MaxINTRatio;
EI.SrcRatio = (DWORD)EC.SrcRatio;
EI.DestRatio = (DWORD)EC.DestRatio;
EI.INTRatio = (DWORD)MinINTRatio;
EI.RatioAdd = (DWORD)RatioAdd;
DBGP_IF(DBGP_EXP0,
DBGP("Ratio: Add=%ld, Sub=%ld, Err=%ld, Min/Max=%ld/%ld"
ARGL(RatioAdd) ARGL(RatioSub) ARGL(RatioError)
ARGL(MinINTRatio) ARGL(MaxINTRatio)));
if (SingleCount) {
//
// Easy case, this is integer multple expansion
//
if ((EC.DestSkip = (EC.SrcSkip = EC.SrcOverhang) * MinINTRatio) <
EC.DestOverhang) {
//
// Destination overhang is larger than the source, reset the
// destination skip and compute the corresponse source skip
//
EC.DestSkip = EC.DestOverhang;
EC.SrcSkip = EC.DestSkip / MinINTRatio; // Beg=Inclusive
}
CurSrcIdx = EC.SrcOverhang + EC.SrcReadSize;
DestEndChkIdx = EC.DestOverhang + EC.DestReadSize;
if ((CurDestIdx = CurSrcIdx * MinINTRatio) > DestEndChkIdx) {
CurDestIdx = DestEndChkIdx;
CurSrcIdx = (CurDestIdx + MinINTRatio - 1) / MinINTRatio;
}
StretchSize = CurSrcIdx - EC.SrcSkip;
FirstCount = MinINTRatio - (EC.DestSkip % MinINTRatio);
if (!(LastCount = CurDestIdx % MinINTRatio)) {
LastCount = MinINTRatio;
}
} else {
//
// Skip all invisable portions of Src and Dest
//
// SrcIdx = Starting Visible Src Index
// DestIdx = Starting Visible Dest Index
// RatioError = Current ratio error for the Dest
//
CurSrcIdx =
CurDestIdx = 0;
SrcEndChkIdx = EC.SrcOverhang;
DestEndChkIdx = EC.DestOverhang;
do {
if ((RatioError += RatioAdd) < 0) {
DestBlkSize = MinINTRatio;
} else {
DestBlkSize = MaxINTRatio;
RatioError -= RatioSub;
}
CurDestIdx += DestBlkSize;
EXP_SrcToDest(CurSrcIdx, &ED, &EI);
EXP_ASSERT(DestBlkSize, (ED.IdxR - ED.IdxL));
EXP_ASSERT(CurDestIdx, ED.IdxR);
EXP_ASSERT(RatioError, ED.RatioErr);
xSrc = EXP_DestToSrc(CurDestIdx - 1, &ED, &EI);
EXP_ASSERT(DestBlkSize, (ED.IdxR - ED.IdxL));
EXP_ASSERT(CurSrcIdx, xSrc);
EXP_ASSERT(RatioError, ED.RatioErr);
DBGP_IF(DBGP_EXP0,
DBGP("OVER_HANG: Src=%4ld, Dest=%4ld, DestBlk=%3ld, RatioErr=%5ld"
ARGL(CurSrcIdx) ARGL(CurDestIdx)
ARGL(DestBlkSize) ARGL(RatioError));
);
} while ((++CurSrcIdx <= SrcEndChkIdx) ||
(CurDestIdx <= DestEndChkIdx));
//
// Now we have the first stretch
//
FirstRatioError = RatioError;
StretchSize = 1;
EC.SrcSkip = (CurSrcIdx - 1);
if ((EC.DestSkip = (CurDestIdx - (FirstCount = DestBlkSize))) <
DestEndChkIdx) {
//
// We have overhang not started at exact Dest block boundary
//
FirstCount -= DestEndChkIdx - EC.DestSkip;
EC.DestSkip = DestEndChkIdx;
}
//
// Now compute the last index
//
SrcEndChkIdx += EC.SrcReadSize;
DestEndChkIdx += EC.DestReadSize;
while ((CurSrcIdx < SrcEndChkIdx) && (CurDestIdx < DestEndChkIdx)) {
if ((RatioError += RatioAdd) < 0) {
DestBlkSize = MinINTRatio;
} else {
RatioError -= RatioSub;
DestBlkSize = MaxINTRatio;
}
++StretchSize;
++CurSrcIdx;
CurDestIdx += DestBlkSize;
EXP_SrcToDest(CurSrcIdx - 1, &ED, &EI);
EXP_ASSERT(DestBlkSize, (ED.IdxR - ED.IdxL));
EXP_ASSERT(CurDestIdx, ED.IdxR);
EXP_ASSERT(RatioError, ED.RatioErr);
xSrc = EXP_DestToSrc(CurDestIdx - 1, &ED, &EI);
EXP_ASSERT(DestBlkSize, (ED.IdxR - ED.IdxL));
EXP_ASSERT(CurSrcIdx - 1, xSrc);
EXP_ASSERT(RatioError, ED.RatioErr);
DBGP_IF(DBGP_EXP0,
DBGP("READ_SIZE: Src=%4ld, Dest=%4ld, DestBlk=%3ld, RatioErr=%5ld"
ARGL(CurSrcIdx) ARGL(CurDestIdx)
ARGL(DestBlkSize) ARGL(RatioError));
);
}
//
// Now compute the last StretchSize
//
// At most the SrcIdx = SrcEnd, and DestIdx may be > DestEnd
//
if (StretchSize == 1) {
//
// we never went through the loop above, the CurSrcIdx <
// SrcEndChkIdx and CurDestIdx < DestEndChkIdx, We must modify the
// FirstCount since the visible region is in only one
// Dest block
//
// 10-Jun-1993 Thu 05:03:55 updated -by- Daniel Chou (danielc)
// We must check if the Src and Destination both are visible
//
if ((EC.SrcSkip >= SrcEndChkIdx) ||
(EC.DestSkip >= DestEndChkIdx)) {
//
// region of source and/or destination is not visible
//
StretchSize = 0;
}
CurDestIdx = DestEndChkIdx; // this is the actually end
} else {
LastCount = DestBlkSize; // assume full block size
if (CurDestIdx > DestEndChkIdx) {
//
// Last Dest is only partial visible
//
LastCount -= (CurDestIdx - DestEndChkIdx);
CurDestIdx = DestEndChkIdx;
}
}
}
if (StretchSize) {
EC.SrcExtend = CurSrcIdx - EC.SrcSkip;
EC.DestExtend = CurDestIdx - EC.DestSkip;
if (StretchSize > STRETCH_MAX_SIZE) {
return(HTERR_STRETCH_RATIO_TOO_BIG);
} else if ((pStretchInfo->Ratio.StretchSize = (WORD)StretchSize) == 1) {
FirstCount = EC.DestExtend;
LastCount = 0;
} else {
if (LastCount <= 0) {
ASSERT(LastCount > 0);
return(INTERR_STRETCH_FACTOR_TOO_BIG);
}
}
pStretchInfo->Ratio.Error = FirstRatioError;
pStretchInfo->Ratio.Single = (WORD)SingleCount;
pStretchInfo->Ratio.First = (WORD)FirstCount;
pStretchInfo->Ratio.Last = (WORD)LastCount;
if ((FirstCount <= 0) ||
(EC.SrcExtend <= 0) ||
(EC.DestExtend <= 0)) {
ASSERT(FirstCount > 0);
ASSERT(EC.SrcExtend > 0);
ASSERT(EC.DestExtend > 0);
return(INTERR_STRETCH_FACTOR_TOO_BIG);
}
DBGP_IF(DBGP_EXP1,
DBGP("\nCalculateExpansion:");
DBGP(" SrcRatio = %ld" ARGDW(EC.SrcRatio));
DBGP(" DestRatio = %ld" ARGDW(EC.DestRatio));
DBGP(" SrcOverhang = %ld" ARGDW(EC.SrcOverhang));
DBGP(" SrcReadSize = %ld" ARGDW(EC.SrcReadSize));
DBGP("DestOverhang = %ld" ARGDW(EC.DestOverhang));
DBGP("DestReadSize = %ld" ARGDW(EC.DestReadSize));
DBGP(" SrcSkip = %ld" ARGDW(EC.SrcSkip));
DBGP(" SrcExtend = %ld" ARGDW(EC.SrcExtend));
DBGP(" DestSkip = %ld" ARGDW(EC.DestSkip));
DBGP(" DestExtend = %ld" ARGDW(EC.DestExtend));
DBGP("Stretch SIZE = %ld" ARGDW(StretchSize));
DBGP(" First = %u" ARGW(pStretchInfo->Ratio.First));
DBGP(" Single = %u" ARGW(pStretchInfo->Ratio.Single));
DBGP(" Last = %u" ARGW(pStretchInfo->Ratio.Last));
DBGP(" MinFactor = %u" ARGW(pStretchInfo->Ratio.MinFactor));
DBGP(" MaxFactor = %u" ARGW(pStretchInfo->Ratio.MaxFactor));
DBGP(" RatioErr = %ld" ARGL(pStretchInfo->Ratio.Error));
DBGP(" RatioSub = %ld" ARGW(pStretchInfo->Ratio.Sub));
DBGP(" RatioAdd = %ld\n" ARGW(pStretchInfo->Ratio.Add));
);
} else {
DBGP_IF(DBGP_EXP1,
DBGP("\nExpansion: STRETCH SIZE = 0, TOTALLY CLIPPED"));
}
*pExpandCompress = EC;
//
// TestCalculateExpansion(pExpandCompress, pStretchInfo);
//
return(StretchSize);
}
#endif // USE_OLD_CAL_EXP
LONG
HTENTRY
CalculateStretch(
PDEVICECOLORINFO pDCI,
PSTRETCHINFO pStretchInfo,
LONG SrcOrigin,
LONG SrcExtend,
LONG SrcSize,
LONG DestOrigin,
LONG DestExtend,
LONG DestSize,
LONG DestClipStart,
LONG DestClipEnd,
LONG BandStart,
LONG BandEnd,
LONG SrcMaskOrigin,
LONG SrcMaskSize,
PLPBYTE ppColorInfo,
PINPUTSCANINFO pInputSI,
CSDATA CSData
)
/*++
Routine Description:
This function calculate the stretch parameters from source to the
destination.
Arguments:
pStretchInfo - a pointer to the STRETCHINFO data structure which will
be filled by this function.
SrcOrigin - The origin of the source surface, it may be Left or Top
origin.
SrcExtend - The size of the source (may be width or height) to be
calculated in the stretch.
SrcSize - The actual size of the source, (may be width or height
depends on the call).
DestOrigin - The origin of the destination surface, it may be Left
or Top origin.
DestExtend - The size of the destination (may be width or height) to
be calculated in the stretch.
DestSize - The actual size of the destination (my be width or
height), this is used to clip the right/bottom side of
the destination.
DestClipStart - The destination clipping starting coordinate. (may be X
or Y direction), the DestClipStart may be negative.
DestClipEnd - The destination clipping ending coordinate. (may be X or
Y direction), the DestClipEnd may be negative.
NOTE: DestClipStart/DestClipEnd only valid if
CSDF_HAS_CLIPRECT flag is set.
BandStart - Band staring coordinate (may be X or Y direction)
BandEnd - Band ending coordinate (may be X or Y direction).
NOTE: BandStart/BandEnd only valid if CSDF_HAS_BANDRECT
flag is set.
SrcMaskOrigin - The origin of the source mask bitmap, it may be left or
top of the bitmap. This field will be ignored if there
is no source mask bitmap.
SrcMaskSize - The size of the source mask bitmap, it may be width or
height of the bitmap. This field will be ignored if
there is no source mask bitmap.
ppColorInfo - This is optional field, if it is not NULL then a memory
allocation is done for the PRIMMONO or PRIMCOLOR data
structures.
pInputSI - Pointer to the InputScanInfo data structure, this only
used for source mask, which this fucntion will allocate
the memory and set InputSI.pSrcMaskLine and
InputSI.SizeSrcMaskLine two field, if no source mask
then this pointer is ignored.
CSData - CSDATA data structure.
SrcFormat - The source surface format
DestFormat - The destination surface format.
Flags - flags Indicate the desired operations,
it may be one or more of following:
CSDF_FLIP_SOURCE
flip the source when calculate the stretch
parameters, this has the effects of mirror
in X and/or Y direction.
CSDF_HAS_SRC_MASK
This flag specified that SrcMaskOrigin,
SrcMaskSize is present, if this flag is not
defined then not computation is done for the
source mask.
CSDF_SRCMASKINFO
This flag indicate that a memory allocation is
needed for the source mask info. The
ppSrcMaskInfo must not NULL.
Return Value:
HTERR_INSUFFICIENT_MEMORY - if memory allocation errors occurred.
HTERR_INVALID_SRC_FORMAT - Invalid source format.
HTERR_INVALID_DEST_FORMAT - Invalid destination format.
HTERR_INTERNAL_ERRORS_START - Other negative nubmer indicate internal
failue.
else
< 0 - An error code to indicate the failure status
= 0 - Destination is fully clipped, (empty)
> 0 - If CALCULATE_STRETCH_COLORINFO flag specified then this
value is size in bytes of total PRIMNOMO/PRIMCOLOR
data strcuture allocated if the X direction of source is
going backward and size PRIMMONO/PRIMCOLOR data structure
if going forward, if CALCULATE_STRETCH_COLORINFO flag is
not specified then return value is the size of the
PRIMMONO/PRIMCOLOR data structure.
If the return value is greater than 0 then STRETCHINFO data structure
pointed by pStretchInfo is filled with all the stretch parameters,
it will be undefined otherwise.
Author:
22-Jan-1991 Tue 13:20:51 created -by- Daniel Chou (danielc)
Revision History:
23-Apr-1992 Thu 20:01:55 updated -by- Daniel Chou (danielc)
changed 'SizePerColorInfo' and 'ColorInfoIncrement' variables from
'CHAR' type to 'SHORT' type, this will make sure if compiled
under MIPS the default 'unsigned char' will not affect the signed
operation.
17-May-1995 Wed 16:55:41 updated -by- Daniel Chou (danielc)
Revised the pattern align point, The BRUSH ORIGIN means the
halftone's brushes origin (left/top at (0, 0)) will mapped to the
point specified by the brush origin. So the origin computation is
correct.
Both X/Y PatternAlign (Origin) are computed as follow
PatternAlign = VisibleDestStart - PatternAlign;
if ((PatternAlign %= CellSize) < 0) {
PatternAlign += CellSize;
}
We will do CellSize Modulation and negative compensation for halftone
pattern when we cached the pattern at htpat.c
--*/
{
LPBYTE pColorInfo;
LONG SrcEnd;
LONG DestEnd;
LONG StretchSize;
LONG TempStart;
LONG TempEnd;
EXPANDCOMPRESS EC;
STRETCHINFO StretchInfo;
SCRCDATA SCRCData;
LONG SizeColorInfo;
LONG CIInputSkip;
WORD Mask;
SHORT SizePerColorInfo;
ASSERTMSG("Src Extend < 0", (SrcExtend >= 0));
ASSERTMSG("Dest Extend < 0", (DestExtend >= 0));
if (CSData.Flags & CSDF_HAS_BANDRECT) {
if ((BandStart < 0L) || (BandEnd < 0L) || (BandStart >= BandEnd)) {
return(HTERR_INVALID_BANDRECT);
}
} else {
BandStart = 0;
BandEnd = LONG_MAX;
}
if (!(CSData.Flags & CSDF_HAS_CLIPRECT)) {
DestClipStart = 0;
DestClipEnd = LONG_MAX;
}
if ((DestClipEnd <= DestClipStart) ||
(DestClipEnd <= 0) ||
(SrcOrigin >= SrcSize) ||
((SrcEnd = SrcOrigin + SrcExtend) <= 0) ||
(DestOrigin >= DestSize) ||
((DestEnd = DestOrigin + DestExtend) <= 0)) {
return(0); // destination is fully clipped
}
//
// First, find out the visible bitblt region on the destination
//
if ((TempStart = DestOrigin) < 0L) {
TempStart = 0L;
}
if (DestClipStart > TempStart) {
TempStart = DestClipStart;
}
if (BandStart > TempStart) {
TempStart = BandStart;
}
if ((TempEnd = DestEnd) > DestSize) {
TempEnd = DestSize;
}
if (TempEnd > DestClipEnd) {
TempEnd = DestClipEnd;
}
if (TempEnd > BandEnd) {
TempEnd = BandEnd;
}
EC.DestOverhang = TempStart - DestOrigin;
if ((EC.DestReadSize = TempEnd - TempStart) <= 0L) {
return(0);
}
//
// secondly, find out the visible bitblt region on the source
//
if ((TempStart = SrcOrigin) < 0L) {
TempStart = 0L;
}
if ((TempEnd = SrcEnd) > SrcSize) {
TempEnd = SrcSize;
}
if (CSData.Flags & CSDF_FLIP_SOURCE) {
EC.SrcOverhang = SrcEnd - TempEnd;
} else {
EC.SrcOverhang = TempStart - SrcOrigin;
}
if ((EC.SrcReadSize = TempEnd - TempStart) <= 0L) {
return(0);
}
//
// Start with all zeros
//
ZeroMemory(&StretchInfo, sizeof(STRETCHINFO));
StretchInfo.Ratio.StretchFactor =
(ULDECI4)((((ULDECI4)DestExtend * 10000L) +
((ULDECI4)SrcExtend >> 1)) / (ULDECI4)SrcExtend);
if (SrcExtend > DestExtend) {
StretchInfo.StretchMode = (BYTE)STRETCH_MODE_COMPRESSED;
XCHG(EC.SrcOverhang, EC.DestOverhang, TempStart);
XCHG(EC.SrcReadSize, EC.DestReadSize, TempStart);
EC.SrcRatio = DestExtend;
EC.DestRatio = SrcExtend;
} else {
StretchInfo.StretchMode = (BYTE)((SrcExtend == DestExtend) ?
STRETCH_MODE_ONE_TO_ONE :
STRETCH_MODE_EXPANDED);
EC.SrcRatio = SrcExtend;
EC.DestRatio = DestExtend;
}
if ((StretchSize = CalculateExpansion(&EC, &StretchInfo)) <= 0) {
return(StretchSize);
}
if (StretchInfo.StretchMode == (BYTE)STRETCH_MODE_COMPRESSED) {
XCHG(EC.SrcExtend, EC.DestExtend, TempStart);
XCHG(EC.SrcSkip, EC.DestSkip, TempStart);
}
//
// Recording total source/destination pels
//
StretchInfo.SrcExtend = EC.SrcExtend;
StretchInfo.DestExtend = EC.DestExtend;
//
// When we flip the source (WIDTH), we actually do not read the source in
// backward fashion, but just make the PRIMMONO/PRIMCOLOR data structures
// constructed in backward fashion, for the source HEIGHT flip, we still
// reading the source in backward fashion, that is the source increment
// always > 0, and it should never used for the height calculation
//
// This is also true for the source mask bits, we always reading the source
// masks bits from left to right (X direction) but the Y direction may be
// flipped.
//
if (CSData.Flags & CSDF_FLIP_SOURCE) {
StretchInfo.Flags |= SIF_SOURCE_DIR_BACKWARD;
//
// Go to end of the source then skip back by amount of SrcLeftSkip
// then reset the source skip so that the skip is counted from left
// to right
//
TempEnd = SrcEnd - EC.SrcSkip - 1;
TempStart = (TempEnd + 1L) - StretchInfo.SrcExtend;
ASSERTMSG("SrcExtend is too big", TempStart >= 0L);
ASSERTMSG("New Src Left/Top is less than original Left/Top",
(TempStart - SrcOrigin) >= 0L);
if (CSData.Flags & CSDF_X_DIR) {
//
// Src/Masks will always from left to right
//
EC.SrcSkip = TempStart - SrcOrigin;
SrcOrigin = TempStart;
DBGP_IF(DBGP_BANDRECT,
DBGP("BandX=(%4ld - %4ld), SrcX=(%4ld - %4ld) [%4ld, %4ld]"
ARGL(BandStart) ARGL(BandEnd)
ARGL(SrcOrigin) ARGL(SrcOrigin + StretchInfo.SrcExtend)
ARGL(EC.SrcSkip) ARGL(StretchInfo.SrcExtend)));
if ((CSData.Flags & CSDF_HAS_SRC_MASK) &&
(((SrcMaskOrigin += EC.SrcSkip) +
StretchInfo.SrcExtend)) > SrcMaskSize) {
return(HTERR_SRC_MASK_BITS_TOO_SMALL);
}
} else {
if (CSData.Flags & CSDF_HAS_SRC_MASK) {
if ((SrcMaskOrigin += (TempEnd - SrcOrigin)) >= SrcMaskSize) {
return(HTERR_SRC_MASK_BITS_TOO_SMALL);
}
}
SrcOrigin = TempEnd;
}
} else {
SrcOrigin += EC.SrcSkip;
ASSERTMSG("SrcExtend is too big",
(SrcOrigin + StretchInfo.SrcExtend) <= SrcEnd);
if ((CSData.Flags & CSDF_HAS_SRC_MASK) &&
(((SrcMaskOrigin += EC.SrcSkip) +
StretchInfo.SrcExtend)) > SrcMaskSize) {
return(HTERR_SRC_MASK_BITS_TOO_SMALL);
}
}
if (CSData.Flags & CSDF_HAS_SRC_MASK) {
//
// Remember, the source mask is always BMF_1BPP format, and we are
// pre-rotated the mask to left by 1.
//
StretchInfo.SrcMaskBitOffset = SrcMaskOrigin;
StretchInfo.SrcMaskByteOffset = SrcMaskOrigin >> 3;
StretchInfo.FirstSrcMaskSkips = (BYTE)(SrcMaskOrigin & 0x07);
StretchInfo.SrcMaskOffsetMask = (BYTE)(0x80 >>
((--SrcMaskOrigin) & 0x07));
if (CSData.Flags & CSDF_SRCMASKINFO) {
pInputSI->SizeSrcMaskLine =
((WORD)((((StretchInfo.SrcMaskBitOffset & 0x07L) +
StretchInfo.SrcExtend - 1L) >> 3) + 1));
if (!(pInputSI->pSrcMaskLine =
(LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"InputSI-pSrcMaskLine",
NONZEROLPTR,
pInputSI->SizeSrcMaskLine))) {
return(HTERR_INSUFFICIENT_MEMORY);
}
}
}
StretchInfo.SrcBitOffset = SrcOrigin;
Mask = 2; // multiplication factors
switch (CSData.SrcFormat) {
case BMF_32BPP:
++Mask; // 3,.. fall through become 4
case BMF_24BPP:
++Mask; // 3... fall through
case BMF_16BPP:
StretchInfo.SrcByteOffset = (SrcOrigin * (LONG)Mask);
break;
case BMF_8BPP:
StretchInfo.SrcByteOffset = SrcOrigin;
break;
case BMF_4BPP:
StretchInfo.SrcByteOffset = SrcOrigin >> 1;
if ((StretchInfo.SrcOffsetByteMask = ((WORD)(SrcOrigin - 1L)
& 0x01) ? (BYTE)0x0f : (BYTE)0xf0) == (BYTE)0xf0) {
//
// The first time shift will still within first byte so we have
// to tell it load the first byte first
//
StretchInfo.Flags |= SIF_GET_FIRST_SOURCE_BYTE;
}
break;
case BMF_1BPP:
StretchInfo.SrcByteOffset = SrcOrigin >> 3;
StretchInfo.BMF1BPPOffsetByteBitShift =
(BYTE)((SrcOrigin - 1L) & 0x07);
if ((StretchInfo.SrcOffsetByteMask = (BYTE)(0x80 >>
StretchInfo.BMF1BPPOffsetByteBitShift)) != (BYTE)0x01) {
//
// The first time shift will still within first byte so we have
// to tell it load the first byte first
//
StretchInfo.Flags |= SIF_GET_FIRST_SOURCE_BYTE;
}
break;
default:
return(HTERR_INVALID_SRC_FORMAT);
}
//
// We will make ClipStart as begining offset of the destination
// and ClipEnd as ending offset of the destination, notice that ClipStart
// may be greater than the ClipEnd if flip, remember we will make both
// offset as inclusive.
//
// the destination start X/Y location must be recorded so that we can
// aligned the pattern correctly.
//
DestClipStart = DestOrigin + EC.DestSkip;
//
// Revised the pattern align point, The BRUSH ORIGIN means the
// halftone's brushes origin (left/top at (0, 0)) will mapped to the
// point specified by the brush origin.
//
StretchInfo.PatternAlign = DestClipStart - pStretchInfo->PatternAlign;
DBGP_IF(DBGP_PATBRUSH,
DBGP("DestOrg=%ld, Skip=%ld, ClipStart=%ld, PatternAlign=%ld -> %ld"
ARGDW(DestOrigin)
ARGDW(EC.DestSkip)
ARGDW(DestClipStart)
ARGDW(pStretchInfo->PatternAlign)
ARGDW(StretchInfo.PatternAlign)));
//
// If we have band rectangle, then we will move the first band's visible
// bit to the left/top 0,0
//
if (CSData.Flags & CSDF_HAS_BANDRECT) {
DestClipStart -= BandStart;
DBGP_IF(DBGP_SETUP0,
DBGP("BandStart = %ld, Reduced DestClipStart = %ld"
ARGDW(BandStart)
ARGDW(DestClipStart)));
}
//
// Assume we are doing the color
//
SizePerColorInfo = (SHORT)sizeof(PRIMCOLOR_COUNT);
//
// Set Temp. DestClipStart/DestClipEnd, the DestClipEnd is inclusive
//
DestClipEnd = (StretchInfo.DestBitOffset = DestClipStart) +
EC.DestExtend - 1;
StretchInfo.DestFullByteSize = EC.DestExtend;
ASSERTMSG("DestExtend is too big", DestClipEnd < DestSize);
DBGP_IF(DBGP_SETUP0,
DBGP("Dest Stretch ** Start=%ld, End=%ld"
ARGDW(DestClipStart) ARGDW(DestClipEnd)));
switch (CSData.DestFormat) {
case BMF_8BPP_VGA256:
StretchInfo.DestByteOffset = DestClipStart;
StretchInfo.DestEdge.FirstByteSkipPels =
StretchInfo.DestEdge.FirstByteMask =
StretchInfo.DestEdge.LastByteSkipPels =
StretchInfo.DestEdge.LastByteMask = (BYTE)0;
break;
case BMF_16BPP_555:
StretchInfo.DestFullByteSize <<= 1;
StretchInfo.DestByteOffset = DestClipStart << 1;
StretchInfo.DestEdge.FirstByteSkipPels =
StretchInfo.DestEdge.FirstByteMask =
StretchInfo.DestEdge.LastByteSkipPels =
StretchInfo.DestEdge.LastByteMask = (BYTE)0;
break;
case BMF_4BPP_VGA16: // 4 bits per pel using all 4 bits
case BMF_4BPP: // 4 Bits Per Pel, !!!We only use lower 3 bits
StretchInfo.DestByteOffset = DestClipStart >> 1;
if (StretchInfo.DestEdge.FirstByteSkipPels =
(BYTE)(DestClipStart & 0x01)) {
StretchInfo.DestEdge.FirstByteMask = (BYTE)0xf0;
--StretchInfo.DestFullByteSize;
} else {
StretchInfo.DestEdge.FirstByteMask = (BYTE)0;
}
if (StretchInfo.DestEdge.LastByteSkipPels =
(BYTE)(1 - (DestClipEnd & 0x01))) {
StretchInfo.DestEdge.LastByteMask = (BYTE)0x0f;
--StretchInfo.DestFullByteSize;
} else {
StretchInfo.DestEdge.LastByteMask = (BYTE)0;
}
ASSERTMSG("Error In compute 4BPP's DestFullByteSize",
(StretchInfo.DestFullByteSize & 0x01) == 0);
StretchInfo.DestFullByteSize >>= 1;
break;
case BMF_1BPP:
//
// Wrong guess!!, we are doing the B/W
//
SizePerColorInfo = (SHORT)sizeof(PRIMMONO_COUNT); // fall through
case BMF_1BPP_3PLANES:
StretchInfo.DestByteOffset = DestClipStart >> 3;
if (StretchInfo.DestEdge.FirstByteSkipPels =
(BYTE)(DestClipStart & 0x07)) {
StretchInfo.DestEdge.FirstByteMask =
(BYTE)~(0xff >> StretchInfo.DestEdge.FirstByteSkipPels);
StretchInfo.DestFullByteSize -=
(LONG)(8 - StretchInfo.DestEdge.FirstByteSkipPels);
} else {
StretchInfo.DestEdge.FirstByteMask = (BYTE)0;
}
//
// The DestClipEnd is inclusive
//
if (StretchInfo.DestEdge.LastByteSkipPels =
(BYTE)(7 - (DestClipEnd & 0x07))) {
StretchInfo.DestEdge.LastByteMask =
(BYTE)~(0xff << StretchInfo.DestEdge.LastByteSkipPels);
StretchInfo.DestFullByteSize -=
(LONG)(8 - StretchInfo.DestEdge.LastByteSkipPels);
} else {
StretchInfo.DestEdge.LastByteMask = (BYTE)0;
}
if (StretchInfo.DestFullByteSize < 0) {
StretchInfo.DestFullByteSize = 0;
}
ASSERTMSG("Error In compute 1BPP's DestFullByteSize",
(StretchInfo.DestFullByteSize & 0x07) == 0);
StretchInfo.DestFullByteSize >>= 3;
break;
default:
return(HTERR_INVALID_DEST_FORMAT);
}
//
// Allocate the PRIMCOLOR/PRIMMONO data structures array if so requested
//
if (ppColorInfo) {
ASSERTMSG("Error: Need not to allocate pColorInfo for Y Stretch",
CSData.Flags & CSDF_X_DIR);
//
// The N Stretch Data works as following
//
// 1 2 3 4 5 .... N-2 N-1 N
// -------------------------------------------------------------------
// Stopper 1stSkip 1stPel 2ndPel 3rdPel NPel LastSkip Stopper
//--------------------------------------------------------------------
// Extra1 Extra2 .... Extra3 Extra4
//
// MONO Case's HEAD TAIL
//
// Prim1 = 0xff Prim1 = 0xff
// Prim2 = 0xff Prim2 = 0xff
// Count = FirstSkipPels Count = LastSkipPels
//
//
StretchSize += STRETCH_EXTRA_SIZE;
SizeColorInfo = (LONG)SizePerColorInfo * StretchSize;
if (!(pColorInfo = (LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"ColorInfo",
NONZEROLPTR,
SizeColorInfo+4))) {
return(HTERR_INSUFFICIENT_MEMORY);
}
#if 0
DBGP("pColorInfo=%lp: StretchSize=%ld x SizePerColorInfo=%ld = %ld"
ARGDW(pColorInfo)
ARGL(StretchSize) ARGL(SizePerColorInfo)
ARGL(SizeColorInfo));
#endif
//
// Assume forward direction, the skip count is alway 1 stretch, which
// is the 'stopper', and skip another one if it is exactly on BYTE
// boundary, The Output always starting from the begining of the
// stretchinfo, if we flip X direction, the source still reading from
// the left to right but only it will put into stretchinfo from right
// to left (backward) direction.
//
CIInputSkip = (LONG)SizePerColorInfo; // assume forward
if (StretchInfo.Flags & SIF_SOURCE_DIR_BACKWARD) {
//
// We starting the input from backward.
//
CIInputSkip = SizeColorInfo - (LONG)(SizePerColorInfo * 2);
StretchInfo.ColorInfoIncrement = -SizePerColorInfo;
} else {
CIInputSkip = (LONG)SizePerColorInfo;
StretchInfo.ColorInfoIncrement = SizePerColorInfo;
}
ppColorInfo[PCI_HEAP_INDEX] = pColorInfo;
ppColorInfo[PCI_INPUT_INDEX] = pColorInfo + CIInputSkip;
if ((SCRCData.SizePerEntry = (WORD)SizePerColorInfo) ==
sizeof(PRIMCOLOR_COUNT)) {
SCRCData.OffsetCount = offsetof(PRIMCOLOR_COUNT, Count);
SCRCData.OffsetPrim1 = offsetof(PRIMCOLOR_COUNT, Color.Prim1);
} else {
SCRCData.OffsetCount = offsetof(PRIMMONO_COUNT, Count);
SCRCData.OffsetPrim1 = offsetof(PRIMMONO_COUNT, Mono.Prim1);
}
//
// The PCI_INPUT_STOPPER is located at FirstSkipPels stretch (at Prim2
// = Prim1 + 1) if direction is going backward, and located at
// LastSkipPels stretch if direction is forward, this stopper is set
// to PRIM_INVALID_DENSITY durning the INPUT function call, so that it
// will stopped right at that stretch, since the input function never
// used the First/LastSkipPels informations which is intented for the
// output function.
//
SetCompressRepeatCount(&StretchInfo,
pColorInfo,
SizeColorInfo,
StretchInfo.DestEdge,
SCRCData,
CSData);
}
//
// Return the StretchInfo
//
*pStretchInfo = StretchInfo;
DBGP_IF(DBGP_STRETCH,
DBGP("\n Flags = 0x%02x" ARGB(StretchInfo.Flags));
DBGP(" StretchMode = %u" ARGW((WORD)StretchInfo.StretchMode));
DBGP(" FirstSrcMaskSkips = %u" ARGW(StretchInfo.FirstSrcMaskSkips));
DBGP(" SrcBitOffset = %ld" ARGDW(StretchInfo.SrcBitOffset));
DBGP(" SrcByteOffset = %ld" ARGDW(StretchInfo.SrcByteOffset));
DBGP(" SrcExtend = %ld" ARGDW(StretchInfo.SrcExtend));
DBGP(" PatternAlign = %ld" ARGDW(StretchInfo.PatternAlign));
DBGP(" DestBitOffset = %ld" ARGDW(StretchInfo.DestBitOffset));
DBGP(" DestByteOffset = %ld" ARGDW(StretchInfo.DestByteOffset));
DBGP(" DestExtend = %ld" ARGDW(StretchInfo.DestExtend));
DBGP(" DestFullByteSize = %ld" ARG(StretchInfo.DestFullByteSize));
DBGP(" SrcMaskBitOffset = %ld" ARGDW(StretchInfo.SrcMaskBitOffset));
DBGP(" SrcMaskByteOffset = %ld\n" ARGDW(StretchInfo.SrcMaskByteOffset));
DBGP(" StretchFactor = %u.%04u" ARGW(StretchInfo.Ratio.StretchFactor / 10000L)
ARGW(StretchInfo.Ratio.StretchFactor % 10000L));
DBGP(" StretchSize = %u" ARGW(StretchInfo.Ratio.StretchSize));
DBGP(" First = %u" ARGW(StretchInfo.Ratio.First));
DBGP(" Single = %u" ARGW(StretchInfo.Ratio.Single));
DBGP(" Last = %u" ARGW(StretchInfo.Ratio.Last));
DBGP(" MinFactor = %u" ARGW(StretchInfo.Ratio.MinFactor));
DBGP(" MaxFactor = %u" ARGW(StretchInfo.Ratio.MaxFactor));
DBGP(" RatioError = %ld" ARGDW(StretchInfo.Ratio.Error));
DBGP(" RatioSub = %ld" ARGDW(StretchInfo.Ratio.Sub));
DBGP(" RatioAdd = %ld\n" ARGDW(StretchInfo.Ratio.Add));
DBGP("DestEdge.FirstByteSkipPels = %u" ARGW(StretchInfo.DestEdge.FirstByteSkipPels));
DBGP(" DestEdge.LastByteSkipPels = %u" ARGW(StretchInfo.DestEdge.LastByteSkipPels));
DBGP(" DestEdge.FirstByteMask = 0x%02x" ARGB(StretchInfo.DestEdge.FirstByteMask));
DBGP(" DestEdge.LastByteMask = 0x%02x\n" ARGB(StretchInfo.DestEdge.LastByteMask));
DBGP(" SrcMaskOffsetMask = 0x%02x" ARGB(StretchInfo.SrcMaskOffsetMask));
DBGP(" SrcOffsetByteMask = 0x%02x" ARGB(StretchInfo.SrcOffsetByteMask));
DBGP(" BMF1BPPOffsetByteBitShift = %u" ARGW(StretchInfo.BMF1BPPOffsetByteBitShift));
DBGP(" ColorInfoIncrement = %d" ARGS(StretchInfo.ColorInfoIncrement));
DBGP("--------------------------------------------------------------------");
DBGP(" SOURCE SurfaceFormat = %u" ARGW(CSData.SrcFormat));
DBGP(" DESTINATION SurfaceFormat = %u" ARGW(CSData.DestFormat));
DBGP(" pColorInfo = %p" ARG((ppColorInfo) ? pColorInfo : 0L));
DBGP(" pSrcMaskLine = %p" ARG((pInputSI) ? pInputSI->pSrcMaskLine : 0L));
DBGP(" SizeSrcMaskLine = %ld\n" ARGDW((pInputSI) ? pInputSI->SizeSrcMaskLine : 0L));
);
return(StretchInfo.Ratio.StretchSize);
}
#define HT_SRC_TD 0x0001
#define HT_DEST_TD 0x0002
#define HT_SRCMASK_TD 0x0004
#define IS_HTSIF_TD(CBParam) ((CBParam).Flags & HTSIF_SCANLINES_TOPDOWN)
LONG
HTENTRY
RenderStretchSetup(
PHALFTONERENDER pHR
)
/*++
Routine Description:
This function setup the source to destination stretches (ie. copy,
compress, expansion) for both X and Y direction.
Arguments:
pHalftoneRender - Pointer to the HALFTONERENDER data structure.
The pHalftoneRender->OutputSI and
pHalftoneRender->YStretch data structures will
be filled with the parameters if function sucessful.
Note: if the Source/Destination rectangle is not well orderd then for
not well ordered direction will be flipped.
Return Value:
a negative return value indicate failure.
HTERR_INSUFFICIENT_MEMORY - if memory allocation errors occurred.
HTERR_SRC_MASK_BITS_TOO_SMALL- If the source mask bitmap is too small to
cover the visible region of the source
bitmap.
HTERR_INVALID_SRC_MASK_BITS - The source mask bitmap is NULL while flag
indicate that there is a source mask bitmap
pointer.
HTERR_INTERNAL_ERRORS_START - Other negative nubmer indicate internal
failue.
else - the total PRIMCOLOR/PRIMMONO data structures
allocated, a zero indicate destination is
fully clipped.
Author:
22-Jan-1991 Tue 12:53:59 created -by- Daniel Chou (danielc)
Revision History:
26-Jul-1991 Fri 01:00:30 updated -by- Daniel Chou (danielc)
Fixed the typo when calculate the source/source mask scan line start,
it was mistaken to using the destination flags.
19-Mar-1993 Fri 10:22:08 updated -by- Daniel Chou (danielc)
The HTSurfaceInfo.Height can be negative, if negative then
HTSIF_SCANLINES_TOPDOWN flag must flip, according to the gdi sepc. if
Height is a negative number then the upper-left corner is the bitmap's
origin and if it is a positive number then lower-left is the bitmap's
origin.
--*/
{
PBITBLTPARAMS pBBP = pHR->HR_Header.pBitbltParams;
LONG SrcXExtend;
LONG DestXExtend;
LONG SrcYExtend;
LONG DestYExtend;
LONG DestLines;
LONG Height;
LONG Result;
CSDATA CSData;
WORD XFlags;
WORD YFlags;
WORD TopDowns;
DBGP_IF(DBGP_SETUP0,
DBGP("** SrcSurf SIZE: [%ld x %ld]"
ARGDW(pHR->InputSI.SrcCBParams.HTCB_TEMP_WIDTH)
ARGDW(pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT));
DBGP("** DestSurf SIZE: [%ld x %ld]"
ARGDW(pHR->OutputSI.DestCBParams.HTCB_TEMP_WIDTH)
ARGDW(pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT));
DBGP("** SrcBitmap: X=%ld-%ld [%ld], Y=%ld-%ld [%ld]"
ARGDW(pBBP->rclSrc.left) ARGDW(pBBP->rclSrc.right)
ARGDW(pBBP->rclSrc.right - pBBP->rclSrc.left)
ARGDW(pBBP->rclSrc.top) ARGDW(pBBP->rclSrc.bottom)
ARGDW(pBBP->rclSrc.bottom - pBBP->rclSrc.top));
DBGP("** DestBitmap: X=%ld-%ld [%ld], Y=%ld-%ld [%ld], BrushOrg=(%ld, %ld)"
ARGDW(pBBP->rclDest.left) ARGDW(pBBP->rclDest.right)
ARGDW(pBBP->rclDest.right - pBBP->rclDest.left)
ARGDW(pBBP->rclDest.top) ARGDW(pBBP->rclDest.bottom)
ARGDW(pBBP->rclDest.bottom - pBBP->rclDest.top)
ARGDW(pBBP->ptlBrushOrg.x) ARGDW(pBBP->ptlBrushOrg.y));
if (pBBP->Flags & BBPF_HAS_DEST_CLIPRECT) {
DBGP("** DestBitmap CLIP: X = %4ld - %4ld [%4ld], Y = %4ld - %4ld [%4ld]"
ARGDW(pBBP->rclClip.left) ARGDW(pBBP->rclClip.right)
ARGDW(pBBP->rclClip.right - pBBP->rclClip.left)
ARGDW(pBBP->rclClip.top) ARGDW(pBBP->rclClip.bottom)
ARGDW(pBBP->rclClip.bottom - pBBP->rclClip.top));
}
if (pBBP->Flags & BBPF_HAS_BANDRECT) {
DBGP("** DestBitmap BAND: X = %4ld - %4ld [%4ld], Y = %4ld - %4ld [%4ld]"
ARGDW(pBBP->rclBand.left) ARGDW(pBBP->rclBand.right)
ARGDW(pBBP->rclBand.right - pBBP->rclBand.left)
ARGDW(pBBP->rclBand.top) ARGDW(pBBP->rclBand.bottom)
ARGDW(pBBP->rclBand.bottom - pBBP->rclBand.top));
}
if (pHR->HR_Header.pSrcMaskSI) {
DBGP("** SrcMaskBitmap: Size = (%ld, %ld), ptlSrcMask = (%ld, %ld)"
ARGDW(pHR->HR_Header.pSrcMaskSI->Width)
ARGDW(pHR->HR_Header.pSrcMaskSI->Height)
ARGDW(pBBP->ptlSrcMask.x) ARGDW(pBBP->ptlSrcMask.y));
}
);
DBGP_IF(DBGP_PATBRUSH,
DBGP(" ** ptlBrushOrg = (%ld, %ld) **"
ARGDW(pBBP->ptlBrushOrg.x) ARGDW(pBBP->ptlBrushOrg.y)));
//
// 19-Mar-1993 Fri 10:26:21 updated -by- Daniel Chou (danielc)
// Check if a negative height been specified.
TopDowns = (WORD)(((IS_HTSIF_TD(pHR->InputSI.SrcCBParams)) ?
HT_SRC_TD : 0) |
((IS_HTSIF_TD(pHR->OutputSI.DestCBParams)) ?
HT_DEST_TD : 0));
if (pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT < 0) {
TopDowns ^= HT_SRC_TD;
pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT =
-pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT;
}
if (pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT < 0) {
TopDowns ^= HT_DEST_TD;
pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT =
-pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT;
}
if (pHR->InputSI.Flags & ISIF_HAS_SRC_MASK) {
if (IS_HTSIF_TD(pHR->InputSI.SrcMaskCBParams)) {
TopDowns |= HT_SRCMASK_TD;
}
if (pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_HEIGHT < 0) {
TopDowns ^= HT_SRCMASK_TD;
pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_HEIGHT =
-pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_HEIGHT;
}
}
DestLines = pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT;
CSData.SrcFormat = pHR->InputSI.SrcCBParams.SurfaceFormat;
CSData.DestFormat = pHR->OutputSI.DestCBParams.SurfaceFormat;
XFlags = (WORD)CSDF_X_DIR;
YFlags = (WORD)0;
//
// Check if we need to flip the parameters (mirror), this will only
// occurred if the source/destination width has different sign.
//
if (pBBP->Flags & BBPF_HAS_DEST_CLIPRECT) {
XFlags |= CSDF_HAS_CLIPRECT;
YFlags |= CSDF_HAS_CLIPRECT;
}
if (pBBP->Flags & BBPF_HAS_BANDRECT) {
//
// This flag only need to be set for the X direction, the Y direction
// will be computed in the function, because we may need to flipped
// the destination up-side-down.
//
XFlags |= CSDF_HAS_BANDRECT;
YFlags |= CSDF_HAS_BANDRECT;
}
//
// calculate the height stretch flags.
//
// Check if we need to flip the parameters (up-side down), this will only
// occurred if the source/destination height has different sign.
//
if ((SrcYExtend = pBBP->rclSrc.bottom - pBBP->rclSrc.top) < 0L) {
//
// Flip the source in X direction, the left,top, bottom,right must
// well orderd.
//
pBBP->rclSrc.top = pBBP->rclSrc.bottom; // make new origin
SrcYExtend = -SrcYExtend;
YFlags ^= CSDF_FLIP_SOURCE;
}
if ((DestYExtend = pBBP->rclDest.bottom - pBBP->rclDest.top) < 0L) {
//
// Flip the destination in X direction, the left,top, bottom,right must
// well orderd.
//
pBBP->rclDest.top = pBBP->rclDest.bottom; // make new origin
DestYExtend = -DestYExtend;
YFlags ^= CSDF_FLIP_SOURCE;
}
//
// If we have source mask bitmap then tell it calculate the offset also.
//
if (pHR->InputSI.Flags & ISIF_HAS_SRC_MASK) {
XFlags |= (WORD)(CSDF_HAS_SRC_MASK | CSDF_SRCMASKINFO);
YFlags |= (WORD)CSDF_HAS_SRC_MASK;
}
//
// Stetch the width first
//
if ((SrcXExtend = pBBP->rclSrc.right - pBBP->rclSrc.left) < 0L) {
//
// Flip the source in X direction, the left,top, bottom,right must
// well orderd.
//
pBBP->rclSrc.left = pBBP->rclSrc.right; // make new origin
SrcXExtend = -SrcXExtend;
XFlags ^= CSDF_FLIP_SOURCE;
}
if ((DestXExtend = pBBP->rclDest.right - pBBP->rclDest.left) < 0L) {
//
// Flip the destination in X direction, the left,top, bottom,right must
// well orderd.
//
pBBP->rclDest.left = pBBP->rclDest.right; // make new origin
DestXExtend = -DestXExtend;
XFlags ^= CSDF_FLIP_SOURCE;
}
if ((!SrcXExtend) || (!SrcYExtend) || (!DestXExtend) || (!DestYExtend)) {
return(0);
}
//
// First, calculate the width stretch.
//
CSData.Flags = XFlags; // get it from calculated X flag
//
// We must set the Brush Origin before the call
//
pHR->XStretch.PatternAlign = pBBP->ptlBrushOrg.x;
if ((Result = CalculateStretch(
pHR->HR_Header.pDeviceColorInfo,
(PSTRETCHINFO)&(pHR->XStretch),
pBBP->rclSrc.left,
SrcXExtend,
pHR->InputSI.SrcCBParams.HTCB_TEMP_WIDTH,
pBBP->rclDest.left,
DestXExtend,
pHR->OutputSI.DestCBParams.HTCB_TEMP_WIDTH,
pBBP->rclClip.left,
pBBP->rclClip.right,
pBBP->rclBand.left,
pBBP->rclBand.right,
pBBP->ptlSrcMask.x,
pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_WIDTH,
(PLPBYTE)pHR->pColorInfo,
&(pHR->InputSI),
CSData)) <= 0) {
FreeHRMemory(pHR);
return(Result);
}
CSData.Flags = YFlags; // get it from calculated Y flag
pHR->YStretch.PatternAlign = pBBP->ptlBrushOrg.y;
if ((Result = CalculateStretch(
pHR->HR_Header.pDeviceColorInfo,
(PSTRETCHINFO)&(pHR->YStretch),
pBBP->rclSrc.top,
SrcYExtend,
pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT,
pBBP->rclDest.top,
DestYExtend,
pHR->OutputSI.DestCBParams.HTCB_TEMP_HEIGHT,
pBBP->rclClip.top,
pBBP->rclClip.bottom,
pBBP->rclBand.top,
pBBP->rclBand.bottom,
pBBP->ptlSrcMask.y,
pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_HEIGHT,
NULL,
NULL,
CSData)) <= 0) {
FreeHRMemory(pHR);
return(Result);
}
//
// Check if the source is 32-bit per pel format and if so, see if it need
// to translate to RGB or it already in RGB format
//
#if 0
if (pHR->InputSI.SrcCBParams.SurfaceFormat == BMF_32BPP) {
//
// If the last 3 bytes used as RGB value then we will advance
// width offset byte by 1 for later RGB access. Note: the
// FirstColorIndex at here must be 0 or 1, we already check this
// value before calling this function.
// (see htrender.c's ValidateHTSI())
//
pHR->XStretch.SrcByteOffset +=
(DWORD)(pHR->HR_Header.pSrcSI->FirstColorIndex);
}
#endif
//
// If the height need to be flipped on the source, make BytesPerScanLine
// negative. Do that for both source and destination
//
// When we arrive here, the source/destination format is guaranteed are
// valid, and width of the source/destination is non zero.
//
// We also have calculate if the physical bitmap is flip top/down, that
// is if the bitmap first scan line is the bottom of the bitmap, if so
// we calculate the ScanStart, ScanCount in opposite direction.
//
// Note: The assumtion here is that when HalftoneRender passed, the
// InputSI is zero filled.
//
// Setup the source partial callback parameters, we must first calculate
// the source's scan line start number and the total bytes to next scanline
// assuming that scan lines are top down, it not then we flip the direction
// of ScanStart/ScanByte.
//
Height = pHR->InputSI.SrcCBParams.HTCB_TEMP_HEIGHT;
pHR->InputSI.SrcCBParams.ScanStart = (LONG)((TopDowns & HT_SRC_TD) ?
pHR->YStretch.SrcBitOffset :
(Height - 1L - pHR->YStretch.SrcBitOffset));
pHR->InputSI.SrcCBParams.RemainedSize = pHR->YStretch.SrcExtend;
if (YFlags & CSDF_FLIP_SOURCE) {
TopDowns ^= HT_SRC_TD;
}
if (!(TopDowns & HT_SRC_TD)) {
pHR->InputSI.SrcCBParams.BytesPerScanLine =
-pHR->InputSI.SrcCBParams.BytesPerScanLine;
}
//
// Setup the destination partial callback parameters.
//
// NOTE: The destination will ALWAYS logically from top to bottom and from
// left to right, when the bitmap is not TOPDOWN type then it still
// top->down, left->right even physically it loading the bitmap
// up-side-down, that is the destination pattern alignment must
// always using logical coordinate.
//
if (pBBP->Flags & BBPF_HAS_BANDRECT) {
//
// This is the new destination buffer height
//
DestLines = pBBP->rclBand.bottom - pBBP->rclBand.top;
//
// Re-compute the destination width when BAND is specified
//
pHR->OutputSI.DestCBParams.BytesPerScanLine =
ComputeBytesPerScanLine(
(WORD)pHR->OutputSI.DestCBParams.SurfaceFormat,
(WORD)pHR->HR_Header.pDestSI->ScanLineAlignBytes,
(DWORD)pBBP->rclBand.right - pBBP->rclBand.left);
if ((LONG)pHR->OutputSI.DestCBParams.MaximumQueryScanLines
>= DestLines) {
pHR->OutputSI.DestCBParams.MaximumQueryScanLines = (WORD)DestLines;
}
}
//
// Compute the planer's bytes per plane if destination is
// BMF_1BPP_3PLANES and caller did not specified the BytesPerPlane field
// (ie. specified a zero)
//
if ((CSData.DestFormat == BMF_1BPP_3PLANES) &&
(!pHR->OutFuncInfo.BytesPerPlane)) {
pHR->OutFuncInfo.BytesPerPlane =
(DWORD)DestLines *
(DWORD)pHR->OutputSI.DestCBParams.BytesPerScanLine;
DBGP_IF(DBGP_SETUP0,
DBGP("** Dest=BMF_1BPP_3PLANES: CY = %ld (@%ld) = %ld bytes"
ARGL(DestLines)
ARGL(pHR->OutputSI.DestCBParams.BytesPerScanLine)
ARGL(pHR->OutFuncInfo.BytesPerPlane)));
}
pHR->OutputSI.DestCBParams.RemainedSize = pHR->YStretch.DestExtend;
if (TopDowns & HT_DEST_TD) {
pHR->OutputSI.DestCBParams.ScanStart = pHR->YStretch.DestBitOffset;
} else {
//
// ** Remember: The rcBand.right/rcBand.bottom is EXclusive
//
pHR->OutputSI.DestCBParams.ScanStart = DestLines - 1L -
pHR->YStretch.DestBitOffset;
pHR->OutputSI.DestCBParams.BytesPerScanLine =
-pHR->OutputSI.DestCBParams.BytesPerScanLine;
}
//
// Calculate the source mask bitmap infomation, if one present
//
if (pHR->InputSI.Flags & ISIF_HAS_SRC_MASK) {
//
// Internally, we will set bit to 1 if the destination have to be
// preserved, and overwrite the destination if the bit is 0, that
// is why we have to invert the source mask bitmap.
//
pHR->CAOTBAInfo.BytesCount = pHR->InputSI.SizeSrcMaskLine;
pHR->CAOTBAInfo.Flags = (WORD)((pBBP->Flags & BBPF_INVERT_SRC_MASK) ?
CAOTBAF_INVERT : 0);
//
//
// Do we need to flip the source mask X/Y directions if the source is
// flip?, is the source mask is rotated according to the source bitmap
// that is?
//
Height = pHR->InputSI.SrcMaskCBParams.HTCB_TEMP_HEIGHT;
pHR->InputSI.SrcMaskCBParams.ScanStart = (LONG)
((TopDowns & HT_SRCMASK_TD) ?
pHR->YStretch.SrcMaskBitOffset :
(Height - 1L - pHR->YStretch.SrcMaskBitOffset));
pHR->InputSI.SrcMaskCBParams.RemainedSize = pHR->YStretch.SrcExtend;
if (YFlags & CSDF_FLIP_SOURCE) {
TopDowns ^= HT_SRCMASK_TD;
}
if (!(TopDowns & HT_SRCMASK_TD)) {
pHR->InputSI.SrcMaskCBParams.BytesPerScanLine =
-pHR->InputSI.SrcMaskCBParams.BytesPerScanLine;
}
}
//
// Make sure we do call DoHTCallBack() at very first time
//
pHR->InputSI.SrcCBParams.ScanCount =
pHR->InputSI.SrcMaskCBParams.ScanCount =
pHR->OutputSI.DestCBParams.ScanCount = 0;
return(Result);
}