1 /*****************************************************************************\
2 ljfastraster.cpp : Implimentation for the LJFastRaster class
4 Copyright (c) 1996 - 2001, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of Hewlett-Packard nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
32 #ifdef APDK_LJFASTRASTER
35 #include "ljfastraster.h"
36 #include "printerproxy.h"
40 #define INDY_STRIP_HEIGHT 128 // Indy strips can't cross 128 boundary
42 extern uint32_t ulMapDJ600_CCM_K[ 9 * 9 * 9 ];
44 BYTE FrBeginSessionSeq[] = {0xC0, 0x00, 0xF8, 0x86, 0xC0, 0x03, 0xF8, 0x8F, 0xD1, 0x58,
45 0x02, 0x58, 0x02, 0xF8, 0x89, 0x41};
46 BYTE FrFeedOrientationSeq[] = {0xC0, 0x00 , 0xF8, 0x28 };
47 // |fd ori enum| |ori cmd|
48 BYTE FrPaperSizeSeq[] = {0xC0, 0x00 ,0xF8, 0x25};
49 // |pap siz enum| |pap sz cmd|
50 BYTE FrMedSourceSeq[] = {0xC0, 0x00 ,0xF8, 0x26 };
51 // |Med src enum| |Med src cmd|
52 BYTE FrMedDestinationSeq[] = {0xC0, 0x00 ,0xF8 , 0x24 };
53 // |Med Dest enum| |Med src cmd|
54 BYTE FrBeginPageSeq[] = {0x43, 0xD3, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x2A, 0x75, 0xC0, 0x07,0xF8, 0x03, 0x6A,
55 0xC0, 0xCC, 0xF8, 0x2C, 0x7B,
56 0xD3, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x4C, 0x6B};
58 BYTE FrBeginImageSeq[] = {0xC2, 0x00, 0x40, 0x70, 0x68, 0xF8, 0x91, 0xC1};
60 BYTE FrVU_ver_TagSeq[] = {0xC2, 0x00, 0x00, 0x04, 0x00 , 0xF8, 0x95 };
61 // |endian alignd | |Fr_ver_ tag|
62 BYTE FrDataLengthSeq[] = {0xC2, 0x86, 0x0A, 0x00, 0x00, 0xF8, 0x92 };
64 BYTE FrVenUniqSeq[] = {0x46};
65 BYTE FrVUExtn_3Seq[] = {0xC2, 0x11, 0x20, 0x70, 0x68 ,0xF8, 0x91 };
66 // |endian alignd Fr rd img tag| |VU extensn|
67 BYTE FrOpenDataSourceSeq[] = {0xC0, 0x00, 0xF8, 0x88, 0xC0, 0x01, 0xF8, 0x82, 0x48};
69 BYTE FrEndPageSeq[] = {0x44};
70 BYTE FrEndSessionSeq[] = {0x42};
71 BYTE FrCloseDataSourceSeq[] = {0x49};
72 // PJL level commands..
76 const char *ccpPJLStartJob = "\033%-12345X";
77 const char *ccpPJLExitSeq = "\033%-12345X@PJL EOJ\012\033%-12345X";
78 const char *ccpPJLSetRes = "@PJL SET RESOLUTION=600\012";
79 const char *ccpPCLEnterXL = "@PJL ENTER LANGUAGE=PCLXL\012";
80 const char *ccpPJLSetTO = "@PJL SET TIMEOUT=900\012";
81 const char *ccpUEL = "\033%-12345X";
82 const char *ccpPJLComment = ") HP-PCL XL;2;0;Comment\012";
83 const char *ccpPJLSet1BPP = "@PJL SET BITSPERPIXEL=1\012";
84 const char *ccpPJLSetECONOMODE = "@PJL SET ECONOMODE=OFF\012";
85 const char *ccpPJLSetTimeStamp = "@PJL SET JOBATTR=";
87 //**END JETLIB ENTRIES
90 LJFastRaster::LJFastRaster (SystemServices* pSS, int numfonts, BOOL proto)
91 : Printer(pSS, numfonts, proto)
94 if ((!proto) && (IOMode.bDevID))
96 constructor_error = VerifyPenInfo();
99 else ePen = BLACK_PEN; // matches default mode
101 pMode[DEFAULTMODE_INDEX] = new LJFastRasterNormalMode ();
102 pMode[GRAYMODE_INDEX] = new LJFastRasterDraftMode ();
103 //pMode[DEFAULTMODE_INDEX] = pMode[GRAYMODE_INDEX];
107 m_bJobStarted = FALSE;
108 #ifdef APDK_AUTODUPLEX
109 m_bRotateBackPage = FALSE; // Lasers don't require back side image to be rotated
113 m_bStartPageNotSent = TRUE;
115 DBG1("LJFastRaster created\n");
118 LJFastRaster::~LJFastRaster ()
120 DISPLAY_STATUS eDispStatus;
121 if (IOMode.bStatus && m_bJobStarted)
123 for (int i = 0; i < 5; i++)
125 pSS->BusyWait (2000);
126 eDispStatus = ParseError (0);
127 if (eDispStatus == DISPLAY_PRINTING_COMPLETE)
129 pSS->DisplayPrinterStatus (eDispStatus);
136 LJFastRasterNormalMode::LJFastRasterNormalMode ()
137 : GrayMode(ulMapDJ600_CCM_K)
139 ResolutionX[0] = 600;
140 ResolutionY[0] = 600;
141 BaseResX = BaseResY = 600;
145 theQuality = qualityNormal;
147 pmQuality = QUALITY_NORMAL;
149 #if defined(APDK_VIP_COLORFILTERING)
150 Config.bErnie = FALSE; // Raghu
153 #ifdef APDK_AUTODUPLEX
154 bDuplexCapable = TRUE;
157 bFontCapable = FALSE;
160 LJFastRasterDraftMode::LJFastRasterDraftMode ()
161 : GrayMode(ulMapDJ600_CCM_K)
163 ResolutionX[0] = 600;
164 ResolutionY[0] = 600;
165 BaseResX = BaseResY = 600;
169 theQuality = qualityDraft;
171 pmQuality = QUALITY_DRAFT;
173 #if defined(APDK_VIP_COLORFILTERING)
174 Config.bErnie = FALSE; // Raghu
177 #ifdef APDK_AUTODUPLEX
178 bDuplexCapable = TRUE;
181 bFontCapable = FALSE;
184 HeaderLJFastRaster::HeaderLJFastRaster (Printer* p, PrintContext* pc)
190 DRIVER_ERROR HeaderLJFastRaster::Send ()
197 DRIVER_ERROR HeaderLJFastRaster::StartSend ()
199 DRIVER_ERROR err = NO_ERROR;
202 err = thePrinter->Send ((const BYTE*)ccpPJLStartJob, strlen (ccpPJLStartJob));
205 //Set the resolution to 600
206 err = thePrinter->Send ((const BYTE*)ccpPJLSetRes, strlen (ccpPJLSetRes));
209 err = thePrinter->Send ((const BYTE*)ccpPJLSet1BPP, strlen (ccpPJLSet1BPP));
212 QUALITY_MODE eQ = QUALITY_NORMAL;
217 thePrintContext->GetPrintModeSettings (eQ, eM, eC, bD);
219 strcpy (res, "@PJL SET ECONOMODE=");
221 if (eQ == QUALITY_DRAFT)
223 strcat (res, "ON\015\012");
227 strcat (res, "OFF\015\012");
229 err = thePrinter->Send ((const BYTE *) res, strlen (res));
233 //Send the time out command
234 err = thePrinter->Send ((const BYTE*)ccpPJLSetTO, strlen (ccpPJLSetTO));
237 //send the mojave PCL_XL_ENTER_LANG command
238 err = thePrinter->Send ((const BYTE*)ccpPCLEnterXL, strlen (ccpPCLEnterXL));
241 //send the comment string
242 err = thePrinter->Send ((const BYTE*)ccpPJLComment, strlen (ccpPJLComment));
245 err = thePrinter->Send ((const BYTE*)FrBeginSessionSeq,sizeof(FrBeginSessionSeq));
248 //** VU command to enable PCL-XL
249 err = thePrinter->Send ((const BYTE*)FrVUExtn_3Seq,sizeof(FrVUExtn_3Seq));
251 err = thePrinter->Send ((const BYTE*)FrVenUniqSeq,sizeof(FrVenUniqSeq));
254 //----------------------------------------------------------------
255 // Open a data source, which will be kept open for the life
256 // of the session. Any operators that need embedded data will
257 // use this data source.
258 //----------------------------------------------------------------
259 err = thePrinter->Send ((const BYTE*)FrOpenDataSourceSeq,sizeof(FrOpenDataSourceSeq));
265 int HeaderLJFastRaster::FrPaperToMediaSize(PAPER_SIZE psize)
269 case LETTER: return 0; break;
270 case LEGAL: return 1; break;
271 case A4: return 2; break;
272 case B4: return 10; break;
273 case B5: return 11; break;
274 case OUFUKU: return 14; break;
275 case HAGAKI: return 14; break;
276 case A6: return 17; break;
277 #ifdef APDK_EXTENDED_MEDIASIZE
278 case A3: return 5; break;
279 case A5: return 16; break;
280 case LEDGER: return 4; break;
281 case EXECUTIVE: return 3; break;
282 case CUSTOM_SIZE: return 96; break;
283 case ENVELOPE_NO_10: return 6; break;
284 case ENVELOPE_A2: return 6; break;
285 case ENVELOPE_C6: return 8; break;
286 case ENVELOPE_DL: return 9; break;
288 default: return 0; break;
292 DRIVER_ERROR HeaderLJFastRaster::StartPage ()
295 BYTE szCustomSize[16];
297 /* Orienatation: is FrFeedOrientationSeq[1]. Can take the following values:
300 Reversed Portrait : 0x02
301 Reversed Landscape : 0x03
302 Image Orientataion: 0x04
304 err = thePrinter->Send ((const BYTE*)FrFeedOrientationSeq,sizeof(FrFeedOrientationSeq));
307 //Put the papersize into the FrPaperSizeSeq[]
308 PAPER_SIZE ps = thePrintContext->GetPaperSize ();
309 int msizeCode = FrPaperToMediaSize(ps);
310 FrPaperSizeSeq[1] = (BYTE) msizeCode;
311 #ifdef APDK_EXTENDED_MEDIASIZE
312 if(msizeCode == 96 || msizeCode == 17) //Custom paper size or A6
322 LJFUnion.fValue = (float) thePrintContext->PhysicalPageSizeX ();
323 uiXsize = LJFUnion.uiValue;
324 LJFUnion.fValue = (float) thePrintContext->PhysicalPageSizeY ();
325 uiYsize = LJFUnion.uiValue;
326 szCustomSize[k++] = 0xD5;
327 szCustomSize[k++] = (BYTE) (uiXsize & 0x000000FF);
328 szCustomSize[k++] = (BYTE) ((uiXsize & 0x0000FF00) >> 8);
329 szCustomSize[k++] = (BYTE) ((uiXsize & 0x00FF0000) >> 16);
330 szCustomSize[k++] = (BYTE) ((uiXsize & 0xFF000000) >> 24);
331 szCustomSize[k++] = (BYTE) (uiYsize & 0x000000FF);
332 szCustomSize[k++] = (BYTE) ((uiYsize & 0x0000FF00) >> 8);
333 szCustomSize[k++] = (BYTE) ((uiYsize & 0x00FF0000) >> 16);
334 szCustomSize[k++] = (BYTE) ((uiYsize & 0xFF000000) >> 24);
335 szCustomSize[k++] = 0xF8;
336 szCustomSize[k++] = 0x2F;
337 err = thePrinter->Send ((const BYTE *) szCustomSize, k);
341 BYTE FrCustomMediaSeq[] = {0xC0,0x00, 0xF8, 0x30};
342 err = thePrinter->Send ((const BYTE *)FrCustomMediaSeq, sizeof(FrCustomMediaSeq));
348 err = thePrinter->Send ((const BYTE*)FrPaperSizeSeq,sizeof(FrPaperSizeSeq));
352 err = thePrinter->Send ((const BYTE *)FrBeginPageSeq, sizeof(FrBeginPageSeq));
360 DRIVER_ERROR HeaderLJFastRaster::EndPage ()
365 err = thePrinter->Send ((const BYTE*)FrEndPageSeq,sizeof(FrEndPageSeq));
371 DRIVER_ERROR HeaderLJFastRaster::EndJob ()
373 DRIVER_ERROR err = NO_ERROR;
375 err = thePrinter->Send((const BYTE*)FrCloseDataSourceSeq, sizeof(FrCloseDataSourceSeq));
378 err = thePrinter->Send((const BYTE*)FrEndSessionSeq, sizeof(FrEndSessionSeq));
381 err = thePrinter->Send((const BYTE*)ccpPJLExitSeq, strlen (ccpPJLExitSeq));
387 DRIVER_ERROR HeaderLJFastRaster::FormFeed ()
389 DRIVER_ERROR err = NO_ERROR;
390 LJFastRaster *pFRPrinter = (LJFastRaster *) thePrinter;
396 pFRPrinter->m_bStartPageNotSent = TRUE;
400 DRIVER_ERROR HeaderLJFastRaster::SendCAPy (unsigned int iAbsY)
405 #define FAST_RASTER_HEADERSIZE 25
407 //** Faster Raster Path Header address values
409 #define BASE_ADDRESS 0
410 #define PAGE_NUM_ADDRESS 1
411 #define RESOLUTION_ADDRESS_HI 2
412 #define RESOLUTION_ADDRESS_LO 3
413 #define COMPRESSION_ADDRESS_HI 4
414 #define COMPRESSION_ADDRESS_LO 5
415 #define COLOR_PLANE_SPECIFIER_ADDRESS 6
416 #define COMPRESSION_RATIO 7
418 #define IMAGE_SIZE_ADDRESS_HIWORD_HI 12
419 #define IMAGE_SIZE_ADDRESS_HIWORD_LO 13
420 #define IMAGE_SIZE_ADDRESS_LOWORD_HI 14
421 #define IMAGE_SIZE_ADDRESS_LOWORD_LO 15
422 #define IMAGE_WIDTH_ADDRESS_HI 16
423 #define IMAGE_WIDTH_ADDRESS_LO 17
424 #define IMAGE_HEIGTH_ADDRESS_HI 18
425 #define IMAGE_HEIGTH_ADDRESS_LO 19
426 #define ABS_X_ADDRESS_HI 20
427 #define ABS_X_ADDRESS_LO 21
428 #define ABS_Y_ADDRESS_HI 22
429 #define ABS_Y_ADDRESS_LO 23
430 #define BIT_DEPTH_ADDRESS 24
441 #define KILOBYTE 1024
442 #define MAX_IMAGE 200*KILOBYTE
444 DRIVER_ERROR LJFastRaster::Encapsulate (const RASTERDATA* InputRaster, BOOL bLastPlane)
447 DRIVER_ERROR err = NO_ERROR;
450 unsigned char pucHeader[FAST_RASTER_HEADERSIZE];
451 long lImageWidth = ((ModeDeltaPlus*)m_pCompressor)->inputsize;
452 long lResolution = 600;
453 long lBlockOffset = ((((ModeDeltaPlus*)m_pCompressor)->m_lPrinterRasterRow + 127) / 128) * 128 - 128;
455 long lBlockHeight = ((ModeDeltaPlus*)m_pCompressor)->m_lCurrBlockHeight;
457 WORD wTemp = LOWORD (lBlockOffset);
461 memset (pucHeader, 0, FAST_RASTER_HEADERSIZE);
463 pucHeader[ABS_X_ADDRESS_HI] = 0;
464 pucHeader[ABS_X_ADDRESS_LO] = 0;
465 pucHeader[ABS_Y_ADDRESS_HI] = HIBYTE (wTemp);
466 pucHeader[ABS_Y_ADDRESS_LO] = LOBYTE (wTemp);
468 pucHeader[BASE_ADDRESS] = 0;
469 pucHeader[PAGE_NUM_ADDRESS] = 1;
471 wTemp = (WORD) (lResolution );
472 byHIByte = HIBYTE (wTemp);
473 byLOByte = LOBYTE (wTemp);
474 pucHeader[RESOLUTION_ADDRESS_HI] = byHIByte;
475 pucHeader[RESOLUTION_ADDRESS_LO] = byLOByte;
477 wTemp = ((ModeDeltaPlus*)m_pCompressor)->m_bCompressed ? (WORD)eDeltaPlus : (WORD)eRAW;
478 byHIByte = HIBYTE (wTemp);
479 byLOByte = LOBYTE (wTemp);
480 pucHeader[COMPRESSION_ADDRESS_HI] = byHIByte;
481 pucHeader[COMPRESSION_ADDRESS_LO] = byLOByte;
483 pucHeader[COLOR_PLANE_SPECIFIER_ADDRESS] = (BYTE)eK;
484 pucHeader[COMPRESSION_RATIO] = (BYTE)ceil (((ModeDeltaPlus*)m_pCompressor)->m_fRatio);
485 wTemp = HIWORD (InputRaster->rastersize[COLORTYPE_COLOR]);
486 byHIByte = HIBYTE (wTemp);
487 byLOByte = LOBYTE (wTemp);
488 pucHeader[IMAGE_SIZE_ADDRESS_HIWORD_HI] = byHIByte;
489 pucHeader[IMAGE_SIZE_ADDRESS_HIWORD_LO] = byLOByte;
491 wTemp = LOWORD (InputRaster->rastersize[COLORTYPE_COLOR]);
492 byHIByte = HIBYTE (wTemp);
493 byLOByte = LOBYTE (wTemp);
494 pucHeader[IMAGE_SIZE_ADDRESS_LOWORD_HI] = byHIByte;
495 pucHeader[IMAGE_SIZE_ADDRESS_LOWORD_LO] = byLOByte;
497 wTemp = LOWORD (lImageWidth*8);
498 byHIByte = HIBYTE (wTemp);
499 byLOByte = LOBYTE (wTemp);
501 pucHeader[IMAGE_WIDTH_ADDRESS_HI] = byHIByte;
502 pucHeader[IMAGE_WIDTH_ADDRESS_LO] = byLOByte;
504 wTemp = LOWORD (lBlockHeight);
505 byHIByte = HIBYTE (wTemp);
506 byLOByte = LOBYTE (wTemp);
507 pucHeader[IMAGE_HEIGTH_ADDRESS_HI] = byHIByte;
508 pucHeader[IMAGE_HEIGTH_ADDRESS_LO] = byLOByte;
510 wTemp = LOWORD (lBitDepth);
511 pucHeader[BIT_DEPTH_ADDRESS] = LOBYTE (wTemp);
513 unsigned int ulVUDataLength = (int)(InputRaster->rastersize[COLORTYPE_COLOR] + FAST_RASTER_HEADERSIZE);
515 BYTE FrEnterFRModeSeq[] = {0xC2, 0x06, 0x20, 0x70,0x68, 0xF8, 0x91, 0xC2};
516 err = Send ((const BYTE *)FrEnterFRModeSeq, sizeof(FrEnterFRModeSeq));
518 res[0] = (BYTE) (ulVUDataLength & 0xFF);
519 res[1] = (BYTE) ((ulVUDataLength & 0x0000FF00) >> 8);
520 res[2] = (BYTE) ((ulVUDataLength & 0x00FF0000) >> 16);
521 res[3] = (BYTE) ((ulVUDataLength & 0xFF000000) >> 24);
528 //** now embed raster data, header and all
529 err = Send (pucHeader, FAST_RASTER_HEADERSIZE);
531 err = Send (InputRaster->rasterdata[COLORTYPE_COLOR],
532 InputRaster->rastersize[COLORTYPE_COLOR]);
536 Header* LJFastRaster::SelectHeader (PrintContext *pc)
538 phLJFastRaster = new HeaderLJFastRaster (this, pc);
539 return phLJFastRaster;
542 DRIVER_ERROR LJFastRaster::VerifyPenInfo()
548 DRIVER_ERROR LJFastRaster::ParsePenInfo(PEN_TYPE& ePen, BOOL QueryPrinter)
555 Compressor* LJFastRaster::CreateCompressor (unsigned int RasterSize)
557 m_pCompressor = new ModeDeltaPlus (pSS, this, RasterSize);
558 return m_pCompressor;
562 * Function name: ParseError
564 * Owner: Darrell Walker
566 * Purpose: To determine what error state the printer is in.
570 * Parameters on entry: status_reg is the contents of the centronics
571 * status register (at the time the error was
574 * Parameters on exit: unchanged
576 * Return Values: The proper DISPLAY_STATUS to reflect the printer
580 DISPLAY_STATUS LJFastRaster::ParseError(BYTE status_reg)
582 DBG1("LJFastRaster: parsing error info\n");
584 DRIVER_ERROR err = NO_ERROR;
585 BYTE szReadBuff[256];
586 DWORD iReadCount = 256;
587 DISPLAY_STATUS eStatus = (DISPLAY_STATUS) status_reg;
594 memset (szReadBuff, 0, 256);
595 err = pSS->FromDevice (szReadBuff, &iReadCount);
596 if (err == NO_ERROR && iReadCount == 0)
599 if (strstr ((char *) szReadBuff, "JOB"))
601 if (!(tmpStr = strstr ((char *) szReadBuff, "NAME")))
602 return DISPLAY_PRINTING;
604 while (*tmpStr < '0' || *tmpStr > '9')
606 sscanf (tmpStr, "%d", &iErrorCode);
607 if (iErrorCode != (long) (this))
608 return DISPLAY_PRINTING;
611 if (strstr ((char *) szReadBuff, "END"))
613 return DISPLAY_PRINTING_COMPLETE;
617 if (strstr ((char *) szReadBuff, "CANCEL"))
618 return DISPLAY_PRINTING_CANCELED;
620 if (!(tmpStr = strstr ((char *) szReadBuff, "CODE")))
624 while (*tmpStr < '0' || *tmpStr > '9')
626 sscanf (tmpStr, "%d", &iErrorCode);
628 if (iErrorCode < 32000)
629 return DISPLAY_PRINTING;
631 if (iErrorCode == 40010 || iErrorCode == 40020)
632 return DISPLAY_NO_PENS; // Actually, out of toner
634 if (iErrorCode == 40021)
635 return DISPLAY_TOP_COVER_OPEN;
637 if ((iErrorCode / 100) == 419)
638 return DISPLAY_OUT_OF_PAPER;
640 if ((iErrorCode / 1000) == 42 || iErrorCode == 40022)
642 DBG1("Paper Jammed\n");
643 return DISPLAY_PAPER_JAMMED;
646 if (iErrorCode > 40049 && iErrorCode < 41000)
649 return DISPLAY_ERROR_TRAP;
652 if (iErrorCode == 40079)
653 return DISPLAY_OFFLINE;
655 return DISPLAY_ERROR_TRAP;
659 //--------------------------------------------------------------------
660 // Function: ModeDeltaPlus::ModeDeltaPlus
662 // Release: [PROTO4_1]
664 // Description: Preferred ctor
666 // Input: padMultiple - the fBufferDataLength returned from
667 // GetRow must be divisible by this value.
669 // Modifies: fpBuffer
677 // Created: 11/07/96 cal
678 // Last Modified: 5/020/01 DG
679 //--------------------------------------------------------------------
680 ModeDeltaPlus::ModeDeltaPlus
682 SystemServices* pSys,
684 unsigned int PlaneSize
686 Compressor(pSys, PlaneSize, TRUE),
687 thePrinter(pPrinter), // needed by Flush
688 pbyInputImageBuffer (NULL),
691 if (constructor_error != NO_ERROR) // if error in base constructor
696 inputsize = PlaneSize / (MAXCOLORPLANES * MAXCOLORDEPTH * MAXCOLORROWS);
697 inputsize = ((inputsize + 7) / 8) * 8;
699 // allocate a 2X compression buffer..
700 compressBuf = (BYTE*)pSS->AllocMem(2 * INDY_STRIP_HEIGHT * inputsize);
701 if (compressBuf == NULL)
703 constructor_error = ALLOCMEM_ERROR;
705 memset (compressBuf, 0x00, 2 * INDY_STRIP_HEIGHT * inputsize);
707 pbyInputImageBuffer = (BYTE*)pSS->AllocMem(INDY_STRIP_HEIGHT * inputsize);
708 if (pbyInputImageBuffer == NULL)
709 constructor_error=ALLOCMEM_ERROR;
710 memset(pbyInputImageBuffer, 0x00, INDY_STRIP_HEIGHT * inputsize);
712 pbySeedRow = (HPUInt8*) pSS->AllocMem (inputsize * sizeof (HPUInt8));
713 if (pbySeedRow == NULL)
715 constructor_error = ALLOCMEM_ERROR;
717 memset (pbySeedRow, 0, inputsize * sizeof (HPUInt8));
719 m_lCurrCDRasterRow = 0;
720 //m_lPrinterRasterRow = (((LJFastRaster*)thePrinter)->phLJFastRaster)->thePrintContext->PrintableStartY() * 600;
722 m_lPrinterRasterRow = 0;
726 m_bCompressed = FALSE;
727 m_compressedsize = 0;
729 } // ModeDeltaPlus::ModeDeltaPlus
732 //--------------------------------------------------------------------
733 // Function: ModeDeltaPlus::~ModeDeltaPlus
735 // Release: [PROTO4_1]
737 // Description: Destructor.
741 // Modifies: fpBuffer - deletes the buffer
742 // ?? - deletes other buffer(s)??
750 // Created: 11/07/96 cal
751 // Last Modified: 5/020/01 DG
752 //--------------------------------------------------------------------
753 ModeDeltaPlus::~ModeDeltaPlus ()
755 if (pbyInputImageBuffer)
757 pSS->FreeMem (pbyInputImageBuffer);
758 pbyInputImageBuffer = NULL;
762 pSS->FreeMem (pbySeedRow);
766 } // ModeDeltaPlus::~ModeDeltaPlus
769 * The maximum width of a line, which is limited by the amount of hardware
770 * buffer space allocated to storing the seedrow.
772 #define ROW_LIMIT 7040
774 * The maximum number of literals in a single command, not counting the first
775 * pixel. This is limited by the hardware buffer used to store a literal
776 * string. For real images, I expect a value of 64 would be a suitable
777 * minimum. The minimum compression ratio will be bounded by this. Note also
778 * that the software does not need any buffer for this, so there need be no
779 * limit at all on a purely software implementation. For the sake of enabling
780 * a hardware implementation, I would strongly recommend leaving it in and set
781 * to some reasonable value (say 1023 or 255).
783 #define LITERAL_LIMIT 511
785 /* These are set up this way to make it easy to change the predictions. */
786 #define LTEST_W col > 0
787 #define LVAL_W(col) cur_row[col-1]
788 #define LTEST_NW col > 0
789 #define LVAL_NW(col) seedrow[col-1]
790 #define LTEST_WW col > 1
791 #define LVAL_WW(col) cur_row[col-2]
792 #define LTEST_NWW col > 1
793 #define LVAL_NWW(col) seedrow[col-2]
794 #define LTEST_NE (col+1) < row_width
795 #define LVAL_NE(col) seedrow[col+1]
796 #define LTEST_NEWCOL 1
797 #define LVAL_NEWCOL(col) new_color
798 #define LTEST_CACHE 1
799 #define LVAL_CACHE(col) cache
801 #define LOC1TEST LTEST_NE
802 #define LOC1VAL(col) LVAL_NE(col)
803 #define LOC2TEST LTEST_NW
804 #define LOC2VAL(col) LVAL_NW(col)
805 #define LOC3TEST LTEST_NEWCOL
806 #define LOC3VAL(col) LVAL_NEWCOL(col)
809 #define check(condition) if (!(condition)) return 0
811 #define write_comp_byte(val) \
812 check(outptr < pastoutmem); \
813 *outptr++ = (HPUInt8) val;
815 #define read_byte(val) \
816 check(inmem < pastinmem); \
819 #define encode_count(count, over, mem) \
823 if (count <= (uint32_t) 253) \
825 check(mem < pastoutmem); \
826 *mem++ = (HPUInt8) count; \
828 else if (count <= (uint32_t) (254 + 255) ) \
830 check((mem+1) < pastoutmem); \
831 check( count >= 254 ); \
832 check( (count - 254) <= 255 ); \
833 *mem++ = (HPUInt8) 0xFE; \
834 *mem++ = (HPUInt8) (count - 254); \
838 check((mem+2) < pastoutmem); \
839 check( count >= 255 ); \
840 check( (count - 255) <= 65535 ); \
842 *mem++ = (HPUInt8) 0xFF; \
843 *mem++ = (HPUInt8) (count >> 8); \
844 *mem++ = (HPUInt8) (count & 0xFF); \
847 #define decode_count(count, over) \
851 count += (uint32_t) inval; \
852 if (inval == (HPUInt8) 0xFE) \
855 count += (uint32_t) inval; \
857 else if (inval == (HPUInt8) 0xFF) \
860 count += (((uint32_t) inval) << 8); \
862 count += (uint32_t) inval; \
866 #define bytes_for_count(count, over) \
867 ( (count >= 255) ? 3 : (count >= over) ? 1 : 0 )
870 /* The number of bytes we should be greater than to call memset/memcpy */
871 #define memutil_thresh 15
873 HPUInt8* ModeDeltaPlus::encode_header(HPUInt8* outptr, const HPUInt8* pastoutmem, uint32_t isrun, uint32_t location, uint32_t seedrow_count, uint32_t run_count, const HPUInt8 new_color)
877 check (location < 4);
878 check( (isrun == 0) || (isrun == 1) );
880 /* encode "literal" in command byte */
881 byte = (isrun << 7) | (location << 5);
883 /* write out number of seedrow bytes to copy */
884 if (seedrow_count > 2)
887 byte |= (seedrow_count << 3);
894 /* write out command byte */
895 write_comp_byte(byte);
897 /* macro to write count if it's 3 or more */
898 encode_count( seedrow_count, 3, outptr );
900 /* if required, write out color of first pixel */
903 write_comp_byte( new_color );
906 /* macro to write count if it's 7 or more */
907 encode_count( run_count, 7, outptr );
912 /******************************************************************************/
914 /******************************************************************************/
915 BOOL ModeDeltaPlus::Compress (HPUInt8 *outmem,
917 const HPUInt8 *inmem,
918 const uint32_t row_width,
919 const uint32_t inheight,
920 uint32_t horz_ht_dist)
922 register HPUInt8 *outptr = outmem;
923 register uint32_t col;
924 const HPUInt8 *seedrow;
925 uint32_t seedrow_count = 0;
926 uint32_t location = 0;
927 HPUInt8 new_color = (HPUInt8) 0xFF;
928 const HPUInt8 *cur_row;
930 const HPUInt8 *pastoutmem = outmem + *outlen;
931 uint32_t do_word_copies;
932 /* Halftone distance must be 1-32 (but allow 0 == 1) */
933 if (horz_ht_dist > 32)
937 if (horz_ht_dist < 1)
942 seedrow = pbySeedRow;
943 do_word_copies = ((row_width % 4) == 0);
945 for (row = 0; row < inheight; row++)
947 cur_row = inmem + (row * row_width);
950 while (col < row_width)
952 /* First look for seedrow copy */
956 /* Try a fast word-based search */
957 while ( ((col & 3) != 0) &&
959 (cur_row[col] == seedrow[col]) )
966 while ( ((col+3) < row_width) &&
967 *((const uint32_t*) (cur_row + col)) == *((const uint32_t*) (seedrow + col)) )
974 while ( (col < row_width) && (cur_row[col] == seedrow[col]) )
980 /* It is possible that we have hit the end of the line already. */
981 if (col == row_width)
983 /* encode pure seed run as fake run */
984 outptr = encode_header(outptr, pastoutmem, 1 /*run*/, 1 /*location*/, seedrow_count, 0 /*runcount*/, (HPUInt8) 0 /*color*/);
985 /* exit the while loop for this row */
988 check(col < row_width);
991 /* determine the prediction for the current pixel */
992 if ( (LOC1TEST) && (cur_row[col] == LOC1VAL(col)) )
994 else if ( (LOC2TEST) && (cur_row[col] == LOC2VAL(col)) )
996 else if ( (LOC3TEST) && (cur_row[col] == LOC3VAL(col)) )
1001 new_color = cur_row[col];
1005 /* Look for a run */
1007 ((col+1) < row_width)
1009 ((col+1) >= horz_ht_dist)
1011 (cur_row[col+1-horz_ht_dist] == cur_row[col+1])
1014 /* We found a run. Determine the length. */
1015 uint32_t run_count = 0; /* Actually 2 */
1017 while ( ((col+1) < row_width) && (cur_row[col+1-horz_ht_dist] == cur_row[col+1]) )
1023 outptr = encode_header(outptr, pastoutmem, 1 /*run*/, location, seedrow_count, run_count, new_color);
1028 /* We didn't find a run. Encode literal(s). */
1030 uint32_t replacement_count = 0; /* Actually 1 */
1031 const HPUInt8* byte_array = cur_row + col + 1;
1035 * The (col+1) in this test is used because there is no need to
1036 * check for literal breaks if this is the last byte of the row.
1037 * Instead we just tack it on to our literal count at the end.
1039 while ( (col+1) < row_width )
1042 * All cases that will break with 1 unit saved. This
1043 * should be the best breaking spots, since we will always
1044 * gain with the break, but never break for no gain. This
1045 * leads to longer strings which is good for decomp speed.
1050 (cur_row[col] == seedrow[col])
1055 (cur_row[col+1] == seedrow[col+1])
1058 /* seedrow and predict */
1060 (cur_row[col+1] == LVAL_NW(col+1))
1062 (cur_row[col+1] == LVAL_NEWCOL(col+1))
1066 ((col+2) < row_width)
1069 /* seedrow and run */
1071 ((col + 2) >= horz_ht_dist) &&
1072 (cur_row[col+2-horz_ht_dist] == cur_row[col+2])
\r
1075 /* seedrow and northeast predict */
1076 (cur_row[col+1] == LVAL_NE(col+1))
1084 (cur_row[col] != seedrow[col])
1086 ((col + 1) >= horz_ht_dist)
1088 (cur_row[col+1-horz_ht_dist] == cur_row[col+1])
1091 /* Run of 3 or more */
1093 ((col+2) < row_width)
1095 ((col + 2) >= horz_ht_dist)
1097 (cur_row[col+2-horz_ht_dist] == cur_row[col+2])
1100 /* Predict first unit of run */
1101 (cur_row[col] == LVAL_NE(col))
1103 (cur_row[col] == LVAL_NW(col))
1105 (cur_row[col] == LVAL_NEWCOL(col))
1111 /* limited hardware buffer */
1112 if (replacement_count >= LITERAL_LIMIT)
1115 /* add another literal to the list */
1116 replacement_count++;
1120 /* If almost at end of block, just extend the literal by one */
1121 if ( (col+1) == row_width ) {
1122 replacement_count++;
1126 outptr = encode_header(outptr, pastoutmem, 0 /*not run*/, location, seedrow_count, replacement_count, new_color);
1128 /* Copy bytes from the byte array. If rc was 1, then we will
1129 * have encoded a zero in the command byte, so nothing will be
1130 * copied here (the 1 indicates the first pixel, which was
1131 * written above or was predicted. If rc is between 2 and 7,
1132 * then a value between 1 and 6 will have been written in the
1133 * command byte, and we will copy it directly. If 8 or more,
1134 * then we encode more counts, then finally copy all the values
1138 if (replacement_count > 0)
1140 /* Now insert rc bytes of data from byte_array */
1141 if (replacement_count > memutil_thresh)
1143 check( (outptr + replacement_count) <= pastoutmem );
1144 memcpy(outptr, byte_array, (size_t) replacement_count);
1145 outptr += replacement_count;
1149 for (i = 0; i < replacement_count; i++)
1151 write_comp_byte( byte_array[i] );
1157 } /* end of column */
1159 /* save current row as next row's seed row */
1164 check( outptr <= pastoutmem );
1165 if (outptr > pastoutmem)
1167 /* We're in big trouble -- we wrote PAST the end of their memory! */
1172 *outlen = (uint32_t) (outptr - outmem);
1175 } /* end of deltaplus_compress2 */
1178 BOOL ModeDeltaPlus::Process
1183 DRIVER_ERROR err = NO_ERROR;
1186 (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL)) // flushing pipeline
1190 if (input->rasterdata[COLORTYPE_COLOR])
1192 if (m_lCurrCDRasterRow < INDY_STRIP_HEIGHT )
1194 //Copy the data to m_SourceBitmap
1195 memcpy(pbyInputImageBuffer + m_lCurrCDRasterRow * inputsize, input->rasterdata[COLORTYPE_COLOR], input->rastersize[COLORTYPE_COLOR]);
1196 m_lCurrCDRasterRow ++;
1198 if (m_lCurrCDRasterRow == INDY_STRIP_HEIGHT || ((LJFastRaster*)thePrinter)->phLJFastRaster->IsLastBand())
1200 if (((LJFastRaster*)thePrinter)->m_bStartPageNotSent)
1202 err = (((LJFastRaster*)thePrinter)->phLJFastRaster)->StartPage();
1203 ((LJFastRaster*)thePrinter)->m_bStartPageNotSent = FALSE;
1204 m_lPrinterRasterRow = 0;
1207 m_compressedsize = 2 * inputsize * INDY_STRIP_HEIGHT;
1208 BOOL bRet = Compress (compressBuf,
1210 pbyInputImageBuffer,
1217 memcpy (compressBuf, pbyInputImageBuffer, inputsize * INDY_STRIP_HEIGHT);
1218 m_compressedsize = inputsize * INDY_STRIP_HEIGHT;
1222 m_bCompressed = TRUE;
1223 //m_fRatio = (float)m_compressedsize / (float)(inputsize * INDY_STRIP_HEIGHT);
1226 memset(pbyInputImageBuffer, 0x00, inputsize * INDY_STRIP_HEIGHT);
1228 m_lPrinterRasterRow += m_lCurrCDRasterRow;
1229 m_lCurrBlockHeight = m_lCurrCDRasterRow;
1230 m_lCurrCDRasterRow = 0;
1233 ((LJFastRaster*)thePrinter)->phLJFastRaster->SetLastBand(FALSE);
1243 BYTE* ModeDeltaPlus::NextOutputRaster(COLORTYPE color)
1244 // since we return 1-for-1, just return result first call
1246 if (iRastersReady==0)
1249 if (color == COLORTYPE_BLACK)
1260 unsigned int ModeDeltaPlus::GetOutputWidth(COLORTYPE color)
1262 if (color == COLORTYPE_COLOR)
1264 return m_compressedsize;
1274 #endif // defined APDK_LJFASTRASTER