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.
5056 lines
149 KiB
5056 lines
149 KiB
/*++
|
|
|
|
Copyright (c) 1990-1991 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
htapi.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module contains all the halftone entry points which communicate
|
|
with caller to the halftone dll.
|
|
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 10:52:03 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
[Environment:]
|
|
|
|
GDI Device Driver - Halftone.
|
|
|
|
|
|
[Notes:]
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#define DBGP_VARNAME dbgpHTAPI
|
|
|
|
#define _HTAPI_ENTRY_
|
|
|
|
#include "htp.h"
|
|
#include "htmapclr.h"
|
|
#include "htpat.h"
|
|
#include "htrender.h"
|
|
#include "htmath.h"
|
|
#include "htalias.h"
|
|
#include "htsetbmp.h"
|
|
#include "stdio.h"
|
|
|
|
#define INCLUDE_DEF_CIEINFO
|
|
#include "htapi.h"
|
|
|
|
|
|
#define DBGP_SHOWPAT 0x00000001
|
|
#define DBGP_TIMER 0x00000002
|
|
#define DBGP_CACHED_DCI 0x00000004
|
|
#define DBGP_CACHED_SMP 0x00000008
|
|
#define DBGP_DISABLE_HT 0x00000010
|
|
#define DBGP_DYECORRECTION 0x00000020
|
|
#define DBGP_DHI_MEM 0x00000040
|
|
#define DBGP_COMPUTE_L2I 0x00000080
|
|
#define DBGP_HTMUTEX 0x00000100
|
|
#define DBGP_GAMMA_PAL 0x00000200
|
|
#define DBGP_CHB 0x00000400
|
|
#define DBGP_DEVPELSDPI 0x00000800
|
|
#define DBGP_SRCBMP 0x00001000
|
|
#define DBGP_TILE 0x00002000
|
|
#define DBGP_HTAPI 0x00004000
|
|
#define DBGP_MEMLINK 0x00008000
|
|
#define DBGP_SHOW_CSMBMP 0x00010000
|
|
|
|
|
|
|
|
DEF_DBGPVAR(BIT_IF(DBGP_SHOWPAT, 0) |
|
|
BIT_IF(DBGP_TIMER, 0) |
|
|
BIT_IF(DBGP_CACHED_DCI, 0) |
|
|
BIT_IF(DBGP_CACHED_SMP, 0) |
|
|
BIT_IF(DBGP_DISABLE_HT, 0) |
|
|
BIT_IF(DBGP_DYECORRECTION, 0) |
|
|
BIT_IF(DBGP_DHI_MEM, 0) |
|
|
BIT_IF(DBGP_COMPUTE_L2I, 0) |
|
|
BIT_IF(DBGP_HTMUTEX, 0) |
|
|
BIT_IF(DBGP_GAMMA_PAL, 0) |
|
|
BIT_IF(DBGP_CHB, 0) |
|
|
BIT_IF(DBGP_DEVPELSDPI, 0) |
|
|
BIT_IF(DBGP_SRCBMP, 0) |
|
|
BIT_IF(DBGP_TILE, 0) |
|
|
BIT_IF(DBGP_HTAPI, 0) |
|
|
BIT_IF(DBGP_MEMLINK, 0) |
|
|
BIT_IF(DBGP_SHOW_CSMBMP, 0))
|
|
|
|
|
|
HTGLOBAL HTGlobal = { (HMODULE)NULL,
|
|
(HTMUTEX)NULL,
|
|
(HTMUTEX)NULL,
|
|
(HTMUTEX)NULL,
|
|
(PCDCIDATA)NULL,
|
|
(PCSMPDATA)NULL,
|
|
(PBGRMAPCACHE)NULL,
|
|
(LONG)0,
|
|
(LONG)0,
|
|
(LONG)0,
|
|
(WORD)0,
|
|
(WORD)0
|
|
};
|
|
|
|
#define DO_DYES_CORRECTION 0
|
|
|
|
#define CMY_8BPP(b, i, m, t) \
|
|
{ \
|
|
if ((i) < (m)) { \
|
|
\
|
|
(t) = FD6_1 - DivFD6((FD6)(i),(FD6)(m)); \
|
|
(b) = (BYTE)SCALE_FD6((t), 255); \
|
|
\
|
|
} else { \
|
|
\
|
|
(b) = 0; \
|
|
} \
|
|
}
|
|
|
|
|
|
#define RGB_8BPP(rgb) (BYTE)SCALE_FD6((rgb), 255)
|
|
#define GET_DEN_LO(x) DivFD6((FD6)((((x) ) & 0xFF) + 1), (FD6)256)
|
|
#define GET_DEN_HI(x) DivFD6((FD6)((((x) >> 8) & 0xFF) + 1), (FD6)256)
|
|
|
|
|
|
#if DBG
|
|
|
|
|
|
LONG
|
|
HTENTRY
|
|
HT_LOADDS
|
|
SetHalftoneError(
|
|
DWORD HT_FuncIndex,
|
|
LONG ErrorID
|
|
)
|
|
{
|
|
const static LPSTR HTApiFuncName[] = {
|
|
|
|
"HalftoneInitProc",
|
|
"HT_CreateDeviceHalftoneInfo",
|
|
"HT_DestroyDeviceHalftoneInfo",
|
|
"HT_CreateHalftoneBrush",
|
|
"HT_ConvertColorTable",
|
|
"HT_CreateStandardMonoPattern",
|
|
"HT_HalftoneBitmap",
|
|
};
|
|
|
|
|
|
const static LPSTR HTErrorStr[] = {
|
|
|
|
"WRONG_VERSION_HTINITINFO",
|
|
"INSUFFICIENT_MEMORY",
|
|
"CANNOT_DEALLOCATE_MEMORY",
|
|
"COLORTABLE_TOO_BIG",
|
|
"QUERY_SRC_BITMAP_FAILED",
|
|
"QUERY_DEST_BITMAP_FAILED",
|
|
"QUERY_SRC_MASK_FAILED",
|
|
"SET_DEST_BITMAP_FAILED",
|
|
"INVALID_SRC_FORMAT",
|
|
"INVALID_SRC_MASK_FORMAT",
|
|
"INVALID_DEST_FORMAT",
|
|
"INVALID_DHI_POINTER",
|
|
"SRC_MASK_BITS_TOO_SMALL",
|
|
"INVALID_HTPATTERN_INDEX",
|
|
"INVALID_HALFTONE_PATTERN",
|
|
"HTPATTERN_SIZE_TOO_BIG",
|
|
"NO_SRC_COLORTRIAD",
|
|
"INVALID_COLOR_TABLE",
|
|
"INVALID_COLOR_TYPE",
|
|
"INVALID_COLOR_TABLE_SIZE",
|
|
"INVALID_PRIMARY_SIZE",
|
|
"INVALID_PRIMARY_VALUE_MAX",
|
|
"INVALID_PRIMARY_ORDER",
|
|
"INVALID_COLOR_ENTRY_SIZE",
|
|
"INVALID_FILL_SRC_FORMAT",
|
|
"INVALID_FILL_MODE_INDEX",
|
|
"INVALID_STDMONOPAT_INDEX",
|
|
"INVALID_DEVICE_RESOLUTION",
|
|
"INVALID_TONEMAP_VALUE",
|
|
"NO_TONEMAP_DATA",
|
|
"TONEMAP_VALUE_IS_SINGULAR",
|
|
"INVALID_BANDRECT",
|
|
"STRETCH_RATIO_TOO_BIG",
|
|
"CHB_INV_COLORTABLE_SIZE",
|
|
"HALFTONE_INTERRUPTTED",
|
|
"HTERR_NO_SRC_HTSURFACEINFO",
|
|
"HTERR_NO_DEST_HTSURFACEINFO",
|
|
"HTERR_8BPP_PATSIZE_TOO_BIG",
|
|
"HTERR_16BPP_555_PATSIZE_TOO_BIG"
|
|
};
|
|
|
|
const static LPSTR HTPErrorStr[] = {
|
|
|
|
"STRETCH_FACTOR_TOO_BIG",
|
|
"XSTRETCH_FACTOR_TOO_BIG",
|
|
"STRETCH_NEG_OVERHANG",
|
|
"COLORSPACE_NOT_MATCH",
|
|
"INVALID_SRCRGB_SIZE",
|
|
"INVALID_DEVRGB_SIZE"
|
|
};
|
|
|
|
|
|
LPSTR pFuncName;
|
|
LONG ErrorIdx;
|
|
BOOL MapErrorOk = FALSE;
|
|
|
|
if (ErrorID < 0) {
|
|
|
|
if (HT_FuncIndex < (sizeof(HTApiFuncName) / sizeof(LPSTR))) {
|
|
|
|
pFuncName = HTApiFuncName[HT_FuncIndex];
|
|
|
|
} else {
|
|
|
|
pFuncName = "Invalid HT API Function Name";
|
|
}
|
|
|
|
ErrorIdx = -ErrorID;
|
|
|
|
if (ErrorIdx <= (sizeof(HTErrorStr) / sizeof(LPSTR))) {
|
|
|
|
DBGP("%s failed: HTERR_%s (%ld)"
|
|
ARG(pFuncName)
|
|
ARG(HTErrorStr[ErrorIdx - 1])
|
|
ARGL(ErrorID));
|
|
DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
|
|
|
MapErrorOk = TRUE;
|
|
|
|
} else if (ErrorIdx >= -(LONG)HTERR_INTERNAL_ERRORS_START) {
|
|
|
|
ErrorIdx += (LONG)HTERR_INTERNAL_ERRORS_START;
|
|
|
|
if (ErrorIdx < (sizeof(HTPErrorStr) / sizeof(LPSTR))) {
|
|
|
|
DBGP("%s Internal Error: %s (%ld)"
|
|
ARG(pFuncName)
|
|
ARG(HTPErrorStr[ErrorIdx])
|
|
ARGL(ErrorID));
|
|
DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
|
|
|
MapErrorOk = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if (!MapErrorOk) {
|
|
|
|
DBGP("%s failed: ??Invalid Error ID (%ld)"
|
|
ARG(pFuncName) ARGL(ErrorID));
|
|
DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
|
}
|
|
}
|
|
|
|
return(ErrorID);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
PASCAL
|
|
HT_LOADDS
|
|
EnableHalftone(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initialize all internal halftone global data to have
|
|
halftone DLL/LIB ready to be used
|
|
|
|
This function MUST called from ALL API entries which does not required
|
|
a PDEVICEHALFTONEINFO data pointer
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Author:
|
|
|
|
02-Mar-1993 Tue 19:38:43 created -by- Daniel Chou (danielc)
|
|
|
|
15-Dec-1995 Fri 16:48:46 updated -by- Daniel Chou (danielc)
|
|
All initialization is done at here
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
FD6 L;
|
|
UINT i;
|
|
|
|
|
|
if (!(HTGlobal.HTMutexBGRMC = CREATE_HTMUTEX())) {
|
|
|
|
DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexBGRMC) failed!");
|
|
return(FALSE);
|
|
}
|
|
|
|
HTGlobal.pBGRMC = NULL;
|
|
HTGlobal.cBGRMC =
|
|
HTGlobal.cIdleBGRMC =
|
|
HTGlobal.cAllocBGRMC = 0;
|
|
|
|
if (!(HTGlobal.HTMutexCDCI = CREATE_HTMUTEX())) {
|
|
|
|
DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCDCI) failed!");
|
|
return(FALSE);
|
|
}
|
|
|
|
HTGlobal.CDCICount = 0;
|
|
|
|
if (!(HTGlobal.HTMutexCSMP = CREATE_HTMUTEX())) {
|
|
|
|
DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCSMP) failed!");
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
HTGlobal.CSMPCount = 0;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
PASCAL
|
|
HT_LOADDS
|
|
DisableHalftone(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function free CDCI/CSMP cached data
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
This function must called when gdisrv.dll is unloaded, sinnce halftone
|
|
is a linked as a library not a individual DLL.
|
|
|
|
Author:
|
|
|
|
20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
HLOCAL hData;
|
|
PCDCIDATA pCDCIData;
|
|
PCSMPDATA pCSMPData;
|
|
PCSMPBMP pCSMPBmp;
|
|
LONG i;
|
|
extern LPWORD ppwHTPat[HTPAT_SIZE_MAX_INDEX];
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: UsedCount: CDCI=%u, CSMP=%u"
|
|
ARGU(HTGlobal.CDCICount)
|
|
ARGU(HTGlobal.CSMPCount)));
|
|
|
|
//
|
|
// Do the BGRMapCache first
|
|
//
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexBGRMC);
|
|
|
|
if (HTGlobal.pBGRMC) {
|
|
|
|
for (i = 0; i < HTGlobal.cBGRMC; i++) {
|
|
|
|
hData = (HLOCAL)HTGlobal.pBGRMC[i].pMap;
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: HTFreeMem(pBGRMC[%ld].pMap=%p"
|
|
ARGDW(i) ARGPTR(hData)));
|
|
|
|
hData = HTFreeMem(hData);
|
|
|
|
ASSERTMSG("FreeHTGlobal: HTFreeMem(BGRMap) Failed", !hData);
|
|
}
|
|
|
|
hData = (HLOCAL)HTGlobal.pBGRMC;
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: HTFreeMem(pBGRMC=%p" ARGPTR(hData)));
|
|
|
|
hData = HTFreeMem(hData);
|
|
|
|
ASSERTMSG("FreeHTGlobal: HTFreeMem(pBGRMC) Failed", !hData);
|
|
}
|
|
|
|
HTGlobal.cBGRMC =
|
|
HTGlobal.cIdleBGRMC =
|
|
HTGlobal.cAllocBGRMC = 0;
|
|
HTGlobal.pBGRMC = NULL;
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexBGRMC);
|
|
DELETE_HTMUTEX(HTGlobal.HTMutexBGRMC);
|
|
|
|
//
|
|
// Do the CDCI Data first
|
|
//
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
pCDCIData = HTGlobal.pCDCIDataHead;
|
|
|
|
while (hData = (HLOCAL)pCDCIData) {
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: HTFreeMem(pCDCIDATA=%p"
|
|
ARGPTR(pCDCIData)));
|
|
|
|
pCDCIData = pCDCIData->pNextCDCIData;
|
|
hData = HTFreeMem(hData);
|
|
|
|
ASSERTMSG("FreeHTGlobal: HTFreeMem(CDCI) Failed", !hData);
|
|
}
|
|
|
|
HTGlobal.pCDCIDataHead = NULL;
|
|
HTGlobal.CDCICount = 0;
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
DELETE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
HTGlobal.HTMutexCDCI = (HTMUTEX)0;
|
|
|
|
//
|
|
// Do the bitmap pattern now
|
|
//
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
|
|
pCSMPData = HTGlobal.pCSMPDataHead;
|
|
|
|
while (pCSMPData) {
|
|
|
|
pCSMPBmp = pCSMPData->pCSMPBmpHead;
|
|
|
|
while (hData = (HLOCAL)pCSMPBmp) {
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: HTFreeMem(pCSMPBmp=%p"
|
|
ARGPTR(pCSMPBmp)));
|
|
|
|
pCSMPBmp = pCSMPBmp->pNextCSMPBmp;
|
|
hData = HTFreeMem(hData);
|
|
|
|
ASSERTMSG("FreeHTGlobal: HTFreeMem(CSMPBMP) Failed", !hData);
|
|
}
|
|
|
|
hData = (HLOCAL)pCSMPData;
|
|
pCSMPData = pCSMPData->pNextCSMPData;
|
|
hData = HTFreeMem(hData);
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTGlobal: HTFreeMem(pCSMPData=%p"
|
|
ARGPTR(pCSMPData)));
|
|
|
|
ASSERTMSG("FreeHTGlobal: HTFreeMem(CSMPDATA) Failed", !hData);
|
|
}
|
|
|
|
HTGlobal.pCSMPDataHead = NULL;
|
|
HTGlobal.CSMPCount = 0;
|
|
|
|
for (i = 0; i < HTPAT_SIZE_MAX_INDEX; i++) {
|
|
|
|
if (hData = (HLOCAL)ppwHTPat[i]) {
|
|
|
|
DBGP_IF(DBGP_DISABLE_HT,
|
|
DBGP("FreeHTPat: HTFreeMem(ppwHTPat[%2ld]=%p"
|
|
ARGDW(i) ARGPTR(hData)));
|
|
|
|
HTFreeMem(hData);
|
|
ppwHTPat[i] = NULL;
|
|
}
|
|
}
|
|
|
|
CHK_MEM_LEAK(NULL, HTMEM_BEGIN);
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
DELETE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
|
|
HTGlobal.HTMutexCSMP = (HTMUTEX)NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
HTENTRY
|
|
CleanUpDHI(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function clean up (free hMutex/memory) of a DeviceHalftoneInfo
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - the pDeviceHalftoneInfo must be valid
|
|
|
|
Return Value:
|
|
|
|
BOOL
|
|
|
|
|
|
Author:
|
|
|
|
20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICECOLORINFO pDCI;
|
|
HTMUTEX HTMutex;
|
|
HLOCAL hData;
|
|
UINT Loop;
|
|
BOOL Ok = TRUE;
|
|
|
|
|
|
|
|
pDCI = PDHI_TO_PDCI(pDeviceHalftoneInfo);
|
|
|
|
ACQUIRE_HTMUTEX(pDCI->HTMutex);
|
|
|
|
HTMutex = pDCI->HTMutex;
|
|
|
|
//
|
|
// Free all memory assoicated with this device
|
|
//
|
|
|
|
if ((pDCI->HTCell.pThresholds) &&
|
|
(!(pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS))) {
|
|
|
|
DBGP_IF(DBGP_DHI_MEM,
|
|
DBGP("CleanUpDHI: HTFreeMem(pDCI->HTCell.pThresholds=%p)"
|
|
ARGPTR(pDCI->HTCell.pThresholds)));
|
|
|
|
if (HTFreeMem(pDCI->HTCell.pThresholds)) {
|
|
|
|
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->HTCell.pThresholds)", FALSE);
|
|
Ok = FALSE;
|
|
}
|
|
}
|
|
|
|
if (hData = (HLOCAL)pDCI->pAlphaBlendBGR) {
|
|
|
|
DBGP_IF(DBGP_DHI_MEM,
|
|
DBGP("CleanUpDHI: HTFreeMem(pDCI->pAlphaBlendBGR=%p)"
|
|
ARGPTR(hData)));
|
|
|
|
if (HTFreeMem(hData)) {
|
|
|
|
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->pAlphaBlendBGR)", FALSE);
|
|
Ok = FALSE;
|
|
}
|
|
}
|
|
|
|
Loop = CRTX_TOTAL_COUNT;
|
|
|
|
while (Loop--) {
|
|
|
|
if (hData = (HLOCAL)pDCI->CRTX[Loop].pFD6XYZ) {
|
|
|
|
DBGP_IF(DBGP_DHI_MEM,
|
|
DBGP("CleanUpDHI: HTFreeMem(pDCI->CRTX[%u].pFD6XYZ=%p)"
|
|
ARGU(Loop) ARGPTR(hData)));
|
|
|
|
if (HTFreeMem(hData)) {
|
|
|
|
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->CRTX[])", FALSE);
|
|
Ok = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
DBGP_IF(DBGP_DHI_MEM,
|
|
DBGP("CleanUpDHI: HTFreeMem(pDHI=%p)"
|
|
ARGPTR(pDeviceHalftoneInfo)));
|
|
|
|
if (HTFreeMem(pDeviceHalftoneInfo)) {
|
|
|
|
ASSERTMSG("CleanUpDHI: FreeMemory(pDeviceHalftoneInfo)", FALSE);
|
|
Ok = FALSE;
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTMutex);
|
|
DELETE_HTMUTEX(HTMutex);
|
|
|
|
return(Ok);
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HalftoneInitProc(
|
|
HMODULE hModule,
|
|
DWORD Reason,
|
|
LPVOID Reserved
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is DLL main entry point, at here we will save the module
|
|
handle, in the future we will need to do other initialization stuff.
|
|
|
|
Arguments:
|
|
|
|
hModule - Handle to this moudle when get loaded.
|
|
|
|
Reason - may be DLL_PROCESS_ATTACH
|
|
|
|
Reserved - reserved
|
|
|
|
Return Value:
|
|
|
|
Always return 1L
|
|
|
|
|
|
Author:
|
|
|
|
20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(Reserved);
|
|
|
|
|
|
switch(Reason) {
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DBGP_IF((DBGP_CACHED_DCI | DBGP_CACHED_SMP),
|
|
DBGP("\n****** DLL_PROCESS_ATTACH ******\n"));
|
|
|
|
HTGlobal.hModule = hModule;
|
|
EnableHalftone();
|
|
|
|
break;
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
DBGP_IF((DBGP_CACHED_DCI | DBGP_CACHED_SMP),
|
|
DBGP("\n****** DLL_PROCESS_DETACH ******\n"));
|
|
|
|
DisableHalftone();
|
|
break;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
#if DO_CACHE_DCI
|
|
|
|
|
|
PCDCIDATA
|
|
HTENTRY
|
|
FindCachedDCI(
|
|
PDEVICECOLORINFO pDCI
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will try to find the cached DEVICECOLORINFO and put the
|
|
cached data to the pDCI
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to current device color info
|
|
|
|
|
|
Return Value:
|
|
|
|
INT, Index number to the PCDCI.Header[] array, if return value is < 0 then
|
|
the CachedDCI data is not found.
|
|
|
|
Author:
|
|
|
|
01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCDCIDATA pCurCDCIData;
|
|
DEFDBGVAR(UINT, SearchIndex = 0)
|
|
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
if (pCurCDCIData = HTGlobal.pCDCIDataHead) {
|
|
|
|
PCDCIDATA pPrevCDCIData = NULL;
|
|
DWORD Checksum = pDCI->HTInitInfoChecksum;
|
|
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("FindCDCI: Looking for Checksum (0x%08lx), Count=%u"
|
|
ARGDW(Checksum) ARGU(HTGlobal.CDCICount)));
|
|
|
|
ASSERT(HTGlobal.CDCICount);
|
|
|
|
while (pCurCDCIData) {
|
|
|
|
if (pCurCDCIData->Checksum == Checksum) {
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("FindCDCI: Found %08lx [CheckSum=%08lx] after %u links, pPrev=%p"
|
|
ARG(pCurCDCIData)
|
|
ARGDW(Checksum)
|
|
ARGU(SearchIndex)
|
|
ARGPTR(pPrevCDCIData)));
|
|
|
|
if (pPrevCDCIData) {
|
|
|
|
//
|
|
// The most recent reference's DCI always as first entry,
|
|
// (ie. Link Head), the last is the longest unreferenced
|
|
// so that if we need to delete a DCI, we delete the
|
|
// last one.
|
|
//
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("FindCDCI: Move pCur to pHead"));
|
|
|
|
pPrevCDCIData->pNextCDCIData = pCurCDCIData->pNextCDCIData;
|
|
pCurCDCIData->pNextCDCIData = HTGlobal.pCDCIDataHead;
|
|
HTGlobal.pCDCIDataHead = pCurCDCIData;
|
|
}
|
|
|
|
return(pCurCDCIData);
|
|
}
|
|
|
|
SETDBGVAR(SearchIndex, SearchIndex + 1);
|
|
|
|
pPrevCDCIData = pCurCDCIData;
|
|
pCurCDCIData = pCurCDCIData->pNextCDCIData;
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI, DBGP("FindCDCI: ??? NOT FOUND ???"));
|
|
|
|
} else {
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI, DBGP("FindCDCI: ++No CDCIDATA cahced yet++"));
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
HTENTRY
|
|
AddCachedDCI(
|
|
PDEVICECOLORINFO pDCI
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function add the DEVICECOLORINFO information to the DCI cache
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to current device color info
|
|
|
|
Lock - TRUE if need to keep the hMutex locked, (only if add is
|
|
sucessfully)
|
|
|
|
Return Value:
|
|
|
|
INT, Index number to the PCDCI.Header[] array where the new data is added,
|
|
if return value is < 0 then the pDCI'CachedDCI data did not add to the
|
|
cached array.
|
|
|
|
NOTE: If AddCachedDCI() return value >= 0 and Lock=TRUE then caller must
|
|
release the PCDCI.hMutex after done with the data, if return value
|
|
is < 0 then no unlock is necessary.
|
|
|
|
|
|
Author:
|
|
|
|
01-May-1992 Fri 13:24:58 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCDCIDATA pCurCDCIData;
|
|
PCDCIDATA pPrevCDCIData;
|
|
DWORD AllocSize;
|
|
DWORD SizeCell;
|
|
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
//
|
|
// We only cached CDCIDATA to certain extend, if we over that limit then
|
|
// delete the last entry in the link list before adding anything
|
|
//
|
|
|
|
if (HTGlobal.CDCICount >= MAX_CDCI_COUNT) {
|
|
|
|
ASSERT(HTGlobal.pCDCIDataHead);
|
|
|
|
pCurCDCIData = HTGlobal.pCDCIDataHead;
|
|
pPrevCDCIData = NULL;
|
|
|
|
while (pCurCDCIData->pNextCDCIData) {
|
|
|
|
pPrevCDCIData = pCurCDCIData;
|
|
pCurCDCIData = pCurCDCIData->pNextCDCIData;
|
|
}
|
|
|
|
ASSERT(pPrevCDCIData);
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("AddCDCI: CDCICount >= %u, Free pLast=%p"
|
|
ARGU(MAX_CDCI_COUNT)
|
|
ARGPTR(pCurCDCIData)));
|
|
|
|
if (HTFreeMem(pCurCDCIData)) {
|
|
|
|
ASSERTMSG("AddCDCI: HTFreeMem(pLastCDCIData) Failed", FALSE);
|
|
}
|
|
|
|
pPrevCDCIData->pNextCDCIData = NULL;
|
|
--HTGlobal.CDCICount;
|
|
}
|
|
|
|
if (pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS) {
|
|
|
|
SizeCell = 0;
|
|
|
|
} else {
|
|
|
|
SizeCell = (DWORD)pDCI->HTCell.Size;
|
|
}
|
|
|
|
AllocSize = (DWORD)SizeCell + (DWORD)sizeof(CDCIDATA);
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" AddCDCI: HTAllocMem(CDCIDATA(%ld) + Cell(%ld)) = %ld bytes"
|
|
ARGDW(sizeof(CDCIDATA))
|
|
ARGDW(SizeCell) ARGDW(AllocSize)));
|
|
|
|
if (pCurCDCIData = (PCDCIDATA)HTAllocMem(NULL,
|
|
HTMEM_CurCDCIData,
|
|
NONZEROLPTR,
|
|
AllocSize)) {
|
|
|
|
//
|
|
// put this data at link list head
|
|
//
|
|
|
|
pCurCDCIData->Checksum = pDCI->HTInitInfoChecksum;
|
|
pCurCDCIData->pNextCDCIData = HTGlobal.pCDCIDataHead;
|
|
pCurCDCIData->ClrXFormBlock = pDCI->ClrXFormBlock;
|
|
pCurCDCIData->DCIFlags = pDCI->Flags;
|
|
pCurCDCIData->DevResXDPI = pDCI->DeviceResXDPI;
|
|
pCurCDCIData->DevResYDPI = pDCI->DeviceResYDPI;
|
|
pCurCDCIData->DevPelRatio = pDCI->DevPelRatio;
|
|
pCurCDCIData->HTCell = pDCI->HTCell;
|
|
|
|
if (SizeCell) {
|
|
|
|
CopyMemory((LPBYTE)(pCurCDCIData + 1),
|
|
(LPBYTE)pDCI->HTCell.pThresholds,
|
|
SizeCell);
|
|
|
|
pCurCDCIData->HTCell.pThresholds = NULL;
|
|
}
|
|
|
|
HTGlobal.pCDCIDataHead = pCurCDCIData;
|
|
++HTGlobal.CDCICount;
|
|
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" AddCDCI: CDCIHeader, UsedCount=%u, pHead=%p, [%08lx]"
|
|
ARGU(HTGlobal.CDCICount)
|
|
ARGPTR(pCurCDCIData)
|
|
ARGDW(pCurCDCIData->Checksum)));
|
|
|
|
} else {
|
|
|
|
ASSERTMSG("AddCDCI: HTAllocMem(pCDCIData) Failed", FALSE);
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
|
|
return((pCurCDCIData) ? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
HTENTRY
|
|
GetCachedDCI(
|
|
PDEVICECOLORINFO pDCI
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will try to find the cached DEVICECOLORINFO and put the
|
|
cached data to the pDCI
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to current device color info
|
|
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN
|
|
|
|
Author:
|
|
|
|
01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCDCIDATA pCDCIData;
|
|
BOOL GetOk = FALSE;
|
|
|
|
|
|
if (pCDCIData = FindCachedDCI(pDCI)) {
|
|
|
|
pDCI->ClrXFormBlock = pCDCIData->ClrXFormBlock;
|
|
pDCI->Flags = pCDCIData->DCIFlags;
|
|
pDCI->DeviceResXDPI = pCDCIData->DevResXDPI;
|
|
pDCI->DeviceResYDPI = pCDCIData->DevResYDPI;
|
|
pDCI->DevPelRatio = pCDCIData->DevPelRatio;
|
|
pDCI->HTCell = pCDCIData->HTCell;
|
|
|
|
if (pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS) {
|
|
|
|
GetOk = TRUE;
|
|
|
|
} else if (pDCI->HTCell.pThresholds =
|
|
(LPBYTE)HTAllocMem((LPVOID)pDCI,
|
|
HTMEM_GetCacheThreshold,
|
|
NONZEROLPTR,
|
|
pDCI->HTCell.Size)) {
|
|
|
|
CopyMemory((LPBYTE)pDCI->HTCell.pThresholds,
|
|
(LPBYTE)(pCDCIData + 1),
|
|
pDCI->HTCell.Size);
|
|
|
|
GetOk = TRUE;
|
|
|
|
} else {
|
|
|
|
DBGMSG("GetCDCI: HTAllocMem(Thresholds) failed");
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
|
|
}
|
|
|
|
return(GetOk);
|
|
}
|
|
|
|
#endif // DO_CACHE_DCI
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
|
|
VOID
|
|
HTENTRY
|
|
DbgDumpCSMPBMP(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
Author:
|
|
|
|
25-Mar-1999 Thu 17:49:53 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCSMPDATA pCSMPData;
|
|
UINT c0 = 0;
|
|
|
|
pCSMPData = HTGlobal.pCSMPDataHead;
|
|
|
|
while (pCSMPData) {
|
|
|
|
PCSMPBMP pCSMPBmp;
|
|
UINT c1 = 0;
|
|
|
|
DBGP_IF(DBGP_SHOW_CSMBMP,
|
|
DBGP("cDatas=%3ld: Checksum=%08lx"
|
|
ARGDW(++c0) ARGDW(pCSMPData->Checksum)));
|
|
|
|
pCSMPBmp = pCSMPData->pCSMPBmpHead;
|
|
|
|
while (pCSMPBmp) {
|
|
|
|
DBGP_IF(DBGP_SHOW_CSMBMP,
|
|
DBGP(" %3ld: Idx=%2ld, %4ldx%4ld=%4ld"
|
|
ARGDW(++c1)
|
|
ARGDW(pCSMPBmp->PatternIndex)
|
|
ARGDW(pCSMPBmp->cxPels)
|
|
ARGDW(pCSMPBmp->cyPels)
|
|
ARGDW(pCSMPBmp->cxBytes)));
|
|
|
|
|
|
|
|
pCSMPBmp = pCSMPBmp->pNextCSMPBmp;
|
|
}
|
|
|
|
pCSMPData = pCSMPData->pNextCSMPData;
|
|
}
|
|
|
|
if (c0 != (UINT)HTGlobal.CSMPCount) {
|
|
|
|
DBGP("c0 (%ld) != CSMPCount (%ld)"
|
|
ARGDW(c0) ARGDW(HTGlobal.CSMPCount));
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
PCSMPBMP
|
|
HTENTRY
|
|
FindCachedSMP(
|
|
PDEVICECOLORINFO pDCI,
|
|
UINT PatternIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will try to find the cached DEVICECOLORINFO and put the
|
|
cached data to the pDCI
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to current device color info
|
|
|
|
|
|
Return Value:
|
|
|
|
INT, Index number to the PCDCI.Header[] array, if return value is < 0 then
|
|
the CachedDCI data is not found.
|
|
|
|
Author:
|
|
|
|
01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PCSMPDATA pPrevCSMPData;
|
|
PCSMPDATA pCurCSMPData;
|
|
PCSMPBMP pCurCSMPBmp;
|
|
DWORD Checksum = pDCI->HTSMPChecksum;
|
|
DEFDBGVAR(UINT, SearchIndex = 0)
|
|
|
|
|
|
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
|
|
DBGP_IF(DBGP_SHOW_CSMBMP, DbgDumpCSMPBMP(); );
|
|
|
|
if (pCurCSMPData = HTGlobal.pCSMPDataHead) {
|
|
|
|
pPrevCSMPData = NULL;
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(">>FindCSMP: Looking for Checksum (0x%08lx), Count=%u"
|
|
ARGDW(Checksum) ARGU(HTGlobal.CSMPCount)));
|
|
|
|
ASSERT(HTGlobal.CSMPCount);
|
|
|
|
while (pCurCSMPData) {
|
|
|
|
if (pCurCSMPData->Checksum == Checksum) {
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: Found after %u links, pPrev=%p"
|
|
ARGU(SearchIndex)
|
|
ARGPTR(pPrevCSMPData)));
|
|
|
|
if (pPrevCSMPData) {
|
|
|
|
//
|
|
// The most recent reference's CSMPDATA always as first
|
|
// entry,(ie. Link Head), the last is the longest
|
|
// unreferenced so that if we need to delete a CSMPDATA,
|
|
// we delete the last one.
|
|
//
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: Move pCur to pHead"));
|
|
|
|
pPrevCSMPData->pNextCSMPData = pCurCSMPData->pNextCSMPData;
|
|
pCurCSMPData->pNextCSMPData = HTGlobal.pCSMPDataHead;
|
|
HTGlobal.pCSMPDataHead = pCurCSMPData;
|
|
}
|
|
|
|
//
|
|
// See we cached any pattern for this group
|
|
//
|
|
|
|
pCurCSMPBmp = pCurCSMPData->pCSMPBmpHead;
|
|
|
|
SETDBGVAR(SearchIndex, 0);
|
|
|
|
while (pCurCSMPBmp) {
|
|
|
|
if ((UINT)pCurCSMPBmp->PatternIndex == PatternIndex) {
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: Found Pat(%u) after %u links"
|
|
ARGU(PatternIndex)
|
|
ARGU(SearchIndex++)));
|
|
|
|
return(pCurCSMPBmp);
|
|
}
|
|
|
|
pCurCSMPBmp = pCurCSMPBmp->pNextCSMPBmp;
|
|
}
|
|
|
|
//
|
|
// Found in this group but no bitmap for PatternIndex is
|
|
// cached yet!
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
SETDBGVAR(SearchIndex, SearchIndex + 1);
|
|
|
|
pPrevCSMPData = pCurCSMPData;
|
|
pCurCSMPData = pCurCSMPData->pNextCSMPData;
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP, DBGP(">>FindCSMP: ??? NOT FOUND ???"));
|
|
|
|
} else {
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI, DBGP(">>FindCSMP: ++No CSMPDATA cahced yet++"));
|
|
}
|
|
|
|
if (!pCurCSMPData) {
|
|
|
|
//
|
|
// Since we did not even found the CSMPDATA checksum group, we want to
|
|
// add it in there, but We only cached CSMPDATA to certain extend, if
|
|
// we over that limit then delete the last entry in the link list
|
|
// before adding anything
|
|
//
|
|
|
|
if (HTGlobal.CSMPCount >= MAX_CSMP_COUNT) {
|
|
|
|
HLOCAL hData;
|
|
|
|
|
|
ASSERT(HTGlobal.pCSMPDataHead);
|
|
|
|
pPrevCSMPData = NULL;
|
|
pCurCSMPData = HTGlobal.pCSMPDataHead;
|
|
|
|
while (pCurCSMPData->pNextCSMPData) {
|
|
|
|
pPrevCSMPData = pCurCSMPData;
|
|
pCurCSMPData = pCurCSMPData->pNextCSMPData;
|
|
}
|
|
|
|
ASSERT(pPrevCSMPData);
|
|
|
|
//
|
|
// Free all the allocated cached standard mono pattern bitmap for
|
|
// this group
|
|
//
|
|
|
|
pCurCSMPBmp = pCurCSMPData->pCSMPBmpHead;
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: CSMPCount >= %u, Free pLast=%p"
|
|
ARGU(MAX_CSMP_COUNT) ARGPTR(pCurCSMPData)));
|
|
|
|
while (hData = (HLOCAL)pCurCSMPBmp) {
|
|
|
|
pCurCSMPBmp = pCurCSMPBmp->pNextCSMPBmp;
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: Free pLastCSMPBmp=%p" ARGPTR(hData)));
|
|
|
|
if (HTFreeMem(hData)) {
|
|
|
|
ASSERTMSG(">>FindCSMP: HTFreeMem(pCurCSMBmp) Failed", FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now free the header for the CSMPDATA
|
|
//
|
|
|
|
if (HTFreeMem(pCurCSMPData)) {
|
|
|
|
ASSERTMSG(">>FindCSMP: HTFreeMem(pLastCSMPData) Failed", FALSE);
|
|
}
|
|
|
|
pPrevCSMPData->pNextCSMPData = NULL;
|
|
--HTGlobal.CSMPCount;
|
|
}
|
|
|
|
if (pCurCSMPData = (PCSMPDATA)HTAllocMem((LPVOID)NULL,
|
|
HTMEM_CurCSMPData,
|
|
NONZEROLPTR,
|
|
sizeof(CSMPDATA))) {
|
|
|
|
//
|
|
// Make this one as the link list head
|
|
//
|
|
|
|
pCurCSMPData->Checksum = Checksum;
|
|
pCurCSMPData->pNextCSMPData = HTGlobal.pCSMPDataHead;
|
|
pCurCSMPData->pCSMPBmpHead = NULL;
|
|
|
|
HTGlobal.pCSMPDataHead = pCurCSMPData;
|
|
++HTGlobal.CSMPCount;
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(" >>FindCSMP: Add CSMPDATA, UsedCount=%u, pHead=%p"
|
|
ARGU(HTGlobal.CSMPCount) ARGPTR(pCurCSMPData)));
|
|
|
|
} else {
|
|
|
|
DBGMSG(" >>FindCSMP: HTAllocMem(CSMPDATA) Failed");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Do allocate new pattern only if we have header
|
|
//
|
|
|
|
if (pCurCSMPData) {
|
|
|
|
STDMONOPATTERN SMP;
|
|
DWORD Size;
|
|
|
|
|
|
SMP.Flags = SMP_TOPDOWN;
|
|
SMP.ScanLineAlignBytes = (BYTE)sizeof(BYTE);
|
|
SMP.PatternIndex = (BYTE)PatternIndex;
|
|
SMP.LineWidth = DEFAULT_SMP_LINE_WIDTH;
|
|
SMP.LinesPerInch = DEFAULT_SMP_LINES_PER_INCH;
|
|
SMP.pPattern = NULL;
|
|
|
|
//
|
|
// Find out the size for the pattern bitmap (BYTE Aligned)
|
|
//
|
|
|
|
Size = (DWORD)CreateStandardMonoPattern(pDCI, &SMP) +
|
|
(DWORD)sizeof(CSMPBMP);
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">>FindCSMP: Add PatternIndex=%u, sz=%ld, DPI(X=%u, Y=%u, P=%u)"
|
|
ARGU(PatternIndex)
|
|
ARGU(Size)
|
|
ARGU(pDCI->DeviceResXDPI)
|
|
ARGU(pDCI->DeviceResYDPI)
|
|
ARGU(pDCI->DevPelRatio)));
|
|
|
|
if (pCurCSMPBmp = (PCSMPBMP)HTAllocMem(NULL,
|
|
HTMEM_CurCSMPBmp,
|
|
NONZEROLPTR,
|
|
Size)) {
|
|
|
|
SMP.pPattern = (LPBYTE)pCurCSMPBmp + sizeof(CSMPBMP);
|
|
|
|
CreateStandardMonoPattern(pDCI, &SMP);
|
|
|
|
//
|
|
// Make this pattern index as link list head
|
|
//
|
|
|
|
pCurCSMPBmp->pNextCSMPBmp = pCurCSMPData->pCSMPBmpHead;
|
|
pCurCSMPBmp->PatternIndex = (WORD)PatternIndex;
|
|
pCurCSMPBmp->cxPels = (WORD)SMP.cxPels;
|
|
pCurCSMPBmp->cyPels = (WORD)SMP.cyPels;
|
|
pCurCSMPBmp->cxBytes = (WORD)SMP.BytesPerScanLine;
|
|
|
|
pCurCSMPData->pCSMPBmpHead = pCurCSMPBmp;
|
|
|
|
return(pCurCSMPBmp);
|
|
|
|
} else {
|
|
|
|
ASSERTMSG(" >>FindCSMP: HTAllocMem(CSMPBMP) Failed", FALSE);
|
|
}
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
LONG
|
|
HTENTRY
|
|
GetCachedSMP(
|
|
PDEVICECOLORINFO pDCI,
|
|
PSTDMONOPATTERN pSMP
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will try to find the cached DEVICECOLORINFO and put the
|
|
cached data to the pDCI
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to current device color info
|
|
|
|
|
|
pSMP - Pointer to the STDMONOPATTERN data structure, if PatIndex is
|
|
< CACHED_SMP_COUNT or, its not default size then it will be
|
|
computed on the fly.
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
The size of the SMP pattern.
|
|
|
|
Author:
|
|
|
|
01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG SizeRet = 0;
|
|
UINT PatIndex;
|
|
|
|
|
|
if (!(pSMP->LineWidth)) {
|
|
|
|
pSMP->LineWidth = DEFAULT_SMP_LINE_WIDTH;
|
|
}
|
|
|
|
if (!(pSMP->LinesPerInch)) {
|
|
|
|
pSMP->LinesPerInch = DEFAULT_SMP_LINES_PER_INCH;
|
|
}
|
|
|
|
if (((PatIndex = (UINT)pSMP->PatternIndex) < HT_SMP_PERCENT_SCREEN_START) &&
|
|
(pSMP->LineWidth == DEFAULT_SMP_LINE_WIDTH) &&
|
|
(pSMP->LinesPerInch == DEFAULT_SMP_LINES_PER_INCH)) {
|
|
|
|
PCSMPBMP pCSMPBmp;
|
|
|
|
if (pCSMPBmp = FindCachedSMP(pDCI, PatIndex)) {
|
|
|
|
CSMPBMP CSMPBmp;
|
|
LPBYTE pPatRet;
|
|
LPBYTE pPat;
|
|
WORD cxBytesRet;
|
|
|
|
|
|
CSMPBmp = *pCSMPBmp;
|
|
pPat = (LPBYTE)pCSMPBmp + sizeof(CSMPBMP);
|
|
pSMP->cxPels = CSMPBmp.cxPels;
|
|
pSMP->cyPels = CSMPBmp.cyPels;
|
|
|
|
cxBytesRet =
|
|
pSMP->BytesPerScanLine = (WORD)
|
|
ComputeBytesPerScanLine((UINT)BMF_1BPP,
|
|
(UINT)pSMP->ScanLineAlignBytes,
|
|
(DWORD)CSMPBmp.cxPels);
|
|
SizeRet = (LONG)cxBytesRet * (LONG)CSMPBmp.cyPels;
|
|
|
|
if (pPatRet = pSMP->pPattern) {
|
|
|
|
INT cxBytes;
|
|
INT PatInc;
|
|
WORD Flags;
|
|
|
|
|
|
PatInc =
|
|
cxBytes = (INT)CSMPBmp.cxBytes;
|
|
Flags = pSMP->Flags;
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(">> GetCSMP: *COPY* [%2u:%ux%u] @%u(%ld) -> @%u(%u) [%s] [%c=K]"
|
|
ARGU(PatIndex)
|
|
ARGU(CSMPBmp.cxPels)
|
|
ARGU(CSMPBmp.cyPels)
|
|
ARGU(cxBytes)
|
|
ARGU((LONG)cxBytes * (LONG)CSMPBmp.cyPels)
|
|
ARGU(cxBytesRet)
|
|
ARGU(SizeRet)
|
|
ARG((Flags & SMP_TOPDOWN) ? "TOP DOWN" : "BOTTOM UP ")
|
|
ARG((Flags & SMP_0_IS_BLACK) ? '0' : '1')));
|
|
|
|
//
|
|
// Start copying the cached pattern
|
|
//
|
|
|
|
if (!(Flags & SMP_TOPDOWN)) {
|
|
|
|
pPat += (LONG)cxBytes * (LONG)(CSMPBmp.cyPels - 1);
|
|
PatInc = -PatInc;
|
|
}
|
|
|
|
while (CSMPBmp.cyPels--) {
|
|
|
|
CopyMemory(pPatRet, pPat, cxBytes);
|
|
|
|
pPatRet += cxBytesRet;
|
|
pPat += PatInc;
|
|
}
|
|
|
|
if (Flags & SMP_0_IS_BLACK) {
|
|
|
|
LONG Count = SizeRet;
|
|
|
|
|
|
pPatRet = pSMP->pPattern;
|
|
|
|
while (Count--) {
|
|
|
|
*pPatRet++ ^= 0xff;
|
|
}
|
|
}
|
|
}
|
|
|
|
RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
|
|
}
|
|
|
|
} else {
|
|
|
|
DBGP_IF(DBGP_CACHED_SMP,
|
|
DBGP(">> GetCSMP: NO CACHED FOR LineWidth=%u, LinesPerInch=%u"
|
|
ARGU(pSMP->LineWidth) ARGU(pSMP->LinesPerInch)));
|
|
}
|
|
|
|
if (!SizeRet) {
|
|
|
|
SizeRet = CreateStandardMonoPattern(pDCI, pSMP);
|
|
}
|
|
|
|
return(SizeRet);
|
|
|
|
}
|
|
|
|
|
|
#if DO_CACHE_DCI
|
|
|
|
|
|
DWORD
|
|
HTENTRY
|
|
ComputeHTINITINFOChecksum(
|
|
PDEVICECOLORINFO pDCI,
|
|
PHTINITINFO pHTInitInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function compute 32-bit checksum for the HTINITINFO data structure
|
|
passed
|
|
|
|
Arguments:
|
|
|
|
pDCI - Pointer to the DCI
|
|
|
|
pHTInitInfo - Pointer to the HTINITINFO5 data structure
|
|
|
|
Return Value:
|
|
|
|
32-bit checksum
|
|
|
|
Author:
|
|
|
|
29-Apr-1992 Wed 18:44:42 created -by- Daniel Chou (danielc)
|
|
|
|
11-Feb-1997 Tue 12:54:50 updated -by- Daniel Chou (danielc)
|
|
Changed using HTINITINFO5
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Checksum;
|
|
WORD wBuf[12];
|
|
|
|
|
|
Checksum = ComputeHTCell((WORD)pHTInitInfo->HTPatternIndex,
|
|
pHTInitInfo->pHalftonePattern,
|
|
NULL);
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" HTPATTERN Checksum= %08lx" ARGDW(Checksum)));
|
|
|
|
wBuf[0] = (WORD)'HT';
|
|
wBuf[1] = (WORD)pHTInitInfo->Flags;
|
|
wBuf[2] = (WORD)(pDCI->HTInitInfoChecksum >> 16);
|
|
wBuf[3] = (WORD)pHTInitInfo->DeviceResXDPI;
|
|
wBuf[4] = (WORD)pHTInitInfo->DeviceResYDPI;
|
|
wBuf[5] = (WORD)pHTInitInfo->DevicePelsDPI;
|
|
wBuf[6] = (WORD)(pDCI->HTInitInfoChecksum & 0xffff);
|
|
wBuf[7] = (WORD)pHTInitInfo->DevicePowerGamma;
|
|
wBuf[8] = (WORD)0x1234;
|
|
|
|
if (pHTInitInfo->Version > HTINITINFO_VERSION2) {
|
|
|
|
wBuf[9] = (WORD)pHTInitInfo->DeviceRGamma;
|
|
wBuf[10] = (WORD)pHTInitInfo->DeviceGGamma;
|
|
wBuf[11] = (WORD)pHTInitInfo->DeviceBGamma;
|
|
|
|
} else {
|
|
|
|
wBuf[9] = 0x1234;
|
|
wBuf[10] = 0xfedc;
|
|
wBuf[11] = 0xabcd;
|
|
}
|
|
|
|
Checksum = ComputeChecksum((LPBYTE)&(wBuf[0]), Checksum, sizeof(wBuf));
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" HTINITINFO Checksum= %08lx [%08lx]"
|
|
ARGDW(Checksum) ARGDW(pDCI->HTInitInfoChecksum)));
|
|
|
|
if (pHTInitInfo->pInputRGBInfo) {
|
|
|
|
Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pInputRGBInfo,
|
|
Checksum,
|
|
sizeof(CIEINFO));
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" RGBINFO Checksum= %08lx" ARGDW(Checksum)));
|
|
}
|
|
|
|
if (pHTInitInfo->pDeviceCIEInfo) {
|
|
|
|
Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pDeviceCIEInfo,
|
|
Checksum,
|
|
sizeof(CIEINFO));
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" CIEINFO Checksum= %08lx" ARGDW(Checksum)));
|
|
}
|
|
|
|
if (pHTInitInfo->pDeviceSolidDyesInfo) {
|
|
|
|
Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pDeviceSolidDyesInfo,
|
|
Checksum,
|
|
sizeof(SOLIDDYESINFO));
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" SOLIDDYE Checksum= %08lx" ARGDW(Checksum)));
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("----------------- FINAL Checksum= %08lx" ARGDW(Checksum)));
|
|
|
|
return(pDCI->HTInitInfoChecksum = Checksum);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
HTCALLBACKFUNCTION
|
|
DefaultHTCallBack(
|
|
PHTCALLBACKPARAMS pHTCallBackParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This stuff function is provided when caller do not specified the halftone
|
|
callback function.
|
|
|
|
Arguments:
|
|
|
|
pHTCallBackParams - Pointer to the PHTCALLBACKPARAMS
|
|
|
|
Return Value:
|
|
|
|
always return false for the caller.
|
|
|
|
Author:
|
|
|
|
18-Mar-1992 Wed 12:28:13 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(pHTCallBackParams);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
#define FLIP_COORD(m, a) (a) = ((m) << 1) - (a)
|
|
|
|
|
|
|
|
|
|
VOID
|
|
HTENTRY
|
|
GetCIEPrims(
|
|
PCIEINFO pCIEInfo,
|
|
PCIEPRIMS pCIEPrims,
|
|
PCIEINFO pDefCIEInfo,
|
|
BOOL FlipWhite
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function take CIEINFO data structure and converted it to the CIEPRIMS
|
|
internal data type
|
|
|
|
Arguments:
|
|
|
|
pCIEInfo - Pointer to the CIEINFO data structure for conversion,
|
|
if this pointer is NULL then DefCIEPrimsIndex is used
|
|
to index into DefaultCIEPrims[].
|
|
|
|
pCIEPrims - Pointer to the CIEPRIMS data structure
|
|
|
|
pDefCIEInfo - Pointer to the CIEINFO for the default
|
|
|
|
Return Value:
|
|
|
|
BOOL If it is standard CIE Info
|
|
|
|
Author:
|
|
|
|
20-Apr-1993 Tue 01:14:23 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
06-Oct-2000 Fri 18:01:40 updated -by- Daniel Chou (danielc)
|
|
fix bug: Move FlipWhite to the outer loop so it will compute even in
|
|
default CIEINFO situation
|
|
|
|
--*/
|
|
|
|
{
|
|
CIEINFO CIEInfo;
|
|
BOOL UseDefCIEInfo = TRUE;
|
|
LONG Diff;
|
|
|
|
|
|
if (pCIEInfo) {
|
|
|
|
CIEInfo = *pCIEInfo;
|
|
|
|
if ((CIEInfo.Red.x < CIE_x_MIN) ||
|
|
(CIEInfo.Red.x > CIE_x_MAX) ||
|
|
(CIEInfo.Red.y < CIE_y_MIN) ||
|
|
(CIEInfo.Red.y > CIE_y_MAX) ||
|
|
(CIEInfo.Green.x < CIE_x_MIN) ||
|
|
(CIEInfo.Green.x > CIE_x_MAX) ||
|
|
(CIEInfo.Green.y < CIE_y_MIN) ||
|
|
(CIEInfo.Green.y > CIE_y_MAX) ||
|
|
(CIEInfo.Blue.x < CIE_x_MIN) ||
|
|
(CIEInfo.Blue.x > CIE_x_MAX) ||
|
|
(CIEInfo.Blue.y < CIE_y_MIN) ||
|
|
(CIEInfo.Blue.y > CIE_y_MAX) ||
|
|
(CIEInfo.AlignmentWhite.x < CIE_x_MIN) ||
|
|
(CIEInfo.AlignmentWhite.x > CIE_x_MAX) ||
|
|
(CIEInfo.AlignmentWhite.y < CIE_y_MIN) ||
|
|
(CIEInfo.AlignmentWhite.y > CIE_y_MAX) ||
|
|
(CIEInfo.AlignmentWhite.Y < (UDECI4)2500) ||
|
|
(CIEInfo.AlignmentWhite.Y > (UDECI4)60000)) {
|
|
|
|
NULL;
|
|
|
|
} else {
|
|
|
|
UseDefCIEInfo = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
if (UseDefCIEInfo) {
|
|
|
|
CIEInfo = *pDefCIEInfo;
|
|
}
|
|
|
|
if (FlipWhite) {
|
|
|
|
FLIP_COORD(pDefCIEInfo->AlignmentWhite.x,
|
|
CIEInfo.AlignmentWhite.x);
|
|
|
|
FLIP_COORD(pDefCIEInfo->AlignmentWhite.y,
|
|
CIEInfo.AlignmentWhite.y);
|
|
}
|
|
|
|
pCIEPrims->r.x = UDECI4ToFD6(CIEInfo.Red.x);
|
|
pCIEPrims->r.y = UDECI4ToFD6(CIEInfo.Red.y);
|
|
pCIEPrims->g.x = UDECI4ToFD6(CIEInfo.Green.x);
|
|
pCIEPrims->g.y = UDECI4ToFD6(CIEInfo.Green.y);
|
|
pCIEPrims->b.x = UDECI4ToFD6(CIEInfo.Blue.x);
|
|
pCIEPrims->b.y = UDECI4ToFD6(CIEInfo.Blue.y);
|
|
pCIEPrims->w.x = UDECI4ToFD6(CIEInfo.AlignmentWhite.x);
|
|
pCIEPrims->w.y = UDECI4ToFD6(CIEInfo.AlignmentWhite.y);
|
|
pCIEPrims->Yw = UDECI4ToFD6(CIEInfo.AlignmentWhite.Y);
|
|
}
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_CreateDeviceHalftoneInfo(
|
|
PHTINITINFO pHTInitInfo,
|
|
PPDEVICEHALFTONEINFO ppDeviceHalftoneInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initialize a device to the halftone dll, it calculate all
|
|
the necessary parameters for the device and return a pointer points to
|
|
the DEVICEHALFTONEINFO data structure back to the caller.
|
|
|
|
NOTE: return pointer will not be particulary anchor to a single physucal
|
|
device, but rather to a group of physical devices, that is if the
|
|
caller has simillar devices which share the same characteristics
|
|
then it may use the same pointer to halftone the bitmap.
|
|
|
|
Arguments:
|
|
|
|
pHTInitInfo - Pointer to the HTINITINFO data structure which
|
|
describe the device characteristics and other
|
|
initialzation requests.
|
|
|
|
ppDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO pointer, if
|
|
content of this pointer is not NULL then halftone
|
|
dll assume the caller has previously cached
|
|
DEVICEHALFTONEINFO data pointed by it, if it
|
|
is NULL then halftone dll compute all the
|
|
DEVICEHALFTONEINFO datas for newly created
|
|
halftone info. for the device. (see following
|
|
'Return Value' for more detail)
|
|
|
|
Return Value:
|
|
|
|
The return value will be greater than 0L if the function sucessfully, and
|
|
it will be an error code (less than or equal to 0) if function failed.
|
|
|
|
Return value greater than 0
|
|
|
|
1. The pointer location points by the ppDeviceHalftoneInfo will be
|
|
updated to stored the pointer which points to the DEVICEHALFTONEINFO
|
|
data structure for later any HT_xxxx() api calls.
|
|
|
|
2. The Return value is the total bytes the caller can saved and used
|
|
as cached DeviceHalftoneInfo for next time calling this function,
|
|
the saved area is started from *(ppDeviceHalftoneInfo) and has
|
|
size in bytes as return value.
|
|
|
|
NOTE: if caller passed a pointer pointed by ppDeviceHalftoneInfo and
|
|
the return value is greater than zero then it signal that it
|
|
passed DEVICEHALFTONEINFO pointer is not correct of data has
|
|
been changed from HTINITINFO data structure, the caller can
|
|
continue to save the newly created DEVICEHALFTONEINFO cached
|
|
data.
|
|
|
|
In any cases the caller's passed pointer stored in the
|
|
ppDeviceHalftoneInfo is overwritten by newly created
|
|
DEVICEHALFTONEINFO data structure pointer.
|
|
|
|
|
|
Return value equal to 0
|
|
|
|
1. The caller passed pointer *(ppDeviceHalftoneInfo) is sucessfully
|
|
used as new device halftone info
|
|
|
|
2. The pointer location points by the ppDeviceHalftoneInfo will be
|
|
updated to stored the new pointer which points to the
|
|
DEVICEHALFTONEINFO data structure for later any HT_xxxx() api calls.
|
|
|
|
|
|
NOTE: The caller's passed pointer stored in the ppDeviceHalftoneInfo
|
|
is overwritten by newly created DEVICEHALFTONEINFO data structure
|
|
pointer.
|
|
|
|
Return value less than or equal to zero
|
|
|
|
The function failed, the storage points by the ppDeviceHalftoneInfo is
|
|
undefined.
|
|
|
|
This function may return following error codes.
|
|
|
|
HTERR_INSUFFICIENT_MEMORY - Not enough memory for halftone
|
|
process.
|
|
|
|
HTERR_HTPATTERN_SIZE_TOO_BIG - Caller defined halftone pattern's
|
|
width or height is excessed limit.
|
|
|
|
HTERR_INVALID_HALFTONEPATTERN - One or more HALFTONEPATTERN data
|
|
structure field specified invalid
|
|
values.
|
|
|
|
|
|
Note: The first field in the DEVICEHALFTONEINFO (DeviceOwnData) is a 32-bit
|
|
area which will be set to 0L upon sucessful returned, the caller can
|
|
put any data in this field.
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 10:54:32 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
05-Jun-1991 Wed 10:22:07 updated -by- Daniel Chou (danielc)
|
|
|
|
Fixed the typing errors for halftone pattern default
|
|
|
|
--*/
|
|
|
|
{
|
|
PHT_DHI pHT_DHI;
|
|
PDEVICECOLORINFO pDCI;
|
|
HTINITINFO HTInitInfo;
|
|
BOOL UseCurNTDefault;
|
|
FD6 DevPelRatio;
|
|
WORD ExtraDCIF;
|
|
DWORD dwBuf[6];
|
|
|
|
#define _RegDataIdx ((DWORD)(dwBuf[0]))
|
|
#define _MaxMulDiv ((FD6)(dwBuf[0]))
|
|
#define _cC ((DWORD)(dwBuf[1]))
|
|
#define _cM ((DWORD)(dwBuf[2]))
|
|
#define _cY ((DWORD)(dwBuf[3]))
|
|
#define _MaxCMY ((DWORD)(dwBuf[4]))
|
|
#define _Idx ((DWORD)(dwBuf[5]))
|
|
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("\n********* HT_CreateDeviceHalftoneInfo *************\n"));
|
|
|
|
ZeroMemory(&HTInitInfo, sizeof(HTINITINFO));
|
|
|
|
//
|
|
// Now check if we have valid data
|
|
//
|
|
|
|
if (pHTInitInfo->Version == (DWORD)HTINITINFO_VERSION2) {
|
|
|
|
HTInitInfo.Version = sizeof(HTINITINFO) - HTINITINFO_V3_CB_EXTRA;
|
|
|
|
} else if (pHTInitInfo->Version == (DWORD)HTINITINFO_VERSION) {
|
|
|
|
HTInitInfo.Version = sizeof(HTINITINFO);
|
|
|
|
} else {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CREATE_DHI, HTERR_WRONG_VERSION_HTINITINFO);
|
|
}
|
|
|
|
CopyMemory(&HTInitInfo, pHTInitInfo, HTInitInfo.Version);
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("*** Allocate HT_DHI(%ld) ***" ARGDW(sizeof(HT_DHI))));
|
|
|
|
if (!(pHT_DHI = (PHT_DHI)HTAllocMem(NULL,
|
|
HTMEM_HT_DHI,
|
|
LPTR,
|
|
sizeof(HT_DHI)))) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CREATE_DHI, HTERR_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
pDCI = &(pHT_DHI->DCI);
|
|
pDCI->HalftoneDLLID = HALFTONE_DLL_ID;
|
|
|
|
if (!(pDCI->HTMutex = CREATE_HTMUTEX())) {
|
|
|
|
DBGMSG("InitHTInternalData: CREATE_HTMUTEX(pDCI->HTMutex) failed!");
|
|
|
|
HTFreeMem(pHT_DHI);
|
|
HTAPI_RET(HTAPI_IDX_CREATE_DHI, (HTERR_INTERNAL_ERRORS_START - 1000));
|
|
}
|
|
|
|
if (!(pDCI->HTCallBackFunction = HTInitInfo.HTCallBackFunction)) {
|
|
|
|
pDCI->HTCallBackFunction = DefaultHTCallBack;
|
|
}
|
|
|
|
HTInitInfo.Flags &= HIF_BIT_MASK;
|
|
|
|
// ****************************************************************
|
|
// * We want to check to see if this is a old data, if yes then *
|
|
// * update the caller to default *
|
|
// ****************************************************************
|
|
//
|
|
|
|
pDCI->HTInitInfoChecksum = HTINITINFO_INITIAL_CHECKSUM;
|
|
|
|
if ((!HTInitInfo.pDeviceCIEInfo) ||
|
|
(HTInitInfo.pDeviceCIEInfo->Cyan.Y != (UDECI4)VALID_YC)) {
|
|
|
|
//
|
|
// Let's munge around the printer info, to see if its an old def,
|
|
// if yes, then we now make this all into NT4.00 default
|
|
//
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("HT: *WARNING* Update Old Default COLORINFO to NT5.00 DEFAULT"));
|
|
|
|
HTInitInfo.pDeviceCIEInfo = NULL;
|
|
UseCurNTDefault = TRUE;
|
|
dwBuf[0] = (DWORD)'NTHT';
|
|
dwBuf[1] = (DWORD)'2000';
|
|
dwBuf[2] = (DWORD)'Dan.';
|
|
dwBuf[3] = (DWORD)'Chou';
|
|
pDCI->HTInitInfoChecksum = ComputeChecksum((LPBYTE)&dwBuf[0],
|
|
pDCI->HTInitInfoChecksum,
|
|
sizeof(dwBuf[0]) * 4);
|
|
|
|
} else {
|
|
|
|
UseCurNTDefault = FALSE;
|
|
}
|
|
|
|
DevPelRatio = (FD6)HTInitInfo.DevicePelsDPI;
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("Passed DevicePelsDPI=%08lx" ARGDW(DevPelRatio)));
|
|
|
|
if ((HTInitInfo.DeviceRGamma == (UDECI4)0xFFFF) &&
|
|
(HTInitInfo.DeviceGGamma == (UDECI4)0xFFFF) &&
|
|
(HTInitInfo.DeviceBGamma == (UDECI4)0xFFFF)) {
|
|
|
|
ExtraDCIF = DCIF_FORCE_ICM;
|
|
|
|
} else {
|
|
|
|
ExtraDCIF = 0;
|
|
}
|
|
|
|
if ((HTInitInfo.DeviceRGamma < (UDECI4)MIN_RGB_GAMMA) ||
|
|
(HTInitInfo.DeviceRGamma > (UDECI4)MAX_RGB_GAMMA) ||
|
|
(HTInitInfo.DeviceGGamma < (UDECI4)MIN_RGB_GAMMA) ||
|
|
(HTInitInfo.DeviceGGamma > (UDECI4)MAX_RGB_GAMMA) ||
|
|
(HTInitInfo.DeviceBGamma < (UDECI4)MIN_RGB_GAMMA) ||
|
|
(HTInitInfo.DeviceBGamma > (UDECI4)MAX_RGB_GAMMA)) {
|
|
|
|
HTInitInfo.DeviceRGamma =
|
|
HTInitInfo.DeviceGGamma =
|
|
HTInitInfo.DeviceBGamma = UDECI4_1;
|
|
}
|
|
|
|
//
|
|
// Compute HTInitInfoChecksum, and check if we have any cached data
|
|
//
|
|
|
|
#if DO_CACHE_DCI
|
|
ComputeHTINITINFOChecksum(pDCI, &HTInitInfo);
|
|
|
|
if (!GetCachedDCI(pDCI)) {
|
|
#else
|
|
if (TRUE) {
|
|
#endif
|
|
LONG Result;
|
|
|
|
//
|
|
// Now start to checking the init information
|
|
//
|
|
|
|
pDCI->Flags = (WORD)((HTInitInfo.Flags & HIF_SQUARE_DEVICE_PEL) ?
|
|
DCIF_SQUARE_DEVICE_PEL : 0);
|
|
|
|
if ((!(pDCI->DeviceResXDPI = HTInitInfo.DeviceResXDPI)) ||
|
|
(!(pDCI->DeviceResYDPI = HTInitInfo.DeviceResYDPI))) {
|
|
|
|
pDCI->DeviceResXDPI =
|
|
pDCI->DeviceResYDPI = 300;
|
|
DevPelRatio = 0;
|
|
}
|
|
|
|
if (DevPelRatio & 0x8000) {
|
|
|
|
//
|
|
// This is a percentage ie. 1000 = 100.0%, 960=96.0%,
|
|
// on the DeviceResXDPI, Maximum number accepted is 300.0%
|
|
// The larger the percetage the larger the dot size and smaller
|
|
// the percentage the smaller the dot size, if specified as 1000
|
|
// which is 100.0% then it has same size as its X resolution
|
|
// The range is 33.3% to 1500%
|
|
//
|
|
|
|
DevPelRatio &= 0x7FFF;
|
|
|
|
if ((DevPelRatio > MAX_RES_PERCENT) ||
|
|
(DevPelRatio < MIN_RES_PERCENT)) {
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (PERCENT) set to DEFAULT=1.0"
|
|
ARGDW(DevPelRatio)));
|
|
|
|
DevPelRatio = FD6_1;
|
|
|
|
} else {
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("*** Percentage INPUT DevicePelsDPI=%ld *** "
|
|
ARGDW(DevPelRatio)));
|
|
|
|
DevPelRatio *= 1000;
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("*** Percentage OUTPUT DevPelRatio=%s *** "
|
|
ARGFD6(DevPelRatio, 1, 6)));
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((DevPelRatio > (pDCI->DeviceResXDPI * 3)) ||
|
|
(DevPelRatio > (pDCI->DeviceResYDPI * 3))) {
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (RES) set to DEFAULT=0"
|
|
ARGDW(DevPelRatio)));
|
|
|
|
DevPelRatio = 0;
|
|
}
|
|
|
|
if (DevPelRatio) {
|
|
|
|
dwBuf[0] = (((DWORD)pDCI->DeviceResXDPI *
|
|
(DWORD)pDCI->DeviceResXDPI) +
|
|
((DWORD)pDCI->DeviceResYDPI *
|
|
(DWORD)pDCI->DeviceResYDPI));
|
|
dwBuf[1] = ((DWORD)DevPelRatio * (DWORD)DevPelRatio * 2);
|
|
DevPelRatio = SquareRoot(DivFD6(dwBuf[0], dwBuf[1]));
|
|
|
|
} else {
|
|
|
|
DevPelRatio = FD6_1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the DevicePelsDPI is out of range then we will make it 0 (same as
|
|
// device resolution), so it can continue to work
|
|
//
|
|
|
|
if (HTInitInfo.Flags & HIF_ADDITIVE_PRIMS) {
|
|
|
|
pDCI->ClrXFormBlock.ColorSpace = CIELUV_1976;
|
|
pDCI->Flags |= DCIF_ADDITIVE_PRIMS;
|
|
|
|
} else {
|
|
|
|
pDCI->ClrXFormBlock.ColorSpace = CIELAB_1976;
|
|
#if DO_DYES_CORRECTION
|
|
pDCI->Flags |= DCIF_NEED_DYES_CORRECTION;
|
|
#endif
|
|
if (HTInitInfo.Flags & HIF_DO_DEVCLR_XFORM) {
|
|
|
|
pDCI->Flags |= DCIF_DO_DEVCLR_XFORM;
|
|
}
|
|
|
|
if (HTInitInfo.Flags & HIF_HAS_BLACK_DYE) {
|
|
|
|
pDCI->Flags |= DCIF_HAS_BLACK_DYE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save the DevPelRatio back to PDCI
|
|
//
|
|
|
|
DBGP_IF(DBGP_DEVPELSDPI,
|
|
DBGP("*** XDPI=%ld, YDPI=%ld, DevPelRatio=%s *** "
|
|
ARGDW(pDCI->DeviceResXDPI) ARGDW(pDCI->DeviceResYDPI)
|
|
ARGFD6(DevPelRatio, 1, 6)));
|
|
|
|
pDCI->DevPelRatio = (FD6)DevPelRatio;
|
|
pDCI->ClrXFormBlock.DevGamma[0] = UDECI4ToFD6(HTInitInfo.DeviceRGamma);
|
|
pDCI->ClrXFormBlock.DevGamma[1] = UDECI4ToFD6(HTInitInfo.DeviceGGamma);
|
|
pDCI->ClrXFormBlock.DevGamma[2] = UDECI4ToFD6(HTInitInfo.DeviceBGamma);
|
|
|
|
if ((UseCurNTDefault) ||
|
|
(HTInitInfo.HTPatternIndex > HTPAT_SIZE_MAX_INDEX) ||
|
|
((HTInitInfo.HTPatternIndex == HTPAT_SIZE_USER) &&
|
|
(HTInitInfo.pHalftonePattern == NULL))) {
|
|
|
|
if ((HTInitInfo.HTPatternIndex != HTPAT_SIZE_8x8) &&
|
|
(HTInitInfo.HTPatternIndex != HTPAT_SIZE_8x8_M)) {
|
|
|
|
HTInitInfo.HTPatternIndex = HTPAT_SIZE_DEFAULT;
|
|
}
|
|
}
|
|
|
|
if ((HTInitInfo.Flags & HIF_ADDITIVE_PRIMS) &&
|
|
(HTInitInfo.HTPatternIndex <= HTPAT_SIZE_4x4_M)) {
|
|
|
|
HTInitInfo.HTPatternIndex = DEFAULT_SCR_HTPAT_SIZE;
|
|
}
|
|
|
|
switch (HTInitInfo.Flags & (HIF_INK_HIGH_ABSORPTION |
|
|
HIF_INK_ABSORPTION_INDICES)) {
|
|
|
|
case HIF_HIGHEST_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 0;
|
|
break;
|
|
|
|
case HIF_HIGHER_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 1;
|
|
break;
|
|
|
|
case HIF_HIGH_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 2;
|
|
break;
|
|
|
|
case HIF_LOW_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 4;
|
|
break;
|
|
|
|
case HIF_LOWER_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 5;
|
|
break;
|
|
|
|
case HIF_LOWEST_INK_ABSORPTION:
|
|
|
|
_RegDataIdx = 6;
|
|
break;
|
|
|
|
case HIF_NORMAL_INK_ABSORPTION:
|
|
default:
|
|
|
|
_RegDataIdx = 3;
|
|
break;
|
|
}
|
|
|
|
pDCI->ClrXFormBlock.RegDataIdx = (BYTE)_RegDataIdx;
|
|
|
|
GetCIEPrims(HTInitInfo.pDeviceCIEInfo,
|
|
&(pDCI->ClrXFormBlock.DevCIEPrims),
|
|
(PCIEINFO)&HT_CIE_SRGB,
|
|
TRUE);
|
|
|
|
GetCIEPrims(HTInitInfo.pInputRGBInfo,
|
|
&(pDCI->ClrXFormBlock.rgbCIEPrims),
|
|
(PCIEINFO)&HT_CIE_SRGB,
|
|
FALSE);
|
|
|
|
//
|
|
// Compute the solid dyes mixes information and its hue shifting
|
|
// correction factors.
|
|
//
|
|
|
|
if (pDCI->Flags & DCIF_NEED_DYES_CORRECTION) {
|
|
|
|
SOLIDDYESINFO SDI;
|
|
MATRIX3x3 FD6SDI;
|
|
BOOL HasDevSDI;
|
|
|
|
//
|
|
// We have make sure the solid dyes info passed from the caller can be
|
|
// inversed, if not we will use our default
|
|
//
|
|
|
|
if (HasDevSDI = (HTInitInfo.pDeviceSolidDyesInfo) ? TRUE : FALSE) {
|
|
|
|
SDI = *(HTInitInfo.pDeviceSolidDyesInfo);
|
|
|
|
if ((SDI.MagentaInCyanDye > (UDECI4)9000) ||
|
|
(SDI.YellowInCyanDye > (UDECI4)9000) ||
|
|
(SDI.CyanInMagentaDye > (UDECI4)9000) ||
|
|
(SDI.YellowInMagentaDye > (UDECI4)9000) ||
|
|
(SDI.CyanInYellowDye > (UDECI4)9000) ||
|
|
(SDI.MagentaInYellowDye > (UDECI4)9000)) {
|
|
|
|
HasDevSDI = FALSE;
|
|
|
|
} else if ((SDI.MagentaInCyanDye == UDECI4_0) &&
|
|
(SDI.YellowInCyanDye == UDECI4_0) &&
|
|
(SDI.CyanInMagentaDye == UDECI4_0) &&
|
|
(SDI.YellowInMagentaDye == UDECI4_0) &&
|
|
(SDI.CyanInYellowDye == UDECI4_0) &&
|
|
(SDI.MagentaInYellowDye == UDECI4_0)) {
|
|
|
|
//
|
|
// Do not need any correction if it all zeros
|
|
//
|
|
|
|
pDCI->Flags &= (WORD)(~DCIF_NEED_DYES_CORRECTION);
|
|
}
|
|
|
|
} else {
|
|
|
|
pDCI->Flags &= (WORD)(~DCIF_NEED_DYES_CORRECTION);
|
|
}
|
|
|
|
if (pDCI->Flags & DCIF_NEED_DYES_CORRECTION) {
|
|
|
|
#define PDCI_CMYDYEMASKS pDCI->ClrXFormBlock.CMYDyeMasks
|
|
|
|
|
|
MULDIVPAIR MDPairs[4];
|
|
FD6 Y;
|
|
|
|
|
|
if ((UseCurNTDefault) || (!HasDevSDI)) {
|
|
|
|
SDI = DefaultSolidDyesInfo;
|
|
}
|
|
|
|
FD6SDI.m[0][1] = UDECI4ToFD6(SDI.CyanInMagentaDye);
|
|
FD6SDI.m[0][2] = UDECI4ToFD6(SDI.CyanInYellowDye);
|
|
|
|
FD6SDI.m[1][0] = UDECI4ToFD6(SDI.MagentaInCyanDye);
|
|
FD6SDI.m[1][2] = UDECI4ToFD6(SDI.MagentaInYellowDye);
|
|
|
|
FD6SDI.m[2][0] = UDECI4ToFD6(SDI.YellowInCyanDye);
|
|
FD6SDI.m[2][1] = UDECI4ToFD6(SDI.YellowInMagentaDye);
|
|
|
|
FD6SDI.m[0][0] =
|
|
FD6SDI.m[1][1] =
|
|
FD6SDI.m[2][2] = FD6_1;
|
|
|
|
ComputeInverseMatrix3x3(&FD6SDI, &(PDCI_CMYDYEMASKS));
|
|
|
|
if (!(pDCI->Flags & DCIF_HAS_BLACK_DYE)) {
|
|
|
|
MAKE_MULDIV_INFO(MDPairs, 3, MULDIV_NO_DIVISOR);
|
|
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Xr(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Xg(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Xb(PDCI_CMYDYEMASKS), FD6_1);
|
|
|
|
Y = FD6_1 - MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
|
|
pDCI->PrimAdj.DevCSXForm.Yrgb.R);
|
|
|
|
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Yr(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Yg(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Yb(PDCI_CMYDYEMASKS), FD6_1);
|
|
|
|
Y -= MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
|
|
pDCI->PrimAdj.DevCSXForm.Yrgb.G);
|
|
|
|
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Zr(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Zg(PDCI_CMYDYEMASKS), FD6_1);
|
|
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Zb(PDCI_CMYDYEMASKS), FD6_1);
|
|
|
|
Y -= MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
|
|
pDCI->PrimAdj.DevCSXForm.Yrgb.B);
|
|
|
|
DBGP_IF(DBGP_DYECORRECTION,
|
|
DBGP("DYE: Maximum Y=%s, Make Luminance from %s to %s, Turn ON DCIF_HAS_BLACK_DYE"
|
|
ARGFD6(Y, 1, 6)
|
|
ARGFD6(pDCI->ClrXFormBlock.DevCIEPrims.Yw, 1, 6)
|
|
ARGFD6(MulFD6(Y,
|
|
pDCI->ClrXFormBlock.DevCIEPrims.Yw),
|
|
1, 6)));
|
|
|
|
pDCI->Flags |= DCIF_HAS_BLACK_DYE;
|
|
pDCI->ClrXFormBlock.DevCIEPrims.Yw =
|
|
MulFD6(pDCI->ClrXFormBlock.DevCIEPrims.Yw, Y);
|
|
}
|
|
|
|
DBGP_IF(DBGP_DYECORRECTION,
|
|
|
|
FD6 C;
|
|
FD6 M;
|
|
FD6 Y;
|
|
FD6 C1;
|
|
FD6 M1;
|
|
FD6 Y1;
|
|
static BYTE DyeName[] = "WCMBYGRK";
|
|
WORD Loop = 0;
|
|
|
|
DBGP("====== DyeCorrection 3x3 Matrix =======");
|
|
DBGP("[Cc Cm Cy] [%s %s %s] [%s %s %s]"
|
|
ARGFD6(FD6SDI.m[0][0], 2, 6)
|
|
ARGFD6(FD6SDI.m[0][1], 2, 6)
|
|
ARGFD6(FD6SDI.m[0][2], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[0][0], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[0][1], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[0][2], 2, 6));
|
|
DBGP("[Mc Mm My]=[%s %s %s]=[%s %s %s]"
|
|
ARGFD6(FD6SDI.m[1][0], 2, 6)
|
|
ARGFD6(FD6SDI.m[1][1], 2, 6)
|
|
ARGFD6(FD6SDI.m[1][2], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[1][0], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[1][1], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[1][2], 2, 6));
|
|
DBGP("[Yc Ym Yy] [%s %s %s] [%s %s %s]"
|
|
ARGFD6(FD6SDI.m[2][0], 2, 6)
|
|
ARGFD6(FD6SDI.m[2][1], 2, 6)
|
|
ARGFD6(FD6SDI.m[2][2], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[2][0], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[2][1], 2, 6)
|
|
ARGFD6(PDCI_CMYDYEMASKS.m[2][2], 2, 6));
|
|
DBGP("================================================");
|
|
|
|
MAKE_MULDIV_INFO(MDPairs, 3, MULDIV_NO_DIVISOR);
|
|
|
|
for (Loop = 0; Loop <= 7; Loop++) {
|
|
|
|
C = (FD6)((Loop & 0x01) ? FD6_1 : FD6_0);
|
|
M = (FD6)((Loop & 0x02) ? FD6_1 : FD6_0);
|
|
Y = (FD6)((Loop & 0x04) ? FD6_1 : FD6_0);
|
|
|
|
|
|
MAKE_MULDIV_PAIR(MDPairs,1,CIE_Xr(PDCI_CMYDYEMASKS),C);
|
|
MAKE_MULDIV_PAIR(MDPairs,2,CIE_Xg(PDCI_CMYDYEMASKS),M);
|
|
MAKE_MULDIV_PAIR(MDPairs,3,CIE_Xb(PDCI_CMYDYEMASKS),Y);
|
|
C1 = MulDivFD6Pairs(MDPairs);
|
|
|
|
MAKE_MULDIV_PAIR(MDPairs,1,CIE_Yr(PDCI_CMYDYEMASKS),C);
|
|
MAKE_MULDIV_PAIR(MDPairs,2,CIE_Yg(PDCI_CMYDYEMASKS),M);
|
|
MAKE_MULDIV_PAIR(MDPairs,3,CIE_Yb(PDCI_CMYDYEMASKS),Y);
|
|
M1 = MulDivFD6Pairs(MDPairs);
|
|
|
|
MAKE_MULDIV_PAIR(MDPairs,1,CIE_Zr(PDCI_CMYDYEMASKS),C);
|
|
MAKE_MULDIV_PAIR(MDPairs,2,CIE_Zg(PDCI_CMYDYEMASKS),M);
|
|
MAKE_MULDIV_PAIR(MDPairs,3,CIE_Zb(PDCI_CMYDYEMASKS),Y);
|
|
Y1 = MulDivFD6Pairs(MDPairs);
|
|
|
|
DBGP("%u:[%c] = [%s %s %s]"
|
|
ARGU(Loop) ARGB(DyeName[Loop])
|
|
ARGFD6(C1, 2, 6) ARGFD6(M1, 2, 6) ARGFD6(Y1, 2, 6));
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Re-compute
|
|
//
|
|
// Geneate internal HTCELL data structure based on the halftone
|
|
// pattern data passed.
|
|
//
|
|
|
|
if ((Result = ComputeHTCell((WORD)HTInitInfo.HTPatternIndex,
|
|
HTInitInfo.pHalftonePattern,
|
|
pDCI)) < 0) {
|
|
|
|
CleanUpDHI((PDEVICEHALFTONEINFO)pHT_DHI);
|
|
HTAPI_RET(HTAPI_IDX_CREATE_DHI, Result);
|
|
}
|
|
|
|
//
|
|
// Compute simulated rotate pattern for 3 planes
|
|
//
|
|
|
|
#if DO_CACHE_DCI
|
|
AddCachedDCI(pDCI);
|
|
#endif
|
|
}
|
|
|
|
pDCI->CRTX[CRTX_LEVEL_255].PrimMax = CRTX_PRIMMAX_255;
|
|
pDCI->CRTX[CRTX_LEVEL_255].SizeCRTX = (WORD)CRTX_SIZE_255;
|
|
pDCI->CRTX[CRTX_LEVEL_RGB].PrimMax = CRTX_PRIMMAX_RGB;
|
|
pDCI->CRTX[CRTX_LEVEL_RGB].SizeCRTX = (WORD)CRTX_SIZE_RGB;
|
|
|
|
//
|
|
// Setting the public field so the caller can looked at
|
|
//
|
|
|
|
pHT_DHI->DHI.DeviceOwnData = 0;
|
|
pHT_DHI->DHI.cxPattern = (WORD)pDCI->HTCell.cxReal;
|
|
pHT_DHI->DHI.cyPattern = (WORD)pDCI->HTCell.Height;
|
|
|
|
if ((HTInitInfo.DefHTColorAdjustment.caIlluminantIndex >
|
|
ILLUMINANT_MAX_INDEX) ||
|
|
(HTInitInfo.DefHTColorAdjustment.caSize !=
|
|
sizeof(COLORADJUSTMENT)) ||
|
|
((HTInitInfo.DefHTColorAdjustment.caRedGamma == 10000) &&
|
|
(HTInitInfo.DefHTColorAdjustment.caGreenGamma == 10000) &&
|
|
(HTInitInfo.DefHTColorAdjustment.caBlueGamma == 10000))) {
|
|
|
|
pHT_DHI->DHI.HTColorAdjustment = DefaultCA;
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("*** USE DEFAULT COLORADJUSTMENT in DCI *** "));
|
|
|
|
} else {
|
|
|
|
pHT_DHI->DHI.HTColorAdjustment = HTInitInfo.DefHTColorAdjustment;
|
|
}
|
|
|
|
if ((HTInitInfo.Flags & (HIF_ADDITIVE_PRIMS | HIF_PRINT_DRAFT_MODE)) ==
|
|
HIF_PRINT_DRAFT_MODE) {
|
|
|
|
pDCI->Flags |= DCIF_PRINT_DRAFT_MODE;
|
|
}
|
|
|
|
//
|
|
// Compute what 8bpp mode we will be in
|
|
//
|
|
|
|
if (HTInitInfo.Flags & HIF_USE_8BPP_BITMASK) {
|
|
|
|
pDCI->Flags |= DCIF_USE_8BPP_BITMASK |
|
|
((HTInitInfo.Flags & HIF_INVERT_8BPP_BITMASK_IDX) ?
|
|
DCIF_INVERT_8BPP_BITMASK_IDX : 0);
|
|
_cC = (DWORD)((HTInitInfo.CMYBitMask8BPP >> 5) & 0x7);
|
|
_cM = (DWORD)((HTInitInfo.CMYBitMask8BPP >> 2) & 0x7);
|
|
_cY = (DWORD)((HTInitInfo.CMYBitMask8BPP ) & 0x3);
|
|
|
|
if (HTInitInfo.CMYBitMask8BPP == 1) {
|
|
|
|
//
|
|
// This is 4:4:4: format (0-4 of 5 levels)
|
|
//
|
|
|
|
_cC =
|
|
_cM =
|
|
_cY = 4;
|
|
HTInitInfo.CMYBitMask8BPP = (BYTE)((5 * 5 * 5) - 1);
|
|
|
|
} else if (HTInitInfo.CMYBitMask8BPP == 2) {
|
|
|
|
//
|
|
// This is 5:5:5: format (0-5 of 6 levels)
|
|
//
|
|
|
|
_cC =
|
|
_cM =
|
|
_cY = 5;
|
|
HTInitInfo.CMYBitMask8BPP = (BYTE)((6 * 6 * 6) - 1);
|
|
|
|
} else if ((_cC < 1) || (_cM < 1) || (_cY < 1)) {
|
|
|
|
_cC =
|
|
_cM =
|
|
_cY = 0xFF;
|
|
HTInitInfo.CMYBitMask8BPP = 0xFF;
|
|
pDCI->Flags |= DCIF_MONO_8BPP_BITMASK;
|
|
}
|
|
|
|
pDCI->CMY8BPPMask.GenerateXlate =
|
|
(pDCI->Flags & DCIF_INVERT_8BPP_BITMASK_IDX) ? 1 : 0;
|
|
|
|
if ((_cC == _cM) && (_cC == _cY)) {
|
|
|
|
pDCI->Flags |= DCIF_CMY8BPPMASK_SAME_LEVEL;
|
|
pDCI->CMY8BPPMask.SameLevel = (BYTE)_cC;
|
|
|
|
} else {
|
|
|
|
pDCI->CMY8BPPMask.SameLevel = 0;
|
|
}
|
|
|
|
if ((_MaxCMY = _cC) < _cM) {
|
|
|
|
_MaxCMY = _cM;
|
|
}
|
|
|
|
if (_MaxCMY < _cY) {
|
|
|
|
_MaxCMY = _cY;
|
|
}
|
|
|
|
//
|
|
// Set to 0xFFFF to indicate this is a default setting to start with
|
|
// then modified depends on the parameters passed
|
|
//
|
|
|
|
pDCI->CMY8BPPMask.KCheck = 0xFFFF;
|
|
|
|
if ((_MaxCMY <= 6) &&
|
|
(pHTInitInfo->pDeviceCIEInfo) &&
|
|
(pHTInitInfo->pDeviceCIEInfo->Blue.Y == VALID_YB_DENSITY)) {
|
|
|
|
PCIEINFO pCIE = pHTInitInfo->pDeviceCIEInfo;
|
|
|
|
//
|
|
// 27-Sep-2000 Wed 15:05:38 updated -by- Daniel Chou (danielc)
|
|
// if Blue.Y == 0xfffe then it specified that it has CMY densities
|
|
// in the CIEINFO, Cyan.x=C1,C2, Cyan.y=C3,C4, Red.Y=C5,C6
|
|
// Magenta.x=M1,M2, Magenta.y=M3,M4, Magenta.Y=M5,M6
|
|
// Yellow.x=Y1,Y2, Yellow.y=Y3,Y4, Yellow.Y=Y5,Y6, each density is
|
|
// one byte and its computation is (C1+1)/256 to get the perentage
|
|
// of the density. The Last level is to specified maximum dye
|
|
// output for that color. for example if Cyan has 2 levels
|
|
// and C1=0x7F and C2=0xF0 then first level of ink is
|
|
// (0x7f+1) / 0x100=50% and last level of ink is 0xF0 which
|
|
// speicified maximum ink will be used, at here =
|
|
// (0xF0 + 1) / 0x100 = 94.14% which maximum cyan ink will be at
|
|
// 94.14% not 100%
|
|
//
|
|
|
|
pDCI->Flags |= DCIF_HAS_DENSITY;
|
|
pDCI->CMY8BPPMask.DenC[0] = GET_DEN_HI(pCIE->Cyan.x);
|
|
pDCI->CMY8BPPMask.DenC[1] = GET_DEN_LO(pCIE->Cyan.x);
|
|
pDCI->CMY8BPPMask.DenC[2] = GET_DEN_HI(pCIE->Cyan.y);
|
|
pDCI->CMY8BPPMask.DenC[3] = GET_DEN_LO(pCIE->Cyan.y);
|
|
pDCI->CMY8BPPMask.DenC[4] = GET_DEN_HI(pCIE->Red.Y);
|
|
pDCI->CMY8BPPMask.DenC[5] = GET_DEN_LO(pCIE->Red.Y);
|
|
pDCI->CMY8BPPMask.DenM[0] = GET_DEN_HI(pCIE->Magenta.x);
|
|
pDCI->CMY8BPPMask.DenM[1] = GET_DEN_LO(pCIE->Magenta.x);
|
|
pDCI->CMY8BPPMask.DenM[2] = GET_DEN_HI(pCIE->Magenta.y);
|
|
pDCI->CMY8BPPMask.DenM[3] = GET_DEN_LO(pCIE->Magenta.y);
|
|
pDCI->CMY8BPPMask.DenM[4] = GET_DEN_HI(pCIE->Magenta.Y);
|
|
pDCI->CMY8BPPMask.DenM[5] = GET_DEN_LO(pCIE->Magenta.Y);
|
|
pDCI->CMY8BPPMask.DenY[0] = GET_DEN_HI(pCIE->Yellow.x);
|
|
pDCI->CMY8BPPMask.DenY[1] = GET_DEN_LO(pCIE->Yellow.x);
|
|
pDCI->CMY8BPPMask.DenY[2] = GET_DEN_HI(pCIE->Yellow.y);
|
|
pDCI->CMY8BPPMask.DenY[3] = GET_DEN_LO(pCIE->Yellow.y);
|
|
pDCI->CMY8BPPMask.DenY[4] = GET_DEN_HI(pCIE->Yellow.Y);
|
|
pDCI->CMY8BPPMask.DenY[5] = GET_DEN_LO(pCIE->Yellow.Y);
|
|
|
|
//
|
|
// The Green.Y is a UDECI4 number that specified the black ink
|
|
// replacement base ratio, the range and meaning as follow
|
|
//
|
|
// 0: Default black ink replacement computation
|
|
// 1 - 9999: Specified black ink replacement base ratio
|
|
// >= 10000: turn off black ink replacement computation
|
|
//
|
|
|
|
if (pCIE->Green.Y >= UDECI4_1) {
|
|
|
|
pDCI->CMY8BPPMask.KCheck = FD6_0;
|
|
|
|
} else if (pCIE->Green.Y != UDECI4_0) {
|
|
|
|
pDCI->CMY8BPPMask.KCheck = UDECI4ToFD6(pCIE->Green.Y);
|
|
}
|
|
|
|
_MaxMulDiv = DivFD6(FD6_1, pDCI->DevPelRatio);
|
|
pDCI->CMY8BPPMask.MaxMulC = MulFD6(pDCI->CMY8BPPMask.DenC[_cC - 1],
|
|
_MaxMulDiv);
|
|
pDCI->CMY8BPPMask.MaxMulM = MulFD6(pDCI->CMY8BPPMask.DenM[_cM - 1],
|
|
_MaxMulDiv);
|
|
pDCI->CMY8BPPMask.MaxMulY = MulFD6(pDCI->CMY8BPPMask.DenY[_cY - 1],
|
|
_MaxMulDiv);
|
|
|
|
for (_Idx = COUNT_ARRAY(pDCI->CMY8BPPMask.DenC);
|
|
_Idx > 0;
|
|
_Idx--) {
|
|
|
|
if (_Idx >= _cC) {
|
|
|
|
pDCI->CMY8BPPMask.DenC[_Idx - 1] = FD6_1;
|
|
}
|
|
|
|
if (_Idx >= _cM) {
|
|
|
|
pDCI->CMY8BPPMask.DenM[_Idx - 1] = FD6_1;
|
|
}
|
|
|
|
if (_Idx >= _cY) {
|
|
|
|
pDCI->CMY8BPPMask.DenY[_Idx - 1] = FD6_1;
|
|
}
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" Cyan %ld/%s Density: %s, %s, %s, %s, %s, %s"
|
|
ARGDW(_cC)
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulC, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[0], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[1], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[2], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[3], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[4], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenC[5], 1, 6)));
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("Magenta %ld/%s Density: %s, %s, %s, %s, %s, %s"
|
|
ARGDW(_cM)
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulM, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[0], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[1], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[2], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[3], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[4], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenM[5], 1, 6)));
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP(" Yellow %ld/%s Density: %s, %s, %s, %s, %s, %s"
|
|
ARGDW(_cY)
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulY, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[0], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[1], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[2], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[3], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[4], 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.DenY[5], 1, 6)));
|
|
|
|
} else {
|
|
|
|
_MaxMulDiv = FD6xL(pDCI->DevPelRatio, _MaxCMY);
|
|
pDCI->CMY8BPPMask.MaxMulC = DivFD6(FD6xL(FD6_1, _cC), _MaxMulDiv);
|
|
pDCI->CMY8BPPMask.MaxMulM = DivFD6(FD6xL(FD6_1, _cM), _MaxMulDiv);
|
|
pDCI->CMY8BPPMask.MaxMulY = DivFD6(FD6xL(FD6_1, _cY), _MaxMulDiv);
|
|
}
|
|
|
|
if ((_MaxMulDiv = pDCI->CMY8BPPMask.MaxMulC) <
|
|
pDCI->CMY8BPPMask.MaxMulM) {
|
|
|
|
_MaxMulDiv = pDCI->CMY8BPPMask.MaxMulM;
|
|
}
|
|
|
|
if (_MaxMulDiv < pDCI->CMY8BPPMask.MaxMulY) {
|
|
|
|
_MaxMulDiv = pDCI->CMY8BPPMask.MaxMulY;
|
|
}
|
|
|
|
if (pDCI->CMY8BPPMask.KCheck == 0xFFFF) {
|
|
|
|
//
|
|
// Default setting, turn off K Replacement only if
|
|
// DevPelsRatio/Density = 100% and CMY inks are in same level
|
|
//
|
|
|
|
pDCI->CMY8BPPMask.KCheck =
|
|
((_MaxMulDiv == FD6_1) &&
|
|
(pDCI->Flags & DCIF_CMY8BPPMASK_SAME_LEVEL)) ?
|
|
FD6_0 : K_REP_START;
|
|
}
|
|
|
|
if (pDCI->CMY8BPPMask.KCheck == FD6_0) {
|
|
|
|
//
|
|
// If K replacement was turn off, but the ratio is not 100% or
|
|
// have different ink levels then wee need to turn it on at
|
|
// 1.0 (FD6_1) so that a 8bpp black replacement function is
|
|
// used, only in k replacement function it compute how to
|
|
// reduced non 100% device pel ratio (KPower)
|
|
//
|
|
|
|
if ((_MaxMulDiv != FD6_1) ||
|
|
(!(pDCI->Flags & DCIF_CMY8BPPMASK_SAME_LEVEL))) {
|
|
|
|
pDCI->CMY8BPPMask.KCheck = FD6_1;
|
|
}
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("KCheck= %s ^ %s = %s"
|
|
ARGFD6(pDCI->CMY8BPPMask.KCheck, 1, 6) ARGFD6(_MaxMulDiv, 1, 6)
|
|
ARGFD6(Power(pDCI->CMY8BPPMask.KCheck, _MaxMulDiv), 1, 6)));
|
|
|
|
pDCI->CMY8BPPMask.KCheck = Power(pDCI->CMY8BPPMask.KCheck, _MaxMulDiv);
|
|
pDCI->CMY8BPPMask.PatSubC =
|
|
(WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulC, 0xFFF) + 1;
|
|
pDCI->CMY8BPPMask.PatSubM =
|
|
(WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulM, 0xFFF) + 1;
|
|
pDCI->CMY8BPPMask.PatSubY =
|
|
(WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulY, 0xFFF) + 1;
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("*** USE_8BPP_BITMASK: CMY=%ld:%ld:%ld, Same=%ld], Mask=%02lx, Max=%ld ***"
|
|
ARGDW(_cC) ARGDW(_cM) ARGDW(_cY)
|
|
ARGDW(pDCI->CMY8BPPMask.SameLevel)
|
|
ARGDW(HTInitInfo.CMYBitMask8BPP) ARGDW(_MaxCMY)));
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("*** MaxMulCMY=%s:%s:%s [KCheck=%s], SubCMY=%4ld:%4ld:%4ld ***"
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulC, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulM, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.MaxMulY, 1, 6)
|
|
ARGFD6(pDCI->CMY8BPPMask.KCheck, 1, 6)
|
|
ARGDW(pDCI->CMY8BPPMask.PatSubC)
|
|
ARGDW(pDCI->CMY8BPPMask.PatSubM)
|
|
ARGDW(pDCI->CMY8BPPMask.PatSubY)));
|
|
|
|
} else {
|
|
|
|
_cC =
|
|
_cM =
|
|
_cY =
|
|
_MaxCMY = 1;
|
|
HTInitInfo.CMYBitMask8BPP = 0xFF;
|
|
}
|
|
|
|
pDCI->CMY8BPPMask.cC = (BYTE)_cC;
|
|
pDCI->CMY8BPPMask.cM = (BYTE)_cM;
|
|
pDCI->CMY8BPPMask.cY = (BYTE)_cY;
|
|
pDCI->CMY8BPPMask.Max = (BYTE)_MaxCMY;
|
|
pDCI->CMY8BPPMask.Mask = (BYTE)HTInitInfo.CMYBitMask8BPP;
|
|
|
|
//
|
|
// Now compute the HTSMP checksum for the pattern
|
|
//
|
|
|
|
dwBuf[0] = (DWORD)pDCI->DeviceResXDPI;
|
|
dwBuf[1] = (DWORD)pDCI->DeviceResYDPI;
|
|
dwBuf[2] = (DWORD)pDCI->DevPelRatio;
|
|
dwBuf[3] = (DWORD)(dwBuf[0] + dwBuf[1]);
|
|
|
|
pDCI->HTSMPChecksum = ComputeChecksum((LPBYTE)&dwBuf[0],
|
|
HTSMP_INITIAL_CHECKSUM,
|
|
sizeof(dwBuf[0]) * 4);
|
|
|
|
ASSERTMSG("pDCI->ClrXFormBlock.RegDataIdx > 6",
|
|
(pDCI->ClrXFormBlock.RegDataIdx < 7));
|
|
|
|
if (pDCI->ClrXFormBlock.RegDataIdx > 6) {
|
|
|
|
pDCI->ClrXFormBlock.RegDataIdx = 3;
|
|
}
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("SMP Checksum = %08lx, RegDataIdx=%u"
|
|
ARGDW(pDCI->HTSMPChecksum)
|
|
ARGU(pDCI->ClrXFormBlock.RegDataIdx)));
|
|
|
|
DBGP_IF(DBGP_CACHED_DCI,
|
|
DBGP("*** Final DevResDPI=%ld x %ld DevPelRatio=%ld, cx/cyPat=%ld x %ld=%ld *** "
|
|
ARGDW(pDCI->DeviceResXDPI)
|
|
ARGDW(pDCI->DeviceResYDPI)
|
|
ARGDW(pDCI->DevPelRatio)
|
|
ARGDW(pHT_DHI->DHI.cxPattern)
|
|
ARGDW(pHT_DHI->DHI.cyPattern)
|
|
ARGDW(pDCI->HTCell.Size)));
|
|
|
|
//
|
|
// Set the ILLUMINANT index to an invalid value for next one will get
|
|
// computed
|
|
//
|
|
|
|
pDCI->Flags |= ExtraDCIF;
|
|
pDCI->ca.caSize = ADJ_FORCE_DEVXFORM;
|
|
pDCI->ca.caIlluminantIndex = 0xffff;
|
|
*ppDeviceHalftoneInfo = (PDEVICEHALFTONEINFO)pHT_DHI;
|
|
|
|
return(HALFTONE_DLL_ID);
|
|
|
|
|
|
#undef _RegDataIdx
|
|
#undef _MaxMulDiv
|
|
#undef _cC
|
|
#undef _cM
|
|
#undef _cY
|
|
#undef _MaxCMY
|
|
#undef _Idx
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_DestroyDeviceHalftoneInfo(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function destroy the handle which returned from halftone initialize
|
|
function HT_CreateDeviceHalftoneInfo()
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
|
|
which returned from the HT_CreateDeviceHalftoneInfo.
|
|
|
|
Return Value:
|
|
|
|
TRUE - if function sucessed.
|
|
FALSE - if function failed.
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 14:18:20 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
if ((!pDeviceHalftoneInfo) ||
|
|
(PHT_DHI_DCI_OF(HalftoneDLLID) != HALFTONE_DLL_ID)) {
|
|
|
|
SET_ERR(HTAPI_IDX_DESTROY_DHI, HTERR_INVALID_DHI_POINTER);
|
|
return(FALSE);
|
|
}
|
|
|
|
return(CleanUpDHI(pDeviceHalftoneInfo));
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_CreateHalftoneBrush(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
|
|
PHTCOLORADJUSTMENT pHTColorAdjustment,
|
|
PCOLORTRIAD pColorTriad,
|
|
CHBINFO CHBInfo,
|
|
LPVOID pOutputBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function create halftone mask for the requested solid color.
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
|
|
which returned from the HT_CreateDeviceHalftoneInfo.
|
|
|
|
pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data structure to
|
|
specified the input/output color adjustment/transform,
|
|
if this pointer is NULL then a default color
|
|
adjustments is applied.
|
|
|
|
pColorTriad - Pointer to the COLORTRIAD data structure to describe
|
|
the brush colors.
|
|
|
|
CHBInfo - CHBINFO data structure, specified following:
|
|
|
|
Flags: CHBF_BW_ONLY
|
|
CHBF_USE_ADDITIVE_PRIMS
|
|
CHBF_NEGATIVE_PATTERN
|
|
|
|
|
|
DestSurfaceFormat: BMF_1BPP
|
|
BMF_4BPP
|
|
BMF_4BPP_VGA16
|
|
BMF_8BPP_VGA256
|
|
|
|
ScanLineAlignBytes: 0 - 255
|
|
|
|
DestPrimaryOrder: One of PRIMARY_ORDER_xxx
|
|
|
|
|
|
|
|
pOutputBuffer - Pointer to the buffer area to received indices/mask.
|
|
in bytes needed to stored the halftone pattern.
|
|
|
|
|
|
Return Value:
|
|
|
|
if the return value is negative or zero then an error was encountered,
|
|
possible error codes are
|
|
|
|
HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is
|
|
passed.
|
|
|
|
HTERR_INVALID_DEST_FORMAT - the Format of the destination
|
|
surface is not one of the defined
|
|
HSC_FORMAT_xxxx
|
|
|
|
HTERR_CHB_INV_COLORTABLE_SIZE - Color table size is not 1
|
|
|
|
otherwise
|
|
|
|
If pSurface is NULL, it return the bytes count which need to stored
|
|
the pattern, otherwise it return the size in byte copied to the output
|
|
buffer.
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 14:28:23 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEVICECOLORINFO pDCI;
|
|
PDEVCLRADJ pDevClrAdj;
|
|
CTSTD_UNION CTSTDUnion;
|
|
WORD ForceFlags;
|
|
LONG cbBufScan;
|
|
LONG cbBufSize;
|
|
|
|
|
|
if ((!pColorTriad) ||
|
|
(pColorTriad->ColorTableEntries != 1) ||
|
|
(!(pColorTriad->pColorTable))) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CHB, HTERR_CHB_INV_COLORTABLE_SIZE);
|
|
}
|
|
|
|
ForceFlags = ADJ_FORCE_BRUSH;
|
|
CTSTDUnion.b.cbPrim = 0;
|
|
CTSTDUnion.b.SrcOrder = pColorTriad->PrimaryOrder;
|
|
CTSTDUnion.b.BMFDest = CHBInfo.DestSurfaceFormat;
|
|
CTSTDUnion.b.DestOrder = CHBInfo.DestPrimaryOrder;
|
|
|
|
if ((CHBInfo.Flags & CHBF_BW_ONLY) ||
|
|
(CHBInfo.DestSurfaceFormat == BMF_1BPP)) {
|
|
|
|
ForceFlags |= ADJ_FORCE_MONO;
|
|
}
|
|
|
|
if (CHBInfo.Flags & CHBF_NEGATIVE_BRUSH) {
|
|
|
|
ForceFlags |= ADJ_FORCE_NEGATIVE;
|
|
}
|
|
|
|
if (CHBInfo.Flags & CHBF_USE_ADDITIVE_PRIMS) {
|
|
|
|
ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
|
|
}
|
|
|
|
if (CHBInfo.Flags & CHBF_ICM_ON) {
|
|
|
|
ForceFlags |= ADJ_FORCE_ICM;
|
|
}
|
|
|
|
SETDBGVAR(pDevClrAdj, NULL);
|
|
|
|
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
|
|
pHTColorAdjustment,
|
|
(pOutputBuffer) ? &pDevClrAdj : NULL,
|
|
0,
|
|
ForceFlags,
|
|
CTSTDUnion.b,
|
|
&cbBufSize))) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CHB, cbBufSize);
|
|
}
|
|
|
|
cbBufScan = (LONG)ComputeBytesPerScanLine(
|
|
(UINT)CHBInfo.DestSurfaceFormat,
|
|
(UINT)CHBInfo.DestScanLineAlignBytes,
|
|
(DWORD)pDCI->HTCell.cxReal);
|
|
cbBufSize = cbBufScan * (LONG)pDCI->HTCell.Height;
|
|
|
|
if (pOutputBuffer) {
|
|
|
|
if (CHBInfo.Flags & CHBF_BOTTOMUP_BRUSH) {
|
|
|
|
(LPBYTE)pOutputBuffer += (cbBufSize - cbBufScan);
|
|
cbBufScan = -cbBufScan;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// CreateHalftoneBrushPat will release the semaphore for us
|
|
//-------------------------------------------------------------------
|
|
|
|
if ((cbBufScan = CreateHalftoneBrushPat(pDCI,
|
|
pColorTriad,
|
|
pDevClrAdj,
|
|
pOutputBuffer,
|
|
cbBufScan)) <= 0) {
|
|
|
|
cbBufSize = cbBufScan;
|
|
}
|
|
|
|
if (HTFreeMem(pDevClrAdj)) {
|
|
|
|
ASSERTMSG("HTFreeMem(pDevClrAdj) Failed", FALSE);
|
|
}
|
|
|
|
} else {
|
|
|
|
RELEASE_HTMUTEX(pDCI->HTMutex);
|
|
|
|
ASSERT(pDevClrAdj == NULL);
|
|
}
|
|
|
|
DBGP_IF(DBGP_HTAPI,
|
|
DBGP("HT_CreateHalftoneBrush(%hs %ld/%6ld): RGB=0x%08lx (%ld), Dst(Fmt=%ld, Order=%ld)"
|
|
ARGPTR((pOutputBuffer) ? "BUF" : "NUL")
|
|
ARGDW(pDCI->cbMemTot) ARGDW(pDCI->cbMemMax)
|
|
ARGDW(*((LPDWORD)pColorTriad->pColorTable))
|
|
ARGDW(pColorTriad->PrimaryOrder)
|
|
ARGDW(CHBInfo.DestSurfaceFormat)
|
|
ARGDW(CHBInfo.DestPrimaryOrder)));
|
|
|
|
HTAPI_RET(HTAPI_IDX_CHB, cbBufSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_ComputeRGBGammaTable(
|
|
WORD GammaTableEntries,
|
|
WORD GammaTableType,
|
|
UDECI4 RedGamma,
|
|
UDECI4 GreenGamma,
|
|
UDECI4 BlueGamma,
|
|
LPBYTE pGammaTable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function compute device gamma correction table based on the lightness
|
|
|
|
(1/RedGamma)
|
|
Gamma[N] = INT((LIGHTNESS(N / GammaTableEntries-1)) x 255)
|
|
|
|
3
|
|
LIGHTNESS(x) = ((x + 0.16) / 1.16) if x >= 0.007996
|
|
(x / 9.033) if x < 0.007996
|
|
|
|
|
|
1. INT() is a integer function which round up to next integer number if
|
|
resulting fraction is 0.5 or higher, the final result always limit
|
|
to have range between 0 and 255.
|
|
|
|
2. N is a integer step number and range from 0 to (GammaTableEntries-1)
|
|
in one (1) increment.
|
|
|
|
|
|
Arguments:
|
|
|
|
GammaTableEntries - Total gamma table entries for each of red, green
|
|
and blue gamma table, halftone dll normalized
|
|
the gamma table with step value computed as
|
|
1/GammaTableEntries.
|
|
|
|
This value must range from 3 to 255 else a 0
|
|
is returned and no table is updated.
|
|
|
|
GammaTableType - red, green and blue gamma table organizations
|
|
|
|
0 - The gamma table is Red, Green, Blue 3 bytes
|
|
for each gamma step entries and total of
|
|
GammaTableEntries entries.
|
|
|
|
1 - The gamma table is Red Gamma tables follow
|
|
by green gamma table then follow by blue
|
|
gamma table, each table has total of
|
|
GammaTableEntries bytes.
|
|
|
|
Other value default to 0.
|
|
|
|
RedGamma - Red gamma number in UDECI4 format
|
|
|
|
GreenGamma - Green gamma number in UDECI4 format
|
|
|
|
BlueGamma - Blue gamma number in UDECI4 format
|
|
|
|
pGammaTable - pointer to the gamma table byte array.
|
|
each output gamma number is range from 0 to 255.
|
|
|
|
|
|
Return Value:
|
|
|
|
Return value is the total table entries updated.
|
|
|
|
Author:
|
|
|
|
15-Sep-1992 Tue 17:49:20 updated -by- Daniel Chou (danielc)
|
|
Fixed bug# 6257
|
|
|
|
17-Jul-1992 Fri 19:04:31 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pRGamma;
|
|
LPBYTE pGGamma;
|
|
LPBYTE pBGamma;
|
|
FD6 L_StepInc;
|
|
FD6 IValue;
|
|
FD6 Lightness;
|
|
LONG Result;
|
|
UINT NextEntry;
|
|
FD6 RGBGamma[3];
|
|
|
|
|
|
//
|
|
// Initialize All internal data first
|
|
//
|
|
|
|
if (((Result = GammaTableEntries) > 256) ||
|
|
(Result < 2)) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
Lightness = FD6_0;
|
|
L_StepInc = DivFD6((FD6)1, (FD6)(GammaTableEntries - 1));
|
|
RGBGamma[0] = UDECI4ToFD6(RedGamma);
|
|
RGBGamma[1] = UDECI4ToFD6(GreenGamma);
|
|
RGBGamma[2] = UDECI4ToFD6(BlueGamma);
|
|
|
|
pRGamma = pGammaTable;
|
|
|
|
if (GammaTableType == 1) {
|
|
|
|
pGGamma = pRGamma + GammaTableEntries;
|
|
pBGamma = pGGamma + GammaTableEntries;
|
|
NextEntry = 1;
|
|
|
|
} else {
|
|
|
|
pGGamma = pRGamma + 1;
|
|
pBGamma = pGGamma + 1;
|
|
NextEntry = 3;
|
|
}
|
|
|
|
while (--GammaTableEntries) {
|
|
|
|
IValue = Lightness; // CIE_L2I(Lightness);
|
|
*pRGamma = RGB_8BPP(Radical(IValue, RGBGamma[0]));
|
|
*pGGamma = RGB_8BPP(Radical(IValue, RGBGamma[1]));
|
|
*pBGamma = RGB_8BPP(Radical(IValue, RGBGamma[2]));
|
|
pRGamma += NextEntry;
|
|
pGGamma += NextEntry;
|
|
pBGamma += NextEntry;
|
|
Lightness += L_StepInc;
|
|
}
|
|
|
|
*pRGamma =
|
|
*pGGamma =
|
|
*pBGamma = 255;
|
|
|
|
return(Result);
|
|
}
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_Get8BPPFormatPalette(
|
|
LPPALETTEENTRY pPaletteEntry,
|
|
UDECI4 RedGamma,
|
|
UDECI4 GreenGamma,
|
|
UDECI4 BlueGamma
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions retrieve a halftone's VGA256 color table definitions
|
|
|
|
Arguments:
|
|
|
|
pPaletteEntry - Pointer to PALETTEENTRY data structure array,
|
|
|
|
RedGamma - The monitor's red gamma value in UDECI4 format
|
|
|
|
GreenGamma - The monitor's green gamma value in UDECI4 format
|
|
|
|
BlueGamma - The monitor's blue gamma value in UDECI4 format
|
|
|
|
|
|
Return Value:
|
|
|
|
if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
|
|
VGA256 halftone process, if it is not NULL then it return the total
|
|
paletteEntry updated.
|
|
|
|
If the pPaletteEntry is not NULL then halftone.dll assume it has enough
|
|
space for the size returned when this pointer is NULL.
|
|
|
|
Author:
|
|
|
|
14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
FD6 RGBGamma[3];
|
|
FD6 IValue;
|
|
FD6 Yr;
|
|
FD6 Yg;
|
|
FD6 Yb;
|
|
UINT RIndex;
|
|
UINT GIndex;
|
|
UINT BIndex;
|
|
UINT TableSize;
|
|
|
|
DEFDBGVAR(UINT, PaletteIdx = 0)
|
|
|
|
|
|
DBGP_IF(DBGP_HTAPI,
|
|
DBGP("HT_Get8BPPFormatPalette(%p): Gamma=%05ld:%05ld:%05ld"
|
|
ARGPTR(pPaletteEntry)
|
|
ARGDW(RedGamma) ARGDW(GreenGamma) ARGDW(BlueGamma)));
|
|
|
|
//
|
|
// Initialize All internal data first
|
|
//
|
|
|
|
if (pPaletteEntry) {
|
|
|
|
RGBGamma[0] = UDECI4ToFD6(RedGamma);
|
|
RGBGamma[1] = UDECI4ToFD6(GreenGamma);
|
|
RGBGamma[2] = UDECI4ToFD6(BlueGamma);
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("***** HT_Get8BPPFormatPalette: %s:%s:%s *****"
|
|
ARGFD6(RGBGamma[0], 1, 4)
|
|
ARGFD6(RGBGamma[1], 1, 4)
|
|
ARGFD6(RGBGamma[2], 1, 4)));
|
|
|
|
//
|
|
// Our VGA256 format is BGR type of Primary order.
|
|
//
|
|
|
|
RIndex =
|
|
GIndex =
|
|
BIndex = 0;
|
|
|
|
TableSize = VGA256_CUBE_SIZE;
|
|
|
|
while (TableSize--) {
|
|
|
|
Yr = DivFD6(RIndex, VGA256_R_IDX_MAX);
|
|
Yg = DivFD6(GIndex, VGA256_G_IDX_MAX);
|
|
Yb = DivFD6(BIndex, VGA256_B_IDX_MAX);
|
|
pPaletteEntry->peRed = RGB_8BPP(Yr);
|
|
pPaletteEntry->peGreen = RGB_8BPP(Yg);
|
|
pPaletteEntry->peBlue = RGB_8BPP(Yb);
|
|
pPaletteEntry->peFlags = 0;
|
|
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("%3u - %3u:%3u:%3u"
|
|
ARGU(PaletteIdx++)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
|
|
++pPaletteEntry;
|
|
|
|
if ((++RIndex) > VGA256_R_IDX_MAX) {
|
|
|
|
RIndex = 0;
|
|
|
|
if ((++GIndex) > VGA256_G_IDX_MAX) {
|
|
|
|
GIndex = 0;
|
|
++BIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// 03-Feb-1999 Wed 00:49:08 updated -by- Daniel Chou (danielc)
|
|
//
|
|
// Since all these monochrome/gray scale is not stick in the system
|
|
// palette, The halftone codes with new supercell will not use these
|
|
// entries anymore, so do not return it.
|
|
//
|
|
#if 0
|
|
RIndex = 0;
|
|
|
|
while (RIndex <= VGA256_M_IDX_MAX) {
|
|
|
|
IValue = DivFD6(RIndex++, VGA256_M_IDX_MAX);
|
|
pPaletteEntry->peRed = RGB_8BPP(IValue);
|
|
pPaletteEntry->peGreen = RGB_8BPP(IValue);
|
|
pPaletteEntry->peBlue = RGB_8BPP(IValue);
|
|
pPaletteEntry->peFlags = 0;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("%3u - %3u:%3u:%3u [%s]"
|
|
ARGU(PaletteIdx++)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )
|
|
ARGFD6(IValue, 1, 6)));
|
|
|
|
++pPaletteEntry;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return((LONG)VGA256_CUBE_SIZE);
|
|
|
|
// return((LONG)VGA256_PALETTE_COUNT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_Get8BPPMaskPalette(
|
|
LPPALETTEENTRY pPaletteEntry,
|
|
BOOL Use8BPPMaskPal,
|
|
BYTE CMYMask,
|
|
UDECI4 RedGamma,
|
|
UDECI4 GreenGamma,
|
|
UDECI4 BlueGamma
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions retrieve a halftone's VGA256 color table definitions
|
|
|
|
Arguments:
|
|
|
|
pPaletteEntry - Pointer to PALETTEENTRY data structure array,
|
|
|
|
Use8BPPMaskPal - TRUE if using byte Mask palette, false to use NT4.0
|
|
standard MS 8bpp palette
|
|
|
|
CMYMask - Specified level mask in C3:M3:Y2
|
|
|
|
RedGamma - The monitor's red gamma value in UDECI4 format
|
|
|
|
GreenGamma - The monitor's green gamma value in UDECI4 format
|
|
|
|
BlueGamma - The monitor's blue gamma value in UDECI4 format
|
|
|
|
|
|
Return Value:
|
|
|
|
if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
|
|
VGA256 halftone process, if it is not NULL then it return the total
|
|
paletteEntry updated.
|
|
|
|
If the pPaletteEntry is not NULL then halftone.dll assume it has enough
|
|
space for the size returned when this pointer is NULL.
|
|
|
|
Author:
|
|
|
|
14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
03-Aug-2000 Thu 19:58:18 updated -by- Daniel Chou (danielc)
|
|
Overloading the pPaletteEntry to returned a inverted indices palette
|
|
based on Whistler bug# 22915. Because the Windows GDI ROP assume
|
|
index 0 always black, last index alwasy white without checking the
|
|
halftone palette and cause many rop got inverted result.
|
|
|
|
08-Sep-2000 Fri 14:24:28 updated -by- Daniel Chou (danielc)
|
|
For new CMY_INVERTED mode, we want to make sure we pack all
|
|
possible ink entries in the middle of 256 indices and pack
|
|
black/white at end. If the total ink color compositions are
|
|
an odd number then we duplicate the middle one. This will
|
|
|
|
//
|
|
// ***************************************************************************
|
|
// * SPECIAL NOTE for Windows NT version later than Windows 2000 Release *
|
|
// ***************************************************************************
|
|
// Current version of Window NT (Post Windows 2000) will Overloading the
|
|
// pPaletteEntry in HT_Get8BPPMaskPalette(DoUseCMYMask) API to returned a
|
|
// inverted indices palette based on additive palette entries composition.
|
|
// Because Windows GDI ROP assume index 0 always black and last index always
|
|
// white without checking the palette entries. (Indices based ROPs rather color
|
|
// based) This cause many ROPS got wrong result which has inverted output.
|
|
//
|
|
// To correct this GDI ROPs behavior, the POST windows 2000 version of GDI
|
|
// Halftone will supports a special CMY_INVERTED format. All new drivers should
|
|
// use this CMY_INVERTED method for future compabilities
|
|
//
|
|
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
// @ Following Steps are required for ALL POST Windows 2000 Drivers when @
|
|
// @ using Window GDI Halftone 8bpp CMY332 Mask mode @
|
|
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
//
|
|
// 1. Must set HT_FLAG_INVERT_8BPP_BITMASK_IDX flags
|
|
//
|
|
// 2. Must set pPaleteEntry[0] when calling HT_Get8BPPMaskPalette() with
|
|
//
|
|
// pPaletteEntry[0].peRed = 'R';
|
|
// pPaletteEntry[0].peGreen = 'G';
|
|
// pPaletteEntry[0].peBlue = 'B';
|
|
// pPaletteEntry[0].peFlags = '0';
|
|
//
|
|
// The caller can use following supplied macro to set this for future
|
|
// compabilities
|
|
//
|
|
// HT_SET_BITMASKPAL2RGB(pPaletteEntry)
|
|
//
|
|
// where pPaletteEntry is the pointer to the PALETTEENTRY that passed to
|
|
// the HT_GET8BPPMaskPalette() fucntion call
|
|
//
|
|
// 3. Must Check the return Palette from HT_Get8BPPMaskPalette() using
|
|
// following Macro
|
|
//
|
|
// HT_IS_BITMASKPALRGB(pPaletteEntry)
|
|
//
|
|
// where pPaletteEntry is the pointer to the PALETTEENTRY that passed to the
|
|
// HT_GET8BPPMaskPalette() fucntion call,
|
|
//
|
|
// If this macro return FALSE then the current version of GDI HALFTONE does
|
|
// NOT support the CMY_INVERTED 8bpp bitmaask mode and it only supports CMY
|
|
// mode.
|
|
//
|
|
// If this macro return TRUE then the GDI HALFTONE DOES support the
|
|
// CMY_INVERTED 8bpp bitmaask mode and the caller must using a translation
|
|
// table to obtain final halftone surface bitmap 8bpp indices ink levels.
|
|
//
|
|
// 4. Behavior changes for GDI halftone that supports 8bpp CMY_INVERTED bitmask
|
|
// mode, following is a list of changes of CMYMask mode passed to
|
|
// the HT_Get8BPPMaskPalette()
|
|
//
|
|
// CMYMask CMY Mode Indices CMY_INVERTED Mode Indices
|
|
// ======= ========================= =============================
|
|
// 0 0: WHITE 0: BLACK
|
|
// 1-254: Light->Dark Gray 1-254: Dark->Light Gray
|
|
// 255: BLACK 255: WHITE
|
|
// -------------------------------------------------------------------
|
|
// 1 0: WHITE 0-65: BLACK
|
|
// 1-123: 5^3 CMY color 66-188: 5^3 RGB color
|
|
// 124-255: BLACK 189-255: WHITE
|
|
// 127-128: Duplicate for XOR ROP
|
|
// (CMY Levels 2:2:2)
|
|
// -------------------------------------------------------------------
|
|
// 2 0: WHITE 0-20: BLACK
|
|
// 1-214: 6^3 CMY color 21-234: 6^3 RGB color
|
|
// 215-255: BLACK 235-255: WHITE
|
|
// -------------------------------------------------------------------
|
|
// 3-255* 0: WHITE 0: BLACK
|
|
// 1-254: CMY Color BitMask 1-254: Centered CxMxY BitMask*
|
|
// 255: BLACK 255: WHITE
|
|
// ===================================================================
|
|
//
|
|
// * For CMYMask mode 3-255, the valid combination must NOT have any
|
|
// of Cyan, Magenta or Yellow ink level equal to 0.
|
|
//
|
|
// * The reason for CMY_INVERTED mode that pading BLACK and WHITE entires
|
|
// at both end and have all other color in the middle is to make sure
|
|
// all 256 color palette entries are even distributed so that GDI ROPs
|
|
// (raster operation) will work more correctly. This is because GDI ROPs
|
|
// are based on the indices not color
|
|
//
|
|
// * The CMY_INVERTED Mode has all non-black, non white indices centered
|
|
// and even distributed within the total 256 palette indices. For
|
|
// example; if a CMY=333 levels then it has total 3x3x3=27 indices,
|
|
// these 27 indices will be centered by packing 114 black indices at
|
|
// begining and packing 114 white indices at end to ensure that ROP
|
|
// will be correct rendered.
|
|
//
|
|
// See following sample function of for how to generate these ink levels
|
|
// and Windows 2000 CMY332 Index translation table
|
|
//
|
|
//
|
|
// 5. For CMYMask index mode 0 to 255, the caller can use following sample
|
|
// function to genrate INKLEVELS translation table
|
|
//
|
|
// The follwing structure and tables are examples of how to translate 8bpp
|
|
// bitmask halftone bitmap indices to ink levels
|
|
//
|
|
// typedef struct _INKLEVELS {
|
|
// BYTE Cyan; // Cyan level from 0 to max
|
|
// BYTE Magenta; // Magenta level from 0 to max
|
|
// BYTE Yellow; // Yellow level from 0 to max
|
|
// BYTE CMY332Idx; // Original windows 2000 CMY332 Index
|
|
// } INKLEVELS, *PINKLEVELS;
|
|
//
|
|
// To Compute a 8bpp translate table of INKLEVELS, following sample
|
|
// function show how to genrate a INKLEVELS translate table for a valid
|
|
// CMYMask range from 0 to 255. It can be use to generate either Windows
|
|
// 2000 CMY Mode or new Post Windows 2000's CMY_INVERTED mode translation
|
|
// table. It also generate a windows 2000 CMY Mode CMY332Idx so caller
|
|
// can map CMY_INVERTED new indices to old index for current existing
|
|
// indices processing function.
|
|
//
|
|
// Example Function that generate translate table for CMYMask 0 to 255,
|
|
// the pInkLevels must pointed to a valid memory location of 256 INKLEVELS
|
|
// entries, if return value is TRUE then it can be used to trnaslate 8bpp
|
|
// indices to ink levels or mapp to the older CMY332 style indices.
|
|
//
|
|
//
|
|
// BOOL
|
|
// GenerateInkLevels(
|
|
// PINKLEVELS pInkLevels, // Pointer to 256 INKLEVELS table
|
|
// BYTE CMYMask, // CMYMask mode
|
|
// BOOL CMYInverted // TRUE for CMY_INVERTED mode
|
|
// )
|
|
// {
|
|
// PINKLEVELS pILDup;
|
|
// PINKLEVELS pILEnd;
|
|
// INKLEVELS InkLevels;
|
|
// INT Count;
|
|
// INT IdxInc;
|
|
// INT cC;
|
|
// INT cM;
|
|
// INT cY;
|
|
// INT xC;
|
|
// INT xM;
|
|
// INT xY;
|
|
// INT iC;
|
|
// INT iM;
|
|
// INT iY;
|
|
// INT mC;
|
|
// INT mM;
|
|
//
|
|
//
|
|
// switch (CMYMask) {
|
|
//
|
|
// case 0:
|
|
//
|
|
// cC =
|
|
// cM =
|
|
// xC =
|
|
// xM = 0;
|
|
// cY =
|
|
// xY = 255;
|
|
// break;
|
|
//
|
|
// case 1:
|
|
// case 2:
|
|
//
|
|
// cC =
|
|
// cM =
|
|
// cY =
|
|
// xC =
|
|
// xM =
|
|
// xY = 3 + (INT)CMYMask;
|
|
// break;
|
|
//
|
|
// default:
|
|
//
|
|
// cC = (INT)((CMYMask >> 5) & 0x07);
|
|
// cM = (INT)((CMYMask >> 2) & 0x07);
|
|
// cY = (INT)( CMYMask & 0x03);
|
|
// xC = 7;
|
|
// xM = 7;
|
|
// xY = 3;
|
|
// break;
|
|
// }
|
|
//
|
|
// Count = (cC + 1) * (cM + 1) * (cY + 1);
|
|
//
|
|
// if ((Count < 1) || (Count > 256)) {
|
|
//
|
|
// return(FALSE);
|
|
// }
|
|
//
|
|
// InkLevels.Cyan =
|
|
// InkLevels.Magenta =
|
|
// InkLevels.Yellow =
|
|
// InkLevels.CMY332Idx = 0;
|
|
// mC = (xM + 1) * (xY + 1);
|
|
// mM = xY + 1;
|
|
// pILDup = NULL;
|
|
//
|
|
// if (CMYInverted) {
|
|
//
|
|
// //
|
|
// // Move the pInkLevels to the first entry which center around
|
|
// // 256 table entries, if we skip any then all entries skipped
|
|
// // will be white (CMY levels all zeros). Because this is
|
|
// // CMY_INVERTED so entries start from back of the table and
|
|
// // moving backward to the begining of the table
|
|
// //
|
|
//
|
|
// pILEnd = pInkLevels - 1;
|
|
// IdxInc = ((256 - Count - (Count & 0x01)) / 2);
|
|
// pInkLevels += 255;
|
|
//
|
|
// while (IdxInc--) {
|
|
//
|
|
// *pInkLevels-- = InkLevels;
|
|
// }
|
|
//
|
|
// if (Count & 0x01) {
|
|
//
|
|
// //
|
|
// // If we have odd number of entries then we need to
|
|
// // duplicate the center one for correct XOR ROP to
|
|
// // operated correctly. The pILDup will always be index
|
|
// // 127, the duplication are indices 127, 128
|
|
// //
|
|
//
|
|
// pILDup = pInkLevels - (Count / 2) - 1;
|
|
// }
|
|
//
|
|
// //
|
|
// // We running from end of table to the begining, because
|
|
// // when in CMYInverted mode, the index 0 is black and index
|
|
// // 255 is white. Since we only generate 'Count' of index
|
|
// // and place them at center, we will change xC, xM, xY max.
|
|
// // index to same as cC, cM and cY.
|
|
// //
|
|
//
|
|
// IdxInc = -1;
|
|
// xC = cC;
|
|
// xM = cM;
|
|
// xY = cY;
|
|
//
|
|
// } else {
|
|
//
|
|
// IdxInc = 1;
|
|
// pILEnd = pInkLevels + 256;
|
|
// }
|
|
//
|
|
// //
|
|
// // At following, the composition of ink levels, index always
|
|
// // from 0 CMY Ink levels (WHITE) to maximum ink levels (BLACK),
|
|
// // the different with CMY_INVERTED mode is we compose it from
|
|
// // index 255 to index 0 rather than from index 0 to 255
|
|
// //
|
|
//
|
|
// if (CMYMask) {
|
|
//
|
|
// INT Idx332C;
|
|
// INT Idx332M;
|
|
//
|
|
// for (iC = 0, Idx332C = -mC; iC <= xC; iC++) {
|
|
//
|
|
// if (iC <= cC) {
|
|
//
|
|
// InkLevels.Cyan = (BYTE)iC;
|
|
// Idx332C += mC;
|
|
// }
|
|
//
|
|
// for (iM = 0, Idx332M = -mM; iM <= xM; iM++) {
|
|
//
|
|
// if (iM <= cM) {
|
|
//
|
|
// InkLevels.Magenta = (BYTE)iM;
|
|
// Idx332M += mM;
|
|
// }
|
|
//
|
|
// for (iY = 0; iY <= xY; iY++) {
|
|
//
|
|
// if (iY <= cY) {
|
|
//
|
|
// InkLevels.Yellow = (BYTE)iY;
|
|
// }
|
|
//
|
|
// InkLevels.CMY332Idx = (BYTE)(Idx332C + Idx332M) +
|
|
// InkLevels.Yellow;
|
|
// *pInkLevels = InkLevels;
|
|
//
|
|
// if ((pInkLevels += IdxInc) == pILDup) {
|
|
//
|
|
// *pInkLevels = InkLevels;
|
|
// pInkLevels += IdxInc;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// //
|
|
// // Now if we need to pack black at other end of the
|
|
// // translation table then do it here, Notice that InkLevels
|
|
// // are at cC, cM and cY here and the CMY332Idx is at BLACK
|
|
// //
|
|
//
|
|
// while (pInkLevels != pILEnd) {
|
|
//
|
|
// *pInkLevels = InkLevels;
|
|
// pInkLevels += IdxInc;
|
|
// }
|
|
//
|
|
// } else {
|
|
//
|
|
// //
|
|
// // Gray Scale case
|
|
// //
|
|
//
|
|
// for (iC = 0; iC < 256; iC++, pInkLevels += IdxInc) {
|
|
//
|
|
// pInkLevels->Cyan =
|
|
// pInkLevels->Magenta =
|
|
// pInkLevels->Yellow =
|
|
// pInkLevels->CMY332Idx = (BYTE)iC;
|
|
// }
|
|
// }
|
|
//
|
|
// return(TRUE);
|
|
// }
|
|
//
|
|
//
|
|
// 6. For CMYMask Mode 0 (Gray scale), the gray scale table just inverted
|
|
// between CMY and CMY_INVERTED mode.
|
|
//
|
|
// CMY mode: 0 to 255 gray scale from WHITE to BLACK increment,
|
|
// CMY_INVERTED Mode: 0 to 255 gray scale from BLACK to WHITE increment.
|
|
//
|
|
//
|
|
// 7. For CMYMask Mode 1 and 2, the caller should use a translation table for
|
|
// translate indices to CMY ink levels.
|
|
//
|
|
// 8. For CMYMode mode 3 to 255,
|
|
//
|
|
// if in CMY Mode (Windows 2000) is specified then The final CMY ink levels
|
|
// indices byte has following meanings
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// | | | | | |
|
|
// +---+ +---+ +=+
|
|
// | | |
|
|
// | | +-- Yellow 0-3 (Max. 4 levels)
|
|
// | |
|
|
// | +-- Magenta 0-7 (Max. 8 levels)
|
|
// |
|
|
// +-- Cyan 0-7 (Max. 8 levels)
|
|
//
|
|
//
|
|
// If a CMY_INVERTED mode is specified then caller must use a translation
|
|
// table to convert a index to the ink levels, to generate this table,
|
|
// please see above #5 description.
|
|
//
|
|
//
|
|
|
|
--*/
|
|
|
|
{
|
|
LPPALETTEENTRY pPalOrg;
|
|
FD6 RGBGamma[3];
|
|
FD6 Tmp;
|
|
FD6 Y;
|
|
INT PalInc;
|
|
UINT PalStart;
|
|
UINT PalIdx;
|
|
UINT cC;
|
|
UINT cM;
|
|
UINT cY;
|
|
UINT iC;
|
|
UINT iM;
|
|
UINT iY;
|
|
UINT MaxPal;
|
|
UINT IdxPalDup;
|
|
BYTE bR;
|
|
BYTE bG;
|
|
BYTE bB;
|
|
|
|
|
|
DBGP_IF(DBGP_HTAPI,
|
|
DBGP("HT_Get8BPPMaskPalette(%p): UseMask=%ld, CMYMask=%02lx, Gamma=%05ld:%05ld:%05ld"
|
|
ARGPTR(pPaletteEntry)
|
|
ARGDW((Use8BPPMaskPal) ? 1 : 0)
|
|
ARGDW(CMYMask)
|
|
ARGDW(RedGamma) ARGDW(GreenGamma) ARGDW(BlueGamma)));
|
|
|
|
if (!Use8BPPMaskPal) {
|
|
|
|
return(HT_Get8BPPFormatPalette(pPaletteEntry,
|
|
RedGamma,
|
|
GreenGamma,
|
|
BlueGamma));
|
|
}
|
|
|
|
//
|
|
// Checking the CMYMask first to make sure caller passed valid CMYMask
|
|
//
|
|
|
|
switch (CMYMask) {
|
|
|
|
case 1:
|
|
|
|
cC =
|
|
cM =
|
|
cY = 4;
|
|
MaxPal = 125;
|
|
break;
|
|
|
|
case 2:
|
|
|
|
cC =
|
|
cM =
|
|
cY = 5;
|
|
MaxPal = 216;
|
|
break;
|
|
|
|
default:
|
|
|
|
MaxPal = 0;
|
|
cC = (UINT)((CMYMask >> 5) & 0x07);
|
|
cM = (UINT)((CMYMask >> 2) & 0x07);
|
|
cY = (UINT)((CMYMask >> 0) & 0x03);
|
|
|
|
//
|
|
// If this is not zero, but one of the cC, cM, cY is zero then return
|
|
// zero to indicate error
|
|
//
|
|
|
|
if ((CMYMask != 0) && ((!cC) || (!cM) || (!cY))) {
|
|
|
|
ASSERTMSG("One of Ink Levels is ZERO", (cC) && (cM) && (cY));
|
|
|
|
return(0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize All internal data first
|
|
//
|
|
|
|
if (pPalOrg = pPaletteEntry) {
|
|
|
|
PalStart = 0;
|
|
PalInc = 1;
|
|
IdxPalDup = 0x200;
|
|
|
|
//
|
|
// Since we will always compose the palette using CMY method, the only
|
|
// thing we need to do for the RGB mode is write the palette from index
|
|
// 255 to 0, the backward writing provied that caller can just invert
|
|
// its 8bpp indices to get the CMY ink levels definition
|
|
//
|
|
|
|
if (*((LPDWORD)pPaletteEntry) == HTBITMASKPALRGB_DW) {
|
|
|
|
//
|
|
// RGB Mode, go to end of the palette end move backward, the reason
|
|
// for the 5:5:5 and 6:6:6 that pas white and black at both end is
|
|
// to make sure the ROP work more correctly for the GDI.
|
|
//
|
|
|
|
pPaletteEntry += 255;
|
|
PalInc = -1;
|
|
|
|
//
|
|
// 08-Sep-2000 Fri 14:22:02 updated -by- Daniel Chou (danielc)
|
|
// For new CMY_INVERTED mode, we want to make sure we pack all
|
|
// possible ink entries in the middle of 256 indices and pack
|
|
// black/white at end. If the total ink color compositions are
|
|
// an odd number then we duplicate the middle one. This will
|
|
// ensure that the ROP will work correctly on color entries
|
|
//
|
|
|
|
if (CMYMask) {
|
|
|
|
MaxPal = (cC + 1) * (cM + 1) * (cY + 1);
|
|
PalStart = (256 - MaxPal) >> 1;
|
|
|
|
if (MaxPal & 0x01) {
|
|
|
|
IdxPalDup = (MaxPal >> 1) + PalStart;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clear all palette entries to zero first
|
|
//
|
|
|
|
ZeroMemory(pPalOrg, sizeof(PALETTEENTRY) * 256);
|
|
|
|
RGBGamma[0] = UDECI4ToFD6(RedGamma);
|
|
RGBGamma[1] = UDECI4ToFD6(GreenGamma);
|
|
RGBGamma[2] = UDECI4ToFD6(BlueGamma);
|
|
PalIdx = 0;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("***** HT_Get8BPPMaskPalette: %s:%s:%s, CMY=%u:%u:%u=%3ld (%s, %ld,%ld) *****"
|
|
ARGFD6(RGBGamma[0], 1, 4)
|
|
ARGFD6(RGBGamma[1], 1, 4)
|
|
ARGFD6(RGBGamma[2], 1, 4)
|
|
ARGDW(cC) ARGDW(cM) ARGDW(cY) ARGDW(MaxPal)
|
|
ARGPTR((PalInc==-1) ? "RGB" : "CMY")
|
|
ARGDW(PalStart) ARGDW(IdxPalDup)));
|
|
|
|
if (MaxPal) {
|
|
|
|
//
|
|
// For the begining filler, we will fill with WHITE, because
|
|
// we are composing use CMY, when CMY is 0 it means white
|
|
//
|
|
|
|
for (;
|
|
PalIdx < PalStart;
|
|
PalIdx++, pPaletteEntry += PalInc) {
|
|
|
|
pPaletteEntry->peRed =
|
|
pPaletteEntry->peGreen =
|
|
pPaletteEntry->peBlue = 0xFF;
|
|
}
|
|
|
|
for (iC = 0; iC <= cC; iC++) {
|
|
|
|
CMY_8BPP(bR, iC, cC, Tmp);
|
|
|
|
for (iM = 0; iM <= cM; iM++) {
|
|
|
|
CMY_8BPP(bG, iM, cM, Tmp)
|
|
|
|
for (iY = 0;
|
|
iY <= cY;
|
|
iY++, PalIdx++, pPaletteEntry += PalInc) {
|
|
|
|
CMY_8BPP(bB, iY, cY, Tmp);
|
|
|
|
pPaletteEntry->peRed = bR;
|
|
pPaletteEntry->peGreen = bG;
|
|
pPaletteEntry->peBlue = bB;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("[%3ld] %3u - %3u:%3u:%3u"
|
|
ARGU(pPaletteEntry - pPalOrg)
|
|
ARGU(PalIdx)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
|
|
if (PalIdx == IdxPalDup) {
|
|
|
|
++PalIdx;
|
|
pPaletteEntry += PalInc;
|
|
pPaletteEntry->peRed = bR;
|
|
pPaletteEntry->peGreen = bG;
|
|
pPaletteEntry->peBlue = bB;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("[%3ld] %3u - %3u:%3u:%3u --- DUP"
|
|
ARGU(pPaletteEntry - pPalOrg)
|
|
ARGU(PalIdx)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// For ending fillers (Current PalIdx to 255), we will fill with
|
|
// BLACK, because we are composing use CMY, when CMY is at MAX it
|
|
// means BLACK, Since we clear all pPalOrg to ZERO at begining of
|
|
// this function, so we are done and do not need to do anything.
|
|
//
|
|
|
|
} else if ((cC < 1) || (cM < 1) || (cY < 1)) {
|
|
|
|
for (Y = 255;
|
|
PalIdx <= 255;
|
|
PalIdx++, Y--, pPaletteEntry += PalInc) {
|
|
|
|
pPaletteEntry->peRed =
|
|
pPaletteEntry->peGreen =
|
|
pPaletteEntry->peBlue = (BYTE)Y;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("[%3ld] %3u - %3u:%3u:%3u"
|
|
ARGU(pPaletteEntry - pPalOrg)
|
|
ARGU(PalIdx)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
}
|
|
|
|
} else {
|
|
|
|
for (iC = 0; iC <= 7; iC++) {
|
|
|
|
CMY_8BPP(bR, iC, cC, Tmp);
|
|
|
|
for (iM = 0; iM <= 7; iM++) {
|
|
|
|
CMY_8BPP(bG, iM, cM, Tmp)
|
|
|
|
for (iY = 0;
|
|
iY <= 3;
|
|
iY++, PalIdx++, pPaletteEntry += PalInc) {
|
|
|
|
CMY_8BPP(bB, iY, cY, Tmp);
|
|
|
|
pPaletteEntry->peRed = bR;
|
|
pPaletteEntry->peGreen = bG;
|
|
pPaletteEntry->peBlue = bB;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("[%3ld] %3u - %3u:%3u:%3u"
|
|
ARGU(pPaletteEntry - pPalOrg)
|
|
ARGU(PalIdx)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Always return full 256 palette entry for halftone
|
|
//
|
|
|
|
return((LONG)256);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_CreateStandardMonoPattern(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
|
|
PSTDMONOPATTERN pStdMonoPattern
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function create standard predefined monochrome pattern for the device.
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
|
|
which returned from the HT_CreateDeviceHalftoneInfo.
|
|
|
|
pStdMonoPattern - Pointer to the STDMONOPATTERN data structure, the
|
|
pPattern in this data structure is optional.
|
|
|
|
Return Value:
|
|
|
|
if the return value is negative or zero then an error was encountered,
|
|
possible error codes are
|
|
|
|
HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is
|
|
passed.
|
|
|
|
HTERR_INVALID_STDMONOPAT_INDEX - The PatternIndex field in
|
|
STDMONOPATTERN data structure is
|
|
invalid.
|
|
otherwise
|
|
|
|
If pPattern field in STDMONOPATTERN data structure Surface is NULL, it
|
|
return the bytes count which need to stored the pattern, otherwise it
|
|
return the size in byte copied to the pattern buffer.
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 14:28:23 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
05-Jun-1991 Wed 10:22:41 updated -by- Daniel Chou (danielc)
|
|
|
|
Fixed the bugs when the pStdMonoPattern is NULL, it was used without
|
|
checking it.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEVICECOLORINFO pDCI;
|
|
CHBINFO CHBInfo;
|
|
CTSTD_UNION CTSTDUnion;
|
|
LONG Result;
|
|
WORD PatCX;
|
|
WORD PatCY;
|
|
BYTE PatIndex;
|
|
|
|
|
|
if ((PatIndex = pStdMonoPattern->PatternIndex) > HT_SMP_MAX_INDEX) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CREATE_SMP, HTERR_INVALID_STDMONOPAT_INDEX);
|
|
}
|
|
|
|
CTSTDUnion.b.cbPrim =
|
|
CTSTDUnion.b.SrcOrder =
|
|
CTSTDUnion.b.BMFDest =
|
|
CTSTDUnion.b.DestOrder = 0;
|
|
|
|
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
0,
|
|
CTSTDUnion.b,
|
|
&Result))) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_CREATE_SMP, Result);
|
|
}
|
|
|
|
if (PatIndex >= HT_SMP_PERCENT_SCREEN_START) {
|
|
|
|
CHBInfo.DestScanLineAlignBytes = pStdMonoPattern->ScanLineAlignBytes;
|
|
PatCX = pStdMonoPattern->cxPels = pDCI->HTCell.cxReal;
|
|
PatCY = pStdMonoPattern->cyPels = pDCI->HTCell.Height;
|
|
|
|
pStdMonoPattern->BytesPerScanLine = (WORD)
|
|
ComputeBytesPerScanLine((UINT)BMF_1BPP,
|
|
(UINT)CHBInfo.DestScanLineAlignBytes,
|
|
(DWORD)PatCX);
|
|
CHBInfo.Flags = CHBF_BW_ONLY;
|
|
|
|
if (pStdMonoPattern->pPattern) {
|
|
|
|
BYTE rgb[3];
|
|
COLORTRIAD ColorTriad;
|
|
|
|
rgb[0] =
|
|
rgb[1] =
|
|
rgb[0] = (BYTE)(HT_SMP_MAX_INDEX - PatIndex);
|
|
|
|
ColorTriad.Type = (BYTE)COLOR_TYPE_RGB;
|
|
ColorTriad.BytesPerPrimary = (BYTE)sizeof(BYTE);
|
|
ColorTriad.BytesPerEntry = (BYTE)(sizeof(BYTE) * 3);
|
|
ColorTriad.PrimaryOrder = PRIMARY_ORDER_RGB;
|
|
ColorTriad.PrimaryValueMax = (FD6)100;
|
|
ColorTriad.ColorTableEntries = 1;
|
|
ColorTriad.pColorTable = (LPVOID)rgb;
|
|
|
|
if (pStdMonoPattern->Flags & SMP_0_IS_BLACK) {
|
|
|
|
CHBInfo.Flags |= CHBF_USE_ADDITIVE_PRIMS;
|
|
}
|
|
|
|
if (!(pStdMonoPattern->Flags & SMP_TOPDOWN)) {
|
|
|
|
CHBInfo.Flags |= CHBF_BOTTOMUP_BRUSH;
|
|
}
|
|
|
|
CHBInfo.DestSurfaceFormat = BMF_1BPP;
|
|
CHBInfo.DestPrimaryOrder = PRIMARY_ORDER_123;
|
|
|
|
Result = HT_CreateHalftoneBrush(pDeviceHalftoneInfo,
|
|
NULL,
|
|
&ColorTriad,
|
|
CHBInfo,
|
|
(LPVOID)pStdMonoPattern->pPattern);
|
|
|
|
} else {
|
|
|
|
Result = (LONG)pStdMonoPattern->BytesPerScanLine *
|
|
(LONG)PatCY;
|
|
}
|
|
|
|
} else {
|
|
|
|
Result = GetCachedSMP(pDCI, pStdMonoPattern);
|
|
}
|
|
|
|
RELEASE_HTMUTEX(pDCI->HTMutex);
|
|
|
|
DBGP_IF(DBGP_SHOWPAT,
|
|
|
|
LPBYTE pCurPat;
|
|
LPBYTE pPatScan;
|
|
BYTE Buf1[80];
|
|
BYTE Buf2[80];
|
|
BYTE Buf3[80];
|
|
BYTE Digit1;
|
|
BYTE Digit2;
|
|
WORD Index;
|
|
WORD XInc;
|
|
WORD YInc;
|
|
BYTE Mask;
|
|
BOOL Swap;
|
|
|
|
|
|
DBGP_IF(DBGP_HTAPI,
|
|
DBGP("HT_CreateStandardMonoPattern(%d) = %ld"
|
|
ARGI(PatIndex - HT_SMP_PERCENT_SCREEN_START)
|
|
ARGDW(Result)));
|
|
|
|
if ((Result > 0) && (pPatScan = pStdMonoPattern->pPattern)) {
|
|
|
|
Swap = (BOOL)(pStdMonoPattern->Flags & SMP_0_IS_BLACK);
|
|
|
|
FillMemory(Buf1, 80, ' ');
|
|
FillMemory(Buf2, 80, ' ');
|
|
Digit1 = 0;
|
|
Digit2 = 0;
|
|
Index = 4;
|
|
XInc = pStdMonoPattern->cxPels;
|
|
|
|
while ((XInc--) && (Index < 79)) {
|
|
|
|
if (!Digit2) {
|
|
|
|
Buf1[Index] = (BYTE)(Digit1 + '0');
|
|
|
|
if (++Digit1 == 10) {
|
|
|
|
Digit1 = 0;
|
|
}
|
|
}
|
|
|
|
Buf2[Index] = (BYTE)(Digit2 + '0');
|
|
|
|
if (++Digit2 == 10) {
|
|
|
|
Digit2 = 0;
|
|
}
|
|
|
|
++Index;
|
|
}
|
|
|
|
Buf1[Index] = Buf2[Index] = 0;
|
|
|
|
DBGP("%s" ARG(Buf1));
|
|
DBGP("%s\r\n" ARG(Buf2));
|
|
|
|
for (YInc = 0; YInc < pStdMonoPattern->cyPels; YInc++) {
|
|
|
|
Index = (WORD)sprintf(Buf3, "%3u ", YInc);
|
|
|
|
pCurPat = pPatScan;
|
|
|
|
for (XInc = 0, Mask = 0x80;
|
|
XInc < pStdMonoPattern->cxPels;
|
|
XInc++) {
|
|
|
|
if (Swap) {
|
|
|
|
Buf3[Index] = (BYTE)((*pCurPat & Mask) ? '°' : 'Û');
|
|
|
|
} else {
|
|
|
|
Buf3[Index] = (BYTE)((*pCurPat & Mask) ? 'Û' : '°');
|
|
}
|
|
|
|
if (!(Mask >>= 1)) {
|
|
|
|
Mask = 0x80;
|
|
++pCurPat;
|
|
}
|
|
|
|
if (++Index > 75) {
|
|
|
|
Index = 75;
|
|
}
|
|
}
|
|
|
|
sprintf(&Buf3[Index], " %-3u", YInc);
|
|
DBGP("%s" ARG(Buf3));
|
|
|
|
pPatScan += pStdMonoPattern->BytesPerScanLine;
|
|
}
|
|
|
|
DBGP("\r\n%s" ARG(Buf2));
|
|
DBGP("%s" ARG(Buf1));
|
|
}
|
|
)
|
|
|
|
HTAPI_RET(HTAPI_IDX_CREATE_SMP, Result);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
HTENTRY
|
|
CheckABInfo(
|
|
PBITBLTPARAMS pBBP,
|
|
UINT SrcSurfFormat,
|
|
UINT DstSurfFormat,
|
|
LPWORD pForceFlags,
|
|
PLONG pcOutMax
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
Author:
|
|
|
|
04-Mar-1999 Thu 18:41:06 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PABINFO pABInfo;
|
|
LONG cOutMax;
|
|
WORD ForceFlags;
|
|
|
|
|
|
if (!(pABInfo = pBBP->pABInfo)) {
|
|
|
|
return(HTERR_INVALID_ABINFO);
|
|
}
|
|
|
|
switch (DstSurfFormat) {
|
|
|
|
case BMF_1BPP:
|
|
|
|
cOutMax = 2;
|
|
break;
|
|
|
|
case BMF_4BPP:
|
|
case BMF_4BPP_VGA16:
|
|
|
|
cOutMax = 16;
|
|
break;
|
|
|
|
case BMF_8BPP:
|
|
case BMF_8BPP_VGA256:
|
|
|
|
cOutMax = 256;
|
|
break;
|
|
|
|
default:
|
|
|
|
cOutMax = 0;
|
|
break;
|
|
}
|
|
|
|
if (cOutMax) {
|
|
|
|
if ((pABInfo->pDstPal == NULL) ||
|
|
(pABInfo->cDstPal > cOutMax)) {
|
|
|
|
return(HTERR_INVALID_ABINFO);
|
|
}
|
|
}
|
|
|
|
*pForceFlags |= ADJ_FORCE_ALPHA_BLEND;
|
|
|
|
|
|
if (pABInfo->Flags & ABIF_USE_CONST_ALPHA_VALUE) {
|
|
|
|
switch (pABInfo->ConstAlphaValue) {
|
|
|
|
case 0:
|
|
|
|
//
|
|
// We do not need to do anything
|
|
//
|
|
|
|
return(0);
|
|
|
|
case 0xFF:
|
|
|
|
*pForceFlags &= ~ADJ_FORCE_ALPHA_BLEND;
|
|
cOutMax = 0;
|
|
break;
|
|
|
|
default:
|
|
|
|
*pForceFlags |= ADJ_FORCE_CONST_ALPHA;
|
|
break;
|
|
}
|
|
|
|
} else if (SrcSurfFormat != BMF_32BPP) {
|
|
|
|
return(HTERR_INVALID_SRC_FORMAT);
|
|
|
|
} else {
|
|
|
|
if (pABInfo->Flags & ABIF_SRC_ALPHA_IS_PREMUL) {
|
|
|
|
*pForceFlags |= ADJ_FORCE_AB_PREMUL_SRC;
|
|
}
|
|
|
|
if (pABInfo->Flags & ABIF_BLEND_DEST_ALPHA) {
|
|
|
|
if (DstSurfFormat != BMF_32BPP) {
|
|
|
|
return(HTERR_INVALID_DEST_FORMAT);
|
|
}
|
|
|
|
*pForceFlags |= ADJ_FORCE_AB_DEST;
|
|
}
|
|
}
|
|
|
|
*pcOutMax = cOutMax;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_HalftoneBitmap(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
|
|
PHTCOLORADJUSTMENT pHTColorAdjustment,
|
|
PHTSURFACEINFO pSourceHTSurfaceInfo,
|
|
PHTSURFACEINFO pSourceMaskHTSurfaceInfo,
|
|
PHTSURFACEINFO pDestinationHTSurfaceInfo,
|
|
PBITBLTPARAMS pBitbltParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function halftone the source bitmap and output to the destination
|
|
surface depends on the surface type and bitblt parameters
|
|
|
|
The source surface type must one of the following:
|
|
|
|
1-bit per pel. (BMF_1BPP)
|
|
4-bit per pel. (BMF_4BPP)
|
|
8-bit per pel. (BMF_8BPP)
|
|
16-bit per pel. (BMF_16BPP)
|
|
24-bit per pel. (BMF_24BPP)
|
|
32-bit per pel. (BMF_32BPP)
|
|
|
|
The destination surface type must one of the following:
|
|
|
|
1-bit per pel. (BMF_1BPP)
|
|
4-bit per pel. (BMF_4BPP)
|
|
3 plane and 1 bit per pel. (BMF_1BPP_3PLANES)
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - pointer to the DEVICEHALFTONEINFO data
|
|
structure
|
|
|
|
pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data
|
|
structure to specified the input/output color
|
|
adjustment/transform, if this pointer is NULL
|
|
then a default color adjustments is applied.
|
|
|
|
pSourceHTSurfaceInfo - pointer to the source surface infomation.
|
|
|
|
pSourceMaskHTSurfaceInfo - pointer to the source mask surface infomation,
|
|
if this pointer is NULL then there is no
|
|
source mask for the halftoning.
|
|
|
|
pDestinationHTSurfaceInfo - pointer to the destination surface infomation.
|
|
|
|
pBitbltParams - pointer to the BITBLTPARAMS data structure to
|
|
specified the source, destination, source
|
|
mask and clipping rectangle information, the
|
|
content of this data structure will not be
|
|
modified by this function.
|
|
|
|
|
|
Return Value:
|
|
|
|
if the return value is less than zero then an error has occurred,
|
|
the error code is one of the following #define which start with HTERR_.
|
|
|
|
HTERR_INSUFFICIENT_MEMORY - not enough memory to do the halftone
|
|
process.
|
|
|
|
HTERR_COLORTABLE_TOO_BIG - can not create the color table to map
|
|
the colors to the dyes' densities.
|
|
|
|
HTERR_QUERY_SRC_BITMAP_FAILED - callback function return FALSE when
|
|
query the source bitmap pointer.
|
|
|
|
HTERR_QUERY_DEST_BITMAP_FAILED - callback function return FALSE when
|
|
query the destination bitmap pointers.
|
|
|
|
HTERR_INVALID_SRC_FORMAT - Invalid source surface format.
|
|
|
|
HTERR_INVALID_DEST_FORMAT - Invalid destination surface type,
|
|
this function only recongnized 1/4/
|
|
bits per pel source surfaces or 1 bit
|
|
per pel 3 planes.
|
|
|
|
HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is passed.
|
|
|
|
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_MAX_QUERYLINES - One or more of Source/Destination
|
|
SourceMasks' maximum query scan line
|
|
is < 0
|
|
|
|
HTERR_INTERNAL_ERRORS_START - any other negative numbers indicate
|
|
a halftone internal failue.
|
|
|
|
else - the total destination scan lines
|
|
halftoned.
|
|
|
|
|
|
Author:
|
|
|
|
05-Feb-1991 Tue 15:23:07 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICECOLORINFO pDCI;
|
|
PHALFTONERENDER pHR;
|
|
PAAHEADER pAAHdr;
|
|
PDEVCLRADJ pDevClrAdj;
|
|
PRGB4B pClrTable;
|
|
PABINFO pABInfo;
|
|
LONG Result;
|
|
WORD ForceFlags;
|
|
WORD BBPFlags;
|
|
CTSTD_UNION CTSTDUnion;
|
|
LONG cInPal;
|
|
LONG cInMax;
|
|
LONG cOutMax;
|
|
BYTE SrcSurfFormat;
|
|
BYTE DstSurfFormat;
|
|
CONST static BYTE MaxPal_0148_LS[4] = { 0, 1, 4, 8 };
|
|
|
|
|
|
DBG_TIMER_RESET;
|
|
|
|
SrcSurfFormat = pSourceHTSurfaceInfo->SurfaceFormat;
|
|
DstSurfFormat = pDestinationHTSurfaceInfo->SurfaceFormat;
|
|
BBPFlags = pBitbltParams->Flags;
|
|
ForceFlags = 0;
|
|
|
|
cInPal =
|
|
cInMax =
|
|
cOutMax = 0;
|
|
|
|
switch (SrcSurfFormat) {
|
|
|
|
case BMF_1BPP:
|
|
case BMF_4BPP:
|
|
case BMF_8BPP:
|
|
|
|
cInMax = (UINT)0x01 << MaxPal_0148_LS[SrcSurfFormat];
|
|
|
|
if (pSourceHTSurfaceInfo->pColorTriad) {
|
|
|
|
cInPal = (LONG)pSourceHTSurfaceInfo->pColorTriad->ColorTableEntries;
|
|
}
|
|
|
|
if (!cInPal) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INVALID_COLOR_TABLE);
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
if ((BBPFlags & BBPF_DO_ALPHA_BLEND) &&
|
|
((Result = CheckABInfo(pBitbltParams,
|
|
SrcSurfFormat,
|
|
DstSurfFormat,
|
|
&ForceFlags,
|
|
&cOutMax)) <= 0)) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
|
|
}
|
|
|
|
DBGP_IF(DBGP_SRCBMP,
|
|
DBGP("SrcFmt=%ld, cInPal=%ld (%ld), DstFmt=%ld, cOutMax=%ld"
|
|
ARGDW(SrcSurfFormat) ARGDW(cInMax) ARGDW(cInPal)
|
|
ARGDW(DstSurfFormat) ARGDW(cOutMax)));
|
|
|
|
CTSTDUnion.b.cbPrim = 0;
|
|
CTSTDUnion.b.SrcOrder = PRIMARY_ORDER_BGR;
|
|
CTSTDUnion.b.BMFDest = (BYTE)DstSurfFormat;
|
|
CTSTDUnion.b.DestOrder = (BYTE)pBitbltParams->DestPrimaryOrder;
|
|
|
|
if (BBPFlags & BBPF_USE_ADDITIVE_PRIMS) {
|
|
|
|
ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
|
|
}
|
|
|
|
if (BBPFlags & BBPF_NEGATIVE_DEST) {
|
|
|
|
ForceFlags |= ADJ_FORCE_NEGATIVE;
|
|
}
|
|
|
|
if ((BBPFlags & BBPF_BW_ONLY) ||
|
|
(CTSTDUnion.b.BMFDest == BMF_1BPP)) {
|
|
|
|
ForceFlags |= ADJ_FORCE_MONO;
|
|
}
|
|
|
|
if (BBPFlags & BBPF_ICM_ON) {
|
|
|
|
ForceFlags |= ADJ_FORCE_ICM;
|
|
}
|
|
|
|
//
|
|
// Find out if we will call anti-aliasing codes
|
|
//
|
|
|
|
ASSERTMSG("Source X is not well ordered",
|
|
pBitbltParams->rclSrc.right >= pBitbltParams->rclSrc.left);
|
|
ASSERTMSG("Source Y is not well ordered",
|
|
pBitbltParams->rclSrc.bottom >= pBitbltParams->rclSrc.top);
|
|
|
|
if (BBPFlags & BBPF_NO_ANTIALIASING) {
|
|
|
|
ForceFlags |= ADJ_FORCE_NO_EXP_AA;
|
|
}
|
|
|
|
//
|
|
// Now Compute the Device Color Adjusment data
|
|
//
|
|
|
|
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
|
|
pHTColorAdjustment,
|
|
&pDevClrAdj,
|
|
sizeof(HALFTONERENDER) + sizeof(AAHEADER) +
|
|
((cInMax + cOutMax) * sizeof(RGB4B)),
|
|
ForceFlags,
|
|
CTSTDUnion.b,
|
|
&Result))) {
|
|
|
|
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
|
|
}
|
|
|
|
pHR = (PHALFTONERENDER)(pDevClrAdj + 1);
|
|
|
|
//
|
|
// We will mask out the more flags, since this flag is currently used
|
|
// internally.
|
|
//
|
|
|
|
pHR->pDeviceColorInfo = pDCI;
|
|
pHR->pDevClrAdj = pDevClrAdj;
|
|
pHR->pBitbltParams = pBitbltParams;
|
|
pHR->pSrcSI = pSourceHTSurfaceInfo;
|
|
pHR->pSrcMaskSI = pSourceMaskHTSurfaceInfo;
|
|
pHR->pDestSI = pDestinationHTSurfaceInfo;
|
|
pAAHdr = (PAAHEADER)(pHR->pAAHdr = (LPVOID)(pHR + 1));
|
|
pClrTable = (PRGB4B)(pAAHdr + 1);
|
|
|
|
if (cInMax) {
|
|
|
|
pAAHdr->SrcSurfInfo.cClrTable = (WORD)cInPal;
|
|
pAAHdr->SrcSurfInfo.pClrTable = (PRGB4B)pClrTable;
|
|
pClrTable += cInMax;
|
|
}
|
|
|
|
if (ForceFlags & ADJ_FORCE_ALPHA_BLEND) {
|
|
|
|
if ((!(pDCI->pAlphaBlendBGR)) &&
|
|
(!(pDCI->pAlphaBlendBGR = (LPBYTE)HTAllocMem(pDCI,
|
|
HTMEM_AlphaBlendBGR,
|
|
LPTR,
|
|
AB_DCI_SIZE)))) {
|
|
|
|
RELEASE_HTMUTEX(pDCI->HTMutex);
|
|
|
|
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
if (ForceFlags & ADJ_FORCE_CONST_ALPHA) {
|
|
|
|
pDCI->PrevConstAlpha = pDCI->CurConstAlpha;
|
|
pDCI->CurConstAlpha = pBitbltParams->pABInfo->ConstAlphaValue;
|
|
}
|
|
|
|
if (cOutMax) {
|
|
|
|
pAAHdr->DstSurfInfo.pClrTable = (PRGB4B)pClrTable;
|
|
pAAHdr->DstSurfInfo.cClrTable =
|
|
(WORD)pBitbltParams->pABInfo->cDstPal;
|
|
}
|
|
}
|
|
|
|
pAAHdr->SrcSurfInfo.AABFData.Format = (BYTE)SrcSurfFormat;
|
|
pAAHdr->DstSurfInfo.AABFData.Format = (BYTE)DstSurfFormat;
|
|
|
|
if (BBPFlags & BBPF_TILE_SRC) {
|
|
|
|
//
|
|
// Remove SrcMask if TILE_SRC is used
|
|
//
|
|
|
|
pHR->pSrcMaskSI = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// The semaphore pDCI->HTMutex will be released by AAHalftoneBitmap
|
|
//-----------------------------------------------------------------------
|
|
|
|
Result = AAHalftoneBitmap(pHR);
|
|
|
|
if (HTFreeMem(pDevClrAdj)) {
|
|
|
|
ASSERTMSG("HTFreeMem(pDevClrAdj) Failed", FALSE);
|
|
}
|
|
|
|
DBGP_IF(DBGP_HTAPI,
|
|
DBGP("HT_HalftoneBitmap(%ld/%6ld): Src[%ld]=(%4ld,%4ld)-(%4ld,%4ld), Dst[%ld]=(%4ld,%4ld)-(%4ld,%4ld) [0x%04lx]"
|
|
ARGDW(pDCI->cbMemTot) ARGDW(pDCI->cbMemMax)
|
|
ARGDW(SrcSurfFormat)
|
|
ARGDW(pBitbltParams->rclSrc.left)
|
|
ARGDW(pBitbltParams->rclSrc.top)
|
|
ARGDW(pBitbltParams->rclSrc.right)
|
|
ARGDW(pBitbltParams->rclSrc.bottom)
|
|
ARGDW(DstSurfFormat)
|
|
ARGDW(pBitbltParams->rclDest.left)
|
|
ARGDW(pBitbltParams->rclDest.top)
|
|
ARGDW(pBitbltParams->rclDest.right)
|
|
ARGDW(pBitbltParams->rclDest.bottom)
|
|
ARGDW(BBPFlags)));
|
|
|
|
DBGP_IF(DBGP_MEMLINK,
|
|
|
|
DumpMemLink(NULL, 0);
|
|
DumpMemLink((LPVOID)pDCI, 0);
|
|
)
|
|
|
|
DBGP_IF(DBGP_TIMER,
|
|
|
|
UINT i;
|
|
|
|
DBG_TIMER_END(TIMER_TOT);
|
|
|
|
DbgTimer[TIMER_LAST].Tot = DbgTimer[TIMER_TOT].Tot;
|
|
|
|
for (i = 1; i < TIMER_LAST; i++) {
|
|
|
|
DbgTimer[TIMER_LAST].Tot -= DbgTimer[i].Tot;
|
|
}
|
|
|
|
DBGP("HTBlt(%s): Setup=%s, AA=%s, In=%s, Out=%s, Mask=%s, Fmt=%ld->%ld [%02lx]"
|
|
ARGTIME(TIMER_TOT)
|
|
ARGTIME(TIMER_SETUP)
|
|
ARGTIME(TIMER_LAST)
|
|
ARGTIME(TIMER_INPUT)
|
|
ARGTIME(TIMER_OUTPUT)
|
|
ARGTIME(TIMER_MASK)
|
|
ARGDW(pSourceHTSurfaceInfo->SurfaceFormat)
|
|
ARGDW(pDevClrAdj->DMI.CTSTDInfo.BMFDest)
|
|
ARGDW(pDevClrAdj->DMI.Flags));
|
|
)
|
|
|
|
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_GammaCorrectPalette(
|
|
LPPALETTEENTRY pPaletteEntry,
|
|
LONG cPalette,
|
|
UDECI4 RedGamma,
|
|
UDECI4 GreenGamma,
|
|
UDECI4 BlueGamma
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions retrieve a halftone's VGA256 color table definitions
|
|
|
|
Arguments:
|
|
|
|
pPaletteEntry - Pointer to PALETTEENTRY data structure array,
|
|
|
|
cPalette - Total palette passed by the pPaletteEntry
|
|
|
|
RedGamma - The monitor's red gamma value in UDECI4 format
|
|
|
|
GreenGamma - The monitor's green gamma value in UDECI4 format
|
|
|
|
BlueGamma - The monitor's blue gamma value in UDECI4 format
|
|
|
|
|
|
Return Value:
|
|
|
|
if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
|
|
VGA256 halftone process, if it is not NULL then it return the total
|
|
paletteEntry updated.
|
|
|
|
If the pPaletteEntry is not NULL then halftone.dll assume it has enough
|
|
space for the size returned when this pointer is NULL.
|
|
|
|
Author:
|
|
|
|
14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
FD6 RGBGamma[3];
|
|
LONG cPal;
|
|
FD6 Yr;
|
|
FD6 Yg;
|
|
FD6 Yb;
|
|
BYTE r;
|
|
BYTE g;
|
|
BYTE b;
|
|
|
|
//
|
|
// Initialize All internal data first
|
|
//
|
|
|
|
if ((cPal = cPalette) && (pPaletteEntry)) {
|
|
|
|
RGBGamma[0] = UDECI4ToFD6(RedGamma);
|
|
RGBGamma[1] = UDECI4ToFD6(GreenGamma);
|
|
RGBGamma[2] = UDECI4ToFD6(BlueGamma);
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("***** HT_GammaCorrectPalette: %s:%s:%s *****"
|
|
ARGFD6(RGBGamma[0], 1, 4)
|
|
ARGFD6(RGBGamma[1], 1, 4)
|
|
ARGFD6(RGBGamma[2], 1, 4)));
|
|
|
|
while (cPalette--) {
|
|
|
|
Yr = (FD6)DivFD6(r = pPaletteEntry->peRed, 255);
|
|
Yg = (FD6)DivFD6(g = pPaletteEntry->peGreen, 255);
|
|
Yb = (FD6)DivFD6(b = pPaletteEntry->peBlue, 255);
|
|
|
|
pPaletteEntry->peRed = RGB_8BPP(Yr);
|
|
pPaletteEntry->peGreen = RGB_8BPP(Yg);
|
|
pPaletteEntry->peBlue = RGB_8BPP(Yb);
|
|
pPaletteEntry->peFlags = 0;
|
|
|
|
DBGP_IF(DBGP_GAMMA_PAL,
|
|
DBGP("%3u - %3u:%3u:%3u --> %3u:%3u:%3u"
|
|
ARGU(cPalette)
|
|
ARGU(r) ARGU(g) ARGU(b)
|
|
ARGU(pPaletteEntry->peRed )
|
|
ARGU(pPaletteEntry->peGreen)
|
|
ARGU(pPaletteEntry->peBlue )));
|
|
|
|
++pPaletteEntry;
|
|
}
|
|
}
|
|
|
|
return((LONG)cPal);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
HT_LOADDS
|
|
HT_ConvertColorTable(
|
|
PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
|
|
PHTCOLORADJUSTMENT pHTColorAdjustment,
|
|
PCOLORTRIAD pColorTriad,
|
|
DWORD Flags
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function modified input color table entries base on the
|
|
pHTColorAdjustment data structure specification.
|
|
|
|
Arguments:
|
|
|
|
pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
|
|
which returned from the HT_CreateDeviceHalftoneInfo.
|
|
|
|
pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data structure to
|
|
specified the input/output color adjustment/transform,
|
|
if this pointer is NULL then a default color
|
|
adjustments is applied.
|
|
|
|
pColorTriad - Specified the source color table format and location.
|
|
|
|
Flags - One of the following may be specified
|
|
|
|
CCTF_BW_ONLY
|
|
|
|
Create grayscale of the color table.
|
|
|
|
CCTF_NEGATIVE
|
|
|
|
Create negative version of the original color
|
|
table.
|
|
|
|
Return Value:
|
|
|
|
if the return value is negative or zero then an error was encountered,
|
|
possible error codes are
|
|
|
|
HTERR_INVALID_COLOR_TABLE - The ColorTableEntries field is = 0 or
|
|
CCTInfo.SizePerColorTableEntry is not
|
|
between 3 to 255, or if the
|
|
CCTInfo.FirstColorIndex in CCTInfo is
|
|
not in the range of 0 to
|
|
(SizePerColorTableEntry - 3).
|
|
|
|
HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is passed.
|
|
|
|
otherwise
|
|
|
|
Total entries of the converted color table is returned.
|
|
|
|
|
|
Author:
|
|
|
|
14-Aug-1991 Wed 12:43:29 updated -by- Daniel Chou (danielc)
|
|
|
|
|
|
Revision History:
|
|
|
|
16-Feb-1993 Tue 00:10:56 updated -by- Daniel Chou (danielc)
|
|
Fixes bug #10448 which create all black densitities brushes, this
|
|
was caused by not initialized ColorTriad.PrimaryOrder.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEVICECOLORINFO pDCI;
|
|
PDEVCLRADJ pDevClrAdj;
|
|
CTSTD_UNION CTSTDUnion;
|
|
WORD ForceFlags;
|
|
LONG Result;
|
|
|
|
return(HTERR_COLORTABLE_TOO_BIG);
|
|
}
|