1
/*****************************************************************************\
2
ljfastraster.cpp : Implimentation for the LJFastRaster class
4
Copyright (c) 1996 - 2015, HP 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 HP 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])
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