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.

2583 lines
71 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. htblt.c
  5. Abstract:
  6. This module contains all halftone bitblt functions.
  7. Development History:
  8. 26-Mar-1992 Thu 23:54:07 updated
  9. 1) add the prclBound parameter to the bDoClipObj()
  10. 2) Remove 'pco' parameter and replaced it with prclClipBound parameter,
  11. since pco is never referenced, prclClipBound is used for the
  12. halftone.
  13. 3) Add another parameter to do NOTSRCCOPY
  14. 11-Feb-1993 Thu 21:32:07 updated
  15. Major re-write to have DrvStretchBlt(), DrvCopyBits) do the right
  16. things.
  17. 15-Nov-1993 Mon 19:28:03 updated
  18. clean up/debugging information
  19. 06-Dec-1993 Mon 19:28:03 updated
  20. Made all bitblt go through HandleComplexBitmap.
  21. 18-Dec-1993 Sat 08:52:56 updated
  22. Move halftone related stuff to htblt.c
  23. 18-Mar-1994 Fri 14:00:14 updated
  24. Adding PLOTF_RTL_NO_DPI_XY, PLOTF_RTLMONO_NO_CID and
  25. PLOTF_RTLMONO_FIXPAL flags
  26. [Environment:]
  27. GDI Device Driver - Plotter.
  28. [Notes:]
  29. Revision History:
  30. --*/
  31. #include "precomp.h"
  32. #pragma hdrstop
  33. #define DBG_PLOTFILENAME DbgHTBlt
  34. #define DBG_HTBLT 0x00000001
  35. #define DBG_ISHTBITS 0x00000002
  36. #define DBG_HTXB 0x00000004
  37. #define DBG_OUTHTBMP 0x00000008
  38. #define DBG_HTBLT_SKIP 0x00000010
  39. #define DBG_TILEBLT 0x00000020
  40. #define DBG_CREATESURFOBJ 0x00000040
  41. #define DBG_BMPDELTA 0x00000080
  42. #define DBG_CLONESURFOBJ 0x00000100
  43. #define DBG_CLONEMASK 0x00000200
  44. #define DBG_HTBLT_CLR 0x00000400
  45. DEFINE_DBGVAR(0);
  46. //
  47. // This is the local structure used in this module only
  48. //
  49. #define SEND_PLOTCMDS(pPDev,pcmd) OutputBytes(pPDev,(pcmd)+1,(LONG)*(pcmd))
  50. #define COPY_PLOTCMDS(cmd,ps,s) if (sizeof(cmd) > cmd[0]+s){CopyMemory(&cmd[cmd[0]+1],ps,s); cmd[0]+=s;}
  51. #define INIT_PLOTCMDS(cmd) cmd[0]=0
  52. #define CHECK_PLOTCMDS(cmd) \
  53. { \
  54. cmd[cmd[0]+1]=0; PLOTASSERT(1,"Command buffer MUST > %ld bytes", \
  55. cmd[0]<sizeof(cmd),sizeof(cmd)); \
  56. }
  57. #define DELETE_SURFOBJ(pso, phBmp) \
  58. { \
  59. if (pso) { EngUnlockSurface(pso); pso=NULL; } \
  60. if (*(phBmp)) { EngDeleteSurface((HSURF)*(phBmp)); *(phBmp)=NULL; } \
  61. }
  62. typedef struct _RTLCLRCONFIG {
  63. BYTE ColorModel;
  64. BYTE EncodingMode;
  65. BYTE BitsPerIndex;
  66. BYTE BitsPerR;
  67. BYTE BitsPerG;
  68. BYTE BitsPerB;
  69. } RTLCLRCONFIG, FAR *PRTLCLRCONFIG;
  70. const POINTL ptlZeroOrigin = {0,0};
  71. static const OUTHTBMPFUNC HTBmpFuncTable[] = { Output1bppHTBmp,
  72. Output1bppRotateHTBmp,
  73. Output4bppHTBmp,
  74. Output4bppRotateHTBmp };
  75. #if DBG
  76. static const LPSTR pszHTBmpFunc[] = { "Output1bppHTBmp",
  77. "Output1bppRotateHTBmp",
  78. "Output4bppHTBmp",
  79. "Output4bppRotateHTBmp" };
  80. #endif
  81. #define DEF_MONOPALIDX_0 0xFFFFFF
  82. #define DEF_MONOPALIDX_1 0x000000
  83. #define DEVTODECI(pPdev, x) DIVRNDUP((x) * 720, (pPDev)->lCurResolution)
  84. #define MAX_HP_Y_MOVE 32767
  85. static BYTE StartGraf[] = "\033*r#ds1A";
  86. static BYTE EndGraf[] = "\033*rC";
  87. static BYTE XMoveDECI[] = "\033&a0h#dH";
  88. static BYTE YMoveDECI[] = "\033*b#dY";
  89. static BYTE YMoveDPI[] = "\033*p#pY";
  90. static BYTE XYMoveDPI[] = "\033*p#px#pY";
  91. static BYTE SetRGBCmd[] = "\033*v#da#db#dc#dI";
  92. static DWORD DefWKPal[] = { 0x00FFFFFF, 0x00000000 };
  93. //
  94. // ROP2 used for devices that require BYTE ALIGNMENT of RTL data
  95. //
  96. #define HPBHF_nD_LAST 0x01
  97. #define HPBHF_nS 0x02
  98. #define HPBHF_1_FIRST 0x40
  99. #define HPBHF_PAD_1 0x80
  100. typedef struct _HPBAHACK {
  101. BYTE Rop3RTL;
  102. BYTE Flags;
  103. } HPBAHACK, *PHPBAHACK;
  104. //
  105. // 0x00: 0 [INV] 0xff: 1
  106. // 0x55: ~D [INV] 0xaa: D
  107. // 0x33: ~S [INV] 0xcc: S
  108. // 0x11: ~(D | S) [INV] 0xee: D | S
  109. // 0x22: D & ~S [INV] 0xdd: S | ~D
  110. // 0x44: S & ~D [INV] 0xbb: D | ~S
  111. // 0x66: D ^ S [INV] 0x99: ~(D ^ S)
  112. // 0x77: ~(D & S) [INV] 0x88: D & S
  113. //
  114. //
  115. // 1. HPBHF_PAD_1 - TRUE if we are not doing AND operation
  116. // 2. HPBHF_nS - If we have to manually flip the source
  117. // 3. HPBHF_nD_LAST - If we have to invert the source in HPGL2 afterward
  118. //
  119. //
  120. // Rop2 0x00, 0x05, 0x0A and 0x0F should not come to OutputHTBitmap
  121. //
  122. //
  123. // This table tells us how to simulate certain ROPS by combining rops that
  124. // the target device is known to support. Some times we end up having to
  125. // send the bitmap more than once, but it does end up coming out correctly.
  126. //
  127. static HPBAHACK HPBAHack[] = {
  128. { 0xAA, 0 }, // 0 0x00
  129. { 0xEE, HPBHF_PAD_1 | HPBHF_nD_LAST }, // SoD_n 0x01
  130. { 0x88, HPBHF_nS }, // nS_aD 0x02
  131. { 0xEE, HPBHF_1_FIRST | HPBHF_PAD_1 | HPBHF_nS }, // nS 0x03
  132. { 0xEE, HPBHF_PAD_1 | HPBHF_nS | HPBHF_nD_LAST }, // nS_oD_n 0x04
  133. { 0xAA, HPBHF_nD_LAST }, // nD 0x05
  134. { 0x66, HPBHF_PAD_1 }, // SxD 0x06
  135. { 0x88, HPBHF_nD_LAST }, // SaD_n 0x07
  136. { 0x88, }, // SaD 0x08
  137. { 0x66, HPBHF_PAD_1 | HPBHF_nD_LAST }, // SxD_n 0x09
  138. { 0xAA, 0 }, // D 0x0A
  139. { 0xEE, HPBHF_PAD_1 | HPBHF_nS }, // nS_oD 0x0B
  140. { 0xEE, HPBHF_1_FIRST | HPBHF_PAD_1 }, // S 0x0C
  141. { 0x88, HPBHF_nS | HPBHF_nD_LAST }, // nS_aD_n 0x0D
  142. { 0xEE, HPBHF_PAD_1 }, // SoD 0x0E
  143. { 0xAA, 0 } // 1 0x0F
  144. };
  145. //
  146. // To make it print correctly in poster mode for the BYTE ALIGNED plotters
  147. // we assume paper is white and do a SRC AND DST
  148. //
  149. #define ROP3_BYTEALIGN_POSTER 0x88
  150. extern PALENTRY HTPal[];
  151. BOOL
  152. IsHTCompatibleSurfObj(
  153. PPDEV pPDev,
  154. SURFOBJ *pso,
  155. XLATEOBJ *pxlo,
  156. DWORD Flags
  157. )
  158. /*++
  159. Routine Description:
  160. This function determines if the surface object is compatible with the
  161. plotter halftone output format.
  162. Arguments:
  163. pPDev - Pointer to the PPDEV data structure to determine what
  164. type of postscript output for current device
  165. pso - engine SURFOBJ to be examine
  166. pxlo - engine XLATEOBJ for source -> postscript translation
  167. Flags - specified ISHTF_xxxx
  168. Return Value:
  169. BOOLEAN true if the pso is compatible with halftone output format, if
  170. return value is true, the pDrvHTInfo->pHTXB is a valid traslation from
  171. indices to 3 planes
  172. Development History:
  173. 11-Feb-1993 Thu 18:49:55 created
  174. 16-Mar-1994 Wed 14:24:04 updated
  175. Change it so if pxlo is NULL then the xlate will be match the pso
  176. format
  177. Revision History:
  178. --*/
  179. {
  180. LPPALETTEENTRY pPal;
  181. PDRVHTINFO pDrvHTInfo;
  182. PALETTEENTRY SrcPal[18];
  183. PPALENTRY pPalEntry;
  184. HTXB PalNibble[HTPAL_XLATE_COUNT];
  185. ULONG HTPalXor;
  186. UINT i;
  187. HTXB htXB;
  188. BOOL GenHTXB = FALSE;
  189. BOOL RetVal;
  190. BYTE PalXlate[HTPAL_XLATE_COUNT];
  191. UINT AltFmt;
  192. UINT BmpFormat;
  193. UINT cPal;
  194. if (!(pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData))) {
  195. PLOTERR(("IsHTCompatibleSurfObj: pDrvHTInfo = NULL?"));
  196. return(FALSE);
  197. }
  198. PLOTDBG(DBG_ISHTBITS, ("IsHTCompatibleSurfObj: Type=%ld, BMF=%ld",
  199. (DWORD)pso->iType, (DWORD)pso->iBitmapFormat));
  200. //
  201. // Make sure these fields' value are valid before the translation is
  202. // created:
  203. //
  204. // 1. pso->iBitmapFormat is one of 1BPP or 4BPP depending on current
  205. // PLOT's surface
  206. // 2. pxlo is non null
  207. // 3. pxlo->fXlate is XO_TABLE
  208. // 4. pxlo->cPal is less than or equal to the halftone palette count
  209. // 5. pxlo->pulXlate is valid
  210. // 6. source color table is within the range of the halftone palette
  211. //
  212. // If your device uses an indexed palette then you must call
  213. // XLATEOBJ_cGetPalette() to get the source palette and make sure that the
  214. // count returned is within your device's range, if we are a 24-bit device
  215. // then you can just get the source palette our from pxlo->pulxlate which
  216. // has the entire source palette for the bitmap
  217. //
  218. RetVal = FALSE;
  219. AltFmt = (UINT)((Flags & ISHTF_ALTFMT) ? pDrvHTInfo->AltBmpFormat : 0xFFFF);
  220. if ((pso->iType == STYPE_BITMAP) &&
  221. (BmpFormat = (UINT)pso->iBitmapFormat) &&
  222. ((BmpFormat == (UINT)pDrvHTInfo->HTBmpFormat) ||
  223. (BmpFormat == AltFmt))) {
  224. HTPalXor = pDrvHTInfo->HTPalXor;
  225. pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
  226. if (pxlo) {
  227. if (BmpFormat == BMF_4BPP) {
  228. i = (UINT)((Flags & ISHTF_HTXB) ? 8 : 16);
  229. } else {
  230. i = 2;
  231. }
  232. cPal = XLATEOBJ_cGetPalette(pxlo,
  233. XO_SRCPALETTE,
  234. sizeof(SrcPal) / sizeof(PALETTEENTRY),
  235. (ULONG *)SrcPal);
  236. PLOTDBG(DBG_ISHTBITS, ("pxlo: flXlate=%08lx, SrcType=%ld, DstType=%ld, cPal=%ld",
  237. (DWORD)pxlo->flXlate,
  238. (DWORD)pxlo->iSrcType,
  239. (DWORD)pxlo->iDstType, cPal));
  240. if ((cPal) && (cPal <= i)) {
  241. PLOTDBG(DBG_ISHTBITS,
  242. ("IsHTCompatibleSurfObj: HTPalXor=%08lx", HTPalXor));
  243. RetVal = TRUE;
  244. for (i = 0, pPal = SrcPal; i < cPal && i < sizeof(PalXlate); i++, pPal++ ) {
  245. HTXB_R(htXB) = pPal->peRed;
  246. HTXB_G(htXB) = pPal->peGreen;
  247. HTXB_B(htXB) = pPal->peBlue;
  248. htXB.dw ^= HTPalXor;
  249. if (((HTXB_R(htXB) != PAL_MAX_I) &&
  250. (HTXB_R(htXB) != PAL_MIN_I)) ||
  251. ((HTXB_G(htXB) != PAL_MAX_I) &&
  252. (HTXB_G(htXB) != PAL_MIN_I)) ||
  253. ((HTXB_B(htXB) != PAL_MAX_I) &&
  254. (HTXB_B(htXB) != PAL_MIN_I))) {
  255. PLOTDBG(DBG_ISHTBITS,
  256. ("SrcPal has NON 0xff/0x00 intensity, NOT HTPalette"));
  257. return(FALSE);
  258. }
  259. PalXlate[i] =
  260. HTXB_I(htXB) = (BYTE)((HTXB_R(htXB) & 0x01) |
  261. (HTXB_G(htXB) & 0x02) |
  262. (HTXB_B(htXB) & 0x04));
  263. PalNibble[i] = htXB;
  264. if (pDrvHTInfo->PalXlate[i] != HTXB_I(htXB)) {
  265. GenHTXB = TRUE;
  266. }
  267. PLOTDBG(DBG_HTXB,
  268. ("%d - %02x:%02x:%02x, Idx=%d, PalXlate=%d",
  269. i,
  270. (BYTE)HTXB_R(htXB),
  271. (BYTE)HTXB_G(htXB),
  272. (BYTE)HTXB_B(htXB),
  273. (INT)PalXlate[i],
  274. (INT)pDrvHTInfo->PalXlate[i]));
  275. }
  276. if (BmpFormat == (UINT)BMF_1BPP) {
  277. //
  278. // For 1 BPP, if the DSTPRIM_OK is set and the destination
  279. // is 4BPP then we will deem the surfaces compatible
  280. //
  281. if ((Flags & ISHTF_DSTPRIM_OK) &&
  282. ((pDrvHTInfo->HTBmpFormat == BMF_4BPP) ||
  283. (AltFmt == BMF_4BPP))) {
  284. NULL;
  285. } else if (((PalXlate[0] != 0) && (PalXlate[0] != 7)) ||
  286. ((PalXlate[1] != 0) && (PalXlate[1] != 7))) {
  287. RetVal = FALSE;
  288. PLOTDBG(DBG_HTXB, ("NON-BLACK/WHITE MONO BITMAP, NOT HTPalette"));
  289. }
  290. }
  291. }
  292. } else {
  293. //
  294. // If the pxlo is NULL and the FORMAT is the same, we assume an
  295. // identity translation. Otherwise we fail.
  296. //
  297. PLOTDBG(DBG_HTXB, ("pxlo=NULL, Xlate to same as BmpFormat=%ld",
  298. (DWORD)BmpFormat));
  299. RetVal = TRUE;
  300. if (BmpFormat == BMF_4BPP) {
  301. cPal = 8;
  302. pPalEntry = HTPal;
  303. } else {
  304. cPal = 2;
  305. pPalEntry = (PPALENTRY)SrcPal;
  306. CopyMemory(pPalEntry + 0, &HTPal[0], sizeof(PALENTRY));
  307. CopyMemory(pPalEntry + 1, &HTPal[7], sizeof(PALENTRY));
  308. }
  309. for (i = 0; i < cPal; i++, pPalEntry++) {
  310. HTXB_R(htXB) = pPalEntry->R;
  311. HTXB_G(htXB) = pPalEntry->G;
  312. HTXB_B(htXB) = pPalEntry->B;
  313. htXB.dw ^= HTPalXor;
  314. PalXlate[i] =
  315. HTXB_I(htXB) = (BYTE)((HTXB_R(htXB) & 0x01) |
  316. (HTXB_G(htXB) & 0x02) |
  317. (HTXB_B(htXB) & 0x04));
  318. PalNibble[i] = htXB;
  319. if (pDrvHTInfo->PalXlate[i] != HTXB_I(htXB)) {
  320. GenHTXB = TRUE;
  321. }
  322. }
  323. }
  324. if (!RetVal) {
  325. PLOTDBG(DBG_HTXB, ("**** IsHTCompatibleSurfObj = NO ****"));
  326. return(FALSE);
  327. }
  328. if ((Flags & ISHTF_HTXB) && (GenHTXB)) {
  329. //
  330. // Copy down the pal xlate
  331. //
  332. PLOTDBG(DBG_HTXB, (" --- Copy XLATE TABLE ---"));
  333. CopyMemory(pDrvHTInfo->PalXlate, PalXlate, sizeof(PalXlate));
  334. //
  335. // We only really generate 4bpp to 3 planes if the destination
  336. // format is BMF_4BPP
  337. //
  338. if (BmpFormat == (UINT)BMF_1BPP) {
  339. pDrvHTInfo->RTLPal[0].Pal = HTPal[PalXlate[0]];
  340. pDrvHTInfo->RTLPal[1].Pal = HTPal[PalXlate[1]];
  341. PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: MONO 1BPP: 0=%02lx:%02lx:%02lx, 1=%02lx:%02lx:%02lx",
  342. (DWORD)pDrvHTInfo->RTLPal[0].Pal.R,
  343. (DWORD)pDrvHTInfo->RTLPal[0].Pal.G,
  344. (DWORD)pDrvHTInfo->RTLPal[0].Pal.B,
  345. (DWORD)pDrvHTInfo->RTLPal[1].Pal.R,
  346. (DWORD)pDrvHTInfo->RTLPal[1].Pal.G,
  347. (DWORD)pDrvHTInfo->RTLPal[1].Pal.B));
  348. } else if (BmpFormat == (UINT)BMF_4BPP) {
  349. PHTXB pTmpHTXB;
  350. UINT h;
  351. UINT l;
  352. DWORD HighNibble;
  353. PLOTDBG(DBG_HTXB, ("--- Generate 4bpp --> 3 planes xlate ---"));
  354. if (!(pDrvHTInfo->pHTXB)) {
  355. PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: Allocate pHTXB=%ld",
  356. HTXB_TABLE_SIZE));
  357. if (!(pDrvHTInfo->pHTXB =
  358. (PHTXB)LocalAlloc(LPTR, HTXB_TABLE_SIZE))) {
  359. PLOTERR(("IsHTCompatibleSurfObj: LocalAlloc(HTXB_TABLE_SIZE) failed"));
  360. return(FALSE);
  361. }
  362. }
  363. pDrvHTInfo->RTLPal[0].Pal = HTPal[0];
  364. pDrvHTInfo->RTLPal[1].Pal = HTPal[1];
  365. PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: COLOR 4BPP: 0=%02lx:%02lx:%02lx, 1=%02lx:%02lx:%02lx",
  366. (DWORD)pDrvHTInfo->RTLPal[0].Pal.R,
  367. (DWORD)pDrvHTInfo->RTLPal[0].Pal.G,
  368. (DWORD)pDrvHTInfo->RTLPal[0].Pal.B,
  369. (DWORD)pDrvHTInfo->RTLPal[1].Pal.R,
  370. (DWORD)pDrvHTInfo->RTLPal[1].Pal.G,
  371. (DWORD)pDrvHTInfo->RTLPal[1].Pal.B));
  372. //
  373. // Generate 4bpp to 3 planes xlate table
  374. //
  375. for (h = 0, pTmpHTXB = pDrvHTInfo->pHTXB;
  376. h < HTXB_H_NIBBLE_MAX;
  377. h++, pTmpHTXB += HTXB_L_NIBBLE_DUP) {
  378. HighNibble = (DWORD)(PalNibble[h].dw & 0xaaaaaaaaL);
  379. for (l = 0; l < HTXB_L_NIBBLE_MAX; l++, pTmpHTXB++) {
  380. pTmpHTXB->dw = (DWORD)((HighNibble) |
  381. (PalNibble[l].dw & 0x55555555L));
  382. }
  383. //
  384. // Duplicate low nibble high order bit, 8 of them
  385. //
  386. CopyMemory(pTmpHTXB,
  387. pTmpHTXB - HTXB_L_NIBBLE_MAX,
  388. sizeof(HTXB) * HTXB_L_NIBBLE_DUP);
  389. }
  390. //
  391. // Copy high nibble duplication, 128 of them
  392. //
  393. CopyMemory(pTmpHTXB,
  394. pDrvHTInfo->pHTXB,
  395. sizeof(HTXB) * HTXB_H_NIBBLE_DUP);
  396. }
  397. }
  398. }
  399. PLOTDBG(DBG_HTXB, ("*** IsHTCompatibleSurfObj = %hs ***", (RetVal) ? "TRUE" : "FALSE"));
  400. return(RetVal);
  401. }
  402. DWORD
  403. ExitToHPGL2Mode(
  404. PPDEV pPDev,
  405. LPBYTE pHPGL2ModeCmds,
  406. LPDWORD pOHTFlags,
  407. DWORD OHTFlags
  408. )
  409. /*++
  410. Routine Description:
  411. This function will exit to HPGL2 Mode
  412. Arguments:
  413. pPDev - Pointer to the PDEV
  414. pHTGL2ModeCmds - Pointer to our internal command to switch to HPGL2
  415. OHTFlags - Current OHTFlags
  416. Return Value:
  417. New OHTFlags
  418. Development History:
  419. 10-Feb-1994 Thu 12:51:14 created
  420. Revision History:
  421. --*/
  422. {
  423. if (OHTFlags & OHTF_IN_RTLMODE) {
  424. if (OHTFlags & OHTF_SET_TR1) {
  425. //
  426. // Send STM command here
  427. //
  428. OutputString(pPDev, "\033*v1N");
  429. }
  430. SEND_PLOTCMDS(pPDev, pHPGL2ModeCmds);
  431. OHTFlags &= ~OHTF_IN_RTLMODE;
  432. PLOTDBG(DBG_HTBLT, ("*** BackTo HPGL/2: %ld=[%hs]",
  433. (DWORD)*pHPGL2ModeCmds, pHPGL2ModeCmds + 1));
  434. }
  435. //
  436. // If we need to clear clip window do it now
  437. //
  438. if (OHTFlags & OHTF_CLIPWINDOW) {
  439. ClearClipWindow(pPDev);
  440. OHTFlags &= ~OHTF_CLIPWINDOW;
  441. PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: ClearClipWindow"));
  442. }
  443. if (OHTFlags & OHTF_SET_TR1) {
  444. OutputString(pPDev, "TR0;");
  445. }
  446. OHTFlags = 0;
  447. if (pOHTFlags) {
  448. *pOHTFlags = OHTFlags;
  449. }
  450. return(OHTFlags);
  451. }
  452. VOID
  453. MoveRelativeY(
  454. PPDEV pPDev,
  455. LONG Y
  456. )
  457. /*++
  458. Routine Description:
  459. Move relative Y positiion by batch for devices that have y coordinate
  460. move limitations.
  461. Arguments:
  462. pPDev - Pointer to our PDEV
  463. Y - Relative amount to move
  464. Return Value:
  465. VOID
  466. Development History:
  467. 13-Apr-1994 Wed 14:38:18 created
  468. Revision History:
  469. --*/
  470. {
  471. LPSTR pMove;
  472. LONG SendY;
  473. BOOL Negative;
  474. pMove = (LPSTR)(RTL_NO_DPI_XY(pPDev) ? YMoveDECI : YMoveDPI);
  475. if (Negative = (Y < 0)) {
  476. Y = -Y;
  477. }
  478. while (Y) {
  479. if ((SendY = Y) > MAX_HP_Y_MOVE) {
  480. SendY = MAX_HP_Y_MOVE;
  481. }
  482. OutputFormatStr(pPDev, pMove, (Negative) ? -SendY : SendY);
  483. Y -= SendY;
  484. }
  485. }
  486. BOOL
  487. OutputHTBitmap(
  488. PPDEV pPDev,
  489. SURFOBJ *psoHT,
  490. CLIPOBJ *pco,
  491. PPOINTL pptlDest,
  492. PRECTL prclSrc,
  493. DWORD Rop3,
  494. LPDWORD pOHTFlags
  495. )
  496. /*++
  497. Routine Description:
  498. This function will handle complex type of region bitmaps
  499. Arguments:
  500. pPDev - Pointer to the PDEV
  501. psoHI - the surface object of the halftone bitmap to be output
  502. pco - a clip object associated with psoHT
  503. pptlDest - pointer to the starting destination point
  504. prclSrc - pointer to the source bitmap rectangle area to be copied
  505. to the destination, if this is NULL then a whole psoHT will
  506. be copied to the destination
  507. Rop3 - a Rop3 to send for the source
  508. pOHTFlags - Pointer to the DWORD containing the current OHTF_xxxx, if this
  509. pointer is NULL then this function will enter RTL mode first
  510. and exit to HPGL2 mode when it returns, if this pointer is
  511. specified then the pOHTFlags will be used and at return the
  512. current OHTFlags will be written to the location pointed to
  513. by pOHTFlags
  514. Return Value:
  515. TRUE if sucessful, FALSE if failure
  516. Development History:
  517. 04-Nov-1993 Thu 15:30:13 updated
  518. 24-Dec-1993 Fri 05:21:57 updated
  519. Total re-write so that take all the bitmap orientations and enum
  520. rects works correctly. this is the major bitmap function entry point
  521. it will call appropriate bitmap function to redner the final output.
  522. The other things is we need to check if switch between HPGL/2 and RTL
  523. can be more efficient. Make sure we can eaiser to adapate to rotate
  524. the bitmap to the left if necessary.
  525. Correct LogExt.cx useage, we must do SPLTOENGUNITS first
  526. 29-Dec-1993 Wed 10:59:41 updated
  527. Change bMore=CLIPOBJ_bEnum sequence,
  528. Change PLOTDBGBLK() macro by adding automatical semi in macro
  529. 13-Jan-1994 Thu 14:09:51 updated
  530. add prclSrc
  531. 14-Jan-1994 Fri 21:03:26 updated
  532. add Rop3
  533. 16-Jan-1994 Thu 14:09:51 updated
  534. Change OutputHTBitmap to take Rop4 to send to plotter.
  535. 08-Feb-1994 Tue 15:54:24 updated
  536. Make sure we do nothing if source is not visible
  537. 21-Mar-1994 Mon 14:20:18 updated
  538. Allocate extra 2 bytes for the scan/rot buffer in case if we must do
  539. byte aligned. And if we need to do byte aligned thing then always
  540. move the HCAPS to the byte boundary first
  541. 13-Apr-1994 Wed 14:59:56 updated
  542. 1. Batch the Relative Y move to have 32767 limitation problem solved.
  543. 2. GrayScale/gamma correct the input BITMAP color
  544. 20-Aug-1994 Sat 21:37:37 updated
  545. Add the bitmap offset location from the FORM imageable area, otherwise
  546. our bitmap will have different offset then the HPGL/2 drawing commands
  547. Revision History:
  548. 22-Oct-1999 Fri 12:17:21 updated
  549. Return FALSE right away if a job canceled, since this function can
  550. take very long time to finished.
  551. --*/
  552. {
  553. #define pDrvHTInfo ((PDRVHTINFO)pPDev->pvDrvHTData)
  554. PRECTL prcl;
  555. OUTHTBMPFUNC HTBmpFunc;
  556. HTBMPINFO HTBmpInfo;
  557. HTENUMRCL HTEnumRCL;
  558. RTLCLRCONFIG RTLClrConfig;
  559. RECTL rclSrc;
  560. RECTL rclDest;
  561. POINTL CursorPos;
  562. POINTL BmpOffset;
  563. SIZEL Size;
  564. HPBAHACK CurHPBAHack;
  565. LONG cxLogExt;
  566. LONG TempY;
  567. DWORD OHTFlags;
  568. DWORD PlotFlags;
  569. BOOL More;
  570. BOOL RetVal;
  571. BOOL BmpRotate;
  572. BOOL FirstEnumRCL = TRUE;
  573. UINT i;
  574. BYTE HPGL2ModeCmds[16];
  575. BYTE RTLModeCmds[32];
  576. if (PLOT_CANCEL_JOB(pPDev)) {
  577. return(FALSE);
  578. }
  579. PlotFlags = GET_PLOTFLAGS(pPDev);
  580. OHTFlags = (DWORD)((pOHTFlags) ? (*pOHTFlags & OHTF_MASK) : 0);
  581. //
  582. // Set up exit HPGL/2 and enter RTL mode commands
  583. //
  584. INIT_PLOTCMDS(HPGL2ModeCmds);
  585. if (PF_PUSHPAL(PlotFlags)) {
  586. COPY_PLOTCMDS(HPGL2ModeCmds, "\033*p1P", 5);
  587. }
  588. COPY_PLOTCMDS(HPGL2ModeCmds, "\033%0B", 4);
  589. CHECK_PLOTCMDS(HPGL2ModeCmds);
  590. if (OHTFlags & OHTF_EXIT_TO_HPGL2) {
  591. PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: Force Exit to HPGL2 Mode"));
  592. ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
  593. return(TRUE);
  594. }
  595. //
  596. // Make sure the caller is right about this,
  597. // so check to see which formats we can handle.
  598. //
  599. PLOTASSERT(1, "OutputHTBitmap: Invalid Bitmap Format %ld passed",
  600. (psoHT->iBitmapFormat ==
  601. pDrvHTInfo->HTBmpFormat) ||
  602. (psoHT->iBitmapFormat ==
  603. pDrvHTInfo->AltBmpFormat),
  604. psoHT->iBitmapFormat);
  605. //
  606. // First set some basic information in HTBmpInfo
  607. //
  608. HTBmpInfo.pPDev = pPDev;
  609. HTBmpInfo.Flags = 0;
  610. HTBmpInfo.Delta = psoHT->lDelta;
  611. //
  612. // We will set color format for the HPGL/2 Plotter to the same one as
  613. // the bitmap format passed, this will allow us to use the 1bpp output
  614. // function for the 4bpp surfaces
  615. //
  616. RTLClrConfig.ColorModel = 0;
  617. RTLClrConfig.EncodingMode = 0;
  618. //
  619. // cxLogExt = the output bitmap function index number
  620. // Size.cx = Count of mono scan lines needed for each pixel line, and
  621. // final count of scan buffer needed
  622. // Size.cy = count of rotation buffer needed (Must be DWORD aligned)
  623. //
  624. if (psoHT->iBitmapFormat == BMF_1BPP) {
  625. cxLogExt = 0;
  626. Size.cx = 1;
  627. RTLClrConfig.BitsPerIndex = 1;
  628. } else {
  629. //
  630. // 4 bits per pel, 3 planes that is
  631. //
  632. cxLogExt = 2;
  633. Size.cx = 3;
  634. RTLClrConfig.BitsPerIndex = 3;
  635. }
  636. RTLClrConfig.BitsPerR =
  637. RTLClrConfig.BitsPerG =
  638. RTLClrConfig.BitsPerB = 8;
  639. //
  640. // We have almost everything setup, now check how to send to the output
  641. // bitmap function, get the full destination size first
  642. //
  643. //
  644. //************************************************************************
  645. // The Following RTL switching, config color command and other related
  646. // commands MUST be sent in this order
  647. //************************************************************************"
  648. //
  649. // 1: Initialize the enter RTL command buffer
  650. //
  651. INIT_PLOTCMDS(RTLModeCmds);
  652. //
  653. // 2. commands to go into RTL mode, and back to HPGL/2 mode, the mode
  654. // switching assumes that the current positions are retained.
  655. //
  656. COPY_PLOTCMDS(RTLModeCmds, "\033%0A", 4);
  657. //
  658. // 3. Push/Pop the HPGL/2 palette commands if this is required (PCD file)
  659. //
  660. if (PF_PUSHPAL(PlotFlags)) {
  661. COPY_PLOTCMDS(RTLModeCmds, "\033*p0P", 5);
  662. }
  663. //
  664. // 4. Color configuration commands and exit back to HPGL/2 command
  665. //
  666. if ((RTLClrConfig.BitsPerIndex != 1) ||
  667. (!PF_RTLMONO_NO_CID(PlotFlags))) {
  668. //
  669. // We only do this if we are COLOR or if we must send CID when mono
  670. // device
  671. //
  672. COPY_PLOTCMDS(RTLModeCmds, "\033*v6W", 5);
  673. COPY_PLOTCMDS(RTLModeCmds, &RTLClrConfig, 6);
  674. }
  675. CHECK_PLOTCMDS(RTLModeCmds);
  676. //
  677. // Now Check the source
  678. //
  679. rclSrc.left =
  680. rclSrc.top = 0;
  681. rclSrc.right = psoHT->sizlBitmap.cx;
  682. rclSrc.bottom = psoHT->sizlBitmap.cy;
  683. if (prclSrc) {
  684. PLOTASSERT(1, "OutputHTBitmap: Invalid prclSrc [%08lx] passed",
  685. ((prclSrc->left >= 0) &&
  686. (prclSrc->top >= 0) &&
  687. (prclSrc->right <= psoHT->sizlBitmap.cx) &&
  688. (prclSrc->bottom <= psoHT->sizlBitmap.cy) &&
  689. (prclSrc->left <= prclSrc->right) &&
  690. (prclSrc->top <= prclSrc->bottom)), prclSrc);
  691. if (!IntersectRECTL(&rclSrc, prclSrc)) {
  692. PLOTWARN(("OutputHTBitmap: EMPTY SRC Passed, Done!"));
  693. ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
  694. return(TRUE);
  695. }
  696. }
  697. if (BmpRotate = (pPDev->PlotForm.BmpRotMode != BMP_ROT_NONE)) {
  698. //
  699. // We must allocate rotation buffer and it must be DWORD aligned.
  700. //
  701. Size.cx *= ((psoHT->sizlBitmap.cy + 23) >> 3);
  702. if (psoHT->iBitmapFormat == BMF_1BPP) {
  703. //
  704. // We also have to take into acount the fact that pixels can start
  705. // anywhere in the first byte, causing us to allocate and extra byte
  706. // for the shift.
  707. //
  708. Size.cy = (LONG)((psoHT->sizlBitmap.cy + 23) >> 3);
  709. Size.cy = (LONG)(DW_ALIGN(Size.cy) << 3);
  710. } else {
  711. Size.cy = (LONG)((psoHT->sizlBitmap.cy + 3) >> 1);
  712. Size.cy = (LONG)(DW_ALIGN(Size.cy) << 1);
  713. }
  714. ++cxLogExt;
  715. } else {
  716. //
  717. // For a non-rotated 4BPP bitmap, we need an extra buffer to
  718. // ensure the final 4bpp bitmap is DWORD aligned. This will speed up
  719. // the 4bpp to 3 plane translation.
  720. //
  721. Size.cy = (LONG)((psoHT->sizlBitmap.cx + 23) >> 3);
  722. Size.cx *= Size.cy;
  723. if (psoHT->iBitmapFormat == BMF_4BPP) {
  724. //
  725. // Make sure the we allocate a rotation buffer for alignment
  726. // purposes
  727. //
  728. Size.cy = (LONG)((psoHT->sizlBitmap.cx + 3) << 1);
  729. Size.cy = (LONG)DW_ALIGN(Size.cy);
  730. } else {
  731. //
  732. // BMF_1BPP will be left/right shifted on a per byte basis on
  733. // the fly.
  734. //
  735. Size.cy = 0;
  736. }
  737. }
  738. HTBmpFunc = HTBmpFuncTable[cxLogExt];
  739. //
  740. // Make sure the first buffer is DWORD aligned, otherwise the next
  741. // buffer (pRotBuf) will not start on a DWORD boundary.
  742. //
  743. Size.cx = DW_ALIGN(Size.cx);
  744. PLOTDBGBLK(HTBmpInfo.cScanBuf = Size.cx;
  745. HTBmpInfo.cRotBuf = Size.cy)
  746. PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: [%hs] - ScanBuf=%ld, RotBuf=%ld",
  747. pszHTBmpFunc[cxLogExt], Size.cx, Size.cy));
  748. //
  749. // Allocate scan buffer and rotation temp buffer if needed
  750. //
  751. if (!(HTBmpInfo.pScanBuf = (LPBYTE)LocalAlloc(LPTR, Size.cx + Size.cy))) {
  752. PLOTERR(("OutputHTBmp: LocalAlloc(%ld) Failed, cx=%ld, cy=%ld",
  753. Size.cx + Size.cy, Size.cx, Size.cy));
  754. ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
  755. return(FALSE);
  756. }
  757. HTBmpInfo.pRotBuf = (Size.cy) ? (HTBmpInfo.pScanBuf + Size.cx) : NULL;
  758. //
  759. // Set up local variables for the command mode and other one time variables
  760. //
  761. cxLogExt = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cx);
  762. //
  763. // Now set up the rclDest for the bitmap we will output to. And set More to
  764. // false, which means one RECT.
  765. //
  766. rclDest.left = pptlDest->x;
  767. rclDest.top = pptlDest->y;
  768. rclDest.right = rclDest.left + (rclSrc.right - rclSrc.left);
  769. rclDest.bottom = rclDest.top + (rclSrc.bottom - rclSrc.top);
  770. //
  771. // The following variables are essential for the default assumptions.
  772. //
  773. // 1. RetVal = TRUE if no clip rect we return OK
  774. // 2. More = FALSE default as current HTEnumRCL.c and rectl
  775. // without calling CLIPOBJ_bEnum()
  776. // 3. HTEnumRCL.c = 1 to have only one default HTEnumRCL.rcl
  777. //
  778. RetVal = TRUE;
  779. More = FALSE;
  780. HTEnumRCL.c = 1;
  781. if ((!pco) || (pco->iDComplexity == DC_TRIVIAL)) {
  782. //
  783. // The whole output destination rectangle is visible
  784. //
  785. PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=%hs",
  786. (pco) ? "DC_TRIVIAL" : "NULL"));
  787. HTEnumRCL.rcl[0] = rclDest;
  788. } else if (pco->iDComplexity == DC_RECT) {
  789. //
  790. // The visible area is one rectangle so intersect with the destination
  791. //
  792. PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=DC_RECT"));
  793. HTEnumRCL.rcl[0] = pco->rclBounds;
  794. } else {
  795. //
  796. // We have a complex clipping region to be computed, call engine to start
  797. // enumerating the rectangles and set More = TRUE so we can get the first
  798. // batch of rectangles.
  799. //
  800. PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=DC_COMPLEX, EnumRects now"));
  801. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  802. More = TRUE;
  803. }
  804. Rop3 &= 0xFF;
  805. PLOTASSERT(1, "OutputHTBitmap: The Rop required PATTERN? [%04lx]",
  806. !ROP3_NEED_PAT(Rop3), Rop3);
  807. if (PF_BYTEALIGN(PlotFlags)) {
  808. if (pPDev->PlotDM.Flags & PDMF_PLOT_ON_THE_FLY) {
  809. PLOTWARN(("OutputHTBitmap: ByteAlign/Poster Mode Rop3 0x%02lx -> 0x%02lx",
  810. Rop3, ROP3_BYTEALIGN_POSTER));
  811. Rop3 = ROP3_BYTEALIGN_POSTER;
  812. }
  813. OHTFlags &= ~OHTF_SET_TR1;
  814. CurHPBAHack = HPBAHack[Rop3 & 0x0F];
  815. if (CurHPBAHack.Flags & HPBHF_nS) {
  816. HTBmpInfo.Flags |= HTBIF_FLIP_MONOBITS;
  817. }
  818. if (CurHPBAHack.Flags & HPBHF_PAD_1) {
  819. HTBmpInfo.Flags |= HTBIF_BA_PAD_1;
  820. }
  821. PLOTDBG(DBG_HTBLT, ("OutpputHTBitmap: BA HACK: Rop3=%02lx -> %02lx, Flags=%04lx",
  822. (DWORD)Rop3,
  823. (DWORD)CurHPBAHack.Rop3RTL,
  824. (DWORD)CurHPBAHack.Flags));
  825. } else {
  826. CurHPBAHack.Rop3RTL = (BYTE)Rop3;
  827. CurHPBAHack.Flags = 0;
  828. }
  829. //
  830. // To have correct image area located for the bitmap, we must offset all
  831. // bitmaps with these amounts
  832. //
  833. BmpOffset.x = SPLTOENGUNITS(pPDev, pPDev->PlotForm.BmpOffset.x);
  834. BmpOffset.y = SPLTOENGUNITS(pPDev, pPDev->PlotForm.BmpOffset.y);
  835. //
  836. // We have 'More' and HTEnumRCL structure set, now go through each clipping
  837. // rectangle and call the halftone output fucntion to do the real work
  838. //
  839. do {
  840. //
  841. // If More is true then we need to get the next batch of rectangles.
  842. //
  843. if (More) {
  844. More = CLIPOBJ_bEnum(pco, sizeof(HTEnumRCL), (ULONG *)&HTEnumRCL);
  845. }
  846. //
  847. // prcl will point to the first enumerated rectangle.
  848. //
  849. prcl = (PRECTL)&HTEnumRCL.rcl[0];
  850. while (HTEnumRCL.c-- && More != DDI_ERROR) {
  851. if (PLOT_CANCEL_JOB(pPDev)) {
  852. RetVal =
  853. More = FALSE;
  854. break;
  855. }
  856. //
  857. // Only do this rectangle area if it is visible
  858. //
  859. HTBmpInfo.rclBmp = *prcl;
  860. if (IntersectRECTL(&(HTBmpInfo.rclBmp), &rclDest)) {
  861. //
  862. // For the very first time, we want to switch to PP1
  863. //
  864. if (FirstEnumRCL) {
  865. SetPixelPlacement(pPDev, SPP_MODE_EDGE);
  866. FirstEnumRCL = FALSE;
  867. }
  868. //
  869. // Now compute useable information to be passed to the output
  870. // halftoned bitmap function
  871. //
  872. HTBmpInfo.OffBmp.x = rclSrc.left +
  873. (HTBmpInfo.rclBmp.left - rclDest.left);
  874. HTBmpInfo.OffBmp.y = rclSrc.top +
  875. (HTBmpInfo.rclBmp.top - rclDest.top);
  876. HTBmpInfo.szlBmp.cx = HTBmpInfo.rclBmp.right -
  877. HTBmpInfo.rclBmp.left;
  878. HTBmpInfo.szlBmp.cy = HTBmpInfo.rclBmp.bottom -
  879. HTBmpInfo.rclBmp.top;
  880. HTBmpInfo.pScan0 = (LPBYTE)psoHT->pvScan0 +
  881. (HTBmpInfo.OffBmp.y * HTBmpInfo.Delta);
  882. PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: rclBmp=(%ld, %ld)-(%ld, %ld) [%ld x %ld] Off=(%ld, %ld)",
  883. HTBmpInfo.rclBmp.left, HTBmpInfo.rclBmp.top,
  884. HTBmpInfo.rclBmp.right, HTBmpInfo.rclBmp.bottom,
  885. HTBmpInfo.szlBmp.cx, HTBmpInfo.szlBmp.cy,
  886. HTBmpInfo.OffBmp.x, HTBmpInfo.OffBmp.y));
  887. //
  888. // Now set the correct cursor position based on the rotation
  889. //
  890. if (BmpRotate) {
  891. Size.cx = HTBmpInfo.szlBmp.cy;
  892. Size.cy = HTBmpInfo.szlBmp.cx;
  893. CursorPos.x = HTBmpInfo.rclBmp.top;
  894. CursorPos.y = cxLogExt - HTBmpInfo.rclBmp.right;
  895. } else {
  896. Size = HTBmpInfo.szlBmp;
  897. CursorPos.x = HTBmpInfo.rclBmp.left;
  898. CursorPos.y = HTBmpInfo.rclBmp.top;
  899. }
  900. //
  901. // Add in the bitmap offset location from the imageable area
  902. //
  903. CursorPos.x += BmpOffset.x;
  904. CursorPos.y += BmpOffset.y;
  905. //
  906. // If we need to BYTE align, then make the X cursor position
  907. // byte aligned first
  908. //
  909. if (PF_BYTEALIGN(PlotFlags)) {
  910. if (i = (UINT)(CursorPos.x & 0x07)) {
  911. //
  912. // We really need to byte aligne x and we also have to
  913. // increase the source width to accomodate the changes
  914. //
  915. PLOTDBG(DBG_HTBLT,
  916. ("OutputHTBitmap: NEED BYTE ALIGN X: %ld -> %ld, SRC WIDTH: %ld -> %ld",
  917. CursorPos.x, CursorPos.x - i,
  918. Size.cx, Size.cx + i));
  919. Size.cx += i;
  920. CursorPos.x -= i;
  921. }
  922. Size.cx = (LONG)((Size.cx + 7) & ~(DWORD)7);
  923. }
  924. PLOTDBG(DBG_HTBLT,
  925. ("OutputHTBitmap: ABS CAP: (%ld, %ld) --> (%ld, %ld), RELATIVE=(%ld, %ld)",
  926. pPDev->ptlRTLCAP.x, pPDev->ptlRTLCAP.y,
  927. CursorPos.x, CursorPos.y,
  928. CursorPos.x - pPDev->ptlRTLCAP.x,
  929. CursorPos.y - pPDev->ptlRTLCAP.y));
  930. if (!(OHTFlags & OHTF_DONE_ROPTR1)) {
  931. if (OHTFlags & OHTF_IN_RTLMODE) {
  932. SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
  933. OHTFlags &= ~OHTF_IN_RTLMODE;
  934. PLOTDBG(DBG_HTBLT, ("*** Enter HPGL/2: %ld=[%hs]",
  935. (DWORD)HPGL2ModeCmds[0], &HPGL2ModeCmds[1]));
  936. }
  937. SetRopMode(pPDev,
  938. (CurHPBAHack.Flags & HPBHF_1_FIRST) ?
  939. 0x88 : CurHPBAHack.Rop3RTL);
  940. if (OHTFlags & OHTF_SET_TR1) {
  941. OutputString(pPDev, "TR1;");
  942. }
  943. }
  944. //
  945. // Entering RTL mode if not already so
  946. //
  947. if (!(OHTFlags & OHTF_IN_RTLMODE)) {
  948. PLOTDBG(DBG_HTBLT, ("*** Enter RTL: %ld=[%hs]",
  949. (DWORD)RTLModeCmds[0], &RTLModeCmds[1]));
  950. SEND_PLOTCMDS(pPDev, RTLModeCmds);
  951. if (OHTFlags & OHTF_SET_TR1) {
  952. //
  953. // Send STM command here
  954. //
  955. OutputString(pPDev, "\033*v0N");
  956. }
  957. if (CurHPBAHack.Flags & HPBHF_nS) {
  958. HTBmpInfo.Flags |= HTBIF_FLIP_MONOBITS;
  959. } else {
  960. HTBmpInfo.Flags &= ~HTBIF_FLIP_MONOBITS;
  961. }
  962. //
  963. // If bitmap is monochrome then make sure we set the
  964. // palette correctly only if we can set it
  965. //
  966. if ((RTLClrConfig.BitsPerIndex == 1) &&
  967. (!(OHTFlags & OHTF_DONE_ROPTR1))) {
  968. PALDW RTLPal;
  969. BOOL FlipMono = FALSE;
  970. for (i = 0; i < 2; i++) {
  971. RTLPal.dw = pDrvHTInfo->RTLPal[i].dw;
  972. //
  973. // Convert the color through gamma/gray scale
  974. //
  975. GetFinalColor(pPDev, &(RTLPal.Pal));
  976. if (RTLPal.dw != DefWKPal[i]) {
  977. if (PF_RTLMONO_FIXPAL(PlotFlags)) {
  978. FlipMono = TRUE;
  979. } else {
  980. OutputFormatStr(pPDev,
  981. SetRGBCmd,
  982. (DWORD)RTLPal.Pal.R,
  983. (DWORD)RTLPal.Pal.G,
  984. (DWORD)RTLPal.Pal.B,
  985. i);
  986. PLOTDBG(DBG_HTBLT_CLR,
  987. ("OutputHTBitmap: Change RTLPal[%ld]=%02lx:%02lx:%02lx",
  988. (DWORD)i,
  989. (DWORD)RTLPal.Pal.R,
  990. (DWORD)RTLPal.Pal.G,
  991. (DWORD)RTLPal.Pal.B));
  992. }
  993. }
  994. }
  995. if (FlipMono) {
  996. HTBmpInfo.Flags ^= HTBIF_FLIP_MONOBITS;
  997. PLOTDBG(DBG_HTBLT_CLR, ("OutputHTBitmap: Flip MONO Bits"));
  998. }
  999. }
  1000. }
  1001. OHTFlags |= (OHTF_IN_RTLMODE | OHTF_DONE_ROPTR1);
  1002. TempY = CursorPos.y - pPDev->ptlRTLCAP.y;
  1003. if (PF_RTL_NO_DPI_XY(PlotFlags)) {
  1004. //
  1005. // We will move X in absolute movements (not relative)
  1006. // by always outputing position 0 to flush out the device
  1007. // X CAP then move absolute to final X position. We will
  1008. // us relative movement for the Y coordinate.
  1009. //
  1010. OutputFormatStr(pPDev,
  1011. XMoveDECI,
  1012. DEVTODECI(pPDev, CursorPos.x));
  1013. } else {
  1014. if ((TempY <= MAX_HP_Y_MOVE) &&
  1015. (TempY >= -MAX_HP_Y_MOVE)) {
  1016. OutputFormatStr(pPDev,
  1017. XYMoveDPI,
  1018. CursorPos.x - pPDev->ptlRTLCAP.x,
  1019. TempY);
  1020. TempY = 0;
  1021. } else {
  1022. OutputFormatStr(pPDev,
  1023. XYMoveDPI,
  1024. CursorPos.x - pPDev->ptlRTLCAP.x,
  1025. 0);
  1026. }
  1027. }
  1028. MoveRelativeY(pPDev, TempY);
  1029. //
  1030. // Update new cursor position after the RTL commands, the
  1031. // CursorPos and pPDev->ptlRTLCAPS always are ABSOLUTE
  1032. // coordinates but we will send the RTL RELATIVE
  1033. // command to position the bitmap.
  1034. //
  1035. pPDev->ptlRTLCAP.x = CursorPos.x;
  1036. pPDev->ptlRTLCAP.y = CursorPos.y + Size.cy;
  1037. //
  1038. // Output Start Graphic commands
  1039. //
  1040. OutputFormatStr(pPDev, StartGraf, Size.cx);
  1041. //
  1042. // Fill One first if we are simulating rops the device can't
  1043. // handle
  1044. //
  1045. if (CurHPBAHack.Flags & HPBHF_1_FIRST) {
  1046. FillRect1bppBmp(&HTBmpInfo, 0xFF, FALSE, BmpRotate);
  1047. OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
  1048. if (CurHPBAHack.Rop3RTL != 0xAA) {
  1049. SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
  1050. SetRopMode(pPDev, CurHPBAHack.Rop3RTL);
  1051. SEND_PLOTCMDS(pPDev, RTLModeCmds);
  1052. MoveRelativeY(pPDev, -Size.cy);
  1053. OutputFormatStr(pPDev, StartGraf, Size.cx);
  1054. }
  1055. }
  1056. //
  1057. // Now call the functions to really output the bitmap
  1058. //
  1059. if (CurHPBAHack.Rop3RTL != 0xAA) {
  1060. if (RetVal = HTBmpFunc(&HTBmpInfo)) {
  1061. //
  1062. // If output is ok then send End Graphic command now
  1063. //
  1064. OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
  1065. } else {
  1066. PLOTERR(("OutputHTBitmap: HTBmpFunc = FALSE (failed)"));
  1067. More = FALSE;
  1068. break;
  1069. }
  1070. }
  1071. if (CurHPBAHack.Flags & HPBHF_nD_LAST) {
  1072. SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
  1073. SetRopMode(pPDev, 0x66);
  1074. SEND_PLOTCMDS(pPDev, RTLModeCmds);
  1075. if ((CurHPBAHack.Flags & HPBHF_1_FIRST) ||
  1076. (CurHPBAHack.Rop3RTL != 0xAA)) {
  1077. MoveRelativeY(pPDev, -Size.cy);
  1078. OutputFormatStr(pPDev, StartGraf, Size.cx);
  1079. OHTFlags |= OHTF_IN_RTLMODE;
  1080. }
  1081. FillRect1bppBmp(&HTBmpInfo, 0x00, TRUE, BmpRotate);
  1082. OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
  1083. }
  1084. if (PF_BYTEALIGN(PlotFlags)) {
  1085. OHTFlags &= ~OHTF_DONE_ROPTR1;
  1086. }
  1087. } else {
  1088. PLOTDBG(DBG_HTBLT_SKIP, ("OutputHTBitmap: INVISIBLE rcl=(%ld, %ld)-(%ld, %ld)",
  1089. prcl->left, prcl->top, prcl->right, prcl->bottom));
  1090. }
  1091. prcl++;
  1092. }
  1093. if (More == DDI_ERROR)
  1094. {
  1095. More = FALSE;
  1096. RetVal = FALSE;
  1097. }
  1098. } while (More);
  1099. //
  1100. // Finally return to HPGL/2 mode
  1101. //
  1102. if ((!RetVal) || (!pOHTFlags)) {
  1103. ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
  1104. }
  1105. if (pOHTFlags) {
  1106. *pOHTFlags = OHTFlags;
  1107. }
  1108. //
  1109. // Get rid of any resources we allocated
  1110. //
  1111. LocalFree((HLOCAL)HTBmpInfo.pScanBuf);
  1112. return(RetVal);
  1113. #undef pDrvHTInfo
  1114. }
  1115. LONG
  1116. GetBmpDelta(
  1117. DWORD SurfaceFormat,
  1118. DWORD cx
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. This function calculates the total bytes needed in order to advance a
  1123. scan line based on the bitmap format and alignment.
  1124. Arguments:
  1125. SurfaceFormat - Surface format of the bitmap, this must be one of the
  1126. standard formats which are defined as BMF_xxx
  1127. cx - Total Pels per scan line in the bitmap.
  1128. Return Value:
  1129. The return value is the total bytes in one scan line if it is greater than
  1130. zero
  1131. Development History:
  1132. 19-Jan-1994 Wed 16:19:39 created
  1133. Revision History:
  1134. --*/
  1135. {
  1136. DWORD Delta = cx;
  1137. switch (SurfaceFormat) {
  1138. case BMF_32BPP:
  1139. Delta <<= 5;
  1140. break;
  1141. case BMF_24BPP:
  1142. Delta *= 24;
  1143. break;
  1144. case BMF_16BPP:
  1145. Delta <<= 4;
  1146. break;
  1147. case BMF_8BPP:
  1148. Delta <<= 3;
  1149. break;
  1150. case BMF_4BPP:
  1151. Delta <<= 2;
  1152. break;
  1153. case BMF_1BPP:
  1154. break;
  1155. default:
  1156. PLOTERR(("GetBmpDelta: Invalid BMF_xxx format = %ld", SurfaceFormat));
  1157. break;
  1158. }
  1159. Delta = (DWORD)DW_ALIGN((Delta + 7) >> 3);
  1160. PLOTDBG(DBG_BMPDELTA, ("Format=%ld, cx=%ld, Delta=%ld",
  1161. SurfaceFormat, cx, Delta));
  1162. return((LONG)Delta);
  1163. }
  1164. SURFOBJ *
  1165. CreateBitmapSURFOBJ(
  1166. PPDEV pPDev,
  1167. HBITMAP *phBmp,
  1168. LONG cxSize,
  1169. LONG cySize,
  1170. DWORD Format,
  1171. LPVOID pvBits
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. This function creates a bitmap and locks the bitmap to return a SURFOBJ
  1176. Arguments:
  1177. pPDev - Pointer to our PDEV
  1178. phBmp - Pointer the HBITMAP location to be returned for the bitmap
  1179. cxSize - CX size of bitmap to be created
  1180. cySize - CY size of bitmap to be created
  1181. Format - one of BMF_xxx bitmap format to be created
  1182. pvBits - the buffer to be used
  1183. Return Value:
  1184. SURFOBJ if sucessful, NULL if failed
  1185. Development History:
  1186. 19-Jan-1994 Wed 16:31:50 created
  1187. Revision History:
  1188. --*/
  1189. {
  1190. SURFOBJ *pso = NULL;
  1191. SIZEL szlBmp;
  1192. szlBmp.cx = cxSize;
  1193. szlBmp.cy = cySize;
  1194. PLOTDBG(DBG_CREATESURFOBJ, ("CreateBitmapSURFOBJ: Format=%ld, Size=%ld x %ld",
  1195. Format, cxSize, cySize));
  1196. if (*phBmp = EngCreateBitmap(szlBmp,
  1197. GetBmpDelta(Format, cxSize),
  1198. Format,
  1199. BMF_TOPDOWN | BMF_NOZEROINIT,
  1200. pvBits)) {
  1201. if (EngAssociateSurface((HSURF)*phBmp, (HDEV)pPDev->hpdev, 0)) {
  1202. if (pso = EngLockSurface((HSURF)*phBmp)) {
  1203. //
  1204. // Sucessful lock down, return it
  1205. //
  1206. return(pso);
  1207. } else {
  1208. PLOTERR(("CreateBmpSurfObj: EngLockSruface(hBmp) failed!"));
  1209. }
  1210. } else {
  1211. PLOTERR(("CreateBmpSurfObj: EngAssociateSurface() failed!"));
  1212. }
  1213. } else {
  1214. PLOTERR(("CreateBMPSurfObj: FAILED to create Bitmap Format=%ld, %ld x %ld",
  1215. Format, cxSize, cySize));
  1216. }
  1217. DELETE_SURFOBJ(pso, phBmp);
  1218. return(NULL);
  1219. }
  1220. BOOL
  1221. HalftoneBlt(
  1222. PPDEV pPDev,
  1223. SURFOBJ *psoDst,
  1224. SURFOBJ *psoHTBlt,
  1225. SURFOBJ *psoSrc,
  1226. XLATEOBJ *pxlo,
  1227. PRECTL prclDst,
  1228. PRECTL prclSrc,
  1229. PPOINTL pptlHTOrigin,
  1230. BOOL DoStretchBlt
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. Arguments:
  1235. pPDev - Pointer to our PDEV
  1236. psoDst - destination surfobj
  1237. psoHTBlt - the final halftoned result will be stored, must be a
  1238. 4/1 halftoned bitmap format
  1239. psoSrc - source surfobj must be BITMAP
  1240. pxlo - xlate object from source to the plotter device
  1241. prclDest - rectangle area for the destination
  1242. prclSrc - rectangle area to be halftoned from the source, if NULL
  1243. then full source size is used
  1244. pptlHTOrigin - the halftone origin, if NULL then (0,0) is assumed
  1245. StretchBlt - if TRUE then a stretch from rclSrc to rclDst otherwise
  1246. a tiling is done
  1247. Return Value:
  1248. BOOL to indicate operation status
  1249. Development History:
  1250. 19-Jan-1994 Wed 15:44:57 created
  1251. Revision History:
  1252. --*/
  1253. {
  1254. SIZEL szlSrc;
  1255. RECTL rclSrc;
  1256. RECTL rclDst;
  1257. RECTL rclCur;
  1258. RECTL rclHTBlt;
  1259. if (PLOT_CANCEL_JOB(pPDev)) {
  1260. return(FALSE);
  1261. }
  1262. PLOTASSERT(1, "HalftoneBlt: psoSrc type [%ld] is not a bitmap",
  1263. psoSrc->iType == STYPE_BITMAP, (LONG)psoSrc->iType);
  1264. PLOTASSERT(1, "HalftoneBlt: psoHTBlt type [%ld] is not a bitmap",
  1265. psoHTBlt->iType == STYPE_BITMAP, (LONG)psoHTBlt->iType);
  1266. if (pPDev->psoHTBlt) {
  1267. PLOTERR(("HalftoneBlt: EngStretchBlt(HALFTONE) RECURSIVE CALLS NOT ALLOWED!"));
  1268. return(FALSE);
  1269. }
  1270. pPDev->psoHTBlt = psoHTBlt;
  1271. if (prclSrc) {
  1272. rclSrc = *prclSrc;
  1273. } else {
  1274. rclSrc.left =
  1275. rclSrc.top = 0;
  1276. rclSrc.right = psoSrc->sizlBitmap.cx;
  1277. rclSrc.bottom = psoSrc->sizlBitmap.cy;
  1278. }
  1279. if (prclDst) {
  1280. rclDst = *prclDst;
  1281. } else {
  1282. rclDst.left =
  1283. rclDst.top = 0;
  1284. rclDst.right = psoHTBlt->sizlBitmap.cx;
  1285. rclDst.bottom = psoHTBlt->sizlBitmap.cy;
  1286. }
  1287. if (!pptlHTOrigin) {
  1288. pptlHTOrigin = (PPOINTL)&ptlZeroOrigin;
  1289. }
  1290. if (DoStretchBlt) {
  1291. szlSrc.cx = rclDst.right - rclDst.left;
  1292. szlSrc.cy = rclDst.bottom - rclDst.top;
  1293. } else {
  1294. szlSrc.cx = rclSrc.right - rclSrc.left;
  1295. szlSrc.cy = rclSrc.bottom - rclSrc.top;
  1296. }
  1297. PLOTDBG(DBG_HTBLT, ("HalftoneBlt: %hs BLT, (%ld,%ld)-(%ld,%ld), SRC=%ldx%ld",
  1298. (DoStretchBlt) ? "STRETCH" : "TILE",
  1299. rclDst.left, rclDst.top, rclDst.right,rclDst.bottom,
  1300. szlSrc.cx, szlSrc.cy));
  1301. //
  1302. // Start to tile it, rclCur is current RECTL on the destination
  1303. //
  1304. rclHTBlt.top = 0;
  1305. rclCur.top =
  1306. rclCur.bottom = rclDst.top;
  1307. while (rclCur.top < rclDst.bottom) {
  1308. //
  1309. // Check the Current Bottom, clip it if necessary
  1310. //
  1311. if ((rclCur.bottom += szlSrc.cy) > rclDst.bottom) {
  1312. rclCur.bottom = rclDst.bottom;
  1313. }
  1314. rclHTBlt.bottom = rclHTBlt.top + (rclCur.bottom - rclCur.top);
  1315. rclHTBlt.left = 0;
  1316. rclCur.left =
  1317. rclCur.right = rclDst.left;
  1318. while (rclCur.left < rclDst.right) {
  1319. //
  1320. // Check the Current right, clip it if necessary
  1321. //
  1322. if ((rclCur.right += szlSrc.cx) > rclDst.right) {
  1323. rclCur.right = rclDst.right;
  1324. }
  1325. //
  1326. // Set it for the tiling rectangle in psoHTBlt
  1327. //
  1328. rclHTBlt.right = rclHTBlt.left + (rclCur.right - rclCur.left);
  1329. PLOTDBG(DBG_HTBLT, ("HalftoneBlt: TILE (%ld,%ld)-(%ld,%ld)->(%ld,%ld)-(%ld,%ld)=%ld x %ld",
  1330. rclCur.left, rclCur.top, rclCur.right, rclCur.bottom,
  1331. rclHTBlt.left, rclHTBlt.top,
  1332. rclHTBlt.right, rclHTBlt.bottom,
  1333. rclCur.right - rclCur.left,
  1334. rclCur.bottom - rclCur.top));
  1335. //
  1336. // Set it before the call for the DrvCopyBits()
  1337. //
  1338. pPDev->rclHTBlt = rclHTBlt;
  1339. if (!EngStretchBlt(psoDst, // Dest
  1340. psoSrc, // SRC
  1341. NULL, // MASK
  1342. NULL, // CLIPOBJ
  1343. pxlo, // XLATEOBJ
  1344. NULL, // COLORADJUSTMENT
  1345. pptlHTOrigin, // BRUSH ORG
  1346. &rclCur, // DEST RECT
  1347. &rclSrc, // SRC RECT
  1348. NULL, // MASK POINT
  1349. HALFTONE)) { // HALFTONE MODE
  1350. PLOTERR(("HalftoneeBlt: EngStretchBits(DST=(%ld,%ld)-(%ld,%ld), SRC=(%ld,%ld) FAIELD!",
  1351. rclCur.left, rclCur.top,
  1352. rclCur.right, rclCur.bottom,
  1353. rclSrc.left, rclSrc.top));
  1354. pPDev->psoHTBlt = NULL;
  1355. return(FALSE);
  1356. }
  1357. rclHTBlt.left = rclHTBlt.right;
  1358. rclCur.left = rclCur.right;
  1359. }
  1360. rclHTBlt.top = rclHTBlt.bottom;
  1361. rclCur.top = rclCur.bottom;
  1362. }
  1363. pPDev->psoHTBlt = NULL;
  1364. return(TRUE);
  1365. }
  1366. SURFOBJ *
  1367. CreateSolidColorSURFOBJ(
  1368. PPDEV pPDev,
  1369. SURFOBJ *psoDst,
  1370. HBITMAP *phBmp,
  1371. DWORD SolidColor
  1372. )
  1373. /*++
  1374. Routine Description:
  1375. This function creates a SOLID color bitmap surfobj which can be used to
  1376. blt around.
  1377. Arguments:
  1378. pPDev - Pointer to our PDEV
  1379. phBmp - Pointer the HBITMAP location to be returned for the bitmap
  1380. SolidColor - Solid color
  1381. Return Value:
  1382. SURFOBJ if sucessful, NULL if failed
  1383. Development History:
  1384. 19-Jan-1994 Wed 16:35:54 created
  1385. Revision History:
  1386. --*/
  1387. {
  1388. SURFOBJ *psoHT = NULL;
  1389. HBITMAP hBmpSolid = NULL;
  1390. SURFOBJ *psoSolid;
  1391. //
  1392. // First create a 24-bit source color bitmap
  1393. //
  1394. if (psoSolid = CreateBitmapSURFOBJ(pPDev,
  1395. &hBmpSolid,
  1396. 1,
  1397. 1,
  1398. BMF_24BPP,
  1399. NULL)) {
  1400. LPBYTE pbgr = (LPBYTE)psoSolid->pvScan0;
  1401. PPALENTRY pPal = (PPALENTRY)&SolidColor;
  1402. DWORD HTCellSize = (DWORD)HTPATSIZE(pPDev);
  1403. *pbgr++ = pPal->R;
  1404. *pbgr++ = pPal->G;
  1405. *pbgr++ = pPal->B;
  1406. //
  1407. // Create a compatible halftone surface with size of halftone cell
  1408. //
  1409. if (psoHT = CreateBitmapSURFOBJ(pPDev,
  1410. phBmp,
  1411. HTCellSize,
  1412. HTCellSize,
  1413. (DWORD)HTBMPFORMAT(pPDev),
  1414. NULL)) {
  1415. //
  1416. // Now halftone blt it
  1417. //
  1418. if (!HalftoneBlt(pPDev, // pPDev
  1419. psoDst, // psoDst
  1420. psoHT, // psoHTBlt
  1421. psoSolid, // psoSrc
  1422. NULL, // pxlo,
  1423. NULL, // prclDst
  1424. NULL, // prclSrc
  1425. NULL, // pptlHTOrigin
  1426. TRUE)) { // DoStretchBlt
  1427. PLOTERR(("CreateSolidColorSURFOBJ: HalftoneBlt(STRETCH) Failed"));
  1428. DELETE_SURFOBJ(psoHT, phBmp);
  1429. }
  1430. } else {
  1431. PLOTERR(("CreateSolidColorSURFOBJ: Create 24BPP SOURCE failed"));
  1432. }
  1433. } else {
  1434. PLOTERR(("CreateSolidColorSURFOBJ: Create 24BPP SOURCE failed"));
  1435. }
  1436. DELETE_SURFOBJ(psoSolid, &hBmpSolid);
  1437. return(psoHT);
  1438. }
  1439. SURFOBJ *
  1440. CloneBrushSURFOBJ(
  1441. PPDEV pPDev,
  1442. SURFOBJ *psoDst,
  1443. HBITMAP *phBmp,
  1444. BRUSHOBJ *pbo
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. This function clones the surface object passed in
  1449. Arguments:
  1450. pPDev - Points to our PPDEV
  1451. psoDst - the surface object for the plotter
  1452. phBmp - Pointer to stored hBbitmap created for the cloned surface
  1453. pbo - BRUSHOBJ to be cloned
  1454. Return Value:
  1455. pointer to the cloned surface object, NULL if failure
  1456. Development History:
  1457. 09-Feb-1994 Wed 13:04:46 updated
  1458. Make it assert and handle it when things not supposed happened.
  1459. 04-Jan-1994 Tue 12:11:23 created
  1460. Revision History:
  1461. --*/
  1462. {
  1463. //
  1464. // Ceate a Solid color brush if so, NOTE: All brush patterns created
  1465. // here have brush origin at (0,0) we will align the brush origin
  1466. // when we actually do the ROPs
  1467. //
  1468. if (!IS_RASTER(pPDev)) {
  1469. return(FALSE);
  1470. }
  1471. if (pbo->iSolidColor & 0xFF000000) {
  1472. PDEVBRUSH pDevBrush = (PDEVBRUSH)pbo->pvRbrush;
  1473. if ((pDevBrush) || (pDevBrush = BRUSHOBJ_pvGetRbrush(pbo))) {
  1474. return(CreateBitmapSURFOBJ(pPDev,
  1475. phBmp,
  1476. pDevBrush->sizlBitmap.cx,
  1477. pDevBrush->sizlBitmap.cy,
  1478. pDevBrush->BmpFormat,
  1479. pDevBrush->BmpBits));
  1480. } else {
  1481. return(FALSE);
  1482. }
  1483. } else {
  1484. return(CreateSolidColorSURFOBJ(pPDev,
  1485. psoDst,
  1486. phBmp,
  1487. pbo->iSolidColor));
  1488. }
  1489. }
  1490. SURFOBJ *
  1491. CloneSURFOBJToHT(
  1492. PPDEV pPDev,
  1493. SURFOBJ *psoDst,
  1494. SURFOBJ *psoSrc,
  1495. XLATEOBJ *pxlo,
  1496. HBITMAP *phBmp,
  1497. PRECTL prclDst,
  1498. PRECTL prclSrc
  1499. )
  1500. /*++
  1501. Routine Description:
  1502. This function clones the surface object passed in
  1503. Arguments:
  1504. pPDev - Pointer to our PPDEV
  1505. psoDst - the surface object for the plotter, if psoDst is NULL
  1506. then only the bitmapp will be created
  1507. psoSrc - The surface object to be cloned
  1508. pxlo - XLATE object to be used from source to plotter surfobj
  1509. phBmp - Pointer to stored hBbitmap created for the cloned surface
  1510. prclDst - rectangle rectangle size/location to be cloned
  1511. prclSrc - source rectangle size/location to be cloned
  1512. Return Value:
  1513. pointer to the cloned surface object, NULL if failed.
  1514. if this function is sucessful it will MODIFY the prclSrc to reflect cloned
  1515. surface object
  1516. Development History:
  1517. 04-Jan-1994 Tue 12:11:23 created
  1518. Revision History:
  1519. --*/
  1520. {
  1521. SURFOBJ *psoHT;
  1522. RECTL rclDst;
  1523. RECTL rclSrc;
  1524. POINTL ptlHTOrigin;
  1525. rclSrc.left =
  1526. rclSrc.top = 0;
  1527. rclSrc.right = psoSrc->sizlBitmap.cx;
  1528. rclSrc.bottom = psoSrc->sizlBitmap.cy;
  1529. if (prclSrc) {
  1530. if (!IntersectRECTL(&rclSrc, prclSrc)) {
  1531. PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: Source rectangle is empty"));
  1532. return(NULL);
  1533. }
  1534. }
  1535. PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: rclSrc=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
  1536. rclSrc.left, rclSrc.top,
  1537. rclSrc.right, rclSrc.bottom,
  1538. rclSrc.right - rclSrc.left,
  1539. rclSrc.bottom - rclSrc.top));
  1540. rclDst.left =
  1541. rclDst.top = 0;
  1542. rclDst.right = psoDst->sizlBitmap.cx;
  1543. rclDst.bottom = psoDst->sizlBitmap.cy;
  1544. if (prclDst) {
  1545. if (!IntersectRECTL(&rclDst, prclDst)) {
  1546. PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: Source rectangle is empty"));
  1547. return(NULL);
  1548. }
  1549. }
  1550. PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: rclDst=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
  1551. rclDst.left, rclDst.top,
  1552. rclDst.right, rclDst.bottom,
  1553. rclDst.right - rclDst.left,
  1554. rclDst.bottom - rclDst.top));
  1555. if (psoHT = CreateBitmapSURFOBJ(pPDev,
  1556. phBmp,
  1557. rclDst.right -= rclDst.left,
  1558. rclDst.bottom -= rclDst.top,
  1559. HTBMPFORMAT(pPDev),
  1560. NULL)) {
  1561. //
  1562. // Halftone and tile the source to the destination
  1563. //
  1564. ptlHTOrigin.x = rclDst.left;
  1565. ptlHTOrigin.y = rclDst.top;
  1566. if (prclSrc) {
  1567. if ((rclDst.left = prclSrc->left) > 0) {
  1568. rclDst.left = 0;
  1569. }
  1570. if ((rclDst.top = prclSrc->top) > 0) {
  1571. rclDst.top = 0;
  1572. }
  1573. //
  1574. // Modify the source to reflect the cloned source
  1575. //
  1576. *prclSrc = rclDst;
  1577. }
  1578. if (psoDst) {
  1579. if (!HalftoneBlt(pPDev,
  1580. psoDst,
  1581. psoHT,
  1582. psoSrc,
  1583. pxlo,
  1584. &rclDst,
  1585. &rclSrc,
  1586. &ptlHTOrigin,
  1587. FALSE)) {
  1588. PLOTERR(("CloneSURFOBJToHT: HalftoneBlt(TILE) Failed"));
  1589. DELETE_SURFOBJ(psoHT, phBmp);
  1590. }
  1591. }
  1592. } else {
  1593. PLOTERR(("CreateSolidColorSURFOBJ: Create Halftone SURFOBJ failed"));
  1594. }
  1595. return(psoHT);
  1596. }
  1597. SURFOBJ *
  1598. CloneMaskSURFOBJ(
  1599. PPDEV pPDev,
  1600. SURFOBJ *psoMask,
  1601. HBITMAP *phBmp,
  1602. PRECTL prclMask
  1603. )
  1604. /*++
  1605. Routine Description:
  1606. This function clones the mask surface object passed in
  1607. Arguments:
  1608. pPDev - Pointer to our PPDEV
  1609. psoMask - The mask surface object to be cloned
  1610. phBmp - Pointer to stored hBbitmap created for the cloned surface
  1611. prclMask - Mask source rectangle size/location to be cloned
  1612. Return Value:
  1613. pointer to the cloned surface object or original passed in psoMask, NULL if
  1614. failed.
  1615. if this function is sucessful it will MODIFY the prclMask to reflect cloned
  1616. surface object
  1617. Development History:
  1618. 04-Jan-1994 Tue 12:11:23 created
  1619. Revision History:
  1620. --*/
  1621. {
  1622. SURFOBJ *psoHT;
  1623. RECTL rclMask;
  1624. DWORD cxMask;
  1625. DWORD cyMask;
  1626. DWORD xLoop;
  1627. if (PLOT_CANCEL_JOB(pPDev)) {
  1628. return(FALSE);
  1629. }
  1630. PLOTASSERT(1, "CloneMaskSURFOBJ: psoMask=%08lx is not 1BPP",
  1631. (psoMask) &&
  1632. (psoMask->iType == STYPE_BITMAP) &&
  1633. (psoMask->iBitmapFormat == BMF_1BPP), psoMask);
  1634. PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: prclMask=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
  1635. prclMask->left, prclMask->top,
  1636. prclMask->right, prclMask->bottom,
  1637. prclMask->right - prclMask->left,
  1638. prclMask->bottom - prclMask->top));
  1639. rclMask.left =
  1640. rclMask.top = 0;
  1641. rclMask.right = psoMask->sizlBitmap.cx;
  1642. rclMask.bottom = psoMask->sizlBitmap.cy;
  1643. if (!IntersectRECTL(&rclMask, prclMask)) {
  1644. PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: Mask rectangle is empty"));
  1645. return(NULL);
  1646. }
  1647. cxMask = rclMask.right - rclMask.left;
  1648. cyMask = rclMask.bottom - rclMask.top;
  1649. PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: rclMask=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
  1650. rclMask.left, rclMask.top,
  1651. rclMask.right, rclMask.bottom,
  1652. rclMask.right - rclMask.left,
  1653. rclMask.bottom - rclMask.top));
  1654. if (psoHT = CreateBitmapSURFOBJ(pPDev,
  1655. phBmp,
  1656. cxMask,
  1657. cyMask,
  1658. HTBMPFORMAT(pPDev),
  1659. NULL)) {
  1660. //
  1661. // Update prclMask
  1662. //
  1663. prclMask->left =
  1664. prclMask->top = 0;
  1665. prclMask->right = cxMask;
  1666. prclMask->bottom = cyMask;
  1667. if (psoHT->iBitmapFormat == BMF_1BPP) {
  1668. //
  1669. // !Remember: Our BMF_1BPP 0=BLACK, 1=WHITE
  1670. //
  1671. if (!EngBitBlt(psoHT, // psoDst
  1672. psoMask, // psoSrc
  1673. NULL, // psoMask
  1674. NULL, // pco
  1675. NULL, // pxlo
  1676. prclMask, // prclDst
  1677. (PPOINTL)&rclMask, // pptlSrc
  1678. NULL, // pptlMask
  1679. NULL, // pbo
  1680. (PPOINTL)&ptlZeroOrigin, // pptlBrushOrg ZERO
  1681. 0x3333)) { // NOTSRCCOPY
  1682. PLOTERR(("DrvBitBlt: EngBitBlt(Mask 0x3333) FAILED"));
  1683. }
  1684. } else {
  1685. BYTE SrcMaskBeg;
  1686. BYTE SrcMask;
  1687. BYTE DstMask;
  1688. BYTE bSrc;
  1689. BYTE bDst;
  1690. LPBYTE pbSrcBeg;
  1691. LPBYTE pbDstBeg;
  1692. LPBYTE pbSrc;
  1693. LPBYTE pbDst;
  1694. PLOTASSERT(1, "CloneMaskSURFOBJ: Cloned Mask psoHT=%08lx is not 4BPP",
  1695. (psoHT->iBitmapFormat == BMF_4BPP), psoHT);
  1696. //
  1697. // get the starting location of the original 1BPP mask
  1698. //
  1699. pbSrcBeg = (LPBYTE)psoMask->pvScan0 +
  1700. (rclMask.top * psoMask->lDelta) +
  1701. (rclMask.left >> 3);
  1702. SrcMaskBeg = (BYTE)(0x80 >> (rclMask.left & 0x07));
  1703. pbDstBeg = psoHT->pvScan0;
  1704. while (cyMask--) {
  1705. xLoop = cxMask;
  1706. pbSrc = pbSrcBeg;
  1707. pbSrcBeg += psoMask->lDelta;
  1708. pbDst = pbDstBeg;
  1709. pbDstBeg += psoHT->lDelta;
  1710. SrcMask = SrcMaskBeg;
  1711. DstMask = 0xF0;
  1712. bSrc = *pbSrc++;
  1713. bDst = 0xFF;
  1714. while (xLoop--) {
  1715. if (!SrcMask) {
  1716. SrcMask = 0x80;
  1717. bSrc = *pbSrc++;
  1718. }
  1719. if (bSrc & SrcMask) {
  1720. bDst ^= DstMask;
  1721. }
  1722. SrcMask >>= 1;
  1723. if ((DstMask ^= 0xFF) == 0xF0) {
  1724. *pbDst++ = bDst;
  1725. bDst = 0xFF;
  1726. }
  1727. }
  1728. }
  1729. }
  1730. } else {
  1731. PLOTERR(("CloneMaskSURFOBJ: Create Mask SURFOBJ failed"));
  1732. }
  1733. return(psoHT);
  1734. }