1 /*****************************************************************************\
2 dj9xxvip.cpp : Implimentation for the DJ9xxVIP class
4 Copyright (c) 1996 - 2002, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of Hewlett-Packard nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
37 #include "printerproxy.h"
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!
45 extern uint32_t ulMapDJ600_CCM_K[ 9 * 9 * 9 ];
47 const char GrayscaleSeq[]= {ESC, '*', 'o', '5', 'W', 0x0B, 0x01, 0x00, 0x00, 0x02};
\r
49 const BYTE ExtraDryTime[] = "\033&b16WPML \004\000\006\001\004\001\004\001\006\010\001";
\r
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);
\r
60 Printer(pSS, NUM_DJ6XX_FONTS, proto),
61 PCL3acceptsDriverware(TRUE)
66 if (!proto && IOMode.bDevID)
68 bCheckForCancelButton = TRUE;
69 constructor_error = VerifyPenInfo();
72 else ePen = BOTH_PENS; // matches default mode
74 PCL3acceptsDriverware = IsPCL3DriverwareAvailable();
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
81 #ifdef APDK_AUTODUPLEX
84 * When bidi is available, query printer for duplexer
85 * For now, this is available only on Linux which is unidi only.
88 bDuplexCapable = TRUE;
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
96 pMode[ModeCount++] = new DJ990BestMode (); // Photo Best
97 pMode[ModeCount++] = new DJ990PhotoNormalMode (); // Photo Normal
99 m_cExtraDryTime = 0;
\r
100 m_iLeftOverspray = 0;
\r
101 m_iTopOverspray = 0;
\r
102 m_iRightOverspray = 0;
\r
103 m_iBottomOverspray = 0;
106 GrayModeDJ990::GrayModeDJ990
113 #if defined(APDK_VIP_COLORFILTERING)
114 Config.bErnie = TRUE;
117 Config.bColorImage=FALSE;
121 bFontCapable = FALSE;
124 #ifdef APDK_AUTODUPLEX
125 bDuplexCapable = TRUE;
127 #ifdef APDK_EXTENDED_MEDIASIZE
128 theQuality = qualityDraft;
129 pmQuality = QUALITY_DRAFT;
133 DJ990Mode::DJ990Mode()
138 * The resolutions here are set to 300 for better performance from Cameras.
139 * REVISIT: Must provide a true 600 dpi printmode later.
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.
147 BaseResX = BaseResY = TextRes = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
149 medium = mediaAuto; // enable media-detect
151 #if defined(APDK_VIP_COLORFILTERING)
152 Config.bErnie = TRUE;
155 Config.bColorImage = FALSE;
157 #ifdef APDK_AUTODUPLEX
158 bDuplexCapable = TRUE;
163 DJ990CMYGrayMode::DJ990CMYGrayMode()
168 * See comments above regarding 300/600 dpi change
171 BaseResX = BaseResY = TextRes = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
173 medium = mediaAuto; // enable media-detect
175 #if defined(APDK_VIP_COLORFILTERING)
176 Config.bErnie = TRUE;
179 Config.bColorImage = FALSE;
181 #ifdef APDK_AUTODUPLEX
182 bDuplexCapable = TRUE;
185 bFontCapable = FALSE;
188 #ifdef APDK_EXTENDED_MEDIASIZE
189 DJ990KGrayMode::DJ990KGrayMode () : PrintMode (NULL)
193 * See comments above regarding 300/600 dpi change.
196 BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
198 #if defined(APDK_VIP_COLORFILTERING)
199 Config.bErnie = TRUE;
202 Config.bColorImage = FALSE;
204 #ifdef APDK_AUTODUPLEX
205 bDuplexCapable = TRUE;
208 bFontCapable = FALSE;
212 DJ9902400Mode::DJ9902400Mode () : PrintMode (NULL)
216 ResolutionX[0] = 1200;
217 ResolutionY[0] = 1200;
218 bFontCapable = FALSE;
219 #ifdef APDK_AUTODUPLEX
220 bDuplexCapable = FALSE;
222 #if defined(APDK_VIP_COLORFILTERING)
223 Config.bErnie = TRUE;
226 Config.bColorImage = FALSE;
228 medium = mediaHighresPhoto;
229 theQuality = qualityPresentation;
230 pmMediaType = MEDIA_PHOTO;
231 pmQuality = QUALITY_HIGHRES_PHOTO;
234 DJ990DraftMode::DJ990DraftMode () : PrintMode (NULL)
236 bFontCapable = FALSE;
237 #ifdef APDK_AUTODUPLEX
238 bDuplexCapable = TRUE;
240 #if defined(APDK_VIP_COLORFILTERING)
241 Config.bErnie = TRUE;
244 Config.bColorImage = FALSE;
247 theQuality = qualityDraft;
248 pmQuality = QUALITY_DRAFT;
251 #endif // APDK_EXTENDED_MEDIASIZE
254 * Some VIP printers do not have Media Sensing device. To enable
255 * selection of Photo/Best mode for these printers, use this mode.
258 DJ990BestMode::DJ990BestMode () : PrintMode (NULL)
260 BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
262 bFontCapable = FALSE;
264 #ifdef APDK_AUTODUPLEX
265 bDuplexCapable = TRUE;
268 #if defined(APDK_VIP_COLORFILTERING)
269 Config.bErnie = TRUE;
272 Config.bColorImage = FALSE;
274 medium = mediaGlossy;
275 theQuality = qualityPresentation;
276 pmQuality = QUALITY_BEST;
277 pmMediaType = MEDIA_PHOTO;
280 DJ990PhotoNormalMode::DJ990PhotoNormalMode () : PrintMode (NULL)
282 BaseResX = BaseResY = ResolutionX[0] = ResolutionY[0] = VIP_BASE_RES;
284 bFontCapable = FALSE;
286 #ifdef APDK_AUTODUPLEX
287 bDuplexCapable = TRUE;
290 #if defined(APDK_VIP_COLORFILTERING)
291 Config.bErnie = TRUE;
294 Config.bColorImage = FALSE;
296 medium = mediaGlossy;
297 theQuality = qualityNormal;
298 pmQuality = QUALITY_NORMAL;
299 pmMediaType = MEDIA_PHOTO;
300 } // DJ990PhotoNormalMode
302 BOOL DJ9xxVIP::UseGUIMode
304 PrintMode* pPrintMode
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.
313 if (pPrintMode->medium == mediaHighresPhoto)
319 #ifdef APDK_AUTODUPLEX
320 if (pPrintMode->QueryDuplexMode() != DUPLEXMODE_NONE)
326 #if defined(APDK_FONTS_NEEDED)
327 // return ((!pPrintMode->bFontCapable) && (!PCL3acceptsDriverware));
328 return (!pPrintMode->bFontCapable);
335 DRIVER_ERROR DJ9xxVIP::AddPJLHeader ()
\r
337 char *szPJLBuffer = NULL;
\r
338 DRIVER_ERROR err = NO_ERROR;
\r
339 int iPJLBufferSize;
\r
340 if (((iPJLBufferSize = pSS->GetPJLHeaderBuffer (&szPJLBuffer)) > 0) && (szPJLBuffer != NULL))
\r
342 err = Send ((const BYTE *) szPJLBuffer, iPJLBufferSize);
\r
349 SystemServices* pSys,
351 unsigned int PlaneSize
353 Compressor(pSys, PlaneSize, TRUE),
354 thePrinter(pPrinter) // needed by Flush
356 if (constructor_error != NO_ERROR) // if error in base constructor
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;
366 memset(SeedRow,0xFF,PlaneSize);
374 const BYTE ResetSeedrow[]={ESC,'*','b','0','Y'};
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.
390 memset(SeedRow,0xFF,inputsize);
391 thePrinter->Send(ResetSeedrow, sizeof(ResetSeedrow));
395 Compressor* DJ9xxVIP::CreateCompressor(unsigned int RasterSize)
397 return new Mode10(pSS,this,RasterSize);
401 Header* DJ9xxVIP::SelectHeader(PrintContext* pc)
403 return new HeaderDJ990(this,pc);
407 HeaderDJ990::HeaderDJ990(Printer* p,PrintContext* pc)
410 SetMediaSource (pc->GetMediaSource());
414 DRIVER_ERROR HeaderDJ990::ConfigureRasterData()
415 // This is the more sophisticated way of setting color and resolution info.
417 // NOTE: Will need to be overridden for DJ5xx.
420 char buff[50]; // 20 + 3 for crdstart + 3 for ##W
424 // begin the CRD command
425 memcpy(out,crdStart,sizeof(crdStart) );
426 out += sizeof(crdStart);
428 // now set up the "#W" part, where #= number of data bytes in the command
430 // format,ID,components(2bytes),resolutions (4bytes),
431 // compresssion method, orientation, bits/component,planes/component
432 *out++ = 0x32; // "2"
433 *out++ = 0x30; // "0"
436 #define VIPcrdFormat 6
437 #define VIPKRGBID 0x1F
439 *out++ = VIPcrdFormat;
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"
447 *out++ = ResolutionX[0]/256;
448 *out++ = ResolutionX[0]%256;
449 *out++ = ResolutionY[0]/256;
450 *out++ = ResolutionY[0]%256;
452 // compression method
453 *out++ = 9; // mode 9 compression
456 *out++ = 0; // pixel major code
458 // bits per component
459 *out++ = 1; // 1 bits each for k
461 // planes per component
462 *out++ = 1; // K = one component, one "plane"
464 *out++ = ResolutionX[0]/256;
465 *out++ = ResolutionX[0]%256;
466 *out++ = ResolutionY[0]/256;
467 *out++ = ResolutionY[0]%256;
469 // compression method
470 *out++ = 10; // mode 10 compression
473 *out++ = 1; // pixel major code
475 // bits per component
476 *out++ = 32; // 8 bits each for s,R,G,B
478 // planes per component
479 *out++ = 1; // sRGB = one component, one "plane"
481 return thePrinter->Send((const BYTE*) buff, out-buff);
482 } //ConfigureRasterData
485 DRIVER_ERROR HeaderDJ990::ConfigureImageData()
487 DRIVER_ERROR err = thePrinter->Send((const BYTE*)cidStart, sizeof(cidStart));
490 sprintf(sizer,"%dW",6);
491 err = thePrinter->Send((const BYTE*)sizer,2);
494 BYTE colorspace = 2; // RGB
496 BYTE bitsindex = 3; // ??
497 BYTE bitsprimary = 8;
502 CID[3] = CID[4] = CID[5] = bitsprimary;
504 return thePrinter->Send((const BYTE*) CID, 6);
505 } //ConfigureImageData
508 DRIVER_ERROR HeaderDJ990::Send()
509 /// ASSUMES COMPRESSION ALWAYS ON -- required by DJ990
512 // PRINTMODE_VALUES *pPMV;
513 COLORMODE eColorMode = COLOR;
514 MEDIATYPE eMediaType;
515 QUALITY_MODE eQualityMode;
518 thePrintContext->GetPrintModeSettings (eQualityMode, eMediaType, eColorMode, bDeviceText);
\r
520 if (eMediaType == MEDIA_CDDVD)
522 thePrintContext->SetMediaSource (sourceTrayCDDVD);
523 SetMediaSource (sourceTrayCDDVD);
528 #ifdef APDK_AUTODUPLEX
529 if (thePrintContext->QueryDuplexMode () != DUPLEXMODE_NONE)
531 err = thePrinter->Send ((const BYTE *) EnableDuplex, sizeof (EnableDuplex));
\r
533 cDryTime = (BYTE) ((thePrinter->GetHint (EXTRA_DRYTIME_HINT)) & 0xFF);
\r
536 err = thePrinter->Send (ExtraDryTime, sizeof (ExtraDryTime) - 1);
\r
537 err = thePrinter->Send ((const BYTE *) &cDryTime, 1);
\r
543 err = ConfigureImageData();
546 err = ConfigureRasterData();
549 if (thePrintMode->dyeCount == 1) // grayscale
551 err=thePrinter->Send((const BYTE*)GrayscaleSeq, sizeof(GrayscaleSeq) );
556 if (eColorMode == GREY_CMY)
559 memcpy (pStr, GrayscaleSeq, 10);
561 err = thePrinter->Send ((const BYTE *) pStr, 10);
565 /////////////////////////////////////////////////////////////////////////////////////
566 // unit-of-measure command --- seems to be need in DJ990 PCL3 mode
568 sprintf(uom,"%c%c%c%d%c",ESC,'&','u',thePrintMode->ResolutionX[K],'D');
569 err = thePrinter->Send((const BYTE*)uom, strlen (uom));
572 // another command that helps PCLviewer
573 unsigned int width=thePrintContext->OutputPixelsPerRow();
574 unsigned int digits = 1;
575 unsigned int x = width;
581 sprintf(uom,"%c%c%c%d%c",ESC,'*','r', width,'S');
582 err = thePrinter->Send((const BYTE*)uom, 4 + digits );
585 ////////////////////////////////////////////////////////////////////////////////////
588 * Custom papersize command
591 if (thePrintContext->thePaperSize == CUSTOM_SIZE)
594 short sWidth, sHeight;
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);
603 b1 = (BYTE) ((sHeight & 0xFF00) >> 8);
604 b2 = (BYTE) (sHeight & 0xFF);
607 err = thePrinter->Send ((const BYTE *) szStr, 20);
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,
618 &fXOverSpray, &fYOverSpray,
619 &fLeftOverSpray, &fTopOverSpray))
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.
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
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
638 short topspray = (short)(fTopOverSpray * thePrintContext->EffectiveResolutionY() + 0.5);
639 cBuf[1] = topspray & 0xFF;
640 cBuf[0] = topspray >> 8;
642 err = thePrinter->Send ((const BYTE *) TopOverSpraySeq, sizeof (TopOverSpraySeq));
643 err = thePrinter->Send ((const BYTE *) cBuf, 2);
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;
650 err = thePrinter->Send ((const BYTE *) LeftOverSpraySeq, sizeof (LeftOverSpraySeq));
651 err = thePrinter->Send ((const BYTE *) cBuf, 2);
654 // Now send media pre-load command
655 err = thePrinter->Send ((const BYTE *) "\033&l-2H", 6); // Moved from Modes(), des 3/11/03
658 // Send speed mech command
\r
659 thePrinter->SetHint (SPEED_MECH_HINT, 0);
\r
661 // no need for compression command, it's in the CRD
663 err = thePrinter->Send((const BYTE*)grafStart, sizeof(grafStart) );
666 if (!thePrinter->UseGUIMode (thePrintContext->CurrentMode) &&
667 (thePrintContext->PhysicalPageSizeX ()) < 8.0)
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);
682 DRIVER_ERROR HeaderDJ990::StartSend()
686 err = thePrinter->Send((const BYTE*)Reset,sizeof(Reset));
689 err = thePrinter->Send((const BYTE*)UEL,sizeof(UEL));
692 err = thePrinter->AddPJLHeader ();
\r
695 err = thePrinter->Send((const BYTE*)EnterLanguage,sizeof(EnterLanguage));
698 if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
700 err = thePrinter->Send((const BYTE*)PCL3,sizeof(PCL3));
704 err = thePrinter->Send((const BYTE*)PCLGUI,sizeof(PCLGUI));
709 err = thePrinter->Send((const BYTE*)&LF,1);
712 err = Modes (); // Set media source, type, size and quality modes.
715 // Send media subtype if set
\r
716 int iMediaSubtype = thePrintContext->GetMediaSubtype ();
\r
717 if (iMediaSubtype != APDK_INVALID_VALUE)
\r
719 BYTE szMediaSubtypeSeq[] = {0x1B, '*', 'o', '5', 'W', 0x0D, 0x03, 0x00, 0x00, 0x00};
\r
720 szMediaSubtypeSeq[8] = (BYTE) ((iMediaSubtype & 0xFF00) >> 8);
\r
721 szMediaSubtypeSeq[9] = (BYTE) (iMediaSubtype & 0x00FF);
\r
722 err = thePrinter->Send ((const BYTE *) szMediaSubtypeSeq, sizeof(szMediaSubtypeSeq));
\r
726 if (!thePrinter->UseGUIMode(thePrintContext->CurrentMode))
728 err = Margins(); // set margins
731 // special GUI mode top margin set
733 else if ((thePrintContext->PrintableStartY ()) > 0.0)
735 CAPy = thePrintContext->GUITopMargin();
738 if ((thePrintContext->GetMediaSource()) == sourceTrayCDDVD)
740 err = thePrinter->Send ((const BYTE *) "\033*o5W\x0D\x03\x00\x04\x0C", 10);
747 /* This could replace Header::SetMediaSource in header.cpp. des 8/5/02 */
748 void HeaderDJ990::SetMediaSource(MediaSource msource)
749 // Sets value of PCL::mediasource and associated counter msrccount
751 msrccount=EscAmplCopy((BYTE*)mediasource,msource,'H');
752 if (msource == sourceTrayCDDVD)
754 SetMediaType (mediaCDDVD);
755 SetQuality (qualityPresentation);
758 if (msource == sourceTray2 || msource > sourceTrayAuto)
760 SetMediaType (mediaPlain);
764 DRIVER_ERROR DJ9xxVIP::VerifyPenInfo()
766 DRIVER_ERROR err=NO_ERROR;
768 if(IOMode.bDevID == FALSE)
770 err = ParsePenInfo(ePen);
772 if(err == UNSUPPORTED_PEN) // probably Power Off - pens couldn't be read
774 DBG1("DJ9xxVIP::Need to do a POWER ON to get penIDs\n");
776 // have to delay or the POWER ON will be ignored
777 if (pSS->BusyWait((DWORD)2000) == JOB_CANCELED)
782 DWORD length = sizeof(DJ895_Power_On);
783 err = pSS->ToDevice(DJ895_Power_On,&length);
786 err = pSS->FlushIO();
789 // give the printer some time to power up
790 if (pSS->BusyWait ((DWORD) 2500) == JOB_CANCELED)
795 err = ParsePenInfo(ePen);
800 // check for the normal case
801 if (ePen == BOTH_PENS || ePen == MDL_BLACK_AND_COLOR_PENS)
806 // Should we return NO_ERROR for MDL_BOTH also - malibu??
808 while ( ePen != BOTH_PENS && pSS->GetVIPVersion () == 1 )
814 // black pen installed, need to install color pen
815 pSS->DisplayPrinterStatus(DISPLAY_NO_COLOR_PEN);
818 // color pen installed, need to install black pen
819 pSS->DisplayPrinterStatus(DISPLAY_NO_BLACK_PEN);
822 // neither pen installed
824 pSS->DisplayPrinterStatus(DISPLAY_NO_PENS);
828 if (pSS->BusyWait(500) == JOB_CANCELED)
833 err = ParsePenInfo(ePen);
837 pSS->DisplayPrinterStatus(DISPLAY_PRINTING);
843 DRIVER_ERROR DJ9xxVIP::ParsePenInfo(PEN_TYPE& ePen, BOOL QueryPrinter)
847 PEN_TYPE temp_pen1 = NO_PEN;
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.
857 if ((pSS->GetVIPVersion ()) > 5)
863 DRIVER_ERROR err = SetPenInfo (str, QueryPrinter);
872 // the first byte indicates how many pens are supported
873 if ((str[0] >= '0') && (str[0] <= '9'))
875 num_pens = str[0] - '0';
877 else if ((str[0] >= 'A') && (str[0] <= 'F'))
879 num_pens = 10 + (str[0] - 'A');
881 else if ((str[0] >= 'a') && (str[0] <= 'f'))
883 num_pens = 10 + (str[0] - 'a');
887 return BAD_DEVICE_ID;
890 if ((int) strlen (str) < (num_pens * 8))
892 return BAD_DEVICE_ID;
897 if (pSS->GetVIPVersion () == 1)
901 return UNSUPPORTED_PEN;
904 // parse pen1 (should be black)
905 AsciiHexToBinary(penInfoBits, str+1, 4);
906 penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
908 if ((penInfoBits[0] == 0xc1) && (penInfoBits[1] == 0x10))
910 temp_pen1 = BLACK_PEN;
912 else if (penInfoBits[0] == 0xc0)
919 return UNSUPPORTED_PEN;
922 // now check pen2 (should be color)
923 AsciiHexToBinary(penInfoBits, str+9, 4);
924 penInfoBits[1] &= 0xf8; // mask off ink level trigger bits
926 if ((penInfoBits[0] == 0xc2) && (penInfoBits[1] == 0x08))
928 if (temp_pen1 == BLACK_PEN)
937 else if (penInfoBits[0] == 0xc0)
944 return UNSUPPORTED_PEN;
950 // Check for missing pens
952 if (*(str - 1) == '1' && *(str - 2) == '1')
954 return UNSUPPORTED_PEN;
964 1 if these fields describe a print head
968 1 if these fields describe an ink supply
971 Bits 29 .. 24 (6 bits) describes the pen/supply type:
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]
985 12 .. 62 = reserved for future use
988 Bits 23 .. 19 (5 bits) describes the pen/supply id:
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)
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]
1011 if (pSS->GetVIPVersion () == 3)
1013 for (i = 0; i < num_pens; i++, p += 4)
1015 if (*p > 0 && *p < '5')
1035 if (ePen == BLACK_PEN)
1039 else if (ePen != BOTH_PENS)
1048 if (iNumMissingPens != 0)
1050 return MISSING_PENS;
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.
1066 for (i = 0; i < num_pens; i++, p += 8)
1068 AsciiHexToBinary (penInfoBits, p, 8);
1070 if ((penInfoBits[1] & 0xf8) == 0xf8)
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.
1076 return UNSUPPORTED_PEN;
1079 if ((penInfoBits[0] & 0x40) != 0x40) // if Bit 31 is 1, this is not a pen
1083 penColor = penInfoBits[0] & 0x3F;
1096 if (ePen == BLACK_PEN)
1100 else if (ePen == MDL_PEN)
1104 else if (ePen == GREY_PEN)
1115 if (ePen == BLACK_PEN)
1117 ePen = MDL_AND_BLACK_PENS;
1119 else if (ePen == COLOR_PEN)
1123 else if (ePen == BOTH_PENS)
1125 ePen = MDL_BLACK_AND_COLOR_PENS;
1127 else if (ePen == GREY_PEN)
1129 ePen = MDL_AND_GREY_PENS;
1131 else if (ePen == GREY_BOTH)
1133 ePen = MDL_GREY_AND_COLOR_PENS;
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)
1172 BOOL DJ9xxVIP::IsPCL3DriverwareAvailable()
1175 // Linux supports Bi-Di, but is not enabled at this time. See comments below.
1179 BOOL pcl3driverware = TRUE; // default to TRUE since this is the case for all but some early units
1180 BOOL inAJob = FALSE;
1183 BYTE devIDBuff[DevIDBuffSize];
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
1194 if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR)
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") )
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)
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;
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
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
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++)
1247 if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR) goto cleanup;
1248 if ( (pStr=(char *)strstr((const char*)devIDBuff+2,";J:")) )
1251 if ( (pEnd=(char *)strstr((const char*)pStr,";")) )
1254 while (pEnd > pStr) // take out trailing spaces in JobName before compare
1256 if (*(pEnd-1) == ' ')
1266 if (!strcmp(pStr, OUR_PJL_JOBNAME))
1271 pSS->BusyWait((DWORD)500);
1275 DBG1("JobName missing from DeviceID strings");
1279 if (i>=maxWaitTries)
1281 // printer didn't respond to driverware in PCL3GUI mode withing allowed timeout
1282 DBG1("Printer didn't respond to PJL\n");
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
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
1299 for (i=0; i<maxWaitTries; i++)
1301 if (pSS->GetDeviceID(devIDBuff, DevIDBuffSize, TRUE) != NO_ERROR) goto cleanup;
1302 if ( (pStr=(char *)strstr((const char*)devIDBuff+2,";J:")) )
1305 if ( (pEnd=(char *)strstr((const char*)pStr,";")) )
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)))
1312 pcl3driverware = TRUE;
1316 pSS->BusyWait((DWORD)500);
1320 DBG1("JobName missing from DeviceID string");
1324 if (i>=maxWaitTries)
1326 // since we haven't gotten a response assume that the printer ignores driverware
1327 // commands in PCL3 mode
1328 pcl3driverware = FALSE;
1333 if (inAJob) // send UEL in case left printer in the context of a job
1335 if (Send((const BYTE*)UEL,sizeof(UEL)) != NO_ERROR) goto bailout;
1336 if (pSS->FlushIO() != NO_ERROR) goto bailout;
1340 return pcl3driverware;
1342 #endif // APDK_LINUX
1344 } //IsPCL3DriverwareAvailable
1347 DISPLAY_STATUS DJ9xxVIP::ParseError(BYTE status_reg)
1349 DBG1("DJ9xxVIP, parsing error info\n");
1351 DRIVER_ERROR err = NO_ERROR;
1352 BYTE DevIDBuffer[DevIDBuffSize];
1354 int iVersion = pSS->GetVIPVersion ();
1356 if(IOMode.bDevID && iVersion < 6)
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);
1363 // job was bi-di but now something's messed up, probably cable unplugged
1364 return DISPLAY_COMM_PROBLEM;
1367 if ( (pStr=(char *)strstr((const char*)DevIDBuffer+2,";S:")) == NULL )
1369 return DISPLAY_COMM_PROBLEM;
1372 // point to PrinterState
1375 pStr+=5; // 3 for ";S:", 2 for version -- point to first byte of "printer state"
1380 return DISPLAY_TOP_COVER_OPEN;
1385 pStr += 12; // point to "feature state"
1387 else if (iVersion < 5)
1398 if ((b1=='0') && (b2=='9')) // 09 = OOP state
1400 DBG1("Out of Paper [from Encoded DevID]\n");
1401 return DISPLAY_OUT_OF_PAPER;
1404 if (b1 == '0' && (b2 == 'c' || b2 == 'C')) // 0C - PhotoTray Mismatch
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.
1412 DBG1("Photo Tray Mismatch [from Encoded DevID]\n");
1413 return DISPLAY_PHOTOTRAY_MISMATCH;
1416 // Paper Jam or Paper Stall
1418 if ((b1 == '1' && b2 == '0') || // Paper Jam
1419 (b1 == '0' && (b2 == 'e' || b2 == 'E')))
1421 return DISPLAY_PAPER_JAMMED;
1426 if (b1 == '0' && (b2 == 'F' || b2 == 'f'))
1428 return DISPLAY_ERROR_TRAP;
1431 // Job Cancelled (AIO printer turn idle after job canceled)
1432 if ((b1=='0') && (b2=='5')) // 05 = CNCL state
1434 DBG1("Printing Canceled [from Encoded DevID]\n");
1435 return DISPLAY_PRINTING_CANCELED;
1438 // VerifyPenInfo will handle prompting the user
1439 // if this is a problem
1440 err = VerifyPenInfo ();
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;
1454 // check for errors we can detect from the status reg
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) )
1461 DBG1("Out Of Paper [from status byte]\n");
1462 return DISPLAY_OUT_OF_PAPER;
1465 // DJ8XX doesn't go offline, so SELECT bit is set even when paper jammed.
1467 if (DEVICE_PAPER_JAMMED(status_reg))
1469 DBG1("Jammed [from status byte]\n");
1470 return DISPLAY_PAPER_JAMMED;
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))
1479 DBG1("Jammed or trapped [from status byte]\n");
1480 return DISPLAY_ERROR_TRAP;
1485 // don't know what the problem is-
1486 // Is the PrinterAlive?
1487 if (pSS->PrinterIsAlive())
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);
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.
1499 ((IOMode.bDevID == FALSE) && (iTotal_SLOW_POLL_Count >= 60)) ||
1500 ((IOMode.bDevID == TRUE) && (iTotal_SLOW_POLL_Count >= 120))
1503 return DISPLAY_BUSY;
1507 return DISPLAY_PRINTING;
1512 return DISPLAY_COMM_PROBLEM;
1517 DRIVER_ERROR DJ9xxVIP::CleanPen()
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' };
1523 DWORD length = sizeof(PEN_CLEAN_PML);
1524 DRIVER_ERROR err = pSS->ToDevice(PEN_CLEAN_PML, &length);
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);
1534 #if defined(APDK_VIP_COLORFILTERING)
1535 /// ERNIE ////////////////////////////////////////////////////////////////
1536 BOOL TErnieFilter::Process(RASTERDATA* ImageData)
1538 if (ImageData == NULL || (ImageData->rasterdata[COLORTYPE_COLOR] == NULL && ImageData->rasterdata[COLORTYPE_BLACK] == NULL))
1544 if (ImageData->rasterdata[COLORTYPE_COLOR])
1546 submitRowToFilter(ImageData->rasterdata[COLORTYPE_COLOR]);
1548 if (ImageData->rasterdata[COLORTYPE_BLACK])
1550 memcpy(fBlackRowPtr[RowIndex], ImageData->rasterdata[COLORTYPE_BLACK], ImageData->rastersize[COLORTYPE_BLACK]);
1552 BlackRasterSize[RowIndex++] = ImageData->rastersize[COLORTYPE_BLACK];
1557 // something ready after 4th time only
1558 return (fNumberOfBufferedRows == 0);
1569 unsigned int TErnieFilter::GetOutputWidth(COLORTYPE rastercolor)
1571 if (rastercolor == COLORTYPE_COLOR)
1573 if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1576 return fRowWidthInPixels * BYTES_PER_PIXEL;
1580 if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1581 return raster.rastersize[rastercolor];
1583 return BlackRasterSize[iRastersDelivered-1];
1588 BYTE* TErnieFilter::NextOutputRaster(COLORTYPE rastercolor)
1590 if (iRastersReady == 0)
1592 if (rastercolor == COLORTYPE_COLOR)
1594 if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1601 if (iRastersReady == 0)
1606 return fRowPtr[iRastersDelivered++];
1611 if (raster.rasterdata[COLORTYPE_COLOR] == NULL)
1613 return raster.rasterdata[rastercolor];
1617 if (BlackRasterSize[iRastersDelivered] == 0)
1620 return fBlackRowPtr[iRastersDelivered];
1623 } //NextOutputRaster
1626 void TErnieFilter::Flush()
1628 writeBufferedRows();
1629 iRastersDelivered=0;
1630 fPixelOffsetIndex = 0;
1631 iRastersReady = fNumberOfBufferedRows;
1632 fNumberOfBufferedRows = 0;
1635 #endif //APDK_VIP_COLORFILTERING
1637 inline uint32_t Mode10::get3Pixel
1643 pixAddress += ((pixelOffset << 1) + pixelOffset); //pixAddress += pixelOffset * 3;
1645 BYTE r = *(pixAddress);
1646 BYTE g = *(pixAddress + 1);
1647 BYTE b = *(pixAddress + 2);
1649 return (kWhite & ((r << 16) | (g << 8) | (b)));
1651 // unsigned int toReturn = *((unsigned int*)pixAddress); // load toReturn with XRGB
1652 // toReturn &= kWhite; // Strip off unwanted X. EGW stripped lsb blue.
1656 void Mode10::put3Pixel
1663 pixAddress += ((pixelOffset << 1) + pixelOffset); //pixAddress += pixelOffset * 3;
1665 unsigned int temp = (pixel & kWhite);
1667 *(pixAddress) = ((temp >> 16) & 0x000000FF);
1668 *(pixAddress + 1) = ((temp >> 8) & 0x000000FF);
1669 *(pixAddress + 2) = (temp & 0x000000FF);
1674 unsigned short Mode10::ShortDelta
1677 uint32_t lastUpperPixel
1683 dr = GetRed(lastPixel) - GetRed(lastUpperPixel);
1684 dg = GetGreen(lastPixel) - GetGreen(lastUpperPixel);
1685 db = GetBlue(lastPixel) - GetBlue(lastUpperPixel);
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
1693 result = 0; // upper bit is zero to signify delta won't work
1699 BOOL Mode10::Process
1703 /****************************************************************************
1704 Initially written by Elden Wood
1707 Similar to mode 9, though tailored for pixel data.
1708 For more information see the Bert Compression Format document.
1710 This function compresses a single row per call.
1711 ****************************************************************************/
1714 (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL)) // flushing pipeline
1720 if (myplane == COLORTYPE_BLACK || input->rasterdata[COLORTYPE_COLOR]==NULL)
1726 thePrinter->Send(ResetSeedrow, sizeof(ResetSeedrow));
1727 memset(SeedRow,0xFF,inputsize);
1732 unsigned int originalsize = input->rastersize[myplane];
1733 unsigned int size = input->rastersize[myplane];
1735 unsigned char *seedRowPtr = (unsigned char*)SeedRow;
1737 unsigned char *compressedDataPtr = compressBuf;
1738 unsigned char *curRowPtr = (unsigned char*)input->rasterdata[myplane];
1739 unsigned int rowWidthInBytes = size;
1743 ASSERT(compressedDataPtr);
1744 ASSERT(rowWidthInBytes >= BYTES_PER_PIXEL);
1745 ASSERT((rowWidthInBytes % BYTES_PER_PIXEL) == 0);
1747 unsigned char *compressedDataStart = compressedDataPtr;
1748 unsigned int lastPixel = (rowWidthInBytes / BYTES_PER_PIXEL) - 1;
1750 // Setup sentinal value to replace last pixel of curRow. Simplifies future end condition checking.
1751 uint32_t realLastPixel = getPixel(curRowPtr, lastPixel);
1753 uint32_t newLastPixel = realLastPixel;
1754 while ((getPixel(curRowPtr, lastPixel-1) == newLastPixel) ||
1755 (getPixel(seedRowPtr, lastPixel) == newLastPixel))
1757 putPixel(curRowPtr, lastPixel, newLastPixel += 0x100); // add one to green.
1760 unsigned int curPixel = 0;
1761 unsigned int seedRowPixelCopyCount;
1762 unsigned int cachedColor = kWhite;
1764 do // all pixels in row
1766 unsigned char CMDByte = 0;
1767 int replacementCount;
1769 // Find seedRowPixelCopyCount for upcoming copy
1770 seedRowPixelCopyCount = curPixel;
1771 while (getPixel(seedRowPtr, curPixel) == getPixel(curRowPtr, curPixel))
1776 seedRowPixelCopyCount = curPixel - seedRowPixelCopyCount;
1777 ASSERT (curPixel <= lastPixel);
1779 int pixelSource = 0;
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.
1783 putPixel(curRowPtr, lastPixel, realLastPixel);
1785 if (getPixel(seedRowPtr, curPixel) == realLastPixel)
1789 else // code last pix as a literal
1793 pixelSource = eeNewPixel;
1794 replacementCount = 1;
1798 else // prior to last pixel of row
1800 ASSERT(curPixel < lastPixel);
1802 replacementCount = curPixel;
1803 uint32_t RLERun = getPixel(curRowPtr, curPixel);
1805 curPixel++; // Adjust for next pixel.
1806 while (RLERun == getPixel(curRowPtr, curPixel)) // RLE
1810 curPixel--; // snap back to current.
1811 replacementCount = curPixel - replacementCount;
1812 ASSERT(replacementCount >= 0);
1814 if (replacementCount > 0) // Adjust for total occurance and move to next pixel to do.
1819 if (cachedColor == RLERun)
1821 pixelSource = eeCachedColor;
1823 else if (getPixel(seedRowPtr, curPixel-replacementCount+1) == RLERun)
1825 pixelSource = eeNEPixel;
1827 else if ((curPixel-replacementCount > 0) && (getPixel(curRowPtr, curPixel-replacementCount-1) == RLERun))
1829 pixelSource = eeWPixel;
1833 pixelSource = eeNewPixel;
1834 cachedColor = RLERun;
1837 CMDByte = eRLE; // Set default for later.
1841 if (curPixel == lastPixel)
1843 ASSERT(replacementCount > 0); // Already found some RLE pixels
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.
1847 putPixel(curRowPtr, lastPixel, realLastPixel);
1853 if (0 == replacementCount) // no RLE so it's a literal by default.
1855 uint32_t tempPixel = getPixel(curRowPtr, curPixel);
1857 ASSERT(tempPixel != getPixel(curRowPtr, curPixel+1)); // not RLE
1858 ASSERT(tempPixel != getPixel(seedRowPtr, curPixel)); // not seedrow copy
1862 if (cachedColor == tempPixel)
1864 pixelSource = eeCachedColor;
1867 else if (getPixel(seedRowPtr, curPixel+1) == tempPixel)
1869 pixelSource = eeNEPixel;
1872 else if ((curPixel > 0) && (getPixel(curRowPtr, curPixel-1) == tempPixel))
1874 pixelSource = eeWPixel;
1880 pixelSource = eeNewPixel;
1881 cachedColor = tempPixel;
1884 replacementCount = curPixel;
1885 uint32_t cachePixel;
1886 uint32_t nextPixel = getPixel(curRowPtr, curPixel+1);
1889 if (++curPixel == lastPixel)
1891 putPixel(curRowPtr, lastPixel, realLastPixel);
1895 cachePixel = nextPixel;
1897 while ((cachePixel != (nextPixel = getPixel(curRowPtr, curPixel+1))) &&
1898 (cachePixel != getPixel(seedRowPtr, curPixel)));
1900 replacementCount = curPixel - replacementCount;
1902 ASSERT(replacementCount > 0);
1906 ASSERT(seedRowPixelCopyCount >= 0);
1908 // Write out compressed data next.
1909 if (eLiteral == CMDByte)
1911 ASSERT(replacementCount >= 1);
1913 replacementCount -= 1; // normalize it
1915 CMDByte |= pixelSource; // Could put this directly into CMDByte above.
1916 CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
1917 CMDByte |= MIN(7, replacementCount);
1919 *compressedDataPtr++ = CMDByte;
1921 if (seedRowPixelCopyCount >= 3)
1923 outputVLIBytesConsecutively(seedRowPixelCopyCount - 3, compressedDataPtr);
1926 replacementCount += 1; // denormalize it
1928 int totalReplacementCount = replacementCount;
1929 int upwardPixelCount = 1;
1931 if (eeNewPixel != pixelSource)
1933 replacementCount -= 1; // Do not encode 1st pixel of run since it comes from an alternate location.
1934 upwardPixelCount = 2;
1937 for ( ; upwardPixelCount <= totalReplacementCount; upwardPixelCount++)
1939 ASSERT(totalReplacementCount >= upwardPixelCount);
1941 unsigned short compressedPixel = ShortDelta( getPixel(curRowPtr, curPixel-replacementCount),
1942 getPixel(seedRowPtr, curPixel-replacementCount));
1943 if (compressedPixel)
1945 *compressedDataPtr++ = compressedPixel >> 8;
1946 *compressedDataPtr++ = (unsigned char)compressedPixel;
1951 uint32_t uncompressedPixel = getPixel(curRowPtr, curPixel-replacementCount);
1953 uncompressedPixel >>= 1; // Lose the lsb of blue and zero out the msb of the 3 bytes.
1955 *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 16);
1956 *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 8);
1957 *compressedDataPtr++ = (BYTE)(uncompressedPixel);
1961 if (((upwardPixelCount-8) % 255) == 0) // See if it's time to spill a single VLI byte.
1963 *compressedDataPtr++ = MIN(255, totalReplacementCount - upwardPixelCount);
1971 ASSERT(eRLE == CMDByte);
1972 ASSERT(replacementCount >= 2);
1974 replacementCount -= 2; // normalize it
1976 CMDByte |= pixelSource; // Could put this directly into CMDByte above.
1977 CMDByte |= MIN(3, seedRowPixelCopyCount) << 3;
1978 CMDByte |= MIN(7, replacementCount);
1980 *compressedDataPtr++ = CMDByte;
1982 if (seedRowPixelCopyCount >= 3)
1984 outputVLIBytesConsecutively(seedRowPixelCopyCount - 3, compressedDataPtr);
1987 replacementCount += 2; // denormalize it
1989 if (eeNewPixel == pixelSource)
1991 unsigned short compressedPixel = ShortDelta(getPixel(curRowPtr, curPixel - replacementCount),
1992 getPixel(seedRowPtr, curPixel - replacementCount));
1993 if (compressedPixel)
1995 *compressedDataPtr++ = compressedPixel >> 8;
1996 *compressedDataPtr++ = (unsigned char)compressedPixel;
2000 uint32_t uncompressedPixel = getPixel(curRowPtr, curPixel - replacementCount);
2002 uncompressedPixel >>= 1;
2004 *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 16);
2005 *compressedDataPtr++ = (BYTE)(uncompressedPixel >> 8);
2006 *compressedDataPtr++ = (BYTE)(uncompressedPixel);
2010 if (replacementCount-2 >= 7) outputVLIBytesConsecutively(replacementCount - (7+2), compressedDataPtr);
2012 } while (curPixel <= lastPixel);
2015 size = compressedDataPtr - compressedDataStart; // return # of compressed bytes.
2016 compressedsize = size;
2017 memcpy(SeedRow, input->rasterdata[myplane], originalsize);
2023 BYTE* Mode10::NextOutputRaster(COLORTYPE color)
2024 // since we return 1-for-1, just return result first call
2026 if (iRastersReady==0)
2029 if (color == COLORTYPE_BLACK)
2031 return raster.rasterdata[color];
2036 if (raster.rasterdata[color] != NULL)
2042 return raster.rasterdata[color];
2047 BYTE DJ9xxVIP::PhotoTrayStatus
2055 BYTE bDevIDBuff[DevIDBuffSize];
2059 bQueryPrinter = FALSE;
2062 err = pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, bQueryPrinter);
2068 if ( (pStr=(char *)strstr((const char*)bDevIDBuff+2,";S:")) == NULL )
2073 // skip over ";S:<version=2bytes><topcover><inklid><duplexer>"
2080 BOOL DJ9xxVIP::PhotoTrayPresent
2085 // for phototray present == 8
2086 return ((PhotoTrayStatus(bQueryPrinter) & 8) == 8);
2087 } //PhotoTrayInstalled
2090 PHOTOTRAY_STATE DJ9xxVIP::PhotoTrayEngaged
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.
2100 // for phototray present and engaged == 9
2101 return ((PHOTOTRAY_STATE) ((PhotoTrayStatus(bQueryPrinter) & 9) == 9));
2102 } //PhotoTrayEngaged
2105 PAPER_SIZE DJ9xxVIP::MandatoryPaperSize()
2107 if (PhotoTrayEngaged (TRUE))
2109 else return UNSUPPORTED_SIZE; // code for "nothing mandatory"
2110 } //MandatoryPaperSize
2113 DRIVER_ERROR DJ9xxVIP::CheckInkLevel()
2119 // BYTE bDevIDBuff[DevIDBuffSize];
2128 * Check for unknown device id version.
2131 if ((pSS->GetVIPVersion ()) > 5)
2136 err = pSS->GetDeviceID(bDevIDBuff, DevIDBuffSize, TRUE);
2142 if ( (pStr=(char *)strstr((const char*)bDevIDBuff+2,";S:")) == NULL )
2148 // Skip to pen-count field
2150 err = SetPenInfo (pStr, FALSE);
2151 if (err != NO_ERROR)
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
2162 if (pSS->GetVIPVersion () == 1)
2165 // DJ990 style DeviceID
2167 // Next 3 should be 2C1
2168 // meaning 2 pens, first field is head/supply for K
2172 b1=*pStr++; b2=*pStr++; b3=*pStr++;
2173 if ( (b1 != '2') || (b2 != 'C') || (b3 != '1'))
2179 pStr++; // skip pen identifier
2180 BYTE blackink = *pStr - 48; // convert from ascii
2181 // only look at low 3 bits
2182 blackink = blackink & 7;
2184 // skip into color field
2186 BYTE colorink = *pStr - 48;
2187 // only look at low 3 bits
2188 colorink = colorink & 7;
2190 if ((blackink<5) && (colorink<5))
2195 if ((blackink>4) && (colorink>4))
2197 return WARN_LOW_INK_BOTH_PENS;
2201 return WARN_LOW_INK_BLACK;
2205 return WARN_LOW_INK_COLOR;
2211 if (pSS->GetVIPVersion () > 4)
2218 if (*pStr > '0' && *pStr < '9')
2220 numPens = *pStr - '0';
2222 else if (*pStr > 'A' && *pStr < 'F')
2224 numPens = *pStr - 'A';
2226 else if (*pStr > 'a' && *pStr < 'f')
2228 numPens = *pStr - 'a';
2234 if (pSS->GetVIPVersion () == 3)
2236 for (i = 0; i < numPens; i++, pStr += 4)
2242 if ((*(pStr+1) & 0xf3) > 1)
2244 if (err != NO_ERROR)
2246 err = WARN_LOW_INK_MULTIPLE_PENS;
2250 err = WARN_LOW_INK_BLACK;
2257 if ((*(pStr+1) & 0xf3) > 1)
2259 if (err != NO_ERROR)
2261 err = WARN_LOW_INK_MULTIPLE_PENS;
2265 err = WARN_LOW_INK_CYAN;
2272 if ((*(pStr+1) & 0xf3) > 1)
2274 if (err != NO_ERROR)
2276 err = WARN_LOW_INK_MULTIPLE_PENS;
2280 err = WARN_LOW_INK_MAGENTA;
2288 if ((*(pStr+1) & 0xf3) > 1)
2290 if (err != NO_ERROR)
2292 err = WARN_LOW_INK_MULTIPLE_PENS;
2296 err = WARN_LOW_INK_YELLOW;
2306 BYTE penInfoBits[4];
2312 for (i = 0; i < numPens; i++, pStr += 8)
2314 AsciiHexToBinary (penInfoBits, pStr, 8);
2316 if ((penInfoBits[0] & 0x40) != 0x40) // if Bit 31 is 1, this is not a pen
2320 int penColor = penInfoBits[0] & 0x3F;
2324 blackink = penInfoBits[1] & 0x7;
2327 colorink = penInfoBits[1] & 0x7;
2330 photoink = penInfoBits[1] & 0x7;
2333 greyink = penInfoBits[1] & 0x7;
2341 colorink = penInfoBits[1] & 0x7; // REVISIT: these are C, M, Y respectively
2347 if (blackink < 2 && colorink < 2 && photoink < 2 && greyink < 2)
2351 else if (blackink > 1 && colorink > 1 && photoink > 1)
2353 return WARN_LOW_INK_COLOR_BLACK_PHOTO;
2355 else if (greyink > 1 && colorink > 1 && photoink > 1)
2357 return WARN_LOW_INK_COLOR_GREY_PHOTO;
2359 else if (blackink > 1 && colorink > 1)
2361 return WARN_LOW_INK_BOTH_PENS;
2363 else if (blackink > 1 && photoink > 1)
2365 return WARN_LOW_INK_BLACK_PHOTO;
2367 else if (greyink > 1 && colorink > 1)
2369 return WARN_LOW_INK_COLOR_GREY;
2371 else if (greyink > 1 && photoink > 1)
2373 return WARN_LOW_INK_GREY_PHOTO;
2375 else if (colorink > 1 && photoink > 1)
2377 return WARN_LOW_INK_COLOR_PHOTO;
2379 else if (blackink > 1)
2381 return WARN_LOW_INK_BLACK;
2383 else if (colorink > 1)
2385 return WARN_LOW_INK_COLOR;
2387 else if (photoink > 1)
2389 return WARN_LOW_INK_PHOTO;
2391 else if (greyink > 1)
2393 return WARN_LOW_INK_GREY;
2395 else if (colorink > 1)
2397 return WARN_LOW_INK_COLOR;
2407 #endif //APDK_DJ9xxVIP