123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810 |
- /* Copyright (C) 1991, 1995, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
- /*$Id: gdevcdj.c,v 1.5 2001/03/13 06:51:39 ghostgum Exp $*/
- /* H-P and Canon colour printer drivers */
- /****************************************************************
- * The code in this file was contributed by the authors whose names and/or
- * e-mail addresses appear below: Aladdin Enterprises takes no
- * responsibility for it. In the past, we have tried to keep it working,
- * but too many users have made too many "improvements" without regard to
- * the overall structure; the last three "improvements" required me to spend
- * several hours fixing each one so that the code worked again at all. For
- * this reason, no further changes to this file will be accepted. We are
- * planning eventually to get these drivers rewritten from scratch.
- *
- * L. Peter Deutsch
- * Aladdin Enterprises
- * February 28, 1996
- ****************************************************************/
- /*
- * Change history:
- * 2000-08-20 Jonathan Kamens <jik@kamens.brookline.ma.us>:
- * change to support printers with different X and Y resolution.
- */
- /*
- * Important compilation notes (YA).
- *
- * You may also try the cdj550cmyk driver after having defined
- * USE_CDJ550_CMYK and added the needed definition in devs.mak. Not tried!
- * (I have a BJC!) Also note that modes descriptions of CMYK printing
- * is done under the BJC section of devices.doc.
- *
- * CMYK to RGB conversion is made a la GhostScript unless you define
- * the preprocessor symbol USE_ADOBE_CMYK_RGB.
- *
- * Ghostscript: R = (1.0 - C) * (1.0 - K)
- * Adobe: R = 1.0 - min(1.0, C + K)
- *
- * (and similarly for G and B). Ghostscript claims its method achieves
- * better results.
- *
- * For the BJC drivers, define BJC_DEFAULT_CENTEREDAREA if you want to
- * have the same top and bottom margins (default to use the tallest
- * imageable area available, usually with a top margin smaller than
- * the bottom one). Defining USE_RECOMMENDED_MARGINS has the same
- * effect and also sets these margins to 12.4 mm. Other compilation
- * defines are explained in devices.doc.
- *
- * You can also define BJC_INIT_800_AS_600 to not use BJC-800-specific code
- * in the page initialization sequence (normally not useful to you at all,
- * just for my debugging of the driver margins).
- *
- */
- #include "std.h" /* to stop stdlib.h redefining types */
- #include <stdlib.h> /* for rand() */
- #include "gdevprn.h"
- #include "gdevpcl.h"
- #include "gsparam.h"
- #include "gsstate.h"
- /* Conversion stuff. */
- #include "gxlum.h"
- /* Canon stuff */
- #include "gdevbjc.h"
- /***
- *** This file contains multiple drivers. The main body of code, and all
- *** but the DesignJet driver, were contributed by George Cameron;
- *** please contact g.cameron@biomed.abdn.ac.uk if you have questions.
- * 1 - cdj500: HP DeskJet 500C
- * 2 - cdj550: HP DeskJet 550C
- * 3 - pjxl300: HP PaintJet XL300
- * 4 - pj: HP PaintJet
- * 5 - pjxl: HP PaintJet XL
- * 6 - declj250: DEC LJ250
- *** The DesignJet 650C driver was contributed by Koert Zeilstra;
- *** please contact koert@zen.cais.com if you have questions.
- * 7 - dnj650c HP DesignJet 650C
- *** The LaserJet 4 driver with dithering was contributed by Eckhard
- *** Rueggeberg; please contact eckhard@ts.go.dlr.de if you have questions.
- * 8 - lj4dith: HP LaserJet 4 with dithering
- *** The ESC/P driver (for Epson ESC/P compatible printers) was written by
- *** Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp>, but is not maintained at
- *** the moment.
- * 9 - esc/p: Epson ESC/P-compatible printers
- *** The BJC600 driver (which also works for BJC4000) was written first
- *** by Yoshio Kuniyoshi <yoshio@nak.math.keio.ac.jp> and later modified by
- *** Yves Arrouye <yves.arrouye@usa.net>. The current driver has been
- *** completely rewritten by me (YA) for good color handling.
- * 10 - bjc600: BJC 600//4000 printers
- *** The BJC800 driver is based on the bjc600 one. By YA too.
- * 11 - bjc800: BJC 800 printer
- ***/
- /*
- * All of the HP-like drivers have 8-bit (monochrome), 16-bit and 24-bit
- * (colour) and for the DJ 550C 32-bit, (colour, cmyk mode)
- * options in addition to the usual 1-bit and 3-bit modes
- * It is also possible to set various printer-specific parameters
- * from the gs command line, eg.
- *
- * gs -sDEVICE=cdj550 -dBitsPerPixel=16 -dDepletion=1 -dShingling=2 tiger.ps
- *
- * Please consult the appropriate section in the devices.doc file for
- * further details on all these drivers.
- *
- * All of the BJC-like drivers have 1-bit and 8-bit monochrome modes, 8-bit,
- * 16-bit, 24-bit and 32-bit colour cmyk mode (the 8-bit monochrome mode
- * is called "4-bit". If you want to add a CMYK printer, look at the
- * bjc6000/bjc800 devices declarations and initialization.
- *
- * If you want to support different color components for the same depth
- * on a non-CMYK printer, look how this is done for CMYK printers in
- * cdj_set_bpp.
- *
- */
- /*
- * This taken from gsdparam.c. I hope it will be useable directly some day.
- *
- */
- #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
- switch ( ncode = pread(plist, (oname = pname), &pa) )\
- {\
- case 0:\
- if ( pa.size != psize )\
- code = gs_error_rangecheck;\
- else {
- /* The body of the processing code goes here. */
- /* If it succeeds, it should do a 'break'; */
- /* if it fails, it should set ecode and fall through. */
- #define END_PARAM(pa, e)\
- }\
- goto e;\
- default:\
- code = ncode;\
- e: param_signal_error(plist, oname, code);\
- case 1:\
- pa.data = 0; /* mark as not filled */\
- }
- private int cdj_param_check_bytes(P5(gs_param_list *, gs_param_name, const byte *, uint, bool));
- private int cdj_param_check_float(P4(gs_param_list *, gs_param_name, floatp, bool));
- #define cdj_param_check_string(plist, pname, str, defined)\
- cdj_param_check_bytes(plist, pname, (const byte *)str, strlen(str), defined)
- /*
- * Drivers stuff.
- *
- */
- #define DESKJET_PRINT_LIMIT 0.04 /* 'real' top margin? */
- #define PAINTJET_PRINT_LIMIT 0.0 /* This is a guess.. */
- #define ESC_P_PRINT_LIMIT 0.335
- /* Margins are left, bottom, right, top. */
- #define DESKJET_MARGINS_LETTER 0.25, 0.50, 0.25, 0.167
- #define DESKJET_MARGINS_A4 0.125, 0.50, 0.143, 0.167
- #define LJET4_MARGINS 0.26, 0.0, 0.0, 0.0
- /* The PaintJet and DesignJet seem to have the same margins */
- /* regardless of paper size. */
- #define PAINTJET_MARGINS 0.167, 0.167, 0.167, 0.167
- #define DESIGNJET_MARGINS 0.167, 0.167, 0.167, 0.167
- /*
- * With ESC/P commands, BJC-600 can print no more than 8 inches width.
- * So it can't use full width of letter size paper. Since non printable
- * left side area is 0.134 inch, we set up margins as follows.
- *
- * Note to readers: the bjc drivers series do *not* use ESC/P commands
- * but raster ops. Configuration of these drivers can be done through
- * the gdevbjc.h file.
- *
- */
- #define ESC_P_MARGINS_LETTER 0.134, 0.276+0.2, 0.366+0.01, 0.335
- #define ESC_P_MARGINS_A4 0.134, 0.276+0.2, 0.166+0.01, 0.335
- /* Define bits-per-pixel for generic drivers - default is 24-bit mode */
- #ifndef BITSPERPIXEL
- # define BITSPERPIXEL 24
- #endif
- /*
- * The following use of size_of rather than sizeof is required to work
- * around a bug in Microsoft Visual C++ 5.0, which considers the THRESHOLD
- * value (128 << SHIFT) to be unsigned because SHIFT is unsigned (because
- * sizeof() is unsigned).
- */
- #define W size_of(word)
- #define I size_of(int)
- #define invert_word(v)\
- ((v) >> 24) + (((v) >> 8) & 0xff00L) +\
- (((word)(v) << 8) & 0xff0000L) + ((word)(v) << 24)
- /* Printer types */
- #define DJ500C 0
- #define DJ550C 1
- #define PJXL300 2
- #define PJ180 3
- #define PJXL180 4
- #define DECLJ250 5
- #define DNJ650C 6
- #define LJ4DITH 7
- #define ESC_P 8
- #define BJC600 9
- #define BJC800 10
- /* No. of ink jets (used to minimise head movements) */
- #define HEAD_ROWS_MONO 50
- #define HEAD_ROWS_COLOUR 16
- /* Colour mapping procedures */
- private dev_proc_map_cmyk_color (gdev_cmyk_map_cmyk_color);
- private dev_proc_map_rgb_color (gdev_cmyk_map_rgb_color);
- private dev_proc_map_color_rgb (gdev_cmyk_map_color_rgb);
- private dev_proc_map_rgb_color (gdev_pcl_map_rgb_color);
- private dev_proc_map_color_rgb (gdev_pcl_map_color_rgb);
- /* Print-page, parameters and miscellaneous procedures */
- private dev_proc_open_device(dj500c_open);
- private dev_proc_open_device(dj550c_open);
- private dev_proc_open_device(dnj650c_open);
- private dev_proc_open_device(lj4dith_open);
- private dev_proc_open_device(pj_open);
- private dev_proc_open_device(pjxl_open);
- private dev_proc_open_device(pjxl300_open);
- private dev_proc_open_device(escp_open);
- private dev_proc_open_device(bjc_open);
- private dev_proc_print_page(declj250_print_page);
- private dev_proc_print_page(dj500c_print_page);
- private dev_proc_print_page(dj550c_print_page);
- private dev_proc_print_page(dnj650c_print_page);
- private dev_proc_print_page(lj4dith_print_page);
- private dev_proc_print_page(pj_print_page);
- private dev_proc_print_page(pjxl_print_page);
- private dev_proc_print_page(pjxl300_print_page);
- private dev_proc_print_page(escp_print_page);
- private dev_proc_print_page(bjc_print_page);
- private dev_proc_get_params(cdj_get_params);
- private dev_proc_get_params(pjxl_get_params);
- private dev_proc_get_params(bjc_get_params);
- #define ep_get_params cdj_get_params
- private dev_proc_put_params(cdj_put_params);
- private dev_proc_put_params(pj_put_params);
- private dev_proc_put_params(pjxl_put_params);
- private dev_proc_put_params(bjc_put_params);
- #define ep_put_params cdj_put_params
- /* The device descriptors */
- #define gx_prn_colour_device_common \
- gx_prn_device_common; \
- short cmyk; /* 0: not CMYK-capable, > 0: printing CMYK, */ \
- /* < 0 : CMYK-capable, not printing CMYK */ \
- uint default_depth; /* Used only for CMYK-capable printers now. */ \
- uint correction
- typedef struct gx_device_cdj_s gx_device_cdj;
- struct gx_device_cdj_s {
- gx_device_common;
- gx_prn_colour_device_common;
- int shingling; /* Interlaced, multi-pass printing */
- int depletion; /* 'Intelligent' dot-removal */
- };
- typedef struct gx_device_pjxl_s gx_device_pjxl;
- struct gx_device_pjxl_s {
- gx_device_common;
- gx_prn_colour_device_common;
- int printqual; /* Mechanical print quality */
- int rendertype; /* Driver or printer dithering control */
- };
- typedef struct gx_device_hp_s gx_device_hp;
- struct gx_device_hp_s {
- gx_device_common;
- gx_prn_colour_device_common;
- };
- typedef struct gx_device_hp_s gx_device_pj;
- typedef struct gx_device_bjc600_s gx_device_bjc600;
- typedef struct gx_device_bjc800_s gx_device_bjc800;
- typedef struct gx_device_bjc800_s gx_device_bjc;
- #define bjc_params_common \
- bool manualFeed; /* Use manual feed */ \
- int mediaType; /* Cf. strings below */ \
- bool mediaWeight_isSet; /* Say if weight is an integer or null */ \
- int mediaWeight; /* Weigth of the media */ \
- int printQuality; /* Cf. strings below */ \
- bool ditheringType; /* Do dithering */ \
- int colorComponents; /* The number of *desired* color comps */ \
- int printColors /* 0: Transparent, \
- 1: C, 2: M, 4: Y, 7: K (Color decomp). \
- if > 8, print in black ink. */
- typedef struct {
- bjc_params_common;
- bool monochromePrint; /* Print with black only */
- } bjc600_params;
- typedef struct {
- bjc_params_common;
- } bjc_params;
- typedef bjc_params bjc800_params;
- #define gx_bjc_device_common \
- gx_device_common; \
- gx_prn_colour_device_common; \
- int ptype; \
- float printLimit
- struct gx_device_bjc600_s {
- gx_bjc_device_common;
- bjc600_params bjc_p;
- };
- struct gx_device_bjc800_s {
- gx_bjc_device_common;
- bjc800_params bjc_p;
- };
- typedef struct {
- gx_device_common;
- gx_prn_colour_device_common;
- } gx_device_colour_prn;
- /* Use the cprn_device macro to access generic fields (like cmyk,
- default_depth and correction), and specific macros for specific
- devices. */
- #define cprn_device ((gx_device_colour_prn*) pdev)
- #define cdj ((gx_device_cdj *)pdev)
- #define pjxl ((gx_device_pjxl *)pdev)
- #define pj ((gx_device_pj *)pdev)
- #define bjc ((gx_device_bjc*) pdev)
- #define bjc600 ((gx_device_bjc600*) pdev)
- #define bjc800 ((gx_device_bjc800*) pdev)
- #define bjcparams (bjc->bjc_p)
- #define bjc600params (bjc600->bjc_p)
- #define bjc800params (bjc800->bjc_p)
- #define bjcversion(p) (((gx_device_bjc*) pdev)->ptype == BJC800 ? \
- BJC_BJC800_VERSION : BJC_BJC600_VERSION)
- #define bjcversionstring(p) (((gx_device_bjc*) pdev)->ptype == BJC800 ? \
- BJC_BJC800_VERSIONSTR : BJC_BJC600_VERSIONSTR)
- #define bjcthickpaper(l) \
- (bjcparams.mediaWeight_isSet && bjcparams.mediaWeight > l)
- #define bjc600thickpaper() bjcthickpaper(BJC600_MEDIAWEIGHT_THICKLIMIT)
- #define bjc800thickpaper() bjcthickpaper(BJC800_MEDIAWEIGHT_THICKLIMIT)
- /* The basic structure for all printers. Note the presence of the cmyk, depth
- and correct fields even if soem are not used by all printers. */
- #define prn_colour_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page, cmyk, correct)\
- prn_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page), cmyk, depth /* default */, correct
- /* Note: the computation of color_info values here must match */
- /* the computation in the cdj_set_bpp procedure below. */
- #define prn_hp_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
- prn_colour_device_body(dtype, procs, dev_name,\
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
- (bpp == 32 ? 4 : (bpp == 1 || bpp == 8) ? 1 : 3), bpp,\
- (bpp >= 8 ? 255 : 1), (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0),\
- (bpp >= 8 ? 5 : 2), (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0),\
- print_page, 0 /* cmyk */, correct)
- #define prn_cmyk_colour_device(dtype, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correct)\
- prn_colour_device_body(dtype, procs, dev_name,\
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, x_dpi, y_dpi, 0, 0, 0, 0,\
- ((bpp == 1 || bpp == 4) ? 1 : 4), bpp,\
- (bpp > 8 ? 255 : 1), (1 << (bpp >> 2)) - 1, /* max_gray, max_color */\
- (bpp > 8 ? 5 : 2), (bpp > 8 ? 5 : bpp > 1 ? 2 : 0),\
- print_page, 1 /* cmyk */, correct)
- #define bjc_device(dtype, p, d, x, y, b, pp, c) \
- prn_cmyk_colour_device(dtype, p, d, x, y, b, pp, c)
- #define cdj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction, shingling, depletion)\
- { prn_hp_colour_device(gx_device_cdj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, correction),\
- shingling,\
- depletion\
- }
- #define pjxl_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, printqual, rendertype)\
- { prn_hp_colour_device(gx_device_pjxl, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0), \
- printqual,\
- rendertype\
- }
- #define pj_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page)\
- { prn_hp_colour_device(gx_device_pj, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0) }
- #define bjc600_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc, mp) \
- { bjc_device(gx_device_bjc600, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
- t, 0., { mf, mt, mws, mw, pq, dt, cc, pc, mp }\
- }
- #define bjc800_device(procs, dev_name, x_dpi, y_dpi, bpp, print_page, t, mf, mt, mws, mw, pq, dt, cc, pc) \
- { bjc_device(gx_device_bjc800, procs, dev_name, x_dpi, y_dpi, bpp, print_page, 0),\
- t, 0., { mf, mt, mws, mw, pq, dt, cc, pc }\
- }
- #define hp_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
- proc_colour_open,\
- gx_default_get_initial_matrix,\
- gx_default_sync_output,\
- gdev_prn_output_page,\
- gdev_prn_close,\
- gdev_pcl_map_rgb_color,\
- gdev_pcl_map_color_rgb,\
- NULL, /* fill_rectangle */\
- NULL, /* tile_rectangle */\
- NULL, /* copy_mono */\
- NULL, /* copy_color */\
- NULL, /* draw_line */\
- gx_default_get_bits,\
- proc_get_params,\
- proc_put_params\
- }
- #define cmyk_colour_procs(proc_colour_open, proc_get_params, proc_put_params) {\
- proc_colour_open,\
- gx_default_get_initial_matrix,\
- gx_default_sync_output,\
- gdev_prn_output_page,\
- gdev_prn_close,\
- NULL /* map_rgb_color */,\
- gdev_cmyk_map_color_rgb,\
- NULL /* fill_rectangle */,\
- NULL /* tile_rectangle */,\
- NULL /* copy_mono */,\
- NULL /* copy_color */,\
- NULL /* draw_line */,\
- gx_default_get_bits,\
- proc_get_params,\
- proc_put_params,\
- gdev_cmyk_map_cmyk_color\
- }
- private gx_device_procs cdj500_procs =
- hp_colour_procs(dj500c_open, cdj_get_params, cdj_put_params);
- private gx_device_procs cdj550_procs =
- hp_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
- #ifdef USE_CDJ550_CMYK
- private gx_device_procs cdj550cmyk_procs =
- cmyk_colour_procs(dj550c_open, cdj_get_params, cdj_put_params);
- #endif
- private gx_device_procs dnj650c_procs =
- hp_colour_procs(dnj650c_open, cdj_get_params, cdj_put_params);
- private gx_device_procs lj4dith_procs =
- hp_colour_procs(lj4dith_open, cdj_get_params, cdj_put_params);
- private gx_device_procs pj_procs =
- hp_colour_procs(pj_open, gdev_prn_get_params, pj_put_params);
- private gx_device_procs pjxl_procs =
- hp_colour_procs(pjxl_open, pjxl_get_params, pjxl_put_params);
- private gx_device_procs pjxl300_procs =
- hp_colour_procs(pjxl300_open, pjxl_get_params, pjxl_put_params);
- private gx_device_procs bjc_procs =
- cmyk_colour_procs(bjc_open, bjc_get_params, bjc_put_params);
- private gx_device_procs escp_procs =
- hp_colour_procs(escp_open, ep_get_params, ep_put_params);
- gx_device_cdj far_data gs_cdjmono_device =
- cdj_device(cdj500_procs, "cdjmono", 300, 300, 1,
- dj500c_print_page, 4, 0, 1);
- gx_device_cdj far_data gs_cdeskjet_device =
- cdj_device(cdj500_procs, "cdeskjet", 300, 300, 3,
- dj500c_print_page, 4, 2, 1);
- gx_device_cdj far_data gs_cdjcolor_device =
- cdj_device(cdj500_procs, "cdjcolor", 300, 300, 24,
- dj500c_print_page, 4, 2, 1);
- gx_device_cdj far_data gs_cdj500_device =
- cdj_device(cdj500_procs, "cdj500", 300, 300, BITSPERPIXEL,
- dj500c_print_page, 4, 2, 1);
- gx_device_cdj far_data gs_cdj550_device =
- cdj_device(cdj550_procs, "cdj550", 300, 300, BITSPERPIXEL,
- dj550c_print_page, 0, 2, 1);
- #ifdef USE_CDJ550_CMYK
- gx_device_cdj far_data gs_cdj550cmyk_device = {
- prn_cmyk_colour_device(cdj550cmyk_procs, "cdj550cmyk", 300, 300,
- BITSPERPIXEL, dj550c_print_page, 0), 2, 1
- };
- #endif
- gx_device_pj far_data gs_declj250_device =
- pj_device(pj_procs, "declj250", 180, 180, BITSPERPIXEL,
- declj250_print_page);
- gx_device_cdj far_data gs_dnj650c_device =
- cdj_device(dnj650c_procs, "dnj650c", 300, 300, BITSPERPIXEL,
- dnj650c_print_page, 0, 2, 1);
-
- gx_device_cdj far_data gs_lj4dith_device =
- cdj_device(lj4dith_procs, "lj4dith", 600, 600, 8,
- lj4dith_print_page, 4, 0, 1);
- gx_device_pj far_data gs_pj_device =
- pj_device(pj_procs, "pj", 180, 180, BITSPERPIXEL,
- pj_print_page);
- gx_device_pjxl far_data gs_pjxl_device =
- pjxl_device(pjxl_procs, "pjxl", 180, 180, BITSPERPIXEL,
- pjxl_print_page, 0, 0);
- gx_device_pjxl far_data gs_pjxl300_device =
- pjxl_device(pjxl300_procs, "pjxl300", 300, 300, BITSPERPIXEL,
- pjxl300_print_page, 0, 0);
- gx_device_cdj far_data gs_escp_device =
- cdj_device(escp_procs, "escp", 360, 360, 8,
- escp_print_page, 0, 0, 1);
- gx_device_cdj far_data gs_escpc_device =
- cdj_device(escp_procs, "escpc", 360, 360, 24,
- escp_print_page, 0, 0, 1);
- /* Args of bjc drivers are manualFeed, mediaType, printQuality, printColor,
- mediaWeight_isSet, mediaWeight, (monochromePrint) */
- gx_device_bjc600 far_data gs_bjc600_device =
- bjc600_device(
- bjc_procs,
- BJC_BJC600,
- BJC600_DEFAULT_RESOLUTION,
- BJC600_DEFAULT_RESOLUTION,
- BJC600_DEFAULT_BITSPERPIXEL,
- bjc_print_page,
- BJC600,
- BJC600_DEFAULT_MANUALFEED,
- BJC600_DEFAULT_MEDIATYPE,
- BJC600_DEFAULT_SETMEDIAWEIGHT,
- BJC600_DEFAULT_MEDIAWEIGHT,
- BJC600_DEFAULT_PRINTQUALITY,
- BJC600_DEFAULT_DITHERINGTYPE,
- BJC600_DEFAULT_COLORCOMPONENTS,
- BJC600_DEFAULT_PRINTCOLORS,
- BJC600_DEFAULT_MONOCHROMEPRINT);
- gx_device_bjc800 far_data gs_bjc800_device =
- bjc800_device(
- bjc_procs,
- BJC_BJC800,
- BJC800_DEFAULT_RESOLUTION,
- BJC800_DEFAULT_RESOLUTION,
- BJC800_DEFAULT_BITSPERPIXEL,
- bjc_print_page,
- BJC800,
- BJC800_DEFAULT_MANUALFEED,
- BJC800_DEFAULT_MEDIATYPE,
- BJC800_DEFAULT_SETMEDIAWEIGHT,
- BJC800_DEFAULT_MEDIAWEIGHT,
- BJC800_DEFAULT_PRINTQUALITY,
- BJC800_DEFAULT_DITHERINGTYPE,
- BJC600_DEFAULT_COLORCOMPONENTS,
- BJC800_DEFAULT_PRINTCOLORS);
- /* Forward references */
- private int gdev_pcl_mode1compress(P3(const byte *, const byte *, byte *));
- private int hp_colour_open(P2(gx_device *, int));
- private int hp_colour_print_page(P3(gx_device_printer *, FILE *, int));
- private int cdj_put_param_int(P6(gs_param_list *, gs_param_name, int *, int, int, int));
- private uint gdev_prn_rasterwidth(P2(const gx_device_printer *, int));
- private int cdj_put_param_bpp(P5(gx_device *, gs_param_list *, int, int, int));
- private int cdj_set_bpp(P3(gx_device *, int, int));
- private void cdj_expand_line(P5(word *, int, short, int, int));
- private int bjc_fscmyk(P5(byte**, byte*[4][4], int**, int, int));
- /* String parameters manipulation */
- typedef struct {
- const char* p_name;
- int p_value;
- } stringParamDescription;
- private const byte* paramValueToString(P2(const stringParamDescription*, int));
- private int paramStringValue(P4(const stringParamDescription*,
- const byte*, int, int*));
- private int put_param_string(P6(gs_param_list*, const byte*,
- gs_param_string*, const stringParamDescription*, int *, int));
- private int get_param_string(P7(gs_param_list*, const byte*,
- gs_param_string*, const stringParamDescription*, int, bool, int));
- /* Open the printer and set up the margins. */
- private int
- dj500c_open(gx_device *pdev)
- { return hp_colour_open(pdev, DJ500C);
- }
- private int
- dj550c_open(gx_device *pdev)
- { return hp_colour_open(pdev, DJ550C);
- }
- private int
- dnj650c_open(gx_device *pdev)
- { return hp_colour_open(pdev, DNJ650C);
- }
- private int
- lj4dith_open(gx_device *pdev)
- { return hp_colour_open(pdev, LJ4DITH);
- }
- private int
- pjxl300_open(gx_device *pdev)
- { return hp_colour_open(pdev, PJXL300);
- }
- private int
- pj_open(gx_device *pdev)
- { return hp_colour_open(pdev, PJ180);
- }
- private int
- pjxl_open(gx_device *pdev)
- { return hp_colour_open(pdev, PJXL180);
- }
- private int
- escp_open(gx_device *pdev)
- { return hp_colour_open(pdev, ESC_P);
- }
- private int
- bjc_open(gx_device *pdev)
- { return hp_colour_open(pdev, bjc->ptype);
- }
- private int
- hp_colour_open(gx_device *pdev, int ptype)
- { /* Change the margins if necessary. */
- static const float dj_a4[4] = { DESKJET_MARGINS_A4 };
- static const float dj_letter[4] = { DESKJET_MARGINS_LETTER };
- static const float lj4_all[4] = { LJET4_MARGINS };
- static const float pj_all[4] = { PAINTJET_MARGINS };
- static const float dnj_all[4] = { DESIGNJET_MARGINS };
- static const float ep_a4[4] = { ESC_P_MARGINS_A4 };
- static const float ep_letter[4] = { ESC_P_MARGINS_LETTER };
- static float bjc_a3[4] = { BJC_MARGINS_A3 }; /* Not const! */
- static float bjc_letter[4] = { BJC_MARGINS_LETTER }; /* Not const! */
- static float bjc_a4[4] = { BJC_MARGINS_A4 }; /* Not const! */
- const float *m = (float *) 0;
- /* Set up colour params if put_params has not already done so */
- if (pdev->color_info.num_components == 0)
- { int code = cdj_set_bpp(pdev, pdev->color_info.depth,
- pdev->color_info.num_components);
- if ( code < 0 )
- return code;
- }
- switch (ptype) {
- case DJ500C:
- case DJ550C:
- m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? dj_a4 :
- dj_letter);
- break;
- case DNJ650C:
- m = dnj_all;
- break;
- case LJ4DITH:
- m = lj4_all;
- break;
- case PJ180:
- case PJXL300:
- case PJXL180:
- m = pj_all;
- break;
- case ESC_P:
- m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? ep_a4 :
- ep_letter);
- break;
- case BJC600:
- case BJC800:
- switch (gdev_pcl_paper_size(pdev)) {
- case PAPER_SIZE_LEGAL:
- case PAPER_SIZE_LETTER:
- m = bjc_letter;
- break;
- case PAPER_SIZE_A0:
- case PAPER_SIZE_A1:
- case PAPER_SIZE_A3:
- m = bjc_a3;
- break;
- default:
- m = bjc_a4;
- }
- #ifndef USE_FIXED_MARGINS
- if (ptype == BJC800) {
- ((float *) m)[1] = BJC_HARD_LOWER_LIMIT;
- }
- #endif
- bjc->printLimit = m[3]; /* The real hardware limit. */
- #ifdef BJC_DEFAULT_CENTEREDAREA
- if (m[3] < m[1]) {
- ((float *) m)[3] = m[1]; /* Top margin = bottom one. */
- } else {
- ((float *) m)[1] = m[3]; /* Bottom margin = top one. */
- }
- #endif
- break;
- /*NOTREACHED*/
- /*
- * The margins must be set so that the resulting page length will be
- * expressed exactly as a multiple of tenthes of inches.
- *
- */
- /**/ {
- float *bjcm = (float *) m;
- byte pdimen = (byte)
- (pdev->height / pdev->y_pixels_per_inch * 10.
- - bjcm[3] * 10. - bjcm[1] * 10. + .5) + 1;
- do {
- --pdimen;
- bjcm[1] = pdev->height / pdev->y_pixels_per_inch
- - bjcm[3] - (float) pdimen / 10.;
- } while (bjcm[1] < BJC_LOWER_LIMIT);
- }
- break;
- }
- gx_device_set_margins(pdev, m, true);
- return gdev_prn_open(pdev);
- }
- /* Added parameters for DeskJet 5xxC */
- /* Get parameters. In addition to the standard and printer
- * parameters, we supply shingling and depletion parameters,
- * and control over the bits-per-pixel used in output rendering */
- private int
- cdj_get_params(gx_device *pdev, gs_param_list *plist)
- { int code = gdev_prn_get_params(pdev, plist);
- if ( code < 0 ||
- (code = param_write_int(plist, "BlackCorrect", (int *)&cdj->correction)) < 0 ||
- (code = param_write_int(plist, "Shingling", &cdj->shingling)) < 0 ||
- (code = param_write_int(plist, "Depletion", &cdj->depletion)) < 0
- )
- return code;
- return code;
- }
- /* Put parameters. */
- private int
- cdj_put_params(gx_device *pdev, gs_param_list *plist)
- { int correction = cdj->correction;
- int shingling = cdj->shingling;
- int depletion = cdj->depletion;
- int bpp = 0;
- int code = 0;
- code = cdj_put_param_int(plist, "BlackCorrect", &correction, 0, 9, code);
- code = cdj_put_param_int(plist, "Shingling", &shingling, 0, 2, code);
- code = cdj_put_param_int(plist, "Depletion", &depletion, 1, 3, code);
- code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
- if ( code < 0 )
- return code;
- code = cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
- if ( code < 0 )
- return code;
- cdj->correction = correction;
- cdj->shingling = shingling;
- cdj->depletion = depletion;
- return 0;
- }
- /* Added parameters for PaintJet XL and PaintJet XL300 */
- /* Get parameters. In addition to the standard and printer
- * parameters, we supply print_quality and render_type
- * parameters, together with bpp control. */
- private int
- pjxl_get_params(gx_device *pdev, gs_param_list *plist)
- { int code = gdev_prn_get_params(pdev, plist);
- if ( code < 0 ||
- (code = param_write_int(plist, "PrintQuality", &pjxl->printqual)) < 0 ||
- (code = param_write_int(plist, "RenderType", &pjxl->rendertype)) < 0
- )
- return code;
- return code;
- }
- /* Put parameters. */
- private int
- pjxl_put_params(gx_device *pdev, gs_param_list *plist)
- { int printqual = pjxl->printqual;
- int rendertype = pjxl->rendertype;
- int bpp = 0, real_bpp = 0;
- int code = 0;
- code = cdj_put_param_int(plist, "PrintQuality", &printqual, -1, 1, code);
- code = cdj_put_param_int(plist, "RenderType", &rendertype, 0, 10, code);
- code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, code);
- if ( code < 0 )
- return code;
- real_bpp = bpp;
- if ( rendertype > 0 )
- { /* If printer is doing the dithering, we must have a
- * true-colour mode, ie. 16 or 24 bits per pixel */
- if ( bpp > 0 && bpp < 16 )
- real_bpp = 24;
- }
- code = cdj_put_param_bpp(pdev, plist, bpp, real_bpp, 0);
- if ( code < 0 )
- return code;
- pjxl->printqual = printqual;
- pjxl->rendertype = rendertype;
- return 0;
- }
- /* Added parameters for PaintJet */
- /* Put parameters. In addition to the standard and printer */
- /* parameters, we allow control of the bits-per-pixel */
- private int
- pj_put_params(gx_device *pdev, gs_param_list *plist)
- { int bpp = 0;
- int code = cdj_put_param_int(plist, "BitsPerPixel", &bpp, 1, 32, 0);
- if ( code < 0 )
- return code;
- return cdj_put_param_bpp(pdev, plist, bpp, bpp, 0);
- }
- private stringParamDescription bjc_processColorsStrings[] = {
- { "DeviceGray", 1 },
- { "DeviceRGB", 3 },
- { "DeviceCMYK", 4 },
- { 0 }
- };
- private stringParamDescription bjc_mediaTypeStrings[] = {
- { "PlainPaper", BJC_MEDIA_PLAINPAPER },
- { "CoatedPaper", BJC_MEDIA_COATEDPAPER },
- { "TransparencyFilm", BJC_MEDIA_TRANSPARENCYFILM },
- { "Envelope", BJC_MEDIA_ENVELOPE },
- { "Card", BJC_MEDIA_CARD},
- { "Other", BJC_MEDIA_OTHER },
- { 0 }
- };
- private stringParamDescription bjc600_printQualityStrings[] = {
- { "Normal", 0 },
- { "High", 1 },
- { "Draft", 2 },
- { 0 }
- };
- private stringParamDescription bjc800_printQualityStrings[] = {
- { "Normal", 0 },
- { "High", 1 },
- { "Low", 3 },
- { "Draft", 4 },
- { 0 },
- };
- private stringParamDescription bjc_ditheringTypeStrings[] = {
- { "None", BJC_DITHER_NONE },
- { "Floyd-Steinberg", BJC_DITHER_FS },
- { 0 }
- };
- private int
- bjc_get_params(gx_device *pdev, gs_param_list *plist)
- {
- int code = gdev_prn_get_params(pdev, plist);
- int ncode;
- gs_param_string pmedia;
- gs_param_string pquality;
- gs_param_string dithering;
- if (code < 0) return_error(code);
- if ((ncode = param_write_bool(plist, BJC_OPTION_MANUALFEED,
- &bjcparams.manualFeed)) < 0) {
- code = ncode;
- }
- code = get_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
- bjc_mediaTypeStrings, bjcparams.mediaType, true, code);
- code = get_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
- (bjc->ptype == BJC800 ? bjc800_printQualityStrings :
- bjc600_printQualityStrings), bjcparams.printQuality,
- true, code);
- code = get_param_string(plist, (unsigned char *)BJC_OPTION_DITHERINGTYPE, &dithering,
- bjc_ditheringTypeStrings, bjcparams.ditheringType, true, code);
- if ((ncode = param_write_int(plist, BJC_OPTION_PRINTCOLORS,
- &bjcparams.printColors)) < 0) {
- code = ncode;
- }
- if ((ncode = (bjcparams.mediaWeight_isSet ?
- param_write_int(plist, BJC_OPTION_MEDIAWEIGHT,
- &bjcparams.mediaWeight) :
- param_write_null(plist, BJC_OPTION_MEDIAWEIGHT))) < 0) {
- code = ncode;
- }
- if (bjc->ptype != BJC800) {
- if ((ncode = param_write_bool(plist, BJC_OPTION_MONOCHROMEPRINT,
- &bjc600params.monochromePrint)) < 0) {
- code = ncode;
- }
- }
- /**/ {
- float version;
- gs_param_string versionString;
- bool bTrue = true;
- version = bjcversion(pdev);
- versionString.data = (byte *)bjcversionstring(pdev);
-
- versionString.size = strlen((char *)versionString.data);
- versionString.persistent = true;
- if ((ncode = param_write_float(plist, BJC_DEVINFO_VERSION,
- &version)) < 0) {
- code = ncode;
- }
- if ((ncode = param_write_string(plist, BJC_DEVINFO_VERSIONSTRING,
- &versionString)) < 0) {
- code = ncode;
- }
- if ((ncode = param_write_bool(plist, BJC_DEVINFO_OUTPUTFACEUP,
- &bTrue)) < 0) {
- code = ncode;
- }
- }
-
- return code;
- }
- /* Put properties for the bjc drivers. */
- private int
- bjc_put_params(gx_device *pdev, gs_param_list *plist)
- {
- int bpp = 0, ccomps = 0;
- int code = 0;
- int ncode;
- bool aBool = true;
- const char* oname = (const char*) 0;
- bjc600_params new600Params;
- bjc800_params new800Params;
- bjc_params* params;
- gs_param_string pprocesscolors;
- gs_param_string pmedia;
- gs_param_string pquality;
- gs_param_float_array hwra;
- if (bjc->ptype != BJC800) {
- new600Params = bjc600params;
- params = (bjc_params*) &new600Params;
- } else {
- new800Params = bjc800params;
- params = (bjc_params*) &new800Params;
- }
- if ((code = cdj_put_param_int(plist, "BitsPerPixel",
- &bpp, 1, 32, code)) != 1) {
- bpp = pdev->color_info.depth;
- }
- if ((code = put_param_string(plist, (unsigned char *)"ProcessColorModel",
- &pprocesscolors, bjc_processColorsStrings, &ccomps, code)) != 1) {
- ccomps = pdev->color_info.num_components;
- }
- if ((ncode = param_read_bool(plist, oname = BJC_OPTION_MANUALFEED,
- ¶ms->manualFeed)) < 0) {
- param_signal_error(plist, oname, code = ncode);
- }
- code = put_param_string(plist, (unsigned char *)BJC_OPTION_MEDIATYPE, &pmedia,
- bjc_mediaTypeStrings, ¶ms->mediaType, code);
- code = cdj_put_param_int(plist, BJC_OPTION_PRINTCOLORS,
- ¶ms->printColors, 0, 15, code);
- code = put_param_string(plist, (unsigned char *)BJC_OPTION_PRINTQUALITY, &pquality,
- (bjc->ptype == BJC800 ? bjc800_printQualityStrings :
- bjc600_printQualityStrings), ¶ms->printQuality, code);
- switch (ncode = param_read_int(plist,
- oname = BJC_OPTION_MEDIAWEIGHT, ¶ms->mediaWeight)) {
- case 0:
- if (params->mediaWeight <= 0) {
- ncode = gs_error_rangecheck;
- } else {
- params->mediaWeight_isSet = 1;
- break;
- }
- goto mwe;
- default:
- if ((ncode = param_read_null(plist, oname)) == 0) {
- params->mediaWeight_isSet = 0;
- break;
- }
- mwe: param_signal_error(plist, oname, code = ncode);
- case 1:
- break;
- }
- if (bjc->ptype != BJC800) {
- bjc600_params* params600 = (bjc600_params*) params;
- if ((ncode = param_read_bool(plist,
- oname = BJC_OPTION_MONOCHROMEPRINT,
- ¶ms600->monochromePrint)) < 0) {
- param_signal_error(plist, oname, code = ncode);
- }
- }
- if ((ncode = cdj_param_check_float(plist, BJC_DEVINFO_VERSION,
- bjcversion(pdev), true)) < 0) {
- code = ncode;
- }
- if ((ncode = cdj_param_check_string(plist, BJC_DEVINFO_VERSIONSTRING,
- bjcversionstring(pdev), true)) < 0) {
- code = ncode;
- }
- if ((ncode = param_read_bool(plist, oname = BJC_DEVINFO_OUTPUTFACEUP,
- &aBool)) < 0) {
- param_signal_error(plist, oname, code = ncode);
- } else if (aBool != true) {
- param_signal_error(plist, oname, code = ncode = gs_error_rangecheck);
- }
- /* Check for invalid resolution. The array macros are taken from
- gsdparam.c and modified to use oname, ncode and code instead
- of param_name, code and ecode respectively. */
- BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre)
- if ( hwra.data[0] <= 0 || hwra.data[1] <= 0 ||
- hwra.data[0] != hwra.data[1] )
- ncode = gs_error_rangecheck;
- else {
- #ifdef BJC_STRICT
- if (hwra.data[0] != BJC_RESOLUTION_LOW &&
- hwra.data[0] != BJC_RESOLUTION_NORMAL &&
- hwra.data[0] != BJC_RESOLUTION_HIGH) {
- ncode = gs_error_rangecheck;
- }
- #else
- /* A small hack for checking resolution without logarithms. */
- /**/ {
- int n;
- for (n = 0; n < 8 * sizeof(n) / BJC_RESOLUTION_BASE; ++n) {
- float res = BJC_RESOLUTION_BASE * (1 << n);
-
- if (res == hwra.data[0]) break;
-
- if (res > hwra.data[0]) {
- ncode = gs_error_rangecheck;
- }
- }
- if (n == 8 * sizeof(n)) {
- ncode = gs_error_rangecheck;
- }
- }
- #endif
- if (ncode < 0) {
- code = ncode;
- } else {
- break;
- }
- }
- END_PARAM(hwra, hwre)
- if ((ncode = cdj_put_param_bpp(pdev, plist, bpp, bpp, ccomps)) < 0) {
- code = ncode;
- }
- if (code < 0)
- return code;
- if (bpp == 1) {
- params->ditheringType = BJC_DITHER_NONE;
- }
- /* Write values that did change */
- if (bjc->ptype != BJC800) {
- bjc600params = new600Params;
- } else {
- bjc800params = new800Params;
- }
- return code;
- }
- /* ------ Internal routines ------ */
- /* The DeskJet500C can compress (mode 9) */
- private int
- dj500c_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, DJ500C);
- }
- /* The DeskJet550C can compress (mode 9) */
- private int
- dj550c_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, DJ550C);
- }
- /* The DesignJet650C can compress (mode 1) */
- private int
- dnj650c_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, DNJ650C);
- }
- private int
- lj4dith_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, LJ4DITH);
- }
- /* The PJXL300 can compress (modes 2 & 3) */
- private int
- pjxl300_print_page(gx_device_printer * pdev, FILE * prn_stream)
- { int ret_code;
- /* Ensure we're operating in PCL mode */
- fputs("\033%-12345X@PJL enter language = PCL\n", prn_stream);
- ret_code = hp_colour_print_page(pdev, prn_stream, PJXL300);
- /* Reenter switch-configured language */
- fputs("\033%-12345X", prn_stream);
- return ret_code;
- }
- /* The PaintJet XL can compress (modes 2 & 3) */
- private int
- pjxl_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, PJXL180);
- }
- /* The PaintJet can compress (mode 1) */
- private int
- pj_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, PJ180);
- }
- /* The LJ250 can compress (mode 1) */
- private int
- declj250_print_page(gx_device_printer * pdev, FILE * prn_stream)
- { int ret_code;
- fputs("\033%8", prn_stream); /* Enter PCL emulation mode */
- ret_code = hp_colour_print_page(pdev, prn_stream, DECLJ250);
- fputs("\033%@", prn_stream); /* Exit PCL emulation mode */
- return ret_code;
- }
- /* The BJC-600 cannot compress w/o raster image commands. */
- private int
- escp_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, ESC_P);
- }
- /* The BJC-600 can compress w/ raster image commands. */
- private int
- bjc_print_page(gx_device_printer * pdev, FILE * prn_stream)
- {
- return hp_colour_print_page(pdev, prn_stream, bjc->ptype);
- }
- /* MACROS FOR DITHERING (we use macros for compact source and faster code) */
- /* Floyd-Steinberg dithering. Often results in a dramatic improvement in
- * subjective image quality, but can also produce dramatic increases in
- * amount of printer data generated and actual printing time!! Mode 9 2D
- * compression is still useful for fairly flat colour or blank areas but its
- * compression is much less effective in areas where the dithering has
- * effectively randomised the dot distribution. */
- #define SHIFT ((I * 8) - 13)
- #define RSHIFT ((I * 8) - 16)
- #define RANDOM (((rand() << RSHIFT) % (MAXVALUE / 2)) - MAXVALUE / 4);
- #define MINVALUE 0
- #define MAXVALUE (255 << SHIFT)
- #define THRESHOLD (128 << SHIFT)
- #define C 8
- #define FSdither(inP, out, errP, Err, Bit, Offset, Element)\
- oldErr = Err;\
- Err = (errP[Element] + ((Err * 7 + C) >> 4) + ((int)inP[Element] << SHIFT));\
- if (Err > THRESHOLD) {\
- out |= Bit;\
- Err -= MAXVALUE;\
- }\
- errP[Element + Offset] += ((Err * 3 + C) >> 4);\
- errP[Element] = ((Err * 5 + oldErr + C) >> 4);
- /* Here we rely on compiler optimisation to remove lines of the form
- * (if (1 >= 4) {...}, ie. the constant boolean expressions */
- /* The original code is in the #else part. Since by default NEW_DITHER
- is not defined, the old code is used. No enhancement is visible for the
- bjc600 drivers with the new code, anyway :-( */
- #ifdef NEW_DITHER
- #define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
- {\
- if (scan == 0) { /* going_up */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- int oldErr;\
- bitmask = 0x80;\
- for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
- if (n >= 4) {\
- FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
- }\
- if (n >= 3) {\
- FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
- FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
- }\
- FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
- dp += n, ep += n;\
- }\
- if (n >= 4)\
- *kP++ = k;\
- if (n >= 3) {\
- *cP++ = c;\
- *mP++ = m;\
- }\
- *yP++ = y;\
- }\
- } else { /* going_down */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- int oldErr;\
- bitmask = 0x01;\
- for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
- dp -= n, ep -= n;\
- FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
- if (n >= 3) {\
- FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
- FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
- }\
- if (n >= 4) {\
- FSdither(dp, k, ep, kErr, bitmask, n, 0);\
- }\
- }\
- *--yP = y;\
- if (n >= 3)\
- { *--mP = m;\
- *--cP = c;\
- }\
- if (n >= 4)\
- *--kP = k;\
- }\
- }\
- }
- #else
- #define FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr, cP, mP, yP, kP, n)\
- {\
- if (scan == 0) { /* going_up */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- int oldErr;\
- bitmask = 0x80;\
- for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
- if (n >= 4) {\
- if (*dp) {\
- FSdither(dp, k, ep, kErr, bitmask, -n, 0);\
- cErr = mErr = yErr = 0;\
- } else {\
- FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
- FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
- FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
- }\
- } else {\
- if (n >= 3) {\
- FSdither(dp, c, ep, cErr, bitmask, -n, n - 3);\
- FSdither(dp, m, ep, mErr, bitmask, -n, n - 2);\
- }\
- FSdither(dp, y, ep, yErr, bitmask, -n, n - 1);\
- }\
- dp += n, ep += n;\
- }\
- if (n >= 4)\
- *kP++ = k;\
- if (n >= 3) {\
- *cP++ = c;\
- *mP++ = m;\
- }\
- *yP++ = y;\
- }\
- } else { /* going_down */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- int oldErr;\
- bitmask = 0x01;\
- for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
- dp -= n, ep -= n;\
- if (n >= 4) {\
- if (*dp) {\
- FSdither(dp, k, ep, kErr, bitmask, n, 0);\
- cErr = mErr = yErr = 0;\
- } else {\
- FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
- FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
- FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
- }\
- } else {\
- FSdither(dp, y, ep, yErr, bitmask, n, n - 1);\
- if (n >= 3) {\
- FSdither(dp, m, ep, mErr, bitmask, n, n - 2);\
- FSdither(dp, c, ep, cErr, bitmask, n, n - 3);\
- }\
- }\
- }\
- *--yP = y;\
- if (n >= 3)\
- { *--mP = m;\
- *--cP = c;\
- }\
- if (n >= 4)\
- *--kP = k;\
- }\
- }\
- }
- #endif
- /* END MACROS FOR DITHERING */
- #define CPbit(inP, out, Bit, Element)\
- if (inP[Element]) {\
- out |= Bit;\
- }
- #define COPYline(scan, i, j, plane_size, cP, mP, yP, kP, n)\
- {\
- if (scan == 0) { /* going_up */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- bitmask = 0x80;\
- for (c = m = y = k = 0; bitmask != 0; bitmask >>= 1) {\
- if (n >= 4) {\
- CPbit(dp, k, bitmask, 0);\
- } \
- if (n >= 3) {\
- CPbit(dp, c, bitmask, n - 3);\
- CPbit(dp, m, bitmask, n - 2);\
- }\
- CPbit(dp, y, bitmask, n - 1);\
- dp += n, ep += n;\
- }\
- if (n >= 4)\
- *kP++ = k;\
- if (n >= 3) {\
- *cP++ = c;\
- *mP++ = m;\
- }\
- *yP++ = y;\
- }\
- } else { /* going_down */\
- for (i = 0; i < plane_size; i++) {\
- byte c, y, m, k, bitmask;\
- bitmask = 0x01;\
- for (c = m = y = k = 0; bitmask != 0; bitmask <<= 1) {\
- dp -= n, ep -= n;\
- if (n >= 4) {\
- CPbit(dp, k, bitmask, 0);\
- }\
- if (n >= 3) {\
- CPbit(dp, m, bitmask, n - 2);\
- CPbit(dp, c, bitmask, n - 3);\
- }\
- CPbit(dp, y, bitmask, n - 1);\
- }\
- *--yP = y;\
- if (n >= 3)\
- { *--mP = m;\
- *--cP = c;\
- }\
- if (n >= 4)\
- *--kP = k;\
- }\
- }\
- }
- /* Some convenient shorthand .. */
- #define x_dpi (pdev->x_pixels_per_inch)
- #define y_dpi (pdev->y_pixels_per_inch)
- #define CONFIG_16BIT "\033*v6W\000\003\000\005\006\005"
- #define CONFIG_24BIT "\033*v6W\000\003\000\010\010\010"
- /* To calculate buffer size as next greater multiple of both parameter and W */
- #define calc_buffsize(a, b) (((((a) + ((b) * W) - 1) / ((b) * W))) * W)
- /*
- * Miscellaneous functions for Canon BJC-600 printers in raster command mode.
- */
- #define fputshort(n, f) fputc((n)%256,f);fputc((n)/256,f)
- private int
- bjc_cmd(byte cmd, int argsize, byte* arg, gx_device_printer* pdev,
- FILE* stream)
- {
- fputs("\033(", stream);
- putc(cmd, stream);
- fputshort(argsize, stream);
- fwrite(arg, sizeof(byte), argsize, stream);
- return 0;
- }
- private int
- bjc_raster_cmd_sub(char c, int rastsize, byte* data, FILE* stream)
- {
- fputs("\033(A", stream);
- fputshort(rastsize + 1, stream);
- putc(c, stream);
- fwrite(data, sizeof(byte), rastsize, stream);
- putc('\015', stream);
- return 0;
- }
- private int
- bjc_raster_cmd(int c_id, int rastsize, byte* data, gx_device_printer* pdev,
- FILE* stream)
- {
- if (bjcparams.printColors == BJC_COLOR_ALLBLACK) {
- bjc_raster_cmd_sub('K', rastsize, data, stream);
- } else if (pdev->color_info.num_components == 1) {
- if (bjcparams.printColors & BJC_COLOR_BLACK) {
- bjc_raster_cmd_sub('K', rastsize, data, stream);
- } else {
- if (bjcparams.printColors & BJC_COLOR_YELLOW)
- bjc_raster_cmd_sub('Y', rastsize, data, stream);
- if (bjcparams.printColors & BJC_COLOR_MAGENTA)
- bjc_raster_cmd_sub('M', rastsize, data, stream);
- if (bjcparams.printColors & BJC_COLOR_CYAN)
- bjc_raster_cmd_sub('C', rastsize, data, stream);
- }
- }else { /* Color decomposition */
- private byte ymckCodes[] = {
- BJC_COLOR_YELLOW,
- BJC_COLOR_MAGENTA,
- BJC_COLOR_CYAN,
- BJC_COLOR_BLACK,
- };
- if (bjcparams.printColors & (int) ymckCodes[c_id]) {
- bjc_raster_cmd_sub("YMCK"[c_id], rastsize, data, stream);
- }
- }
- return 0;
- }
- private int
- bjc_init_page(gx_device_printer* pdev, FILE* stream)
- {
- byte pagemargins[3], resolution[4], paperloading[2];
- /* Compute page margins. */
- pagemargins[0] = (byte) ((float) pdev->height / pdev->y_pixels_per_inch
- * 10 + .5);
- pagemargins[1] = (byte) 1;
- pagemargins[2] = (byte) ((pdev->width / pdev->x_pixels_per_inch * 10) -
- pdev->HWMargins[0] / 7.2 - pdev->HWMargins[2] / 7.2 + .5);
- /* Cheat to keep margins into bounds (while waiting to have the right
- margins for big papers. */
- switch (bjc->ptype) {
- case BJC800:
- if (pagemargins[2] > 114) pagemargins[2] = 114;
- break;
- default:
- if (pagemargins[2] > 80) pagemargins[2] = 80;
- break;
- }
- /* Initialize resolution argument. */
- resolution[0] = (byte) ((int)pdev->y_pixels_per_inch / 256);
- resolution[1] = (byte) ((int)pdev->y_pixels_per_inch % 256);
- resolution[2] = (byte) ((int)pdev->x_pixels_per_inch / 256);
- resolution[3] = (byte) ((int)pdev->x_pixels_per_inch % 256);
- /* Initialize paper loading argument. */
- paperloading[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
- paperloading[1] = bjcparams.mediaType << 4;
- /* Reinitialize printer in raster mode. */
- fputs("\033[K", stream);
- fputshort(2, stream);
- fputc(0x00, stream);
- fputc(0x0f, stream);
- /* Set page mode on (ignore data at end of page) */
- bjc_cmd('a', 1, (byte*) "\001", pdev, stream);
- /* Set page margins */
- bjc_cmd('g', 3, pagemargins, pdev, stream);
- /* Set compression on (this is PackBits compression a la TIFF/Mac) */
- bjc_cmd('b', 1, (byte*) "\001", pdev, stream);
- /* Set paper loading. */
- bjc_cmd('l', 2, paperloading, pdev, stream);
- /* Set printing method. */
- #ifndef BJC_INIT_800_AS_600
- if (bjc->ptype == BJC800) {
- #else
- if (0) {
- #endif
- byte printmode[2];
- printmode[0] = bjcparams.printQuality;
- /* Modes not used are 3 (CN, Color Normal) and 2 (TP+ (?)) */
- switch (bjcparams.printQuality) {
- case BJC_QUALITY_DRAFT:
- printmode[0] = 4; /* Draft */
- break;
- }
- printmode[1] = (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
- bjc800thickpaper());
- bjc_cmd('c', 2, printmode, pdev, stream);
- } else /* BJC600 */ {
- byte printmeth[3];
- printmeth[0] = 0x10 + ((1 - bjcparams.manualFeed) << 2);
- printmeth[1] = (bjcparams.mediaType << 4) + bjcparams.printQuality;
- printmeth[2] = (bjcparams.printQuality == BJC_QUALITY_HIGH ?
- 0x10 : 0) + (bjcparams.mediaType >= BJC_MEDIA_ENVELOPE ? 1 :
- bjc600thickpaper());
- bjc_cmd('c', 3, printmeth, pdev, stream);
- }
- /* Set raster resolution */
- bjc_cmd('d', 4, resolution, pdev, stream);
- return 0;
- }
- private int
- bjc_v_skip(int n, gx_device_printer* pdev, FILE* stream)
- {
- if (n) {
- fputs("\033(e", stream);
- putc(2, stream);
- putc(0, stream);
- putc(n / 256, stream);
- putc(n % 256, stream);
- }
- return 0;
- }
- private int
- bjc_finish_page(gx_device_printer* pdev, FILE* stream)
- {
- bjc_cmd('a', 1, (byte*) "\000", pdev, stream);
- bjc_cmd('b', 1, (byte*) "\000", pdev, stream);
- fputc('\014', stream);
- fputs("\033@", stream);
- return 0;
- }
- /* 1D runlength compression for BJC-600
- * this code is borrowed from gdevpcl.c:gdev_pcl_mode2compress.
- */
- private int
- bjc_compress(const byte *row, const byte *end_row, byte *compressed)
- {
- register const byte *exam = row;
- register byte *cptr = compressed; /* output pointer into compressed bytes */
-
- while ( exam < end_row ) {
- /* Search ahead in the input looking for a run */
- /* of at least 4 identical bytes. */
- const byte *compr = exam;
- const byte *end_dis;
- const byte *next;
- register byte test, test2;
- test = *exam;
- while ( exam < end_row ) {
- test2 = *++exam;
- if ( test == test2 )
- break;
- test = test2;
- }
-
- /* Find out how long the run is */
- end_dis = exam - 1;
- if ( exam == end_row ) { /* no run */
- next = --end_row;
- } else {
- next = exam + 1;
- while ( next < end_row && *next == test ) next++;
- }
-
- /* Now [compr..end_dis) should be encoded as dissimilar, */
- /* and [end_dis..next) should be encoded as similar. */
- /* Note that either of these ranges may be empty. */
-
- for ( ; ; ) { /* Encode up to 128 dissimilar bytes */
- uint count = end_dis - compr; /* uint for faster switch */
- switch ( count ) { /* Use memcpy only if it's worthwhile. */
- case 6: cptr[6] = compr[5];
- case 5: cptr[5] = compr[4];
- case 4: cptr[4] = compr[3];
- case 3: cptr[3] = compr[2];
- case 2: cptr[2] = compr[1];
- case 1: cptr[1] = compr[0];
- *cptr = count - 1;
- cptr += count + 1;
- case 0: /* all done */
- break;
- default:
- if ( count > 128 ) count = 128;
- *cptr++ = count - 1;
- memcpy(cptr, compr, count);
- cptr += count, compr += count;
- continue;
- }
- break;
- }
-
- { /* Encode up to 128 similar bytes. */
- /* Note that count may be <0 at end of row. */
- int count = next - end_dis;
- if (next < end_row || test != 0)
- while ( count > 0 ) {
- int this = (count > 128 ? 128 : count);
- *cptr++ = 257 - this;
- *cptr++ = (byte)test;
- count -= this;
- }
- exam = next;
- }
- }
- return cptr - compressed;
- }
- /*
- * For the ESC/P mode, resolution is fixed as 360dpi and we must transform
- * image data to serialized data.
- */
- private word *ep_storage;
- private uint ep_storage_size_words;
- private byte *ep_raster_buf[4][BJC_HEAD_ROWS], *ep_print_buf;
- private int ep_num_comps, ep_plane_size, img_rows=BJC_HEAD_ROWS;
- #define row_bytes (img_rows / 8)
- #define row_words (row_bytes / sizeof(word))
- #define min_rows (32) /* for optimization of text image printing */
- private int
- ep_print_image(FILE *prn_stream, char cmd, byte *data, int size)
- {
- static int ln_idx=0, vskip1=0, vskip2=0, real_rows;
- int i;
- static const char color[4] = {4,1,2,0};
- switch (cmd) {
- case 3: /* Black */
- case 2: /* Cyan */
- case 1: /* Magenta */
- case 0: /* Yellow */
- memcpy(ep_raster_buf[((int) cmd)][ln_idx+vskip2], data, size);
- return 0;
- case 'B': /* blank line skip */
- if (!ln_idx) {
- vskip1 += size;
- } else if (size >= img_rows - (ln_idx+vskip2) || ln_idx+vskip2 >= min_rows) {
- /* The 'I' cmd must precede 'B' cmd! */
- vskip2 += size;
- ep_print_image(prn_stream, 'F', 0, 0); /* flush and reset status */
- } else {
- vskip2 += size;
- }
- return 0;
- case 'I': /* Increment index */
- ln_idx += vskip2 + 1;
- vskip2 = 0;
- if (ln_idx < img_rows) return 0;
- /* if ep_raster_buf filled up, then fall through here and flush buffer */
- case 'F': /* flush print buffer */
- if (!ln_idx) return 0; /* The end of the page. */
- /* before print the image, perform vertical skip. */
- while (vskip1 >= (255*2)) {
- fputs("\033J\377", prn_stream); /* n/180in. feeding */
- vskip1 -= (255*2);
- }
- if (vskip1 > 255) {
- fputs("\033J\200", prn_stream);
- vskip1 -= 256;
- }
- if (vskip1) {
- /* n/360in. feeding */
- fputs("\033|J", prn_stream); putc(0, prn_stream); putc(vskip1, prn_stream);
- }
- /* Optimize the number of nozzles to be used. */
- if (ln_idx > 56) { /* use 64 nozzles */
- real_rows = 64;
- } else if (ln_idx > 48) { /* use 56 nozzles */
- real_rows = 56;
- } else if (ln_idx > 32) { /* use 48 nozzles */
- real_rows = 48;
- } else { /* use 32 nozzles */
- real_rows = 32;
- }
- for (i = 0; i < ep_num_comps; i++) {
- int lnum, hskip, print_size, img_rows;
- byte *p0, *p1, *p2, *p3;
- byte *inp, *inbuf, *outp, *outbuf;
- img_rows = real_rows; /* Note that this img_rows is not the one that
- * defined out of this function. */
- outbuf = ep_print_buf;
- /* Transpose raster image for serial printer image */
- for (lnum=0; lnum < img_rows; lnum+=8, outbuf++) {
- inbuf = inp = ep_raster_buf[i][lnum];
- for (outp = outbuf; inp < inbuf+ep_plane_size; inp++, outp += img_rows) {
- memflip8x8(inp, ep_plane_size, outp, row_bytes);
- }
- }
- /* Set color */
- if (ep_num_comps == 1) {
- /* Don't set color (to enable user setting). */
- putc('\015', prn_stream);
- } else {
- /* set color to one of CMYK. */
- fputs("\015\033r", prn_stream);
- putc(color[i], prn_stream);
- }
- *(outp = ep_print_buf + ep_plane_size * img_rows) = 1; /* sentinel */
- p0 = p3 = ep_print_buf;
- /* print image p0 to p1 and h skip p1 to p2 if p2<outp,
- * then make p0=p2 and continue */
- while (p0 < outp) {
- static const word zeros[8] = {0,0,0,0,0,0,0,0};
- if (p3 < outp) {
- /* p1 is the head of running zeros. */
- /* note that h skip unit is 1/180inch */
- for (p1 = p3; !memcmp(p3, zeros, row_bytes*2); p3 += row_bytes*2);
- /* p2 is the head of non zero image. */
- p2 = p3;
- redo:
- for (p3 += row_bytes; memcmp(p3, zeros, row_bytes); p3 += row_bytes);
- if (p3 < outp && memcmp(p3+row_bytes, zeros, row_bytes)) goto redo;
- } else p1 = p2 = outp;
- if (p0 < p1) { /* print the image between p0 and p1 */
- print_size = ((p1 < outp) ? p1 : outp) - p0;
- fputs("\033|B", prn_stream); putc(img_rows, prn_stream);
- fputshort(print_size, prn_stream);
- fwrite(p0, sizeof(byte), print_size, prn_stream);
- }
- if (p1 < p2) { /* skip running zeros from p1 to p2 */
- hskip = (((p2 < outp) ? p2 : outp) - p1) / row_bytes / 2;
- fputs("\033\\", prn_stream);
- fputshort(hskip, prn_stream);
- }
- p0 = p2;
- }
- }
- return ep_print_image(prn_stream, 'R', 0, vskip2 + ln_idx);
- case 'R': /* Reset status */
- ln_idx = 0;
- vskip1 = size;
- vskip2 = 0;
- memset(ep_storage, 0, ep_storage_size_words * W);
- return 0;
- default: /* This should not happen */
- errprintf("ep_print_image: illegal command character `%c'.\n", cmd);
- return 1;
- }
- /* NOT REACHED */
- }
- /* Send the page to the printer. Compress each scan line. */
- private int
- hp_colour_print_page(gx_device_printer * pdev, FILE * prn_stream, int ptype)
- {
- uint raster_width = gdev_prn_rasterwidth(pdev, 1);
- /* int line_size = gdev_prn_rasterwidth(pdev, 0); */
- int line_size = gdev_prn_raster(pdev);
- int line_size_words = (line_size + W - 1) / W;
- int paper_size = gdev_pcl_paper_size((gx_device *)pdev);
- int num_comps = pdev->color_info.num_components;
- int bits_per_pixel = pdev->color_info.depth;
- int storage_bpp = bits_per_pixel;
- int expanded_bpp = bits_per_pixel;
- int plane_size, databuff_size;
- int combined_escapes = 1;
- int errbuff_size = 0;
- int outbuff_size = 0;
- int compression = 0;
- int scan = 0;
- int *errors[2];
- const char *cid_string = (const char*) 0;
- byte *data[4], *plane_data[4][4], *out_data;
- byte *out_row, *out_row_alt;
- word *storage;
- uint storage_size_words;
- /* Tricks and cheats ... */
- switch (ptype) {
- case DJ550C:
- if (num_comps == 3 && !cprn_device->cmyk)
- num_comps = 4; /* 4-component printing */
- break;
- case ESC_P:
- if (bits_per_pixel == 24) /* prefer 3-component printing for bpp=24. */
- num_comps = 3;
- else
- if (num_comps != 1)
- num_comps = 4;
- break;
- case PJXL300:
- case PJXL180:
- if (pjxl->rendertype > 0) {
- if (bits_per_pixel < 16)
- pjxl->rendertype = 0;
- else {
- /* Control codes for CID sequence */
- cid_string = (bits_per_pixel == 16) ? CONFIG_16BIT : CONFIG_24BIT;
- /* Pretend we're a monobit device so we send the data out unchanged */
- bits_per_pixel = storage_bpp = expanded_bpp = 1;
- num_comps = 1;
- }
- }
- break;
- }
- if (cprn_device->cmyk <= 0) {
- if (storage_bpp == 8 && num_comps >= 3)
- bits_per_pixel = expanded_bpp = 3; /* Only 3 bits of each byte used */
- }
- plane_size = calc_buffsize(line_size, storage_bpp);
- ep_plane_size = plane_size;
- if (bits_per_pixel == 1) { /* Data printed direct from i/p */
- databuff_size = 0; /* so no data buffer required, */
- outbuff_size = plane_size * 4; /* but need separate output buffers */
- }
-
- if (bits_per_pixel > 4) { /* Error buffer for FS dithering */
- storage_bpp = expanded_bpp =
- num_comps * 8; /* 8, 24 or 32 bits */
- if (cprn_device->cmyk > 0) { /* Use CMYK dithering algorithm. */
- errbuff_size = 4 * (5 + 1 + 1 + line_size + 1 + 2) * I;
- } else { /* Use original (RGB) dithering. */
- errbuff_size = /* 4n extra values for line ends */
- calc_buffsize((plane_size * expanded_bpp + num_comps * 4) * I, 1);
- }
- }
- databuff_size = plane_size * storage_bpp;
- storage_size_words = ((plane_size + plane_size) * num_comps +
- databuff_size + errbuff_size + outbuff_size) / W;
- storage = (ulong *) gs_malloc(storage_size_words, W, "hp_colour_print_page");
- ep_storage_size_words = (plane_size * (num_comps + 1)) / W * img_rows
- + 16; /* Redundant space for sentinel and aligning. */
- ep_storage = (word *) gs_malloc(ep_storage_size_words, W, "ep_print_buffer");
- /*
- * The principal data pointers are stored as pairs of values, with
- * the selection being made by the 'scan' variable. The function of the
- * scan variable is overloaded, as it controls both the alternating
- * raster scan direction used in the Floyd-Steinberg dithering and also
- * the buffer alternation required for line-difference compression.
- *
- * Thus, the number of pointers required is as follows:
- *
- * errors: 2 (scan direction only)
- * data: 4 (scan direction and alternating buffers)
- * plane_data: 4 (scan direction and alternating buffers)
- */
- if (storage == 0 || ep_storage == 0) /* can't allocate working area */
- return_error(gs_error_VMerror);
- else {
- int i, j;
- byte *p = out_data = out_row = (byte *)storage;
- byte *ep_p = (byte *)ep_storage;
- data[0] = data[1] = data[2] = p;
- data[3] = p + databuff_size;
- out_row_alt = out_row + plane_size * 2;
- if (bits_per_pixel > 1) {
- p += databuff_size;
- }
- if (bits_per_pixel > 4) {
- errors[0] = (int *)p + num_comps * 2;
- errors[1] = errors[0] + databuff_size;
- p += errbuff_size;
- }
- for (i = 0; i < num_comps; i++) {
- plane_data[0][i] = plane_data[2][i] = p;
- p += plane_size;
- }
- for (i = 0; i < num_comps; i++) {
- plane_data[1][i] = p;
- plane_data[3][i] = p + plane_size;
- p += plane_size;
- }
- if (bits_per_pixel == 1) {
- out_data = out_row = p; /* size is outbuff_size * 4 */
- out_row_alt = out_row + plane_size * 2;
- data[1] += databuff_size; /* coincides with plane_data pointers */
- data[3] += databuff_size;
- }
- for (i = 0; i < num_comps; i++) {
- for (j = 0; j < img_rows; j++) {
- ep_raster_buf[i][j] = ep_p;
- ep_p += plane_size;
- }
- /* Make a sentinel and align to word size. */
- ep_print_buf = (byte *)((word)(ep_p + sizeof(word)) & ~(sizeof(word)-1));
- }
- ep_num_comps = num_comps;
- }
-
- /* Initialize printer. */
- if (ptype == BJC600 || ptype == BJC800) {
- bjc_init_page(pdev, prn_stream);
- } else {
- if (ptype == LJ4DITH) {
- fputs("\033*rB", prn_stream);
- } else {
- fputs("\033*rbC", prn_stream); /* End raster graphics */
- }
- fprintf(prn_stream, "\033*t%dR", (int)x_dpi);
- /* Set resolution */
- }
-
- /* Clear temp storage */
- memset(storage, 0, storage_size_words * W);
- #define DOFFSET (dev_t_margin(pdev) - DESKJET_PRINT_LIMIT) /* Print position */
- #define POFFSET (dev_t_margin(pdev) - PAINTJET_PRINT_LIMIT)
- #define EOFFSET (dev_t_margin(pdev) - ESC_P_PRINT_LIMIT)
- #define BOFFSET (dev_t_margin(pdev) - bjc->printLimit)
- switch (ptype) {
- case LJ4DITH:
- /* Page size, orientation, top margin & perforation skip */
- fprintf(prn_stream, "\033&l26A\033&l0o0e0L\033*r0F" );
- fprintf(prn_stream, "\033*p0x0Y" ); /* These Offsets are hacked ! */
- fprintf(prn_stream, "\033&u600D\033*r1A" );
- /* Select data compression */
- compression = 3;
- combined_escapes = 0;
- break;
- case DJ500C:
- case DJ550C:
- /* Page size, orientation, top margin & perforation skip */
- fprintf(prn_stream, "\033&l%daolE", paper_size);
- /* Set depletion and shingling levels */
- fprintf(prn_stream, "\033*o%dd%dQ", cdj->depletion, cdj->shingling);
- /* Move to top left of printed area */
- fprintf(prn_stream, "\033*p%dY", (int)(300 * DOFFSET));
- /* Set number of planes ((-)1 is mono, (-)3 is (cmy)rgb, -4 is cmyk),
- * and raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
- /* Select data compression */
- compression = 9;
- break;
- case DNJ650C:
- if (pdev->x_pixels_per_inch == 600) {
- /* set resolution to 600dpi 1st through PJL command */
- fprintf(prn_stream,"\033%%-12345X@PJL SET RESOLUTION = 600\n");
- }
- fprintf (prn_stream, "\033%%0B"); /* Enter HPGL/2 mode */
- fprintf (prn_stream, "BP5,1"); /* Turn off autorotation */
- fprintf (prn_stream, "PS%d,%d",
- (int)((pdev->height/pdev->y_pixels_per_inch)*1016),
- (int)((pdev->width/pdev->x_pixels_per_inch)*1016)); /* Set length/width of page */
- fprintf (prn_stream, "PU"); /* Pen up */
- fprintf (prn_stream, "PA%d,%d", 0, 0); /* Move pen to upper-left */
- fprintf (prn_stream, "\033%%1A"); /* Enter HP-RTL mode */
- fprintf (prn_stream, "\033&a1N"); /* No negative motion - allow plotting
- while receiving */
- if (pdev->x_pixels_per_inch == 600)
- fprintf (prn_stream, "\033*t600R"); /* request 600dpi via HP RTL */
- { static const char temp[] = {
- 033, '*', 'v', '6', 'W',
- 000 /* color model */,
- 000 /* pixel encoding mode */,
- 003 /* number of bits per index */,
- 010 /* bits red */,
- 010 /* bits green */,
- 010 /* bits blue */
- };
- fwrite (temp, 1, sizeof(temp), prn_stream);
- }
- /* Set raster width */
- fprintf(prn_stream, "\033*r%dS", raster_width);
- /* Start raster graphics */
- fprintf(prn_stream, "\033*r1A");
- /* Select data compression */
- compression = 1;
- /* No combined escapes for raster transfers */
- combined_escapes = 0;
- break;
- case PJXL300:
- /* Page size, orientation, top margin & perforation skip */
- fprintf(prn_stream, "\033&l%daolE", paper_size);
- /* Set no-negative-motion mode, for faster (unbuffered) printing */
- fprintf(prn_stream, "\033&a1N");
- /* Set print quality */
- fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
- /* Move to top left of printed area */
- fprintf(prn_stream, "\033*p%dY", (int)(300 * POFFSET));
- /* Configure colour setup */
- if (pjxl->rendertype > 0) {
- /* Set render type */
- fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
- /* Configure image data */
- fputs(cid_string, prn_stream);
- /* Set raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds1A", raster_width);
- } else {
- /* Set number of planes (1 is mono, 3 is rgb),
- * and raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds-%du0A", raster_width, num_comps);
- }
- /* No combined escapes for raster transfers */
- combined_escapes = 0;
- break;
- case PJXL180:
- /* Page size, orientation, top margin & perforation skip */
- fprintf(prn_stream, "\033&l%daolE", paper_size);
- /* Set print quality */
- fprintf(prn_stream, "\033*o%dQ", pjxl->printqual);
- /* Move to top left of printed area */
- fprintf(prn_stream, "\033*p%dY", (int)(180 * POFFSET));
- /* Configure colour setup */
- if (pjxl->rendertype > 0) {
- /* Set render type */
- fprintf(prn_stream, "\033*t%dJ", pjxl->rendertype);
- /* Configure image data */
- fputs(cid_string, prn_stream);
- /* Set raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds1A", raster_width);
- } else {
- /* Set number of planes (1 is mono, 3 is rgb),
- * and raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
- }
- break;
- case PJ180:
- case DECLJ250:
- /* Disable perforation skip */
- fprintf(prn_stream, "\033&lL");
- /* Move to top left of printed area */
- fprintf(prn_stream, "\033&a%dV", (int)(720 * POFFSET));
- /* Set number of planes (1 is mono, 3 is rgb),
- * and raster width, then start raster graphics */
- fprintf(prn_stream, "\033*r%ds%du0A", raster_width, num_comps);
- if (ptype == DECLJ250) {
- /* No combined escapes for raster transfers */
- combined_escapes = 0;
- /* From here on, we're a standard Paintjet .. */
- ptype = PJ180;
- }
- /* Select data compression */
- compression = 1;
- break;
- case ESC_P:
- /* Move to top left of printed area (must be modified for large movement(YK))*/
- if ((int)(EOFFSET*360)) fprintf(prn_stream, "\033|J%c%c", 0, (int)(360*EOFFSET));
- combined_escapes = 0;
- break;
- case BJC600:
- case BJC800:
- /* Move to top left of printed area */
- bjc_v_skip((int)(pdev->HWResolution[1] * BOFFSET), pdev, prn_stream);
- combined_escapes = 0;
- compression = 2; /* BJC600 uses the same method as mode 2 compression */
- break;
- }
- /* Unfortunately, the Paintjet XL300 PCL interpreter introduces a
- * version of the PCL language which is different to all earlier HP
- * colour and mono inkjets, in that it loses the very useful ability
- * to use combined escape sequences with the raster transfer
- * commands. In this respect, it is incompatible even with the older
- * 180 dpi PaintJet and PaintJet XL printers! Another regrettable
- * omission is that 'mode 9' compression is not supported, as this
- * mode can give both computational and PCL file size advantages. */
- if (combined_escapes) {
- /* From now on, all escape commands start with \033*b, so we
- * combine them (if the printer supports this). */
- fputs("\033*b", prn_stream);
- /* Set compression if the mode has been defined. */
- if (compression)
- fprintf(prn_stream, "%dm", compression);
- }
- else if (ptype == BJC600 || ptype == BJC800)
- ; /* Currently, nothing to do. */
- else
- if (compression)
- fprintf(prn_stream, "\033*b%dM", compression);
- /* Send each scan line in turn */
- {
- int cErr, mErr, yErr, kErr;
- int this_pass, lnum, i;
- int start_rows;
- int lend, num_blank_lines = 0;
- word rmask = ~(word) 0 << ((-pdev->width * storage_bpp) & (W * 8 - 1));
- lend = pdev->height - (dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi;
- switch (ptype) {
- case BJC600:
- case BJC800:
- start_rows = BJC_HEAD_ROWS;
- break;
- /* Inhibit blank line printing for RGB-only printers, since in
- * this case 'blank' means black! Also disabled for XL300 due to
- * an obscure bug in the printer's firmware */
- case PJ180:
- case PJXL180:
- case PJXL300:
- start_rows = -1;
- break;
- default:
- start_rows = (num_comps == 1) ? HEAD_ROWS_MONO - 1 :
- HEAD_ROWS_COLOUR - 1;
- break;
- }
- cErr = mErr = yErr = kErr = 0;
- if (bits_per_pixel > 4) { /* Randomly seed initial error buffer */
- if (cprn_device->cmyk > 0 && expanded_bpp == 32) {
- bjc_fscmyk(data, plane_data, errors, plane_size, -1);
- } else {
- int *ep = errors[0];
- for (i = 0; i < databuff_size; i++) {
- *ep++ = RANDOM;
- }
- }
- }
- this_pass = start_rows;
- for (lnum = 0; lnum < lend; lnum++) {
- word *data_words = (word *)data[scan];
- register word *end_data = data_words + line_size_words;
- gdev_prn_copy_scan_lines(pdev, lnum, data[scan], line_size);
- /* Mask off 1-bits beyond the line width. */
- end_data[-1] &= rmask;
- /* Remove trailing 0s. */
- while (end_data > data_words && end_data[-1] == 0)
- end_data--;
- if (ptype != DNJ650C) /* DesignJet can't skip blank lines ? ? */
- if (end_data == data_words) { /* Blank line */
- num_blank_lines++;
- continue;
- }
- /* Skip blank lines if any */
- if (num_blank_lines > 0) {
- if (ptype == ESC_P) {
- ep_print_image(prn_stream, 'B', 0, num_blank_lines);
- } else if (ptype == BJC600 || ptype == BJC800) {
- bjc_v_skip(num_blank_lines, pdev, prn_stream);
- } else if (num_blank_lines < this_pass) {
- /* Moving down from current position
- * causes head motion on the DeskJets, so
- * if the number of lines is within the
- * current pass of the print head, we're
- * better off printing blanks. */
- this_pass -= num_blank_lines;
- if (combined_escapes) {
- fputc('y', prn_stream); /* Clear current and seed rows */
- for (; num_blank_lines; num_blank_lines--)
- fputc('w', prn_stream);
- } else {
- #if 0
- /**************** The following code has been proposed ****************/
- /**************** as a replacement: ****************/
- fputs("\033*b1Y", prn_stream); /* Clear current and seed rows */
- if ( num_blank_lines > 1 )
- fprintf(prn_stream, "\033*b%dY", num_blank_lines - 1);
- num_blank_lines = 0;
- #else
- fputs("\033*bY", prn_stream); /* Clear current and seed rows */
- if (ptype == DNJ650C) {
- fprintf (prn_stream, "\033*b%dY", num_blank_lines);
- num_blank_lines = 0;
- }
- else {
- for (; num_blank_lines; num_blank_lines--)
- fputs("\033*bW", prn_stream);
- }
- #endif
- }
- } else {
- if (combined_escapes)
- fprintf(prn_stream, "%dy", num_blank_lines);
- else
- fprintf(prn_stream, "\033*b%dY", num_blank_lines);
- }
- memset(plane_data[1 - scan][0], 0, plane_size * num_comps);
- num_blank_lines = 0;
- this_pass = start_rows;
- }
- { /* Printing non-blank lines */
- register byte *kP = plane_data[scan + 2][3];
- register byte *cP = plane_data[scan + 2][2];
- register byte *mP = plane_data[scan + 2][1];
- register byte *yP = plane_data[scan + 2][0];
- register byte *dp = data[scan + 2];
- register int *ep = errors[scan];
- int zero_row_count;
- int i, j;
- byte *odp;
- if (this_pass)
- this_pass--;
- else
- this_pass = start_rows;
- if (expanded_bpp > bits_per_pixel) { /* Expand line if required */
- cdj_expand_line(data_words, line_size,
- cprn_device->cmyk,
- bits_per_pixel, expanded_bpp);
- }
- /* In colour modes, we have some bit-shuffling to do before
- * we can print the data; in FS mode we also have the
- * dithering to take care of. */
- switch (expanded_bpp) { /* Can be 1, 3, 8, 24 or 32 */
- case 3:
- /* Transpose the data to get pixel planes. */
- for (i = 0, odp = plane_data[scan][0]; i < databuff_size;
- i += 8, odp++) { /* The following is for 16-bit
- * machines */
- #define spread3(c)\
- { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
- static ulong spr40[8] = spread3(0x40);
- static ulong spr08[8] = spread3(8);
- static ulong spr02[8] = spread3(2);
- register byte *dp = data[scan] + i;
- register ulong pword =
- (spr40[dp[0]] << 1) +
- (spr40[dp[1]]) +
- (spr40[dp[2]] >> 1) +
- (spr08[dp[3]] << 1) +
- (spr08[dp[4]]) +
- (spr08[dp[5]] >> 1) +
- (spr02[dp[6]]) +
- (spr02[dp[7]] >> 1);
- odp[0] = (byte) (pword >> 16);
- odp[plane_size] = (byte) (pword >> 8);
- odp[plane_size * 2] = (byte) (pword);
- }
- break;
- case 8:
- switch (ptype) {
- case BJC600:
- case BJC800:
- if (bjcparams.ditheringType == BJC_DITHER_NONE) {
- COPYline(scan, i, j, plane_size, cP, mP, yP, kP, 1);
- break;
- }
- default:
- FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
- cP, mP, yP, kP, 1);
- }
- break;
- case 24:
- FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
- cP, mP, yP, kP, 3);
- break;
- case 32:
- if (cprn_device->cmyk > 0) {
- bjc_fscmyk(data, plane_data, errors, plane_size, scan);
- } else {
- FSDline(scan, i, j, plane_size, cErr, mErr, yErr, kErr,
- cP, mP, yP, kP, 4);
- }
- break;
- } /* switch(expanded_bpp) */
- /* Make sure all black is in the k plane */
- if (num_comps == 4 && (cprn_device->cmyk <= 0 || expanded_bpp != 32)) {
- register word *kp = (word *)plane_data[scan][3];
- register word *cp = (word *)plane_data[scan][2];
- register word *mp = (word *)plane_data[scan][1];
- register word *yp = (word *)plane_data[scan][0];
- if (bits_per_pixel > 4) { /* Done as 4 planes */
- for (i = 0; i < plane_size / W; i++) {
- word bits = *cp & *mp & *yp;
- *kp++ |= bits;
- bits = ~bits;
- *cp++ &= bits;
- *mp++ &= bits;
- *yp++ &= bits;
- }
- } else { /* This has really been done as 3 planes */
- for (i = 0; i < plane_size / W; i++) {
- word bits = *cp & *mp & *yp;
- *kp++ = bits;
- bits = ~bits;
- *cp++ &= bits;
- *mp++ &= bits;
- *yp++ &= bits;
- }
- }
- }
- /* Transfer raster graphics in the order (K), C, M, Y */
- for (zero_row_count = 0, i = num_comps - 1; i >= 0; i--) {
- int output_plane = 1;
- int out_count = 0;
-
- switch (ptype) {
- case DJ500C: /* Always compress using mode 9 */
- case DJ550C:
- out_count = gdev_pcl_mode9compress(plane_size,
- plane_data[scan][i],
- plane_data[1 - scan][i],
- out_data);
- /* This optimisation allows early termination of the
- * row, but this doesn't work correctly in an alternating
- * mode 2 / mode 3 regime, so we only use it with mode 9
- * compression */
- if (out_count == 0)
- { output_plane = 0; /* No further output for this plane */
- if (i == 0)
- fputc('w', prn_stream);
- else
- zero_row_count++;
- }
- else
- { for (; zero_row_count; zero_row_count--)
- fputc('v', prn_stream);
- }
- break;
- case PJ180:
- case DNJ650C:
- if (num_comps > 1)
- { word *wp = (word *)plane_data[scan][i];
- for (j = 0; j < plane_size / W; j++, wp++)
- *wp = ~*wp;
- }
- out_count = gdev_pcl_mode1compress((const byte *)
- plane_data[scan][i],
- (const byte *)
- plane_data[scan][i] + plane_size - 1,
- out_data);
- break;
- case PJXL180: /* Need to invert data as CMY not supported */
- if (num_comps > 1)
- { word *wp = (word *)plane_data[scan][i];
- for (j = 0; j < plane_size / W; j++, wp++)
- *wp = ~*wp;
- }
- /* fall through .. */
- case PJXL300: /* Compression modes 2 and 3 are both
- * available. Try both and see which one
- * produces the least output data. */
- case LJ4DITH:
- { const byte *plane = plane_data[scan][i];
- byte *prev_plane = plane_data[1 - scan][i];
- const word *row = (word *)plane;
- const word *end_row = row + plane_size/W;
- int count2 = gdev_pcl_mode2compress(row, end_row, out_row_alt);
- int count3 = gdev_pcl_mode3compress(plane_size, plane, prev_plane, out_row);
- int penalty = combined_escapes ? strlen("#m") : strlen("\033*b#M");
- int penalty2 = (compression == 2 ? 0 : penalty);
- int penalty3 = (compression == 3 ? 0 : penalty);
-
- if (count3 + penalty3 < count2 + penalty2)
- { if ( compression != 3 ) {
- if (combined_escapes)
- fputs("3m", prn_stream);
- else
- fputs("\033*b3M", prn_stream);
- compression = 3;
- }
- out_data = out_row;
- out_count = count3;
- }
- else
- { if ( compression != 2 ) {
- if (combined_escapes)
- fputs("2m", prn_stream);
- else
- fputs("\033*b2M", prn_stream);
- compression = 2;
- }
- out_data = out_row_alt;
- out_count = count2;
- }
- }
- break;
- case BJC600:
- case BJC800:
- { const byte *plane = (byte *)plane_data[scan][i];
- int count2 = bjc_compress(plane, plane + plane_size, out_row_alt);
- out_data = out_row_alt;
- out_count = count2;
- }
- break;
- }
- if (output_plane) {
- if (combined_escapes)
- fprintf(prn_stream, "%d%c", out_count, "wvvv"[i]);
- else if (ptype == BJC600 || ptype == BJC800) {
- if (out_count)
- bjc_raster_cmd(num_comps == 1 ? 3 : i,
- out_count, out_data, pdev, prn_stream);
- if (i == 0) bjc_v_skip(1, pdev, prn_stream);
- } else if (ptype == ESC_P)
- ep_print_image(prn_stream, i, plane_data[scan][i], plane_size);
- else
- fprintf(prn_stream, "\033*b%d%c", out_count, "WVVV"[i]);
- if (ptype < ESC_P)
- fwrite(out_data, sizeof(byte), out_count, prn_stream);
- }
-
- } /* Transfer Raster Graphics ... */
- if (ptype == ESC_P)
- ep_print_image(prn_stream, 'I', 0, 0); /* increment line index */
- scan = 1 - scan; /* toggle scan direction */
- } /* Printing non-blank lines */
- } /* for lnum ... */
- } /* send each scan line in turn */
- if (combined_escapes)
- fputs("0M", prn_stream);
- /* end raster graphics */
- if (ptype == BJC600 || ptype == BJC800) {
- bjc_finish_page(pdev, prn_stream);
- }
- else if (ptype != ESC_P)
- fputs("\033*rbC\033E", prn_stream);
- /* eject page */
- if (ptype == PJ180)
- fputc('\f', prn_stream);
- else if (ptype == DNJ650C)
- fputs ("\033*rC\033%0BPG;", prn_stream);
- else if (ptype == BJC600 || ptype == BJC800)
- ; /* Already done */
- else if (ptype == ESC_P) {
- ep_print_image(prn_stream, 'F', 0, 0); /* flush print buffer */
- fputs("\014\033@", prn_stream); /* reset after eject page */
- } else
- fputs("\033&l0H", prn_stream);
- /* free temporary storage */
- gs_free((char *) ep_storage, ep_storage_size_words, W, "ep_print_buffer");
- gs_free((char *) storage, storage_size_words, W, "hp_colour_print_page");
- return 0;
- }
- /*
- * Row compression for the H-P PaintJet.
- * Compresses data from row up to end_row, storing the result
- * starting at compressed. Returns the number of bytes stored.
- * The compressed format consists of a byte N followed by a
- * data byte that is to be repeated N+1 times.
- * In the worst case, the `compressed' representation is
- * twice as large as the input.
- * We complement the bytes at the same time, because
- * we accumulated the image in complemented form.
- */
- private int
- gdev_pcl_mode1compress(const byte *row, const byte *end_row, byte *compressed)
- { register const byte *in = row;
- register byte *out = compressed;
- while ( in < end_row )
- { byte test = *in++;
- const byte *run = in;
- while ( in < end_row && *in == test ) in++;
- /* Note that in - run + 1 is the repetition count. */
- while ( in - run > 255 )
- { *out++ = 255;
- *out++ = test;
- run += 256;
- }
- *out++ = in - run;
- *out++ = test;
- }
- return out - compressed;
- }
- /*
- * Map a CMYK color to a color index. We just use depth / 4 bits per color
- * to produce the color index.
- *
- * Important note: CMYK values are stored in the order K, C, M, Y because of
- * the way the HP drivers work.
- *
- */
- #define gx_color_value_to_bits(cv, b) \
- ((cv) >> (gx_color_value_bits - (b)))
- #define gx_bits_to_color_value(cv, b) \
- ((cv) << (gx_color_value_bits - (b)))
- #define gx_cmyk_value_bits(c, m, y, k, b) \
- ((gx_color_value_to_bits((k), (b)) << (3 * (b))) | \
- (gx_color_value_to_bits((c), (b)) << (2 * (b))) | \
- (gx_color_value_to_bits((m), (b)) << (b)) | \
- (gx_color_value_to_bits((y), (b))))
- #define gx_value_cmyk_bits(v, c, m, y, k, b) \
- (k) = gx_bits_to_color_value(((v) >> (3 * (b))) & ((1 << (b)) - 1), (b)), \
- (c) = gx_bits_to_color_value(((v) >> (2 * (b))) & ((1 << (b)) - 1), (b)), \
- (m) = gx_bits_to_color_value(((v) >> (b)) & ((1 << (b)) - 1), (b)), \
- (y) = gx_bits_to_color_value((v) & ((1 << (b)) - 1), (b))
- private gx_color_index
- gdev_cmyk_map_cmyk_color(gx_device* pdev,
- gx_color_value cyan, gx_color_value magenta, gx_color_value yellow,
- gx_color_value black) {
- gx_color_index color;
- switch (pdev->color_info.depth) {
- case 1:
- color = (cyan | magenta | yellow | black) > gx_max_color_value / 2 ?
- (gx_color_index) 1 : (gx_color_index) 0;
- break;
- default: {
- int nbits = pdev->color_info.depth;
- if (cyan == magenta && magenta == yellow) {
- /* Convert CMYK to gray -- Red Book 6.2.2 */
- float bpart = ((float) cyan) * (lum_red_weight / 100.) +
- ((float) magenta) * (lum_green_weight / 100.) +
- ((float) yellow) * (lum_blue_weight / 100.) +
- (float) black;
- cyan = magenta = yellow = (gx_color_index) 0;
- black = (gx_color_index) (bpart > gx_max_color_value ?
- gx_max_color_value : bpart);
- }
- color = gx_cmyk_value_bits(cyan, magenta, yellow, black,
- nbits >> 2);
- }
- }
- return color;
- }
- /* Mapping of RGB colors to gray values. */
- private gx_color_index
- gdev_cmyk_map_rgb_color(gx_device *pdev, gx_color_value r, gx_color_value g, gx_color_value b)
- {
- if (gx_color_value_to_byte(r & g & b) == 0xff) {
- return (gx_color_index) 0; /* White */
- } else {
- gx_color_value c = gx_max_color_value - r;
- gx_color_value m = gx_max_color_value - g;
- gx_color_value y = gx_max_color_value - b;
- switch (pdev->color_info.depth) {
- case 1:
- return (c | m | y) > gx_max_color_value / 2 ?
- (gx_color_index) 1 : (gx_color_index) 0;
- /*NOTREACHED*/
- break;
- case 8:
- return ((ulong) c * lum_red_weight * 10
- + (ulong) m * lum_green_weight * 10
- + (ulong) y * lum_blue_weight * 10)
- >> (gx_color_value_bits + 2);
- /*NOTREACHED*/
- break;
- }
- }
- return (gx_color_index) 0; /* This should never happen. */
- }
- /* Mapping of CMYK colors. */
- private int
- gdev_cmyk_map_color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
- {
- switch (pdev->color_info.depth) {
- case 1:
- prgb[0] = prgb[1] = prgb[2] = gx_max_color_value * (1 - color);
- break;
- case 8:
- if (pdev->color_info.num_components == 1) {
- gx_color_value value = (gx_color_value) color ^ 0xff;
- prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
- break;
- }
- default: {
- unsigned long bcyan, bmagenta, byellow, black;
- int nbits = pdev->color_info.depth;
- gx_value_cmyk_bits(color, bcyan, bmagenta, byellow, black,
- nbits >> 2);
- #ifdef USE_ADOBE_CMYK_RGB
- /* R = 1.0 - min(1.0, C + K), etc. */
- bcyan += black, bmagenta += black, byellow += black;
- prgb[0] = (bcyan > gx_max_color_value ? (gx_color_value) 0 :
- gx_max_color_value - bcyan);
- prgb[1] = (bmagenta > gx_max_color_value ? (gx_color_value) 0 :
- gx_max_color_value - bmagenta);
- prgb[2] = (byellow > gx_max_color_value ? (gx_color_value) 0 :
- gx_max_color_value - byellow);
- #else
- /* R = (1.0 - C) * (1.0 - K), etc. */
- prgb[0] = (gx_color_value)
- ((ulong)(gx_max_color_value - bcyan) *
- (gx_max_color_value - black) / gx_max_color_value);
- prgb[1] = (gx_color_value)
- ((ulong)(gx_max_color_value - bmagenta) *
- (gx_max_color_value - black) / gx_max_color_value);
- prgb[2] = (gx_color_value)
- ((ulong)(gx_max_color_value - byellow) *
- (gx_max_color_value - black) / gx_max_color_value);
- #endif
- }
- }
- return 0;
- }
- /*
- * Map a r-g-b color to a color index.
- * We complement the colours, since we're using cmy anyway, and
- * because the buffering routines expect white to be zero.
- * Includes colour balancing, following HP recommendations, to try
- * and correct the greenish cast resulting from an equal mix of the
- * c, m, y, inks by reducing the cyan component to give a truer black.
- */
- /* Simple black generation/under-color removal with BG(k) = UG(k) = k. YA. */
- #define bg_and_ucr(c, c_v, m, m_v, y, y_v, k) \
- do { \
- register byte cv = c_v, mv = m_v, yv = y_v, kv; \
- \
- kv = (cv > mv ? mv : cv); \
- kv = (yv > k ? k : y); \
- y = yv - kv; m = mv - kv; c = cv -kv; k = kv; \
- } while (0)
- private gx_color_index
- gdev_pcl_map_rgb_color(gx_device *pdev, gx_color_value r,
- gx_color_value g, gx_color_value b)
- {
- if (gx_color_value_to_byte(r & g & b) == 0xff)
- return (gx_color_index)0; /* white */
- else {
- int correction = cprn_device->correction;
- gx_color_value c = gx_max_color_value - r;
- gx_color_value m = gx_max_color_value - g;
- gx_color_value y = gx_max_color_value - b;
-
- /* Colour correction for better blacks when using the colour ink
- * cartridge (on the DeskJet 500C only). We reduce the cyan component
- * by some fraction (eg. 4/5) to correct the slightly greenish cast
- * resulting from an equal mix of the three inks */
- if (correction) {
- ulong maxval, minval, range;
-
- maxval = c >= m ? (c >= y ? c : y) : (m >= y ? m : y);
- if (maxval > 0) {
- minval = c <= m ? (c <= y ? c : y) : (m <= y? m : y);
- range = maxval - minval;
-
- #define shift (gx_color_value_bits - 12)
- c = ((c >> shift) * (range + (maxval * correction))) /
- ((maxval * (correction + 1)) >> shift);
- }
- }
-
- switch (pdev->color_info.depth) {
- case 1:
- return ((c | m | y) > gx_max_color_value / 2 ?
- (gx_color_index)1 : (gx_color_index)0);
- case 8:
- if (pdev->color_info.num_components >= 3)
- #define gx_color_value_to_1bit(cv) ((cv) >> (gx_color_value_bits - 1))
- return (gx_color_value_to_1bit(c) +
- (gx_color_value_to_1bit(m) << 1) +
- (gx_color_value_to_1bit(y) << 2));
- else
- #define red_weight 306
- #define green_weight 601
- #define blue_weight 117
- return ((((ulong)c * red_weight +
- (ulong)m * green_weight +
- (ulong)y * blue_weight)
- >> (gx_color_value_bits + 2)));
- case 16:
- #define gx_color_value_to_5bits(cv) ((cv) >> (gx_color_value_bits - 5))
- #define gx_color_value_to_6bits(cv) ((cv) >> (gx_color_value_bits - 6))
- return (gx_color_value_to_5bits(y) +
- (gx_color_value_to_6bits(m) << 5) +
- (gx_color_value_to_5bits(c) << 11));
- case 24:
- return (gx_color_value_to_byte(y) +
- (gx_color_value_to_byte(m) << 8) +
- ((ulong)gx_color_value_to_byte(c) << 16));
- case 32:
- { return ((c == m && c == y) ? ((ulong)gx_color_value_to_byte(c) << 24)
- : (gx_color_value_to_byte(y) +
- (gx_color_value_to_byte(m) << 8) +
- ((ulong)gx_color_value_to_byte(c) << 16)));
- }
- }
- }
- return (gx_color_index)0; /* This never happens */
- }
-
- /* Map a color index to a r-g-b color. */
- private int
- gdev_pcl_map_color_rgb(gx_device *pdev, gx_color_index color,
- gx_color_value prgb[3])
- {
- /* For the moment, we simply ignore any black correction */
- switch (pdev->color_info.depth) {
- case 1:
- prgb[0] = prgb[1] = prgb[2] = -((gx_color_value)color ^ 1);
- break;
- case 8:
- if (pdev->color_info.num_components >= 3)
- { gx_color_value c = (gx_color_value)color ^ 7;
- prgb[0] = -(c & 1);
- prgb[1] = -((c >> 1) & 1);
- prgb[2] = -(c >> 2);
- }
- else
- { gx_color_value value = (gx_color_value)color ^ 0xff;
- prgb[0] = prgb[1] = prgb[2] = (value << 8) + value;
- }
- break;
- case 16:
- { gx_color_value c = (gx_color_value)color ^ 0xffff;
- ushort value = c >> 11;
- prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
- (value >> 4)) >> (16 - gx_color_value_bits);
- value = (c >> 6) & 0x3f;
- prgb[1] = ((value << 10) + (value << 4) + (value >> 2))
- >> (16 - gx_color_value_bits);
- value = c & 0x1f;
- prgb[2] = ((value << 11) + (value << 6) + (value << 1) +
- (value >> 4)) >> (16 - gx_color_value_bits);
- }
- break;
- case 24:
- { gx_color_value c = (gx_color_value)color ^ 0xffffff;
- prgb[0] = gx_color_value_from_byte(c >> 16);
- prgb[1] = gx_color_value_from_byte((c >> 8) & 0xff);
- prgb[2] = gx_color_value_from_byte(c & 0xff);
- }
- break;
- case 32:
- #define gx_maxcol gx_color_value_from_byte(gx_color_value_to_byte(gx_max_color_value))
- { gx_color_value w = gx_maxcol - gx_color_value_from_byte(color >> 24);
- prgb[0] = w - gx_color_value_from_byte((color >> 16) & 0xff);
- prgb[1] = w - gx_color_value_from_byte((color >> 8) & 0xff);
- prgb[2] = w - gx_color_value_from_byte(color & 0xff);
- }
- break;
- }
- return 0;
- }
- /*
- * Convert and expand scanlines:
- *
- * For devices with 3 components:
- *
- * (a) 16 -> 24 bit (1-stage)
- * (b) 16 -> 32 bit (2-stage)
- * or (c) 24 -> 32 bit (1-stage)
- *
- * For devices with 4 components:
- *
- * (a) 16 -> 32 bit (1-stage)
- * (b) 8 -> 32 bit (2-stage)
- * or (c) 24 -> 32 bit (1-stage)
- *
- */
- private void
- cdj_expand_line(word *line, int linesize, short cmyk, int bpp, int ebpp)
- {
- int endline = linesize;
- byte *start = (byte *)line;
- register byte *in, *out;
- if (cmyk > 0) {
- if (bpp == 8) {
- in = start + endline;
- out = start + (endline *= 2);
- while (in > start) {
- register byte b0;
- register byte bs0, bs1, bs2, bs3;
- b0 = *--in;
- bs0 = b0 & 0x03;
- bs1 = (b0 >> 2) & 0x03;
- bs2 = (b0 >> 4) & 0x03;
- bs3 = (b0 >> 6) & 0x03;
-
- *--out = (bs0 << 2) + bs0 + (bs1 << 6) + (bs1 << 4);
- *--out = (bs2 << 2) + bs2 + (bs3 << 6) + (bs3 << 4);
- }
- }
- if (bpp == 24) {
- endline = (endline + 2) / 3;
-
- in = start + endline * 3;
- out = start + endline * 4;
- while (in > start) {
- register byte b0, b1, b2;
- b0 = *--in;
- b1 = *--in;
- b2 = *--in;
- *--out = (b0 << 2) + ((b0 >> 4) & 0x03);
- *--out = ((b1 & 0x0f) << 4) + ((b0 >> 6) << 2)
- + ((b1 >> 2) & 0x03);
- *--out = ((b2 & 0x03) << 6) + ((b1 >> 4) << 2) + (b2 & 0x03);
- *--out = (b2 & 0xfc) + ((b2 >> 6) & 0x03);
- }
- } else if (ebpp == 32) {
- endline = (endline + 1) / 2;
- in = start + endline * 2;
- out = start + (endline *= 4);
- while (in > start) {
- register byte b0, b1;
- b0 = *--in;
- b1 = *--in;
- *--out = (b0 << 4) + ((b0 >> 4) & 0x07);
- *--out = (b0 & 0xf0) + ((b0 >> 4) & 0xf);
- *--out = (b1 << 4) + ((b1 >> 4) & 0x0f);
- *--out = (b1 & 0xf0) + ((b1 >> 4) & 0xf);
- }
- }
- } else /* cmyk > 0 */ {
- if (bpp == 16) /* 16 to 24 (cmy) if required */
- { register byte b0, b1;
- endline = ((endline + 1) / 2);
- in = start + endline * 2;
- out = start + (endline *= 3);
-
- while (in > start)
- { b0 = *--in;
- b1 = *--in;
- *--out = (b0 << 3) + ((b0 >> 2) & 0x7);
- *--out = (b1 << 5) + ((b0 >> 3) & 0x1c) + ((b1 >> 1) & 0x3);
- *--out = (b1 & 0xf8) + (b1 >> 5);
- }
- }
- if (ebpp == 32) /* 24/32 (cmy) to 32 (cmyk) if required */
- { register byte c, m, y;
- endline = ((endline + 2) / 3);
- in = start + endline * 3;
- out = start + endline * 4;
- while (in > start)
- {
- y = *--in;
- m = *--in;
- c = *--in;
- if (c == y && c == m) {
- *--out = 0, *--out = 0, *--out = 0;
- *--out = c;
- } else {
- *--out = y, *--out = m, *--out = c;
- *--out = 0;
- }
- }
- }
- }
- }
- private int
- cdj_put_param_int(gs_param_list *plist, gs_param_name pname, int *pvalue,
- int minval, int maxval, int ecode)
- { int code, value;
- switch ( code = param_read_int(plist, pname, &value) )
- {
- default:
- return code;
- case 1:
- return ecode;
- case 0:
- if ( value < minval || value > maxval )
- param_signal_error(plist, pname, gs_error_rangecheck);
- *pvalue = value;
- return (ecode < 0 ? ecode : 1);
- }
- }
- private int
- cdj_set_bpp(gx_device *pdev, int bpp, int ccomps)
- { gx_device_color_info *ci = &pdev->color_info;
- if (ccomps && bpp == 0) {
- if (cprn_device->cmyk) {
- switch (ccomps) {
- default:
- return gs_error_rangecheck;
- /*NOTREACHED*/
- break;
- case 1:
- bpp = 1;
- break;
- case 3:
- bpp = 24;
- break;
- case 4:
- switch (ci->depth) {
- case 8:
- case 16:
- case 24:
- case 32:
- break;
- default:
- bpp = cprn_device->default_depth;
- break;
- }
- break;
- }
- }
- }
- if (bpp == 0) {
- bpp = ci->depth; /* Use the current setting. */
- }
- if (cprn_device->cmyk < 0) {
- /* Reset procedures because we may have been in another mode. */
- dev_proc(pdev, map_cmyk_color) = gdev_cmyk_map_cmyk_color;
- dev_proc(pdev, map_rgb_color) = NULL;
- dev_proc(pdev, map_color_rgb) = gdev_cmyk_map_color_rgb;
- if (pdev->is_open) gs_closedevice(pdev);
- }
- /* Check for valid bpp values */
- switch ( bpp )
- {
- case 16:
- case 32:
- if (cprn_device->cmyk && ccomps && ccomps != 4) goto bppe;
- break;
- case 24:
- if (!cprn_device->cmyk || ccomps == 0 || ccomps == 4) {
- break;
- } else if (ccomps == 1) {
- goto bppe;
- } else {
- /* 3 components 24 bpp printing for CMYK device. */
- cprn_device->cmyk = -1;
- }
- break;
- case 8:
- if (cprn_device->cmyk) {
- if (ccomps) {
- if (ccomps == 3) {
- cprn_device->cmyk = -1;
- bpp = 3;
- } else if (ccomps != 1 && ccomps != 4) {
- goto bppe;
- }
- }
- if (ccomps != 1) break;
- } else {
- break;
- }
- case 1:
- if (ccomps != 1) goto bppe;
- if (cprn_device->cmyk && bpp != pdev->color_info.depth) {
- dev_proc(pdev, map_cmyk_color) = NULL;
- dev_proc(pdev, map_rgb_color) = gdev_cmyk_map_rgb_color;
- if (pdev->is_open) {
- gs_closedevice(pdev);
- }
- }
- break;
- case 3:
- if (!cprn_device->cmyk) {
- break;
- }
- default:
- bppe: return gs_error_rangecheck;
- }
- if (cprn_device->cmyk == -1) {
- dev_proc(pdev, map_cmyk_color) = NULL;
- dev_proc(pdev, map_rgb_color) = gdev_pcl_map_rgb_color;
- dev_proc(pdev, map_color_rgb) = gdev_pcl_map_color_rgb;
- if (pdev->is_open) {
- gs_closedevice(pdev);
- }
- }
- switch (ccomps) {
- case 0:
- break;
- case 1:
- if (bpp != 1 && bpp != 8) goto cce;
- break;
- case 4:
- if (cprn_device->cmyk) {
- if (bpp >= 8) break;
- }
- case 3:
- if (bpp == 1 || bpp == 3 || bpp == 8 || bpp == 16
- || bpp == 24 || bpp == 32) {
- break;
- }
- cce: default: return gs_error_rangecheck;
- }
- if (cprn_device->cmyk) {
- if (cprn_device->cmyk > 0) {
- ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 4);
- } else {
- ci->num_components = ccomps ? ccomps : (bpp < 8 ? 1 : 3);
- }
- if (bpp != 1 && ci->num_components == 1) { /* We do dithered grays. */
- bpp = bpp < 8 ? 8 : bpp;
- }
- ci->max_color = (1 << (bpp >> 2)) - 1;
- ci->max_gray = (bpp >= 8 ? 255 : 1);
- if (ci->num_components == 1) {
- ci->dither_grays = (bpp >= 8 ? 5 : 2);
- ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
- } else {
- ci->dither_grays = (bpp > 8 ? 5 : 2);
- ci->dither_colors = (bpp > 8 ? 5 : bpp > 1 ? 2 : 0);
- }
- } else {
- ci->num_components = (bpp == 1 || bpp == 8 ? 1 : 3);
- ci->max_color = (bpp >= 8 ? 255 : bpp > 1 ? 1 : 0);
- ci->max_gray = (bpp >= 8 ? 255 : 1);
- ci->dither_grays = (bpp >= 8 ? 5 : 2);
- ci->dither_colors = (bpp >= 8 ? 5 : bpp > 1 ? 2 : 0);
- }
- ci->depth = ((bpp > 1) && (bpp < 8) ? 8 : bpp);
- return 0;
- }
- /* new_bpp == save_bpp or new_bpp == 0 means don't change bpp.
- ccomps == 0 means don't change number of color comps.
- If new_bpp != 0, it must be the value of the BitsPerPixel element of
- the plist; real_bpp may differ from new_bpp.
- */
- private int
- cdj_put_param_bpp(gx_device *pdev, gs_param_list *plist, int new_bpp,
- int real_bpp, int ccomps)
- {
- if (new_bpp == 0 && ccomps == 0)
- return gdev_prn_put_params(pdev, plist);
- else
- {
- gx_device_color_info save_info;
- int save_bpp;
- int code;
- save_info = pdev->color_info;
- save_bpp = save_info.depth;
- #define save_ccomps save_info.num_components
- if ( save_bpp == 8 && save_ccomps == 3 && !cprn_device->cmyk)
- save_bpp = 3;
- code = cdj_set_bpp(pdev, real_bpp, ccomps);
- if ( code < 0 ) {
- param_signal_error(plist, "BitsPerPixel", code);
- param_signal_error(plist, "ProcessColorModel", code);
- return code;
- }
- pdev->color_info.depth = new_bpp; /* cdj_set_bpp maps 3/6 to 8 */
- code = gdev_prn_put_params(pdev, plist);
- if ( code < 0 )
- { cdj_set_bpp(pdev, save_bpp, save_ccomps);
- return code;
- }
- cdj_set_bpp(pdev, real_bpp, ccomps); /* reset depth if needed */
- if ((cdj->color_info.depth != save_bpp ||
- (ccomps != 0 && ccomps != save_ccomps))
- && pdev->is_open )
- return gs_closedevice(pdev);
- return 0;
- #undef save_ccomps
- }
- }
- /* This returns either the number of pixels in a scan line, or the number
- * of bytes required to store the line, both clipped to the page margins */
- private uint
- gdev_prn_rasterwidth(const gx_device_printer *pdev, int pixelcount)
- {
- ulong raster_width =
- pdev->width - pdev->x_pixels_per_inch * (dev_l_margin(pdev) + dev_r_margin(pdev));
- return (pixelcount ?
- (uint)raster_width :
- (uint)((raster_width * pdev->color_info.depth + 7) >> 3));
- }
- /* Functions for manipulation params strings */
- private const byte*
- paramValueToString(const stringParamDescription* params, int value)
- {
- for (; params->p_name; ++params) {
- if (params->p_value == value) {
- return (const byte *)params->p_name;
- }
- }
- return (const byte*) 0;
- }
- private int
- paramStringValue(const stringParamDescription* params,
- const byte* name, int namelen, int* value)
- {
- for (; params->p_name; ++params) {
- if (strncmp(params->p_name, (char *)name, namelen) == 0 &&
- params->p_name[namelen] == 0) {
- *value = params->p_value;
- return 1;
- }
- }
- return 0;
- }
- private int
- put_param_string(gs_param_list* plist,
- const byte* pname, gs_param_string* pstring,
- const stringParamDescription* params, int *pvalue, int code)
- {
- int ncode;
- if ((ncode = param_read_string(plist, (char *)pname, pstring)) < 0) {
- param_signal_error(plist, (char *)pname, code = ncode);
- } else if (ncode == 1) {
- pstring->data = 0, pstring->size = 0;
- } else {
- int value = 0;
- if (paramStringValue(params, pstring->data, pstring->size,
- &value) == 0) {
- param_signal_error(plist, (char *)pname, code = gs_error_rangecheck);
- } else {
- *pvalue = value;
- }
- }
- return code;
- }
- private int
- get_param_string(gs_param_list* plist,
- const byte* pname, gs_param_string* pstring,
- const stringParamDescription* params, int pvalue, bool persist, int code)
- {
- int ncode;
- pstring->data = paramValueToString(params, pvalue);
- if (pstring->data == (byte*) 0) {
- param_signal_error(plist, (char *)pname, ncode = gs_error_unknownerror);
- } else {
- pstring->size = strlen((char *)pstring->data);
- pstring->persistent = persist;
- }
- if ((ncode = param_write_string(plist, (char *)pname, pstring)) < 0) {
- code = ncode;
- }
- return code;
- }
- /*
- * This taken from gsdparam.c. I hope it will be useable directly some day.
- *
- */
- private int
- cdj_param_check_bytes(gs_param_list *plist, gs_param_name pname, const byte *str,
- uint size, bool defined)
- { int code;
- gs_param_string new_value;
- switch ( code = param_read_string(plist, pname, &new_value) )
- {
- case 0:
- if ( defined && new_value.size == size &&
- !memcmp((const char *)str, (const char *)new_value.data,
- size)
- )
- break;
- code = gs_note_error(gs_error_rangecheck);
- goto e;
- default:
- if ( param_read_null(plist, pname) == 0 )
- return 1;
- e: param_signal_error(plist, pname, code);
- case 1:
- ;
- }
- return code;
- }
- /* This is original code. */
- private int
- cdj_param_check_float(gs_param_list *plist, gs_param_name pname, floatp fval,
- bool defined)
- { int code;
- float new_value;
- switch ( code = param_read_float(plist, pname, &new_value) )
- {
- case 0:
- if ( defined && new_value == fval)
- break;
- code = gs_note_error(gs_error_rangecheck);
- goto e;
- default:
- if ( param_read_null(plist, pname) == 0 )
- return 1;
- e: param_signal_error(plist, pname, code);
- case 1:
- ;
- }
- return code;
- }
- /* The following dithering algorithm has been kindly given to me (YA) by
- * Klaus-Gunther Hess, I just adapted it for use with the code here. */
- /*
- (From KGH:)
- Just about the features of the code:
- - Stored Color-Values are BYTES in the order C-M-Y-K.
- (Indices need to change with gdevcdj.c)
- - There are individual THRESHOLDs and SPOTSIZEs for
- the color-components. The following relation should
- be maintained:
- SPOTSIZE = 2 * THRESHOLD + 1
- (The internal calculation is dedicated for limiting
- ink-density at the 720x720DpI-Resolution of the
- Epson-Printers, without loss of dynamic color-range)
- - In addition to that there are EMIN & EMAX-Values
- for the components. The Values are computed from
- the dithering-algorithm and can be replaced by
- constants, if neither the implementation nor
- THRESHOLD and SPOTSIZE can change.
- - The algorithm is tuned for speed. (K-only, if gray-
- levels are detected, with EMIN/EMAX-clipping of
- stored CMY-Errors. [Notice: cerr, merr, yerr are
- *not* reset to zero! Clearing them would cause
- regular patterns & "Halos" to appear!])
- */
- /*
- * Macros, that represent the undisturbed dithering-algorithm
- *
- * FSerror: compute the desired Value
- * FSdecide: decision based on the value computed by FSerror
- * FSdiffuse: distribute remaining error among pixels
- */
- #define FSerror(Val,Erow,Ecol) (Val + Erow + ((7 * Ecol)>>4))
- #define FSdecide(Error,Threshold,Spotsize,Pixel,Bit) \
- if(Error > Threshold) {\
- Pixel |= Bit;\
- Error -= Spotsize;\
- }
- #define FSdiffuse(Error,Erow,Ecol,Eprev)\
- Eprev += (3 * Error + 8)>>4;\
- Erow = (5 * Error + Ecol + 8)>>4;\
- Ecol = Error;
- /*
- * some aliases for values from the device-structure
- */
- #define DIRECTION direction[0]
- #define CMYK_THRESHOLD(I) threshold[I]
- #define SPOTSIZE(I) spotsize[I]
- #define EMIN(I) emin[I]
- #define EMAX(I) emax[I]
- #define NPIXEL (plane_size * 8)
- #define IDX_C 1
- #define IDX_M 2
- #define IDX_Y 3
- #define IDX_K 0
- #define ODX_C 2
- #define ODX_M 1
- #define ODX_Y 0
- #define ODX_K 3
- private int
- bjc_fscmyk(byte** inplanes, byte* outplanes[4][4], int** errplanes,
- int plane_size, int scan) {
- byte* err = (byte*) errplanes[0];
- /* =========================================================== */
- if(scan < 0) { /* scan < 0 -> initialize private buffer */
- /* =========================================================== */
- int p,i,v;
- int *direction,*threshold,*spotsize,*emin,*emax;
- int *errv,*errc;
- /*
- * allocate the error-buffer
- */
- /*KGHorig
- i = 4 * (5 + 1 + 1 + sd->stc.prt_pixels + 1) * sizeof(errv[0]);
- if((sd->stc.err_size < i) || (NULL == sd->stc.err)) {
- if(NULL != sd->stc.err)
- gs_free(sd->stc.err,sd->stc.err_size,1,"stcm/err");
- sd->stc.err_size = i;
- sd->stc.err = gs_malloc(sd->stc.err_size,1,"stcm/err");
- if(sd->stc.err == NULL) return_error(gs_error_VMerror);
- }
- */
- direction = (int *) err;
- threshold = direction + 4;
- spotsize = threshold + 4;
- emin = spotsize + 4;
- emax = emin + 4;
- errc = emax + 4;
- errv = errc + 2*4;
- /*
- * compute initial values
- */
- DIRECTION = -1;
- for(i = 0; i < 4; ++i) {
- int j;
- float maxv = 1.0;
- /*KGHorig
- if((sd->stc.xfer[i].size < 1) || (sd->stc.xfer[i].data == NULL)) {
- maxv = 1.0;
- } else {
- maxv = 1.0/255.0;
- for(j = 0; j < sd->stc.xfer[i].size; ++j)
- if(maxv < sd->stc.xfer[i].data[j])
- maxv = sd->stc.xfer[i].data[j];
- }
- */
- CMYK_THRESHOLD(i) = 127.0 / maxv + 0.5;
- SPOTSIZE(i) = ((int) CMYK_THRESHOLD(i)<<1)+1;
- j = CMYK_THRESHOLD(i); /* Maximum Error-Value */
- errc[3] = 0;
- FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
- FSdiffuse(CMYK_THRESHOLD(i),errv[0],errc[0],errv[-4]);
- EMAX(i) = errv[0];
- errc[0] = 0;
- FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
- FSdiffuse((-CMYK_THRESHOLD(i)),errv[0],errc[0],errv[-4]);
- EMIN(i) = errv[0];
- }
- #ifdef CDJ_DEBUG_FS
- for(i = 0; i < 4; ++i) errprintf(
- "CMYK_THRESHOLD(%d)=%5d, spotsize(%d)=%5d, emin(%d)=%5d, emax(%d)=%5d\n",
- i,CMYK_THRESHOLD(i),i,SPOTSIZE(i),i,EMIN(i),i,EMAX(i));
- #endif
- for(i = 0; i < 4; ++i) errc[i] = 0;
- for(p = 0; p < NPIXEL; ++p) {
- for(i = 0; i < 4; ++i) {
- /*KHGOrig
- if(sd->stc.flags & STCDFLAG0) v = 0;
- */
- if (0) v = 0; /* Must provide a default for that. */
- else v = (rand() % SPOTSIZE(i)) - CMYK_THRESHOLD(i);
- FSdiffuse(v,errv[i],errc[i],errv[i-4]);
- }
- errv += i;
- }
- /* =========================================================== */
- } else { /* scan >= 0 -> scanline-processing */
- /* =========================================================== */
- int w,p,dir,thedir;
- byte *out[4],pixel[4],bit;
- /*KGHorig
- int *width = outplanes[scan];
- */
- int *direction = (int *) err;
- int *threshold = direction + 4;
- int *spotsize = threshold + 4;
- int *emin = spotsize + 4;
- int *emax = emin + 4;
- int *errc = emax + 4;
- int *errv = errc + 2*4;
- int kerr,cerr,merr,yerr;
- byte* in;
- /*KGHorig
- if(sd->stc.flags & STCDFLAG1) {
- */
- if (0) { /* Eventually will provide a flag for this. */
- cerr = merr = yerr = kerr = 0;
- } else {
- cerr = errc[0];
- merr = errc[1];
- yerr = errc[2];
- kerr = errc[3];
- }
- out[0] = outplanes[scan + 2][ODX_C];
- out[1] = outplanes[scan + 2][ODX_M];
- out[2] = outplanes[scan + 2][ODX_Y];
- out[3] = outplanes[scan + 2][ODX_K];
- pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
- if(DIRECTION < 0) { /* scan == 0, run backward */
- w = NPIXEL;
- in = inplanes[2] + 4 * (NPIXEL - 1);
- errv += (w-1)<<2;
- dir = -4;
- /*KGHorig
- if(w > 8) for(p = 0; p < 4; ++p) out[p] += (w-1)>>3;
- */
- thedir = -1;
- for (p = 0; p < 4; ++p) {
- out[p] += plane_size - 1;
- }
- } else { /* run forward */
- w = 1;
- in = inplanes[3] - 4 * NPIXEL;
- dir = 4;
- thedir = 1;
- for (p = 0; p < 4; ++p) {
- out[p] -= plane_size;
- }
- } /* run backward/forward */
- /*KGHorig
- if(0 == (sd->stc.flags & STCDFLAG1)) DIRECTION = -DIRECTION;
- */
- if (1) DIRECTION = -DIRECTION; /* Scan in other direction. */
- bit = 0x80>>((w-1) & 7);
- w = (w+7)>>3;
- for(p = NPIXEL; p; --p) { /* loop over pixels */
- int cmy = in[IDX_C] | in[IDX_M] | in[IDX_Y];
- int kv = FSerror(in[IDX_K],errv[3],kerr);
- int cv;
- FSdecide(kv,CMYK_THRESHOLD(3),SPOTSIZE(3),pixel[3],bit);
- if(cmy) {
- if(pixel[3] & bit) { /* black known to fire */
- FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
- cv = FSerror(in[IDX_C],errv[0],cerr);
- cv -= SPOTSIZE(0);
- if ((cv+CMYK_THRESHOLD(0)) < 0) cv = -CMYK_THRESHOLD(0);
- FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
- cv = FSerror(in[IDX_M],errv[1],merr);
- cv -= SPOTSIZE(1);
- if ((cv+CMYK_THRESHOLD(1)) < 0) cv = -CMYK_THRESHOLD(1);
- FSdiffuse(cv,errv[1],merr,errv[1-dir]);
- cv = FSerror(in[IDX_Y],errv[2],yerr);
- cv -= SPOTSIZE(2);
- if ((cv+CMYK_THRESHOLD(2)) < 0) cv = -CMYK_THRESHOLD(2);
- FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
- } else {
- cv = FSerror(in[IDX_C],errv[0],cerr);
- FSdecide(cv,CMYK_THRESHOLD(0),SPOTSIZE(0),pixel[0],bit);
- FSdiffuse(cv,errv[0],cerr,errv[0-dir]);
- cv = FSerror(in[IDX_M],errv[1],merr);
- FSdecide(cv,CMYK_THRESHOLD(1),SPOTSIZE(1),pixel[1],bit);
- FSdiffuse(cv,errv[1],merr,errv[1-dir]);
- cv = FSerror(in[IDX_Y],errv[2],yerr);
- FSdecide(cv,CMYK_THRESHOLD(2),SPOTSIZE(2),pixel[2],bit);
- FSdiffuse(cv,errv[2],yerr,errv[2-dir]);
- if(pixel[0] & pixel[1] & pixel[2] & bit) {
- pixel[0] &= ~bit;
- pixel[1] &= ~bit;
- pixel[2] &= ~bit;
- pixel[3] |= bit;
- kv -= SPOTSIZE(3);
- if ((kv+CMYK_THRESHOLD(3)) < 0) kv = -CMYK_THRESHOLD(0);
- FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
- }
- }
- } else {
- FSdiffuse(kv,errv[3],kerr,errv[3-dir]);
- if( errv[0] > EMAX(0)) errv[0] = EMAX(0);
- else if(errv[0] < EMIN(0)) errv[0] = EMIN(0);
- if( errv[1] > EMAX(1)) errv[1] = EMAX(1);
- else if(errv[1] < EMIN(1)) errv[1] = EMIN(1);
- if( errv[2] > EMAX(2)) errv[2] = EMAX(2);
- else if(errv[2] < EMIN(2)) errv[2] = EMIN(2);
- }
- /*
- * Adjust indices
- */
- bit = dir > 0 ? (bit>>1) : (bit<<1);
- if(bit == 0) {
- /*KGHorig
- if(((*out[0] = pixel[0]) != 0) && (width[0] < w)) width[0] = w;
- if(((*out[1] = pixel[1]) != 0) && (width[1] < w)) width[1] = w;
- if(((*out[2] = pixel[2]) != 0) && (width[2] < w)) width[2] = w;
- if(((*out[3] = pixel[3]) != 0) && (width[3] < w)) width[3] = w;
- */
- *out[0] = pixel[0];
- *out[1] = pixel[1];
- *out[2] = pixel[2];
- *out[3] = pixel[3];
- out[0] += thedir; out[1] += thedir;
- out[2] += thedir; out[3] += thedir;
- pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
- if(dir > 0) bit = 0x80;
- else bit = 0x01;
- w += dir>>2;
- }
- in += dir;
- errv += dir;
- } /* loop over pixels */
- /*KGHorig
- if(0 == (sd->stc.flags & STCDFLAG1)) {
- */
- if (1) {
- cerr = errc[0] = cerr;
- merr = errc[1] = merr;
- yerr = errc[2] = yerr;
- kerr = errc[3] = kerr;
- }
- /* =========================================================== */
- } /* initialization or scanline-Processing */
- /* =========================================================== */
- return 0;
- }
|