1 /*****************************************************************************\
2   dj9xxvip.cpp : Implimentation for the DJ9xxVIP class
3 
4   Copyright (c) 1996 - 2015, HP Co.
5   All rights reserved.
6 
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
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.
18 
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 \*****************************************************************************/
30 
31 
32 #ifdef APDK_DJ9xxVIP
33 
34 #include "header.h"
35 #include "io_defs.h"
36 #include "dj9xxvip.h"
37 #include "printerproxy.h"
38 
39 APDK_BEGIN_NAMESPACE
40 
41 
42 #define OUR_PJL_JOBNAME "_PJL_pjl_PJL_pjl_" // this can be anything we want it to be
43 #define DRIVERWARE_JOBNAME  "NEWDRIVERWARE" // don't change this - it is defined in firmware!
44 
45 extern uint32_t ulMapDJ600_CCM_K[ 9 * 9 * 9 ];
46 
47 const char GrayscaleSeq[]= {ESC, '*', 'o', '5', 'W', 0x0B, 0x01, 0x00, 0x00, 0x02};
48 
49 const BYTE ExtraDryTime[] = "\033&b16WPML \004\000\006\001\004\001\004\001\006\010\001";
50 
51 extern BYTE EscAmplCopy(BYTE *dest, int num, char end);
52 extern void AsciiHexToBinary(BYTE* dest, char* src, int count);
53 extern MediaType MediaTypeToPcl (MEDIATYPE eMediaType);
54 
DJ9xxVIP(SystemServices * pSS,BOOL proto)55 DJ9xxVIP::DJ9xxVIP
56 (
57     SystemServices* pSS,
58     BOOL proto
59 ) :
60     Printer(pSS, NUM_DJ6XX_FONTS, proto),
61     PCL3acceptsDriverware(TRUE)
62 {
63 
64     m_bVIPPrinter = TRUE;
65 
66     if (!proto && IOMode.bDevID)
67     {
68         bCheckForCancelButton = TRUE;
69         constructor_error = VerifyPenInfo();
70         CERRCHECK;
71     }
72     else ePen = BOTH_PENS;    // matches default mode
73 
74     PCL3acceptsDriverware = IsPCL3DriverwareAvailable();
75 
76     ModeCount = 0;
77     pMode[ModeCount++] = new GrayModeDJ990(ulMapDJ600_CCM_K,PCL3acceptsDriverware);  // Grayscale K
78     pMode[ModeCount++] = new DJ990Mode();           // Automatic Color
79     pMode[ModeCount++] = new DJ990CMYGrayMode();    // Automatic Grayscale CMY
80 
81 #ifdef APDK_AUTODUPLEX
82 
83 /*
84  *  When bidi is available, query printer for duplexer
85  *  For now, this is available only on Linux which is unidi only.
86  */
87 
88     bDuplexCapable = TRUE;
89 #endif
90 
91 #ifdef APDK_EXTENDED_MEDIASIZE
92     pMode[ModeCount++] = new DJ990KGrayMode ();        // Normal Grayscale K
93     pMode[ModeCount++] = new DJ9902400Mode ();         // HiRes
94     pMode[ModeCount++] = new DJ990DraftMode ();        // Draft Color
95 #endif
96     pMode[ModeCount++] = new DJ990BestMode ();         // Photo Best
97     pMode[ModeCount++] = new DJ990PhotoNormalMode ();  // Photo Normal
98 
99     m_cExtraDryTime    = 0;
100     m_iLeftOverspray   = 0;
101     m_iTopOverspray    = 0;
102     m_iRightOverspray  = 0;
103     m_iBottomOverspray = 0;
104 }
105 
GrayModeDJ990(uint32_t * map,BOOL PCL3OK)106 GrayModeDJ990::GrayModeDJ990
107 (
108     uint32_t *map,
109     BOOL PCL3OK
110 ) :
111     GrayMode(map)
112 {
113 #if defined(APDK_VIP_COLORFILTERING)
114     Config.bErnie = TRUE;
115 #endif
116 
117     Config.bColorImage=FALSE;
118 
119     if (!PCL3OK)
120     {
121         bFontCapable = FALSE;
122     }
123 
124 #ifdef APDK_AUTODUPLEX
125     bDuplexCapable = TRUE;
126 #endif
127 #ifdef APDK_EXTENDED_MEDIASIZE
128     theQuality = qualityDraft;
129     pmQuality = QUALITY_DRAFT;
130 #endif
131 }
132 
DJ990Mode()133 DJ990Mode::DJ990Mode()
134 : PrintMode(NULL)
135 {
136 
137 /*
138  *  The resolutions here are set to 300 for better performance from Cameras.
139  *  REVISIT: Must provide a true 600 dpi printmode later.
140  *  12/21/01
141  *
142  *  For now have added APDK_HIGH_RES_MODES which sets VIP_BASE_RES to 600 in dj9xxvip.h
143  *  If APDK_HIGH_RES_MODES is not defined then VIP_BASE_RES is 300.
144  *  1/9/2002 - JLM
145  */
146 
147     BaseResX = BaseResY = TextRes = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
148 
149     medium = mediaAuto;     // enable media-detect
150 
151 #if defined(APDK_VIP_COLORFILTERING)
152     Config.bErnie = TRUE;
153 #endif
154 
155     Config.bColorImage = FALSE;
156 
157 #ifdef APDK_AUTODUPLEX
158     bDuplexCapable = TRUE;
159 #endif
160 } //DJ990Mode
161 
162 
DJ990CMYGrayMode()163 DJ990CMYGrayMode::DJ990CMYGrayMode()
164 : PrintMode(NULL)
165 {
166 
167 /*
168  *  See comments above regarding 300/600 dpi change
169  */
170 
171     BaseResX = BaseResY = TextRes = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
172 
173     medium = mediaAuto;     // enable media-detect
174 
175 #if defined(APDK_VIP_COLORFILTERING)
176     Config.bErnie = TRUE;
177 #endif
178 
179     Config.bColorImage = FALSE;
180 
181 #ifdef APDK_AUTODUPLEX
182     bDuplexCapable = TRUE;
183 #endif
184     pmColor = GREY_CMY;
185     bFontCapable = FALSE;
186 } //DJ990CMYGrayMode
187 
188 #ifdef APDK_EXTENDED_MEDIASIZE
DJ990KGrayMode()189 DJ990KGrayMode::DJ990KGrayMode () : PrintMode (NULL)
190 {
191 
192 /*
193  *  See comments above regarding 300/600 dpi change.
194  */
195 
196     BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
197     medium = mediaPlain;
198 #if defined(APDK_VIP_COLORFILTERING)
199     Config.bErnie = TRUE;
200 #endif
201 
202     Config.bColorImage = FALSE;
203 
204 #ifdef APDK_AUTODUPLEX
205     bDuplexCapable = TRUE;
206 #endif
207     pmColor = GREY_K;
208     bFontCapable = FALSE;
209     dyeCount = 1;
210 } //DJ990KGrayMode
211 
DJ9902400Mode()212 DJ9902400Mode::DJ9902400Mode () : PrintMode (NULL)
213 {
214     BaseResX =
215     BaseResY = 1200;
216     ResolutionX[0] = 1200;
217     ResolutionY[0] = 1200;
218     bFontCapable = FALSE;
219 #ifdef APDK_AUTODUPLEX
220     bDuplexCapable = FALSE;
221 #endif
222 #if defined(APDK_VIP_COLORFILTERING)
223     Config.bErnie = TRUE;
224 #endif
225 
226     Config.bColorImage = FALSE;
227 
228     medium = mediaHighresPhoto;
229     theQuality = qualityPresentation;
230     pmMediaType = MEDIA_PHOTO;
231     pmQuality = QUALITY_HIGHRES_PHOTO;
232 } // DJ9902400Mode
233 
DJ990DraftMode()234 DJ990DraftMode::DJ990DraftMode () : PrintMode (NULL)
235 {
236     bFontCapable = FALSE;
237 #ifdef APDK_AUTODUPLEX
238     bDuplexCapable = TRUE;
239 #endif
240 #if defined(APDK_VIP_COLORFILTERING)
241     Config.bErnie = TRUE;
242 #endif
243 
244    Config.bColorImage = FALSE;
245 
246     medium = mediaAuto;
247     theQuality = qualityDraft;
248     pmQuality = QUALITY_DRAFT;
249 } // DJ990DraftMode
250 
251 #endif  // APDK_EXTENDED_MEDIASIZE
252 
253 /*
254  *  Some VIP printers do not have Media Sensing device. To enable
255  *  selection of Photo/Best mode for these printers, use this mode.
256  */
257 
DJ990BestMode()258 DJ990BestMode::DJ990BestMode () : PrintMode (NULL)
259 {
260     BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
261 
262 	bFontCapable = FALSE;
263 
264 #ifdef  APDK_AUTODUPLEX
265 	bDuplexCapable = TRUE;
266 #endif
267 
268 #if defined(APDK_VIP_COLORFILTERING)
269     Config.bErnie = TRUE;
270 #endif
271 
272    Config.bColorImage = FALSE;
273 
274 	medium      = mediaGlossy;
275 	theQuality  = qualityPresentation;
276 	pmQuality   = QUALITY_BEST;
277     pmMediaType = MEDIA_PHOTO;
278 } // DJ990BestMode
279 
DJ990PhotoNormalMode()280 DJ990PhotoNormalMode::DJ990PhotoNormalMode () : PrintMode (NULL)
281 {
282     BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
283 
284 	bFontCapable = FALSE;
285 
286 #ifdef  APDK_AUTODUPLEX
287 	bDuplexCapable = TRUE;
288 #endif
289 
290 #if defined(APDK_VIP_COLORFILTERING)
291     Config.bErnie = TRUE;
292 #endif
293 
294    Config.bColorImage = FALSE;
295 
296 	medium      = mediaGlossy;
297 	theQuality  = qualityNormal;
298 	pmQuality   = QUALITY_NORMAL;
299     pmMediaType = MEDIA_PHOTO;
300 } // DJ990PhotoNormalMode
301 
UseGUIMode(PrintMode * pPrintMode)302 BOOL DJ9xxVIP::UseGUIMode
303 (
304     PrintMode* pPrintMode
305 )
306 {
307 	// The reason to change all print mode in DJ9xxVIP family to PCL3GUI mode is that
308 	// the PCL3 path in VIP printers is not tested.  They don't support newer CRD
309 	// command.  The device fint support for this group is not recommended.
310 
311 	return TRUE;
312 	/*
313 	if (pPrintMode->medium == mediaHighresPhoto)
314 	{
315 		return TRUE;
316 	}
317 	else
318 	{
319 #ifdef APDK_AUTODUPLEX
320 		if (pPrintMode->QueryDuplexMode() != DUPLEXMODE_NONE)
321 		{
322 			return TRUE;
323 		}
324 #endif
325 	}
326 #if defined(APDK_FONTS_NEEDED)
327 //    return ((!pPrintMode->bFontCapable) && (!PCL3acceptsDriverware));
328     return (!pPrintMode->bFontCapable);
329 #else
330     return TRUE;
331 #endif
332 	*/
333 } //UseGUIMode
334 
AddPJLHeader()335 DRIVER_ERROR DJ9xxVIP::AddPJLHeader ()
336 {
337     char            *szPJLBuffer = NULL;
338     DRIVER_ERROR    err = NO_ERROR;
339     int             iPJLBufferSize;
340     if (((iPJLBufferSize = pSS->GetPJLHeaderBuffer (&szPJLBuffer)) > 0) && (szPJLBuffer != NULL))
341     {
342         err = Send ((const BYTE *) szPJLBuffer, iPJLBufferSize);
343     }
344     return err;
345 }
346 
Mode10(SystemServices * pSys,Printer * pPrinter,unsigned int PlaneSize)347 Mode10::Mode10
348 (
349     SystemServices* pSys,
350     Printer* pPrinter,
351     unsigned int PlaneSize
352 ) :
353     Compressor(pSys, PlaneSize, TRUE),
354     thePrinter(pPrinter)    // needed by Flush
355 {
356     if (constructor_error != NO_ERROR)  // if error in base constructor
357     {
358         return;
359     }
360 
361 	// In the worst case, compression expands data by 50%
362 	compressBuf = (BYTE*)pSS->AllocMem(PlaneSize + PlaneSize/2);
363 	if (compressBuf == NULL)
364 		constructor_error=ALLOCMEM_ERROR;
365 
366     memset(SeedRow,0xFF,PlaneSize);
367 } //Mode10
368 
369 
~Mode10()370 Mode10::~Mode10()
371 { }
372 
373 
374 const BYTE ResetSeedrow[]={ESC,'*','b','0','Y'};
375 
Flush()376 void Mode10::Flush()
377 // special problem here regarding white rasters: we can't just reset our seedrow to white,
378 // because if a true white raster comes next it will compress to zero, and firmware will
379 // print ITS seedrow. So when we zero our seedrow, we need to zero the firmware seedrow.
380 // The way to do this is to send ESC*b0Y. So that's what we will do here.
381 {
382     if (!seeded)
383     {
384         return;
385     }
386 	compressedsize=0;
387 
388     iRastersReady = 0;
389     seeded = FALSE;
390     memset(SeedRow,0xFF,inputsize);
391     thePrinter->Send(ResetSeedrow, sizeof(ResetSeedrow));
392 } //Flush
393 
394 
CreateCompressor(unsigned int RasterSize)395 Compressor* DJ9xxVIP::CreateCompressor(unsigned int RasterSize)
396 {
397     return new Mode10(pSS,this,RasterSize);
398 }
399 
400 
SelectHeader(PrintContext * pc)401 Header* DJ9xxVIP::SelectHeader(PrintContext* pc)
402 {
403     return new HeaderDJ990(this,pc);
404 }
405 
406 
HeaderDJ990(Printer * p,PrintContext * pc)407 HeaderDJ990::HeaderDJ990(Printer* p,PrintContext* pc)
408     : Header(p,pc)
409 {
410     SetMediaSource (pc->GetMediaSource());
411 }
412 
413 
ConfigureRasterData()414 DRIVER_ERROR HeaderDJ990::ConfigureRasterData()
415 // This is the more sophisticated way of setting color and resolution info.
416 //
417 // NOTE: Will need to be overridden for DJ5xx.
418 {
419 
420 	char buff[50];      // 20 + 3 for crdstart + 3 for ##W
421 	char *out = buff;
422 
423 
424     // begin the CRD command
425     memcpy(out,crdStart,sizeof(crdStart) );
426     out += sizeof(crdStart);
427 
428     // now set up the "#W" part, where #= number of data bytes in the command
429     // #= 20
430     //      format,ID,components(2bytes),resolutions (4bytes),
431     //      compresssion method, orientation, bits/component,planes/component
432 	*out++ = 0x32;    // "2"
433     *out++ = 0x30;    // "0"
434     *out++ = 'W';
435 
436 #define VIPcrdFormat 6
437 #define VIPKRGBID 0x1F
438 
439     *out++ = VIPcrdFormat;
440     *out++ = VIPKRGBID;
441 
442     // 2-byte component count field
443     // number of components for sRGB is 1 by defintiion
444     *out++ = 0;     // leading byte
445     *out++ = 2;     // 2 "component"
446 
447     *out++ = ResolutionX[0]/256;
448     *out++ = ResolutionX[0]%256;
449     *out++ = ResolutionY[0]/256;
450     *out++ = ResolutionY[0]%256;
451 
452     // compression method
453     *out++ = 9;    // mode 9 compression
454 
455     // orientation
456     *out++ = 0;     // pixel major code
457 
458     // bits per component
459     *out++ = 1;    // 1 bits each for k
460 
461     // planes per component
462     *out++ = 1;     // K = one component, one "plane"
463 
464     *out++ = ResolutionX[0]/256;
465     *out++ = ResolutionX[0]%256;
466     *out++ = ResolutionY[0]/256;
467     *out++ = ResolutionY[0]%256;
468 
469     // compression method
470     *out++ = 10;    // mode 10 compression
471 
472     // orientation
473     *out++ = 1;     // pixel major code
474 
475     // bits per component
476     *out++ = 32;    // 8 bits each for s,R,G,B
477 
478     // planes per component
479     *out++ = 1;     // sRGB = one component, one "plane"
480 
481     return thePrinter->Send((const BYTE*) buff, out-buff);
482 } //ConfigureRasterData
483 
484 
ConfigureImageData()485 DRIVER_ERROR HeaderDJ990::ConfigureImageData()
486 {
487     DRIVER_ERROR err = thePrinter->Send((const BYTE*)cidStart, sizeof(cidStart));
488     ERRCHECK;
489     char sizer[3];
490     sprintf(sizer,"%dW",6);
491     err = thePrinter->Send((const BYTE*)sizer,2);
492     ERRCHECK;
493 
494     BYTE colorspace = 2;    // RGB
495     BYTE coding = 3;
496     BYTE bitsindex = 3;     // ??
497     BYTE bitsprimary = 8;
498     BYTE CID[6];
499     CID[0] = colorspace;
500     CID[1]=coding;
501     CID[2] = bitsindex;
502     CID[3] = CID[4] = CID[5] = bitsprimary;
503 
504     return thePrinter->Send((const BYTE*) CID, 6);
505 } //ConfigureImageData
506 
507 
Send()508 DRIVER_ERROR HeaderDJ990::Send()
509 /// ASSUMES COMPRESSION ALWAYS ON -- required by DJ990
510 {
511     DRIVER_ERROR err;
512 //    PRINTMODE_VALUES    *pPMV;
513     COLORMODE       eColorMode = COLOR;
514     MEDIATYPE       eMediaType;
515     QUALITY_MODE    eQualityMode;
516     BOOL            bDeviceText;
517 
518     thePrintContext->GetPrintModeSettings (eQualityMode, eMediaType, eColorMode, bDeviceText);
519 
520     if (eMediaType == MEDIA_CDDVD)
521     {
522         thePrintContext->SetMediaSource (sourceTrayCDDVD);
523         SetMediaSource (sourceTrayCDDVD);
524     }
525 
526     StartSend();
527 
528 #ifdef APDK_AUTODUPLEX
529     if (thePrintContext->QueryDuplexMode () != DUPLEXMODE_NONE)
530     {
531         err = thePrinter->Send ((const BYTE *) EnableDuplex, sizeof (EnableDuplex));
532         BYTE    cDryTime;
533         cDryTime = (BYTE) ((thePrinter->GetHint (EXTRA_DRYTIME_HINT)) & 0xFF);
534         if (cDryTime != 0)
535         {
536             err = thePrinter->Send (ExtraDryTime, sizeof (ExtraDryTime) - 1);
537             err = thePrinter->Send ((const BYTE *) &cDryTime, 1);
538             ERRCHECK;
539         }
540     }
541 #endif
542 
543     err = ConfigureImageData();
544     ERRCHECK;
545 
546     err = ConfigureRasterData();
547     ERRCHECK;
548 
549     if (thePrintMode->dyeCount == 1)    // grayscale
550     {
551         err=thePrinter->Send((const BYTE*)GrayscaleSeq, sizeof(GrayscaleSeq) );
552         ERRCHECK;
553     }
554     else
555     {
556         if (eColorMode == GREY_CMY)
557         {
558             char    pStr[12];
559             memcpy (pStr, GrayscaleSeq, 10);
560             pStr[9] = 0x01;
561             err = thePrinter->Send ((const BYTE *) pStr, 10);
562         }
563     }
564 
565     /////////////////////////////////////////////////////////////////////////////////////
566     // unit-of-measure command --- seems to be need in DJ990 PCL3 mode
567     char uom[10];
568     sprintf(uom,"%c%c%c%d%c",ESC,'&','u',thePrintMode->ResolutionX[K],'D');
569     err = thePrinter->Send((const BYTE*)uom, strlen (uom));
570     ERRCHECK;
571 
572     // another command that helps PCLviewer
573     unsigned int width=thePrintContext->OutputPixelsPerRow();
574     unsigned int digits = 1;
575     unsigned int x = width;
576     while (x > 10)
577     {
578         digits++;
579         x = x / 10;
580     }
581     sprintf(uom,"%c%c%c%d%c",ESC,'*','r', width,'S');
582     err = thePrinter->Send((const BYTE*)uom, 4 + digits );
583     ERRCHECK;
584 
585     ////////////////////////////////////////////////////////////////////////////////////
586 
587 /*
588  *  Custom papersize command
589  */
590 
591     if (thePrintContext->thePaperSize == CUSTOM_SIZE)
592     {
593         BYTE    szStr[32];
594         short   sWidth, sHeight;
595         BYTE    b1, b2;
596         sWidth  = (short) (thePrintContext->PhysicalPageSizeX () * thePrintContext->EffectiveResolutionX ());
597         sHeight = (short) (thePrintContext->PhysicalPageSizeY () * thePrintContext->EffectiveResolutionY ());
598         memcpy (szStr, "\x1B*o5W\x0E\x05\x00\x00\x00\x1B*o5W\x0E\x06\x00\x00\x00", 20);
599         b1 = (BYTE) ((sWidth & 0xFF00) >> 8);
600         b2 = (BYTE) (sWidth & 0xFF);
601         szStr[8] = b1;
602         szStr[9] = b2;
603         b1 = (BYTE) ((sHeight & 0xFF00) >> 8);
604         b2 = (BYTE) (sHeight & 0xFF);
605         szStr[18] = b1;
606         szStr[19] = b2;
607         err = thePrinter->Send ((const BYTE *) szStr, 20);
608     }
609 
610     float   fXOverSpray = 0.0;
611     float   fYOverSpray = 0.0;
612     float   fLeftOverSpray = 0.0;
613     float   fTopOverSpray  = 0.0;
614 	FullbleedType   fbType;
615     if (thePrintContext->bDoFullBleed &&
616         thePrinter->FullBleedCapable (thePrintContext->thePaperSize,
617 									  &fbType,
618                                       &fXOverSpray, &fYOverSpray,
619                                       &fLeftOverSpray, &fTopOverSpray))
620     {
621 
622 /*
623  *      To get the printer to do fullbleed printing, send the top and
624  *      left overspray commands. Overspray is needed to take care of
625  *      skew during paper pick. These values may be mech dependent.
626  *      Currently, supported only on PhotoSmart 100. Malibu supports
627  *      fullbleed printing also. The current values for overspray are
628  *      0.059 inch for top, bottom and left edges and 0.079 for right edge.
629  */
630 
631         BYTE cBuf[4];
632         BYTE TopOverSpraySeq[]  = {0x1b, 0x2A, 0x6F, 0x35, 0x57, 0x0E, 0x02, 0x00};
633                                 // "Esc*o5W 0E 02 00 00 00" Top edge overspray for full-bleed printing
634 
635         BYTE LeftOverSpraySeq[] = {0x1b, 0x2A, 0x6F, 0x35, 0x57, 0x0E, 0x01, 0x00};
636                                 // "Esc*o5W 0E 01 00 00 00" Left edge overspray for full-bleed printing
637 
638         short topspray = (short)(fTopOverSpray * thePrintContext->EffectiveResolutionY() + 0.5);
639         cBuf[1] = topspray & 0xFF;
640         cBuf[0] = topspray >> 8;
641 
642         err = thePrinter->Send ((const BYTE *) TopOverSpraySeq, sizeof (TopOverSpraySeq));
643         err = thePrinter->Send ((const BYTE *) cBuf, 2);
644 
645         // set the left overspray value based on resolution and global constant for horizontal overspray
646         short leftspray = (short)(fLeftOverSpray * thePrintContext->EffectiveResolutionX() + 0.5);
647         cBuf[1] = leftspray & 0xFF;
648         cBuf[0] = leftspray >> 8;
649 
650         err = thePrinter->Send ((const BYTE *) LeftOverSpraySeq, sizeof (LeftOverSpraySeq));
651         err = thePrinter->Send ((const BYTE *) cBuf, 2);
652     }
653 
654 //  Now send media pre-load command
655     err = thePrinter->Send ((const BYTE *) "\033&l-2H", 6);   // Moved from Modes(), des 3/11/03
656     ERRCHECK;
657 
658 //  Send speed mech command
659     thePrinter->SetHint (SPEED_MECH_HINT, 0);
660 
661     // no need for compression command, it's in the CRD
662 
663     err = thePrinter->Send((const BYTE*)grafStart, sizeof(grafStart) );
664     ERRCHECK;
665 
666     if (!thePrinter->UseGUIMode (thePrintContext->CurrentMode) &&
667         (thePrintContext->PhysicalPageSizeX ()) < 8.0)
668     {
669 
670         BYTE    blankRow[40];
671         memset (blankRow, 0xFF, 40);
672         strcpy ((char *) blankRow, "\033*p0Y\033*b23W");
673         blankRow[11] = 18;   // ce, 7f
674         blankRow[30] = 0xCE; blankRow[31] = 0x7F;
675         err = thePrinter->Send ((const BYTE *) blankRow, 34);
676     }
677 
678     return err;
679 } //Send
680 
681 
StartSend()682 DRIVER_ERROR HeaderDJ990::StartSend()
683 {
684     DRIVER_ERROR err;
685 
686     err = thePrinter->Send((const BYTE*)Reset,sizeof(Reset));
687     ERRCHECK;
688 
689     err = thePrinter->Send((const BYTE*)UEL,sizeof(UEL));
690     ERRCHECK;
691 
692     err = thePrinter->AddPJLHeader ();
693     ERRCHECK;
694 
695     err = thePrinter->Send((const BYTE*)EnterLanguage,sizeof(EnterLanguage));
696     ERRCHECK;
697 
698     if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
699     {
700         err = thePrinter->Send((const BYTE*)PCL3,sizeof(PCL3));
701     }
702     else
703     {
704         err = thePrinter->Send((const BYTE*)PCLGUI,sizeof(PCLGUI));
705     }
706     ERRCHECK;
707 
708 
709     err = thePrinter->Send((const BYTE*)&LF,1);
710     ERRCHECK;
711 
712     err = Modes ();            // Set media source, type, size and quality modes.
713     ERRCHECK;
714 
715 //  Send media subtype if set
716     int    iMediaSubtype = thePrintContext->GetMediaSubtype ();
717     if (iMediaSubtype != APDK_INVALID_VALUE)
718     {
719         BYTE    szMediaSubtypeSeq[] = {0x1B, '*', 'o', '5', 'W', 0x0D, 0x03, 0x00, 0x00, 0x00};
720         szMediaSubtypeSeq[8] = (BYTE) ((iMediaSubtype & 0xFF00) >> 8);
721         szMediaSubtypeSeq[9] = (BYTE) (iMediaSubtype & 0x00FF);
722         err = thePrinter->Send ((const BYTE *) szMediaSubtypeSeq, sizeof(szMediaSubtypeSeq));
723         ERRCHECK;
724     }
725 
726     if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
727     {
728         err = Margins();          // set margins
729     }
730 
731 // special GUI mode top margin set
732 
733     else if ((thePrintContext->PrintableStartY ()) > 0.0)
734     {
735         CAPy = thePrintContext->GUITopMargin();
736     }
737 
738     if ((thePrintContext->GetMediaSource()) == sourceTrayCDDVD)
739     {
740         err = thePrinter->Send ((const BYTE *) "\033*o5W\x0D\x03\x00\x04\x0C", 10);
741         ERRCHECK;
742     }
743 
744     return err;
745 } //StartSend
746 
747 /* This could replace Header::SetMediaSource in header.cpp. des 8/5/02 */
SetMediaSource(MediaSource msource)748 void HeaderDJ990::SetMediaSource(MediaSource msource)
749 // Sets value of PCL::mediasource and associated counter msrccount
750 {
751     msrccount=EscAmplCopy((BYTE*)mediasource,msource,'H');
752     if (msource == sourceTrayCDDVD)
753     {
754         SetMediaType (mediaCDDVD);
755         SetQuality (qualityPresentation);
756         return;
757     }
758     if (msource == sourceTray2 || msource > sourceTrayAuto)
759     {
760         SetMediaType (mediaPlain);
761     }
762 }
763 
VerifyPenInfo()764 DRIVER_ERROR DJ9xxVIP::VerifyPenInfo()
765 {
766     DRIVER_ERROR err=NO_ERROR;
767 
768     if(IOMode.bDevID == FALSE)
769         return err;
770     err = ParsePenInfo(ePen);
771 
772     if(err == UNSUPPORTED_PEN) // probably Power Off - pens couldn't be read
773     {
774         DBG1("DJ9xxVIP::Need to do a POWER ON to get penIDs\n");
775 
776         // have to delay or the POWER ON will be ignored
777         if (pSS->BusyWait((DWORD)2000) == JOB_CANCELED)
778         {
779             return JOB_CANCELED;
780         }
781 
782         DWORD length = sizeof(DJ895_Power_On);
783         err = pSS->ToDevice(DJ895_Power_On,&length);
784         ERRCHECK;
785 
786         err = pSS->FlushIO();
787         ERRCHECK;
788 
789         // give the printer some time to power up
790         if (pSS->BusyWait ((DWORD) 2500) == JOB_CANCELED)
791         {
792             return JOB_CANCELED;
793         }
794 
795         err = ParsePenInfo(ePen);
796     }
797 
798     ERRCHECK;
799 
800     // check for the normal case
801     if (ePen == BOTH_PENS || ePen == MDL_BLACK_AND_COLOR_PENS)
802     {
803         return NO_ERROR;
804     }
805 
806 //  Should we return NO_ERROR for MDL_BOTH also - malibu??
807 
808     while ( ePen != BOTH_PENS &&  pSS->GetVIPVersion () == 1  )
809     {
810 
811         switch (ePen)
812         {
813             case BLACK_PEN:
814                 // black pen installed, need to install color pen
815                 pSS->DisplayPrinterStatus(DISPLAY_NO_COLOR_PEN);
816                 break;
817             case COLOR_PEN:
818                 // color pen installed, need to install black pen
819                 pSS->DisplayPrinterStatus(DISPLAY_NO_BLACK_PEN);
820                 break;
821             case NO_PEN:
822                 // neither pen installed
823             default:
824                 pSS->DisplayPrinterStatus(DISPLAY_NO_PENS);
825                 break;
826         }
827 
828         if (pSS->BusyWait(500) == JOB_CANCELED)
829         {
830             return JOB_CANCELED;
831         }
832 
833         err =  ParsePenInfo(ePen);
834         ERRCHECK;
835     }
836 
837     pSS->DisplayPrinterStatus(DISPLAY_PRINTING);
838 
839     return NO_ERROR;
840 } //VerifyPenInfo
841 
842 
ParsePenInfo(PEN_TYPE & ePen,BOOL QueryPrinter)843 DRIVER_ERROR DJ9xxVIP::ParsePenInfo(PEN_TYPE& ePen, BOOL QueryPrinter)
844 {
845     char* str;
846     int num_pens = 0;
847     PEN_TYPE temp_pen1 = NO_PEN;
848     BYTE penInfoBits[4];
849     int     i;
850 
851 /*
852  *  First check if this printer's firmware version is one I know about. Currently
853  *  I know upto S:04. I can't guess if the pen info nibbles have shifted in the
854  *  new version. Can't tell the user about missing pens.
855  */
856 
857     if ((pSS->GetVIPVersion ()) > 5)
858     {
859         ePen = BOTH_PENS;
860         return NO_ERROR;
861     }
862 
863     DRIVER_ERROR err = SetPenInfo (str, QueryPrinter);
864 //    ERRCHECK;
865     if (err != NO_ERROR)
866     {
867         ePen = BOTH_PENS;
868         return NO_ERROR;
869     }
870     iNumMissingPens = 0;
871 
872     // the first byte indicates how many pens are supported
873     if ((str[0] >= '0') && (str[0] <= '9'))
874     {
875         num_pens = str[0] - '0';
876     }
877     else if ((str[0] >= 'A') && (str[0] <= 'F'))
878     {
879         num_pens = 10 + (str[0] - 'A');
880     }
881     else if ((str[0] >= 'a') && (str[0] <= 'f'))
882     {
883         num_pens = 10 + (str[0] - 'a');
884     }
885     else
886     {
887         return BAD_DEVICE_ID;
888     }
889 
890     if ((int) strlen (str) < (num_pens * 8))
891     {
892         return BAD_DEVICE_ID;
893     }
894 
895 //  DJ990 style DevID
896 
897     if (pSS->GetVIPVersion () == 1)
898     {
899         if (num_pens < 2)
900         {
901             return UNSUPPORTED_PEN;
902         }
903 
904         // parse pen1 (should be black)
905         AsciiHexToBinary(penInfoBits, str+1, 4);
906         penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
907 
908         if ((penInfoBits[0] == 0xc1) && (penInfoBits[1] == 0x10))
909         {
910             temp_pen1 = BLACK_PEN;
911         }
912         else if (penInfoBits[0] == 0xc0)
913         {   // missing pen
914             temp_pen1 = NO_PEN;
915             iNumMissingPens = 1;
916         }
917         else
918         {
919             return UNSUPPORTED_PEN;
920         }
921 
922         // now check pen2 (should be color)
923         AsciiHexToBinary(penInfoBits, str+9, 4);
924         penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
925 
926         if ((penInfoBits[0] == 0xc2) && (penInfoBits[1] == 0x08))
927         {   // Chinook
928             if (temp_pen1 == BLACK_PEN)
929             {
930                 ePen = BOTH_PENS;
931             }
932             else
933             {
934                 ePen = COLOR_PEN;
935             }
936         }
937         else if (penInfoBits[0] == 0xc0)
938         {   // missing pen
939             ePen = temp_pen1;
940             iNumMissingPens = 1;
941         }
942         else
943         {
944             return UNSUPPORTED_PEN;
945         }
946 
947         return NO_ERROR;
948     }
949 
950 //  Check for missing pens
951 
952     if (*(str - 1) == '1' && *(str - 2) == '1')
953     {
954         return UNSUPPORTED_PEN;
955     }
956 
957     char    *p = str + 1;
958 
959 /*
960  *  Pen Type Info
961  *
962     Bit 31 (1 bit)
963 
964     1 if these fields describe a print head
965     0 otherwise
966     Bit 30 (1 bit)
967 
968     1 if these fields describe an ink supply
969     0 otherwise
970 
971     Bits 29 .. 24 (6 bits) describes the pen/supply type:
972 
973     0  = none
974     1  = black
975     2  = CMY
976     3  = KCM
977     4  = Cyan
978     5  = Meganta
979     6  = Yellow
980 	7  = Cyan - low dye load
981     8  = Magenta - low dye load
982     9  = Yellow - low dye load (may never be used, but reserve space anyway) [def added Jun 3, 2002]
983     10 = gGK - two shades of grey plus black; g=light grey, G=medium Grey, K=black  [added Sep 12, 02]
984     11 = Blue Pen
985     12 .. 62 = reserved for future use
986     63 = Unknown
987 
988     Bits 23 .. 19 (5 bits) describes the pen/supply id:
989 
990     0 = none
991     1 = color (Formerly N)
992     2 = black (Formerly H)
993     3 = Flash (Formerly F)
994     4 = (Formerly R -- only 6xx family)
995     5 = (Formerly C -- only 6xx family)
996     6 = (Formerly M -- only for 6xx family)
997     7 = (Cp1160 Pen)
998     8 = Europa (Jupiter Ink)
999     9 = Wax (pen/ink combo; k)
1000     10 = (pen/ink combo; cmy)
1001     11 = (pen/ink combo; kcm)
1002     12 = (pen/ink combo; k)    [def added Jun 27, 2002]
1003     13 = (k)  [def added Jun 27, 2002]
1004     14 = pen/ink combo; gGK)  [added Sep 12, 02]
1005     15 .. 30 = reserved for future use    [def added Jun 27, 2002]
1006     31 = Other/Unknown  [def added Jun 27, 2002]
1007  */
1008 
1009     ePen = NO_PEN;
1010 
1011     if (pSS->GetVIPVersion () == 3)
1012     {
1013         for (i = 0; i < num_pens; i++, p += 4)
1014         {
1015             if (*p > 0 && *p < '5')
1016             {
1017                 continue;
1018             }
1019             switch (*p)
1020             {
1021                 case 0:
1022                 {
1023                     iNumMissingPens++;
1024                     break;
1025                 }
1026                 case '5':
1027                 {
1028                     ePen = BLACK_PEN;
1029                     break;
1030                 }
1031                 case '6':
1032                 case '7':
1033                 case '8':
1034                 {
1035                     if (ePen == BLACK_PEN)
1036                     {
1037                         ePen = BOTH_PENS;
1038                     }
1039                     else if (ePen != BOTH_PENS)
1040                     {
1041                         ePen = COLOR_PEN;
1042                     }
1043                     break;
1044                 }
1045             }
1046 
1047         }
1048         if (iNumMissingPens != 0)
1049         {
1050             return MISSING_PENS;
1051         }
1052         return NO_ERROR;
1053     }
1054 
1055 #if 0
1056 
1057     BYTE    penColor;
1058 
1059 /*
1060  *  These printers don't need all pens to be installed to print. Parsing the pen info
1061  *  is not all that useful. Also, the note about incompatible pen is not valid anymore,
1062  *  it just means unknown or other pen.
1063  *  Raghu - 11/17/05
1064  */
1065 
1066     for (i = 0; i < num_pens; i++, p += 8)
1067     {
1068         AsciiHexToBinary (penInfoBits, p, 8);
1069 
1070         if ((penInfoBits[1] & 0xf8) == 0xf8)
1071         {
1072 
1073 //          The high 5 bits in the 3rd and 4th nibble (second byte) identify the
1074 //          installed pen. If all 5 bits are on, user has installed an incompatible pen.
1075 
1076             return UNSUPPORTED_PEN;
1077         }
1078 
1079         if ((penInfoBits[0] & 0x40) != 0x40)         // if Bit 31 is 1, this is not a pen
1080         {
1081             continue;
1082         }
1083         penColor = penInfoBits[0] & 0x3F;
1084         switch (penColor)
1085         {
1086             case 0:
1087             {
1088                 iNumMissingPens++;
1089                 break;
1090             }
1091             case 1:
1092                 ePen = BLACK_PEN;
1093                 break;
1094             case 2:
1095             {
1096                 if (ePen == BLACK_PEN)
1097                 {
1098                     ePen = BOTH_PENS;
1099                 }
1100                 else if (ePen == MDL_PEN)
1101                 {
1102                     ePen = MDL_BOTH;
1103                 }
1104                 else if (ePen == GREY_PEN)
1105                 {
1106                     ePen = GREY_BOTH;
1107                 }
1108                 else
1109                 {
1110                     ePen = COLOR_PEN;
1111                 }
1112                 break;
1113             }
1114             case 3:
1115                 if (ePen == BLACK_PEN)
1116                 {
1117                     ePen = MDL_AND_BLACK_PENS;
1118                 }
1119                 else if (ePen == COLOR_PEN)
1120                 {
1121                     ePen = MDL_BOTH;
1122                 }
1123                 else if (ePen == BOTH_PENS)
1124                 {
1125                     ePen = MDL_BLACK_AND_COLOR_PENS;
1126                 }
1127                 else if (ePen == GREY_PEN)
1128                 {
1129                     ePen = MDL_AND_GREY_PENS;
1130                 }
1131                 else if (ePen == GREY_BOTH)
1132                 {
1133                     ePen = MDL_GREY_AND_COLOR_PENS;
1134                 }
1135                 else
1136                 {
1137                     ePen = MDL_PEN;
1138                 }
1139                 break;
1140             case 4:             // cyan pen
1141             case 5:             // magenta pen
1142             case 6:             // yellow pen
1143             case 7:             // low dye load cyan pen
1144             case 8:             // low dye load magenta pen
1145             case 9:             // low dye load yellow pen
1146             case 11:            // blue pen
1147                 if (ePen == BLACK_PEN || ePen == BOTH_PENS)
1148                 {
1149                     ePen = BOTH_PENS;
1150                 }
1151                 else
1152                 {
1153                     ePen = COLOR_PEN;
1154                 }
1155                 break;
1156             case 10:
1157                 ePen = GREY_PEN;
1158                 break;
1159             default:
1160                 ePen = UNKNOWN_PEN;
1161         }
1162     }
1163     return NO_ERROR;
1164 #endif
1165 
1166     ePen = BOTH_PENS;
1167     return NO_ERROR;
1168 
1169 } //ParsePenInfo
1170 
1171 
IsPCL3DriverwareAvailable()1172 BOOL DJ9xxVIP::IsPCL3DriverwareAvailable()
1173 {
1174 #ifdef  APDK_LINUX
1175     // Linux supports Bi-Di, but is not enabled at this time. See comments below.
1176     return TRUE;
1177 #else
1178 
1179     BOOL pcl3driverware = TRUE;     // default to TRUE since this is the case for all but some early units
1180     BOOL inAJob = FALSE;
1181     char *pStr;
1182     char *pEnd;
1183     BYTE devIDBuff[DevIDBuffSize];
1184     int maxWaitTries;
1185     int i;
1186 
1187     // if don't have bidi can't check so assume driverware is ok since only certain
1188     // 990s don't handle driverware in PCL3 mode
1189     if (!IOMode.bDevID)
1190     {
1191         return TRUE;
1192     }
1193 
1194     if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR)
1195     {
1196         goto cleanup;
1197     }
1198 
1199     // if printer does not have firmware based on the first 990 release
1200     // don't bother checking, can assume driverware commands are OK
1201     if (!strstr((const char*)devIDBuff+2,"MDL:DESKJET 990C") &&
1202         !strstr((const char*)devIDBuff+2,"MDL:PHOTOSMART 1215") &&
1203         !strstr((const char*)devIDBuff+2,"MDL:PHOTOSMART 1218") )
1204     {
1205         return TRUE;
1206     }
1207 
1208     // high-level process to check if driverware is available in PCL3 mode:
1209     //  1. set JobName through the normal PJL command to some string X
1210     //  2. poll DeviceID until see this JobName (syncs host with printer in case
1211     //     printer is still printing an earlier job etc.)
1212     //  3. go into PCL3 mode
1213     //  4. send driverware command to set JobName
1214     //  5. get the DeviceID and look at the JobName, if it is not "NEWDRIVERWARE" (what
1215     //     the firmware driverware command sets it to) conclude that driverware is
1216     //     not available in PCL3 mode; if  the JobName is "NEWDRIVERWARE" then conclude
1217     //     that driverware is available in PCL3 mode
1218     //  6. exit this "job" (send a UEL)
1219 
1220 
1221 
1222     // set the JobName via PJL
1223     if (Flush() != NO_ERROR) goto cleanup;
1224     if (Send((const BYTE*)UEL,sizeof(UEL)) != NO_ERROR) goto cleanup;
1225     inAJob = TRUE;
1226     if (Send((const BYTE*)JobName,sizeof(JobName)) != NO_ERROR) goto cleanup;
1227     if (Send((const BYTE*)&Quote,1) != NO_ERROR) goto cleanup;
1228     if (Send((const BYTE*)OUR_PJL_JOBNAME,strlen(OUR_PJL_JOBNAME)) != NO_ERROR) goto cleanup;
1229     if (Send((const BYTE*)&Quote,1) != NO_ERROR) goto cleanup;
1230     if (Send((const BYTE*)&LF,1) != NO_ERROR) goto cleanup;
1231     if (Flush() != NO_ERROR) goto cleanup;          // we flush our ::Send buffer
1232     if (pSS->FlushIO() != NO_ERROR) goto cleanup;   // we flush any external I/O buffer
1233 
1234     // wait for printer to see this and set JobName in the DeviceID
1235     // we know printer will respond, it is just a matter of time so wait
1236     // a while until see it since it may take a few seconds
1237     // for it to sync up with us if it is busy printing or picking
1238     //
1239     // this is a pretty long timeout but if the printer is finishing up
1240     // a preceding job we need to give it time to finish it since it won't
1241     // set the new jobname until the last job is complete
1242     // one possible enhancement would be to look at the flags in the DeviceID
1243     // to see if a job is active on more than one i/o connection
1244     maxWaitTries = 120;  // wait max of 60sec
1245     for (i=0; i<maxWaitTries; i++)
1246     {
1247         if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR)    goto cleanup;
1248         if ( (pStr=(char *)strstr((const char*)devIDBuff+2,";J:")) )
1249         {
1250             pStr += 3;
1251             if ( (pEnd=(char *)strstr((const char*)pStr,";")) )
1252             {
1253                 *pEnd = '\0';
1254                 while (pEnd > pStr) // take out trailing spaces in JobName before compare
1255                 {
1256                     if (*(pEnd-1) == ' ')
1257                     {
1258                         *(pEnd-1) = '\0';
1259                     }
1260                     else
1261                     {
1262                         break;
1263                     }
1264                     pEnd--;
1265                 }
1266                 if (!strcmp(pStr, OUR_PJL_JOBNAME))
1267                 {
1268                     break;
1269                 }
1270             }
1271             pSS->BusyWait((DWORD)500);
1272         }
1273         else
1274         {
1275             DBG1("JobName missing from DeviceID strings");
1276             goto cleanup;
1277         }
1278     }
1279     if (i>=maxWaitTries)
1280     {
1281         // printer didn't respond to driverware in PCL3GUI mode withing allowed timeout
1282         DBG1("Printer didn't respond to PJL\n");
1283         goto cleanup;
1284     }
1285 
1286     // now printer is in sync with us so try PCL3 mode and expect it to react to command
1287     // immediately or will assume that it ignores driverware in that mode
1288     if (Send((const BYTE*)EnterLanguage,sizeof(EnterLanguage)) != NO_ERROR) goto cleanup;
1289     if (Send((const BYTE*)PCL3,sizeof(PCL3)) != NO_ERROR) goto cleanup;
1290     if (Send((const BYTE*)&LF,1) != NO_ERROR) goto cleanup;
1291     if (Send((const BYTE*)DriverwareJobName,sizeof(DriverwareJobName)) != NO_ERROR) goto cleanup;
1292     if (Flush() != NO_ERROR) goto cleanup;          // we flush our ::Send buffer
1293     if (pSS->FlushIO() != NO_ERROR) goto cleanup;   // we flush any external I/O buffer
1294 
1295     // wait for printer to see this and set DeviceID to reflect this command
1296     // since we are sending in PCL3 mode we don't know if printer will respond
1297     // so don't wait very long
1298     maxWaitTries = 4;
1299     for (i=0; i<maxWaitTries; i++)
1300     {
1301         if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR)    goto cleanup;
1302         if ( (pStr=(char *)strstr((const char*)devIDBuff+2,";J:")) )
1303         {
1304             pStr += 3;
1305             if ( (pEnd=(char *)strstr((const char*)pStr,";")) )
1306             {
1307                 *pEnd = '\0';
1308                 // firmware may have garbage in remainder of JobName buffer - truncate
1309                 // it to the length of the string that should be set before compare
1310                 if (!strncmp(pStr, DRIVERWARE_JOBNAME, strlen(DRIVERWARE_JOBNAME)))
1311                 {
1312                     pcl3driverware = TRUE;
1313                     break;
1314                 }
1315             }
1316             pSS->BusyWait((DWORD)500);
1317         }
1318         else
1319         {
1320             DBG1("JobName missing from DeviceID string");
1321             goto cleanup;
1322         }
1323     }
1324     if (i>=maxWaitTries)
1325     {
1326         // since we haven't gotten a response assume that the printer ignores driverware
1327         // commands in PCL3 mode
1328         pcl3driverware = FALSE;
1329     }
1330 
1331 
1332 cleanup:
1333     if (inAJob)   // send UEL in case left printer in the context of a job
1334     {
1335         if (Send((const BYTE*)UEL,sizeof(UEL)) != NO_ERROR) goto bailout;
1336         if (pSS->FlushIO() != NO_ERROR) goto bailout;
1337     }
1338 
1339 bailout:
1340     return pcl3driverware;
1341 
1342 #endif  // APDK_LINUX
1343 
1344 } //IsPCL3DriverwareAvailable
1345 
1346 
ParseError(BYTE status_reg)1347 DISPLAY_STATUS DJ9xxVIP::ParseError(BYTE status_reg)
1348 {
1349     DBG1("DJ9xxVIP, parsing error info\n");
1350 
1351     DRIVER_ERROR err = NO_ERROR;
1352     BYTE DevIDBuffer[DevIDBuffSize];
1353     char *pStr;
1354     int     iVersion = pSS->GetVIPVersion ();
1355 
1356     if(IOMode.bDevID && iVersion < 6)
1357     {
1358         // If a bi-di cable was plugged in and everything was OK, let's see if it's still
1359         // plugged in and everything is OK
1360         err = pSS->GetDeviceID (DevIDBuffer, DevIDBuffSize, TRUE);
1361         if(err != NO_ERROR)
1362         {
1363             // job was bi-di but now something's messed up, probably cable unplugged
1364             return DISPLAY_COMM_PROBLEM;
1365         }
1366 
1367         if ( (pStr=(char *)strstr((const char*)DevIDBuffer+2,";S:")) == NULL )
1368         {
1369             return DISPLAY_COMM_PROBLEM;
1370         }
1371 
1372         // point to PrinterState
1373         BYTE b1,b2;
1374 
1375         pStr+=5;   // 3 for ";S:", 2 for version -- point to first byte of "printer state"
1376         b1=*pStr;
1377 
1378         if (b1=='9')
1379         {
1380             return DISPLAY_TOP_COVER_OPEN;
1381         }
1382 
1383         if (iVersion < 3)
1384         {
1385             pStr += 12;     // point to "feature state"
1386         }
1387         else if (iVersion < 5)
1388         {
1389             pStr += 14;
1390         }
1391         else
1392         {
1393             pStr += 18;
1394         }
1395 
1396         b1=*pStr++;
1397         b2=*pStr++;
1398         if ((b1=='0') && (b2=='9'))     // 09 = OOP state
1399         {
1400             DBG1("Out of Paper [from Encoded DevID]\n");
1401             return DISPLAY_OUT_OF_PAPER;
1402         }
1403 
1404         if (b1 == '0' && (b2 == 'c' || b2 == 'C'))      // 0C - PhotoTray Mismatch
1405         {
1406 
1407 /*
1408  *          PhotoTray is engaged, but requested paper size is larger than A6.
1409  *          It may also mean A6/Photo size is requested but photo tray is not engaged.
1410  */
1411 
1412             DBG1("Photo Tray Mismatch [from Encoded DevID]\n");
1413             return DISPLAY_PHOTOTRAY_MISMATCH;
1414         }
1415 
1416 //      Paper Jam or Paper Stall
1417 
1418         if ((b1 == '1' && b2 == '0') ||        // Paper Jam
1419             (b1 == '0' && (b2 == 'e' || b2 == 'E')))
1420         {
1421             return DISPLAY_PAPER_JAMMED;
1422         }
1423 
1424 //      Carriage Stall
1425 
1426         if (b1 == '0' && (b2 == 'F' || b2 == 'f'))
1427         {
1428             return DISPLAY_ERROR_TRAP;
1429         }
1430 
1431 //      Job Cancelled (AIO printer turn idle after job canceled)
1432         if ((b1=='0') && (b2=='5'))     // 05 = CNCL state
1433         {
1434             DBG1("Printing Canceled [from Encoded DevID]\n");
1435             return DISPLAY_PRINTING_CANCELED;
1436         }
1437 
1438         // VerifyPenInfo will handle prompting the user
1439         // if this is a problem
1440         err = VerifyPenInfo ();
1441 
1442         if(err != NO_ERROR)
1443         {
1444             // VerifyPenInfo returned an error, which can only happen when ToDevice
1445             // or GetDeviceID returns an error. Either way, it's BAD_DEVICE_ID or
1446             // IO_ERROR, both unrecoverable.  This is probably due to the printer
1447             // being turned off during printing, resulting in us not being able to
1448             // power it back on in VerifyPenInfo, since the buffer still has a
1449             // partial raster in it and we can't send the power-on command.
1450             return DISPLAY_COMM_PROBLEM;
1451         }
1452     }
1453 
1454     // check for errors we can detect from the status reg
1455     if (IOMode.bStatus)
1456     {
1457         // Although DJ8XX is OOP, printer continues taking data and BUSY bit gets
1458         // set.  See IO_defs.h
1459         if ( DEVICE_IS_OOP(status_reg) )
1460         {
1461             DBG1("Out Of Paper [from status byte]\n");
1462             return DISPLAY_OUT_OF_PAPER;
1463         }
1464 
1465         // DJ8XX doesn't go offline, so SELECT bit is set even when paper jammed.
1466         // See IO_defs.h
1467         if (DEVICE_PAPER_JAMMED(status_reg))
1468         {
1469             DBG1("Jammed [from status byte]\n");
1470             return DISPLAY_PAPER_JAMMED;
1471         }
1472 /*
1473  *      Do not process this. Malibu printers set the NFAULT bit low when a pen is
1474  *      missing, eventhough they support reserve mode printing. This causes us to
1475  *      report ERROR_TRAP message. Consequence is that we may not catch carriage
1476  *      stall, but should eventually result in time out.
1477         if (DEVICE_IO_TRAP(status_reg))
1478         {
1479             DBG1("Jammed or trapped [from status byte]\n");
1480             return DISPLAY_ERROR_TRAP;
1481         }
1482  */
1483     }
1484 
1485     // don't know what the problem is-
1486     //  Is the PrinterAlive?
1487     if (pSS->PrinterIsAlive())
1488     {
1489         iTotal_SLOW_POLL_Count += iMax_SLOW_POLL_Count;
1490 #if defined(DEBUG) && (DBG_MASK & DBG_LVL1)
1491         printf("iTotal_SLOW_POLL_Count = %d\n",iTotal_SLOW_POLL_Count);
1492 #endif
1493         // -Note that iTotal_SLOW_POLL_Count is a multiple of
1494         //  iMax_SLOW_POLL_Count allowing us to check this
1495         //  on an absolute time limit - not relative to the number
1496         //  of times we happen to have entered ParseError.
1497         // -Also note that we have different thresholds for uni-di & bi-di.
1498         if(
1499             ((IOMode.bDevID == FALSE) && (iTotal_SLOW_POLL_Count >= 60)) ||
1500             ((IOMode.bDevID == TRUE)  && (iTotal_SLOW_POLL_Count >= 120))
1501           )
1502         {
1503             return DISPLAY_BUSY;
1504         }
1505         else
1506         {
1507             return DISPLAY_PRINTING;
1508         }
1509     }
1510     else
1511     {
1512         return DISPLAY_COMM_PROBLEM;
1513     }
1514 } //ParseError
1515 
1516 
CleanPen()1517 DRIVER_ERROR DJ9xxVIP::CleanPen()
1518 {
1519     const BYTE DJ990_User_Output_Page[] = {ESC, '%','P','u','i','f','p','.',
1520         'm','u','l','t','i','_','b','u','t','t','o','n','_','p','u','s','h',' ','3',';',
1521         'u','d','w','.','q','u','i','t',';',ESC,'%','-','1','2','3','4','5','X' };
1522 
1523     DWORD length = sizeof(PEN_CLEAN_PML);
1524     DRIVER_ERROR err = pSS->ToDevice(PEN_CLEAN_PML, &length);
1525     ERRCHECK;
1526 
1527     // send this page so that the user sees some output.  If you don't send this, the
1528     // pens get serviced but nothing prints out.
1529     length = sizeof(DJ990_User_Output_Page);
1530     return pSS->ToDevice(DJ990_User_Output_Page, &length);
1531 } //CleanPen
1532 
1533 
1534 #if defined(APDK_VIP_COLORFILTERING)
1535 /// ERNIE ////////////////////////////////////////////////////////////////
Process(RASTERDATA * ImageData)1536 BOOL TErnieFilter::Process(RASTERDATA* ImageData)
1537 {
1538 	if (ImageData == NULL || (ImageData->rasterdata[COLORTYPE_COLOR] == NULL && ImageData->rasterdata[COLORTYPE_BLACK] == NULL))
1539 	{
1540 		return FALSE;
1541 	}
1542 	else
1543 	{
1544 		if (ImageData->rasterdata[COLORTYPE_COLOR])
1545 		{
1546 			submitRowToFilter(ImageData->rasterdata[COLORTYPE_COLOR]);
1547 
1548 			if (ImageData->rasterdata[COLORTYPE_BLACK])
1549 			{
1550 				memcpy(fBlackRowPtr[RowIndex], ImageData->rasterdata[COLORTYPE_BLACK], ImageData->rastersize[COLORTYPE_BLACK]);
1551 			}
1552 			BlackRasterSize[RowIndex++] = ImageData->rastersize[COLORTYPE_BLACK];
1553 
1554 			if (RowIndex == 4)
1555 				RowIndex = 0;
1556 
1557 			// something ready after 4th time only
1558 			return (fNumberOfBufferedRows == 0);
1559 		}
1560 		else
1561 		{
1562 			iRastersReady = 1;
1563 		}
1564 	}
1565 	return TRUE;
1566 } //Process
1567 
1568 
GetOutputWidth(COLORTYPE rastercolor)1569 unsigned int TErnieFilter::GetOutputWidth(COLORTYPE  rastercolor)
1570 {
1571 	if (rastercolor == COLORTYPE_COLOR)
1572 	{
1573 		if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1574 			return 0;
1575 		else
1576 			return fRowWidthInPixels * BYTES_PER_PIXEL;
1577 	}
1578 	else
1579 	{
1580 		if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1581 			return raster.rastersize[rastercolor];
1582 		else
1583 			return BlackRasterSize[iRastersDelivered-1];
1584 	}
1585 } //GetOutputWidth
1586 
1587 
NextOutputRaster(COLORTYPE rastercolor)1588 BYTE* TErnieFilter::NextOutputRaster(COLORTYPE  rastercolor)
1589 {
1590 	if (iRastersReady == 0)
1591 		return (BYTE*)NULL;
1592 	if (rastercolor == COLORTYPE_COLOR)
1593 	{
1594 		if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1595 		{
1596 			iRastersReady--;
1597 			return (BYTE*)NULL;
1598 		}
1599 		else
1600 		{
1601 			if (iRastersReady == 0)
1602 				return (BYTE*)NULL;
1603 
1604 			iRastersReady--;
1605 
1606 			return fRowPtr[iRastersDelivered++];
1607 		}
1608 	}
1609 	else
1610 	{
1611 		if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1612 		{
1613 			return raster.rasterdata[rastercolor];
1614 		}
1615 		else
1616 		{
1617 			if (BlackRasterSize[iRastersDelivered] == 0)
1618 				return NULL;
1619 			else
1620 				return fBlackRowPtr[iRastersDelivered];
1621 		}
1622 	}
1623 } //NextOutputRaster
1624 
1625 
Flush()1626 void TErnieFilter::Flush()
1627 {
1628     writeBufferedRows();
1629     iRastersDelivered=0;
1630     fPixelOffsetIndex = 0;
1631     iRastersReady = fNumberOfBufferedRows;
1632     fNumberOfBufferedRows = 0;
1633 } //Flush
1634 
1635 #endif //APDK_VIP_COLORFILTERING
1636 
get3Pixel(BYTE * pixAddress,int pixelOffset)1637 inline uint32_t Mode10::get3Pixel
1638 (
1639     BYTE* pixAddress,
1640     int pixelOffset
1641 )
1642 {
1643     pixAddress += ((pixelOffset << 1) + pixelOffset);     //pixAddress += pixelOffset * 3;
1644 
1645     BYTE r = *(pixAddress);
1646     BYTE g = *(pixAddress + 1);
1647     BYTE b = *(pixAddress + 2);
1648 
1649     return (kWhite & ((r << 16) | (g << 8) | (b)));
1650 
1651 //  unsigned int toReturn = *((unsigned int*)pixAddress); // load toReturn with XRGB
1652 //  toReturn &= kWhite; // Strip off unwanted X. EGW stripped lsb blue.
1653 } //get3Pixel
1654 
1655 
put3Pixel(BYTE * pixAddress,int pixelOffset,uint32_t pixel)1656 void Mode10::put3Pixel
1657 (
1658     BYTE* pixAddress,
1659     int pixelOffset,
1660     uint32_t pixel
1661 )
1662 {
1663     pixAddress += ((pixelOffset << 1) + pixelOffset);     //pixAddress += pixelOffset * 3;
1664 
1665     unsigned int temp = (pixel & kWhite);
1666 
1667     *(pixAddress) = ((temp >> 16) & 0x000000FF);
1668     *(pixAddress + 1) = ((temp >> 8) & 0x000000FF);
1669     *(pixAddress + 2) = (temp & 0x000000FF);
1670 
1671 } //put3Pixel
1672 
1673 
ShortDelta(uint32_t lastPixel,uint32_t lastUpperPixel)1674 unsigned short Mode10::ShortDelta
1675 (
1676     uint32_t lastPixel,
1677     uint32_t lastUpperPixel
1678 )
1679 {
1680     int dr,dg,db;
1681     int result;
1682 
1683     dr = GetRed(lastPixel) - GetRed(lastUpperPixel);
1684     dg = GetGreen(lastPixel) - GetGreen(lastUpperPixel);
1685     db = GetBlue(lastPixel) - GetBlue(lastUpperPixel);
1686 
1687     if ((dr <= 15) && (dr >= -16) && (dg <= 15) && (dg >= -16) && (db <= 30) && (db >= -32))
1688     {   // Note db is divided by 2 to double it's range from -16..15 to -32..30
1689         result = ((dr << 10) & 0x007C00) | (((dg << 5) & 0x0003E0) | ((db >> 1) & 0x01F) | 0x8000);   // set upper bit to signify short delta
1690     }
1691     else
1692     {
1693         result = 0;  // upper bit is zero to signify delta won't work
1694     }
1695 
1696     return result;
1697 }
1698 
Process(RASTERDATA * input)1699 BOOL Mode10::Process
1700 (
1701     RASTERDATA* input
1702 )
1703 /****************************************************************************
1704 Initially written by Elden Wood
1705 August 1998
1706 
1707 Similar to mode 9, though tailored for pixel data.
1708 For more information see the Bert Compression Format document.
1709 
1710 This function compresses a single row per call.
1711 ****************************************************************************/
1712 {
1713     if (input==NULL ||
1714 		(input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL))    // flushing pipeline
1715     {
1716         Flush();
1717         return FALSE;
1718     }
1719 
1720 	if (myplane == COLORTYPE_BLACK || input->rasterdata[COLORTYPE_COLOR]==NULL)
1721 	{
1722 		iRastersReady = 1;
1723 		compressedsize = 0;
1724 		if (seeded)
1725 		{
1726 			thePrinter->Send(ResetSeedrow, sizeof(ResetSeedrow));
1727             memset(SeedRow,0xFF,inputsize);
1728 			seeded = FALSE;
1729 		}
1730 		return TRUE;
1731 	}
1732     unsigned int originalsize = input->rastersize[myplane];
1733 	unsigned int size = input->rastersize[myplane];
1734 
1735     unsigned char *seedRowPtr = (unsigned char*)SeedRow;
1736 
1737     unsigned char *compressedDataPtr = compressBuf;
1738     unsigned char *curRowPtr =  (unsigned char*)input->rasterdata[myplane];
1739     unsigned int rowWidthInBytes = size;
1740 
1741     ASSERT(curRowPtr);
1742     ASSERT(seedRowPtr);
1743     ASSERT(compressedDataPtr);
1744     ASSERT(rowWidthInBytes >= BYTES_PER_PIXEL);
1745     ASSERT((rowWidthInBytes % BYTES_PER_PIXEL) == 0);
1746 
1747     unsigned char *compressedDataStart = compressedDataPtr;
1748     unsigned int lastPixel = (rowWidthInBytes / BYTES_PER_PIXEL) - 1;
1749 
1750     // Setup sentinal value to replace last pixel of curRow. Simplifies future end condition checking.
1751     uint32_t realLastPixel = getPixel(curRowPtr, lastPixel);
1752 
1753     uint32_t newLastPixel = realLastPixel;
1754     while ((getPixel(curRowPtr, lastPixel-1) == newLastPixel) ||
1755             (getPixel(seedRowPtr, lastPixel) == newLastPixel))
1756     {
1757         putPixel(curRowPtr, lastPixel, newLastPixel += 0x100); // add one to green.
1758     }
1759 
1760     unsigned int curPixel = 0;
1761     unsigned int seedRowPixelCopyCount;
1762     unsigned int cachedColor = kWhite;
1763 
1764     do // all pixels in row
1765     {
1766         unsigned char CMDByte = 0;
1767         int replacementCount;
1768 
1769         // Find seedRowPixelCopyCount for upcoming copy
1770         seedRowPixelCopyCount = curPixel;
1771         while (getPixel(seedRowPtr, curPixel) == getPixel(curRowPtr, curPixel))
1772         {
1773             curPixel++;
1774         }
1775 
1776         seedRowPixelCopyCount = curPixel - seedRowPixelCopyCount;
1777         ASSERT (curPixel <= lastPixel);
1778 
1779         int pixelSource = 0;
1780 
1781         if (curPixel == lastPixel) // On last pixel of row. RLE could also leave us on the last pixel of the row from the previous iteration.
1782         {
1783             putPixel(curRowPtr, lastPixel, realLastPixel);
1784 
1785             if (getPixel(seedRowPtr, curPixel) == realLastPixel)
1786             {
1787                 goto mode10rtn;
1788             }
1789             else // code last pix as a literal
1790             {
1791 
1792                 CMDByte = eLiteral;
1793                 pixelSource = eeNewPixel;
1794                 replacementCount = 1;
1795                 curPixel++;
1796             }
1797         }
1798         else // prior to last pixel of row
1799         {
1800             ASSERT(curPixel < lastPixel);
1801 
1802             replacementCount = curPixel;
1803             uint32_t RLERun = getPixel(curRowPtr, curPixel);
1804 
1805             curPixel++; // Adjust for next pixel.
1806             while (RLERun == getPixel(curRowPtr, curPixel)) // RLE
1807             {
1808                 curPixel++;
1809             }
1810             curPixel--; // snap back to current.
1811             replacementCount = curPixel - replacementCount;
1812             ASSERT(replacementCount >= 0);
1813 
1814             if (replacementCount > 0) // Adjust for total occurance and move to next pixel to do.
1815             {
1816                 curPixel++;
1817                 replacementCount++;
1818 
1819                 if (cachedColor == RLERun)
1820                 {
1821                     pixelSource = eeCachedColor;
1822                 }
1823                 else if (getPixel(seedRowPtr, curPixel-replacementCount+1) == RLERun)
1824                 {
1825                     pixelSource = eeNEPixel;
1826                 }
1827                 else if ((curPixel-replacementCount > 0) &&  (getPixel(curRowPtr, curPixel-replacementCount-1) == RLERun))
1828                 {
1829                     pixelSource = eeWPixel;
1830                 }
1831                 else
1832                 {
1833                     pixelSource = eeNewPixel;
1834                     cachedColor = RLERun;
1835                 }
1836 
1837                 CMDByte = eRLE; // Set default for later.
1838 
1839             }
1840 
1841             if (curPixel == lastPixel)
1842             {
1843                 ASSERT(replacementCount > 0); // Already found some RLE pixels
1844 
1845                 if (realLastPixel == RLERun) // Add to current RLE. Otherwise it'll be part of the literal from the seedrow section above on the next iteration.
1846                 {
1847                     putPixel(curRowPtr, lastPixel, realLastPixel);
1848                     replacementCount++;
1849                     curPixel++;
1850                 }
1851             }
1852 
1853             if (0 == replacementCount) // no RLE so it's a literal by default.
1854             {
1855                 uint32_t tempPixel = getPixel(curRowPtr, curPixel);
1856 
1857                 ASSERT(tempPixel != getPixel(curRowPtr, curPixel+1)); // not RLE
1858                 ASSERT(tempPixel != getPixel(seedRowPtr, curPixel)); // not seedrow copy
1859 
1860                 CMDByte = eLiteral;
1861 
1862                 if (cachedColor == tempPixel)
1863                 {
1864                     pixelSource = eeCachedColor;
1865 
1866                 }
1867                 else if (getPixel(seedRowPtr, curPixel+1) == tempPixel)
1868                 {
1869                     pixelSource = eeNEPixel;
1870 
1871                 }
1872                 else if ((curPixel > 0) &&  (getPixel(curRowPtr, curPixel-1) == tempPixel))
1873                 {
1874                     pixelSource = eeWPixel;
1875 
1876                 }
1877                 else
1878                 {
1879 
1880                     pixelSource = eeNewPixel;
1881                     cachedColor = tempPixel;
1882                 }
1883 
1884                 replacementCount = curPixel;
1885                 uint32_t cachePixel;
1886                 uint32_t nextPixel = getPixel(curRowPtr, curPixel+1);
1887                 do
1888                 {
1889                     if (++curPixel == lastPixel)
1890                     {
1891                         putPixel(curRowPtr, lastPixel, realLastPixel);
1892                         curPixel++;
1893                         break;
1894                     }
1895                     cachePixel = nextPixel;
1896                 }
1897                 while ((cachePixel != (nextPixel = getPixel(curRowPtr, curPixel+1))) &&
1898                         (cachePixel != getPixel(seedRowPtr, curPixel)));
1899 
1900                 replacementCount = curPixel - replacementCount;
1901 
1902                 ASSERT(replacementCount > 0);
1903             }
1904         }
1905 
1906         ASSERT(seedRowPixelCopyCount >= 0);
1907 
1908         // Write out compressed data next.
1909         if (eLiteral == CMDByte)
1910         {
1911             ASSERT(replacementCount >= 1);
1912 
1913             replacementCount -= 1; // normalize it
1914 
1915             CMDByte |= pixelSource; // Could put this directly into CMDByte above.
1916             CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
1917             CMDByte |= MIN(7, replacementCount);
1918 
1919             *compressedDataPtr++ = CMDByte;
1920 
1921             if (seedRowPixelCopyCount >= 3)
1922             {
1923                 outputVLIBytesConsecutively(seedRowPixelCopyCount - 3, compressedDataPtr);
1924             }
1925 
1926             replacementCount += 1; // denormalize it
1927 
1928             int totalReplacementCount = replacementCount;
1929             int upwardPixelCount = 1;
1930 
1931             if (eeNewPixel != pixelSource)
1932             {
1933                 replacementCount -= 1; // Do not encode 1st pixel of run since it comes from an alternate location.
1934                 upwardPixelCount = 2;
1935             }
1936 
1937             for ( ; upwardPixelCount <= totalReplacementCount; upwardPixelCount++)
1938             {
1939                 ASSERT(totalReplacementCount >= upwardPixelCount);
1940 
1941                 unsigned short compressedPixel = ShortDelta(    getPixel(curRowPtr, curPixel-replacementCount),
1942                                                                 getPixel(seedRowPtr, curPixel-replacementCount));
1943                 if (compressedPixel)
1944                 {
1945                     *compressedDataPtr++ = compressedPixel >> 8;
1946                     *compressedDataPtr++ = (unsigned char)compressedPixel;
1947 
1948                 }
1949                 else
1950                 {
1951                     uint32_t uncompressedPixel = getPixel(curRowPtr, curPixel-replacementCount);
1952 
1953                     uncompressedPixel >>= 1; // Lose the lsb of blue and zero out the msb of the 3 bytes.
1954 
1955                     *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 16);
1956                     *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 8);
1957                     *compressedDataPtr++ = (BYTE)(uncompressedPixel);
1958 
1959                 }
1960 
1961                 if (((upwardPixelCount-8) % 255) == 0)  // See if it's time to spill a single VLI byte.
1962                 {
1963                     *compressedDataPtr++ = MIN(255, totalReplacementCount - upwardPixelCount);
1964                 }
1965 
1966                 replacementCount--;
1967             }
1968         }
1969         else // RLE
1970         {
1971             ASSERT(eRLE == CMDByte);
1972             ASSERT(replacementCount >= 2);
1973 
1974             replacementCount -= 2; // normalize it
1975 
1976             CMDByte |= pixelSource; // Could put this directly into CMDByte above.
1977             CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
1978             CMDByte |= MIN(7, replacementCount);
1979 
1980             *compressedDataPtr++ = CMDByte;
1981 
1982             if (seedRowPixelCopyCount >= 3)
1983             {
1984                 outputVLIBytesConsecutively(seedRowPixelCopyCount - 3, compressedDataPtr);
1985             }
1986 
1987             replacementCount += 2; // denormalize it
1988 
1989             if (eeNewPixel == pixelSource)
1990             {
1991                 unsigned short compressedPixel = ShortDelta(getPixel(curRowPtr, curPixel - replacementCount),
1992                                                             getPixel(seedRowPtr, curPixel - replacementCount));
1993                 if (compressedPixel)
1994                 {
1995                     *compressedDataPtr++ = compressedPixel >> 8;
1996                     *compressedDataPtr++ = (unsigned char)compressedPixel;
1997                 }
1998                 else
1999                 {
2000                     uint32_t uncompressedPixel = getPixel(curRowPtr, curPixel - replacementCount);
2001 
2002                     uncompressedPixel >>= 1;
2003 
2004                     *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 16);
2005                     *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 8);
2006                     *compressedDataPtr++ = (BYTE)(uncompressedPixel);
2007                 }
2008             }
2009 
2010             if (replacementCount-2 >= 7) outputVLIBytesConsecutively(replacementCount - (7+2), compressedDataPtr);
2011         }
2012     } while (curPixel <= lastPixel);
2013 
2014 mode10rtn:
2015     size = compressedDataPtr - compressedDataStart; // return # of compressed bytes.
2016     compressedsize = size;
2017     memcpy(SeedRow, input->rasterdata[myplane], originalsize);
2018     seeded = TRUE;
2019     iRastersReady = 1;
2020     return TRUE;
2021 } //Process
2022 
NextOutputRaster(COLORTYPE color)2023 BYTE* Mode10::NextOutputRaster(COLORTYPE color)
2024 // since we return 1-for-1, just return result first call
2025 {
2026 	if (iRastersReady==0)
2027 		return (BYTE*)NULL;
2028 
2029 	if (color == COLORTYPE_BLACK)
2030 	{
2031 		return raster.rasterdata[color];
2032 	}
2033 	else
2034 	{
2035 		iRastersReady=0;
2036 		if (raster.rasterdata[color] != NULL)
2037 		{
2038 			return compressBuf;
2039 		}
2040 		else
2041 		{
2042 			return raster.rasterdata[color];
2043 		}
2044 	}
2045 }
2046 
PhotoTrayStatus(BOOL bQueryPrinter)2047 BYTE DJ9xxVIP::PhotoTrayStatus
2048 (
2049     BOOL bQueryPrinter
2050 )
2051 {
2052     DRIVER_ERROR err;
2053     char* pStr;
2054 
2055     BYTE bDevIDBuff[DevIDBuffSize];
2056 
2057     if (!IOMode.bDevID)
2058     {
2059         bQueryPrinter = FALSE;
2060     }
2061 
2062     err = pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, bQueryPrinter);
2063     if (err!=NO_ERROR)
2064     {
2065         return 0;
2066     }
2067 
2068     if ( (pStr=(char *)strstr((const char*)bDevIDBuff+2,";S:")) == NULL )
2069     {
2070         return 0;
2071     }
2072 
2073     // skip over ";S:<version=2bytes><topcover><inklid><duplexer>"
2074     pStr += 8;
2075     BYTE b = *pStr;
2076     return b;
2077 } //PhotoTrayStatus
2078 
2079 
PhotoTrayPresent(BOOL bQueryPrinter)2080 BOOL DJ9xxVIP::PhotoTrayPresent
2081 (
2082     BOOL bQueryPrinter
2083 )
2084 {
2085     // for phototray present == 8
2086     return ((PhotoTrayStatus(bQueryPrinter) & 8) == 8);
2087 } //PhotoTrayInstalled
2088 
2089 
PhotoTrayEngaged(BOOL bQueryPrinter)2090 PHOTOTRAY_STATE DJ9xxVIP::PhotoTrayEngaged
2091 (
2092     BOOL bQueryPrinter
2093 )
2094 {
2095 
2096 /*
2097  *  When you add any new printer models to this class, make sure that the printer
2098  *  has the phototray sensor and reports the phototray state correctly.
2099  */
2100     // for phototray present and engaged == 9
2101     return ((PHOTOTRAY_STATE) ((PhotoTrayStatus(bQueryPrinter) & 9) == 9));
2102 } //PhotoTrayEngaged
2103 
2104 
MandatoryPaperSize()2105 PAPER_SIZE DJ9xxVIP::MandatoryPaperSize()
2106 {
2107     if (PhotoTrayEngaged (TRUE))
2108         return PHOTO_SIZE;
2109     else return UNSUPPORTED_SIZE;   // code for "nothing mandatory"
2110 } //MandatoryPaperSize
2111 
2112 
CheckInkLevel()2113 DRIVER_ERROR DJ9xxVIP::CheckInkLevel()
2114 {
2115     DRIVER_ERROR    err;
2116     char            *pStr;
2117     int             i;
2118 
2119 //    BYTE bDevIDBuff[DevIDBuffSize];
2120 
2121     if (!IOMode.bDevID)
2122     {
2123         return NO_ERROR;
2124     }
2125 
2126 #if 0
2127 /*
2128  *  Check for unknown device id version.
2129  */
2130 
2131     if ((pSS->GetVIPVersion ()) > 5)
2132     {
2133         return NO_ERROR;
2134     }
2135 
2136     err = pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, TRUE);
2137     if (err!=NO_ERROR)
2138     {
2139         return err;
2140     }
2141 
2142     if ( (pStr=(char *)strstr((const char*)bDevIDBuff+2,";S:")) == NULL )
2143     {
2144         return NO_ERROR;
2145     }
2146 #endif
2147 
2148     // Skip to pen-count field
2149 
2150     err = SetPenInfo (pStr, FALSE);
2151     if (err != NO_ERROR)
2152     {
2153         return NO_ERROR;
2154     }
2155 
2156 	/*
2157 	 *  VIPVersion = DevID Version + 1 - DevID Version no is 2 bytes following ;S:
2158 	 *  Version 00 and 01 report 12 bytes for status info
2159 	 *  Version 02 and onwards, report two additional bytes before pen info
2160 	 */
2161 
2162     if (pSS->GetVIPVersion () == 1)
2163     {
2164 
2165 //      DJ990 style DeviceID
2166 
2167         // Next 3 should be 2C1
2168         // meaning 2 pens, first field is head/supply for K
2169 
2170 //        pStr += 19;
2171         BYTE b1,b2,b3;
2172         b1=*pStr++; b2=*pStr++; b3=*pStr++;
2173         if ( (b1 != '2') || (b2 != 'C') || (b3 != '1'))
2174         {
2175             return NO_ERROR;
2176         }
2177 
2178         // black pen
2179         pStr++;     // skip pen identifier
2180         BYTE blackink = *pStr - 48;     // convert from ascii
2181         // only look at low 3 bits
2182         blackink = blackink & 7;
2183 
2184         // skip into color field
2185         pStr += 8;
2186         BYTE colorink = *pStr - 48;
2187         // only look at low 3 bits
2188         colorink = colorink & 7;
2189 
2190         if ((blackink<5) && (colorink<5))
2191         {
2192             return NO_ERROR;
2193         }
2194 
2195         if ((blackink>4) && (colorink>4))
2196         {
2197             return WARN_LOW_INK_BOTH_PENS;
2198         }
2199         if (blackink>4)
2200         {
2201             return WARN_LOW_INK_BLACK;
2202         }
2203         else
2204         {
2205             return WARN_LOW_INK_COLOR;
2206         }
2207     }
2208 
2209 #if 0
2210     pStr += 21;
2211     if (pSS->GetVIPVersion () > 4)
2212     {
2213         pStr += 4;
2214     }
2215 #endif
2216 
2217     int     numPens = 0;
2218     if (*pStr > '0' && *pStr < '9')
2219     {
2220         numPens = *pStr - '0';
2221     }
2222     else if (*pStr > 'A' && *pStr < 'F')
2223     {
2224         numPens = *pStr - 'A';
2225     }
2226     else if (*pStr > 'a' && *pStr < 'f')
2227     {
2228         numPens = *pStr - 'a';
2229     }
2230 
2231     pStr++;
2232 
2233     err = NO_ERROR;
2234     if (pSS->GetVIPVersion () == 3)
2235     {
2236         for (i = 0; i < numPens; i++, pStr += 4)
2237         {
2238             switch (*pStr)
2239             {
2240                 case '5':
2241                 {
2242                     if ((*(pStr+1) & 0xf3) > 1)
2243                     {
2244                         if (err != NO_ERROR)
2245                         {
2246                             err = WARN_LOW_INK_MULTIPLE_PENS;
2247                         }
2248                         else
2249                         {
2250                             err = WARN_LOW_INK_BLACK;
2251                         }
2252                     }
2253                     break;
2254                 }
2255                 case '6':
2256                 {
2257                     if ((*(pStr+1) & 0xf3) > 1)
2258                     {
2259                         if (err != NO_ERROR)
2260                         {
2261                             err = WARN_LOW_INK_MULTIPLE_PENS;
2262                         }
2263                         else
2264                         {
2265                             err = WARN_LOW_INK_CYAN;
2266                         }
2267                     }
2268                     break;
2269                 }
2270                 case '7':
2271                 {
2272                     if ((*(pStr+1) & 0xf3) > 1)
2273                     {
2274                         if (err != NO_ERROR)
2275                         {
2276                             err = WARN_LOW_INK_MULTIPLE_PENS;
2277                         }
2278                         else
2279                         {
2280                             err = WARN_LOW_INK_MAGENTA;
2281                         }
2282                     }
2283 
2284                     break;
2285                 }
2286                 case '8':
2287                 {
2288                     if ((*(pStr+1) & 0xf3) > 1)
2289                     {
2290                         if (err != NO_ERROR)
2291                         {
2292                             err = WARN_LOW_INK_MULTIPLE_PENS;
2293                         }
2294                         else
2295                         {
2296                             err = WARN_LOW_INK_YELLOW;
2297                         }
2298                     }
2299                     break;
2300                 }
2301             }
2302         }
2303         return err;
2304     }
2305 
2306 	BYTE    penInfoBits[4];
2307     BYTE    blackink = 0;
2308     BYTE    colorink = 0;
2309     BYTE    photoink = 0;
2310     BYTE    greyink = 0;
2311 
2312     for (i = 0; i < numPens; i++, pStr += 8)
2313     {
2314         AsciiHexToBinary (penInfoBits, pStr, 8);
2315 
2316         if ((penInfoBits[0] & 0x40) != 0x40)        // if Bit 31 is 1, this is not a pen
2317         {
2318             continue;
2319         }
2320         int penColor = penInfoBits[0] & 0x3F;
2321         switch (penColor)
2322         {
2323             case 1:
2324                 blackink =  penInfoBits[1] & 0x7;
2325                 break;
2326             case 2:
2327                 colorink =  penInfoBits[1] & 0x7;
2328                 break;
2329             case 3:
2330                 photoink =  penInfoBits[1] & 0x7;
2331                 break;
2332             case 10:
2333                 greyink =  penInfoBits[1] & 0x7;
2334                 break;
2335             case 4:
2336             case 5:
2337             case 6:
2338             case 7:
2339             case 8:
2340             case 9:
2341                 colorink = penInfoBits[1] & 0x7;   // REVISIT: these are C, M, Y respectively
2342                 break;
2343             default:
2344                 break;
2345         }
2346     }
2347     if (blackink < 2 && colorink < 2 && photoink < 2 && greyink < 2)
2348     {
2349         return NO_ERROR;
2350     }
2351     else if (blackink > 1 && colorink > 1 && photoink > 1)
2352     {
2353         return WARN_LOW_INK_COLOR_BLACK_PHOTO;
2354     }
2355     else if (greyink > 1 && colorink > 1 && photoink > 1)
2356     {
2357         return WARN_LOW_INK_COLOR_GREY_PHOTO;
2358     }
2359     else if (blackink > 1 && colorink > 1)
2360     {
2361         return WARN_LOW_INK_BOTH_PENS;
2362     }
2363     else if (blackink > 1 && photoink > 1)
2364     {
2365         return WARN_LOW_INK_BLACK_PHOTO;
2366     }
2367     else if (greyink > 1 && colorink > 1)
2368     {
2369         return WARN_LOW_INK_COLOR_GREY;
2370     }
2371     else if (greyink > 1 && photoink > 1)
2372     {
2373         return WARN_LOW_INK_GREY_PHOTO;
2374     }
2375     else if (colorink > 1 && photoink > 1)
2376     {
2377         return WARN_LOW_INK_COLOR_PHOTO;
2378     }
2379     else if (blackink > 1)
2380     {
2381         return WARN_LOW_INK_BLACK;
2382     }
2383     else if (colorink > 1)
2384     {
2385         return WARN_LOW_INK_COLOR;
2386     }
2387     else if (photoink > 1)
2388     {
2389         return WARN_LOW_INK_PHOTO;
2390     }
2391     else if (greyink > 1)
2392     {
2393         return WARN_LOW_INK_GREY;
2394 	}
2395     else if (colorink > 1)
2396     {
2397         return WARN_LOW_INK_COLOR;
2398     }
2399 	else
2400 	{
2401 		return NO_ERROR;
2402 	}
2403 } //CheckInkLevel
2404 
2405 APDK_END_NAMESPACE
2406 
2407 #endif  //APDK_DJ9xxVIP
2408