1 /*****************************************************************************\
2 job.cpp : Implimentation for the Job class
4 Copyright (c) 1996 - 2001, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of Hewlett-Packard nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
32 #include "halftoner.h"
33 #include "colormatch.h"
34 #include "scaler_open.h"
35 #include "scaler_prop.h"
38 extern Halftoner* Create_Halftoner( SystemServices* pSys, PrintMode* pPM,
39 unsigned int iInputWidth, unsigned int iNumRows[], unsigned int HiResFactor,
41 extern Scaler* Create_Scaler(SystemServices* pSys,int inputwidth,
42 int numerator,int denominator,BOOL vip,unsigned int BytesPerPixel);
43 extern ColorMatcher* Create_ColorMatcher( SystemServices* pSys,
44 ColorMap cm,unsigned int DyeCount,
45 unsigned int iInputWidth);
46 extern BOOL ProprietaryImaging();
47 extern BOOL ProprietaryScaling();
52 extern float frac(float f);
54 #define InitialPixelSize 3 // means first data into pipeline is RGB24
55 #define Bytes(x) ((x/8)+(x%8))
57 //////////////////////////////////////////////////////////////////////////
58 // The Job object receives data for a contiguous set of pages targeted at
59 // a single printer, with a single group of settings encapsulated in the
61 // At least one page will be ejected for a job, if any data at all
62 // is printed (no half-page jobs). If settings are to be changed, this
63 // must be done between jobs.
67 constructor - must pass a valid PrintContext to create the job.
68 Check constructor_error for NO_ERROR before continuing.
83 pBlackPlaneReplicator(NULL),
86 pBlackPlaneCompressor(NULL),
88 #if defined(APDK_VIP_COLORFILTERING)
91 #if defined(APDK_FONTS_NEEDED)
94 CurrentMode(pPC->CurrentMode),
101 #ifdef APDK_USAGE_LOG
110 constructor_error = NO_ERROR;
112 if (!thePrintContext->PrinterSelected())
114 constructor_error = NO_PRINTER_SELECTED;
117 thePrinter = thePrintContext->thePrinter;
120 for (i=0; i<(unsigned)MAXCOLORPLANES; i++)
121 if (CurrentMode->MixedRes) // means res(K) !+ res(C,M,Y)
122 numrows[i] = CurrentMode->ResolutionX[i] / CurrentMode->BaseResX;
125 ResBoost = CurrentMode->BaseResX / CurrentMode->BaseResY;
126 if (ResBoost==0) ResBoost=1; // safety
129 pHead = thePrinter->SelectHeader(thePrintContext);
133 // set up blank raster used by SendRasters
134 constructor_error=setblankraster();
137 // flush any garbage out of the printer's buffer
138 constructor_error=thePrinter->Flush();
140 // send the PCL header
141 constructor_error=pHead->Send();
143 // set CAPy after sending header in case header used it
147 constructor_error=Configure();
151 #if defined(APDK_FONTS_NEEDED)
153 pText = new TextTranslator(thePrinter, pHead->QualityCode(),
154 thePrintContext->CurrentMode->dyeCount);
157 theTextManager = NULL;
158 if (CurrentMode->bFontCapable)
160 unsigned int pixelsX = (unsigned int) (int) (thePrintContext->printablewidth() *
161 CurrentMode->BaseResX);
162 unsigned int pixelsY = (unsigned int) (int) (thePrintContext->printableheight() *
163 CurrentMode->BaseResY);
165 theTextManager=new TextManager( pText, pixelsX,pixelsY );
166 CNEWCHECK(theTextManager);
167 constructor_error = theTextManager->constructor_error;
172 if (!thePrintContext->ModeAgreesWithHardware(TRUE))
173 constructor_error = WARN_MODE_MISMATCH;
175 #ifdef APDK_USAGE_LOG
180 DRIVER_ERROR Job::SetupHalftoning(HALFTONING_ALGORITHM eHT)
181 // Subroutine of Job constructor to handle ColorMatcher/Halftoner initialization.
182 // OutputWidth set in InitScaler (it is not the ultimate width if horizontal doubling is needed)
183 // Has to decide whether to use matrix or fast-error-diffusion, open or proprietary.
185 // first level of decision on matrix-vs.FED is the printmode setting itself
186 BOOL usematrix = (eHT == MATRIX);
187 // but this is overridden in speed-optimized builds
188 // we also can simulate the build-switch at runtime in the test harness
189 #ifdef APDK_OPTIMIZE_FOR_SPEED
193 pHalftoner = Create_Halftoner(thePrintContext->pSS, CurrentMode,
194 OutputWidth, numrows,ResBoost,usematrix);
195 NEWCHECK(pHalftoner);
196 return pHalftoner->constructor_error;
199 DRIVER_ERROR Job::SetupColorMatching()
202 unsigned int cmWidth=InputWidth;
203 if (pResSynth) // if 2X scaling happens before ColorMatching
206 pColorMatcher = Create_ColorMatcher(thePrintContext->pSS, CurrentMode->cmap,
207 CurrentMode->dyeCount, cmWidth);
208 NEWCHECK(pColorMatcher);
209 return pColorMatcher->constructor_error;
210 } //SetupColorMatching
219 // Client isn't required to call NewPage at end of last page, so
220 // we may need to eject a page now.
223 MediaSource mSource = thePrintContext->GetMediaSource ();
224 if (mSource == sourceBanner)
226 thePrintContext->SetMediaSource (sourceTrayAuto);
229 thePrintContext->SetMediaSource (mSource);
233 // Tell printer that job is over.
239 // Delete the 4 components created in Job constructor.
240 #if defined(APDK_FONTS_NEEDED)
241 DBG1("deleting TextManager\n");
244 delete theTextManager;
248 DBG1("deleting RasterSender\n");
261 delete pColorMatcher;
266 pSS->FreeMemory(BlankRaster);
271 pSS->FreeMemory(BlackRaster);
274 if (pBlackPlaneReplicator)
276 delete pBlackPlaneReplicator;
299 #if defined(APDK_VIP_COLORFILTERING)
308 delete theCompressor;
311 if (pBlackPlaneCompressor)
313 delete pBlackPlaneCompressor;
316 #if defined(APDK_FONTS_NEEDED)
321 #endif // defined(APDK_FONTS_NEEDED)
326 thePrinter->EndJob = TRUE; // the Job is done -
327 thePrinter->Send(&temp,0); // call Send to dump any buffered data
330 DBG1("done with ~Job\n");
334 DRIVER_ERROR Job::SendCAPy()
336 return pHead->SendCAPy(CAPy++);
339 ///////////////////////////////////////////////////////////////////////////////////
342 This is the fundamental method for the driver, by means of which graphics data
343 is sent to the printer.
345 DRIVER_ERROR Job::SendRasters(BYTE* ImageData) // RGB24 data for one raster
346 // This is how graphical data is sent to the driver.
348 // We do not check for rasters where data is supplied but happens
349 // to be all blank (white); caller should have used NULL in this case.
352 Capture_SendRasters(NULL, ImageData);
355 return sendrasters(NULL, ImageData);
359 ///////////////////////////////////////////////////////////////////////////////////
362 This is the fundamental method for the driver, by means of which graphics data
363 is sent to the printer.
365 DRIVER_ERROR Job::SendRasters(BYTE* BlackImageData, BYTE* ColorImageData) // 1bit K data and RGB24 data for one raster
366 // This is how graphical data is sent to the driver.
368 // We do not check for rasters where data is supplied but happens
369 // to be all blank (white); caller should have used NULL in this case.
372 Capture_SendRasters(BlackImageData, ColorImageData);
374 return sendrasters(BlackImageData, ColorImageData);
378 This is the method for use to check if they can send a separate 1 bit black channel
380 DRIVER_ERROR Job::SupportSeparateBlack(BOOL* bSeparateBlack)
382 *bSeparateBlack = thePrinter->SupportSeparateBlack(CurrentMode);
386 // internal entry point, used by newpage
387 DRIVER_ERROR Job::sendrasters(BYTE* BlackImageData, BYTE* ColorImageData)
389 DRIVER_ERROR err = NO_ERROR;
391 if (thePipeline == NULL)
396 // need to put out some data occasionally in case of all-text page,
397 // so printer will go ahead and start printing the text before end of page
398 if (BlackImageData == NULL && ColorImageData == NULL)
400 if (thePrinter->GetDataFormat() == RASTER_STRIP)
403 ColorImageData=BlankRaster;
408 if (skipcount >= 200)
411 ColorImageData=BlankRaster;
415 fcount += ScaleFactor;
418 err = thePipeline->Flush();
425 DataSent=TRUE; // so we know we need a formfeed when job ends
428 RowsInput++; // needed in case res > 300
430 if (BlackImageData || ColorImageData)
436 err = thePrinter->SkipRasters ((fcount / 1000)); // needed for DJ3320
438 fcount =fcount % 1000;
441 if (BlackImageData && CurrentMode->dyeCount != 3 && CurrentMode->dyeCount != 6)
443 err = setblackraster();
446 for (unsigned int i = 0; i < thePrintContext->InputWidth / 8; i++)
448 unsigned char bitflag = 0x80;
449 for (unsigned int j = 0; j < 8; j++)
451 if (BlackImageData[i] & bitflag)
452 BlackRaster[i*8+j] = 1;
453 bitflag = bitflag >> 1;
456 if (thePrintContext->InputWidth % 8 > 0)
458 unsigned int i = thePrintContext->InputWidth / 8;
459 unsigned char bitflag = 0x80;
460 for (unsigned int j = 0; j < thePrintContext->InputWidth % 8; j++)
462 if (BlackImageData[i] & bitflag)
463 BlackRaster[i*8+j] = 1;
464 bitflag = bitflag >> 1;
467 thePipeline->Exec->raster.rastersize[COLORTYPE_BLACK] = thePrintContext->InputWidth;
468 thePipeline->Exec->raster.rasterdata[COLORTYPE_BLACK] = BlackRaster;
472 thePipeline->Exec->raster.rastersize[COLORTYPE_BLACK] = 0;
473 thePipeline->Exec->raster.rasterdata[COLORTYPE_BLACK] = NULL;
477 thePipeline->Exec->raster.rastersize[COLORTYPE_COLOR] = thePrintContext->InputWidth*3;
478 thePipeline->Exec->raster.rasterdata[COLORTYPE_COLOR] = ColorImageData;
482 thePipeline->Exec->raster.rastersize[COLORTYPE_COLOR] = 0;
483 thePipeline->Exec->raster.rasterdata[COLORTYPE_COLOR] = NULL;
485 err = thePipeline->Execute(&(thePipeline->Exec->raster));
492 DRIVER_ERROR Job::newpage()
493 // (for internal use, called by external NewPage)
497 if (thePrinter->GetDataFormat() == RASTER_STRIP)
499 pHead->SetLastBand(TRUE);
502 sendrasters(); // flush pipeline
504 if ((thePrintContext->GetMediaSource ()) == sourceBanner)
510 err = pHead->FormFeed();
513 // reset vertical cursor counter
514 if (thePrinter->UseGUIMode(thePrintContext->CurrentMode) &&
515 ((int) (thePrintContext->PrintableStartY () * 100)) != 0)
516 // DJ895 in GUImode doesn't accept top-margin setting, so we use CAP for topmargin
517 // Start at the top for full-bleed printing - PhotoSmart 100 for now
519 CAPy = thePrintContext->GUITopMargin();
527 skipcount = RowsInput = 0;
530 // reset flag used to see if formfeed needed
533 if (!thePrintContext->ModeAgreesWithHardware(TRUE))
535 return WARN_MODE_MISMATCH;
538 #ifdef APDK_USAGE_LOG
539 theTranslator->PrintDotCount(UHeader);
540 theTranslator->NextPage();
548 This method forces the associated printer to flush the remaining buffered
\r
549 data and tells it that the job is ended.
\r
551 Calling this method is not mandatory, since the object destructor already
\r
552 performs this action. It may be required, however, if the destructor is not
\r
553 called for some reason (for instance, when the call depends on the execution
\r
554 of a "finalize" method of a Java wrapper.
\r
557 DRIVER_ERROR Job::Flush()
\r
562 thePrinter->EndJob = TRUE; // the Job is done -
\r
563 return thePrinter->Send(&temp,0); // call Send to dump any buffered data
\r
565 return NO_PRINTER_SELECTED;
\r
569 Resets counters, flushes buffers, and sends a form feed to the printer.
571 DRIVER_ERROR Job::NewPage()
572 // External entry point
581 void Job::SetOutputWidth()
582 // set OutputWidth -- this is local and may not agree with PrintContext
583 // in cases where horizontal doubling is needed
585 OutputWidth = thePrintContext->OutputWidth;
586 InputWidth = thePrintContext->InputWidth;
588 if (CurrentMode->BaseResX != CurrentMode->BaseResY) // if horizontal expansion needed
590 int mixedfactor = CurrentMode->BaseResX / CurrentMode->BaseResY;
591 int widthfactor = OutputWidth / InputWidth;
592 if (widthfactor >= mixedfactor)
594 OutputWidth = OutputWidth / mixedfactor;
600 DRIVER_ERROR Job::InitScaler()
601 // sets pResSynth & pReplicator
603 unsigned int numerator, denominator;
604 // set OutputWidth -- this is local and may not agree with PrintContext
605 // in cases where horizontal doubling is needed (see next if clause)
608 if ((OutputWidth % InputWidth) == 0)
610 numerator = OutputWidth / InputWidth;
615 numerator = OutputWidth;
616 denominator = InputWidth;
620 float tempfactor = (float)numerator / (float)denominator;
621 tempfactor *= 1000.0f;
622 ScaleFactor = (unsigned int) (int) tempfactor;
624 // Two paths: if ResSynth included (proprietary path), then use it for the first doubling;
625 // otherwise do it all in PixelReplication phase
626 // but don't use ResSynth anyway if printer-res=600 and scale<4 (i.e. original-res<150),
627 // or printer-res=300 and scale<2.33 (i.e. original-res<133)
630 #ifdef APDK_OPTIMIZE_FOR_SPEED
632 #endif // APDK_OPTIMIZE_FOR_SPEED
639 if (thePrintContext->EffectiveResolutionX()>300)
641 // I don't know about 1200dpi, so I'm doing it this way
642 RSok = ScaleFactor >= 4000;
646 RSok = ScaleFactor >= 2333;
651 unsigned int ReplFormat; // how many bytes per pixel
652 if (CurrentMode->Config.bColorImage)
654 ReplFormat = CurrentMode->dyeCount; // dealing with colormatching output
658 ReplFormat = 3; // RGB only
661 BOOL vip = !CurrentMode->Config.bColorImage;
663 if ((!ProprietaryScaling()) || !RSok )
664 // everything happens at Replication phase; input may be KCMY (or K, CMY, etc.) or RGB
667 pReplicator = new Scaler_Open(pSS,InputWidth,numerator,denominator,vip,ReplFormat);
668 NEWCHECK(pReplicator);
669 return pReplicator->constructor_error;
672 // Proprietary path and scalefactor>=2, so break it up into 2 parts
673 // first give ResSynth a factor of 2, which is all it really does anyway.
675 // Scaler_Prop only operates on RGB, so it doesn't need the last two parameters
676 pResSynth = Create_Scaler(pSS,InputWidth,2,1,
677 TRUE, // as if VIP since it is working on RGB only at this phase
678 3); // 3 bytes per pixel
680 pResSynth->myplane = COLORTYPE_COLOR;
681 if (pResSynth->constructor_error != NO_ERROR)
683 return pResSynth->constructor_error;
686 pBlackPlaneReplicator = new Scaler_Open(pSS,InputWidth,2,1,FALSE,1);
687 NEWCHECK(pBlackPlaneReplicator);
688 pBlackPlaneReplicator->myplane = COLORTYPE_BLACK;
689 if (pBlackPlaneReplicator->constructor_error != NO_ERROR)
691 return pBlackPlaneReplicator->constructor_error;
694 // now replicate the rest of the way -- only half as much left
695 pReplicator = new Scaler_Open(pSS,2*InputWidth,numerator,2*denominator,vip,ReplFormat);
696 NEWCHECK(pReplicator);
697 return pReplicator->constructor_error;
702 DRIVER_ERROR Job::Configure()
703 // mode has been set -- now set up rasterwidths and pipeline
710 err = InitScaler(); // create pReplicator and maybe pResSynth
713 if ((CurrentMode->Config.bResSynth) && ProprietaryScaling()
714 && pResSynth) // pResSynth==NULL if no scaling required
716 p = new Pipeline(pBlackPlaneReplicator);
719 thePipeline->AddPhase(p);
722 p = new Pipeline(pResSynth);
725 thePipeline->AddPhase(p);
730 #if (defined(APDK_DJ9xxVIP) || defined(APDK_LJJETREADY)) && defined(APDK_VIP_COLORFILTERING)
731 if (CurrentMode->Config.bErnie)
733 // create Ernie (need pixelwidth for constructor)
736 width = p->GetMaxOutputWidth(COLORTYPE_COLOR) / 3; // GetOutputWidth returns # of bytes
740 width = thePrintContext->InputWidth;
743 // calculate Ernie threshold value
744 //Normal: threshold = (resolution) * (0.0876) - 2
745 // roughly: image at original 300 implies threshold=24; 600=>48, 150=>12, 75=>6
746 // to get resolution of "original" image, divide target resolution by scalefactor
747 float scale = (float)thePrintContext->OutputWidth / (float)thePrintContext->InputWidth;
748 float original_res = ((float)thePrintContext->EffectiveResolutionX()) / scale;
749 if (useRS && (scale >= 2.0f))
751 // image already doubled by ResSynth so consider the resolution as of now
752 original_res *= 2.0f;
754 float fthreshold = original_res * 0.0876f;
755 int threshold = (int)fthreshold - 2;
757 pErnie = new TErnieFilter(width, eBGRPixelData, threshold);
758 p = new Pipeline(pErnie);
762 thePipeline->AddPhase(p);
769 #endif //APDK_DJ9xxVIP && APDK_VIP_COLORFILTERING
771 if (CurrentMode->Config.bColorImage)
773 err = SetupColorMatching(); // create pColorMatcher
775 p = new Pipeline(pColorMatcher);
779 thePipeline->AddPhase(p);
787 if (CurrentMode->Config.bPixelReplicate)
790 p = new Pipeline(pReplicator);
794 thePipeline->AddPhase(p);
802 if (CurrentMode->Config.bColorImage)
804 err = SetupHalftoning(CurrentMode->Config.eHT); // create pHalftoner
806 p = new Pipeline(pHalftoner);
810 thePipeline->AddPhase(p);
818 if (CurrentMode->Config.bCompress)
822 width = p->GetMaxOutputWidth(COLORTYPE_COLOR);
826 width = thePrintContext->InputWidth;
828 unsigned int SeedBufferSize;
829 if (pHalftoner) // if data is halftoned-output
831 // format is 1 bit-per-pixel for each ink,drop,pass
832 SeedBufferSize = MAXCOLORPLANES * MAXCOLORDEPTH * MAXCOLORROWS * width;
834 else // VIP data is just RGB24 here
836 SeedBufferSize = width;
839 theCompressor = thePrinter->CreateCompressor(SeedBufferSize);
840 NEWCHECK(theCompressor);
841 err = theCompressor->constructor_error;
843 theCompressor->myplane = COLORTYPE_COLOR;
845 p = new Pipeline(theCompressor);
849 thePipeline->AddPhase(p);
855 if (thePrinter->VIPPrinter())
857 width = (width/3+7)/8;
860 // VIP black data is 1 bit here
861 unsigned int SeedBufferSize;
862 SeedBufferSize = width;
863 pBlackPlaneCompressor = thePrinter->CreateBlackPlaneCompressor(SeedBufferSize, TRUE);
864 NEWCHECK(pBlackPlaneCompressor);
865 err = pBlackPlaneCompressor->constructor_error;
867 pBlackPlaneCompressor->myplane = COLORTYPE_BLACK;
869 p = new Pipeline(pBlackPlaneCompressor);
873 thePipeline->AddPhase(p);
884 // always end pipeline with RasterSender
885 // create RasterSender object
886 pSender = new RasterSender(thePrinter,thePrintContext,this,pHalftoner);
888 err = pSender->constructor_error;
891 p = new Pipeline(pSender);
895 thePipeline->AddPhase(p);
906 DRIVER_ERROR Job::setblankraster()
910 pSS->FreeMemory(BlankRaster);
913 size_t BlankRasterSize = thePrintContext->OutputWidth * 3; // Raghu
914 BlankRaster = (BYTE*)pSS->AllocMem (BlankRasterSize);
915 NEWCHECK(BlankRaster);
917 memset (BlankRaster, 0xFF, BlankRasterSize); // Raghu
922 DRIVER_ERROR Job::setblackraster()
924 size_t BlackRasterSize = thePrintContext->InputWidth;
927 BlackRaster = (BYTE*)pSS->AllocMem (BlackRasterSize);
928 NEWCHECK(BlackRaster);
930 memset (BlackRaster, 0, BlackRasterSize);
936 //////////////////////////////////////////////////////////////////////
937 #if defined(APDK_FONTS_NEEDED)
940 This method is used to send ASCII data to the printer, which it will render
941 as determined by the Font object.
943 DRIVER_ERROR Job::TextOut
945 const char* pTextString,
946 unsigned int iLenString,
951 // This is how ASCII data is sent to the driver.
952 // Everything is really handled by the TextManager, including error checking.
955 Capture_TextOut(pTextString, iLenString, font, iAbsX, iAbsY);
958 // Map coordinates (assumed to be in the graphical space) to the text-placement grid,
959 // which may be of lower resolution, indicated by TextRes
961 // using floats to cover the unusual case where graphical res is lower than text
962 float xfactor = ((float)CurrentMode->BaseResX) / ((float)CurrentMode->TextRes);
963 float yfactor = ((float)CurrentMode->BaseResY) / ((float)CurrentMode->TextRes);
965 float x = (float)iAbsX / xfactor;
966 float y = (float)iAbsY / yfactor;
968 iAbsX = (unsigned int)(int)x; // double cast for webtv compiler
969 iAbsY = (unsigned int)(int)y;
971 DRIVER_ERROR err = theTextManager->TextOut(pTextString,iLenString,font,iAbsX,iAbsY);
976 #ifdef APDK_USAGE_LOG
977 if (iLenString > UTextSize)
979 iLenString = UTextSize-1;
980 UHeader[iLenString] = '\0';
984 strcpy(UHeader,pTextString);
989 UHeader[UText] = '\0';
1001 ///////////////////////////////////////////////////////////
1002 // Pipeline management
1011 Exec->myphase = this;
1015 void Pipeline::AddPhase(Pipeline* newp)
1027 Pipeline::~Pipeline()
1036 BOOL Pipeline::Process(RASTERDATA* raster)
1038 return Exec->Process(raster);
1042 DRIVER_ERROR Pipeline::Execute(RASTERDATA* InputRaster)
1046 if (Process(InputRaster) // true if output ready; may set err
1051 next->Exec->raster.rasterdata[COLORTYPE_BLACK] = NextOutputRaster(COLORTYPE_BLACK);
1052 next->Exec->raster.rasterdata[COLORTYPE_COLOR] = NextOutputRaster(COLORTYPE_COLOR);
1053 while (next->Exec->raster.rasterdata[COLORTYPE_COLOR] ||
1054 next->Exec->raster.rasterdata[COLORTYPE_BLACK])
1056 next->Exec->raster.rastersize[COLORTYPE_COLOR] = GetOutputWidth(COLORTYPE_COLOR);
1057 next->Exec->raster.rastersize[COLORTYPE_BLACK] = GetOutputWidth(COLORTYPE_BLACK);
1058 err = next->Execute(&(next->Exec->raster));
1060 next->Exec->raster.rasterdata[COLORTYPE_BLACK] = NextOutputRaster(COLORTYPE_BLACK);
1061 next->Exec->raster.rasterdata[COLORTYPE_COLOR] = NextOutputRaster(COLORTYPE_COLOR);
1069 DRIVER_ERROR Pipeline::Flush()
1075 if (next && (err == NO_ERROR))
1077 next->Exec->raster.rasterdata[COLORTYPE_BLACK] = NextOutputRaster(COLORTYPE_BLACK);
1078 next->Exec->raster.rasterdata[COLORTYPE_COLOR] = NextOutputRaster(COLORTYPE_COLOR);
1079 while (next->Exec->raster.rasterdata[COLORTYPE_COLOR] || next->Exec->raster.rasterdata[COLORTYPE_BLACK])
1081 next->Exec->raster.rastersize[COLORTYPE_BLACK] = GetOutputWidth(COLORTYPE_BLACK);
1082 next->Exec->raster.rastersize[COLORTYPE_COLOR] = GetOutputWidth(COLORTYPE_COLOR);
1083 err = next->Execute(&(next->Exec->raster));
1084 next->Exec->raster.rasterdata[COLORTYPE_BLACK] = NextOutputRaster(COLORTYPE_BLACK);
1085 next->Exec->raster.rasterdata[COLORTYPE_COLOR] = NextOutputRaster(COLORTYPE_COLOR);
1088 // one more to continue flushing downstream
1089 err = next->Flush();
1096 Processor::Processor() :
1098 iRastersDelivered(0),
1100 myplane(COLORTYPE_BOTH)
1102 for (int i = COLORTYPE_COLOR; i < MAX_COLORTYPE; i++)
1104 raster.rasterdata[i] = NULL;
1105 raster.rastersize[i] = 0;
1110 Processor::~Processor()