Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4735 lines
134 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 "htsetbmp.h"
#include "htrender.h"
#include "htmath.h"
#include "stdio.h"
#define INCLUDE_DEF_CIEINFO
#include "htapi.h"
#define DBGP_SHOWPAT 0x0001
#define DBGP_TIMER 0x0002
#define DBGP_CACHED_DCI 0x0004
#define DBGP_CACHED_SMP 0x0008
#define DBGP_DYECORRECTION 0x0010
#define DBGP_8BPP_PAL 0x0020
#define DBGP_DHI_MEM 0x0040
#define DBGP_COMPUTE_L2I 0x0080
#define DBGP_HTMUTEX 0x0100
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_DYECORRECTION, 0) |
BIT_IF(DBGP_8BPP_PAL, 0) |
BIT_IF(DBGP_DHI_MEM, 0) |
BIT_IF(DBGP_COMPUTE_L2I, 0) |
BIT_IF(DBGP_HTMUTEX, 0))
//
// Turn on TEST_3PLANES only for debugging mode
//
#define TEST_3PLANES 0
#if 0
#define HAS_FILL_MODE
#endif
HTGLOBAL HTGlobal = { (HMODULE)NULL,
(HTMUTEX)NULL,
(HTMUTEX)NULL,
(PCDCIDATA)NULL,
(PCSMPDATA)NULL,
(WORD)0,
(WORD)0
};
FD6 L2I_16bpp555[RGB555_C_LEVELS + 1];
FD6 L2I_VGA256Mono[VGA256_MONO_SIZE + 1];
DEFDBGVAR(BOOL, DisableCacheDCI_SMP = FALSE)
#define RGB_8BPP(rgb,Gamma) (BYTE)SCALE_FD6(Radical((rgb), Gamma), 255)
//
// Following are the constant for VGA16 half intensity and light gray color
//
//===========================================================================
#ifdef HAS_FILL_MODE
BYTERGB VGAPalette[] = {
// Index 0
{ 0, 0, 0 }, { 0, 0, 20 }, { 0, 0, 40 }, { 0, 0, 60 }, { 0, 0, 80 }, { 0, 0,100 },
{ 0, 20, 0 }, { 0, 20, 20 }, { 0, 20, 40 }, { 0, 20, 60 }, { 0, 20, 80 }, { 0, 20,100 },
{ 0, 40, 0 }, { 0, 40, 20 }, { 0, 40, 40 }, { 0, 40, 60 }, { 0, 40, 80 }, { 0, 40,100 },
{ 0, 60, 0 }, { 0, 60, 20 }, { 0, 60, 40 }, { 0, 60, 60 }, { 0, 60, 80 }, { 0, 60,100 },
{ 0, 80, 0 }, { 0, 80, 20 }, { 0, 80, 40 }, { 0, 80, 60 }, { 0, 80, 80 }, { 0, 80,100 },
{ 0,100, 0 }, { 0,100, 20 }, { 0,100, 40 }, { 0,100, 60 }, { 0,100, 80 }, { 0,100,100 },
// Index 36
{ 20, 0, 0 }, { 20, 0, 20 }, { 20, 0, 40 }, { 20, 0, 60 }, { 20, 0, 80 }, { 20, 0,100 },
{ 20, 20, 0 }, { 20, 20, 20 }, { 20, 20, 40 }, { 20, 20, 60 }, { 20, 20, 80 }, { 20, 20,100 },
{ 20, 40, 0 }, { 20, 40, 20 }, { 20, 40, 40 }, { 20, 40, 60 }, { 20, 40, 80 }, { 20, 40,100 },
{ 20, 60, 0 }, { 20, 60, 20 }, { 20, 60, 40 }, { 20, 60, 60 }, { 20, 60, 80 }, { 20, 60,100 },
{ 20, 80, 0 }, { 20, 80, 20 }, { 20, 80, 40 }, { 20, 80, 60 }, { 20, 80, 80 }, { 20, 80,100 },
{ 20,100, 0 }, { 20,100, 20 }, { 20,100, 40 }, { 20,100, 60 }, { 20,100, 80 }, { 20,100,100 },
// Index 72
{ 40, 0, 0 }, { 40, 0, 20 }, { 40, 0, 40 }, { 40, 0, 60 }, { 40, 0, 80 }, { 40, 0,100 },
{ 40, 20, 0 }, { 40, 20, 20 }, { 40, 20, 40 }, { 40, 20, 60 }, { 40, 20, 80 }, { 40, 20,100 },
{ 40, 40, 0 }, { 40, 40, 20 }, { 40, 40, 40 }, { 40, 40, 60 }, { 40, 40, 80 }, { 40, 40,100 },
{ 40, 60, 0 }, { 40, 60, 20 }, { 40, 60, 40 }, { 40, 60, 60 }, { 40, 60, 80 }, { 40, 60,100 },
{ 40, 80, 0 }, { 40, 80, 20 }, { 40, 80, 40 }, { 40, 80, 60 }, { 40, 80, 80 }, { 40, 80,100 },
{ 40,100, 0 }, { 40,100, 20 }, { 40,100, 40 }, { 40,100, 60 }, { 40,100, 80 }, { 40,100,100 },
// Index 108
{ 60, 0, 0 }, { 60, 0, 20 }, { 60, 0, 40 }, { 60, 0, 60 }, { 60, 0, 80 }, { 60, 0,100 },
{ 60, 20, 0 }, { 60, 20, 20 }, { 60, 20, 40 }, { 60, 20, 60 }, { 60, 20, 80 }, { 60, 20,100 },
{ 60, 40, 0 }, { 60, 40, 20 }, { 60, 40, 40 }, { 60, 40, 60 }, { 60, 40, 80 }, { 60, 40,100 },
{ 60, 60, 0 }, { 60, 60, 20 }, { 60, 60, 40 }, { 60, 60, 60 }, { 60, 60, 80 }, { 60, 60,100 },
{ 60, 80, 0 }, { 60, 80, 20 }, { 60, 80, 40 }, { 60, 80, 60 }, { 60, 80, 80 }, { 60, 80,100 },
{ 60,100, 0 }, { 60,100, 20 }, { 60,100, 40 }, { 60,100, 60 }, { 60,100, 80 }, { 60,100,100 },
// Index 144
{ 80, 0, 0 }, { 80, 0, 20 }, { 80, 0, 40 }, { 80, 0, 60 }, { 80, 0, 80 }, { 80, 0,100 },
{ 80, 20, 0 }, { 80, 20, 20 }, { 80, 20, 40 }, { 80, 20, 60 }, { 80, 20, 80 }, { 80, 20,100 },
{ 80, 40, 0 }, { 80, 40, 20 }, { 80, 40, 40 }, { 80, 40, 60 }, { 80, 40, 80 }, { 80, 40,100 },
{ 80, 60, 0 }, { 80, 60, 20 }, { 80, 60, 40 }, { 80, 60, 60 }, { 80, 60, 80 }, { 80, 60,100 },
{ 80, 80, 0 }, { 80, 80, 20 }, { 80, 80, 40 }, { 80, 80, 60 }, { 80, 80, 80 }, { 80, 80,100 },
{ 80,100, 0 }, { 80,100, 20 }, { 80,100, 40 }, { 80,100, 60 }, { 80,100, 80 }, { 80,100,100 },
// Index 180
{100, 0, 0 }, {100, 0, 20 }, {100, 0, 40 }, {100, 0, 60 }, {100, 0, 80 }, {100, 0,100 },
{100, 20, 0 }, {100, 20, 20 }, {100, 20, 40 }, {100, 20, 60 }, {100, 20, 80 }, {100, 20,100 },
{100, 40, 0 }, {100, 40, 20 }, {100, 40, 40 }, {100, 40, 60 }, {100, 40, 80 }, {100, 40,100 },
{100, 60, 0 }, {100, 60, 20 }, {100, 60, 40 }, {100, 60, 60 }, {100, 60, 80 }, {100, 60,100 },
{100, 80, 0 }, {100, 80, 20 }, {100, 80, 40 }, {100, 80, 60 }, {100, 80, 80 }, {100, 80,100 },
{100,100, 0 }, {100,100, 20 }, {100,100, 40 }, {100,100, 60 }, {100,100, 80 }, {100,100,100 },
// Index 216
{ 10, 0, 0 }, { 30, 0, 0 }, { 50, 0, 0 }, { 70, 0, 0 }, { 90, 0, 0 }, // R 216
{100, 10, 10 }, {100, 30, 30 }, {100, 50, 50 }, {100, 70, 70 }, {100, 90, 90 }, // 221
{ 0, 10, 0 }, { 0, 30, 0 }, { 0, 50, 0 }, { 0, 70, 0 }, { 0, 90, 0 }, // G 226
{ 10,100, 10 }, { 30,100, 30 }, { 50,100, 50 }, { 70,100, 70 }, { 90,100, 90 }, // 231
{ 0, 0, 10 }, { 0, 0, 30 }, { 0, 0, 50 }, { 0, 0, 70 }, { 0, 0, 90 }, // B 236
{ 10, 10,100 }, { 30, 30,100 }, { 50, 50,100 }, { 70, 70,100 }, { 90, 90,100 }, // 241
{ 7, 7, 7 }, { 14, 14, 14 }, { 27, 27, 27 }, { 34, 34, 34 }, { 47, 47, 47 }, // W 246
{ 54, 54, 54 }, { 67, 67, 67 }, { 74, 74, 74 }, { 87, 87, 87 }, { 94, 94, 94 } // 251
};
BYTE VGABmp1[] = {
0, 1, 2, 3, 4, 5, 36, 37, 38, 39, 40, 41, 72, 73, 74, 75, 76, 77,
6, 7, 8, 9, 10, 11, 42, 43, 44, 45, 46, 47, 78, 79, 80, 81, 82, 83,
12, 13, 14, 15, 16, 17, 48, 49, 50, 51, 52, 53, 84, 85, 86, 87, 88, 89,
18, 19, 20, 21, 22, 23, 54, 55, 56, 57, 58, 59, 90, 91, 92, 93, 94, 95,
24, 25, 26, 27, 28, 29, 60, 61, 62, 63, 64, 65, 96, 97, 98, 99,100,101,
30, 31, 32, 33, 34, 35, 66, 67, 68, 69, 70, 71, 102,103,104,105,106,107,
108,109,110,111,112,113, 144,145,146,147,148,149, 180,181,182,183,184,185,
114,115,116,117,118,119, 150,151,152,153,154,155, 186,187,188,189,190,191,
120,121,122,123,124,125, 156,157,158,159,160,161, 192,193,194,195,196,197,
126,127,128,129,130,131, 162,163,164,165,166,167, 198,199,200,201,202,203,
132,133,134,135,136,137, 168,169,170,171,172,173, 204,205,206,207,208,209,
138,139,140,141,142,143, 174,175,176,177,178,179, 210,211,212,213,214,215
};
BYTE VGABmp2[] = {
0,
246,247, 43,248,249, 86, 250,251,129,252,
253,172,254,255,215
};
BYTE VGABmp3[] = {
180, // R
186, 192, 198, 204, 210, // R -> Y
174, 138, 102, 66, 30, // Y -> G
31, 32, 33, 34, 35, // G -> C
29, 23, 17, 11, 5, // C -> B
41, 77, 113, 149, 185, // B -> M
184, 183, 182, 181, 180 // M -> R
};
BYTE VGABmp4[] = {
0,
216, 36,217, 72,218,108, 219,144,220,180, // Red
221,187,222,194,223,201, 224,208,225,215,
0,
226, 6,227, 12,228, 18, 229, 24,230, 30, // Green
231, 67,232,104,233,141, 234,178,235,215,
0,
236, 1,237, 2,238, 3, 239, 4,240, 5,
241, 47,242, 89,243,131, 244,173,245,215 // Blue
};
HTTESTDATA VGAData[] =
{
{ 18, 12, 650000, VGABmp1 },
{ sizeof(VGABmp2), 1, 70000, VGABmp2 },
{ sizeof(VGABmp3), 1, 100000, VGABmp3 },
{ sizeof(VGABmp4) / 3, 3, 180000, VGABmp4 }
};
SHORTRGB MemColorPalette[] = { // this is a xyz chart
{ 920, 810, 580 }, // 1/1 0 A: dark skin
{ 4110, 3760, 3030 }, // 1/2 1 B: light skin
{ 1830, 1860, 3730 }, // 1/3 2 C: blue sky
{ 940, 1170, 670 }, // 1/4 3 D: foliage
{ 2690, 2440, 5030 }, // 1/5 4 E: blue flower
{ 3500, 4600, 5310 }, // 1/6 5 F: bluish green
{ 3860, 3110, 660 }, // 2/1 6 G: orange
{ 1230, 1020, 3590 }, // 2/2 7 H: purplish blue
{ 2840, 1920, 1510 }, // 2/3 8 I: moderate red
{ 590, 400, 1020 }, // 2/4 9 J: purple
{ 3680, 4740, 1270 }, // 2/5 10 K: yellow green
{ 4970, 4600, 940 }, // 2/6 11 L: orange yellow
{ 500, 350, 1830 }, // 3/1 12 M: blue
{ 1490, 2340, 1060 }, // 3/2 13 N: green
{ 1760, 1020, 480 }, // 3/3 14 O: red
{ 6140, 6440, 1120 }, // 3/4 15 P: yellow
{ 3000, 1920, 3320 }, // 3/5 16 Q: magenta
{ 1490, 1920, 4210 }, // 3/6 17 R: cyan
{ 9810, 10000, 11840 }, // 4/1 18 S: white
{ 6320, 6440, 7630 }, // 4/2 19 T: neutral 8
{ 3740, 3810, 4510 }, // 4/3 10 U: neutral 6.5
{ 1890, 1920, 2270 }, // 4/4 21 V: neutral 5
{ 670, 680, 800 }, // 4/5 22 W: neutral 3.5
{ 0, 0, 0 } // 4/6 23 X: black
};
#if 0
BYTERGB SMPTEPalette[] = {
{ 191, 191, 191 }, // GY 0
{ 191, 191, 0 }, // Y 1
{ 0, 191, 191 }, // C 2
{ 0, 191, 0 }, // G 3
{ 191, 0, 191 }, // M 4
{ 191, 0, 0 }, // R 5
{ 0, 0, 191 }, // B 6
{ 0, 76, 127 }, // -I 7
{ 255, 255, 255 }, // W 8
{ 75, 0, 139 }, // +Q 9
{ 0, 0, 0 }, // BK 10
0.2, 0.4, 0.6, 0.8
{ 11, 11, 11 }, // BK+4 11
{ 22, 22, 22 } // BK+6 12
};
#endif
SHORTRGB SMPTEPalette[] = { // this is a YIQ chart
{ 5454, 0, 0 }, // 0: Gray
{ 4692, 1700, -1673 }, // 1: Yellow
{ 3871, -3156, -1149 }, // 2: Cyan
{ 3108, -1456, -2796 }, // 3: Green
{ 2346, 1456, 2769 }, // 4: Magenta
{ 1583, 3156, 1123 }, // 5: Red
{ 763, -1700, 1647 }, // 6: Blue
{ 723, -890, 309 }, // 7: -I // 2467
{ 10000, 0, 0 }, // 8: White
{ 581, -441, 962 }, // 9: +Q // 1665
{ 0, 0, 0 }, // 10: Black
{ 500, 0, 0 }, // 11: Black+1
{ 1000, 0, 0 }, // 12: Black+2
{ 1500, 0, 0 }, // 13: Black+3
{ 2000, 0, 0 }, // 14: Black+4
{ 2500, 0, 0 }, // 15: Black+5
{ 3000, 0, 0 }, // 16: Black+6
{ 3500, 0, 0 }, // 17: Black+7
{ 4000, 0, 0 } // 18: Black+8
};
BYTE SMPTEBmp1[] = {
0, 0, 0, 0, // GY
1, 1, 1, 1, // Y
2, 2, 2, 2, // C
3, 3, 3, 3, // G
4, 4, 4, 4, // M
5, 5, 5, 5, // R
6, 6, 6, 6 // B
};
BYTE SMPTEBmp2[] = {
6, 6, 6, 6, // B
10,10,10,10, // BK
4, 4, 4, 4, // M
10,10,10,10, // BK
2, 2, 2, 2, // C
10,10,10,10, // BK
0, 0, 0, 0 // GY
};
BYTE SMPTEBmp3[] = {
7, 7, 7, 7, 7, // -I
8, 8, 8, 8, 8, // W
9, 9, 9, 9, 9, // +Q
10,10,10,10,10, // BK
11,12,13,14,
15,16,17,18
};
HTTESTDATA SMPTEData[] =
{
{ sizeof(SMPTEBmp1), 1, 670000, SMPTEBmp1 },
{ sizeof(SMPTEBmp2), 1, 80000, SMPTEBmp2 },
{ sizeof(SMPTEBmp3), 1, 250000, SMPTEBmp3 }
};
#define TESTINFO_COLOR_TABLE 0
#define TESTINFO_SMPTE 1
#define TESTINFO_STD_CLR 2
#define TESTINFO_VGA 3
HTTESTINFO HTTestInfo[] = {
{ // **COLOR TABLE**
{
COLOR_TYPE_RGB, // Type
sizeof(SHORT), // BytesPerPrimary
sizeof(SHORTRGB), // BytesPerEntry,
PRIMARY_ORDER_RGB, // PrimaryOrder,
UDECI4_1, // PrimaryValueMax
0, // ColorTableEntries
NULL // no color table
},
NULL, // pTestData
BMF_16BPP, // SurfaceFormat
0, // TotalData
0, // cx
0 // cy
},
{ // **SMPTE**
{
COLOR_TYPE_YIQ,
sizeof(SHORT),
sizeof(SHORTRGB),
PRIMARY_ORDER_YIQ,
DECI4_1,
COUNT_ARRAY(SMPTEPalette), // ColorTableEntries
SMPTEPalette // pColorTable
},
SMPTEData,
BMF_8BPP,
COUNT_ARRAY(SMPTEData), // TotalData;
1, // cx
1 // cy
},
{ // **Memory Color PALETTE **
{
COLOR_TYPE_XYZ,
sizeof(SHORT),
sizeof(SHORTRGB),
PRIMARY_ORDER_XYZ,
DECI4_1,
COUNT_ARRAY(MemColorPalette), // ColorTableEntries
MemColorPalette // pColorTable
},
NULL, // pTestData
BMF_8BPP,
0, // no data
6, // cx
4 // cy
},
{ // **VGA PALETTE **
{
COLOR_TYPE_RGB,
sizeof(BYTE),
sizeof(BYTERGB),
PRIMARY_ORDER_RGB,
100,
COUNT_ARRAY(VGAPalette), // ColorTableEntries
VGAPalette // pColorTable
},
VGAData, // pTestData
BMF_8BPP,
COUNT_ARRAY(VGAData), // no data
1,
1
}
};
#endif
#if DBG
LONG
HTENTRY
HT_LOADDS
SetHalftoneError(
DWORD HT_FuncIndex,
LONG ErrorID
)
{
static LPSTR HTApiFuncName[] = {
"HalftoneInitProc",
"HT_CreateDeviceHalftoneInfo",
"HT_DestroyDeviceHalftoneInfo",
"HT_CreateHalftoneBrush",
"HT_ConvertColorTable",
"HT_CreateStandardMonoPattern",
"HT_HalftoneBitmap",
};
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"
};
static LPSTR HTPErrorStr[] = {
"STRETCH_FACTOR_TOO_BIG",
"XSTRETCH_FACTOR_TOO_BIG",
"STRETCH_NEG_OVERHANG",
"REGRESS_INV_MODE",
"REGRESS_NO_YDATA",
"REGRESS_INV_XDATA",
"REGRESS_INV_YDATA",
"REGRESS_INV_DATACOUNT",
"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
//
//*****************************************************************************
// START RGB 3 planes device test code, this is testing for the planer format
//
#if DBG
#if TEST_3PLANES
VOID
Convert4BPPTo1BPP3Planes(
LPBYTE pSrcPlane,
LPBYTE pDstPlane,
DWORD BytesPerSrcScanLine,
DWORD BytesPerDstScanLine,
DWORD cx,
DWORD cy,
DWORD SizePerPlane
)
{
LPBYTE p1Plane;
LPBYTE pPlane1;
LPBYTE pPlane2;
LPBYTE pPlane3;
DWORD xLoop;
BYTE Load;
BYTE Mask;
BYTE DestNow;
BYTE DestNext;
BYTE Plane1Byte;
BYTE Plane2Byte;
BYTE Plane3Byte;
DBGP("\n\n* Convert4BPPTo1BPP3Planes [%ld x %ld] [%ld BytesPerPlane] *"
ARGDW(cx) ARGDW(cy) ARGDW(SizePerPlane));
DBGP("pSrcPlane = %08lx [%ld PerScan), pDstPlane = %08lx [%ld PerScan]"
ARGDW(pSrcPlane) ARGDW(BytesPerSrcScanLine)
ARGDW(pDstPlane) ARGDW(BytesPerDstScanLine));
while (cy--) {
p1Plane = pSrcPlane;
pPlane1 = pDstPlane;
pPlane2 = pPlane1 + SizePerPlane;
pPlane3 = pPlane2 + SizePerPlane;
Mask = 0x80;
xLoop = cx;
Load = 0x01;
Plane1Byte =
Plane2Byte =
Plane3Byte = 0;
while (xLoop--) {
if (Load ^= 0x01) {
DestNow = DestNext;
} else {
DestNext =
DestNow = *p1Plane++;
DestNow >>= 4;
DestNext &= 0x0f;
}
if (DestNow & 0x01) {
Plane1Byte |= Mask;
}
if (DestNow & 0x02) {
Plane2Byte |= Mask;
}
if (DestNow & 0x04) {
Plane3Byte |= Mask;
}
if (!(Mask >>= 1)) {
*pPlane1++ = Plane1Byte;
*pPlane2++ = Plane2Byte;
*pPlane3++ = Plane3Byte;
Plane1Byte =
Plane2Byte =
Plane3Byte = 0;
Mask = 0x80;
}
}
if (Mask != 0x80) {
*pPlane1 = Plane1Byte;
*pPlane2 = Plane2Byte;
*pPlane3 = Plane3Byte;
}
pSrcPlane += BytesPerSrcScanLine;
pDstPlane += BytesPerDstScanLine;
}
}
VOID
Convert1BPP3PlanesTo4BPP(
LPBYTE pSrcPlane,
LPBYTE pDstPlane,
DWORD BytesPerSrcScanLine,
DWORD BytesPerDstScanLine,
DWORD cx,
DWORD cy,
DWORD SizePerPlane
)
{
LPBYTE p1Plane;
LPBYTE pPlane1;
LPBYTE pPlane2;
LPBYTE pPlane3;
DWORD xLoop;
BYTE Save;
BYTE Mask;
BYTE DestByte;
BYTE Plane1Byte;
BYTE Plane2Byte;
BYTE Plane3Byte;
DBGP("\n\n* Convert1BPP3PlanesTo4BPP [%ld x %ld] [%ld BytesPerPlane] *"
ARGDW(cx) ARGDW(cy) ARGDW(SizePerPlane));
DBGP("pSrcPlane = %08lx [%ld PerScan), pDstPlane = %08lx [%ld PerScan]"
ARGDW(pSrcPlane) ARGDW(BytesPerSrcScanLine)
ARGDW(pDstPlane) ARGDW(BytesPerDstScanLine));
while (cy--) {
pPlane1 = pSrcPlane;
pPlane2 = pPlane1 + SizePerPlane;
pPlane3 = pPlane2 + SizePerPlane;
p1Plane = pDstPlane;
xLoop = cx;
Save = 1;
Mask = 0x0;
DestByte = 0x0;
while (xLoop--) {
if (!(Mask >>= 1)) {
Plane1Byte = *(pPlane1++);
Plane2Byte = *(pPlane2++);
Plane3Byte = *(pPlane3++);
Mask = 0x80;
}
if (Save ^= 0x01) {
if (Plane1Byte & Mask) {
DestByte |= 0x01;
}
if (Plane2Byte & Mask) {
DestByte |= 0x02;
}
if (Plane3Byte & Mask) {
DestByte |= 0x04;
}
*p1Plane++ = DestByte;
DestByte = 0x0;
} else {
if (Plane1Byte & Mask) {
DestByte |= 0x10;
}
if (Plane2Byte & Mask) {
DestByte |= 0x20;
}
if (Plane3Byte & Mask) {
DestByte |= 0x40;
}
}
}
if (!Save) {
*p1Plane = DestByte;
}
pSrcPlane += BytesPerSrcScanLine;
pDstPlane += BytesPerDstScanLine;
}
}
#endif // TEST_3PLANES
#endif // DBG
//
// END OF RGB 3 planes device test code, this is testing for the planer format
//*****************************************************************************
//
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;
EnableHTMemLink();
if (!(HTGlobal.HTMutexCDCI = CREATE_HTMUTEX())) {
ASSERTMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCDCI) failed!",
HTGlobal.HTMutexCDCI);
return(FALSE);
}
HTGlobal.CDCICount = 0;
if (!(HTGlobal.HTMutexCSMP = CREATE_HTMUTEX())) {
ASSERTMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCSMP) failed!",
HTGlobal.HTMutexCSMP);
return(FALSE);
}
HTGlobal.CSMPCount = 0;
DBGP_IF(DBGP_HTMUTEX,
DBGP("\nINIT HTMutex: CDCI=%08lx, CSMP=%08lx"
ARGDW(HTGlobal.HTMutexCDCI)
ARGDW(HTGlobal.HTMutexCSMP)));
for (i = 1; i <= (UINT)(RGB555_C_LEVELS - 2); i++) {
L = DivFD6(i, (UINT)(RGB555_C_LEVELS - 1));
L2I_16bpp555[i] = CIE_L2I(L);
DBGP_IF(DBGP_COMPUTE_L2I,
DBGP("RGB555 %3u = %s"
ARGU(i)
ARGFD6(L2I_16bpp555[i], 1, 6)));
}
for (i = 1; i <= (UINT)(VGA256_MONO_SIZE - 2); i++) {
L = DivFD6(i, (UINT)(VGA256_MONO_SIZE - 1));
L2I_VGA256Mono[i] = CIE_L2I(L);
DBGP_IF(DBGP_COMPUTE_L2I,
DBGP("VGA MONO %3u = %s"
ARGU(i)
ARGFD6(L2I_VGA256Mono[i], 1, 6)));
}
L2I_16bpp555[0] =
L2I_VGA256Mono[0] = FD6_0;
L2I_16bpp555[RGB555_C_LEVELS] =
L2I_VGA256Mono[VGA256_MONO_SIZE] = FD6_1;
//
// The last one just to prevent from divide by 0
//
L2I_16bpp555[RGB555_C_LEVELS - 1] =
L2I_VGA256Mono[VGA256_MONO_SIZE - 1] = (FD6)(FD6_1 + 1);
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;
DBGP_IF((DBGP_CACHED_DCI | DBGP_CACHED_SMP),
DBGP("FreeHTGlobal: UsedCount: CDCI=%u, CSMP=%u"
ARGU(HTGlobal.CDCICount)
ARGU(HTGlobal.CSMPCount)));
HTShowMemLink("Before DisableHalftone", 0, -1);
//
// Do the CDCI Data first
//
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
pCDCIData = HTGlobal.pCDCIDataHead;
while (hData = (HLOCAL)pCDCIData) {
DBGP_IF(DBGP_CACHED_DCI,
DBGP("FreeHTGlobal: HTLocalFree(pCDCIDATA=%08lx"
ARG(pCDCIData)));
pCDCIData = pCDCIData->pNextCDCIData;
hData = HTLocalFree(hData);
ASSERTMSG("FreeHTGlobal: HTLocalFree(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_CACHED_SMP,
DBGP("FreeHTGlobal: HTLocalFree(pCSMPBmp=%08lx"
ARG(pCSMPBmp)));
pCSMPBmp = pCSMPBmp->pNextCSMPBmp;
hData = HTLocalFree(hData);
ASSERTMSG("FreeHTGlobal: HTLocalFree(CSMPBMP) Failed",
!hData);
}
hData = (HLOCAL)pCSMPData;
pCSMPData = pCSMPData->pNextCSMPData;
hData = HTLocalFree(hData);
DBGP_IF(DBGP_CACHED_SMP,
DBGP("FreeHTGlobal: HTLocalFree(pCSMPData=%08lx"
ARG(pCSMPData)));
ASSERTMSG("FreeHTGlobal: HTLocalFree(CSMPDATA) Failed",
!hData);
}
HTGlobal.pCSMPDataHead = NULL;
HTGlobal.CSMPCount = 0;
RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
DELETE_HTMUTEX(HTGlobal.HTMutexCSMP);
HTGlobal.HTMutexCSMP = (HTMUTEX)NULL;
HTShowMemLink("After DisableHalftone", 0, 0);
HTMEMLINK_SNAPSHOT;
DisableHTMemLink();
}
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;
HTShowMemLink("Before CleanUpDHI", (DWORD)pDeviceHalftoneInfo, -1);
pDCI = PDHI_TO_PDCI(pDeviceHalftoneInfo);
ACQUIRE_HTMUTEX(pDCI->HTMutex);
HTMutex = pDCI->HTMutex;
//
// Free all memory assoicated with this device
//
if (pDCI->HTCell.pThresholds) {
DBGP_IF(DBGP_DHI_MEM,
DBGP("CleanUpDHI: HTLocalFree(pDCI->HTCell.pThresholds=%08lx)"
ARG(pDCI->HTCell.pThresholds)));
if (HTLocalFree((HLOCAL)pDCI->HTCell.pThresholds)) {
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->HTCell.pThresholds)", FALSE);
Ok = FALSE;
}
}
Loop = CMI_TOTAL_COUNT;
while (Loop--) {
if (hData = (HLOCAL)pDCI->CMI[Loop].pMappingTable) {
DBGP_IF(DBGP_DHI_MEM,
DBGP("CleanUpDHI: HTLocalFree(pDCI->CMI[%u]=%08lx)"
ARGU(Loop) ARGDW(hData)));
if (HTLocalFree(hData)) {
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->CMI[])", FALSE);
Ok = FALSE;
}
}
}
Loop = CBFL_TOTAL_COUNT;
while (Loop--) {
if (hData = (HLOCAL)pDCI->CBFLUT[Loop].pLUT) {
DBGP_IF(DBGP_DHI_MEM,
DBGP("CleanUpDHI: HTLocalFree(pDCI->CBFLUT[%u].pLUT=%08lx)"
ARGU(Loop) ARGDW(hData)));
if (HTLocalFree(hData)) {
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->CBLUT[])", FALSE);
Ok = FALSE;
}
}
}
Loop = CRTX_TOTAL_COUNT;
while (Loop--) {
if (hData = (HLOCAL)pDCI->CRTX[Loop].pFD6XYZ) {
DBGP_IF(DBGP_DHI_MEM,
DBGP("CleanUpDHI: HTLocalFree(pDCI->CRTX[%u].pFD6XYZ=%08lx)"
ARGU(Loop) ARGDW(hData)));
if (HTLocalFree(hData)) {
ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->CRTX[])", FALSE);
Ok = FALSE;
}
}
}
DBGP_IF(DBGP_DHI_MEM,
DBGP("CleanUpDHI: HTLocalFree(pDHI=%08lx)"
ARGDW(pDeviceHalftoneInfo)));
if (HTLocalFree((HLOCAL)pDeviceHalftoneInfo)) {
ASSERTMSG("CleanUpDHI: FreeMemory(pDeviceHalftoneInfo)", FALSE);
Ok = FALSE;
}
RELEASE_HTMUTEX(HTMutex);
DELETE_HTMUTEX(HTMutex);
HTShowMemLink("After CleanUpDHI", (DWORD)pDeviceHalftoneInfo, 0);
HTMEMLINK_SNAPSHOT;
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);
}
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)
#if DBG
if (DisableCacheDCI_SMP) {
return(NULL);
}
#endif
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=%08lx"
ARG(pCurCDCIData)
ARGDW(Checksum)
ARGU(SearchIndex)
ARG(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;
WORD SizeCell;
#if DBG
if (DisableCacheDCI_SMP) {
return(FALSE);
}
#endif
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=%08lx"
ARGU(MAX_CDCI_COUNT)
ARGDW(pCurCDCIData)));
if (HTLocalFree((HLOCAL)pCurCDCIData)) {
ASSERTMSG("AddCDCI: HTLocalFree(pLastCDCIData) Failed", FALSE);
}
pPrevCDCIData->pNextCDCIData = NULL;
--HTGlobal.CDCICount;
}
SizeCell = (WORD)pDCI->HTCell.Size;
AllocSize = (DWORD)SizeCell + (DWORD)sizeof(CDCIDATA);
DBGP_IF(DBGP_CACHED_DCI,
DBGP(" AddCDCI: HTLocalAlloc(CDCIDATA(%ld) + Cell(%ld)) = %ld bytes"
ARGDW(sizeof(CDCIDATA))
ARGDW(SizeCell) ARGDW(AllocSize)));
if (pCurCDCIData = (PCDCIDATA)HTLocalAlloc(0,
"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->cxCell = pDCI->HTCell.Width;
pCurCDCIData->cyCell = pDCI->HTCell.Height;
pCurCDCIData->SizeCell = SizeCell;
pCurCDCIData->DensitySteps = pDCI->HTCell.DensitySteps;
pCurCDCIData->DevResXDPI = pDCI->DeviceResXDPI;
pCurCDCIData->DevResYDPI = pDCI->DeviceResYDPI;
pCurCDCIData->DevPelsDPI = pDCI->DevicePelsDPI;
CopyMemory((LPBYTE)pCurCDCIData + sizeof(CDCIDATA),
(LPBYTE)pDCI->HTCell.pThresholds,
SizeCell);
HTGlobal.pCDCIDataHead = pCurCDCIData;
++HTGlobal.CDCICount;
DBGP_IF(DBGP_CACHED_DCI,
DBGP(" AddCDCI: CDCIHeader, UsedCount=%u, pHead=%08lx, [%08lx]"
ARGU(HTGlobal.CDCICount)
ARGU(pCurCDCIData)
ARGDW(pCurCDCIData->Checksum)));
} else {
ASSERTMSG("AddCDCI: HTLocalAlloc(pCDCIData) Failed", FALSE);
}
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
return((BOOL)(pCurCDCIData));
}
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)) {
WORD SizeCell = (WORD)pCDCIData->SizeCell;
if (pDCI->HTCell.pThresholds =
(LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"Threshold",
NONZEROLPTR,
(DWORD)SizeCell)) {
pDCI->ClrXFormBlock = pCDCIData->ClrXFormBlock;
pDCI->Flags = pCDCIData->DCIFlags;
pDCI->HTCell.Width = pCDCIData->cxCell;
pDCI->HTCell.Height = pCDCIData->cyCell;
pDCI->HTCell.Size = SizeCell;
pDCI->HTCell.DensitySteps = pCDCIData->DensitySteps;
pDCI->DeviceResXDPI = pCDCIData->DevResXDPI;
pDCI->DeviceResYDPI = pCDCIData->DevResYDPI;
pDCI->DevicePelsDPI = pCDCIData->DevPelsDPI;
CopyMemory((LPBYTE)pDCI->HTCell.pThresholds,
(LPBYTE)pCDCIData + sizeof(CDCIDATA),
SizeCell);
GetOk = TRUE;
} else {
ASSERTMSG("GetCDCI: HTLocalAlloc(Thresholds) failed", FALSE);
}
RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
}
return(GetOk);
}
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)
#if DBG
if (DisableCacheDCI_SMP) {
return(NULL);
}
#endif
ACQUIRE_HTMUTEX(HTGlobal.HTMutexCSMP);
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=%08lx"
ARGU(SearchIndex)
ARG(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=%08lx"
ARGU(MAX_CSMP_COUNT)
ARGDW(pCurCSMPData)));
while (hData = (HLOCAL)pCurCSMPBmp) {
pCurCSMPBmp = pCurCSMPBmp->pNextCSMPBmp;
DBGP_IF(DBGP_CACHED_SMP,
DBGP(">>FindCSMP: Free pLastCSMPBmp=%08lx"
ARGDW(hData)));
if (HTLocalFree(hData)) {
ASSERTMSG(">>FindCSMP: HTLocalFree(pCurCSMBmp) Failed", FALSE);
}
}
//
// Now free the header for the CSMPDATA
//
if (HTLocalFree((HLOCAL)pCurCSMPData)) {
ASSERTMSG(">>FindCSMP: HTLocalFree(pLastCSMPData) Failed", FALSE);
}
pPrevCSMPData->pNextCSMPData = NULL;
--HTGlobal.CSMPCount;
}
if (pCurCSMPData = (PCSMPDATA)HTLocalAlloc(0,
"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=%08lx"
ARGU(HTGlobal.CSMPCount)
ARGU(pCurCSMPData)));
} else {
ASSERTMSG(" >>FindCSMP: HTLocalAlloc(CSMPDATA) Failed", FALSE);
}
}
//
// 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->DevicePelsDPI)));
if (pCurCSMPBmp = (PCSMPBMP)HTLocalAlloc(0,
"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: HTLocalAlloc(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(BMF_1BPP,
pSMP->ScanLineAlignBytes,
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);
}
DWORD
HTENTRY
ComputeHTINITINFOChecksum(
PDEVICECOLORINFO pDCI,
PHTINITINFO pHTInitInfo
)
/*++
Routine Description:
This function compute 32-bit checksum for the HTINITINFO data structure
passed
Arguments:
pHTInitInfo - Pointer to the HTINITINFO data structure
Pointers and HTCOLORADJUSTMENT data structure are not part
of checksum computation, but content of pointers will be
included in the checksum calculation.
Return Value:
32-bit checksum
Author:
29-Apr-1992 Wed 18:44:42 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
DWORD Checksum;
WORD wBuf[8];
wBuf[0] = (WORD)'HT';
wBuf[1] = (WORD)pHTInitInfo->Flags;
wBuf[2] = (WORD)pHTInitInfo->HTPatternIndex;
wBuf[3] = (WORD)pHTInitInfo->DevicePowerGamma;
wBuf[4] = (WORD)pHTInitInfo->DeviceResXDPI;
wBuf[5] = (WORD)pHTInitInfo->DeviceResYDPI;
wBuf[6] = (WORD)pHTInitInfo->DevicePelsDPI;
wBuf[7] = (WORD)(((wBuf[4] + wBuf[6]) >> 1) + wBuf[5]);
Checksum = ComputeChecksum((LPBYTE)&(wBuf[0]),
pDCI->HTInitInfoChecksum,
sizeof(wBuf));
DBGP_IF(DBGP_CACHED_DCI,
DBGP(" HTINITINFO Checksum= %08lx [%08lx]"
ARGDW(Checksum) ARGDW(pDCI->HTInitInfoChecksum)));
if (pHTInitInfo->pHalftonePattern) {
HALFTONEPATTERN HTPat = *(pHTInitInfo->pHalftonePattern);
DWORD Size;
if (HTPat.Width > MAX_HTPATTERN_WIDTH) {
HTPat.Width = MAX_HTPATTERN_WIDTH;
}
if (HTPat.Height > MAX_HTPATTERN_HEIGHT) {
HTPat.Height = MAX_HTPATTERN_HEIGHT;
}
HTPat.pToneMap = NULL;
Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pHalftonePattern,
Checksum,
sizeof(HALFTONEPATTERN));
DBGP_IF(DBGP_CACHED_DCI,
DBGP(" HTPATTERN Checksum= %08lx" ARGDW(Checksum)));
if (HTPat.pToneMap = pHTInitInfo->pHalftonePattern->pToneMap) {
Size = (DWORD)HTPat.Width * (DWORD)HTPat.Height;
if (!(HTPat.Flags & HTPF_THRESHOLD_ARRAY)) {
Size *= 2;
}
Checksum = ComputeChecksum((LPBYTE)HTPat.pToneMap, Checksum, Size);
DBGP_IF(DBGP_CACHED_DCI,
DBGP(" TONEMAP Checksum= %08lx" ARGDW(Checksum)));
}
}
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);
}
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);
}
VOID
HTENTRY
GetCIEPrims(
PCIEINFO pCIEInfo,
PCIEPRIMS pCIEPrims,
PCIEINFO pDefCIEInfo
)
/*++
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:
VOID
Author:
20-Apr-1993 Tue 01:14:23 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
CIEINFO CIEInfo = (pCIEInfo) ? *pCIEInfo : *pDefCIEInfo;
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)40000)) {
CIEInfo = *pDefCIEInfo;
}
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;
WORD *pw;
BYTE HTInitInfoFlags;
BOOL UseCurNTDefault;
UDECI4 DevPowerGamma;
WORD DevPelsDPI;
DWORD dwBuf[4];
DBGP_IF(DBGP_CACHED_DCI,
DBGP("\n********* HT_CreateDeviceHalftoneInfo *************\n"));
//
// Now check if we have valid data
//
if (pHTInitInfo->Version != (DWORD)HTINITINFO_VERSION) {
HTAPI_RET(HTAPI_IDX_CREATE_DHI, HTERR_WRONG_VERSION_HTINITINFO);
}
DBGP_IF(DBGP_CACHED_DCI,
DBGP("*** Allocate HT_DHI(%ld) ***" ARGDW(sizeof(HT_DHI))));
if (!(pHT_DHI = (PHT_DHI)HTLocalAlloc(0xFFFFFFFF,
"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())) {
ASSERTMSG("InitHTInternalData: CREATE_HTMUTEX(pDCI->HTMutex) failed!",
pDCI->HTMutex);
HTAPI_RET(HTAPI_IDX_CREATE_DHI, (HTERR_INTERNAL_ERRORS_START - 999));
}
if (!(pDCI->HTCallBackFunction = pHTInitInfo->HTCallBackFunction)) {
pDCI->HTCallBackFunction = DefaultHTCallBack;
}
HTInitInfoFlags = (BYTE)(pHTInitInfo->Flags &= (HIF_SQUARE_DEVICE_PEL |
HIF_HAS_BLACK_DYE |
HIF_ADDITIVE_PRIMS));
// ****************************************************************
// * 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 ((DevPowerGamma = pHTInitInfo->DevicePowerGamma) <
(UDECI4)RGB_GAMMA_MIN) {
DevPowerGamma = (UDECI4)((HTInitInfoFlags & HIF_ADDITIVE_PRIMS) ?
10000 : HTStdSubDevGamma);
}
if ((!pHTInitInfo->pDeviceCIEInfo) ||
(pHTInitInfo->pDeviceCIEInfo->Cyan.Y == UDECI4_0)) {
//
// 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 NT4.00 DEFAULT, DevGamma=%s"
ARGFD6(HTStdSubDevGamma * 100, 1, 4)));
UseCurNTDefault = TRUE;
if (!(HTInitInfoFlags & HIF_ADDITIVE_PRIMS)) {
DevPowerGamma = HTStdSubDevGamma;
}
dwBuf[0] = (DWORD)'NTHT';
dwBuf[1] = (DWORD)'4.00';
dwBuf[2] = (DWORD)'Dan.';
dwBuf[3] = (DWORD)'Chou';
DevPelsDPI = 0;
pDCI->HTInitInfoChecksum = ComputeChecksum((LPBYTE)&dwBuf[0],
pDCI->HTInitInfoChecksum,
sizeof(dwBuf));
} else {
DevPelsDPI = pHTInitInfo->DevicePelsDPI;
UseCurNTDefault = FALSE;
}
//
// Compute HTInitInfoChecksum, and check if we have any cached data
//
ComputeHTINITINFOChecksum(pDCI, pHTInitInfo);
if (!GetCachedDCI(pDCI)) {
FD6 VGAGamma;
LONG Result;
//
// Now start to checking the init information
//
pDCI->Flags = (WORD)((HTInitInfoFlags & HIF_SQUARE_DEVICE_PEL) ?
DCIF_SQUARE_DEVICE_PEL : 0);
if ((!(pDCI->DeviceResXDPI = pHTInitInfo->DeviceResXDPI)) ||
(!(pDCI->DeviceResYDPI = pHTInitInfo->DeviceResYDPI))) {
pDCI->DeviceResXDPI =
pDCI->DeviceResYDPI = 300;
DevPelsDPI = 0;
}
if ((DevPelsDPI & 0x8000) && (DevPelsDPI &= 0x7fff)) {
//
// 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%
//
if ((DevPelsDPI > MAX_RES_PERCENT) ||
(DevPelsDPI < MIN_RES_PERCENT)) {
DBGP_IF(DBGP_CACHED_DCI,
DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (PERCENT) set to DEFAULT=0"
ARGDW(DevPelsDPI)));
DevPelsDPI = 0;
} else {
DBGP_IF(DBGP_CACHED_DCI,
DBGP("*** Percentage INPUT DevicePelsDPI=%ld *** "
ARGDW(DevPelsDPI)));
DevPelsDPI = (WORD)(((DWORD)pDCI->DeviceResXDPI * 1000L)
/ (DWORD)DevPelsDPI);
DBGP_IF(DBGP_CACHED_DCI,
DBGP("*** Percentage OUTPUT DevicePelsDPI=%ld *** "
ARGDW(DevPelsDPI)));
}
} else if ((DevPelsDPI > (pDCI->DeviceResXDPI * 3)) ||
(DevPelsDPI > (pDCI->DeviceResYDPI * 3))) {
DBGP_IF(DBGP_CACHED_DCI,
DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (RES) set to DEFAULT=0"
ARGDW(DevPelsDPI)));
DevPelsDPI = 0;
}
//
// If the DevicePelsDPI is out of range then we will make it 0 (same as
// device resolution), so it can continue to work
//
if (HTInitInfoFlags & HIF_ADDITIVE_PRIMS) {
pDCI->ClrXFormBlock.ColorSpace = CIELUV_1976;
pDCI->Flags |= DCIF_ADDITIVE_PRIMS;
} else {
pDCI->ClrXFormBlock.ColorSpace = CIELAB_1976;
pDCI->Flags |= DCIF_NEED_DYES_CORRECTION;
if (HTInitInfoFlags & HIF_HAS_BLACK_DYE) {
pDCI->Flags |= DCIF_HAS_BLACK_DYE;
}
if (!(DevPelsDPI)) {
DevPelsDPI = (WORD)((((DWORD)pDCI->DeviceResXDPI +
(DWORD)pDCI->DeviceResYDPI) * 450) / 1000);
}
}
//
// Save the DevPelsDPI back to PDCI
//
pDCI->DevicePelsDPI = DevPelsDPI;
if (DevPowerGamma != UDECI4_1) {
pDCI->Flags |= DCIF_HAS_DEV_GAMMA;
pDCI->ClrXFormBlock.DevRGBGamma =
VGAGamma = UDECI4ToFD6(DevPowerGamma);
} else {
pDCI->ClrXFormBlock.DevRGBGamma =
VGAGamma = FD6_1;
}
pDCI->ClrXFormBlock.VGA16_80h = Power((FD6)501961, VGAGamma);
pDCI->ClrXFormBlock.VGA16_c0h = Power((FD6)752941, VGAGamma);
//
// This is special for the standard screen
//
if ((HTInitInfoFlags & HIF_ADDITIVE_PRIMS) &&
(!(pHTInitInfo->pHalftonePattern)) &&
(pHTInitInfo->HTPatternIndex == HTPAT_SIZE_4x4_M)) {
pDCI->Flags |= DCIF_HAS_ALT_4x4_HTPAT;
}
//
// Check the input and device CIE info
//
GetCIEPrims((UseCurNTDefault) ? NULL : pHTInitInfo->pDeviceCIEInfo,
&(pDCI->ClrXFormBlock.DevCIEPrims),
(HTInitInfoFlags & HIF_ADDITIVE_PRIMS) ?
&HT_CIE_STD_MONITOR : &HT_CIE_STD_PRINTER);
GetCIEPrims(pHTInitInfo->pInputRGBInfo,
&(pDCI->ClrXFormBlock.rgbCIEPrims),
&HT_CIE_STD_MONITOR);
#if 0
//
// Default Alignement white is same as device
//
pDCI->ClrXFormBlock.rgbCIEPrims.w = pDCI->ClrXFormBlock.DevCIEPrims.w;
#endif
ComputeColorSpaceXForm(&(pDCI->ClrXFormBlock.DevCIEPrims),
&(pDCI->ClrXFormBlock.DevCSXForm),
pDCI->ClrXFormBlock.ColorSpace,
ILLUMINANT_MAX_INDEX + 1,
TRUE);
//
// 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 = (BOOL)pHTInitInfo->pDeviceSolidDyesInfo) {
SDI = *(pHTInitInfo->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);
}
}
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->ClrXFormBlock.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->ClrXFormBlock.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->ClrXFormBlock.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);
ComputeColorSpaceXForm(&(pDCI->ClrXFormBlock.DevCIEPrims),
&(pDCI->ClrXFormBlock.DevCSXForm),
pDCI->ClrXFormBlock.ColorSpace,
ILLUMINANT_MAX_INDEX + 1,
TRUE);
}
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/REGRESS data structure based on the halftone
// pattern data passed.
//
if ((Result = ComputeHTCellRegress((WORD)pHTInitInfo->HTPatternIndex,
pHTInitInfo->pHalftonePattern,
pDCI)) < 0) {
CleanUpDHI((PDEVICEHALFTONEINFO)pHT_DHI);
HTAPI_RET(HTAPI_IDX_CREATE_DHI, Result);
}
AddCachedDCI(pDCI);
}
pDCI->CRTX[CRTX_LEVEL_255].PrimMax = 255;
pDCI->CRTX[CRTX_LEVEL_255].SizeCRTX = (WORD)(((255+1)*3) * sizeof(FD6XYZ));
pDCI->CRTX[CRTX_LEVEL_31].PrimMax = 31;
pDCI->CRTX[CRTX_LEVEL_31].SizeCRTX = (WORD)(((31+1)*3) * sizeof(FD6XYZ));
//
// Setting the public field so the caller can looked at
//
pHT_DHI->DHI.DeviceOwnData = 0;
pHT_DHI->DHI.cxPattern = (WORD)pDCI->HTCell.Width;
pHT_DHI->DHI.cyPattern = (WORD)pDCI->HTCell.Height;
if ((pHTInitInfo->DefHTColorAdjustment.caIlluminantIndex >
ILLUMINANT_MAX_INDEX) ||
(pHTInitInfo->DefHTColorAdjustment.caSize !=
sizeof(COLORADJUSTMENT)) ||
((pHTInitInfo->DefHTColorAdjustment.caRedGamma == 20000) &&
(pHTInitInfo->DefHTColorAdjustment.caGreenGamma == 20000) &&
(pHTInitInfo->DefHTColorAdjustment.caBlueGamma == 20000))) {
pHT_DHI->DHI.HTColorAdjustment = DefaultCA;
DBGP_IF(DBGP_CACHED_DCI,
DBGP("*** USE DEFAULT COLORADJUSTMENT in DCI *** "));
} else {
pHT_DHI->DHI.HTColorAdjustment = pHTInitInfo->DefHTColorAdjustment;
}
//
// Now compute the HTSMP checksum for the pattern
//
pw = (WORD *)&dwBuf[0];
pw[0] =
pw[3] =
pw[5] = pDCI->DeviceResXDPI;
pw[1] =
pw[2] =
pw[7] = pDCI->DeviceResYDPI;
pw[4] =
pw[6] = pDCI->DevicePelsDPI;
pDCI->HTSMPChecksum = ComputeChecksum((LPBYTE)pw,
HTSMP_INITIAL_CHECKSUM,
sizeof(dwBuf));
DBGP_IF(DBGP_CACHED_DCI,
DBGP("SMP Checksum = %08lx" ARGDW(pDCI->HTSMPChecksum)));
DBGP_IF(DBGP_CACHED_DCI,
DBGP("*** Final DevResDPI=%ld x %ld DevicePelsDPI=%ld, cx/cyPat=%ld x %ld=%ld, Step=%ld *** "
ARGDW(pDCI->DeviceResXDPI)
ARGDW(pDCI->DeviceResYDPI)
ARGDW(pDCI->DevicePelsDPI)
ARGDW(pDCI->HTCell.Width)
ARGDW(pDCI->HTCell.Height)
ARGDW(pDCI->HTCell.Size)
ARGDW(pDCI->HTCell.DensitySteps)));
//
// Set IlluminantIndex to a invalid value so we can re-compute RGBToXYZ
//
pDCI->ca.caIlluminantIndex = 0xffff;
*ppDeviceHalftoneInfo = (PDEVICEHALFTONEINFO)pHT_DHI;
HTShowMemLink("HT_CreateDeviceHalftoneInfo", (DWORD)pHT_DHI, -1);
HTMEMLINK_SNAPSHOT;
return(HALFTONE_DLL_ID);
}
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 (!pDCIAdjClr(pDeviceHalftoneInfo, NULL, NULL, 0)) {
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_1BPP_3PLANES
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.
form BMF_1BPP_3PLANES, the return value is the size for one plane, the
caller should multiply it by 3 to get the correct buffer size.
Author:
05-Feb-1991 Tue 14:28:23 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDEVICECOLORINFO pDCI;
HTCOLORADJUSTMENT ca;
HTBRUSHDATA HTBrushData;
DEVCLRADJ DevClrAdj;
CTSTD_UNION CTSTDUnion;
HTCELL HTCell;
PRIMCOLOR_COUNT PCC;
WORD ForceFlags;
SHORT SizePerScan;
extern HTCELL HTCell_OD4x4;
ForceFlags = ADJ_FORCE_BRUSH;
ca.caSize = sizeof(HTCOLORADJUSTMENT);
ca.caFlags = 0;
ca.caIlluminantIndex = (pHTColorAdjustment) ?
pHTColorAdjustment->caIlluminantIndex :
ILLUMINANT_DEFAULT;
ca.caRedGamma =
ca.caGreenGamma =
ca.caBlueGamma = 10000;
ca.caReferenceBlack = 0;
ca.caReferenceWhite = 10000;
ca.caContrast =
ca.caBrightness =
ca.caColorfulness =
ca.caRedGreenTint = 0;
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) ||
(CHBInfo.DestSurfaceFormat == BMF_4BPP_VGA16) ||
(CHBInfo.DestSurfaceFormat == BMF_8BPP_VGA256) ||
(CHBInfo.DestSurfaceFormat == BMF_16BPP_555)) {
ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
}
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
&ca,
(PDEVCLRADJ)&DevClrAdj,
ForceFlags))) {
HTAPI_RET(HTAPI_IDX_CHB, HTERR_INVALID_DHI_POINTER);
}
if (pColorTriad->ColorTableEntries != 1) {
HTAPI_RET(HTAPI_IDX_CHB, HTERR_CHB_INV_COLORTABLE_SIZE);
}
if ((pDCI->Flags & DCIF_HAS_ALT_4x4_HTPAT) &&
((CHBInfo.DestSurfaceFormat == BMF_8BPP_VGA256) ||
(CHBInfo.DestSurfaceFormat == BMF_16BPP_555))) {
HTCell = HTCell_OD4x4;
} else {
HTCell = pDCI->HTCell;
}
CTSTDUnion.b.Flags = CTSTDF_CHKNONWHITE;
CTSTDUnion.b.SrcOrder = pColorTriad->PrimaryOrder;
CTSTDUnion.b.DestOrder = CHBInfo.DestPrimaryOrder;
HTBrushData.Flags = 0;
HTBrushData.cxHTCell = (BYTE)HTCell.Width;
HTBrushData.cyHTCell = (BYTE)HTCell.Height;
SizePerScan =
HTBrushData.ScanLinePadBytes =
(SHORT)ComputeBytesPerScanLine(CHBInfo.DestSurfaceFormat,
(WORD)CHBInfo.DestScanLineAlignBytes,
(DWORD)HTCell.Width);
HTBrushData.SizePerPlane = (WORD)((WORD)HTBrushData.cyHTCell *
(WORD)SizePerScan);
CTSTDUnion.b.BMFDest =
HTBrushData.SurfaceFormat = CHBInfo.DestSurfaceFormat;
switch (CTSTDUnion.b.BMFDest) {
case BMF_1BPP:
case BMF_1BPP_3PLANES:
HTBrushData.ScanLinePadBytes -= (SHORT)((HTCell.Width + 7) >> 3);
break;
case BMF_4BPP_VGA16:
case BMF_4BPP:
HTBrushData.ScanLinePadBytes -= (SHORT)((HTCell.Width + 1) >> 1);
break;
case BMF_8BPP_VGA256:
HTBrushData.ScanLinePadBytes -= (SHORT)HTCell.Width;
break;
case BMF_16BPP_555:
HTBrushData.ScanLinePadBytes -= (SHORT)(HTCell.Width << 1);
break;
default:
HTAPI_RET(HTAPI_IDX_CHB, HTERR_INVALID_DEST_FORMAT);
}
if (pOutputBuffer) {
LPBYTE pThresholds;
LPBYTE pbSrc;
LPBYTE pbDst = NULL;
UINT SizeToCopy;
LONG Result;
BYTE SubValue;
BYTE OldValue;
if ((Result = ColorTriadSrcToDev(pDCI,
CTSTDUnion,
NULL, // no abort
pColorTriad,
(LPVOID)&(PCC.Color),
&DevClrAdj)) != 1) {
HTAPI_RET(HTAPI_IDX_CHB, Result);
}
if (ForceFlags & ADJ_FORCE_ADDITIVE_PRIMS) {
//
// We need to invert the pattern
//
pbSrc = HTCell.pThresholds;
SizeToCopy = (UINT)HTCell.Size;
if (pThresholds = (LPBYTE)HTLocalAlloc((DWORD)pDeviceHalftoneInfo,
"Brush-Threshold",
LPTR,
SizeToCopy)) {
pbDst = pThresholds;
SubValue = (BYTE)(HTCell.DensitySteps + 1);
while (SizeToCopy--) {
if ((OldValue = *pbSrc++) == 255) {
*pbDst++ = (BYTE)0;
} else {
*pbDst++ = (BYTE)(SubValue - OldValue);
}
}
} else {
HTAPI_RET(HTAPI_IDX_CHB, HTERR_INSUFFICIENT_MEMORY);
}
} else {
pThresholds = HTCell.pThresholds;
}
if (CHBInfo.Flags & CHBF_BOTTOMUP_BRUSH) {
(LPBYTE)pOutputBuffer += (HTBrushData.SizePerPlane -
SizePerScan);
HTBrushData.ScanLinePadBytes += -(SizePerScan << 1);
}
MakeHalftoneBrush(pThresholds, pOutputBuffer, PCC, HTBrushData);
if (pbDst) {
HTLocalFree((HLOCAL)pThresholds);
}
}
HTShowMemLink("HT_CreateHalftoneBrush", (DWORD)pDeviceHalftoneInfo, -1);
return((LONG)HTBrushData.SizePerPlane);
}
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;
RGBGAMMA RGBGamma;
//
// 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.R = UDECI4ToFD6(RedGamma);
RGBGamma.G = UDECI4ToFD6(GreenGamma);
RGBGamma.B = 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 = CIE_L2I(Lightness);
*pRGamma = RGB_8BPP(IValue, RGBGamma.R);
*pGGamma = RGB_8BPP(IValue, RGBGamma.G);
*pBGamma = RGB_8BPP(IValue, RGBGamma.B);
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:
--*/
{
PFD6 pFD6;
RGBGAMMA RGBGamma;
FD6 IValue;
UINT RIndex;
UINT GIndex;
UINT BIndex;
UINT TableSize;
DEFDBGVAR(UINT, PaletteIdx = 0)
//
// Initialize All internal data first
//
if (pPaletteEntry) {
static FD6 VGA256_RS[] = { VGA256_R0,
VGA256_R1,
VGA256_R2,
VGA256_R3,
VGA256_R4,
VGA256_R5,
VGA256_R6,
VGA256_R7 };
static FD6 VGA256_GS[] = { VGA256_G0,
VGA256_G1,
VGA256_G2,
VGA256_G3,
VGA256_G4,
VGA256_G5,
VGA256_G6,
VGA256_G7 };
static FD6 VGA256_BS[] = { VGA256_B0,
VGA256_B1,
VGA256_B2,
VGA256_B3,
VGA256_B4,
VGA256_B5,
VGA256_B6,
VGA256_B7 };
RGBGamma.R = UDECI4ToFD6(RedGamma);
RGBGamma.G = UDECI4ToFD6(GreenGamma);
RGBGamma.B = UDECI4ToFD6(BlueGamma);
DBGP_IF(DBGP_8BPP_PAL,
DBGP("HT_Get8BPPFormatPalette: %s:%s:%s"
ARGFD6(RGBGamma.R, 1, 4)
ARGFD6(RGBGamma.G, 1, 4)
ARGFD6(RGBGamma.B, 1, 4)));
//
// Our VGA256 format is BGR type of Primary order.
//
RIndex =
GIndex =
BIndex = 0;
TableSize = VGA256_CUBE_SIZE;
while (TableSize--) {
pPaletteEntry->peRed = RGB_8BPP(VGA256_RS[RIndex], RGBGamma.R);
pPaletteEntry->peGreen = RGB_8BPP(VGA256_GS[GIndex], RGBGamma.G);
pPaletteEntry->peBlue = RGB_8BPP(VGA256_BS[BIndex], RGBGamma.B);
pPaletteEntry->peFlags = 0;
DBGP_IF(DBGP_8BPP_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;
}
}
}
pFD6 = L2I_VGA256Mono;
TableSize = VGA256_MONO_SIZE;
while (TableSize--) {
IValue = *pFD6++;
pPaletteEntry->peRed = RGB_8BPP(IValue, RGBGamma.R);
pPaletteEntry->peGreen = RGB_8BPP(IValue, RGBGamma.G);
pPaletteEntry->peBlue = RGB_8BPP(IValue, RGBGamma.B);
pPaletteEntry->peFlags = 0;
DBGP_IF(DBGP_8BPP_PAL,
DBGP("%3u - %3u:%3u:%3u"
ARGU(PaletteIdx++)
ARGU(pPaletteEntry->peRed )
ARGU(pPaletteEntry->peGreen)
ARGU(pPaletteEntry->peBlue )));
++pPaletteEntry;
}
}
return((LONG)VGA256_PALETTE_COUNT);
}
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;
DEVCLRADJ DevClrAdj;
CTSTD_UNION CTSTDUnion;
WORD ForceFlags;
LONG Result;
DEFDBGVAR(DBG_TIMER, DbgTimer)
DBGP_IF(DBGP_TIMER, DBG_TIMER_RESET(&DbgTimer));
ForceFlags = ADJ_FORCE_ADDITIVE_PRIMS;
if (Flags & CCTF_NEGATIVE) {
ForceFlags |= ADJ_FORCE_NEGATIVE;
}
if (Flags & CCTF_BW_ONLY) {
ForceFlags |= ADJ_FORCE_MONO;
}
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
pHTColorAdjustment,
(PDEVCLRADJ)&DevClrAdj,
ForceFlags))) {
HTAPI_RET(HTAPI_IDX_CCT, HTERR_INVALID_DHI_POINTER);
}
CTSTDUnion.b.Flags = 0;
CTSTDUnion.b.DestOrder =
CTSTDUnion.b.SrcOrder = pColorTriad->PrimaryOrder;
if ((Result = ColorTriadSrcToDev(pDCI,
CTSTDUnion,
NULL, // no abort
pColorTriad,
NULL,
&DevClrAdj)) <= 0) {
HTAPI_RET(HTAPI_IDX_CCT, Result);
}
DBGP_IF(DBGP_TIMER,
DBG_ELAPSETIME(&DbgTimer);
DBGP("HT_ConvertColorTable: %s (%ld colors)"
ARGTIME(DbgTimer.Time[0].dw)
ARGDW(Result)));
HTShowMemLink("HT_ConvertColorTable", (DWORD)pDeviceHalftoneInfo, -1);
return(Result);
}
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;
LONG Result;
WORD PatCX;
WORD PatCY;
BYTE PatIndex;
if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo, NULL, NULL, 0))) {
HTAPI_RET(HTAPI_IDX_CREATE_SMP, HTERR_INVALID_DHI_POINTER);
}
if ((PatIndex = pStdMonoPattern->PatternIndex) > HT_SMP_MAX_INDEX) {
HTAPI_RET(HTAPI_IDX_CREATE_SMP, HTERR_INVALID_STDMONOPAT_INDEX);
}
if (PatIndex >= HT_SMP_PERCENT_SCREEN_START) {
CHBInfo.DestScanLineAlignBytes = pStdMonoPattern->ScanLineAlignBytes;
PatCX = pStdMonoPattern->cxPels = pDCI->HTCell.Width;
PatCY = pStdMonoPattern->cyPels = pDCI->HTCell.Height;
pStdMonoPattern->BytesPerScanLine = (WORD)
ComputeBytesPerScanLine(BMF_1BPP,
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);
}
#if 1
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("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));
}
)
#endif
HTShowMemLink("HT_CreateStandardMonoPattern",
(DWORD)pDeviceHalftoneInfo,
-1);
HTAPI_RET(HTAPI_IDX_CREATE_SMP, Result);
}
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:
--*/
{
HR_HEADER HR_Header;
DEVCLRADJ DevClrAdj;
WORD ForceFlags;
LONG Result;
BYTE SurfaceFormat;
#ifdef HAS_FILL_MODE
UINT TestInfoIndex;
HTCOLORADJUSTMENT HTClrAdj;
BOOL IsFillMode;
#endif
//
//*****************************************************************************
// START RGB 3 planes device test data, this is testing for the planer format
//
#if DBG
#if TEST_3PLANES
DEFDBGVAR(LPBYTE, p1Plane)
DEFDBGVAR(HTSURFACEINFO, DestSI)
DEFDBGVAR(DWORD, DestCX)
DEFDBGVAR(DWORD, DestCY)
DEFDBGVAR(DWORD, BytesPerPlane)
DEFDBGVAR(DWORD, BytesPerScanLine1Plane)
DEFDBGVAR(DWORD, BytesPerScanLine3Planes)
DEFDBGVAR(BOOL, Simulate3Planes = FALSE)
#endif
#endif
//
// END OF RGB 3 planes device test data, this is testing for the planer format
//*****************************************************************************
//
DBGP_IF(DBGP_TIMER, DBG_TIMER_RESET(&HR_Header.DbgTimer));
ForceFlags = ADJ_FORCE_SUB_COLOR;
SurfaceFormat = pDestinationHTSurfaceInfo->SurfaceFormat;
if ((pBitbltParams->Flags & BBPF_USE_ADDITIVE_PRIMS) ||
(SurfaceFormat == BMF_4BPP_VGA16) ||
(SurfaceFormat == BMF_8BPP_VGA256) ||
(SurfaceFormat == BMF_16BPP_555)) {
ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
}
if (pBitbltParams->Flags & BBPF_NEGATIVE_DEST) {
ForceFlags |= ADJ_FORCE_NEGATIVE;
}
if ((pBitbltParams->Flags & BBPF_BW_ONLY) ||
(SurfaceFormat == BMF_1BPP)) {
ForceFlags |= ADJ_FORCE_MONO;
}
//
// Firstable check if we have valid pDeviceHalftoneInfo, if not then
// return error now
//
#ifdef HAS_FILL_MODE
if (!(HR_Header.pDeviceColorInfo = pDCIAdjClr(pDeviceHalftoneInfo,
NULL,
NULL,
ForceFlags))) {
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INVALID_DHI_POINTER);
}
if (IsFillMode = (BOOL)(pBitbltParams->Flags & BBPF_FILL_MODE)) {
BYTE FillModeIndex;
if ((FillModeIndex = pBitbltParams->FillModeIndex) ==
BBP_FILL_COLOR_TABLE) {
if ((!pSourceHTSurfaceInfo) ||
(pSourceHTSurfaceInfo->SurfaceFormat >= BMF_24BPP) ||
(!pSourceHTSurfaceInfo->pColorTriad) ||
(!(pSourceHTSurfaceInfo->pColorTriad->ColorTableEntries))) {
//
// Some how we have invalid color table, or the source surface
// format is 24-bit or greater then make it show the VGA color
//
FillModeIndex = BBP_FILL_VGA_16_PALETTE;
}
}
if (FillModeIndex == BBP_FILL_COLOR_TABLE) { // still is!!
//
// Same as the bitmap adjustment, we will not change the color
// adjustment
//
TestInfoIndex = TESTINFO_COLOR_TABLE;
} else {
//
// We will use local color adjustments
//
HTClrAdj = (pHTColorAdjustment) ?
*pHTColorAdjustment :
pDeviceHalftoneInfo->HTColorAdjustment;
pHTColorAdjustment = &HTClrAdj;
//
// Make sure we have valid fill mode
//
switch (FillModeIndex) {
case BBP_FILL_NTSC_COLOR_BAR:
//
// This is a YIQ data, so no RGB gamma is ever computed, the
// Reflect density mode must be LOG (Normal), the input color
// adjustment is NTSC (D65)
//
TestInfoIndex = TESTINFO_SMPTE;
// HTClrAdj.IlluminantIndex = ILLUMINANT_D65;
// HTClrAdj.Flags |= CLRADJF_LOG_FILTER;
break;
case BBP_FILL_MEMORY_COLORS:
//
// This is a XYZ data computed from NTSC (D65) and Y is
// normalized,
//
TestInfoIndex = TESTINFO_STD_CLR;
// HTClrAdj.IlluminantIndex = ILLUMINANT_D65;
// HTClrAdj.Flags |= CLRADJF_LOG_FILTER;
break;
case BBP_FILL_VGA_16_PALETTE:
//
// This is a normalized RGB (ie. no input RGB gamma correction)
// and it can be under any illuminant, the DensityMode is set
// to linear mode.
//
TestInfoIndex = TESTINFO_VGA;
if (HR_Header.pDeviceColorInfo->Flags & DCIF_ADDITIVE_PRIMS) {
HTClrAdj.Flags &= ~CLRADJF_LOG_FILTER;
} else {
HTClrAdj.Flags |= CLRADJF_LOG_FILTER;
}
HTClrAdj.RedGamma =
HTClrAdj.GreenGamma =
HTClrAdj.BlueGamma = UDECI4_1;
break;
default:
return(HTERR_INVALID_FILL_MODE_INDEX);
}
}
}
#endif
//
// Now Compute the Device Color Adjusment data
//
if (!(HR_Header.pDeviceColorInfo = pDCIAdjClr(pDeviceHalftoneInfo,
pHTColorAdjustment,
&DevClrAdj,
ForceFlags))) {
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INVALID_DHI_POINTER);
}
//
// We will mask out the more flags, since this flag is currently used
// internally.
//
HR_Header.pDevClrAdj = &DevClrAdj;
HR_Header.pBitbltParams = pBitbltParams;
HR_Header.pSrcSI = pSourceHTSurfaceInfo;
HR_Header.pSrcMaskSI = pSourceMaskHTSurfaceInfo;
HR_Header.pDestSI = pDestinationHTSurfaceInfo;
//
//*****************************************************************************
// START RGB 3 planes device test code, this is testing for the planer format
//
#if DBG
#if TEST_3PLANES
if ((HR_Header.pDestSI->SurfaceFormat == BMF_4BPP) &&
(HR_Header.pDestSI->MaximumQueryScanLines == 0)) {
DWORD AllocateSize;
DestSI = *pDestinationHTSurfaceInfo;
if (pBitbltParams->Flags & BBPF_HAS_BANDRECT) {
DestCX = pBitbltParams->rclBand.right - pBitbltParams->rclBand.left;
DestCY = pBitbltParams->rclBand.bottom - pBitbltParams->rclBand.top;
} else {
DestCX = DestSI.Width;
DestCY = DestSI.Height;
}
BytesPerScanLine1Plane =
(DWORD)ComputeBytesPerScanLine(DestSI.SurfaceFormat,
DestSI.ScanLineAlignBytes,
DestCX);
BytesPerScanLine3Planes =
(DWORD)ComputeBytesPerScanLine(BMF_1BPP_3PLANES,
DestSI.ScanLineAlignBytes,
DestCX);
p1Plane = DestSI.pPlane;
BytesPerPlane = (DWORD)(BytesPerScanLine3Planes * DestCY);
DestSI.BytesPerPlane = 0;
AllocateSize = (DWORD)(BytesPerPlane * 3);
if (DestSI.pPlane = (LPBYTE)HTLocalAlloc((DWORD)pDeviceHalftoneInfo,
"DestSI.pPlane",
LPTR,
AllocateSize)) {
DestSI.SurfaceFormat = BMF_1BPP_3PLANES;
HR_Header.pDestSI = &DestSI;
Simulate3Planes = TRUE;
DBGP("\n\n====== INTERNAL 3 PLANES SIMULATION ======");
Convert4BPPTo1BPP3Planes(p1Plane,
DestSI.pPlane,
BytesPerScanLine1Plane,
BytesPerScanLine3Planes,
DestCX,
DestCY,
BytesPerPlane);
} else {
DBGP("HTLocalAlloc(%ld) FAILED for Simulate 3 planer"
ARGDW(AllocateSize));
}
}
#endif // TEST_3PLANES
#endif // DBG
//
// END OF RGB 3 planes device test code, this is testing for the planer format
//*****************************************************************************
//
#ifdef HAS_FILL_MODE
if (IsFillMode) {
Result = FillTestPattern(&HR_Header, TestInfoIndex);
} else {
#else
{
#endif
Result = HalftoneBitmap(&HR_Header);
}
if ((Result >= 0) && (pBitbltParams->pAbort)) {
*(pBitbltParams->pAbort) = (WORD)0;
}
//
//*****************************************************************************
// START RGB 3 planes device test code, this is testing for the planer format
//
#if DBG
#if TEST_3PLANES
if (Simulate3Planes) {
Convert1BPP3PlanesTo4BPP(DestSI.pPlane,
p1Plane,
BytesPerScanLine3Planes,
BytesPerScanLine1Plane,
DestCX,
DestCY,
BytesPerPlane);
if (HTLocalFree((HLOCAL)DestSI.pPlane)) {
DBGP("HTLocalFree(%8lx) FAILED for Simulated 3 planer"
ARGDW(DestSI.pPlane));
}
}
#endif
#endif
//
// END OF RGB 3 planes device test code, this is testing for the planer format
//*****************************************************************************
//
DBGP_IF(DBGP_TIMER,
{
DWORD TotTime;
DWORD SrcSize;
DWORD DstSize;
DWORD SrcKB;
DWORD DstKB;
DWORD KBPerSec;
DBG_ELAPSETIME(&HR_Header.DbgTimer);
SrcSize = (DWORD)
ComputeBytesPerScanLine(HR_Header.pSrcSI->SurfaceFormat,
HR_Header.pSrcSI->ScanLineAlignBytes,
HR_Header.pSrcSI->Width) *
(DWORD)HR_Header.pSrcSI->Height;
DstSize = (DWORD)
ComputeBytesPerScanLine(HR_Header.pDestSI->SurfaceFormat,
HR_Header.pDestSI->ScanLineAlignBytes,
HR_Header.pDestSI->Width) *
(DWORD)HR_Header.pDestSI->Height;
SrcKB = (DWORD)(((SrcSize * 100) + 512) / 1024);
DstKB = (DWORD)(((DstSize * 100) + 512) / 1024);
TotTime = HR_Header.DbgTimer.Time[0].dw +
HR_Header.DbgTimer.Time[1].dw;
KBPerSec = (DWORD)((((SrcKB + DstKB) * 1000L) + (TotTime / 2))
/ TotTime);
DBGP("HT_BMP=%5ld, %s (%s:%s) S=%5ld.%02uk, D=%5ld.%02uk, %6ld.%02u k/s"
ARGL(Result)
ARGTIME(TotTime)
ARGTIME(HR_Header.DbgTimer.Time[0].dw)
ARGTIME(HR_Header.DbgTimer.Time[1].dw)
ARGDW(SrcKB / 100)
ARGDW(SrcKB % 100)
ARGDW(DstKB / 100)
ARGDW(DstKB % 100)
ARGDW(KBPerSec / 100)
ARGDW(KBPerSec % 100));
}
)
HTShowMemLink("HT_HalftoneBitmap", (DWORD)pDeviceHalftoneInfo, -1);
HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
}
#ifdef HAS_FILL_MODE
LONG
HTENTRY
FillTestPattern(
PHR_HEADER pHR,
UINT TestInfoIndex
)
/*++
Routine Description:
This function generate test pattern.
Arguments:
pHR - Ponter the HR_HEADER block
TestInfoIndex - The TESTINFO_xxxx indices number
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:
09-Jun-1992 Tue 18:41:01 updated -by- Daniel Chou (danielc)
1. Fixed bug 'SrcSI.SurfaceFormat' to 'pOldSrcSI->SurfaceFormat'
--*/
{
PHTSURFACEINFO pOldSrcSI;
HTSURFACEINFO SrcSI;
BITBLTPARAMS BBP;
PHTTESTDATA pTestData;
PHTTESTINFO pTestInfo;
HTTESTDATA TestData;
COLORTRIAD ColorTriad;
LPWORD pBmp;
LONG Result;
LONG SizeBmp;
UINT Loop;
WORD Color;
LONG cyDest;
LONG yMax;
WORD TotalData;
WORD cx;
WORD cy;
pBmp = NULL;
pOldSrcSI = pHR->pSrcSI;
BBP = *(pHR->pBitbltParams);
SrcSI.pColorTriad = &ColorTriad;
pHR->pSrcSI = &SrcSI;
pHR->pBitbltParams = &BBP;
pHR->pSrcMaskSI = NULL; // disable source masking mode
pTestInfo = &HTTestInfo[TestInfoIndex];
SrcSI.hSurface = 'Fill';
SrcSI.Flags = HTSIF_SCANLINES_TOPDOWN;
SrcSI.SurfaceFormat = (BYTE)pTestInfo->SurfaceFormat;
SrcSI.ScanLineAlignBytes = (BYTE)BMF_ALIGN_BYTE;
SrcSI.MaximumQueryScanLines = 0;
TotalData = (WORD)pTestInfo->TotalData;
cx = (WORD)pTestInfo->cx;
cy = (WORD)pTestInfo->cy;
if (TestInfoIndex == TESTINFO_COLOR_TABLE) {
TotalData = 0;
ColorTriad = *(pOldSrcSI->pColorTriad);
if (!(Result = (LONG)((LONG)(SquareRoot(ColorTriad.ColorTableEntries) +
500L) / 1000L))) {
Result = 1;
}
cy = (WORD)((ColorTriad.ColorTableEntries +
((DWORD)Result >> 1)) / (DWORD)Result);
cx = (WORD)Result;
} else {
ColorTriad = pTestInfo->ColorTriad;
}
//
// Using Local copy
//
BBP.rclSrc.left =
BBP.rclSrc.top = 0;
cyDest = (yMax = BBP.rclDest.bottom) - BBP.rclDest.top;
if (!(Loop = (UINT)TotalData)) {
if ((!cx) || (!cy)) {
cx = 1;
cy = (WORD)ColorTriad.ColorTableEntries;
}
SrcSI.SurfaceFormat = BMF_16BPP;
SrcSI.ScanLineAlignBytes = (BYTE)BMF_ALIGN_WORD;
SizeBmp = (TestData.cx = cx) * (TestData.cy = cy);
if (!(pBmp = (LPWORD)HTLocalAlloc((DWORD)pDeviceHalftoneInfo,
"FillTest:pBmp",
NONZEROLPTR,
SizeBmp * sizeof(WORD)))) {
return(HTERR_INSUFFICIENT_MEMORY);
}
for (Loop = 0, Color = 0; Loop < (UINT)SizeBmp; Loop++) {
pBmp[Loop] = (WORD)Color;
if (++Color >= (WORD)ColorTriad.ColorTableEntries) {
Color = 0;
}
}
Loop = 1;
TestData.pBitmap = (LPBYTE)pBmp;
TestData.cyRatio = FD6_1;
pTestData = &TestData;
} else {
pTestData = pTestInfo->pTestData;
}
while (Loop--) {
TestData = *pTestData++;
BBP.rclSrc.right = SrcSI.Width = (LONG)TestData.cx;
BBP.rclSrc.bottom = SrcSI.Height = (LONG)TestData.cy;
SrcSI.pPlane = (LPBYTE)TestData.pBitmap;
if (!(BBP.rclDest.bottom = BBP.rclDest.top +
(LONG)MulFD6(TestData.cyRatio, cyDest))) {
BBP.rclDest.bottom = 1;
} else if (BBP.rclDest.bottom > yMax) {
BBP.rclDest.bottom = yMax;
}
if ((Result = HalftoneBitmap(pHR)) < 0) {
break;
}
BBP.rclDest.top = BBP.rclDest.bottom;
}
if (pBmp) {
HTLocalFree((HLOCAL)pBmp);
}
HTShowMemLink("FillTestPattern", (DWORD)pDeviceHalftoneInfo, -1);
return(Result);
}
#endif