Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5056 lines
149 KiB

  1. /*++
  2. Copyright (c) 1990-1991 Microsoft Corporation
  3. Module Name:
  4. htapi.c
  5. Abstract:
  6. This module contains all the halftone entry points which communicate
  7. with caller to the halftone dll.
  8. Author:
  9. 05-Feb-1991 Tue 10:52:03 created -by- Daniel Chou (danielc)
  10. [Environment:]
  11. GDI Device Driver - Halftone.
  12. [Notes:]
  13. Revision History:
  14. --*/
  15. #define DBGP_VARNAME dbgpHTAPI
  16. #define _HTAPI_ENTRY_
  17. #include "htp.h"
  18. #include "htmapclr.h"
  19. #include "htpat.h"
  20. #include "htrender.h"
  21. #include "htmath.h"
  22. #include "htalias.h"
  23. #include "htsetbmp.h"
  24. #include "stdio.h"
  25. #define INCLUDE_DEF_CIEINFO
  26. #include "htapi.h"
  27. #define DBGP_SHOWPAT 0x00000001
  28. #define DBGP_TIMER 0x00000002
  29. #define DBGP_CACHED_DCI 0x00000004
  30. #define DBGP_CACHED_SMP 0x00000008
  31. #define DBGP_DISABLE_HT 0x00000010
  32. #define DBGP_DYECORRECTION 0x00000020
  33. #define DBGP_DHI_MEM 0x00000040
  34. #define DBGP_COMPUTE_L2I 0x00000080
  35. #define DBGP_HTMUTEX 0x00000100
  36. #define DBGP_GAMMA_PAL 0x00000200
  37. #define DBGP_CHB 0x00000400
  38. #define DBGP_DEVPELSDPI 0x00000800
  39. #define DBGP_SRCBMP 0x00001000
  40. #define DBGP_TILE 0x00002000
  41. #define DBGP_HTAPI 0x00004000
  42. #define DBGP_MEMLINK 0x00008000
  43. #define DBGP_SHOW_CSMBMP 0x00010000
  44. DEF_DBGPVAR(BIT_IF(DBGP_SHOWPAT, 0) |
  45. BIT_IF(DBGP_TIMER, 0) |
  46. BIT_IF(DBGP_CACHED_DCI, 0) |
  47. BIT_IF(DBGP_CACHED_SMP, 0) |
  48. BIT_IF(DBGP_DISABLE_HT, 0) |
  49. BIT_IF(DBGP_DYECORRECTION, 0) |
  50. BIT_IF(DBGP_DHI_MEM, 0) |
  51. BIT_IF(DBGP_COMPUTE_L2I, 0) |
  52. BIT_IF(DBGP_HTMUTEX, 0) |
  53. BIT_IF(DBGP_GAMMA_PAL, 0) |
  54. BIT_IF(DBGP_CHB, 0) |
  55. BIT_IF(DBGP_DEVPELSDPI, 0) |
  56. BIT_IF(DBGP_SRCBMP, 0) |
  57. BIT_IF(DBGP_TILE, 0) |
  58. BIT_IF(DBGP_HTAPI, 0) |
  59. BIT_IF(DBGP_MEMLINK, 0) |
  60. BIT_IF(DBGP_SHOW_CSMBMP, 0))
  61. HTGLOBAL HTGlobal = { (HMODULE)NULL,
  62. (HTMUTEX)NULL,
  63. (HTMUTEX)NULL,
  64. (HTMUTEX)NULL,
  65. (PCDCIDATA)NULL,
  66. (PCSMPDATA)NULL,
  67. (PBGRMAPCACHE)NULL,
  68. (LONG)0,
  69. (LONG)0,
  70. (LONG)0,
  71. (WORD)0,
  72. (WORD)0
  73. };
  74. #define DO_DYES_CORRECTION 0
  75. #define CMY_8BPP(b, i, m, t) \
  76. { \
  77. if ((i) < (m)) { \
  78. \
  79. (t) = FD6_1 - DivFD6((FD6)(i),(FD6)(m)); \
  80. (b) = (BYTE)SCALE_FD6((t), 255); \
  81. \
  82. } else { \
  83. \
  84. (b) = 0; \
  85. } \
  86. }
  87. #define RGB_8BPP(rgb) (BYTE)SCALE_FD6((rgb), 255)
  88. #define GET_DEN_LO(x) DivFD6((FD6)((((x) ) & 0xFF) + 1), (FD6)256)
  89. #define GET_DEN_HI(x) DivFD6((FD6)((((x) >> 8) & 0xFF) + 1), (FD6)256)
  90. #if DBG
  91. LONG
  92. HTENTRY
  93. HT_LOADDS
  94. SetHalftoneError(
  95. DWORD HT_FuncIndex,
  96. LONG ErrorID
  97. )
  98. {
  99. const static LPSTR HTApiFuncName[] = {
  100. "HalftoneInitProc",
  101. "HT_CreateDeviceHalftoneInfo",
  102. "HT_DestroyDeviceHalftoneInfo",
  103. "HT_CreateHalftoneBrush",
  104. "HT_ConvertColorTable",
  105. "HT_CreateStandardMonoPattern",
  106. "HT_HalftoneBitmap",
  107. };
  108. const static LPSTR HTErrorStr[] = {
  109. "WRONG_VERSION_HTINITINFO",
  110. "INSUFFICIENT_MEMORY",
  111. "CANNOT_DEALLOCATE_MEMORY",
  112. "COLORTABLE_TOO_BIG",
  113. "QUERY_SRC_BITMAP_FAILED",
  114. "QUERY_DEST_BITMAP_FAILED",
  115. "QUERY_SRC_MASK_FAILED",
  116. "SET_DEST_BITMAP_FAILED",
  117. "INVALID_SRC_FORMAT",
  118. "INVALID_SRC_MASK_FORMAT",
  119. "INVALID_DEST_FORMAT",
  120. "INVALID_DHI_POINTER",
  121. "SRC_MASK_BITS_TOO_SMALL",
  122. "INVALID_HTPATTERN_INDEX",
  123. "INVALID_HALFTONE_PATTERN",
  124. "HTPATTERN_SIZE_TOO_BIG",
  125. "NO_SRC_COLORTRIAD",
  126. "INVALID_COLOR_TABLE",
  127. "INVALID_COLOR_TYPE",
  128. "INVALID_COLOR_TABLE_SIZE",
  129. "INVALID_PRIMARY_SIZE",
  130. "INVALID_PRIMARY_VALUE_MAX",
  131. "INVALID_PRIMARY_ORDER",
  132. "INVALID_COLOR_ENTRY_SIZE",
  133. "INVALID_FILL_SRC_FORMAT",
  134. "INVALID_FILL_MODE_INDEX",
  135. "INVALID_STDMONOPAT_INDEX",
  136. "INVALID_DEVICE_RESOLUTION",
  137. "INVALID_TONEMAP_VALUE",
  138. "NO_TONEMAP_DATA",
  139. "TONEMAP_VALUE_IS_SINGULAR",
  140. "INVALID_BANDRECT",
  141. "STRETCH_RATIO_TOO_BIG",
  142. "CHB_INV_COLORTABLE_SIZE",
  143. "HALFTONE_INTERRUPTTED",
  144. "HTERR_NO_SRC_HTSURFACEINFO",
  145. "HTERR_NO_DEST_HTSURFACEINFO",
  146. "HTERR_8BPP_PATSIZE_TOO_BIG",
  147. "HTERR_16BPP_555_PATSIZE_TOO_BIG"
  148. };
  149. const static LPSTR HTPErrorStr[] = {
  150. "STRETCH_FACTOR_TOO_BIG",
  151. "XSTRETCH_FACTOR_TOO_BIG",
  152. "STRETCH_NEG_OVERHANG",
  153. "COLORSPACE_NOT_MATCH",
  154. "INVALID_SRCRGB_SIZE",
  155. "INVALID_DEVRGB_SIZE"
  156. };
  157. LPSTR pFuncName;
  158. LONG ErrorIdx;
  159. BOOL MapErrorOk = FALSE;
  160. if (ErrorID < 0) {
  161. if (HT_FuncIndex < (sizeof(HTApiFuncName) / sizeof(LPSTR))) {
  162. pFuncName = HTApiFuncName[HT_FuncIndex];
  163. } else {
  164. pFuncName = "Invalid HT API Function Name";
  165. }
  166. ErrorIdx = -ErrorID;
  167. if (ErrorIdx <= (sizeof(HTErrorStr) / sizeof(LPSTR))) {
  168. DBGP("%s failed: HTERR_%s (%ld)"
  169. ARG(pFuncName)
  170. ARG(HTErrorStr[ErrorIdx - 1])
  171. ARGL(ErrorID));
  172. DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
  173. MapErrorOk = TRUE;
  174. } else if (ErrorIdx >= -(LONG)HTERR_INTERNAL_ERRORS_START) {
  175. ErrorIdx += (LONG)HTERR_INTERNAL_ERRORS_START;
  176. if (ErrorIdx < (sizeof(HTPErrorStr) / sizeof(LPSTR))) {
  177. DBGP("%s Internal Error: %s (%ld)"
  178. ARG(pFuncName)
  179. ARG(HTPErrorStr[ErrorIdx])
  180. ARGL(ErrorID));
  181. DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
  182. MapErrorOk = TRUE;
  183. }
  184. }
  185. if (!MapErrorOk) {
  186. DBGP("%s failed: ??Invalid Error ID (%ld)"
  187. ARG(pFuncName) ARGL(ErrorID));
  188. DBGP("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
  189. }
  190. }
  191. return(ErrorID);
  192. }
  193. #endif
  194. BOOL
  195. PASCAL
  196. HT_LOADDS
  197. EnableHalftone(
  198. VOID
  199. )
  200. /*++
  201. Routine Description:
  202. This function initialize all internal halftone global data to have
  203. halftone DLL/LIB ready to be used
  204. This function MUST called from ALL API entries which does not required
  205. a PDEVICEHALFTONEINFO data pointer
  206. Arguments:
  207. None
  208. Return Value:
  209. None
  210. Author:
  211. 02-Mar-1993 Tue 19:38:43 created -by- Daniel Chou (danielc)
  212. 15-Dec-1995 Fri 16:48:46 updated -by- Daniel Chou (danielc)
  213. All initialization is done at here
  214. Revision History:
  215. --*/
  216. {
  217. FD6 L;
  218. UINT i;
  219. if (!(HTGlobal.HTMutexBGRMC = CREATE_HTMUTEX())) {
  220. DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexBGRMC) failed!");
  221. return(FALSE);
  222. }
  223. HTGlobal.pBGRMC = NULL;
  224. HTGlobal.cBGRMC =
  225. HTGlobal.cIdleBGRMC =
  226. HTGlobal.cAllocBGRMC = 0;
  227. if (!(HTGlobal.HTMutexCDCI = CREATE_HTMUTEX())) {
  228. DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCDCI) failed!");
  229. return(FALSE);
  230. }
  231. HTGlobal.CDCICount = 0;
  232. if (!(HTGlobal.HTMutexCSMP = CREATE_HTMUTEX())) {
  233. DBGMSG("InitHTInternalData: CREATE_HTMUTEX(HTMutexCSMP) failed!");
  234. return(FALSE);
  235. }
  236. HTGlobal.CSMPCount = 0;
  237. return(TRUE);
  238. }
  239. VOID
  240. PASCAL
  241. HT_LOADDS
  242. DisableHalftone(
  243. VOID
  244. )
  245. /*++
  246. Routine Description:
  247. This function free CDCI/CSMP cached data
  248. Arguments:
  249. none.
  250. Return Value:
  251. BOOL
  252. This function must called when gdisrv.dll is unloaded, sinnce halftone
  253. is a linked as a library not a individual DLL.
  254. Author:
  255. 20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
  256. Revision History:
  257. --*/
  258. {
  259. HLOCAL hData;
  260. PCDCIDATA pCDCIData;
  261. PCSMPDATA pCSMPData;
  262. PCSMPBMP pCSMPBmp;
  263. LONG i;
  264. extern LPWORD ppwHTPat[HTPAT_SIZE_MAX_INDEX];
  265. DBGP_IF(DBGP_DISABLE_HT,
  266. DBGP("FreeHTGlobal: UsedCount: CDCI=%u, CSMP=%u"
  267. ARGU(HTGlobal.CDCICount)
  268. ARGU(HTGlobal.CSMPCount)));
  269. //
  270. // Do the BGRMapCache first
  271. //
  272. ACQUIRE_HTMUTEX(HTGlobal.HTMutexBGRMC);
  273. if (HTGlobal.pBGRMC) {
  274. for (i = 0; i < HTGlobal.cBGRMC; i++) {
  275. hData = (HLOCAL)HTGlobal.pBGRMC[i].pMap;
  276. DBGP_IF(DBGP_DISABLE_HT,
  277. DBGP("FreeHTGlobal: HTFreeMem(pBGRMC[%ld].pMap=%p"
  278. ARGDW(i) ARGPTR(hData)));
  279. hData = HTFreeMem(hData);
  280. ASSERTMSG("FreeHTGlobal: HTFreeMem(BGRMap) Failed", !hData);
  281. }
  282. hData = (HLOCAL)HTGlobal.pBGRMC;
  283. DBGP_IF(DBGP_DISABLE_HT,
  284. DBGP("FreeHTGlobal: HTFreeMem(pBGRMC=%p" ARGPTR(hData)));
  285. hData = HTFreeMem(hData);
  286. ASSERTMSG("FreeHTGlobal: HTFreeMem(pBGRMC) Failed", !hData);
  287. }
  288. HTGlobal.cBGRMC =
  289. HTGlobal.cIdleBGRMC =
  290. HTGlobal.cAllocBGRMC = 0;
  291. HTGlobal.pBGRMC = NULL;
  292. RELEASE_HTMUTEX(HTGlobal.HTMutexBGRMC);
  293. DELETE_HTMUTEX(HTGlobal.HTMutexBGRMC);
  294. //
  295. // Do the CDCI Data first
  296. //
  297. ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
  298. pCDCIData = HTGlobal.pCDCIDataHead;
  299. while (hData = (HLOCAL)pCDCIData) {
  300. DBGP_IF(DBGP_DISABLE_HT,
  301. DBGP("FreeHTGlobal: HTFreeMem(pCDCIDATA=%p"
  302. ARGPTR(pCDCIData)));
  303. pCDCIData = pCDCIData->pNextCDCIData;
  304. hData = HTFreeMem(hData);
  305. ASSERTMSG("FreeHTGlobal: HTFreeMem(CDCI) Failed", !hData);
  306. }
  307. HTGlobal.pCDCIDataHead = NULL;
  308. HTGlobal.CDCICount = 0;
  309. RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
  310. DELETE_HTMUTEX(HTGlobal.HTMutexCDCI);
  311. HTGlobal.HTMutexCDCI = (HTMUTEX)0;
  312. //
  313. // Do the bitmap pattern now
  314. //
  315. ACQUIRE_HTMUTEX(HTGlobal.HTMutexCSMP);
  316. pCSMPData = HTGlobal.pCSMPDataHead;
  317. while (pCSMPData) {
  318. pCSMPBmp = pCSMPData->pCSMPBmpHead;
  319. while (hData = (HLOCAL)pCSMPBmp) {
  320. DBGP_IF(DBGP_DISABLE_HT,
  321. DBGP("FreeHTGlobal: HTFreeMem(pCSMPBmp=%p"
  322. ARGPTR(pCSMPBmp)));
  323. pCSMPBmp = pCSMPBmp->pNextCSMPBmp;
  324. hData = HTFreeMem(hData);
  325. ASSERTMSG("FreeHTGlobal: HTFreeMem(CSMPBMP) Failed", !hData);
  326. }
  327. hData = (HLOCAL)pCSMPData;
  328. pCSMPData = pCSMPData->pNextCSMPData;
  329. hData = HTFreeMem(hData);
  330. DBGP_IF(DBGP_DISABLE_HT,
  331. DBGP("FreeHTGlobal: HTFreeMem(pCSMPData=%p"
  332. ARGPTR(pCSMPData)));
  333. ASSERTMSG("FreeHTGlobal: HTFreeMem(CSMPDATA) Failed", !hData);
  334. }
  335. HTGlobal.pCSMPDataHead = NULL;
  336. HTGlobal.CSMPCount = 0;
  337. for (i = 0; i < HTPAT_SIZE_MAX_INDEX; i++) {
  338. if (hData = (HLOCAL)ppwHTPat[i]) {
  339. DBGP_IF(DBGP_DISABLE_HT,
  340. DBGP("FreeHTPat: HTFreeMem(ppwHTPat[%2ld]=%p"
  341. ARGDW(i) ARGPTR(hData)));
  342. HTFreeMem(hData);
  343. ppwHTPat[i] = NULL;
  344. }
  345. }
  346. CHK_MEM_LEAK(NULL, HTMEM_BEGIN);
  347. RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
  348. DELETE_HTMUTEX(HTGlobal.HTMutexCSMP);
  349. HTGlobal.HTMutexCSMP = (HTMUTEX)NULL;
  350. }
  351. BOOL
  352. HTENTRY
  353. CleanUpDHI(
  354. PDEVICEHALFTONEINFO pDeviceHalftoneInfo
  355. )
  356. /*++
  357. Routine Description:
  358. This function clean up (free hMutex/memory) of a DeviceHalftoneInfo
  359. Arguments:
  360. pDeviceHalftoneInfo - the pDeviceHalftoneInfo must be valid
  361. Return Value:
  362. BOOL
  363. Author:
  364. 20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
  365. Revision History:
  366. --*/
  367. {
  368. PDEVICECOLORINFO pDCI;
  369. HTMUTEX HTMutex;
  370. HLOCAL hData;
  371. UINT Loop;
  372. BOOL Ok = TRUE;
  373. pDCI = PDHI_TO_PDCI(pDeviceHalftoneInfo);
  374. ACQUIRE_HTMUTEX(pDCI->HTMutex);
  375. HTMutex = pDCI->HTMutex;
  376. //
  377. // Free all memory assoicated with this device
  378. //
  379. if ((pDCI->HTCell.pThresholds) &&
  380. (!(pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS))) {
  381. DBGP_IF(DBGP_DHI_MEM,
  382. DBGP("CleanUpDHI: HTFreeMem(pDCI->HTCell.pThresholds=%p)"
  383. ARGPTR(pDCI->HTCell.pThresholds)));
  384. if (HTFreeMem(pDCI->HTCell.pThresholds)) {
  385. ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->HTCell.pThresholds)", FALSE);
  386. Ok = FALSE;
  387. }
  388. }
  389. if (hData = (HLOCAL)pDCI->pAlphaBlendBGR) {
  390. DBGP_IF(DBGP_DHI_MEM,
  391. DBGP("CleanUpDHI: HTFreeMem(pDCI->pAlphaBlendBGR=%p)"
  392. ARGPTR(hData)));
  393. if (HTFreeMem(hData)) {
  394. ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->pAlphaBlendBGR)", FALSE);
  395. Ok = FALSE;
  396. }
  397. }
  398. Loop = CRTX_TOTAL_COUNT;
  399. while (Loop--) {
  400. if (hData = (HLOCAL)pDCI->CRTX[Loop].pFD6XYZ) {
  401. DBGP_IF(DBGP_DHI_MEM,
  402. DBGP("CleanUpDHI: HTFreeMem(pDCI->CRTX[%u].pFD6XYZ=%p)"
  403. ARGU(Loop) ARGPTR(hData)));
  404. if (HTFreeMem(hData)) {
  405. ASSERTMSG("CleanUpDHI: FreeMemory(pDCI->CRTX[])", FALSE);
  406. Ok = FALSE;
  407. }
  408. }
  409. }
  410. DBGP_IF(DBGP_DHI_MEM,
  411. DBGP("CleanUpDHI: HTFreeMem(pDHI=%p)"
  412. ARGPTR(pDeviceHalftoneInfo)));
  413. if (HTFreeMem(pDeviceHalftoneInfo)) {
  414. ASSERTMSG("CleanUpDHI: FreeMemory(pDeviceHalftoneInfo)", FALSE);
  415. Ok = FALSE;
  416. }
  417. RELEASE_HTMUTEX(HTMutex);
  418. DELETE_HTMUTEX(HTMutex);
  419. return(Ok);
  420. }
  421. BOOL
  422. APIENTRY
  423. HT_LOADDS
  424. HalftoneInitProc(
  425. HMODULE hModule,
  426. DWORD Reason,
  427. LPVOID Reserved
  428. )
  429. /*++
  430. Routine Description:
  431. This function is DLL main entry point, at here we will save the module
  432. handle, in the future we will need to do other initialization stuff.
  433. Arguments:
  434. hModule - Handle to this moudle when get loaded.
  435. Reason - may be DLL_PROCESS_ATTACH
  436. Reserved - reserved
  437. Return Value:
  438. Always return 1L
  439. Author:
  440. 20-Feb-1991 Wed 18:42:11 created -by- Daniel Chou (danielc)
  441. Revision History:
  442. --*/
  443. {
  444. UNREFERENCED_PARAMETER(Reserved);
  445. switch(Reason) {
  446. case DLL_PROCESS_ATTACH:
  447. DBGP_IF((DBGP_CACHED_DCI | DBGP_CACHED_SMP),
  448. DBGP("\n****** DLL_PROCESS_ATTACH ******\n"));
  449. HTGlobal.hModule = hModule;
  450. EnableHalftone();
  451. break;
  452. case DLL_PROCESS_DETACH:
  453. DBGP_IF((DBGP_CACHED_DCI | DBGP_CACHED_SMP),
  454. DBGP("\n****** DLL_PROCESS_DETACH ******\n"));
  455. DisableHalftone();
  456. break;
  457. }
  458. return(TRUE);
  459. }
  460. #if DO_CACHE_DCI
  461. PCDCIDATA
  462. HTENTRY
  463. FindCachedDCI(
  464. PDEVICECOLORINFO pDCI
  465. )
  466. /*++
  467. Routine Description:
  468. This function will try to find the cached DEVICECOLORINFO and put the
  469. cached data to the pDCI
  470. Arguments:
  471. pDCI - Pointer to current device color info
  472. Return Value:
  473. INT, Index number to the PCDCI.Header[] array, if return value is < 0 then
  474. the CachedDCI data is not found.
  475. Author:
  476. 01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
  477. Revision History:
  478. --*/
  479. {
  480. PCDCIDATA pCurCDCIData;
  481. DEFDBGVAR(UINT, SearchIndex = 0)
  482. ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
  483. if (pCurCDCIData = HTGlobal.pCDCIDataHead) {
  484. PCDCIDATA pPrevCDCIData = NULL;
  485. DWORD Checksum = pDCI->HTInitInfoChecksum;
  486. DBGP_IF(DBGP_CACHED_DCI,
  487. DBGP("FindCDCI: Looking for Checksum (0x%08lx), Count=%u"
  488. ARGDW(Checksum) ARGU(HTGlobal.CDCICount)));
  489. ASSERT(HTGlobal.CDCICount);
  490. while (pCurCDCIData) {
  491. if (pCurCDCIData->Checksum == Checksum) {
  492. DBGP_IF(DBGP_CACHED_DCI,
  493. DBGP("FindCDCI: Found %08lx [CheckSum=%08lx] after %u links, pPrev=%p"
  494. ARG(pCurCDCIData)
  495. ARGDW(Checksum)
  496. ARGU(SearchIndex)
  497. ARGPTR(pPrevCDCIData)));
  498. if (pPrevCDCIData) {
  499. //
  500. // The most recent reference's DCI always as first entry,
  501. // (ie. Link Head), the last is the longest unreferenced
  502. // so that if we need to delete a DCI, we delete the
  503. // last one.
  504. //
  505. DBGP_IF(DBGP_CACHED_DCI,
  506. DBGP("FindCDCI: Move pCur to pHead"));
  507. pPrevCDCIData->pNextCDCIData = pCurCDCIData->pNextCDCIData;
  508. pCurCDCIData->pNextCDCIData = HTGlobal.pCDCIDataHead;
  509. HTGlobal.pCDCIDataHead = pCurCDCIData;
  510. }
  511. return(pCurCDCIData);
  512. }
  513. SETDBGVAR(SearchIndex, SearchIndex + 1);
  514. pPrevCDCIData = pCurCDCIData;
  515. pCurCDCIData = pCurCDCIData->pNextCDCIData;
  516. }
  517. DBGP_IF(DBGP_CACHED_DCI, DBGP("FindCDCI: ??? NOT FOUND ???"));
  518. } else {
  519. DBGP_IF(DBGP_CACHED_DCI, DBGP("FindCDCI: ++No CDCIDATA cahced yet++"));
  520. }
  521. RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
  522. return(NULL);
  523. }
  524. BOOL
  525. HTENTRY
  526. AddCachedDCI(
  527. PDEVICECOLORINFO pDCI
  528. )
  529. /*++
  530. Routine Description:
  531. This function add the DEVICECOLORINFO information to the DCI cache
  532. Arguments:
  533. pDCI - Pointer to current device color info
  534. Lock - TRUE if need to keep the hMutex locked, (only if add is
  535. sucessfully)
  536. Return Value:
  537. INT, Index number to the PCDCI.Header[] array where the new data is added,
  538. if return value is < 0 then the pDCI'CachedDCI data did not add to the
  539. cached array.
  540. NOTE: If AddCachedDCI() return value >= 0 and Lock=TRUE then caller must
  541. release the PCDCI.hMutex after done with the data, if return value
  542. is < 0 then no unlock is necessary.
  543. Author:
  544. 01-May-1992 Fri 13:24:58 created -by- Daniel Chou (danielc)
  545. Revision History:
  546. --*/
  547. {
  548. PCDCIDATA pCurCDCIData;
  549. PCDCIDATA pPrevCDCIData;
  550. DWORD AllocSize;
  551. DWORD SizeCell;
  552. ACQUIRE_HTMUTEX(HTGlobal.HTMutexCDCI);
  553. //
  554. // We only cached CDCIDATA to certain extend, if we over that limit then
  555. // delete the last entry in the link list before adding anything
  556. //
  557. if (HTGlobal.CDCICount >= MAX_CDCI_COUNT) {
  558. ASSERT(HTGlobal.pCDCIDataHead);
  559. pCurCDCIData = HTGlobal.pCDCIDataHead;
  560. pPrevCDCIData = NULL;
  561. while (pCurCDCIData->pNextCDCIData) {
  562. pPrevCDCIData = pCurCDCIData;
  563. pCurCDCIData = pCurCDCIData->pNextCDCIData;
  564. }
  565. ASSERT(pPrevCDCIData);
  566. DBGP_IF(DBGP_CACHED_DCI,
  567. DBGP("AddCDCI: CDCICount >= %u, Free pLast=%p"
  568. ARGU(MAX_CDCI_COUNT)
  569. ARGPTR(pCurCDCIData)));
  570. if (HTFreeMem(pCurCDCIData)) {
  571. ASSERTMSG("AddCDCI: HTFreeMem(pLastCDCIData) Failed", FALSE);
  572. }
  573. pPrevCDCIData->pNextCDCIData = NULL;
  574. --HTGlobal.CDCICount;
  575. }
  576. if (pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS) {
  577. SizeCell = 0;
  578. } else {
  579. SizeCell = (DWORD)pDCI->HTCell.Size;
  580. }
  581. AllocSize = (DWORD)SizeCell + (DWORD)sizeof(CDCIDATA);
  582. DBGP_IF(DBGP_CACHED_DCI,
  583. DBGP(" AddCDCI: HTAllocMem(CDCIDATA(%ld) + Cell(%ld)) = %ld bytes"
  584. ARGDW(sizeof(CDCIDATA))
  585. ARGDW(SizeCell) ARGDW(AllocSize)));
  586. if (pCurCDCIData = (PCDCIDATA)HTAllocMem(NULL,
  587. HTMEM_CurCDCIData,
  588. NONZEROLPTR,
  589. AllocSize)) {
  590. //
  591. // put this data at link list head
  592. //
  593. pCurCDCIData->Checksum = pDCI->HTInitInfoChecksum;
  594. pCurCDCIData->pNextCDCIData = HTGlobal.pCDCIDataHead;
  595. pCurCDCIData->ClrXFormBlock = pDCI->ClrXFormBlock;
  596. pCurCDCIData->DCIFlags = pDCI->Flags;
  597. pCurCDCIData->DevResXDPI = pDCI->DeviceResXDPI;
  598. pCurCDCIData->DevResYDPI = pDCI->DeviceResYDPI;
  599. pCurCDCIData->DevPelRatio = pDCI->DevPelRatio;
  600. pCurCDCIData->HTCell = pDCI->HTCell;
  601. if (SizeCell) {
  602. CopyMemory((LPBYTE)(pCurCDCIData + 1),
  603. (LPBYTE)pDCI->HTCell.pThresholds,
  604. SizeCell);
  605. pCurCDCIData->HTCell.pThresholds = NULL;
  606. }
  607. HTGlobal.pCDCIDataHead = pCurCDCIData;
  608. ++HTGlobal.CDCICount;
  609. DBGP_IF(DBGP_CACHED_DCI,
  610. DBGP(" AddCDCI: CDCIHeader, UsedCount=%u, pHead=%p, [%08lx]"
  611. ARGU(HTGlobal.CDCICount)
  612. ARGPTR(pCurCDCIData)
  613. ARGDW(pCurCDCIData->Checksum)));
  614. } else {
  615. ASSERTMSG("AddCDCI: HTAllocMem(pCDCIData) Failed", FALSE);
  616. }
  617. RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
  618. return((pCurCDCIData) ? TRUE : FALSE);
  619. }
  620. BOOL
  621. HTENTRY
  622. GetCachedDCI(
  623. PDEVICECOLORINFO pDCI
  624. )
  625. /*++
  626. Routine Description:
  627. This function will try to find the cached DEVICECOLORINFO and put the
  628. cached data to the pDCI
  629. Arguments:
  630. pDCI - Pointer to current device color info
  631. Return Value:
  632. BOOLEAN
  633. Author:
  634. 01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
  635. Revision History:
  636. --*/
  637. {
  638. PCDCIDATA pCDCIData;
  639. BOOL GetOk = FALSE;
  640. if (pCDCIData = FindCachedDCI(pDCI)) {
  641. pDCI->ClrXFormBlock = pCDCIData->ClrXFormBlock;
  642. pDCI->Flags = pCDCIData->DCIFlags;
  643. pDCI->DeviceResXDPI = pCDCIData->DevResXDPI;
  644. pDCI->DeviceResYDPI = pCDCIData->DevResYDPI;
  645. pDCI->DevPelRatio = pCDCIData->DevPelRatio;
  646. pDCI->HTCell = pCDCIData->HTCell;
  647. if (pDCI->HTCell.Flags & HTCF_STATIC_PTHRESHOLDS) {
  648. GetOk = TRUE;
  649. } else if (pDCI->HTCell.pThresholds =
  650. (LPBYTE)HTAllocMem((LPVOID)pDCI,
  651. HTMEM_GetCacheThreshold,
  652. NONZEROLPTR,
  653. pDCI->HTCell.Size)) {
  654. CopyMemory((LPBYTE)pDCI->HTCell.pThresholds,
  655. (LPBYTE)(pCDCIData + 1),
  656. pDCI->HTCell.Size);
  657. GetOk = TRUE;
  658. } else {
  659. DBGMSG("GetCDCI: HTAllocMem(Thresholds) failed");
  660. }
  661. RELEASE_HTMUTEX(HTGlobal.HTMutexCDCI);
  662. }
  663. return(GetOk);
  664. }
  665. #endif // DO_CACHE_DCI
  666. #if DBG
  667. VOID
  668. HTENTRY
  669. DbgDumpCSMPBMP(
  670. VOID
  671. )
  672. /*++
  673. Routine Description:
  674. Arguments:
  675. Return Value:
  676. Author:
  677. 25-Mar-1999 Thu 17:49:53 created -by- Daniel Chou (danielc)
  678. Revision History:
  679. --*/
  680. {
  681. PCSMPDATA pCSMPData;
  682. UINT c0 = 0;
  683. pCSMPData = HTGlobal.pCSMPDataHead;
  684. while (pCSMPData) {
  685. PCSMPBMP pCSMPBmp;
  686. UINT c1 = 0;
  687. DBGP_IF(DBGP_SHOW_CSMBMP,
  688. DBGP("cDatas=%3ld: Checksum=%08lx"
  689. ARGDW(++c0) ARGDW(pCSMPData->Checksum)));
  690. pCSMPBmp = pCSMPData->pCSMPBmpHead;
  691. while (pCSMPBmp) {
  692. DBGP_IF(DBGP_SHOW_CSMBMP,
  693. DBGP(" %3ld: Idx=%2ld, %4ldx%4ld=%4ld"
  694. ARGDW(++c1)
  695. ARGDW(pCSMPBmp->PatternIndex)
  696. ARGDW(pCSMPBmp->cxPels)
  697. ARGDW(pCSMPBmp->cyPels)
  698. ARGDW(pCSMPBmp->cxBytes)));
  699. pCSMPBmp = pCSMPBmp->pNextCSMPBmp;
  700. }
  701. pCSMPData = pCSMPData->pNextCSMPData;
  702. }
  703. if (c0 != (UINT)HTGlobal.CSMPCount) {
  704. DBGP("c0 (%ld) != CSMPCount (%ld)"
  705. ARGDW(c0) ARGDW(HTGlobal.CSMPCount));
  706. }
  707. }
  708. #endif
  709. PCSMPBMP
  710. HTENTRY
  711. FindCachedSMP(
  712. PDEVICECOLORINFO pDCI,
  713. UINT PatternIndex
  714. )
  715. /*++
  716. Routine Description:
  717. This function will try to find the cached DEVICECOLORINFO and put the
  718. cached data to the pDCI
  719. Arguments:
  720. pDCI - Pointer to current device color info
  721. Return Value:
  722. INT, Index number to the PCDCI.Header[] array, if return value is < 0 then
  723. the CachedDCI data is not found.
  724. Author:
  725. 01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
  726. Revision History:
  727. --*/
  728. {
  729. PCSMPDATA pPrevCSMPData;
  730. PCSMPDATA pCurCSMPData;
  731. PCSMPBMP pCurCSMPBmp;
  732. DWORD Checksum = pDCI->HTSMPChecksum;
  733. DEFDBGVAR(UINT, SearchIndex = 0)
  734. ACQUIRE_HTMUTEX(HTGlobal.HTMutexCSMP);
  735. DBGP_IF(DBGP_SHOW_CSMBMP, DbgDumpCSMPBMP(); );
  736. if (pCurCSMPData = HTGlobal.pCSMPDataHead) {
  737. pPrevCSMPData = NULL;
  738. DBGP_IF(DBGP_CACHED_DCI,
  739. DBGP(">>FindCSMP: Looking for Checksum (0x%08lx), Count=%u"
  740. ARGDW(Checksum) ARGU(HTGlobal.CSMPCount)));
  741. ASSERT(HTGlobal.CSMPCount);
  742. while (pCurCSMPData) {
  743. if (pCurCSMPData->Checksum == Checksum) {
  744. DBGP_IF(DBGP_CACHED_SMP,
  745. DBGP(">>FindCSMP: Found after %u links, pPrev=%p"
  746. ARGU(SearchIndex)
  747. ARGPTR(pPrevCSMPData)));
  748. if (pPrevCSMPData) {
  749. //
  750. // The most recent reference's CSMPDATA always as first
  751. // entry,(ie. Link Head), the last is the longest
  752. // unreferenced so that if we need to delete a CSMPDATA,
  753. // we delete the last one.
  754. //
  755. DBGP_IF(DBGP_CACHED_SMP,
  756. DBGP(">>FindCSMP: Move pCur to pHead"));
  757. pPrevCSMPData->pNextCSMPData = pCurCSMPData->pNextCSMPData;
  758. pCurCSMPData->pNextCSMPData = HTGlobal.pCSMPDataHead;
  759. HTGlobal.pCSMPDataHead = pCurCSMPData;
  760. }
  761. //
  762. // See we cached any pattern for this group
  763. //
  764. pCurCSMPBmp = pCurCSMPData->pCSMPBmpHead;
  765. SETDBGVAR(SearchIndex, 0);
  766. while (pCurCSMPBmp) {
  767. if ((UINT)pCurCSMPBmp->PatternIndex == PatternIndex) {
  768. DBGP_IF(DBGP_CACHED_SMP,
  769. DBGP(">>FindCSMP: Found Pat(%u) after %u links"
  770. ARGU(PatternIndex)
  771. ARGU(SearchIndex++)));
  772. return(pCurCSMPBmp);
  773. }
  774. pCurCSMPBmp = pCurCSMPBmp->pNextCSMPBmp;
  775. }
  776. //
  777. // Found in this group but no bitmap for PatternIndex is
  778. // cached yet!
  779. //
  780. break;
  781. }
  782. SETDBGVAR(SearchIndex, SearchIndex + 1);
  783. pPrevCSMPData = pCurCSMPData;
  784. pCurCSMPData = pCurCSMPData->pNextCSMPData;
  785. }
  786. DBGP_IF(DBGP_CACHED_SMP, DBGP(">>FindCSMP: ??? NOT FOUND ???"));
  787. } else {
  788. DBGP_IF(DBGP_CACHED_DCI, DBGP(">>FindCSMP: ++No CSMPDATA cahced yet++"));
  789. }
  790. if (!pCurCSMPData) {
  791. //
  792. // Since we did not even found the CSMPDATA checksum group, we want to
  793. // add it in there, but We only cached CSMPDATA to certain extend, if
  794. // we over that limit then delete the last entry in the link list
  795. // before adding anything
  796. //
  797. if (HTGlobal.CSMPCount >= MAX_CSMP_COUNT) {
  798. HLOCAL hData;
  799. ASSERT(HTGlobal.pCSMPDataHead);
  800. pPrevCSMPData = NULL;
  801. pCurCSMPData = HTGlobal.pCSMPDataHead;
  802. while (pCurCSMPData->pNextCSMPData) {
  803. pPrevCSMPData = pCurCSMPData;
  804. pCurCSMPData = pCurCSMPData->pNextCSMPData;
  805. }
  806. ASSERT(pPrevCSMPData);
  807. //
  808. // Free all the allocated cached standard mono pattern bitmap for
  809. // this group
  810. //
  811. pCurCSMPBmp = pCurCSMPData->pCSMPBmpHead;
  812. DBGP_IF(DBGP_CACHED_SMP,
  813. DBGP(">>FindCSMP: CSMPCount >= %u, Free pLast=%p"
  814. ARGU(MAX_CSMP_COUNT) ARGPTR(pCurCSMPData)));
  815. while (hData = (HLOCAL)pCurCSMPBmp) {
  816. pCurCSMPBmp = pCurCSMPBmp->pNextCSMPBmp;
  817. DBGP_IF(DBGP_CACHED_SMP,
  818. DBGP(">>FindCSMP: Free pLastCSMPBmp=%p" ARGPTR(hData)));
  819. if (HTFreeMem(hData)) {
  820. ASSERTMSG(">>FindCSMP: HTFreeMem(pCurCSMBmp) Failed", FALSE);
  821. }
  822. }
  823. //
  824. // Now free the header for the CSMPDATA
  825. //
  826. if (HTFreeMem(pCurCSMPData)) {
  827. ASSERTMSG(">>FindCSMP: HTFreeMem(pLastCSMPData) Failed", FALSE);
  828. }
  829. pPrevCSMPData->pNextCSMPData = NULL;
  830. --HTGlobal.CSMPCount;
  831. }
  832. if (pCurCSMPData = (PCSMPDATA)HTAllocMem((LPVOID)NULL,
  833. HTMEM_CurCSMPData,
  834. NONZEROLPTR,
  835. sizeof(CSMPDATA))) {
  836. //
  837. // Make this one as the link list head
  838. //
  839. pCurCSMPData->Checksum = Checksum;
  840. pCurCSMPData->pNextCSMPData = HTGlobal.pCSMPDataHead;
  841. pCurCSMPData->pCSMPBmpHead = NULL;
  842. HTGlobal.pCSMPDataHead = pCurCSMPData;
  843. ++HTGlobal.CSMPCount;
  844. DBGP_IF(DBGP_CACHED_SMP,
  845. DBGP(" >>FindCSMP: Add CSMPDATA, UsedCount=%u, pHead=%p"
  846. ARGU(HTGlobal.CSMPCount) ARGPTR(pCurCSMPData)));
  847. } else {
  848. DBGMSG(" >>FindCSMP: HTAllocMem(CSMPDATA) Failed");
  849. }
  850. }
  851. //
  852. // Do allocate new pattern only if we have header
  853. //
  854. if (pCurCSMPData) {
  855. STDMONOPATTERN SMP;
  856. DWORD Size;
  857. SMP.Flags = SMP_TOPDOWN;
  858. SMP.ScanLineAlignBytes = (BYTE)sizeof(BYTE);
  859. SMP.PatternIndex = (BYTE)PatternIndex;
  860. SMP.LineWidth = DEFAULT_SMP_LINE_WIDTH;
  861. SMP.LinesPerInch = DEFAULT_SMP_LINES_PER_INCH;
  862. SMP.pPattern = NULL;
  863. //
  864. // Find out the size for the pattern bitmap (BYTE Aligned)
  865. //
  866. Size = (DWORD)CreateStandardMonoPattern(pDCI, &SMP) +
  867. (DWORD)sizeof(CSMPBMP);
  868. DBGP_IF(DBGP_CACHED_SMP,
  869. DBGP(">>FindCSMP: Add PatternIndex=%u, sz=%ld, DPI(X=%u, Y=%u, P=%u)"
  870. ARGU(PatternIndex)
  871. ARGU(Size)
  872. ARGU(pDCI->DeviceResXDPI)
  873. ARGU(pDCI->DeviceResYDPI)
  874. ARGU(pDCI->DevPelRatio)));
  875. if (pCurCSMPBmp = (PCSMPBMP)HTAllocMem(NULL,
  876. HTMEM_CurCSMPBmp,
  877. NONZEROLPTR,
  878. Size)) {
  879. SMP.pPattern = (LPBYTE)pCurCSMPBmp + sizeof(CSMPBMP);
  880. CreateStandardMonoPattern(pDCI, &SMP);
  881. //
  882. // Make this pattern index as link list head
  883. //
  884. pCurCSMPBmp->pNextCSMPBmp = pCurCSMPData->pCSMPBmpHead;
  885. pCurCSMPBmp->PatternIndex = (WORD)PatternIndex;
  886. pCurCSMPBmp->cxPels = (WORD)SMP.cxPels;
  887. pCurCSMPBmp->cyPels = (WORD)SMP.cyPels;
  888. pCurCSMPBmp->cxBytes = (WORD)SMP.BytesPerScanLine;
  889. pCurCSMPData->pCSMPBmpHead = pCurCSMPBmp;
  890. return(pCurCSMPBmp);
  891. } else {
  892. ASSERTMSG(" >>FindCSMP: HTAllocMem(CSMPBMP) Failed", FALSE);
  893. }
  894. }
  895. RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
  896. return(NULL);
  897. }
  898. LONG
  899. HTENTRY
  900. GetCachedSMP(
  901. PDEVICECOLORINFO pDCI,
  902. PSTDMONOPATTERN pSMP
  903. )
  904. /*++
  905. Routine Description:
  906. This function will try to find the cached DEVICECOLORINFO and put the
  907. cached data to the pDCI
  908. Arguments:
  909. pDCI - Pointer to current device color info
  910. pSMP - Pointer to the STDMONOPATTERN data structure, if PatIndex is
  911. < CACHED_SMP_COUNT or, its not default size then it will be
  912. computed on the fly.
  913. Return Value:
  914. The size of the SMP pattern.
  915. Author:
  916. 01-May-1992 Fri 13:10:14 created -by- Daniel Chou (danielc)
  917. Revision History:
  918. --*/
  919. {
  920. LONG SizeRet = 0;
  921. UINT PatIndex;
  922. if (!(pSMP->LineWidth)) {
  923. pSMP->LineWidth = DEFAULT_SMP_LINE_WIDTH;
  924. }
  925. if (!(pSMP->LinesPerInch)) {
  926. pSMP->LinesPerInch = DEFAULT_SMP_LINES_PER_INCH;
  927. }
  928. if (((PatIndex = (UINT)pSMP->PatternIndex) < HT_SMP_PERCENT_SCREEN_START) &&
  929. (pSMP->LineWidth == DEFAULT_SMP_LINE_WIDTH) &&
  930. (pSMP->LinesPerInch == DEFAULT_SMP_LINES_PER_INCH)) {
  931. PCSMPBMP pCSMPBmp;
  932. if (pCSMPBmp = FindCachedSMP(pDCI, PatIndex)) {
  933. CSMPBMP CSMPBmp;
  934. LPBYTE pPatRet;
  935. LPBYTE pPat;
  936. WORD cxBytesRet;
  937. CSMPBmp = *pCSMPBmp;
  938. pPat = (LPBYTE)pCSMPBmp + sizeof(CSMPBMP);
  939. pSMP->cxPels = CSMPBmp.cxPels;
  940. pSMP->cyPels = CSMPBmp.cyPels;
  941. cxBytesRet =
  942. pSMP->BytesPerScanLine = (WORD)
  943. ComputeBytesPerScanLine((UINT)BMF_1BPP,
  944. (UINT)pSMP->ScanLineAlignBytes,
  945. (DWORD)CSMPBmp.cxPels);
  946. SizeRet = (LONG)cxBytesRet * (LONG)CSMPBmp.cyPels;
  947. if (pPatRet = pSMP->pPattern) {
  948. INT cxBytes;
  949. INT PatInc;
  950. WORD Flags;
  951. PatInc =
  952. cxBytes = (INT)CSMPBmp.cxBytes;
  953. Flags = pSMP->Flags;
  954. DBGP_IF(DBGP_CACHED_DCI,
  955. DBGP(">> GetCSMP: *COPY* [%2u:%ux%u] @%u(%ld) -> @%u(%u) [%s] [%c=K]"
  956. ARGU(PatIndex)
  957. ARGU(CSMPBmp.cxPels)
  958. ARGU(CSMPBmp.cyPels)
  959. ARGU(cxBytes)
  960. ARGU((LONG)cxBytes * (LONG)CSMPBmp.cyPels)
  961. ARGU(cxBytesRet)
  962. ARGU(SizeRet)
  963. ARG((Flags & SMP_TOPDOWN) ? "TOP DOWN" : "BOTTOM UP ")
  964. ARG((Flags & SMP_0_IS_BLACK) ? '0' : '1')));
  965. //
  966. // Start copying the cached pattern
  967. //
  968. if (!(Flags & SMP_TOPDOWN)) {
  969. pPat += (LONG)cxBytes * (LONG)(CSMPBmp.cyPels - 1);
  970. PatInc = -PatInc;
  971. }
  972. while (CSMPBmp.cyPels--) {
  973. CopyMemory(pPatRet, pPat, cxBytes);
  974. pPatRet += cxBytesRet;
  975. pPat += PatInc;
  976. }
  977. if (Flags & SMP_0_IS_BLACK) {
  978. LONG Count = SizeRet;
  979. pPatRet = pSMP->pPattern;
  980. while (Count--) {
  981. *pPatRet++ ^= 0xff;
  982. }
  983. }
  984. }
  985. RELEASE_HTMUTEX(HTGlobal.HTMutexCSMP);
  986. }
  987. } else {
  988. DBGP_IF(DBGP_CACHED_SMP,
  989. DBGP(">> GetCSMP: NO CACHED FOR LineWidth=%u, LinesPerInch=%u"
  990. ARGU(pSMP->LineWidth) ARGU(pSMP->LinesPerInch)));
  991. }
  992. if (!SizeRet) {
  993. SizeRet = CreateStandardMonoPattern(pDCI, pSMP);
  994. }
  995. return(SizeRet);
  996. }
  997. #if DO_CACHE_DCI
  998. DWORD
  999. HTENTRY
  1000. ComputeHTINITINFOChecksum(
  1001. PDEVICECOLORINFO pDCI,
  1002. PHTINITINFO pHTInitInfo
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This function compute 32-bit checksum for the HTINITINFO data structure
  1007. passed
  1008. Arguments:
  1009. pDCI - Pointer to the DCI
  1010. pHTInitInfo - Pointer to the HTINITINFO5 data structure
  1011. Return Value:
  1012. 32-bit checksum
  1013. Author:
  1014. 29-Apr-1992 Wed 18:44:42 created -by- Daniel Chou (danielc)
  1015. 11-Feb-1997 Tue 12:54:50 updated -by- Daniel Chou (danielc)
  1016. Changed using HTINITINFO5
  1017. Revision History:
  1018. --*/
  1019. {
  1020. DWORD Checksum;
  1021. WORD wBuf[12];
  1022. Checksum = ComputeHTCell((WORD)pHTInitInfo->HTPatternIndex,
  1023. pHTInitInfo->pHalftonePattern,
  1024. NULL);
  1025. DBGP_IF(DBGP_CACHED_DCI,
  1026. DBGP(" HTPATTERN Checksum= %08lx" ARGDW(Checksum)));
  1027. wBuf[0] = (WORD)'HT';
  1028. wBuf[1] = (WORD)pHTInitInfo->Flags;
  1029. wBuf[2] = (WORD)(pDCI->HTInitInfoChecksum >> 16);
  1030. wBuf[3] = (WORD)pHTInitInfo->DeviceResXDPI;
  1031. wBuf[4] = (WORD)pHTInitInfo->DeviceResYDPI;
  1032. wBuf[5] = (WORD)pHTInitInfo->DevicePelsDPI;
  1033. wBuf[6] = (WORD)(pDCI->HTInitInfoChecksum & 0xffff);
  1034. wBuf[7] = (WORD)pHTInitInfo->DevicePowerGamma;
  1035. wBuf[8] = (WORD)0x1234;
  1036. if (pHTInitInfo->Version > HTINITINFO_VERSION2) {
  1037. wBuf[9] = (WORD)pHTInitInfo->DeviceRGamma;
  1038. wBuf[10] = (WORD)pHTInitInfo->DeviceGGamma;
  1039. wBuf[11] = (WORD)pHTInitInfo->DeviceBGamma;
  1040. } else {
  1041. wBuf[9] = 0x1234;
  1042. wBuf[10] = 0xfedc;
  1043. wBuf[11] = 0xabcd;
  1044. }
  1045. Checksum = ComputeChecksum((LPBYTE)&(wBuf[0]), Checksum, sizeof(wBuf));
  1046. DBGP_IF(DBGP_CACHED_DCI,
  1047. DBGP(" HTINITINFO Checksum= %08lx [%08lx]"
  1048. ARGDW(Checksum) ARGDW(pDCI->HTInitInfoChecksum)));
  1049. if (pHTInitInfo->pInputRGBInfo) {
  1050. Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pInputRGBInfo,
  1051. Checksum,
  1052. sizeof(CIEINFO));
  1053. DBGP_IF(DBGP_CACHED_DCI,
  1054. DBGP(" RGBINFO Checksum= %08lx" ARGDW(Checksum)));
  1055. }
  1056. if (pHTInitInfo->pDeviceCIEInfo) {
  1057. Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pDeviceCIEInfo,
  1058. Checksum,
  1059. sizeof(CIEINFO));
  1060. DBGP_IF(DBGP_CACHED_DCI,
  1061. DBGP(" CIEINFO Checksum= %08lx" ARGDW(Checksum)));
  1062. }
  1063. if (pHTInitInfo->pDeviceSolidDyesInfo) {
  1064. Checksum = ComputeChecksum((LPBYTE)pHTInitInfo->pDeviceSolidDyesInfo,
  1065. Checksum,
  1066. sizeof(SOLIDDYESINFO));
  1067. DBGP_IF(DBGP_CACHED_DCI,
  1068. DBGP(" SOLIDDYE Checksum= %08lx" ARGDW(Checksum)));
  1069. }
  1070. DBGP_IF(DBGP_CACHED_DCI,
  1071. DBGP("----------------- FINAL Checksum= %08lx" ARGDW(Checksum)));
  1072. return(pDCI->HTInitInfoChecksum = Checksum);
  1073. }
  1074. #endif
  1075. HTCALLBACKFUNCTION
  1076. DefaultHTCallBack(
  1077. PHTCALLBACKPARAMS pHTCallBackParams
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. This stuff function is provided when caller do not specified the halftone
  1082. callback function.
  1083. Arguments:
  1084. pHTCallBackParams - Pointer to the PHTCALLBACKPARAMS
  1085. Return Value:
  1086. always return false for the caller.
  1087. Author:
  1088. 18-Mar-1992 Wed 12:28:13 created -by- Daniel Chou (danielc)
  1089. Revision History:
  1090. --*/
  1091. {
  1092. UNREFERENCED_PARAMETER(pHTCallBackParams);
  1093. return(FALSE);
  1094. }
  1095. #define FLIP_COORD(m, a) (a) = ((m) << 1) - (a)
  1096. VOID
  1097. HTENTRY
  1098. GetCIEPrims(
  1099. PCIEINFO pCIEInfo,
  1100. PCIEPRIMS pCIEPrims,
  1101. PCIEINFO pDefCIEInfo,
  1102. BOOL FlipWhite
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. This function take CIEINFO data structure and converted it to the CIEPRIMS
  1107. internal data type
  1108. Arguments:
  1109. pCIEInfo - Pointer to the CIEINFO data structure for conversion,
  1110. if this pointer is NULL then DefCIEPrimsIndex is used
  1111. to index into DefaultCIEPrims[].
  1112. pCIEPrims - Pointer to the CIEPRIMS data structure
  1113. pDefCIEInfo - Pointer to the CIEINFO for the default
  1114. Return Value:
  1115. BOOL If it is standard CIE Info
  1116. Author:
  1117. 20-Apr-1993 Tue 01:14:23 created -by- Daniel Chou (danielc)
  1118. Revision History:
  1119. 06-Oct-2000 Fri 18:01:40 updated -by- Daniel Chou (danielc)
  1120. fix bug: Move FlipWhite to the outer loop so it will compute even in
  1121. default CIEINFO situation
  1122. --*/
  1123. {
  1124. CIEINFO CIEInfo;
  1125. BOOL UseDefCIEInfo = TRUE;
  1126. LONG Diff;
  1127. if (pCIEInfo) {
  1128. CIEInfo = *pCIEInfo;
  1129. if ((CIEInfo.Red.x < CIE_x_MIN) ||
  1130. (CIEInfo.Red.x > CIE_x_MAX) ||
  1131. (CIEInfo.Red.y < CIE_y_MIN) ||
  1132. (CIEInfo.Red.y > CIE_y_MAX) ||
  1133. (CIEInfo.Green.x < CIE_x_MIN) ||
  1134. (CIEInfo.Green.x > CIE_x_MAX) ||
  1135. (CIEInfo.Green.y < CIE_y_MIN) ||
  1136. (CIEInfo.Green.y > CIE_y_MAX) ||
  1137. (CIEInfo.Blue.x < CIE_x_MIN) ||
  1138. (CIEInfo.Blue.x > CIE_x_MAX) ||
  1139. (CIEInfo.Blue.y < CIE_y_MIN) ||
  1140. (CIEInfo.Blue.y > CIE_y_MAX) ||
  1141. (CIEInfo.AlignmentWhite.x < CIE_x_MIN) ||
  1142. (CIEInfo.AlignmentWhite.x > CIE_x_MAX) ||
  1143. (CIEInfo.AlignmentWhite.y < CIE_y_MIN) ||
  1144. (CIEInfo.AlignmentWhite.y > CIE_y_MAX) ||
  1145. (CIEInfo.AlignmentWhite.Y < (UDECI4)2500) ||
  1146. (CIEInfo.AlignmentWhite.Y > (UDECI4)60000)) {
  1147. NULL;
  1148. } else {
  1149. UseDefCIEInfo = FALSE;
  1150. }
  1151. }
  1152. if (UseDefCIEInfo) {
  1153. CIEInfo = *pDefCIEInfo;
  1154. }
  1155. if (FlipWhite) {
  1156. FLIP_COORD(pDefCIEInfo->AlignmentWhite.x,
  1157. CIEInfo.AlignmentWhite.x);
  1158. FLIP_COORD(pDefCIEInfo->AlignmentWhite.y,
  1159. CIEInfo.AlignmentWhite.y);
  1160. }
  1161. pCIEPrims->r.x = UDECI4ToFD6(CIEInfo.Red.x);
  1162. pCIEPrims->r.y = UDECI4ToFD6(CIEInfo.Red.y);
  1163. pCIEPrims->g.x = UDECI4ToFD6(CIEInfo.Green.x);
  1164. pCIEPrims->g.y = UDECI4ToFD6(CIEInfo.Green.y);
  1165. pCIEPrims->b.x = UDECI4ToFD6(CIEInfo.Blue.x);
  1166. pCIEPrims->b.y = UDECI4ToFD6(CIEInfo.Blue.y);
  1167. pCIEPrims->w.x = UDECI4ToFD6(CIEInfo.AlignmentWhite.x);
  1168. pCIEPrims->w.y = UDECI4ToFD6(CIEInfo.AlignmentWhite.y);
  1169. pCIEPrims->Yw = UDECI4ToFD6(CIEInfo.AlignmentWhite.Y);
  1170. }
  1171. LONG
  1172. APIENTRY
  1173. HT_LOADDS
  1174. HT_CreateDeviceHalftoneInfo(
  1175. PHTINITINFO pHTInitInfo,
  1176. PPDEVICEHALFTONEINFO ppDeviceHalftoneInfo
  1177. )
  1178. /*++
  1179. Routine Description:
  1180. This function initialize a device to the halftone dll, it calculate all
  1181. the necessary parameters for the device and return a pointer points to
  1182. the DEVICEHALFTONEINFO data structure back to the caller.
  1183. NOTE: return pointer will not be particulary anchor to a single physucal
  1184. device, but rather to a group of physical devices, that is if the
  1185. caller has simillar devices which share the same characteristics
  1186. then it may use the same pointer to halftone the bitmap.
  1187. Arguments:
  1188. pHTInitInfo - Pointer to the HTINITINFO data structure which
  1189. describe the device characteristics and other
  1190. initialzation requests.
  1191. ppDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO pointer, if
  1192. content of this pointer is not NULL then halftone
  1193. dll assume the caller has previously cached
  1194. DEVICEHALFTONEINFO data pointed by it, if it
  1195. is NULL then halftone dll compute all the
  1196. DEVICEHALFTONEINFO datas for newly created
  1197. halftone info. for the device. (see following
  1198. 'Return Value' for more detail)
  1199. Return Value:
  1200. The return value will be greater than 0L if the function sucessfully, and
  1201. it will be an error code (less than or equal to 0) if function failed.
  1202. Return value greater than 0
  1203. 1. The pointer location points by the ppDeviceHalftoneInfo will be
  1204. updated to stored the pointer which points to the DEVICEHALFTONEINFO
  1205. data structure for later any HT_xxxx() api calls.
  1206. 2. The Return value is the total bytes the caller can saved and used
  1207. as cached DeviceHalftoneInfo for next time calling this function,
  1208. the saved area is started from *(ppDeviceHalftoneInfo) and has
  1209. size in bytes as return value.
  1210. NOTE: if caller passed a pointer pointed by ppDeviceHalftoneInfo and
  1211. the return value is greater than zero then it signal that it
  1212. passed DEVICEHALFTONEINFO pointer is not correct of data has
  1213. been changed from HTINITINFO data structure, the caller can
  1214. continue to save the newly created DEVICEHALFTONEINFO cached
  1215. data.
  1216. In any cases the caller's passed pointer stored in the
  1217. ppDeviceHalftoneInfo is overwritten by newly created
  1218. DEVICEHALFTONEINFO data structure pointer.
  1219. Return value equal to 0
  1220. 1. The caller passed pointer *(ppDeviceHalftoneInfo) is sucessfully
  1221. used as new device halftone info
  1222. 2. The pointer location points by the ppDeviceHalftoneInfo will be
  1223. updated to stored the new pointer which points to the
  1224. DEVICEHALFTONEINFO data structure for later any HT_xxxx() api calls.
  1225. NOTE: The caller's passed pointer stored in the ppDeviceHalftoneInfo
  1226. is overwritten by newly created DEVICEHALFTONEINFO data structure
  1227. pointer.
  1228. Return value less than or equal to zero
  1229. The function failed, the storage points by the ppDeviceHalftoneInfo is
  1230. undefined.
  1231. This function may return following error codes.
  1232. HTERR_INSUFFICIENT_MEMORY - Not enough memory for halftone
  1233. process.
  1234. HTERR_HTPATTERN_SIZE_TOO_BIG - Caller defined halftone pattern's
  1235. width or height is excessed limit.
  1236. HTERR_INVALID_HALFTONEPATTERN - One or more HALFTONEPATTERN data
  1237. structure field specified invalid
  1238. values.
  1239. Note: The first field in the DEVICEHALFTONEINFO (DeviceOwnData) is a 32-bit
  1240. area which will be set to 0L upon sucessful returned, the caller can
  1241. put any data in this field.
  1242. Author:
  1243. 05-Feb-1991 Tue 10:54:32 created -by- Daniel Chou (danielc)
  1244. Revision History:
  1245. 05-Jun-1991 Wed 10:22:07 updated -by- Daniel Chou (danielc)
  1246. Fixed the typing errors for halftone pattern default
  1247. --*/
  1248. {
  1249. PHT_DHI pHT_DHI;
  1250. PDEVICECOLORINFO pDCI;
  1251. HTINITINFO HTInitInfo;
  1252. BOOL UseCurNTDefault;
  1253. FD6 DevPelRatio;
  1254. WORD ExtraDCIF;
  1255. DWORD dwBuf[6];
  1256. #define _RegDataIdx ((DWORD)(dwBuf[0]))
  1257. #define _MaxMulDiv ((FD6)(dwBuf[0]))
  1258. #define _cC ((DWORD)(dwBuf[1]))
  1259. #define _cM ((DWORD)(dwBuf[2]))
  1260. #define _cY ((DWORD)(dwBuf[3]))
  1261. #define _MaxCMY ((DWORD)(dwBuf[4]))
  1262. #define _Idx ((DWORD)(dwBuf[5]))
  1263. DBGP_IF(DBGP_CACHED_DCI,
  1264. DBGP("\n********* HT_CreateDeviceHalftoneInfo *************\n"));
  1265. ZeroMemory(&HTInitInfo, sizeof(HTINITINFO));
  1266. //
  1267. // Now check if we have valid data
  1268. //
  1269. if (pHTInitInfo->Version == (DWORD)HTINITINFO_VERSION2) {
  1270. HTInitInfo.Version = sizeof(HTINITINFO) - HTINITINFO_V3_CB_EXTRA;
  1271. } else if (pHTInitInfo->Version == (DWORD)HTINITINFO_VERSION) {
  1272. HTInitInfo.Version = sizeof(HTINITINFO);
  1273. } else {
  1274. HTAPI_RET(HTAPI_IDX_CREATE_DHI, HTERR_WRONG_VERSION_HTINITINFO);
  1275. }
  1276. CopyMemory(&HTInitInfo, pHTInitInfo, HTInitInfo.Version);
  1277. DBGP_IF(DBGP_CACHED_DCI,
  1278. DBGP("*** Allocate HT_DHI(%ld) ***" ARGDW(sizeof(HT_DHI))));
  1279. if (!(pHT_DHI = (PHT_DHI)HTAllocMem(NULL,
  1280. HTMEM_HT_DHI,
  1281. LPTR,
  1282. sizeof(HT_DHI)))) {
  1283. HTAPI_RET(HTAPI_IDX_CREATE_DHI, HTERR_INSUFFICIENT_MEMORY);
  1284. }
  1285. pDCI = &(pHT_DHI->DCI);
  1286. pDCI->HalftoneDLLID = HALFTONE_DLL_ID;
  1287. if (!(pDCI->HTMutex = CREATE_HTMUTEX())) {
  1288. DBGMSG("InitHTInternalData: CREATE_HTMUTEX(pDCI->HTMutex) failed!");
  1289. HTFreeMem(pHT_DHI);
  1290. HTAPI_RET(HTAPI_IDX_CREATE_DHI, (HTERR_INTERNAL_ERRORS_START - 1000));
  1291. }
  1292. if (!(pDCI->HTCallBackFunction = HTInitInfo.HTCallBackFunction)) {
  1293. pDCI->HTCallBackFunction = DefaultHTCallBack;
  1294. }
  1295. HTInitInfo.Flags &= HIF_BIT_MASK;
  1296. // ****************************************************************
  1297. // * We want to check to see if this is a old data, if yes then *
  1298. // * update the caller to default *
  1299. // ****************************************************************
  1300. //
  1301. pDCI->HTInitInfoChecksum = HTINITINFO_INITIAL_CHECKSUM;
  1302. if ((!HTInitInfo.pDeviceCIEInfo) ||
  1303. (HTInitInfo.pDeviceCIEInfo->Cyan.Y != (UDECI4)VALID_YC)) {
  1304. //
  1305. // Let's munge around the printer info, to see if its an old def,
  1306. // if yes, then we now make this all into NT4.00 default
  1307. //
  1308. DBGP_IF(DBGP_CACHED_DCI,
  1309. DBGP("HT: *WARNING* Update Old Default COLORINFO to NT5.00 DEFAULT"));
  1310. HTInitInfo.pDeviceCIEInfo = NULL;
  1311. UseCurNTDefault = TRUE;
  1312. dwBuf[0] = (DWORD)'NTHT';
  1313. dwBuf[1] = (DWORD)'2000';
  1314. dwBuf[2] = (DWORD)'Dan.';
  1315. dwBuf[3] = (DWORD)'Chou';
  1316. pDCI->HTInitInfoChecksum = ComputeChecksum((LPBYTE)&dwBuf[0],
  1317. pDCI->HTInitInfoChecksum,
  1318. sizeof(dwBuf[0]) * 4);
  1319. } else {
  1320. UseCurNTDefault = FALSE;
  1321. }
  1322. DevPelRatio = (FD6)HTInitInfo.DevicePelsDPI;
  1323. DBGP_IF(DBGP_DEVPELSDPI,
  1324. DBGP("Passed DevicePelsDPI=%08lx" ARGDW(DevPelRatio)));
  1325. if ((HTInitInfo.DeviceRGamma == (UDECI4)0xFFFF) &&
  1326. (HTInitInfo.DeviceGGamma == (UDECI4)0xFFFF) &&
  1327. (HTInitInfo.DeviceBGamma == (UDECI4)0xFFFF)) {
  1328. ExtraDCIF = DCIF_FORCE_ICM;
  1329. } else {
  1330. ExtraDCIF = 0;
  1331. }
  1332. if ((HTInitInfo.DeviceRGamma < (UDECI4)MIN_RGB_GAMMA) ||
  1333. (HTInitInfo.DeviceRGamma > (UDECI4)MAX_RGB_GAMMA) ||
  1334. (HTInitInfo.DeviceGGamma < (UDECI4)MIN_RGB_GAMMA) ||
  1335. (HTInitInfo.DeviceGGamma > (UDECI4)MAX_RGB_GAMMA) ||
  1336. (HTInitInfo.DeviceBGamma < (UDECI4)MIN_RGB_GAMMA) ||
  1337. (HTInitInfo.DeviceBGamma > (UDECI4)MAX_RGB_GAMMA)) {
  1338. HTInitInfo.DeviceRGamma =
  1339. HTInitInfo.DeviceGGamma =
  1340. HTInitInfo.DeviceBGamma = UDECI4_1;
  1341. }
  1342. //
  1343. // Compute HTInitInfoChecksum, and check if we have any cached data
  1344. //
  1345. #if DO_CACHE_DCI
  1346. ComputeHTINITINFOChecksum(pDCI, &HTInitInfo);
  1347. if (!GetCachedDCI(pDCI)) {
  1348. #else
  1349. if (TRUE) {
  1350. #endif
  1351. LONG Result;
  1352. //
  1353. // Now start to checking the init information
  1354. //
  1355. pDCI->Flags = (WORD)((HTInitInfo.Flags & HIF_SQUARE_DEVICE_PEL) ?
  1356. DCIF_SQUARE_DEVICE_PEL : 0);
  1357. if ((!(pDCI->DeviceResXDPI = HTInitInfo.DeviceResXDPI)) ||
  1358. (!(pDCI->DeviceResYDPI = HTInitInfo.DeviceResYDPI))) {
  1359. pDCI->DeviceResXDPI =
  1360. pDCI->DeviceResYDPI = 300;
  1361. DevPelRatio = 0;
  1362. }
  1363. if (DevPelRatio & 0x8000) {
  1364. //
  1365. // This is a percentage ie. 1000 = 100.0%, 960=96.0%,
  1366. // on the DeviceResXDPI, Maximum number accepted is 300.0%
  1367. // The larger the percetage the larger the dot size and smaller
  1368. // the percentage the smaller the dot size, if specified as 1000
  1369. // which is 100.0% then it has same size as its X resolution
  1370. // The range is 33.3% to 1500%
  1371. //
  1372. DevPelRatio &= 0x7FFF;
  1373. if ((DevPelRatio > MAX_RES_PERCENT) ||
  1374. (DevPelRatio < MIN_RES_PERCENT)) {
  1375. DBGP_IF(DBGP_DEVPELSDPI,
  1376. DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (PERCENT) set to DEFAULT=1.0"
  1377. ARGDW(DevPelRatio)));
  1378. DevPelRatio = FD6_1;
  1379. } else {
  1380. DBGP_IF(DBGP_DEVPELSDPI,
  1381. DBGP("*** Percentage INPUT DevicePelsDPI=%ld *** "
  1382. ARGDW(DevPelRatio)));
  1383. DevPelRatio *= 1000;
  1384. DBGP_IF(DBGP_DEVPELSDPI,
  1385. DBGP("*** Percentage OUTPUT DevPelRatio=%s *** "
  1386. ARGFD6(DevPelRatio, 1, 6)));
  1387. }
  1388. } else {
  1389. if ((DevPelRatio > (pDCI->DeviceResXDPI * 3)) ||
  1390. (DevPelRatio > (pDCI->DeviceResYDPI * 3))) {
  1391. DBGP_IF(DBGP_DEVPELSDPI,
  1392. DBGP("HT: *WARNING* Invalid DevicePelsDPI=%ld (RES) set to DEFAULT=0"
  1393. ARGDW(DevPelRatio)));
  1394. DevPelRatio = 0;
  1395. }
  1396. if (DevPelRatio) {
  1397. dwBuf[0] = (((DWORD)pDCI->DeviceResXDPI *
  1398. (DWORD)pDCI->DeviceResXDPI) +
  1399. ((DWORD)pDCI->DeviceResYDPI *
  1400. (DWORD)pDCI->DeviceResYDPI));
  1401. dwBuf[1] = ((DWORD)DevPelRatio * (DWORD)DevPelRatio * 2);
  1402. DevPelRatio = SquareRoot(DivFD6(dwBuf[0], dwBuf[1]));
  1403. } else {
  1404. DevPelRatio = FD6_1;
  1405. }
  1406. }
  1407. //
  1408. // If the DevicePelsDPI is out of range then we will make it 0 (same as
  1409. // device resolution), so it can continue to work
  1410. //
  1411. if (HTInitInfo.Flags & HIF_ADDITIVE_PRIMS) {
  1412. pDCI->ClrXFormBlock.ColorSpace = CIELUV_1976;
  1413. pDCI->Flags |= DCIF_ADDITIVE_PRIMS;
  1414. } else {
  1415. pDCI->ClrXFormBlock.ColorSpace = CIELAB_1976;
  1416. #if DO_DYES_CORRECTION
  1417. pDCI->Flags |= DCIF_NEED_DYES_CORRECTION;
  1418. #endif
  1419. if (HTInitInfo.Flags & HIF_DO_DEVCLR_XFORM) {
  1420. pDCI->Flags |= DCIF_DO_DEVCLR_XFORM;
  1421. }
  1422. if (HTInitInfo.Flags & HIF_HAS_BLACK_DYE) {
  1423. pDCI->Flags |= DCIF_HAS_BLACK_DYE;
  1424. }
  1425. }
  1426. //
  1427. // Save the DevPelRatio back to PDCI
  1428. //
  1429. DBGP_IF(DBGP_DEVPELSDPI,
  1430. DBGP("*** XDPI=%ld, YDPI=%ld, DevPelRatio=%s *** "
  1431. ARGDW(pDCI->DeviceResXDPI) ARGDW(pDCI->DeviceResYDPI)
  1432. ARGFD6(DevPelRatio, 1, 6)));
  1433. pDCI->DevPelRatio = (FD6)DevPelRatio;
  1434. pDCI->ClrXFormBlock.DevGamma[0] = UDECI4ToFD6(HTInitInfo.DeviceRGamma);
  1435. pDCI->ClrXFormBlock.DevGamma[1] = UDECI4ToFD6(HTInitInfo.DeviceGGamma);
  1436. pDCI->ClrXFormBlock.DevGamma[2] = UDECI4ToFD6(HTInitInfo.DeviceBGamma);
  1437. if ((UseCurNTDefault) ||
  1438. (HTInitInfo.HTPatternIndex > HTPAT_SIZE_MAX_INDEX) ||
  1439. ((HTInitInfo.HTPatternIndex == HTPAT_SIZE_USER) &&
  1440. (HTInitInfo.pHalftonePattern == NULL))) {
  1441. if ((HTInitInfo.HTPatternIndex != HTPAT_SIZE_8x8) &&
  1442. (HTInitInfo.HTPatternIndex != HTPAT_SIZE_8x8_M)) {
  1443. HTInitInfo.HTPatternIndex = HTPAT_SIZE_DEFAULT;
  1444. }
  1445. }
  1446. if ((HTInitInfo.Flags & HIF_ADDITIVE_PRIMS) &&
  1447. (HTInitInfo.HTPatternIndex <= HTPAT_SIZE_4x4_M)) {
  1448. HTInitInfo.HTPatternIndex = DEFAULT_SCR_HTPAT_SIZE;
  1449. }
  1450. switch (HTInitInfo.Flags & (HIF_INK_HIGH_ABSORPTION |
  1451. HIF_INK_ABSORPTION_INDICES)) {
  1452. case HIF_HIGHEST_INK_ABSORPTION:
  1453. _RegDataIdx = 0;
  1454. break;
  1455. case HIF_HIGHER_INK_ABSORPTION:
  1456. _RegDataIdx = 1;
  1457. break;
  1458. case HIF_HIGH_INK_ABSORPTION:
  1459. _RegDataIdx = 2;
  1460. break;
  1461. case HIF_LOW_INK_ABSORPTION:
  1462. _RegDataIdx = 4;
  1463. break;
  1464. case HIF_LOWER_INK_ABSORPTION:
  1465. _RegDataIdx = 5;
  1466. break;
  1467. case HIF_LOWEST_INK_ABSORPTION:
  1468. _RegDataIdx = 6;
  1469. break;
  1470. case HIF_NORMAL_INK_ABSORPTION:
  1471. default:
  1472. _RegDataIdx = 3;
  1473. break;
  1474. }
  1475. pDCI->ClrXFormBlock.RegDataIdx = (BYTE)_RegDataIdx;
  1476. GetCIEPrims(HTInitInfo.pDeviceCIEInfo,
  1477. &(pDCI->ClrXFormBlock.DevCIEPrims),
  1478. (PCIEINFO)&HT_CIE_SRGB,
  1479. TRUE);
  1480. GetCIEPrims(HTInitInfo.pInputRGBInfo,
  1481. &(pDCI->ClrXFormBlock.rgbCIEPrims),
  1482. (PCIEINFO)&HT_CIE_SRGB,
  1483. FALSE);
  1484. //
  1485. // Compute the solid dyes mixes information and its hue shifting
  1486. // correction factors.
  1487. //
  1488. if (pDCI->Flags & DCIF_NEED_DYES_CORRECTION) {
  1489. SOLIDDYESINFO SDI;
  1490. MATRIX3x3 FD6SDI;
  1491. BOOL HasDevSDI;
  1492. //
  1493. // We have make sure the solid dyes info passed from the caller can be
  1494. // inversed, if not we will use our default
  1495. //
  1496. if (HasDevSDI = (HTInitInfo.pDeviceSolidDyesInfo) ? TRUE : FALSE) {
  1497. SDI = *(HTInitInfo.pDeviceSolidDyesInfo);
  1498. if ((SDI.MagentaInCyanDye > (UDECI4)9000) ||
  1499. (SDI.YellowInCyanDye > (UDECI4)9000) ||
  1500. (SDI.CyanInMagentaDye > (UDECI4)9000) ||
  1501. (SDI.YellowInMagentaDye > (UDECI4)9000) ||
  1502. (SDI.CyanInYellowDye > (UDECI4)9000) ||
  1503. (SDI.MagentaInYellowDye > (UDECI4)9000)) {
  1504. HasDevSDI = FALSE;
  1505. } else if ((SDI.MagentaInCyanDye == UDECI4_0) &&
  1506. (SDI.YellowInCyanDye == UDECI4_0) &&
  1507. (SDI.CyanInMagentaDye == UDECI4_0) &&
  1508. (SDI.YellowInMagentaDye == UDECI4_0) &&
  1509. (SDI.CyanInYellowDye == UDECI4_0) &&
  1510. (SDI.MagentaInYellowDye == UDECI4_0)) {
  1511. //
  1512. // Do not need any correction if it all zeros
  1513. //
  1514. pDCI->Flags &= (WORD)(~DCIF_NEED_DYES_CORRECTION);
  1515. }
  1516. } else {
  1517. pDCI->Flags &= (WORD)(~DCIF_NEED_DYES_CORRECTION);
  1518. }
  1519. if (pDCI->Flags & DCIF_NEED_DYES_CORRECTION) {
  1520. #define PDCI_CMYDYEMASKS pDCI->ClrXFormBlock.CMYDyeMasks
  1521. MULDIVPAIR MDPairs[4];
  1522. FD6 Y;
  1523. if ((UseCurNTDefault) || (!HasDevSDI)) {
  1524. SDI = DefaultSolidDyesInfo;
  1525. }
  1526. FD6SDI.m[0][1] = UDECI4ToFD6(SDI.CyanInMagentaDye);
  1527. FD6SDI.m[0][2] = UDECI4ToFD6(SDI.CyanInYellowDye);
  1528. FD6SDI.m[1][0] = UDECI4ToFD6(SDI.MagentaInCyanDye);
  1529. FD6SDI.m[1][2] = UDECI4ToFD6(SDI.MagentaInYellowDye);
  1530. FD6SDI.m[2][0] = UDECI4ToFD6(SDI.YellowInCyanDye);
  1531. FD6SDI.m[2][1] = UDECI4ToFD6(SDI.YellowInMagentaDye);
  1532. FD6SDI.m[0][0] =
  1533. FD6SDI.m[1][1] =
  1534. FD6SDI.m[2][2] = FD6_1;
  1535. ComputeInverseMatrix3x3(&FD6SDI, &(PDCI_CMYDYEMASKS));
  1536. if (!(pDCI->Flags & DCIF_HAS_BLACK_DYE)) {
  1537. MAKE_MULDIV_INFO(MDPairs, 3, MULDIV_NO_DIVISOR);
  1538. MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Xr(PDCI_CMYDYEMASKS), FD6_1);
  1539. MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Xg(PDCI_CMYDYEMASKS), FD6_1);
  1540. MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Xb(PDCI_CMYDYEMASKS), FD6_1);
  1541. Y = FD6_1 - MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
  1542. pDCI->PrimAdj.DevCSXForm.Yrgb.R);
  1543. MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Yr(PDCI_CMYDYEMASKS), FD6_1);
  1544. MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Yg(PDCI_CMYDYEMASKS), FD6_1);
  1545. MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Yb(PDCI_CMYDYEMASKS), FD6_1);
  1546. Y -= MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
  1547. pDCI->PrimAdj.DevCSXForm.Yrgb.G);
  1548. MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Zr(PDCI_CMYDYEMASKS), FD6_1);
  1549. MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Zg(PDCI_CMYDYEMASKS), FD6_1);
  1550. MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Zb(PDCI_CMYDYEMASKS), FD6_1);
  1551. Y -= MulFD6(FD6_1 - MulDivFD6Pairs(MDPairs),
  1552. pDCI->PrimAdj.DevCSXForm.Yrgb.B);
  1553. DBGP_IF(DBGP_DYECORRECTION,
  1554. DBGP("DYE: Maximum Y=%s, Make Luminance from %s to %s, Turn ON DCIF_HAS_BLACK_DYE"
  1555. ARGFD6(Y, 1, 6)
  1556. ARGFD6(pDCI->ClrXFormBlock.DevCIEPrims.Yw, 1, 6)
  1557. ARGFD6(MulFD6(Y,
  1558. pDCI->ClrXFormBlock.DevCIEPrims.Yw),
  1559. 1, 6)));
  1560. pDCI->Flags |= DCIF_HAS_BLACK_DYE;
  1561. pDCI->ClrXFormBlock.DevCIEPrims.Yw =
  1562. MulFD6(pDCI->ClrXFormBlock.DevCIEPrims.Yw, Y);
  1563. }
  1564. DBGP_IF(DBGP_DYECORRECTION,
  1565. FD6 C;
  1566. FD6 M;
  1567. FD6 Y;
  1568. FD6 C1;
  1569. FD6 M1;
  1570. FD6 Y1;
  1571. static BYTE DyeName[] = "WCMBYGRK";
  1572. WORD Loop = 0;
  1573. DBGP("====== DyeCorrection 3x3 Matrix =======");
  1574. DBGP("[Cc Cm Cy] [%s %s %s] [%s %s %s]"
  1575. ARGFD6(FD6SDI.m[0][0], 2, 6)
  1576. ARGFD6(FD6SDI.m[0][1], 2, 6)
  1577. ARGFD6(FD6SDI.m[0][2], 2, 6)
  1578. ARGFD6(PDCI_CMYDYEMASKS.m[0][0], 2, 6)
  1579. ARGFD6(PDCI_CMYDYEMASKS.m[0][1], 2, 6)
  1580. ARGFD6(PDCI_CMYDYEMASKS.m[0][2], 2, 6));
  1581. DBGP("[Mc Mm My]=[%s %s %s]=[%s %s %s]"
  1582. ARGFD6(FD6SDI.m[1][0], 2, 6)
  1583. ARGFD6(FD6SDI.m[1][1], 2, 6)
  1584. ARGFD6(FD6SDI.m[1][2], 2, 6)
  1585. ARGFD6(PDCI_CMYDYEMASKS.m[1][0], 2, 6)
  1586. ARGFD6(PDCI_CMYDYEMASKS.m[1][1], 2, 6)
  1587. ARGFD6(PDCI_CMYDYEMASKS.m[1][2], 2, 6));
  1588. DBGP("[Yc Ym Yy] [%s %s %s] [%s %s %s]"
  1589. ARGFD6(FD6SDI.m[2][0], 2, 6)
  1590. ARGFD6(FD6SDI.m[2][1], 2, 6)
  1591. ARGFD6(FD6SDI.m[2][2], 2, 6)
  1592. ARGFD6(PDCI_CMYDYEMASKS.m[2][0], 2, 6)
  1593. ARGFD6(PDCI_CMYDYEMASKS.m[2][1], 2, 6)
  1594. ARGFD6(PDCI_CMYDYEMASKS.m[2][2], 2, 6));
  1595. DBGP("================================================");
  1596. MAKE_MULDIV_INFO(MDPairs, 3, MULDIV_NO_DIVISOR);
  1597. for (Loop = 0; Loop <= 7; Loop++) {
  1598. C = (FD6)((Loop & 0x01) ? FD6_1 : FD6_0);
  1599. M = (FD6)((Loop & 0x02) ? FD6_1 : FD6_0);
  1600. Y = (FD6)((Loop & 0x04) ? FD6_1 : FD6_0);
  1601. MAKE_MULDIV_PAIR(MDPairs,1,CIE_Xr(PDCI_CMYDYEMASKS),C);
  1602. MAKE_MULDIV_PAIR(MDPairs,2,CIE_Xg(PDCI_CMYDYEMASKS),M);
  1603. MAKE_MULDIV_PAIR(MDPairs,3,CIE_Xb(PDCI_CMYDYEMASKS),Y);
  1604. C1 = MulDivFD6Pairs(MDPairs);
  1605. MAKE_MULDIV_PAIR(MDPairs,1,CIE_Yr(PDCI_CMYDYEMASKS),C);
  1606. MAKE_MULDIV_PAIR(MDPairs,2,CIE_Yg(PDCI_CMYDYEMASKS),M);
  1607. MAKE_MULDIV_PAIR(MDPairs,3,CIE_Yb(PDCI_CMYDYEMASKS),Y);
  1608. M1 = MulDivFD6Pairs(MDPairs);
  1609. MAKE_MULDIV_PAIR(MDPairs,1,CIE_Zr(PDCI_CMYDYEMASKS),C);
  1610. MAKE_MULDIV_PAIR(MDPairs,2,CIE_Zg(PDCI_CMYDYEMASKS),M);
  1611. MAKE_MULDIV_PAIR(MDPairs,3,CIE_Zb(PDCI_CMYDYEMASKS),Y);
  1612. Y1 = MulDivFD6Pairs(MDPairs);
  1613. DBGP("%u:[%c] = [%s %s %s]"
  1614. ARGU(Loop) ARGB(DyeName[Loop])
  1615. ARGFD6(C1, 2, 6) ARGFD6(M1, 2, 6) ARGFD6(Y1, 2, 6));
  1616. }
  1617. );
  1618. }
  1619. }
  1620. //
  1621. // Re-compute
  1622. //
  1623. // Geneate internal HTCELL data structure based on the halftone
  1624. // pattern data passed.
  1625. //
  1626. if ((Result = ComputeHTCell((WORD)HTInitInfo.HTPatternIndex,
  1627. HTInitInfo.pHalftonePattern,
  1628. pDCI)) < 0) {
  1629. CleanUpDHI((PDEVICEHALFTONEINFO)pHT_DHI);
  1630. HTAPI_RET(HTAPI_IDX_CREATE_DHI, Result);
  1631. }
  1632. //
  1633. // Compute simulated rotate pattern for 3 planes
  1634. //
  1635. #if DO_CACHE_DCI
  1636. AddCachedDCI(pDCI);
  1637. #endif
  1638. }
  1639. pDCI->CRTX[CRTX_LEVEL_255].PrimMax = CRTX_PRIMMAX_255;
  1640. pDCI->CRTX[CRTX_LEVEL_255].SizeCRTX = (WORD)CRTX_SIZE_255;
  1641. pDCI->CRTX[CRTX_LEVEL_RGB].PrimMax = CRTX_PRIMMAX_RGB;
  1642. pDCI->CRTX[CRTX_LEVEL_RGB].SizeCRTX = (WORD)CRTX_SIZE_RGB;
  1643. //
  1644. // Setting the public field so the caller can looked at
  1645. //
  1646. pHT_DHI->DHI.DeviceOwnData = 0;
  1647. pHT_DHI->DHI.cxPattern = (WORD)pDCI->HTCell.cxReal;
  1648. pHT_DHI->DHI.cyPattern = (WORD)pDCI->HTCell.Height;
  1649. if ((HTInitInfo.DefHTColorAdjustment.caIlluminantIndex >
  1650. ILLUMINANT_MAX_INDEX) ||
  1651. (HTInitInfo.DefHTColorAdjustment.caSize !=
  1652. sizeof(COLORADJUSTMENT)) ||
  1653. ((HTInitInfo.DefHTColorAdjustment.caRedGamma == 10000) &&
  1654. (HTInitInfo.DefHTColorAdjustment.caGreenGamma == 10000) &&
  1655. (HTInitInfo.DefHTColorAdjustment.caBlueGamma == 10000))) {
  1656. pHT_DHI->DHI.HTColorAdjustment = DefaultCA;
  1657. DBGP_IF(DBGP_CACHED_DCI,
  1658. DBGP("*** USE DEFAULT COLORADJUSTMENT in DCI *** "));
  1659. } else {
  1660. pHT_DHI->DHI.HTColorAdjustment = HTInitInfo.DefHTColorAdjustment;
  1661. }
  1662. if ((HTInitInfo.Flags & (HIF_ADDITIVE_PRIMS | HIF_PRINT_DRAFT_MODE)) ==
  1663. HIF_PRINT_DRAFT_MODE) {
  1664. pDCI->Flags |= DCIF_PRINT_DRAFT_MODE;
  1665. }
  1666. //
  1667. // Compute what 8bpp mode we will be in
  1668. //
  1669. if (HTInitInfo.Flags & HIF_USE_8BPP_BITMASK) {
  1670. pDCI->Flags |= DCIF_USE_8BPP_BITMASK |
  1671. ((HTInitInfo.Flags & HIF_INVERT_8BPP_BITMASK_IDX) ?
  1672. DCIF_INVERT_8BPP_BITMASK_IDX : 0);
  1673. _cC = (DWORD)((HTInitInfo.CMYBitMask8BPP >> 5) & 0x7);
  1674. _cM = (DWORD)((HTInitInfo.CMYBitMask8BPP >> 2) & 0x7);
  1675. _cY = (DWORD)((HTInitInfo.CMYBitMask8BPP ) & 0x3);
  1676. if (HTInitInfo.CMYBitMask8BPP == 1) {
  1677. //
  1678. // This is 4:4:4: format (0-4 of 5 levels)
  1679. //
  1680. _cC =
  1681. _cM =
  1682. _cY = 4;
  1683. HTInitInfo.CMYBitMask8BPP = (BYTE)((5 * 5 * 5) - 1);
  1684. } else if (HTInitInfo.CMYBitMask8BPP == 2) {
  1685. //
  1686. // This is 5:5:5: format (0-5 of 6 levels)
  1687. //
  1688. _cC =
  1689. _cM =
  1690. _cY = 5;
  1691. HTInitInfo.CMYBitMask8BPP = (BYTE)((6 * 6 * 6) - 1);
  1692. } else if ((_cC < 1) || (_cM < 1) || (_cY < 1)) {
  1693. _cC =
  1694. _cM =
  1695. _cY = 0xFF;
  1696. HTInitInfo.CMYBitMask8BPP = 0xFF;
  1697. pDCI->Flags |= DCIF_MONO_8BPP_BITMASK;
  1698. }
  1699. pDCI->CMY8BPPMask.GenerateXlate =
  1700. (pDCI->Flags & DCIF_INVERT_8BPP_BITMASK_IDX) ? 1 : 0;
  1701. if ((_cC == _cM) && (_cC == _cY)) {
  1702. pDCI->Flags |= DCIF_CMY8BPPMASK_SAME_LEVEL;
  1703. pDCI->CMY8BPPMask.SameLevel = (BYTE)_cC;
  1704. } else {
  1705. pDCI->CMY8BPPMask.SameLevel = 0;
  1706. }
  1707. if ((_MaxCMY = _cC) < _cM) {
  1708. _MaxCMY = _cM;
  1709. }
  1710. if (_MaxCMY < _cY) {
  1711. _MaxCMY = _cY;
  1712. }
  1713. //
  1714. // Set to 0xFFFF to indicate this is a default setting to start with
  1715. // then modified depends on the parameters passed
  1716. //
  1717. pDCI->CMY8BPPMask.KCheck = 0xFFFF;
  1718. if ((_MaxCMY <= 6) &&
  1719. (pHTInitInfo->pDeviceCIEInfo) &&
  1720. (pHTInitInfo->pDeviceCIEInfo->Blue.Y == VALID_YB_DENSITY)) {
  1721. PCIEINFO pCIE = pHTInitInfo->pDeviceCIEInfo;
  1722. //
  1723. // 27-Sep-2000 Wed 15:05:38 updated -by- Daniel Chou (danielc)
  1724. // if Blue.Y == 0xfffe then it specified that it has CMY densities
  1725. // in the CIEINFO, Cyan.x=C1,C2, Cyan.y=C3,C4, Red.Y=C5,C6
  1726. // Magenta.x=M1,M2, Magenta.y=M3,M4, Magenta.Y=M5,M6
  1727. // Yellow.x=Y1,Y2, Yellow.y=Y3,Y4, Yellow.Y=Y5,Y6, each density is
  1728. // one byte and its computation is (C1+1)/256 to get the perentage
  1729. // of the density. The Last level is to specified maximum dye
  1730. // output for that color. for example if Cyan has 2 levels
  1731. // and C1=0x7F and C2=0xF0 then first level of ink is
  1732. // (0x7f+1) / 0x100=50% and last level of ink is 0xF0 which
  1733. // speicified maximum ink will be used, at here =
  1734. // (0xF0 + 1) / 0x100 = 94.14% which maximum cyan ink will be at
  1735. // 94.14% not 100%
  1736. //
  1737. pDCI->Flags |= DCIF_HAS_DENSITY;
  1738. pDCI->CMY8BPPMask.DenC[0] = GET_DEN_HI(pCIE->Cyan.x);
  1739. pDCI->CMY8BPPMask.DenC[1] = GET_DEN_LO(pCIE->Cyan.x);
  1740. pDCI->CMY8BPPMask.DenC[2] = GET_DEN_HI(pCIE->Cyan.y);
  1741. pDCI->CMY8BPPMask.DenC[3] = GET_DEN_LO(pCIE->Cyan.y);
  1742. pDCI->CMY8BPPMask.DenC[4] = GET_DEN_HI(pCIE->Red.Y);
  1743. pDCI->CMY8BPPMask.DenC[5] = GET_DEN_LO(pCIE->Red.Y);
  1744. pDCI->CMY8BPPMask.DenM[0] = GET_DEN_HI(pCIE->Magenta.x);
  1745. pDCI->CMY8BPPMask.DenM[1] = GET_DEN_LO(pCIE->Magenta.x);
  1746. pDCI->CMY8BPPMask.DenM[2] = GET_DEN_HI(pCIE->Magenta.y);
  1747. pDCI->CMY8BPPMask.DenM[3] = GET_DEN_LO(pCIE->Magenta.y);
  1748. pDCI->CMY8BPPMask.DenM[4] = GET_DEN_HI(pCIE->Magenta.Y);
  1749. pDCI->CMY8BPPMask.DenM[5] = GET_DEN_LO(pCIE->Magenta.Y);
  1750. pDCI->CMY8BPPMask.DenY[0] = GET_DEN_HI(pCIE->Yellow.x);
  1751. pDCI->CMY8BPPMask.DenY[1] = GET_DEN_LO(pCIE->Yellow.x);
  1752. pDCI->CMY8BPPMask.DenY[2] = GET_DEN_HI(pCIE->Yellow.y);
  1753. pDCI->CMY8BPPMask.DenY[3] = GET_DEN_LO(pCIE->Yellow.y);
  1754. pDCI->CMY8BPPMask.DenY[4] = GET_DEN_HI(pCIE->Yellow.Y);
  1755. pDCI->CMY8BPPMask.DenY[5] = GET_DEN_LO(pCIE->Yellow.Y);
  1756. //
  1757. // The Green.Y is a UDECI4 number that specified the black ink
  1758. // replacement base ratio, the range and meaning as follow
  1759. //
  1760. // 0: Default black ink replacement computation
  1761. // 1 - 9999: Specified black ink replacement base ratio
  1762. // >= 10000: turn off black ink replacement computation
  1763. //
  1764. if (pCIE->Green.Y >= UDECI4_1) {
  1765. pDCI->CMY8BPPMask.KCheck = FD6_0;
  1766. } else if (pCIE->Green.Y != UDECI4_0) {
  1767. pDCI->CMY8BPPMask.KCheck = UDECI4ToFD6(pCIE->Green.Y);
  1768. }
  1769. _MaxMulDiv = DivFD6(FD6_1, pDCI->DevPelRatio);
  1770. pDCI->CMY8BPPMask.MaxMulC = MulFD6(pDCI->CMY8BPPMask.DenC[_cC - 1],
  1771. _MaxMulDiv);
  1772. pDCI->CMY8BPPMask.MaxMulM = MulFD6(pDCI->CMY8BPPMask.DenM[_cM - 1],
  1773. _MaxMulDiv);
  1774. pDCI->CMY8BPPMask.MaxMulY = MulFD6(pDCI->CMY8BPPMask.DenY[_cY - 1],
  1775. _MaxMulDiv);
  1776. for (_Idx = COUNT_ARRAY(pDCI->CMY8BPPMask.DenC);
  1777. _Idx > 0;
  1778. _Idx--) {
  1779. if (_Idx >= _cC) {
  1780. pDCI->CMY8BPPMask.DenC[_Idx - 1] = FD6_1;
  1781. }
  1782. if (_Idx >= _cM) {
  1783. pDCI->CMY8BPPMask.DenM[_Idx - 1] = FD6_1;
  1784. }
  1785. if (_Idx >= _cY) {
  1786. pDCI->CMY8BPPMask.DenY[_Idx - 1] = FD6_1;
  1787. }
  1788. }
  1789. DBGP_IF(DBGP_CACHED_DCI,
  1790. DBGP(" Cyan %ld/%s Density: %s, %s, %s, %s, %s, %s"
  1791. ARGDW(_cC)
  1792. ARGFD6(pDCI->CMY8BPPMask.MaxMulC, 1, 6)
  1793. ARGFD6(pDCI->CMY8BPPMask.DenC[0], 1, 6)
  1794. ARGFD6(pDCI->CMY8BPPMask.DenC[1], 1, 6)
  1795. ARGFD6(pDCI->CMY8BPPMask.DenC[2], 1, 6)
  1796. ARGFD6(pDCI->CMY8BPPMask.DenC[3], 1, 6)
  1797. ARGFD6(pDCI->CMY8BPPMask.DenC[4], 1, 6)
  1798. ARGFD6(pDCI->CMY8BPPMask.DenC[5], 1, 6)));
  1799. DBGP_IF(DBGP_CACHED_DCI,
  1800. DBGP("Magenta %ld/%s Density: %s, %s, %s, %s, %s, %s"
  1801. ARGDW(_cM)
  1802. ARGFD6(pDCI->CMY8BPPMask.MaxMulM, 1, 6)
  1803. ARGFD6(pDCI->CMY8BPPMask.DenM[0], 1, 6)
  1804. ARGFD6(pDCI->CMY8BPPMask.DenM[1], 1, 6)
  1805. ARGFD6(pDCI->CMY8BPPMask.DenM[2], 1, 6)
  1806. ARGFD6(pDCI->CMY8BPPMask.DenM[3], 1, 6)
  1807. ARGFD6(pDCI->CMY8BPPMask.DenM[4], 1, 6)
  1808. ARGFD6(pDCI->CMY8BPPMask.DenM[5], 1, 6)));
  1809. DBGP_IF(DBGP_CACHED_DCI,
  1810. DBGP(" Yellow %ld/%s Density: %s, %s, %s, %s, %s, %s"
  1811. ARGDW(_cY)
  1812. ARGFD6(pDCI->CMY8BPPMask.MaxMulY, 1, 6)
  1813. ARGFD6(pDCI->CMY8BPPMask.DenY[0], 1, 6)
  1814. ARGFD6(pDCI->CMY8BPPMask.DenY[1], 1, 6)
  1815. ARGFD6(pDCI->CMY8BPPMask.DenY[2], 1, 6)
  1816. ARGFD6(pDCI->CMY8BPPMask.DenY[3], 1, 6)
  1817. ARGFD6(pDCI->CMY8BPPMask.DenY[4], 1, 6)
  1818. ARGFD6(pDCI->CMY8BPPMask.DenY[5], 1, 6)));
  1819. } else {
  1820. _MaxMulDiv = FD6xL(pDCI->DevPelRatio, _MaxCMY);
  1821. pDCI->CMY8BPPMask.MaxMulC = DivFD6(FD6xL(FD6_1, _cC), _MaxMulDiv);
  1822. pDCI->CMY8BPPMask.MaxMulM = DivFD6(FD6xL(FD6_1, _cM), _MaxMulDiv);
  1823. pDCI->CMY8BPPMask.MaxMulY = DivFD6(FD6xL(FD6_1, _cY), _MaxMulDiv);
  1824. }
  1825. if ((_MaxMulDiv = pDCI->CMY8BPPMask.MaxMulC) <
  1826. pDCI->CMY8BPPMask.MaxMulM) {
  1827. _MaxMulDiv = pDCI->CMY8BPPMask.MaxMulM;
  1828. }
  1829. if (_MaxMulDiv < pDCI->CMY8BPPMask.MaxMulY) {
  1830. _MaxMulDiv = pDCI->CMY8BPPMask.MaxMulY;
  1831. }
  1832. if (pDCI->CMY8BPPMask.KCheck == 0xFFFF) {
  1833. //
  1834. // Default setting, turn off K Replacement only if
  1835. // DevPelsRatio/Density = 100% and CMY inks are in same level
  1836. //
  1837. pDCI->CMY8BPPMask.KCheck =
  1838. ((_MaxMulDiv == FD6_1) &&
  1839. (pDCI->Flags & DCIF_CMY8BPPMASK_SAME_LEVEL)) ?
  1840. FD6_0 : K_REP_START;
  1841. }
  1842. if (pDCI->CMY8BPPMask.KCheck == FD6_0) {
  1843. //
  1844. // If K replacement was turn off, but the ratio is not 100% or
  1845. // have different ink levels then wee need to turn it on at
  1846. // 1.0 (FD6_1) so that a 8bpp black replacement function is
  1847. // used, only in k replacement function it compute how to
  1848. // reduced non 100% device pel ratio (KPower)
  1849. //
  1850. if ((_MaxMulDiv != FD6_1) ||
  1851. (!(pDCI->Flags & DCIF_CMY8BPPMASK_SAME_LEVEL))) {
  1852. pDCI->CMY8BPPMask.KCheck = FD6_1;
  1853. }
  1854. }
  1855. DBGP_IF(DBGP_CACHED_DCI,
  1856. DBGP("KCheck= %s ^ %s = %s"
  1857. ARGFD6(pDCI->CMY8BPPMask.KCheck, 1, 6) ARGFD6(_MaxMulDiv, 1, 6)
  1858. ARGFD6(Power(pDCI->CMY8BPPMask.KCheck, _MaxMulDiv), 1, 6)));
  1859. pDCI->CMY8BPPMask.KCheck = Power(pDCI->CMY8BPPMask.KCheck, _MaxMulDiv);
  1860. pDCI->CMY8BPPMask.PatSubC =
  1861. (WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulC, 0xFFF) + 1;
  1862. pDCI->CMY8BPPMask.PatSubM =
  1863. (WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulM, 0xFFF) + 1;
  1864. pDCI->CMY8BPPMask.PatSubY =
  1865. (WORD)MulFD6(pDCI->CMY8BPPMask.MaxMulY, 0xFFF) + 1;
  1866. DBGP_IF(DBGP_CACHED_DCI,
  1867. DBGP("*** USE_8BPP_BITMASK: CMY=%ld:%ld:%ld, Same=%ld], Mask=%02lx, Max=%ld ***"
  1868. ARGDW(_cC) ARGDW(_cM) ARGDW(_cY)
  1869. ARGDW(pDCI->CMY8BPPMask.SameLevel)
  1870. ARGDW(HTInitInfo.CMYBitMask8BPP) ARGDW(_MaxCMY)));
  1871. DBGP_IF(DBGP_CACHED_DCI,
  1872. DBGP("*** MaxMulCMY=%s:%s:%s [KCheck=%s], SubCMY=%4ld:%4ld:%4ld ***"
  1873. ARGFD6(pDCI->CMY8BPPMask.MaxMulC, 1, 6)
  1874. ARGFD6(pDCI->CMY8BPPMask.MaxMulM, 1, 6)
  1875. ARGFD6(pDCI->CMY8BPPMask.MaxMulY, 1, 6)
  1876. ARGFD6(pDCI->CMY8BPPMask.KCheck, 1, 6)
  1877. ARGDW(pDCI->CMY8BPPMask.PatSubC)
  1878. ARGDW(pDCI->CMY8BPPMask.PatSubM)
  1879. ARGDW(pDCI->CMY8BPPMask.PatSubY)));
  1880. } else {
  1881. _cC =
  1882. _cM =
  1883. _cY =
  1884. _MaxCMY = 1;
  1885. HTInitInfo.CMYBitMask8BPP = 0xFF;
  1886. }
  1887. pDCI->CMY8BPPMask.cC = (BYTE)_cC;
  1888. pDCI->CMY8BPPMask.cM = (BYTE)_cM;
  1889. pDCI->CMY8BPPMask.cY = (BYTE)_cY;
  1890. pDCI->CMY8BPPMask.Max = (BYTE)_MaxCMY;
  1891. pDCI->CMY8BPPMask.Mask = (BYTE)HTInitInfo.CMYBitMask8BPP;
  1892. //
  1893. // Now compute the HTSMP checksum for the pattern
  1894. //
  1895. dwBuf[0] = (DWORD)pDCI->DeviceResXDPI;
  1896. dwBuf[1] = (DWORD)pDCI->DeviceResYDPI;
  1897. dwBuf[2] = (DWORD)pDCI->DevPelRatio;
  1898. dwBuf[3] = (DWORD)(dwBuf[0] + dwBuf[1]);
  1899. pDCI->HTSMPChecksum = ComputeChecksum((LPBYTE)&dwBuf[0],
  1900. HTSMP_INITIAL_CHECKSUM,
  1901. sizeof(dwBuf[0]) * 4);
  1902. ASSERTMSG("pDCI->ClrXFormBlock.RegDataIdx > 6",
  1903. (pDCI->ClrXFormBlock.RegDataIdx < 7));
  1904. if (pDCI->ClrXFormBlock.RegDataIdx > 6) {
  1905. pDCI->ClrXFormBlock.RegDataIdx = 3;
  1906. }
  1907. DBGP_IF(DBGP_CACHED_DCI,
  1908. DBGP("SMP Checksum = %08lx, RegDataIdx=%u"
  1909. ARGDW(pDCI->HTSMPChecksum)
  1910. ARGU(pDCI->ClrXFormBlock.RegDataIdx)));
  1911. DBGP_IF(DBGP_CACHED_DCI,
  1912. DBGP("*** Final DevResDPI=%ld x %ld DevPelRatio=%ld, cx/cyPat=%ld x %ld=%ld *** "
  1913. ARGDW(pDCI->DeviceResXDPI)
  1914. ARGDW(pDCI->DeviceResYDPI)
  1915. ARGDW(pDCI->DevPelRatio)
  1916. ARGDW(pHT_DHI->DHI.cxPattern)
  1917. ARGDW(pHT_DHI->DHI.cyPattern)
  1918. ARGDW(pDCI->HTCell.Size)));
  1919. //
  1920. // Set the ILLUMINANT index to an invalid value for next one will get
  1921. // computed
  1922. //
  1923. pDCI->Flags |= ExtraDCIF;
  1924. pDCI->ca.caSize = ADJ_FORCE_DEVXFORM;
  1925. pDCI->ca.caIlluminantIndex = 0xffff;
  1926. *ppDeviceHalftoneInfo = (PDEVICEHALFTONEINFO)pHT_DHI;
  1927. return(HALFTONE_DLL_ID);
  1928. #undef _RegDataIdx
  1929. #undef _MaxMulDiv
  1930. #undef _cC
  1931. #undef _cM
  1932. #undef _cY
  1933. #undef _MaxCMY
  1934. #undef _Idx
  1935. }
  1936. BOOL
  1937. APIENTRY
  1938. HT_LOADDS
  1939. HT_DestroyDeviceHalftoneInfo(
  1940. PDEVICEHALFTONEINFO pDeviceHalftoneInfo
  1941. )
  1942. /*++
  1943. Routine Description:
  1944. This function destroy the handle which returned from halftone initialize
  1945. function HT_CreateDeviceHalftoneInfo()
  1946. Arguments:
  1947. pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
  1948. which returned from the HT_CreateDeviceHalftoneInfo.
  1949. Return Value:
  1950. TRUE - if function sucessed.
  1951. FALSE - if function failed.
  1952. Author:
  1953. 05-Feb-1991 Tue 14:18:20 created -by- Daniel Chou (danielc)
  1954. Revision History:
  1955. --*/
  1956. {
  1957. if ((!pDeviceHalftoneInfo) ||
  1958. (PHT_DHI_DCI_OF(HalftoneDLLID) != HALFTONE_DLL_ID)) {
  1959. SET_ERR(HTAPI_IDX_DESTROY_DHI, HTERR_INVALID_DHI_POINTER);
  1960. return(FALSE);
  1961. }
  1962. return(CleanUpDHI(pDeviceHalftoneInfo));
  1963. }
  1964. LONG
  1965. APIENTRY
  1966. HT_LOADDS
  1967. HT_CreateHalftoneBrush(
  1968. PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
  1969. PHTCOLORADJUSTMENT pHTColorAdjustment,
  1970. PCOLORTRIAD pColorTriad,
  1971. CHBINFO CHBInfo,
  1972. LPVOID pOutputBuffer
  1973. )
  1974. /*++
  1975. Routine Description:
  1976. This function create halftone mask for the requested solid color.
  1977. Arguments:
  1978. pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
  1979. which returned from the HT_CreateDeviceHalftoneInfo.
  1980. pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data structure to
  1981. specified the input/output color adjustment/transform,
  1982. if this pointer is NULL then a default color
  1983. adjustments is applied.
  1984. pColorTriad - Pointer to the COLORTRIAD data structure to describe
  1985. the brush colors.
  1986. CHBInfo - CHBINFO data structure, specified following:
  1987. Flags: CHBF_BW_ONLY
  1988. CHBF_USE_ADDITIVE_PRIMS
  1989. CHBF_NEGATIVE_PATTERN
  1990. DestSurfaceFormat: BMF_1BPP
  1991. BMF_4BPP
  1992. BMF_4BPP_VGA16
  1993. BMF_8BPP_VGA256
  1994. ScanLineAlignBytes: 0 - 255
  1995. DestPrimaryOrder: One of PRIMARY_ORDER_xxx
  1996. pOutputBuffer - Pointer to the buffer area to received indices/mask.
  1997. in bytes needed to stored the halftone pattern.
  1998. Return Value:
  1999. if the return value is negative or zero then an error was encountered,
  2000. possible error codes are
  2001. HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is
  2002. passed.
  2003. HTERR_INVALID_DEST_FORMAT - the Format of the destination
  2004. surface is not one of the defined
  2005. HSC_FORMAT_xxxx
  2006. HTERR_CHB_INV_COLORTABLE_SIZE - Color table size is not 1
  2007. otherwise
  2008. If pSurface is NULL, it return the bytes count which need to stored
  2009. the pattern, otherwise it return the size in byte copied to the output
  2010. buffer.
  2011. Author:
  2012. 05-Feb-1991 Tue 14:28:23 created -by- Daniel Chou (danielc)
  2013. Revision History:
  2014. --*/
  2015. {
  2016. PDEVICECOLORINFO pDCI;
  2017. PDEVCLRADJ pDevClrAdj;
  2018. CTSTD_UNION CTSTDUnion;
  2019. WORD ForceFlags;
  2020. LONG cbBufScan;
  2021. LONG cbBufSize;
  2022. if ((!pColorTriad) ||
  2023. (pColorTriad->ColorTableEntries != 1) ||
  2024. (!(pColorTriad->pColorTable))) {
  2025. HTAPI_RET(HTAPI_IDX_CHB, HTERR_CHB_INV_COLORTABLE_SIZE);
  2026. }
  2027. ForceFlags = ADJ_FORCE_BRUSH;
  2028. CTSTDUnion.b.cbPrim = 0;
  2029. CTSTDUnion.b.SrcOrder = pColorTriad->PrimaryOrder;
  2030. CTSTDUnion.b.BMFDest = CHBInfo.DestSurfaceFormat;
  2031. CTSTDUnion.b.DestOrder = CHBInfo.DestPrimaryOrder;
  2032. if ((CHBInfo.Flags & CHBF_BW_ONLY) ||
  2033. (CHBInfo.DestSurfaceFormat == BMF_1BPP)) {
  2034. ForceFlags |= ADJ_FORCE_MONO;
  2035. }
  2036. if (CHBInfo.Flags & CHBF_NEGATIVE_BRUSH) {
  2037. ForceFlags |= ADJ_FORCE_NEGATIVE;
  2038. }
  2039. if (CHBInfo.Flags & CHBF_USE_ADDITIVE_PRIMS) {
  2040. ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
  2041. }
  2042. if (CHBInfo.Flags & CHBF_ICM_ON) {
  2043. ForceFlags |= ADJ_FORCE_ICM;
  2044. }
  2045. SETDBGVAR(pDevClrAdj, NULL);
  2046. if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
  2047. pHTColorAdjustment,
  2048. (pOutputBuffer) ? &pDevClrAdj : NULL,
  2049. 0,
  2050. ForceFlags,
  2051. CTSTDUnion.b,
  2052. &cbBufSize))) {
  2053. HTAPI_RET(HTAPI_IDX_CHB, cbBufSize);
  2054. }
  2055. cbBufScan = (LONG)ComputeBytesPerScanLine(
  2056. (UINT)CHBInfo.DestSurfaceFormat,
  2057. (UINT)CHBInfo.DestScanLineAlignBytes,
  2058. (DWORD)pDCI->HTCell.cxReal);
  2059. cbBufSize = cbBufScan * (LONG)pDCI->HTCell.Height;
  2060. if (pOutputBuffer) {
  2061. if (CHBInfo.Flags & CHBF_BOTTOMUP_BRUSH) {
  2062. (LPBYTE)pOutputBuffer += (cbBufSize - cbBufScan);
  2063. cbBufScan = -cbBufScan;
  2064. }
  2065. //-------------------------------------------------------------------
  2066. // CreateHalftoneBrushPat will release the semaphore for us
  2067. //-------------------------------------------------------------------
  2068. if ((cbBufScan = CreateHalftoneBrushPat(pDCI,
  2069. pColorTriad,
  2070. pDevClrAdj,
  2071. pOutputBuffer,
  2072. cbBufScan)) <= 0) {
  2073. cbBufSize = cbBufScan;
  2074. }
  2075. if (HTFreeMem(pDevClrAdj)) {
  2076. ASSERTMSG("HTFreeMem(pDevClrAdj) Failed", FALSE);
  2077. }
  2078. } else {
  2079. RELEASE_HTMUTEX(pDCI->HTMutex);
  2080. ASSERT(pDevClrAdj == NULL);
  2081. }
  2082. DBGP_IF(DBGP_HTAPI,
  2083. DBGP("HT_CreateHalftoneBrush(%hs %ld/%6ld): RGB=0x%08lx (%ld), Dst(Fmt=%ld, Order=%ld)"
  2084. ARGPTR((pOutputBuffer) ? "BUF" : "NUL")
  2085. ARGDW(pDCI->cbMemTot) ARGDW(pDCI->cbMemMax)
  2086. ARGDW(*((LPDWORD)pColorTriad->pColorTable))
  2087. ARGDW(pColorTriad->PrimaryOrder)
  2088. ARGDW(CHBInfo.DestSurfaceFormat)
  2089. ARGDW(CHBInfo.DestPrimaryOrder)));
  2090. HTAPI_RET(HTAPI_IDX_CHB, cbBufSize);
  2091. }
  2092. LONG
  2093. APIENTRY
  2094. HT_LOADDS
  2095. HT_ComputeRGBGammaTable(
  2096. WORD GammaTableEntries,
  2097. WORD GammaTableType,
  2098. UDECI4 RedGamma,
  2099. UDECI4 GreenGamma,
  2100. UDECI4 BlueGamma,
  2101. LPBYTE pGammaTable
  2102. )
  2103. /*++
  2104. Routine Description:
  2105. This function compute device gamma correction table based on the lightness
  2106. (1/RedGamma)
  2107. Gamma[N] = INT((LIGHTNESS(N / GammaTableEntries-1)) x 255)
  2108. 3
  2109. LIGHTNESS(x) = ((x + 0.16) / 1.16) if x >= 0.007996
  2110. (x / 9.033) if x < 0.007996
  2111. 1. INT() is a integer function which round up to next integer number if
  2112. resulting fraction is 0.5 or higher, the final result always limit
  2113. to have range between 0 and 255.
  2114. 2. N is a integer step number and range from 0 to (GammaTableEntries-1)
  2115. in one (1) increment.
  2116. Arguments:
  2117. GammaTableEntries - Total gamma table entries for each of red, green
  2118. and blue gamma table, halftone dll normalized
  2119. the gamma table with step value computed as
  2120. 1/GammaTableEntries.
  2121. This value must range from 3 to 255 else a 0
  2122. is returned and no table is updated.
  2123. GammaTableType - red, green and blue gamma table organizations
  2124. 0 - The gamma table is Red, Green, Blue 3 bytes
  2125. for each gamma step entries and total of
  2126. GammaTableEntries entries.
  2127. 1 - The gamma table is Red Gamma tables follow
  2128. by green gamma table then follow by blue
  2129. gamma table, each table has total of
  2130. GammaTableEntries bytes.
  2131. Other value default to 0.
  2132. RedGamma - Red gamma number in UDECI4 format
  2133. GreenGamma - Green gamma number in UDECI4 format
  2134. BlueGamma - Blue gamma number in UDECI4 format
  2135. pGammaTable - pointer to the gamma table byte array.
  2136. each output gamma number is range from 0 to 255.
  2137. Return Value:
  2138. Return value is the total table entries updated.
  2139. Author:
  2140. 15-Sep-1992 Tue 17:49:20 updated -by- Daniel Chou (danielc)
  2141. Fixed bug# 6257
  2142. 17-Jul-1992 Fri 19:04:31 created -by- Daniel Chou (danielc)
  2143. Revision History:
  2144. --*/
  2145. {
  2146. LPBYTE pRGamma;
  2147. LPBYTE pGGamma;
  2148. LPBYTE pBGamma;
  2149. FD6 L_StepInc;
  2150. FD6 IValue;
  2151. FD6 Lightness;
  2152. LONG Result;
  2153. UINT NextEntry;
  2154. FD6 RGBGamma[3];
  2155. //
  2156. // Initialize All internal data first
  2157. //
  2158. if (((Result = GammaTableEntries) > 256) ||
  2159. (Result < 2)) {
  2160. return(0);
  2161. }
  2162. Lightness = FD6_0;
  2163. L_StepInc = DivFD6((FD6)1, (FD6)(GammaTableEntries - 1));
  2164. RGBGamma[0] = UDECI4ToFD6(RedGamma);
  2165. RGBGamma[1] = UDECI4ToFD6(GreenGamma);
  2166. RGBGamma[2] = UDECI4ToFD6(BlueGamma);
  2167. pRGamma = pGammaTable;
  2168. if (GammaTableType == 1) {
  2169. pGGamma = pRGamma + GammaTableEntries;
  2170. pBGamma = pGGamma + GammaTableEntries;
  2171. NextEntry = 1;
  2172. } else {
  2173. pGGamma = pRGamma + 1;
  2174. pBGamma = pGGamma + 1;
  2175. NextEntry = 3;
  2176. }
  2177. while (--GammaTableEntries) {
  2178. IValue = Lightness; // CIE_L2I(Lightness);
  2179. *pRGamma = RGB_8BPP(Radical(IValue, RGBGamma[0]));
  2180. *pGGamma = RGB_8BPP(Radical(IValue, RGBGamma[1]));
  2181. *pBGamma = RGB_8BPP(Radical(IValue, RGBGamma[2]));
  2182. pRGamma += NextEntry;
  2183. pGGamma += NextEntry;
  2184. pBGamma += NextEntry;
  2185. Lightness += L_StepInc;
  2186. }
  2187. *pRGamma =
  2188. *pGGamma =
  2189. *pBGamma = 255;
  2190. return(Result);
  2191. }
  2192. LONG
  2193. APIENTRY
  2194. HT_LOADDS
  2195. HT_Get8BPPFormatPalette(
  2196. LPPALETTEENTRY pPaletteEntry,
  2197. UDECI4 RedGamma,
  2198. UDECI4 GreenGamma,
  2199. UDECI4 BlueGamma
  2200. )
  2201. /*++
  2202. Routine Description:
  2203. This functions retrieve a halftone's VGA256 color table definitions
  2204. Arguments:
  2205. pPaletteEntry - Pointer to PALETTEENTRY data structure array,
  2206. RedGamma - The monitor's red gamma value in UDECI4 format
  2207. GreenGamma - The monitor's green gamma value in UDECI4 format
  2208. BlueGamma - The monitor's blue gamma value in UDECI4 format
  2209. Return Value:
  2210. if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
  2211. VGA256 halftone process, if it is not NULL then it return the total
  2212. paletteEntry updated.
  2213. If the pPaletteEntry is not NULL then halftone.dll assume it has enough
  2214. space for the size returned when this pointer is NULL.
  2215. Author:
  2216. 14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
  2217. Revision History:
  2218. --*/
  2219. {
  2220. FD6 RGBGamma[3];
  2221. FD6 IValue;
  2222. FD6 Yr;
  2223. FD6 Yg;
  2224. FD6 Yb;
  2225. UINT RIndex;
  2226. UINT GIndex;
  2227. UINT BIndex;
  2228. UINT TableSize;
  2229. DEFDBGVAR(UINT, PaletteIdx = 0)
  2230. DBGP_IF(DBGP_HTAPI,
  2231. DBGP("HT_Get8BPPFormatPalette(%p): Gamma=%05ld:%05ld:%05ld"
  2232. ARGPTR(pPaletteEntry)
  2233. ARGDW(RedGamma) ARGDW(GreenGamma) ARGDW(BlueGamma)));
  2234. //
  2235. // Initialize All internal data first
  2236. //
  2237. if (pPaletteEntry) {
  2238. RGBGamma[0] = UDECI4ToFD6(RedGamma);
  2239. RGBGamma[1] = UDECI4ToFD6(GreenGamma);
  2240. RGBGamma[2] = UDECI4ToFD6(BlueGamma);
  2241. DBGP_IF(DBGP_GAMMA_PAL,
  2242. DBGP("***** HT_Get8BPPFormatPalette: %s:%s:%s *****"
  2243. ARGFD6(RGBGamma[0], 1, 4)
  2244. ARGFD6(RGBGamma[1], 1, 4)
  2245. ARGFD6(RGBGamma[2], 1, 4)));
  2246. //
  2247. // Our VGA256 format is BGR type of Primary order.
  2248. //
  2249. RIndex =
  2250. GIndex =
  2251. BIndex = 0;
  2252. TableSize = VGA256_CUBE_SIZE;
  2253. while (TableSize--) {
  2254. Yr = DivFD6(RIndex, VGA256_R_IDX_MAX);
  2255. Yg = DivFD6(GIndex, VGA256_G_IDX_MAX);
  2256. Yb = DivFD6(BIndex, VGA256_B_IDX_MAX);
  2257. pPaletteEntry->peRed = RGB_8BPP(Yr);
  2258. pPaletteEntry->peGreen = RGB_8BPP(Yg);
  2259. pPaletteEntry->peBlue = RGB_8BPP(Yb);
  2260. pPaletteEntry->peFlags = 0;
  2261. DBGP_IF(DBGP_GAMMA_PAL,
  2262. DBGP("%3u - %3u:%3u:%3u"
  2263. ARGU(PaletteIdx++)
  2264. ARGU(pPaletteEntry->peRed )
  2265. ARGU(pPaletteEntry->peGreen)
  2266. ARGU(pPaletteEntry->peBlue )));
  2267. ++pPaletteEntry;
  2268. if ((++RIndex) > VGA256_R_IDX_MAX) {
  2269. RIndex = 0;
  2270. if ((++GIndex) > VGA256_G_IDX_MAX) {
  2271. GIndex = 0;
  2272. ++BIndex;
  2273. }
  2274. }
  2275. }
  2276. //
  2277. // 03-Feb-1999 Wed 00:49:08 updated -by- Daniel Chou (danielc)
  2278. //
  2279. // Since all these monochrome/gray scale is not stick in the system
  2280. // palette, The halftone codes with new supercell will not use these
  2281. // entries anymore, so do not return it.
  2282. //
  2283. #if 0
  2284. RIndex = 0;
  2285. while (RIndex <= VGA256_M_IDX_MAX) {
  2286. IValue = DivFD6(RIndex++, VGA256_M_IDX_MAX);
  2287. pPaletteEntry->peRed = RGB_8BPP(IValue);
  2288. pPaletteEntry->peGreen = RGB_8BPP(IValue);
  2289. pPaletteEntry->peBlue = RGB_8BPP(IValue);
  2290. pPaletteEntry->peFlags = 0;
  2291. DBGP_IF(DBGP_GAMMA_PAL,
  2292. DBGP("%3u - %3u:%3u:%3u [%s]"
  2293. ARGU(PaletteIdx++)
  2294. ARGU(pPaletteEntry->peRed )
  2295. ARGU(pPaletteEntry->peGreen)
  2296. ARGU(pPaletteEntry->peBlue )
  2297. ARGFD6(IValue, 1, 6)));
  2298. ++pPaletteEntry;
  2299. }
  2300. #endif
  2301. }
  2302. return((LONG)VGA256_CUBE_SIZE);
  2303. // return((LONG)VGA256_PALETTE_COUNT);
  2304. }
  2305. LONG
  2306. APIENTRY
  2307. HT_LOADDS
  2308. HT_Get8BPPMaskPalette(
  2309. LPPALETTEENTRY pPaletteEntry,
  2310. BOOL Use8BPPMaskPal,
  2311. BYTE CMYMask,
  2312. UDECI4 RedGamma,
  2313. UDECI4 GreenGamma,
  2314. UDECI4 BlueGamma
  2315. )
  2316. /*++
  2317. Routine Description:
  2318. This functions retrieve a halftone's VGA256 color table definitions
  2319. Arguments:
  2320. pPaletteEntry - Pointer to PALETTEENTRY data structure array,
  2321. Use8BPPMaskPal - TRUE if using byte Mask palette, false to use NT4.0
  2322. standard MS 8bpp palette
  2323. CMYMask - Specified level mask in C3:M3:Y2
  2324. RedGamma - The monitor's red gamma value in UDECI4 format
  2325. GreenGamma - The monitor's green gamma value in UDECI4 format
  2326. BlueGamma - The monitor's blue gamma value in UDECI4 format
  2327. Return Value:
  2328. if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
  2329. VGA256 halftone process, if it is not NULL then it return the total
  2330. paletteEntry updated.
  2331. If the pPaletteEntry is not NULL then halftone.dll assume it has enough
  2332. space for the size returned when this pointer is NULL.
  2333. Author:
  2334. 14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
  2335. Revision History:
  2336. 03-Aug-2000 Thu 19:58:18 updated -by- Daniel Chou (danielc)
  2337. Overloading the pPaletteEntry to returned a inverted indices palette
  2338. based on Whistler bug# 22915. Because the Windows GDI ROP assume
  2339. index 0 always black, last index alwasy white without checking the
  2340. halftone palette and cause many rop got inverted result.
  2341. 08-Sep-2000 Fri 14:24:28 updated -by- Daniel Chou (danielc)
  2342. For new CMY_INVERTED mode, we want to make sure we pack all
  2343. possible ink entries in the middle of 256 indices and pack
  2344. black/white at end. If the total ink color compositions are
  2345. an odd number then we duplicate the middle one. This will
  2346. //
  2347. // ***************************************************************************
  2348. // * SPECIAL NOTE for Windows NT version later than Windows 2000 Release *
  2349. // ***************************************************************************
  2350. // Current version of Window NT (Post Windows 2000) will Overloading the
  2351. // pPaletteEntry in HT_Get8BPPMaskPalette(DoUseCMYMask) API to returned a
  2352. // inverted indices palette based on additive palette entries composition.
  2353. // Because Windows GDI ROP assume index 0 always black and last index always
  2354. // white without checking the palette entries. (Indices based ROPs rather color
  2355. // based) This cause many ROPS got wrong result which has inverted output.
  2356. //
  2357. // To correct this GDI ROPs behavior, the POST windows 2000 version of GDI
  2358. // Halftone will supports a special CMY_INVERTED format. All new drivers should
  2359. // use this CMY_INVERTED method for future compabilities
  2360. //
  2361. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  2362. // @ Following Steps are required for ALL POST Windows 2000 Drivers when @
  2363. // @ using Window GDI Halftone 8bpp CMY332 Mask mode @
  2364. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  2365. //
  2366. // 1. Must set HT_FLAG_INVERT_8BPP_BITMASK_IDX flags
  2367. //
  2368. // 2. Must set pPaleteEntry[0] when calling HT_Get8BPPMaskPalette() with
  2369. //
  2370. // pPaletteEntry[0].peRed = 'R';
  2371. // pPaletteEntry[0].peGreen = 'G';
  2372. // pPaletteEntry[0].peBlue = 'B';
  2373. // pPaletteEntry[0].peFlags = '0';
  2374. //
  2375. // The caller can use following supplied macro to set this for future
  2376. // compabilities
  2377. //
  2378. // HT_SET_BITMASKPAL2RGB(pPaletteEntry)
  2379. //
  2380. // where pPaletteEntry is the pointer to the PALETTEENTRY that passed to
  2381. // the HT_GET8BPPMaskPalette() fucntion call
  2382. //
  2383. // 3. Must Check the return Palette from HT_Get8BPPMaskPalette() using
  2384. // following Macro
  2385. //
  2386. // HT_IS_BITMASKPALRGB(pPaletteEntry)
  2387. //
  2388. // where pPaletteEntry is the pointer to the PALETTEENTRY that passed to the
  2389. // HT_GET8BPPMaskPalette() fucntion call,
  2390. //
  2391. // If this macro return FALSE then the current version of GDI HALFTONE does
  2392. // NOT support the CMY_INVERTED 8bpp bitmaask mode and it only supports CMY
  2393. // mode.
  2394. //
  2395. // If this macro return TRUE then the GDI HALFTONE DOES support the
  2396. // CMY_INVERTED 8bpp bitmaask mode and the caller must using a translation
  2397. // table to obtain final halftone surface bitmap 8bpp indices ink levels.
  2398. //
  2399. // 4. Behavior changes for GDI halftone that supports 8bpp CMY_INVERTED bitmask
  2400. // mode, following is a list of changes of CMYMask mode passed to
  2401. // the HT_Get8BPPMaskPalette()
  2402. //
  2403. // CMYMask CMY Mode Indices CMY_INVERTED Mode Indices
  2404. // ======= ========================= =============================
  2405. // 0 0: WHITE 0: BLACK
  2406. // 1-254: Light->Dark Gray 1-254: Dark->Light Gray
  2407. // 255: BLACK 255: WHITE
  2408. // -------------------------------------------------------------------
  2409. // 1 0: WHITE 0-65: BLACK
  2410. // 1-123: 5^3 CMY color 66-188: 5^3 RGB color
  2411. // 124-255: BLACK 189-255: WHITE
  2412. // 127-128: Duplicate for XOR ROP
  2413. // (CMY Levels 2:2:2)
  2414. // -------------------------------------------------------------------
  2415. // 2 0: WHITE 0-20: BLACK
  2416. // 1-214: 6^3 CMY color 21-234: 6^3 RGB color
  2417. // 215-255: BLACK 235-255: WHITE
  2418. // -------------------------------------------------------------------
  2419. // 3-255* 0: WHITE 0: BLACK
  2420. // 1-254: CMY Color BitMask 1-254: Centered CxMxY BitMask*
  2421. // 255: BLACK 255: WHITE
  2422. // ===================================================================
  2423. //
  2424. // * For CMYMask mode 3-255, the valid combination must NOT have any
  2425. // of Cyan, Magenta or Yellow ink level equal to 0.
  2426. //
  2427. // * The reason for CMY_INVERTED mode that pading BLACK and WHITE entires
  2428. // at both end and have all other color in the middle is to make sure
  2429. // all 256 color palette entries are even distributed so that GDI ROPs
  2430. // (raster operation) will work more correctly. This is because GDI ROPs
  2431. // are based on the indices not color
  2432. //
  2433. // * The CMY_INVERTED Mode has all non-black, non white indices centered
  2434. // and even distributed within the total 256 palette indices. For
  2435. // example; if a CMY=333 levels then it has total 3x3x3=27 indices,
  2436. // these 27 indices will be centered by packing 114 black indices at
  2437. // begining and packing 114 white indices at end to ensure that ROP
  2438. // will be correct rendered.
  2439. //
  2440. // See following sample function of for how to generate these ink levels
  2441. // and Windows 2000 CMY332 Index translation table
  2442. //
  2443. //
  2444. // 5. For CMYMask index mode 0 to 255, the caller can use following sample
  2445. // function to genrate INKLEVELS translation table
  2446. //
  2447. // The follwing structure and tables are examples of how to translate 8bpp
  2448. // bitmask halftone bitmap indices to ink levels
  2449. //
  2450. // typedef struct _INKLEVELS {
  2451. // BYTE Cyan; // Cyan level from 0 to max
  2452. // BYTE Magenta; // Magenta level from 0 to max
  2453. // BYTE Yellow; // Yellow level from 0 to max
  2454. // BYTE CMY332Idx; // Original windows 2000 CMY332 Index
  2455. // } INKLEVELS, *PINKLEVELS;
  2456. //
  2457. // To Compute a 8bpp translate table of INKLEVELS, following sample
  2458. // function show how to genrate a INKLEVELS translate table for a valid
  2459. // CMYMask range from 0 to 255. It can be use to generate either Windows
  2460. // 2000 CMY Mode or new Post Windows 2000's CMY_INVERTED mode translation
  2461. // table. It also generate a windows 2000 CMY Mode CMY332Idx so caller
  2462. // can map CMY_INVERTED new indices to old index for current existing
  2463. // indices processing function.
  2464. //
  2465. // Example Function that generate translate table for CMYMask 0 to 255,
  2466. // the pInkLevels must pointed to a valid memory location of 256 INKLEVELS
  2467. // entries, if return value is TRUE then it can be used to trnaslate 8bpp
  2468. // indices to ink levels or mapp to the older CMY332 style indices.
  2469. //
  2470. //
  2471. // BOOL
  2472. // GenerateInkLevels(
  2473. // PINKLEVELS pInkLevels, // Pointer to 256 INKLEVELS table
  2474. // BYTE CMYMask, // CMYMask mode
  2475. // BOOL CMYInverted // TRUE for CMY_INVERTED mode
  2476. // )
  2477. // {
  2478. // PINKLEVELS pILDup;
  2479. // PINKLEVELS pILEnd;
  2480. // INKLEVELS InkLevels;
  2481. // INT Count;
  2482. // INT IdxInc;
  2483. // INT cC;
  2484. // INT cM;
  2485. // INT cY;
  2486. // INT xC;
  2487. // INT xM;
  2488. // INT xY;
  2489. // INT iC;
  2490. // INT iM;
  2491. // INT iY;
  2492. // INT mC;
  2493. // INT mM;
  2494. //
  2495. //
  2496. // switch (CMYMask) {
  2497. //
  2498. // case 0:
  2499. //
  2500. // cC =
  2501. // cM =
  2502. // xC =
  2503. // xM = 0;
  2504. // cY =
  2505. // xY = 255;
  2506. // break;
  2507. //
  2508. // case 1:
  2509. // case 2:
  2510. //
  2511. // cC =
  2512. // cM =
  2513. // cY =
  2514. // xC =
  2515. // xM =
  2516. // xY = 3 + (INT)CMYMask;
  2517. // break;
  2518. //
  2519. // default:
  2520. //
  2521. // cC = (INT)((CMYMask >> 5) & 0x07);
  2522. // cM = (INT)((CMYMask >> 2) & 0x07);
  2523. // cY = (INT)( CMYMask & 0x03);
  2524. // xC = 7;
  2525. // xM = 7;
  2526. // xY = 3;
  2527. // break;
  2528. // }
  2529. //
  2530. // Count = (cC + 1) * (cM + 1) * (cY + 1);
  2531. //
  2532. // if ((Count < 1) || (Count > 256)) {
  2533. //
  2534. // return(FALSE);
  2535. // }
  2536. //
  2537. // InkLevels.Cyan =
  2538. // InkLevels.Magenta =
  2539. // InkLevels.Yellow =
  2540. // InkLevels.CMY332Idx = 0;
  2541. // mC = (xM + 1) * (xY + 1);
  2542. // mM = xY + 1;
  2543. // pILDup = NULL;
  2544. //
  2545. // if (CMYInverted) {
  2546. //
  2547. // //
  2548. // // Move the pInkLevels to the first entry which center around
  2549. // // 256 table entries, if we skip any then all entries skipped
  2550. // // will be white (CMY levels all zeros). Because this is
  2551. // // CMY_INVERTED so entries start from back of the table and
  2552. // // moving backward to the begining of the table
  2553. // //
  2554. //
  2555. // pILEnd = pInkLevels - 1;
  2556. // IdxInc = ((256 - Count - (Count & 0x01)) / 2);
  2557. // pInkLevels += 255;
  2558. //
  2559. // while (IdxInc--) {
  2560. //
  2561. // *pInkLevels-- = InkLevels;
  2562. // }
  2563. //
  2564. // if (Count & 0x01) {
  2565. //
  2566. // //
  2567. // // If we have odd number of entries then we need to
  2568. // // duplicate the center one for correct XOR ROP to
  2569. // // operated correctly. The pILDup will always be index
  2570. // // 127, the duplication are indices 127, 128
  2571. // //
  2572. //
  2573. // pILDup = pInkLevels - (Count / 2) - 1;
  2574. // }
  2575. //
  2576. // //
  2577. // // We running from end of table to the begining, because
  2578. // // when in CMYInverted mode, the index 0 is black and index
  2579. // // 255 is white. Since we only generate 'Count' of index
  2580. // // and place them at center, we will change xC, xM, xY max.
  2581. // // index to same as cC, cM and cY.
  2582. // //
  2583. //
  2584. // IdxInc = -1;
  2585. // xC = cC;
  2586. // xM = cM;
  2587. // xY = cY;
  2588. //
  2589. // } else {
  2590. //
  2591. // IdxInc = 1;
  2592. // pILEnd = pInkLevels + 256;
  2593. // }
  2594. //
  2595. // //
  2596. // // At following, the composition of ink levels, index always
  2597. // // from 0 CMY Ink levels (WHITE) to maximum ink levels (BLACK),
  2598. // // the different with CMY_INVERTED mode is we compose it from
  2599. // // index 255 to index 0 rather than from index 0 to 255
  2600. // //
  2601. //
  2602. // if (CMYMask) {
  2603. //
  2604. // INT Idx332C;
  2605. // INT Idx332M;
  2606. //
  2607. // for (iC = 0, Idx332C = -mC; iC <= xC; iC++) {
  2608. //
  2609. // if (iC <= cC) {
  2610. //
  2611. // InkLevels.Cyan = (BYTE)iC;
  2612. // Idx332C += mC;
  2613. // }
  2614. //
  2615. // for (iM = 0, Idx332M = -mM; iM <= xM; iM++) {
  2616. //
  2617. // if (iM <= cM) {
  2618. //
  2619. // InkLevels.Magenta = (BYTE)iM;
  2620. // Idx332M += mM;
  2621. // }
  2622. //
  2623. // for (iY = 0; iY <= xY; iY++) {
  2624. //
  2625. // if (iY <= cY) {
  2626. //
  2627. // InkLevels.Yellow = (BYTE)iY;
  2628. // }
  2629. //
  2630. // InkLevels.CMY332Idx = (BYTE)(Idx332C + Idx332M) +
  2631. // InkLevels.Yellow;
  2632. // *pInkLevels = InkLevels;
  2633. //
  2634. // if ((pInkLevels += IdxInc) == pILDup) {
  2635. //
  2636. // *pInkLevels = InkLevels;
  2637. // pInkLevels += IdxInc;
  2638. // }
  2639. // }
  2640. // }
  2641. // }
  2642. //
  2643. // //
  2644. // // Now if we need to pack black at other end of the
  2645. // // translation table then do it here, Notice that InkLevels
  2646. // // are at cC, cM and cY here and the CMY332Idx is at BLACK
  2647. // //
  2648. //
  2649. // while (pInkLevels != pILEnd) {
  2650. //
  2651. // *pInkLevels = InkLevels;
  2652. // pInkLevels += IdxInc;
  2653. // }
  2654. //
  2655. // } else {
  2656. //
  2657. // //
  2658. // // Gray Scale case
  2659. // //
  2660. //
  2661. // for (iC = 0; iC < 256; iC++, pInkLevels += IdxInc) {
  2662. //
  2663. // pInkLevels->Cyan =
  2664. // pInkLevels->Magenta =
  2665. // pInkLevels->Yellow =
  2666. // pInkLevels->CMY332Idx = (BYTE)iC;
  2667. // }
  2668. // }
  2669. //
  2670. // return(TRUE);
  2671. // }
  2672. //
  2673. //
  2674. // 6. For CMYMask Mode 0 (Gray scale), the gray scale table just inverted
  2675. // between CMY and CMY_INVERTED mode.
  2676. //
  2677. // CMY mode: 0 to 255 gray scale from WHITE to BLACK increment,
  2678. // CMY_INVERTED Mode: 0 to 255 gray scale from BLACK to WHITE increment.
  2679. //
  2680. //
  2681. // 7. For CMYMask Mode 1 and 2, the caller should use a translation table for
  2682. // translate indices to CMY ink levels.
  2683. //
  2684. // 8. For CMYMode mode 3 to 255,
  2685. //
  2686. // if in CMY Mode (Windows 2000) is specified then The final CMY ink levels
  2687. // indices byte has following meanings
  2688. //
  2689. // Bit 7 6 5 4 3 2 1 0
  2690. // | | | | | |
  2691. // +---+ +---+ +=+
  2692. // | | |
  2693. // | | +-- Yellow 0-3 (Max. 4 levels)
  2694. // | |
  2695. // | +-- Magenta 0-7 (Max. 8 levels)
  2696. // |
  2697. // +-- Cyan 0-7 (Max. 8 levels)
  2698. //
  2699. //
  2700. // If a CMY_INVERTED mode is specified then caller must use a translation
  2701. // table to convert a index to the ink levels, to generate this table,
  2702. // please see above #5 description.
  2703. //
  2704. //
  2705. --*/
  2706. {
  2707. LPPALETTEENTRY pPalOrg;
  2708. FD6 RGBGamma[3];
  2709. FD6 Tmp;
  2710. FD6 Y;
  2711. INT PalInc;
  2712. UINT PalStart;
  2713. UINT PalIdx;
  2714. UINT cC;
  2715. UINT cM;
  2716. UINT cY;
  2717. UINT iC;
  2718. UINT iM;
  2719. UINT iY;
  2720. UINT MaxPal;
  2721. UINT IdxPalDup;
  2722. BYTE bR;
  2723. BYTE bG;
  2724. BYTE bB;
  2725. DBGP_IF(DBGP_HTAPI,
  2726. DBGP("HT_Get8BPPMaskPalette(%p): UseMask=%ld, CMYMask=%02lx, Gamma=%05ld:%05ld:%05ld"
  2727. ARGPTR(pPaletteEntry)
  2728. ARGDW((Use8BPPMaskPal) ? 1 : 0)
  2729. ARGDW(CMYMask)
  2730. ARGDW(RedGamma) ARGDW(GreenGamma) ARGDW(BlueGamma)));
  2731. if (!Use8BPPMaskPal) {
  2732. return(HT_Get8BPPFormatPalette(pPaletteEntry,
  2733. RedGamma,
  2734. GreenGamma,
  2735. BlueGamma));
  2736. }
  2737. //
  2738. // Checking the CMYMask first to make sure caller passed valid CMYMask
  2739. //
  2740. switch (CMYMask) {
  2741. case 1:
  2742. cC =
  2743. cM =
  2744. cY = 4;
  2745. MaxPal = 125;
  2746. break;
  2747. case 2:
  2748. cC =
  2749. cM =
  2750. cY = 5;
  2751. MaxPal = 216;
  2752. break;
  2753. default:
  2754. MaxPal = 0;
  2755. cC = (UINT)((CMYMask >> 5) & 0x07);
  2756. cM = (UINT)((CMYMask >> 2) & 0x07);
  2757. cY = (UINT)((CMYMask >> 0) & 0x03);
  2758. //
  2759. // If this is not zero, but one of the cC, cM, cY is zero then return
  2760. // zero to indicate error
  2761. //
  2762. if ((CMYMask != 0) && ((!cC) || (!cM) || (!cY))) {
  2763. ASSERTMSG("One of Ink Levels is ZERO", (cC) && (cM) && (cY));
  2764. return(0);
  2765. }
  2766. break;
  2767. }
  2768. //
  2769. // Initialize All internal data first
  2770. //
  2771. if (pPalOrg = pPaletteEntry) {
  2772. PalStart = 0;
  2773. PalInc = 1;
  2774. IdxPalDup = 0x200;
  2775. //
  2776. // Since we will always compose the palette using CMY method, the only
  2777. // thing we need to do for the RGB mode is write the palette from index
  2778. // 255 to 0, the backward writing provied that caller can just invert
  2779. // its 8bpp indices to get the CMY ink levels definition
  2780. //
  2781. if (*((LPDWORD)pPaletteEntry) == HTBITMASKPALRGB_DW) {
  2782. //
  2783. // RGB Mode, go to end of the palette end move backward, the reason
  2784. // for the 5:5:5 and 6:6:6 that pas white and black at both end is
  2785. // to make sure the ROP work more correctly for the GDI.
  2786. //
  2787. pPaletteEntry += 255;
  2788. PalInc = -1;
  2789. //
  2790. // 08-Sep-2000 Fri 14:22:02 updated -by- Daniel Chou (danielc)
  2791. // For new CMY_INVERTED mode, we want to make sure we pack all
  2792. // possible ink entries in the middle of 256 indices and pack
  2793. // black/white at end. If the total ink color compositions are
  2794. // an odd number then we duplicate the middle one. This will
  2795. // ensure that the ROP will work correctly on color entries
  2796. //
  2797. if (CMYMask) {
  2798. MaxPal = (cC + 1) * (cM + 1) * (cY + 1);
  2799. PalStart = (256 - MaxPal) >> 1;
  2800. if (MaxPal & 0x01) {
  2801. IdxPalDup = (MaxPal >> 1) + PalStart;
  2802. }
  2803. }
  2804. }
  2805. //
  2806. // Clear all palette entries to zero first
  2807. //
  2808. ZeroMemory(pPalOrg, sizeof(PALETTEENTRY) * 256);
  2809. RGBGamma[0] = UDECI4ToFD6(RedGamma);
  2810. RGBGamma[1] = UDECI4ToFD6(GreenGamma);
  2811. RGBGamma[2] = UDECI4ToFD6(BlueGamma);
  2812. PalIdx = 0;
  2813. DBGP_IF(DBGP_GAMMA_PAL,
  2814. DBGP("***** HT_Get8BPPMaskPalette: %s:%s:%s, CMY=%u:%u:%u=%3ld (%s, %ld,%ld) *****"
  2815. ARGFD6(RGBGamma[0], 1, 4)
  2816. ARGFD6(RGBGamma[1], 1, 4)
  2817. ARGFD6(RGBGamma[2], 1, 4)
  2818. ARGDW(cC) ARGDW(cM) ARGDW(cY) ARGDW(MaxPal)
  2819. ARGPTR((PalInc==-1) ? "RGB" : "CMY")
  2820. ARGDW(PalStart) ARGDW(IdxPalDup)));
  2821. if (MaxPal) {
  2822. //
  2823. // For the begining filler, we will fill with WHITE, because
  2824. // we are composing use CMY, when CMY is 0 it means white
  2825. //
  2826. for (;
  2827. PalIdx < PalStart;
  2828. PalIdx++, pPaletteEntry += PalInc) {
  2829. pPaletteEntry->peRed =
  2830. pPaletteEntry->peGreen =
  2831. pPaletteEntry->peBlue = 0xFF;
  2832. }
  2833. for (iC = 0; iC <= cC; iC++) {
  2834. CMY_8BPP(bR, iC, cC, Tmp);
  2835. for (iM = 0; iM <= cM; iM++) {
  2836. CMY_8BPP(bG, iM, cM, Tmp)
  2837. for (iY = 0;
  2838. iY <= cY;
  2839. iY++, PalIdx++, pPaletteEntry += PalInc) {
  2840. CMY_8BPP(bB, iY, cY, Tmp);
  2841. pPaletteEntry->peRed = bR;
  2842. pPaletteEntry->peGreen = bG;
  2843. pPaletteEntry->peBlue = bB;
  2844. DBGP_IF(DBGP_GAMMA_PAL,
  2845. DBGP("[%3ld] %3u - %3u:%3u:%3u"
  2846. ARGU(pPaletteEntry - pPalOrg)
  2847. ARGU(PalIdx)
  2848. ARGU(pPaletteEntry->peRed )
  2849. ARGU(pPaletteEntry->peGreen)
  2850. ARGU(pPaletteEntry->peBlue )));
  2851. if (PalIdx == IdxPalDup) {
  2852. ++PalIdx;
  2853. pPaletteEntry += PalInc;
  2854. pPaletteEntry->peRed = bR;
  2855. pPaletteEntry->peGreen = bG;
  2856. pPaletteEntry->peBlue = bB;
  2857. DBGP_IF(DBGP_GAMMA_PAL,
  2858. DBGP("[%3ld] %3u - %3u:%3u:%3u --- DUP"
  2859. ARGU(pPaletteEntry - pPalOrg)
  2860. ARGU(PalIdx)
  2861. ARGU(pPaletteEntry->peRed )
  2862. ARGU(pPaletteEntry->peGreen)
  2863. ARGU(pPaletteEntry->peBlue )));
  2864. }
  2865. }
  2866. }
  2867. }
  2868. //
  2869. // For ending fillers (Current PalIdx to 255), we will fill with
  2870. // BLACK, because we are composing use CMY, when CMY is at MAX it
  2871. // means BLACK, Since we clear all pPalOrg to ZERO at begining of
  2872. // this function, so we are done and do not need to do anything.
  2873. //
  2874. } else if ((cC < 1) || (cM < 1) || (cY < 1)) {
  2875. for (Y = 255;
  2876. PalIdx <= 255;
  2877. PalIdx++, Y--, pPaletteEntry += PalInc) {
  2878. pPaletteEntry->peRed =
  2879. pPaletteEntry->peGreen =
  2880. pPaletteEntry->peBlue = (BYTE)Y;
  2881. DBGP_IF(DBGP_GAMMA_PAL,
  2882. DBGP("[%3ld] %3u - %3u:%3u:%3u"
  2883. ARGU(pPaletteEntry - pPalOrg)
  2884. ARGU(PalIdx)
  2885. ARGU(pPaletteEntry->peRed )
  2886. ARGU(pPaletteEntry->peGreen)
  2887. ARGU(pPaletteEntry->peBlue )));
  2888. }
  2889. } else {
  2890. for (iC = 0; iC <= 7; iC++) {
  2891. CMY_8BPP(bR, iC, cC, Tmp);
  2892. for (iM = 0; iM <= 7; iM++) {
  2893. CMY_8BPP(bG, iM, cM, Tmp)
  2894. for (iY = 0;
  2895. iY <= 3;
  2896. iY++, PalIdx++, pPaletteEntry += PalInc) {
  2897. CMY_8BPP(bB, iY, cY, Tmp);
  2898. pPaletteEntry->peRed = bR;
  2899. pPaletteEntry->peGreen = bG;
  2900. pPaletteEntry->peBlue = bB;
  2901. DBGP_IF(DBGP_GAMMA_PAL,
  2902. DBGP("[%3ld] %3u - %3u:%3u:%3u"
  2903. ARGU(pPaletteEntry - pPalOrg)
  2904. ARGU(PalIdx)
  2905. ARGU(pPaletteEntry->peRed )
  2906. ARGU(pPaletteEntry->peGreen)
  2907. ARGU(pPaletteEntry->peBlue )));
  2908. }
  2909. }
  2910. }
  2911. }
  2912. }
  2913. //
  2914. // Always return full 256 palette entry for halftone
  2915. //
  2916. return((LONG)256);
  2917. }
  2918. LONG
  2919. APIENTRY
  2920. HT_LOADDS
  2921. HT_CreateStandardMonoPattern(
  2922. PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
  2923. PSTDMONOPATTERN pStdMonoPattern
  2924. )
  2925. /*++
  2926. Routine Description:
  2927. This function create standard predefined monochrome pattern for the device.
  2928. Arguments:
  2929. pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
  2930. which returned from the HT_CreateDeviceHalftoneInfo.
  2931. pStdMonoPattern - Pointer to the STDMONOPATTERN data structure, the
  2932. pPattern in this data structure is optional.
  2933. Return Value:
  2934. if the return value is negative or zero then an error was encountered,
  2935. possible error codes are
  2936. HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is
  2937. passed.
  2938. HTERR_INVALID_STDMONOPAT_INDEX - The PatternIndex field in
  2939. STDMONOPATTERN data structure is
  2940. invalid.
  2941. otherwise
  2942. If pPattern field in STDMONOPATTERN data structure Surface is NULL, it
  2943. return the bytes count which need to stored the pattern, otherwise it
  2944. return the size in byte copied to the pattern buffer.
  2945. Author:
  2946. 05-Feb-1991 Tue 14:28:23 created -by- Daniel Chou (danielc)
  2947. Revision History:
  2948. 05-Jun-1991 Wed 10:22:41 updated -by- Daniel Chou (danielc)
  2949. Fixed the bugs when the pStdMonoPattern is NULL, it was used without
  2950. checking it.
  2951. --*/
  2952. {
  2953. PDEVICECOLORINFO pDCI;
  2954. CHBINFO CHBInfo;
  2955. CTSTD_UNION CTSTDUnion;
  2956. LONG Result;
  2957. WORD PatCX;
  2958. WORD PatCY;
  2959. BYTE PatIndex;
  2960. if ((PatIndex = pStdMonoPattern->PatternIndex) > HT_SMP_MAX_INDEX) {
  2961. HTAPI_RET(HTAPI_IDX_CREATE_SMP, HTERR_INVALID_STDMONOPAT_INDEX);
  2962. }
  2963. CTSTDUnion.b.cbPrim =
  2964. CTSTDUnion.b.SrcOrder =
  2965. CTSTDUnion.b.BMFDest =
  2966. CTSTDUnion.b.DestOrder = 0;
  2967. if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
  2968. NULL,
  2969. NULL,
  2970. 0,
  2971. 0,
  2972. CTSTDUnion.b,
  2973. &Result))) {
  2974. HTAPI_RET(HTAPI_IDX_CREATE_SMP, Result);
  2975. }
  2976. if (PatIndex >= HT_SMP_PERCENT_SCREEN_START) {
  2977. CHBInfo.DestScanLineAlignBytes = pStdMonoPattern->ScanLineAlignBytes;
  2978. PatCX = pStdMonoPattern->cxPels = pDCI->HTCell.cxReal;
  2979. PatCY = pStdMonoPattern->cyPels = pDCI->HTCell.Height;
  2980. pStdMonoPattern->BytesPerScanLine = (WORD)
  2981. ComputeBytesPerScanLine((UINT)BMF_1BPP,
  2982. (UINT)CHBInfo.DestScanLineAlignBytes,
  2983. (DWORD)PatCX);
  2984. CHBInfo.Flags = CHBF_BW_ONLY;
  2985. if (pStdMonoPattern->pPattern) {
  2986. BYTE rgb[3];
  2987. COLORTRIAD ColorTriad;
  2988. rgb[0] =
  2989. rgb[1] =
  2990. rgb[0] = (BYTE)(HT_SMP_MAX_INDEX - PatIndex);
  2991. ColorTriad.Type = (BYTE)COLOR_TYPE_RGB;
  2992. ColorTriad.BytesPerPrimary = (BYTE)sizeof(BYTE);
  2993. ColorTriad.BytesPerEntry = (BYTE)(sizeof(BYTE) * 3);
  2994. ColorTriad.PrimaryOrder = PRIMARY_ORDER_RGB;
  2995. ColorTriad.PrimaryValueMax = (FD6)100;
  2996. ColorTriad.ColorTableEntries = 1;
  2997. ColorTriad.pColorTable = (LPVOID)rgb;
  2998. if (pStdMonoPattern->Flags & SMP_0_IS_BLACK) {
  2999. CHBInfo.Flags |= CHBF_USE_ADDITIVE_PRIMS;
  3000. }
  3001. if (!(pStdMonoPattern->Flags & SMP_TOPDOWN)) {
  3002. CHBInfo.Flags |= CHBF_BOTTOMUP_BRUSH;
  3003. }
  3004. CHBInfo.DestSurfaceFormat = BMF_1BPP;
  3005. CHBInfo.DestPrimaryOrder = PRIMARY_ORDER_123;
  3006. Result = HT_CreateHalftoneBrush(pDeviceHalftoneInfo,
  3007. NULL,
  3008. &ColorTriad,
  3009. CHBInfo,
  3010. (LPVOID)pStdMonoPattern->pPattern);
  3011. } else {
  3012. Result = (LONG)pStdMonoPattern->BytesPerScanLine *
  3013. (LONG)PatCY;
  3014. }
  3015. } else {
  3016. Result = GetCachedSMP(pDCI, pStdMonoPattern);
  3017. }
  3018. RELEASE_HTMUTEX(pDCI->HTMutex);
  3019. DBGP_IF(DBGP_SHOWPAT,
  3020. LPBYTE pCurPat;
  3021. LPBYTE pPatScan;
  3022. BYTE Buf1[80];
  3023. BYTE Buf2[80];
  3024. BYTE Buf3[80];
  3025. BYTE Digit1;
  3026. BYTE Digit2;
  3027. WORD Index;
  3028. WORD XInc;
  3029. WORD YInc;
  3030. BYTE Mask;
  3031. BOOL Swap;
  3032. DBGP_IF(DBGP_HTAPI,
  3033. DBGP("HT_CreateStandardMonoPattern(%d) = %ld"
  3034. ARGI(PatIndex - HT_SMP_PERCENT_SCREEN_START)
  3035. ARGDW(Result)));
  3036. if ((Result > 0) && (pPatScan = pStdMonoPattern->pPattern)) {
  3037. Swap = (BOOL)(pStdMonoPattern->Flags & SMP_0_IS_BLACK);
  3038. FillMemory(Buf1, 80, ' ');
  3039. FillMemory(Buf2, 80, ' ');
  3040. Digit1 = 0;
  3041. Digit2 = 0;
  3042. Index = 4;
  3043. XInc = pStdMonoPattern->cxPels;
  3044. while ((XInc--) && (Index < 79)) {
  3045. if (!Digit2) {
  3046. Buf1[Index] = (BYTE)(Digit1 + '0');
  3047. if (++Digit1 == 10) {
  3048. Digit1 = 0;
  3049. }
  3050. }
  3051. Buf2[Index] = (BYTE)(Digit2 + '0');
  3052. if (++Digit2 == 10) {
  3053. Digit2 = 0;
  3054. }
  3055. ++Index;
  3056. }
  3057. Buf1[Index] = Buf2[Index] = 0;
  3058. DBGP("%s" ARG(Buf1));
  3059. DBGP("%s\r\n" ARG(Buf2));
  3060. for (YInc = 0; YInc < pStdMonoPattern->cyPels; YInc++) {
  3061. Index = (WORD)sprintf(Buf3, "%3u ", YInc);
  3062. pCurPat = pPatScan;
  3063. for (XInc = 0, Mask = 0x80;
  3064. XInc < pStdMonoPattern->cxPels;
  3065. XInc++) {
  3066. if (Swap) {
  3067. Buf3[Index] = (BYTE)((*pCurPat & Mask) ? '' : '');
  3068. } else {
  3069. Buf3[Index] = (BYTE)((*pCurPat & Mask) ? '' : '');
  3070. }
  3071. if (!(Mask >>= 1)) {
  3072. Mask = 0x80;
  3073. ++pCurPat;
  3074. }
  3075. if (++Index > 75) {
  3076. Index = 75;
  3077. }
  3078. }
  3079. sprintf(&Buf3[Index], " %-3u", YInc);
  3080. DBGP("%s" ARG(Buf3));
  3081. pPatScan += pStdMonoPattern->BytesPerScanLine;
  3082. }
  3083. DBGP("\r\n%s" ARG(Buf2));
  3084. DBGP("%s" ARG(Buf1));
  3085. }
  3086. )
  3087. HTAPI_RET(HTAPI_IDX_CREATE_SMP, Result);
  3088. }
  3089. LONG
  3090. HTENTRY
  3091. CheckABInfo(
  3092. PBITBLTPARAMS pBBP,
  3093. UINT SrcSurfFormat,
  3094. UINT DstSurfFormat,
  3095. LPWORD pForceFlags,
  3096. PLONG pcOutMax
  3097. )
  3098. /*++
  3099. Routine Description:
  3100. Arguments:
  3101. Return Value:
  3102. Author:
  3103. 04-Mar-1999 Thu 18:41:06 created -by- Daniel Chou (danielc)
  3104. Revision History:
  3105. --*/
  3106. {
  3107. PABINFO pABInfo;
  3108. LONG cOutMax;
  3109. WORD ForceFlags;
  3110. if (!(pABInfo = pBBP->pABInfo)) {
  3111. return(HTERR_INVALID_ABINFO);
  3112. }
  3113. switch (DstSurfFormat) {
  3114. case BMF_1BPP:
  3115. cOutMax = 2;
  3116. break;
  3117. case BMF_4BPP:
  3118. case BMF_4BPP_VGA16:
  3119. cOutMax = 16;
  3120. break;
  3121. case BMF_8BPP:
  3122. case BMF_8BPP_VGA256:
  3123. cOutMax = 256;
  3124. break;
  3125. default:
  3126. cOutMax = 0;
  3127. break;
  3128. }
  3129. if (cOutMax) {
  3130. if ((pABInfo->pDstPal == NULL) ||
  3131. (pABInfo->cDstPal > cOutMax)) {
  3132. return(HTERR_INVALID_ABINFO);
  3133. }
  3134. }
  3135. *pForceFlags |= ADJ_FORCE_ALPHA_BLEND;
  3136. if (pABInfo->Flags & ABIF_USE_CONST_ALPHA_VALUE) {
  3137. switch (pABInfo->ConstAlphaValue) {
  3138. case 0:
  3139. //
  3140. // We do not need to do anything
  3141. //
  3142. return(0);
  3143. case 0xFF:
  3144. *pForceFlags &= ~ADJ_FORCE_ALPHA_BLEND;
  3145. cOutMax = 0;
  3146. break;
  3147. default:
  3148. *pForceFlags |= ADJ_FORCE_CONST_ALPHA;
  3149. break;
  3150. }
  3151. } else if (SrcSurfFormat != BMF_32BPP) {
  3152. return(HTERR_INVALID_SRC_FORMAT);
  3153. } else {
  3154. if (pABInfo->Flags & ABIF_SRC_ALPHA_IS_PREMUL) {
  3155. *pForceFlags |= ADJ_FORCE_AB_PREMUL_SRC;
  3156. }
  3157. if (pABInfo->Flags & ABIF_BLEND_DEST_ALPHA) {
  3158. if (DstSurfFormat != BMF_32BPP) {
  3159. return(HTERR_INVALID_DEST_FORMAT);
  3160. }
  3161. *pForceFlags |= ADJ_FORCE_AB_DEST;
  3162. }
  3163. }
  3164. *pcOutMax = cOutMax;
  3165. return(1);
  3166. }
  3167. LONG
  3168. APIENTRY
  3169. HT_LOADDS
  3170. HT_HalftoneBitmap(
  3171. PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
  3172. PHTCOLORADJUSTMENT pHTColorAdjustment,
  3173. PHTSURFACEINFO pSourceHTSurfaceInfo,
  3174. PHTSURFACEINFO pSourceMaskHTSurfaceInfo,
  3175. PHTSURFACEINFO pDestinationHTSurfaceInfo,
  3176. PBITBLTPARAMS pBitbltParams
  3177. )
  3178. /*++
  3179. Routine Description:
  3180. This function halftone the source bitmap and output to the destination
  3181. surface depends on the surface type and bitblt parameters
  3182. The source surface type must one of the following:
  3183. 1-bit per pel. (BMF_1BPP)
  3184. 4-bit per pel. (BMF_4BPP)
  3185. 8-bit per pel. (BMF_8BPP)
  3186. 16-bit per pel. (BMF_16BPP)
  3187. 24-bit per pel. (BMF_24BPP)
  3188. 32-bit per pel. (BMF_32BPP)
  3189. The destination surface type must one of the following:
  3190. 1-bit per pel. (BMF_1BPP)
  3191. 4-bit per pel. (BMF_4BPP)
  3192. 3 plane and 1 bit per pel. (BMF_1BPP_3PLANES)
  3193. Arguments:
  3194. pDeviceHalftoneInfo - pointer to the DEVICEHALFTONEINFO data
  3195. structure
  3196. pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data
  3197. structure to specified the input/output color
  3198. adjustment/transform, if this pointer is NULL
  3199. then a default color adjustments is applied.
  3200. pSourceHTSurfaceInfo - pointer to the source surface infomation.
  3201. pSourceMaskHTSurfaceInfo - pointer to the source mask surface infomation,
  3202. if this pointer is NULL then there is no
  3203. source mask for the halftoning.
  3204. pDestinationHTSurfaceInfo - pointer to the destination surface infomation.
  3205. pBitbltParams - pointer to the BITBLTPARAMS data structure to
  3206. specified the source, destination, source
  3207. mask and clipping rectangle information, the
  3208. content of this data structure will not be
  3209. modified by this function.
  3210. Return Value:
  3211. if the return value is less than zero then an error has occurred,
  3212. the error code is one of the following #define which start with HTERR_.
  3213. HTERR_INSUFFICIENT_MEMORY - not enough memory to do the halftone
  3214. process.
  3215. HTERR_COLORTABLE_TOO_BIG - can not create the color table to map
  3216. the colors to the dyes' densities.
  3217. HTERR_QUERY_SRC_BITMAP_FAILED - callback function return FALSE when
  3218. query the source bitmap pointer.
  3219. HTERR_QUERY_DEST_BITMAP_FAILED - callback function return FALSE when
  3220. query the destination bitmap pointers.
  3221. HTERR_INVALID_SRC_FORMAT - Invalid source surface format.
  3222. HTERR_INVALID_DEST_FORMAT - Invalid destination surface type,
  3223. this function only recongnized 1/4/
  3224. bits per pel source surfaces or 1 bit
  3225. per pel 3 planes.
  3226. HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is passed.
  3227. HTERR_SRC_MASK_BITS_TOO_SMALL - If the source mask bitmap is too
  3228. small to cover the visible region of
  3229. the source bitmap.
  3230. HTERR_INVALID_MAX_QUERYLINES - One or more of Source/Destination
  3231. SourceMasks' maximum query scan line
  3232. is < 0
  3233. HTERR_INTERNAL_ERRORS_START - any other negative numbers indicate
  3234. a halftone internal failue.
  3235. else - the total destination scan lines
  3236. halftoned.
  3237. Author:
  3238. 05-Feb-1991 Tue 15:23:07 created -by- Daniel Chou (danielc)
  3239. Revision History:
  3240. --*/
  3241. {
  3242. PDEVICECOLORINFO pDCI;
  3243. PHALFTONERENDER pHR;
  3244. PAAHEADER pAAHdr;
  3245. PDEVCLRADJ pDevClrAdj;
  3246. PRGB4B pClrTable;
  3247. PABINFO pABInfo;
  3248. LONG Result;
  3249. WORD ForceFlags;
  3250. WORD BBPFlags;
  3251. CTSTD_UNION CTSTDUnion;
  3252. LONG cInPal;
  3253. LONG cInMax;
  3254. LONG cOutMax;
  3255. BYTE SrcSurfFormat;
  3256. BYTE DstSurfFormat;
  3257. CONST static BYTE MaxPal_0148_LS[4] = { 0, 1, 4, 8 };
  3258. DBG_TIMER_RESET;
  3259. SrcSurfFormat = pSourceHTSurfaceInfo->SurfaceFormat;
  3260. DstSurfFormat = pDestinationHTSurfaceInfo->SurfaceFormat;
  3261. BBPFlags = pBitbltParams->Flags;
  3262. ForceFlags = 0;
  3263. cInPal =
  3264. cInMax =
  3265. cOutMax = 0;
  3266. switch (SrcSurfFormat) {
  3267. case BMF_1BPP:
  3268. case BMF_4BPP:
  3269. case BMF_8BPP:
  3270. cInMax = (UINT)0x01 << MaxPal_0148_LS[SrcSurfFormat];
  3271. if (pSourceHTSurfaceInfo->pColorTriad) {
  3272. cInPal = (LONG)pSourceHTSurfaceInfo->pColorTriad->ColorTableEntries;
  3273. }
  3274. if (!cInPal) {
  3275. HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INVALID_COLOR_TABLE);
  3276. }
  3277. default:
  3278. break;
  3279. }
  3280. if ((BBPFlags & BBPF_DO_ALPHA_BLEND) &&
  3281. ((Result = CheckABInfo(pBitbltParams,
  3282. SrcSurfFormat,
  3283. DstSurfFormat,
  3284. &ForceFlags,
  3285. &cOutMax)) <= 0)) {
  3286. HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
  3287. }
  3288. DBGP_IF(DBGP_SRCBMP,
  3289. DBGP("SrcFmt=%ld, cInPal=%ld (%ld), DstFmt=%ld, cOutMax=%ld"
  3290. ARGDW(SrcSurfFormat) ARGDW(cInMax) ARGDW(cInPal)
  3291. ARGDW(DstSurfFormat) ARGDW(cOutMax)));
  3292. CTSTDUnion.b.cbPrim = 0;
  3293. CTSTDUnion.b.SrcOrder = PRIMARY_ORDER_BGR;
  3294. CTSTDUnion.b.BMFDest = (BYTE)DstSurfFormat;
  3295. CTSTDUnion.b.DestOrder = (BYTE)pBitbltParams->DestPrimaryOrder;
  3296. if (BBPFlags & BBPF_USE_ADDITIVE_PRIMS) {
  3297. ForceFlags |= ADJ_FORCE_ADDITIVE_PRIMS;
  3298. }
  3299. if (BBPFlags & BBPF_NEGATIVE_DEST) {
  3300. ForceFlags |= ADJ_FORCE_NEGATIVE;
  3301. }
  3302. if ((BBPFlags & BBPF_BW_ONLY) ||
  3303. (CTSTDUnion.b.BMFDest == BMF_1BPP)) {
  3304. ForceFlags |= ADJ_FORCE_MONO;
  3305. }
  3306. if (BBPFlags & BBPF_ICM_ON) {
  3307. ForceFlags |= ADJ_FORCE_ICM;
  3308. }
  3309. //
  3310. // Find out if we will call anti-aliasing codes
  3311. //
  3312. ASSERTMSG("Source X is not well ordered",
  3313. pBitbltParams->rclSrc.right >= pBitbltParams->rclSrc.left);
  3314. ASSERTMSG("Source Y is not well ordered",
  3315. pBitbltParams->rclSrc.bottom >= pBitbltParams->rclSrc.top);
  3316. if (BBPFlags & BBPF_NO_ANTIALIASING) {
  3317. ForceFlags |= ADJ_FORCE_NO_EXP_AA;
  3318. }
  3319. //
  3320. // Now Compute the Device Color Adjusment data
  3321. //
  3322. if (!(pDCI = pDCIAdjClr(pDeviceHalftoneInfo,
  3323. pHTColorAdjustment,
  3324. &pDevClrAdj,
  3325. sizeof(HALFTONERENDER) + sizeof(AAHEADER) +
  3326. ((cInMax + cOutMax) * sizeof(RGB4B)),
  3327. ForceFlags,
  3328. CTSTDUnion.b,
  3329. &Result))) {
  3330. HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
  3331. }
  3332. pHR = (PHALFTONERENDER)(pDevClrAdj + 1);
  3333. //
  3334. // We will mask out the more flags, since this flag is currently used
  3335. // internally.
  3336. //
  3337. pHR->pDeviceColorInfo = pDCI;
  3338. pHR->pDevClrAdj = pDevClrAdj;
  3339. pHR->pBitbltParams = pBitbltParams;
  3340. pHR->pSrcSI = pSourceHTSurfaceInfo;
  3341. pHR->pSrcMaskSI = pSourceMaskHTSurfaceInfo;
  3342. pHR->pDestSI = pDestinationHTSurfaceInfo;
  3343. pAAHdr = (PAAHEADER)(pHR->pAAHdr = (LPVOID)(pHR + 1));
  3344. pClrTable = (PRGB4B)(pAAHdr + 1);
  3345. if (cInMax) {
  3346. pAAHdr->SrcSurfInfo.cClrTable = (WORD)cInPal;
  3347. pAAHdr->SrcSurfInfo.pClrTable = (PRGB4B)pClrTable;
  3348. pClrTable += cInMax;
  3349. }
  3350. if (ForceFlags & ADJ_FORCE_ALPHA_BLEND) {
  3351. if ((!(pDCI->pAlphaBlendBGR)) &&
  3352. (!(pDCI->pAlphaBlendBGR = (LPBYTE)HTAllocMem(pDCI,
  3353. HTMEM_AlphaBlendBGR,
  3354. LPTR,
  3355. AB_DCI_SIZE)))) {
  3356. RELEASE_HTMUTEX(pDCI->HTMutex);
  3357. HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, HTERR_INSUFFICIENT_MEMORY);
  3358. }
  3359. if (ForceFlags & ADJ_FORCE_CONST_ALPHA) {
  3360. pDCI->PrevConstAlpha = pDCI->CurConstAlpha;
  3361. pDCI->CurConstAlpha = pBitbltParams->pABInfo->ConstAlphaValue;
  3362. }
  3363. if (cOutMax) {
  3364. pAAHdr->DstSurfInfo.pClrTable = (PRGB4B)pClrTable;
  3365. pAAHdr->DstSurfInfo.cClrTable =
  3366. (WORD)pBitbltParams->pABInfo->cDstPal;
  3367. }
  3368. }
  3369. pAAHdr->SrcSurfInfo.AABFData.Format = (BYTE)SrcSurfFormat;
  3370. pAAHdr->DstSurfInfo.AABFData.Format = (BYTE)DstSurfFormat;
  3371. if (BBPFlags & BBPF_TILE_SRC) {
  3372. //
  3373. // Remove SrcMask if TILE_SRC is used
  3374. //
  3375. pHR->pSrcMaskSI = NULL;
  3376. }
  3377. //-----------------------------------------------------------------------
  3378. // The semaphore pDCI->HTMutex will be released by AAHalftoneBitmap
  3379. //-----------------------------------------------------------------------
  3380. Result = AAHalftoneBitmap(pHR);
  3381. if (HTFreeMem(pDevClrAdj)) {
  3382. ASSERTMSG("HTFreeMem(pDevClrAdj) Failed", FALSE);
  3383. }
  3384. DBGP_IF(DBGP_HTAPI,
  3385. DBGP("HT_HalftoneBitmap(%ld/%6ld): Src[%ld]=(%4ld,%4ld)-(%4ld,%4ld), Dst[%ld]=(%4ld,%4ld)-(%4ld,%4ld) [0x%04lx]"
  3386. ARGDW(pDCI->cbMemTot) ARGDW(pDCI->cbMemMax)
  3387. ARGDW(SrcSurfFormat)
  3388. ARGDW(pBitbltParams->rclSrc.left)
  3389. ARGDW(pBitbltParams->rclSrc.top)
  3390. ARGDW(pBitbltParams->rclSrc.right)
  3391. ARGDW(pBitbltParams->rclSrc.bottom)
  3392. ARGDW(DstSurfFormat)
  3393. ARGDW(pBitbltParams->rclDest.left)
  3394. ARGDW(pBitbltParams->rclDest.top)
  3395. ARGDW(pBitbltParams->rclDest.right)
  3396. ARGDW(pBitbltParams->rclDest.bottom)
  3397. ARGDW(BBPFlags)));
  3398. DBGP_IF(DBGP_MEMLINK,
  3399. DumpMemLink(NULL, 0);
  3400. DumpMemLink((LPVOID)pDCI, 0);
  3401. )
  3402. DBGP_IF(DBGP_TIMER,
  3403. UINT i;
  3404. DBG_TIMER_END(TIMER_TOT);
  3405. DbgTimer[TIMER_LAST].Tot = DbgTimer[TIMER_TOT].Tot;
  3406. for (i = 1; i < TIMER_LAST; i++) {
  3407. DbgTimer[TIMER_LAST].Tot -= DbgTimer[i].Tot;
  3408. }
  3409. DBGP("HTBlt(%s): Setup=%s, AA=%s, In=%s, Out=%s, Mask=%s, Fmt=%ld->%ld [%02lx]"
  3410. ARGTIME(TIMER_TOT)
  3411. ARGTIME(TIMER_SETUP)
  3412. ARGTIME(TIMER_LAST)
  3413. ARGTIME(TIMER_INPUT)
  3414. ARGTIME(TIMER_OUTPUT)
  3415. ARGTIME(TIMER_MASK)
  3416. ARGDW(pSourceHTSurfaceInfo->SurfaceFormat)
  3417. ARGDW(pDevClrAdj->DMI.CTSTDInfo.BMFDest)
  3418. ARGDW(pDevClrAdj->DMI.Flags));
  3419. )
  3420. HTAPI_RET(HTAPI_IDX_HALFTONE_BMP, Result);
  3421. }
  3422. LONG
  3423. APIENTRY
  3424. HT_LOADDS
  3425. HT_GammaCorrectPalette(
  3426. LPPALETTEENTRY pPaletteEntry,
  3427. LONG cPalette,
  3428. UDECI4 RedGamma,
  3429. UDECI4 GreenGamma,
  3430. UDECI4 BlueGamma
  3431. )
  3432. /*++
  3433. Routine Description:
  3434. This functions retrieve a halftone's VGA256 color table definitions
  3435. Arguments:
  3436. pPaletteEntry - Pointer to PALETTEENTRY data structure array,
  3437. cPalette - Total palette passed by the pPaletteEntry
  3438. RedGamma - The monitor's red gamma value in UDECI4 format
  3439. GreenGamma - The monitor's green gamma value in UDECI4 format
  3440. BlueGamma - The monitor's blue gamma value in UDECI4 format
  3441. Return Value:
  3442. if pPaletteEntry is NULL then it return the PALETTEENTRY count needed for
  3443. VGA256 halftone process, if it is not NULL then it return the total
  3444. paletteEntry updated.
  3445. If the pPaletteEntry is not NULL then halftone.dll assume it has enough
  3446. space for the size returned when this pointer is NULL.
  3447. Author:
  3448. 14-Apr-1992 Tue 13:03:21 created -by- Daniel Chou (danielc)
  3449. Revision History:
  3450. --*/
  3451. {
  3452. FD6 RGBGamma[3];
  3453. LONG cPal;
  3454. FD6 Yr;
  3455. FD6 Yg;
  3456. FD6 Yb;
  3457. BYTE r;
  3458. BYTE g;
  3459. BYTE b;
  3460. //
  3461. // Initialize All internal data first
  3462. //
  3463. if ((cPal = cPalette) && (pPaletteEntry)) {
  3464. RGBGamma[0] = UDECI4ToFD6(RedGamma);
  3465. RGBGamma[1] = UDECI4ToFD6(GreenGamma);
  3466. RGBGamma[2] = UDECI4ToFD6(BlueGamma);
  3467. DBGP_IF(DBGP_GAMMA_PAL,
  3468. DBGP("***** HT_GammaCorrectPalette: %s:%s:%s *****"
  3469. ARGFD6(RGBGamma[0], 1, 4)
  3470. ARGFD6(RGBGamma[1], 1, 4)
  3471. ARGFD6(RGBGamma[2], 1, 4)));
  3472. while (cPalette--) {
  3473. Yr = (FD6)DivFD6(r = pPaletteEntry->peRed, 255);
  3474. Yg = (FD6)DivFD6(g = pPaletteEntry->peGreen, 255);
  3475. Yb = (FD6)DivFD6(b = pPaletteEntry->peBlue, 255);
  3476. pPaletteEntry->peRed = RGB_8BPP(Yr);
  3477. pPaletteEntry->peGreen = RGB_8BPP(Yg);
  3478. pPaletteEntry->peBlue = RGB_8BPP(Yb);
  3479. pPaletteEntry->peFlags = 0;
  3480. DBGP_IF(DBGP_GAMMA_PAL,
  3481. DBGP("%3u - %3u:%3u:%3u --> %3u:%3u:%3u"
  3482. ARGU(cPalette)
  3483. ARGU(r) ARGU(g) ARGU(b)
  3484. ARGU(pPaletteEntry->peRed )
  3485. ARGU(pPaletteEntry->peGreen)
  3486. ARGU(pPaletteEntry->peBlue )));
  3487. ++pPaletteEntry;
  3488. }
  3489. }
  3490. return((LONG)cPal);
  3491. }
  3492. LONG
  3493. APIENTRY
  3494. HT_LOADDS
  3495. HT_ConvertColorTable(
  3496. PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
  3497. PHTCOLORADJUSTMENT pHTColorAdjustment,
  3498. PCOLORTRIAD pColorTriad,
  3499. DWORD Flags
  3500. )
  3501. /*++
  3502. Routine Description:
  3503. This function modified input color table entries base on the
  3504. pHTColorAdjustment data structure specification.
  3505. Arguments:
  3506. pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
  3507. which returned from the HT_CreateDeviceHalftoneInfo.
  3508. pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data structure to
  3509. specified the input/output color adjustment/transform,
  3510. if this pointer is NULL then a default color
  3511. adjustments is applied.
  3512. pColorTriad - Specified the source color table format and location.
  3513. Flags - One of the following may be specified
  3514. CCTF_BW_ONLY
  3515. Create grayscale of the color table.
  3516. CCTF_NEGATIVE
  3517. Create negative version of the original color
  3518. table.
  3519. Return Value:
  3520. if the return value is negative or zero then an error was encountered,
  3521. possible error codes are
  3522. HTERR_INVALID_COLOR_TABLE - The ColorTableEntries field is = 0 or
  3523. CCTInfo.SizePerColorTableEntry is not
  3524. between 3 to 255, or if the
  3525. CCTInfo.FirstColorIndex in CCTInfo is
  3526. not in the range of 0 to
  3527. (SizePerColorTableEntry - 3).
  3528. HTERR_INVALID_DHI_POINTER - Invalid pDevideHalftoneInfo is passed.
  3529. otherwise
  3530. Total entries of the converted color table is returned.
  3531. Author:
  3532. 14-Aug-1991 Wed 12:43:29 updated -by- Daniel Chou (danielc)
  3533. Revision History:
  3534. 16-Feb-1993 Tue 00:10:56 updated -by- Daniel Chou (danielc)
  3535. Fixes bug #10448 which create all black densitities brushes, this
  3536. was caused by not initialized ColorTriad.PrimaryOrder.
  3537. --*/
  3538. {
  3539. PDEVICECOLORINFO pDCI;
  3540. PDEVCLRADJ pDevClrAdj;
  3541. CTSTD_UNION CTSTDUnion;
  3542. WORD ForceFlags;
  3543. LONG Result;
  3544. return(HTERR_COLORTABLE_TOO_BIG);
  3545. }