Codebase list pnm2ppa / 80db757
Merge commit 'upstream/1.12' Didier Raboud 12 years ago
56 changed file(s) with 6340 addition(s) and 3689 deletion(s). Raw diff Collapse all Expand all
152152 pattern bug in calibrate_ppa. repaired the HP820
153153 fix that got broken when the vertical offset was
154154 redefined by 600 dots...
155
156
157
158
159
160
161
162
155 20010829 duncan Change the preprocessor flag __BEOS__ to __NO_SYSLOG__
156 as it is not BeOS specific (it supresses use of the
157 System Log) Added Makefile entries for Solaris, and
158 an INSTALL.SOLARIS file.
159
160 20020211 duncan Cleanup C++-style comments (gives gcc compiler warnings)
161 Small syslog.c/Makefile cleanups for Solaris.
162 Minor documentation updates. Change a confusing
163 syslog message about "unsupported PNM formats" so it is
164 clear that the error was non-PNM input to pnm2ppa.
165 Increase version to pnm2ppa-1.10
166
167 20020224 duncan Reworked cutswath.c and ppa.c so print sweeps
168 are sent separately by ppa_print_page()
169 in cutswath.c to ppa_print_sweep() in ppa.c
170 (until now, they were going in groups of
171 gMaxPass= 4 at a time in color high quality mode)
172 This will now permit improvement of the print sweep
173 pattern, and make the code easier to understand
174 (easier to separate ppa stuff from image stuff)
175 if someone wants to do a gimp-print PPA backend.
176
177
178 20020311 duncan lots more (incremental) reworking of cutswath.c;
179 now it's pretty well modularized, reading the input
180 image constructing the sweep data, constructing
181 the nozzle data, are all done in separate functions
182 now. Also, modified image.c so the
183 the expansion of data to ppm format
184 (three bytes per 8 dots) is not done for
185 pgm or pbm input (unless the -p option which uses
186 colored ink to make black, and disbles the black
187 ink is used). a new global variable gByteCount = 1
188 or 3 distingushes the two types of intermediate data
189 format.
190
191
192 Also still TODO: I finally understood that
193 the striping of black parts of the image when
194 e.g. the gs example file "tiger.ps"is printed in
195 high-quality mode is because the color and black
196 sweeps are not aligned, so sometimes the color prints
197 on top of black, sometimes the color prints
198 underneath black. If both types of ink are to be used
199 at the same place, the simple solution is probably to
200 prevent black sweeps getting ahead of
201 unprinted color in ppaprint_page() in cutswath.c.
202
203 20020526 duncan solved the striping problem; reworked cutswath.c
204 so black ink is never overprinted by color ink.
205
206 20020601 duncan reworked the code that prevents color swaths
207 and black swaths from having vertical_pos that
208 differs by 1, 2 or 3 lines (needed for HP820C).
209 (to go with the new swath-cutting algorithm).
210
211 Added a method for recognising if input is a
212 calibration page produced by calibrate_ppa,
213 as these dont work correctly with the new
214 swath-cutting algorithm. (will restore
215 a "legacy-style" (pnm2ppa-1.04-style) method
216 for printing input that is detected to be
217 calibration pages)
218
219 20020610 duncan added a method for storing info on lines as
220 they are read from the image. (whether they have black,
221 and/or color data, etc.) Helps a lot!
222 final fixes to calibrate_ppa. new code seems to work
223 20020623 duncan added a new command line option --dpi300 that
224 interprets input resolution as 300dpi instead of 600dpi
225 20020930 duncan enable compression of (color) data by default (only
226 compression of black data was previously enabled).
227 added a configuration file keyword "compression"
228 to switch it off, in case there are problems ...
229 (color data compression seems to work on HP722C!)
230 20021005 duncan disable logging of informational syslog messages by
231 default. They can (only) be reenabled by "log_info 1"
232 in the default configuration file /etc/pnm2ppa.conf.
233 (They will still go to stderr in "verbose" mode).
234 20021109 duncan make "version 0" in the config file set the printer
235 type to NOPRINTER, and abort printing if this is not
236 subsequently set to a valid printer model.
11 # Makefile for pnm2ppa
22 #
33
4 INSTALLDIR=/usr/local/bin
5 CONFDIR=/etc
6 MANDIR=/usr/local/man/man1
4 # paths to locations where the pnm2ppa binary, the configuration file,
5 # and the man page should be installed. On some systems (like Solaris)
6 # the install command requires the syntax BINDIR="-f /usr/local/bin".
7 BINDIR="/usr/local/bin"
8 CONFDIR="/etc"
9 MANDIR="/usr/local/man/man1"
710
11 #compiler and linker options:
812 CC=gcc
13 CFLAGS=-Wall -pedantic -O2
14 LDFLAGS=-lm
15
916 INSTALL=install
17 # Install under Linux and other versions with the -b (backup) option
18 # (Comment out next line on systems (*BSD, Solaris..) without this option)
19 INSTALL+= -b
1020
11 # production build
12 CFLAGS=-Wall -pedantic -O2 -g -DNDEBUG
13 LDFLAGS=-lm
1421 OBJS = pnm2ppa.o syslog.o ppa.o image.o dither.o cutswath.o hash_ink.o gamma.o
1522 SRC = pnm2ppa.c syslog.c ppa.c image.c dither.c cutswath.c hash_ink.c gamma.c
1623
17 # production build (beos)
18 #CFLAGS=-Wall -pedantic -O2 -g -DNDEBUG -D__BEOS__
19 #OBJS = pnm2ppa.o syslog.o ppa.o image.o dither.o cutswath.o hash_ink.o gamma.o
20 #SRC = pnm2ppa.c syslog.c ppa.c image.c dither.c cutswath.c hash_ink.c gamma.c
24 # The SysLog call may be absent or incompatible on some systems
25 # (e.g., BeOS,..) or you may not wish to have this feature.
26 # To remove support for writing to the System Log, uncomment the next line:
27 #CFLAGS+= -D__NO_SYSLOG__
2128
22 # debug build
23 #CFLAGS=-Wall -pedantic -g -O2 -DDEBUG=1
24 #LDFLAGS=-lm
25 #-lefence
26 #DOBJS = pnm2ppa.o syslog.o ppa.o image.o cutswath.o debug.o dither.o gamma.o hash_ink.o
27 #OBJS = $(DOBJS)
28 #SRC = pnm2ppa.c syslog.c ppa.c image.c cutswath.c debug.c dither.c gamma.c hash_ink.c
29 # Some systems (e.g. Solaris) may not support the LOG_PERROR option to
30 # open_syslog(). (This copies syslog messages to stderr as well as to
31 # the system log.) In that case, uncomment the next line:
32 #CFLAGS+= -D__NO_LOG_PERROR__
2933
30 # debug build (beos)
31 #CFLAGS=-Wall -pedantic -g -DDEBUG=1 -D__BEOS__
32 #OBJS = pnm2ppa.o ppa.o image.o cutswath.o debug.o dither.o hash_ink.o gamma.o syslog.o
33 #SRC = pnm2ppa.c ppa.c image.c cutswath.c debug.c dither.c hash_ink.c gamma.c syslog.c
34 # For debug builds, uncomment the next three lines to get debug messages:
35 #CFLAGS+= -g -DDEBUG=1
36 #OBJS+= debug.o
37 #SRC+= debug.c
3438
35 # If you have FreeBSD, you need to uncomment the next LDFLAG.
39 # For debugging with "Electric Fence" (if you have it):
40 #LDFLAGS+=-lefence
41
42 # On BeOS the LDFLAGS should not be used.
43 # Uncomment the next line if you are compiling for BeOS:
44 #LDFLAGS=
45
46 # On Mac OS X 10.x, you need to uncomment the next CFLAGS and LDFLAGS lines.
47 # You may also need to install libgnugetopt (there are precompiled
48 # versions for Mac OS X available on the net, or it can be compiled
49 # from source). Don't forget to rename the shared library from
50 # "/usr/local/lib/libgnugetopt.a" to "/usr/local/lib/libgnugetopt.dylib".
51 #CFLAGS=-Wall -no-cpp-precomp -traditional-cpp -pedantic -O2
52 #LDFLAGS=-L/usr/local/lib -lgnugetopt
53
54 # If you have FreeBSD you need to uncomment the next LDFLAGS.
3655 # You may also need to install libgnugetopt from the ports collection.
37 # LDFLAGS+=-L/usr/local/lib -lgnugetopt
56 # (Also, make sure the getopt.h it supplies is appropriately installed.)
57 #LDFLAGS+=-L/usr/local/lib -lgnugetopt
3858
39 # Install under Linux and other versions with the -b (backup) option
40 INSTALL=install -b
41 INSTALLD=install -b -d
59 # If you have Solaris you need to uncomment the next LDFLAG
60 # You will also need to install a library with GNU getopt:
61 # (e.g., libiberty which is available from http://sunfreeware.com)
62 #LDFLAGS+=-L/usr/local/lib -liberty
4263
43 # INSTALL for FreeBSD (doesn't have the -b (backup) option)
44 # XXX FreeBSD users, please tell me what the flag for backup is!
45 #
46 # If you have FreeBSD, uncomment the next line
47 # INSTALL=install
48 # INSTALLD=install -d
49
50 # Language selection. Choose one only.
51
64 # Language selection for messages from pnm2ppa. Choose one only.
5265 LANG=EN
5366 #LANG=CZ
5467 #LANG=ES
5669 #LANG=IT
5770 #LANG=NL
5871
72 #------------------------------------------------------------------
5973 # Normal Users!
6074 #
6175 # Do not edit below this line! No user servicable parts below!
62
76 #--------------------------------------------------------------------
77 INSTALLD=$(INSTALL) -d
6378 CFLAGS+=-DLANG_$(LANG)
6479
6580 default: all
87102 rm -f *.o *~ calibrate_ppa pnm2ppa make_hash_ink gmon.out hash_ink.c
88103
89104
90 install: pnm2ppa calibrate_ppa
91 $(INSTALL) -m 755 pnm2ppa $(INSTALLDIR)
105 install: pnm2ppa calibrate_ppa
106 $(INSTALLD) $(BINDIR)
107 $(INSTALLD) $(CONFDIR)
92108 $(INSTALLD) $(MANDIR)
109 $(INSTALL) -m 755 pnm2ppa $(BINDIR)
93110 $(INSTALL) -m 644 docs/en/pnm2ppa.1 $(MANDIR)
94111 # development only - allows root to edit
95 $(INSTALL) -m 644 pnm2ppa.conf $(CONFDIR)
112 $(INSTALL) -m 644 pnm2ppa.conf $(CONFDIR)
96113 # calibration tool
97 $(INSTALL) -m 755 calibrate_ppa $(INSTALLDIR)
114 $(INSTALL) -m 755 calibrate_ppa $(BINDIR)
98115 # final production - much tighter
99116 # $(INSTALL) -m 444 pnm2ppa.conf $(CONFDIR)
100117 @@echo
101118 @@echo Now, edit /etc/pnm2ppa.conf to choose your printer
102119
103120 uninstall:
104 rm -f $(INSTALLDIR)/pnm2ppa
105 rm -f $(INSTALLDIR)/calibrate_ppa
121 rm -f $(BINDIR)/pnm2ppa
122 rm -f $(BINDIR)/calibrate_ppa
106123 rm -f $(MANDIR)/pnm2ppa.1
107124 rm -f $(CONFDIR)/pnm2ppa.conf
108125
7777
7878 Do NOT install these suid/gid!
7979
80 calibrate.c: This is used to produce various ppmraw format PixMap images
80 calibrate_ppa.c:
81 This is used to produce various ppmraw format PixMap images
8182 used with pnm2ppa for printer calibration. Note: these
8283 PixMaps are LARGE (100MB!!) and should generally be piped
8384 directly to pnm2ppa.
8485
8586 THIS SHOULD USUALLY BE INSTALLED.
8687
87 parse_vlink.c a utility useful in debugging pnm2ppa that can interpret
88 parse_vlink.c
89 a utility useful in debugging pnm2ppa that can interpret
8890 ppa format output instructions to the printer, whether
8991 produced by pnm2ppa, or captured from the Windows9x drivers.
9092 It is in the ppa_protocol subdirectory, and is not compiled
3737 int make_test_pattern ( FILE *, int, char * );
3838
3939
40 //int black_maxlines = 300;
41 int black_maxlines = 128; //put this back to old value for now (duncan)
40 /* int black_maxlines = 300; */
41 int black_maxlines = 128; /*put this back to old value for now (duncan)*/
4242
4343
4444 void
6060 printf (" --clean pattern 2: clean print head. \n");
6161 printf (" --center pattern 3: center paper. \n");
6262 printf (" -s <paper> default papersize (a4, legal, letter = us (default))\n");
63 // printf (" -v <printer> Printer model:710=712=720=722;820;1000 (default:7xx)\n");
63 #if 0
64 printf (" -v <printer> Printer model:710=712=720=722;820;1000 (default:7xx)\n");
65 #endif
6466 printf ("\n");
6567 }
6668
9092 gHeight = LETTERHEIGHT ;
9193
9294
93 // read through the optional arguments before tring to find filenames
95 /* read through the optional arguments before tring to find filenames */
9496
9597 while ((c = getopt_long (argc, argv, "gho:p:s:v:",
9698 long_opts, &opt_index)) != EOF)
99101 switch (c)
100102 {
101103 case 0:
102 // long options
104 /* long options */
103105 switch (opt_index)
104106 {
105107 case 0:
106 // --gamma
108 /* --gamma */
107109 gamma = true;
108110 break;
109111 case 1:
110 // --align
112 /* --align */
111113 gamma = false;
112114 testPattern = 0;
113115 break;
114116 case 2:
115 // --test
117 /* --test */
116118 gamma = false;
117119 testPattern = 1;
118120 break;
119121 case 3:
120 // --clean
122 /* --clean */
121123 gamma = false;
122124 testPattern = 2;
123125 break;
124126 case 4:
125 // --center
127 /* --center */
126128 gamma = false;
127129 testPattern = 3;
128130 break;
129131 case 5:
130 // --help
132 /* --help */
131133 show_usage (*argv);
132134 return 0;
133135 break;
165167 break;
166168
167169 case 'p':
168 // select alternate test pattern
170 /* select alternate test pattern */
169171 gamma = false;
170172 testPattern = atoi( optarg );
171173 break;
172174
173175
174176 case 's':
175 // paper size stuffer
177 /* paper size stuffer */
176178 if (!strncmp (optarg, "us", 2) || !strncmp (optarg, "letter", 6))
177179 {
178180 gWidth = LETTERWIDTH;
195197 exit (0);
196198 }
197199 break;
198
200 #if 0
199201 case 'v':
200 // printer model
202 /* printer model */
201203 if (!strncmp (optarg, "820", 3) || !strncmp (optarg, "1000", 4))
202204 black_maxlines = 128;
203205 else if (!strncmp (optarg, "71", 2) || !strncmp (optarg, "72", 2))
204 // black_maxlines = 300;
205 black_maxlines = 128; //reverted for the moment
206 /* black_maxlines = 300; */
207 black_maxlines = 128; /*reverted for the moment - Duncan */
206208 else
207209 {
208210 fprintf(stderr,"%s: unknown printer model \"%s\"\n",
210212 exit (0);
211213 }
212214 break;
213
215 #endif
216
214217 default:
215218 exit (0);
216219 break;
330333 Height = gHeight;
331334
332335 /* pixel dimensions */
333 // Pwidth = Width ;
334 // Pheight = Height ;
336 #if 0
337 Pwidth = Width ;
338 Pheight = Height ;
339 #endif
335340
336341 /* each color is coded on 2 bits if 1 byte rrggbbxx */
337342
338 fprintf(outFile,"P6\n%d %d\n255\n",Width,Height);
343 fprintf(outFile,"P6\n# pnm2ppa calibration image\n%d %d\n255\n",
344 Width,Height);
339345
340346 for ( line = 0; line < Height ; line += maxlines )
341347 {
367373 case 3:
368374 centering();
369375 break;
370 // case 4:
371 //centering_grid();
372 //break;
373 // case 4:
374 //color_squares();
375 //break;
376 //case 5:
377 // make_vertical_line();
378 //break;
379 //case 6:
380 //make_big_x();
381 //break;
382
376 #if 0
377 case 4:
378 centering_grid();
379 break;
380 case 4:
381 color_squares();
382 break;
383 case 5:
384 make_vertical_line();
385 break;
386 case 6:
387 make_big_x();
388 break;
389 #endif
383390 default:
384391 fprintf(stderr,"%s: unknown test pattern (%d)\n",progname,testPattern);
385392 fprintf(stderr,"test pattern 0 : cartridge alignment (default)\n");
410417 v = ((color_bitmap [x] & mask) >> i);
411418 switch(v)
412419 {
413 case 0x00: // 4 drops of ink
420 case 0x00: /* 4 drops of ink */
414421 v=0x00;
415422 break;
416 case 0x01: // 3 drops of ink
423 case 0x01: /* 3 drops of ink */
417424 v=0x08;
418425 break;
419 case 0x02: // 1 drops of ink
426 case 0x02: /* 1 drops of ink */
420427 v=0x80;
421428 break;
422 case 0x03: // 0 drops of ink
429 case 0x03: /* 0 drops of ink */
423430 v=0xff;
424431 }
425432 putc(v, outFile);
495502 void
496503 color_alignment( void )
497504 {
498 //add for color test, alignment pattern
505 /* add for color test, alignment pattern */
499506 int x,y,t,shear,direction;
500507 int vpos;
501508 int hpos;
507514 hpos=Width/2-2000;
508515 for(y=1;y<20;y++)
509516 {
510 for(x=0;x<100;x++)
517 for(x=0;x<128;x++)
511518 {
512519 setpixel(y*200+hpos,x+vpos,BLACK);
513 setpixel(y*201-10+hpos,x+vpos+100,BLUE);
514 setpixel(y*201-10+1+hpos,x+vpos+100,BLUE);
515 setpixel(y*200+hpos,x+vpos+200,BLACK);
520 setpixel(y*201-10+hpos,x+vpos+128,BLUE);
521 setpixel(y*201-10+1+hpos,x+vpos+128,BLUE);
522 setpixel(y*200+hpos,x+vpos+256,BLACK);
516523 }
517524 if ((y-10) > 0)
518525 sprintf(buf,"+%d",y-10);
519526 else
520527 sprintf(buf,"%d",y-10);
521 setstring(y*200+hpos,vpos+350,buf,5);
522 }
523 setstring(Width/2 -200,vpos+450,"COLOFFSX",7);
528 setstring(y*200+hpos,vpos+400,buf,5);
529 }
530 setstring(Width/2 -200,vpos+500,"COLOFFSX",7);
524531 /* vertical black/color offset pattern */
525532
526533 vpos=1200;
583590 direction = -1; /* this is determined by whether sweep is L2R or R2L */
584591 for(y=1;y<20;y++)
585592 {
586 shear = direction*(y-10);
593 shear = -direction*(y-10);
587594 for(x=0; x < black_maxlines ;x++)
588595 {
589596 setpixel(y*200+hpos,x+vpos+000,BLACK);
614621 void
615622 check_alignment( void )
616623 {
617 // alignment verification pattern
624 /* alignment verification pattern */
618625 int x,y;
619626 int vpos, vpos1, vpos2;
620627 int hpos, hpos1,hpos2;
794801 void
795802 head_cleaning( void )
796803 {
797 // test page for cleaning
804 /* test page for cleaning */
798805 int x,y,a,b,c;
799806 int vpos;
800807 char buf[128];
876883 }
877884 }
878885
879 //grey
886 /*grey*/
880887 vpos=2000;
881888 for (y=100;y<Width-1000;y++)
882889 {
886893 }
887894 }
888895
889 //magenta,yellow,cyan
896 /*magenta,yellow,cyan*/
890897 vpos=2300;
891898 for (y=100;y<Width-1000;y++)
892899 {
897904 setpixel (y,x+vpos+256,CYAN);
898905 }
899906 }
900 //black
907 /*black*/
901908 vpos=2800;
902909 for (y=100;y<Width-1000;y++)
903910 {
982989 color_squares( void )
983990 {
984991 int x,y,z;
985 //color squares (Giorgio) (dont work after modifications 15/03/2000)
986 //seems to use a different color coding scheme ..... 125 possible
987 // color values in a byte ...
992 /* color squares (Giorgio) (dont work after modifications 15/03/2000)
993 seems to use a different color coding scheme ..... 125 possible
994 color values in a byte ... */
988995
989996
990997 z=0;
+2076
-1738
cutswath.c less more
00 /***********************************************************************
11 cutswath.c - function to cut a swath of a PNM file for PPA printers
2 -------------------
2 -------------------
33 begin : Thu Jan 13 2000
4 copyright : (C) 1998-2000 by the pnm2ppa project
4 copyright : (C) 1998-2002 by the pnm2ppa project
55 email :
66 ***************************************************************************/
77
3030
3131 #include "lang.h"
3232
33 int b_left, b_right, b_vpos , b_dir ;
34 int c_left, c_right, c_vpos , c_dir ;
35
36 /* sweep_data->direction must be set already */
33 /* stores information of previous sweeps */
34 int prev_black_vpos , prev_black_dir;
35 int prev_color_vpos , prev_color_dir;
36
37 /* pointers to next sweep that will print, and waiting sweeps */
38 ppaSweepData_t *current_swath, *waiting_color, *waiting_black;
39
40 /* stores info on printable limits of page */
41 ppaPageLimits_t ColorPageLimits;
42 ppaPageLimits_t BlackPageLimits;
43
44 int
45 cut_im_black_swath (image_t *image, ppaPrinter_t *printer,
46 ppaSweepData_t *sweep_data, int last_line);
47 int
48 cut_im_color_swath (image_t *image, ppaPrinter_t *printer,
49 ppaSweepData_t *sweep_data[4]);
50
51 /*
52 Here, we should call cut_im_black_swath and cut_im_color_swath to begin.
53
54 Then, we need to determine which of these swaths comes earlier on the page
55 and print it first. Then we should re-call the appropriate cut_im_*_swath
56 function to refill that buffer and repeat this procedure.
57
58 NEW (Feb 2002) : Finally, the sweep data is sent one sweep at a time to
59 ppa_print_sweep(), where the PPA instructions are produced...
60
61 This will make any further improvements much easier (i.e,
62 staggering the print swaths, in high quality color mode).
63 */
64
65 int
66 ppa_print_page (ppaPrinter_t *printer, image_t *image)
67 {
68 ppaSweepData_t sweeps[6];
69 ppaSweepData_t *prev = NULL, *curblack = NULL, *curcolor = NULL,
70 *color[4] = {NULL, NULL, NULL, NULL},
71 *tmp = NULL, *unused = NULL, *waiting = NULL;
72 int reload[2] = { 1, 1 };
73 int done[2] = { 0, 0 };
74 int found[2] = { 0, 0};
75 int j, k;
76 int last_dir = unknown;
77 int last_line;
78 int color_sweep = 0, color_todo = 0;
79 int color_byte_width, black_byte_width;
80 BOOLEAN NoPrint = gTerminate;
81 BOOLEAN color_done = false;
82 ppaPageLimits_t * black_page_limit = &BlackPageLimits;
83 ppaPageLimits_t * color_page_limit = &ColorPageLimits;
84 /* read the data from the input file */
85
86
87 /* initialize page limits for this document */
88 /*
89 vertical limits are in lines (1 line = 1dot at 600dpi),
90 horizontal limits are in data bytes:
91 1 color data byte = 8 dots at 300dpi,
92 1 black data byte = 8 dots at 600dpi
93 */
94
95 image->left = 0;
96 image->right = 0;
97 image->top = 0;
98 image->bottom = 0;
99 if(printer->left_margin > 0)
100 image->left = printer->left_margin;
101 if(printer->right_margin > 0)
102 image->right = printer->right_margin;
103 if(image->left >= image->width - image->right)
104 NoPrint = true;
105 if(printer->top_margin > 0)
106 image->top = printer->top_margin;
107 if(printer->bottom_margin > 0)
108 image->bottom = printer->bottom_margin;
109 if(image->top >= image->height - image->bottom)
110 NoPrint = true;
111 if(NoPrint)
112 gTerminate = true;
113
114
115
116 /* protect against invalid margin settings configured by users */
117 color_byte_width = (image->width / 2 + 7) / 8;
118 color_page_limit->left = printer->left_margin / 2 / 8;
119 if ( color_page_limit->left < 0 )
120 color_page_limit->left = 0 ;
121 color_page_limit->right = (gWidth - printer->right_margin) / 2 / 8;
122 if ( color_page_limit->right > color_byte_width )
123 color_page_limit->right = color_byte_width ;
124 color_page_limit->bottom = gHeight - printer->bottom_margin ;
125 if ( color_page_limit->bottom > gHeight)
126 color_page_limit->bottom = gHeight ;
127 if ( color_page_limit->bottom < 0 )
128 color_page_limit->bottom = 0;
129 color_page_limit->top = printer->top_margin ;
130 if ( color_page_limit->top < 0 )
131 color_page_limit->top = 0 ;
132 if ( color_page_limit->top > color_page_limit->bottom )
133 color_page_limit->top = color_page_limit->bottom ;
134
135 black_byte_width = (image->width + 7) / 8;
136 black_page_limit->left = printer->left_margin / 8;
137 if ( black_page_limit->left < 0 )
138 black_page_limit->left = 0;
139 black_page_limit->right = ( gWidth - printer->right_margin ) / 8;
140 if (black_page_limit->right > black_byte_width )
141 black_page_limit->right = black_byte_width;
142 black_page_limit->bottom = color_page_limit->bottom;
143 black_page_limit->top = color_page_limit->top;
144
145 /* create an array for storing info about each line on this page */
146
147 if ((image->LineType = malloc (image->height)) == NULL) {
148 snprintf(syslog_message,message_size,"ppa_print_page(): %s",
149 gMessages[E_CS_BADMALLOC]);
150 wrap_syslog (LOG_CRIT,"%s",syslog_message);
151 return 0;
152 }
153 memset(image->LineType, 0x00, image->height);
154
155 /* note: a full-size (all nozzles) color swath is 64 even lines (300dpi);
156 a full-size (all nozzles) black swath is 300 lines (150 even + 150 odd);
157
158 is is necessary to restrict black swath to 128 lines (64 even + 64 odd)
159 on some printer models, when printing in dual inks, color+black ?
160 HP7x0: NO, but there is some artifact at the begining of
161 each black swath that does not immediately follow a black
162 swath. (see the calibrate_ppa --align output....)
163 so leave the setting at 128 in gColorMode for now.
164 (duncan, 2000-10-24)
165 HP820: YES flashes lights ... (maybe it will work if what
166 produces the artifacts on HP7x0 is fixed..?)
167 HP1000: ?
168 */
169
170
171 DPRINTF("ppa_print_page(): begin page\n");
172
173 /* initialize global prev vertical position and direction markers, etc. */
174 prev_color_vpos = color_page_limit->top - 1;
175 prev_black_vpos = black_page_limit->top - 1;
176 prev_black_dir = prev_color_dir = unknown;
177
178 for (k = 0; k < 6; k++) {
179 sweeps[k].direction = unknown;
180 sweeps[k].next = NULL;
181 sweeps[k].image_data = NULL;
182 sweeps[k].nozzle_data = NULL;
183 }
184
185 /* initialize sweep_data pointers */
186 curblack = &sweeps[0];
187 unused = &sweeps[1];
188 for (k = 0; k < gMaxPass; k++)
189 color[k] = &sweeps[k+2];
190
191 /* when the cut_im_*_swath functions are called with
192 the sweep direction = "unknown", they will assign
193 the direction.
194 if gMaxPass is even (i.e. != 1) , the initial
195 value of color[0]->direction is ignored.
196 the cut_im_*swath functions may also override the
197 inital sweep directions in some other cases
198 (e.g., unidirectional printing was requested).
199
200 If gMaxPass is even, half of
201 the gMaxPass color sweeps will be left_to_right,
202 half will be right_to_left. In the present code
203 (gMaxPass = 4) all these sweeps have the same
204 vertical position. ppa_print_page() currently
205 is based on the assumption that if gMaxPass is even.
206 each r2L color sweep has a corresponding l2R sweep with
207 the same vertical_pos. If this changes, it should be
208 reworked.
209 */
210
211 if ( !gColorMode){
212 done[1] = 1;
213 prev_color_vpos = color_page_limit->bottom +1;
214 }
215 DPRINTF ("ppa_print_page: chkpt 1\n");
216
217 while (!done[0] || !done[1]){
218
219
220 /* to be safe, don't ever read beyond end of page */
221 if(image->blackCurLine >= gHeight)
222 done[0] = 1;
223 if(image->colorCurLine >= gHeight)
224 color_done = 1;
225 if(color_done && !color_todo)
226 done[1] = 1;
227
228 /* create a color swath */
229 if (reload[1] && !done[1]){
230 reload[1] = 0;
231 current_swath = prev;
232 waiting_color = NULL;
233 curcolor = NULL;
234 if(curblack->image_data)
235 waiting_black = curblack;
236 else
237 waiting_black = NULL;
238 if (color_todo){
239 color_sweep++;
240 color_todo--;
241 /* attempt to alternate direction */
242 if (!gUnimode && prev ){
243 BOOLEAN switch_dir=false;
244 if ( !waiting ||
245 color[color_sweep]->vertical_pos <= waiting->vertical_pos){
246 if (color[color_sweep]->direction == prev->direction)
247 switch_dir = true;
248 } else if (color[color_sweep]->direction == waiting->direction)
249 switch_dir = true;
250
251 if (switch_dir){
252 for (j=1; j <= color_todo; j++){
253 if (color[color_sweep+j]->vertical_pos >
254 color[color_sweep]->vertical_pos)
255 break;
256 if (color[color_sweep+j]->direction !=
257 color[color_sweep]->direction)
258 {
259 tmp = color[color_sweep];
260 color[color_sweep] = color[color_sweep+j];
261 color[color_sweep+j] = tmp;
262 break;
263 }
264 }
265 }
266 }
267 curcolor = color[color_sweep];
268 DPRINTF("*** loaded color[%d], dir=%d, vpos=%d, todo=%d\n",
269 color_sweep,curcolor->direction,
270 curcolor->vertical_pos, color_todo);
271 #ifdef DEBUG
272 for (k=0; k <= color_todo; k++){
273 DPRINTF(" %p [%d] dir=%d vpos=%d color=%d\n",
274 color[color_sweep+k],k,
275 color[color_sweep+k]->direction,
276 color[color_sweep+k]->vertical_pos,
277 color[color_sweep+k]->in_color);
278 }
279 #endif
280 } else if (!color_done)
281 switch (cut_im_color_swath (image, printer, color)) {
282 case 0:
283 snprintf(syslog_message,message_size, "ppa_print_page(): %s cut_im_color_swath()",
284 gMessages[E_CS_ERROR]);
285 wrap_syslog (LOG_CRIT,"%s",syslog_message);
286 break;
287 return 1;
288 case 1:
289 DPRINTF("ppa_print_page: cut_im_color_swath returned 1\n");
290 color_done = true;
291 prev_color_vpos = color_page_limit->bottom +1;
292 prev_color_dir = unknown;;
293 break;
294 case 2:
295 /* count and sort non-NULL sweeps */
296 color_todo = 0;
297 for (k=0; k < gMaxPass; k++){
298 if (color[k]->image_data)
299 color_todo++;
300 else {
301 for (j=k+1; j < gMaxPass; j++){
302 if (color[j]->image_data){
303 tmp = color[j];
304 color[j] = color[k];
305 color[k] = tmp;
306 break;
307 }
308 }
309 }
310 if (!color[k]->image_data)
311 break;
312 }
313 /* sort by vertical_pos */
314 for (k=0; k < color_todo; k++) {
315 int next = k;
316 for (j = k+1; j < color_todo; j++){
317 if (color[j]->vertical_pos < color[next]->vertical_pos)
318 next = j;
319 }
320 tmp = color[k];
321 color[k] = color[next];
322 color[next] = tmp;
323 }
324 /* attempt to alternate direction */
325 color_sweep = 0;
326 color_todo--;
327 if (!gUnimode && prev ){
328 BOOLEAN switch_dir=false;
329 if ( !waiting ||
330 color[color_sweep]->vertical_pos < waiting->vertical_pos){
331 if (color[color_sweep]->direction == prev->direction)
332 switch_dir = true;
333 }
334 else if (color[color_sweep]->direction == waiting->direction)
335 switch_dir = true;
336
337 if (switch_dir){
338 for (j=1; j <= color_todo; j++){
339 if (color[color_sweep+j]->vertical_pos >
340 color[color_sweep]->vertical_pos)
341 break;
342 if (color[color_sweep+j]->direction !=
343 color[color_sweep]->direction){
344 tmp = color[color_sweep];
345 color[color_sweep] = color[color_sweep+j];
346 color[color_sweep+j] = tmp;
347 break;
348 }
349 }
350 }
351 }
352 curcolor = color[color_sweep];
353 found[1]=1;
354 DPRINTF("*** loaded color[%d], dir=%d, vpos=%d, todo=%d\n",
355 color_sweep,curcolor->direction,
356 curcolor->vertical_pos, color_todo);
357 #ifdef DEBUG
358 for (k=0; k <= color_todo; k++){
359 DPRINTF(" %p [%d] dir=%d vpos=%d color=%d\n",
360 color[color_sweep+k],k,
361 color[color_sweep+k]->direction,
362 color[color_sweep+k]->vertical_pos,
363 color[color_sweep+k]->in_color);
364 }
365 #endif
366 break;
367 case 3:
368 prev_color_dir = unknown;
369 prev_color_vpos = color_page_limit->top - 1;
370 reload[1]=1;
371 found[1]=0;
372 break;
373 default:
374 snprintf(syslog_message,message_size,"ppa_print_page(): %s ",
375 gMessages[E_CS_BADSWITCH]);
376 wrap_syslog (LOG_CRIT,"%s",syslog_message);
377 return 1;
378 }
379 }
380
381
382 /* create a black swath */
383 if (reload[0]){
384 reload[0] = 0;
385 current_swath = prev;
386 waiting_black = NULL;
387 waiting_color = curcolor;
388 if (gColorMode && !color_done)
389 last_line = image->colorCurLine ;
390 else
391 last_line = image->height;
392 switch (cut_im_black_swath (image, printer, curblack, last_line)){
393 case 0:
394 snprintf(syslog_message,message_size,"ppa_print_page(): %s cut_im_black_swath()",
395 gMessages[E_CS_ERROR]);
396 wrap_syslog (LOG_CRIT,"%s",syslog_message);
397 return 1;
398 break;
399 case 1:
400 done[0] = 1;
401 prev_black_vpos = black_page_limit->bottom +1;
402 prev_black_dir = unknown;;
403 break;
404 case 2:
405 found[0]=1;
406 DPRINTF("*** loaded black, dir=%d, vpos=%d\n",
407 curblack->direction, curblack->vertical_pos);
408 #ifdef DEBUG
409 DPRINTF(" %p [B] dir=%d vpos=%d color=%d\n",
410 curblack,
411 curblack->direction,
412 curblack->vertical_pos,
413 curblack->in_color);
414 #endif
415 break;
416 case 3:
417 prev_black_vpos = black_page_limit->top -1;
418 prev_black_dir = unknown;
419 reload[0]=1;
420 found[0]=0;
421 break;
422 default:
423 snprintf(syslog_message,message_size,"ppa_print_page(): %s",
424 gMessages[E_CS_BADSWITCH]);
425 wrap_syslog (LOG_CRIT,"%s",syslog_message);
426 return 1;
427 }
428 }
429
430 if (done[0] && done[1])
431 break;
432
433 /* choose which swath (black or color) should print next */
434 if ( (!done[0] && found[0] &&
435 (color_done || !found[1] ||
436 curblack->vertical_pos < curcolor->vertical_pos)) ) {
437 /* print the current black swath, if it exists and has a
438 vertical_pos that is earlier any current color swath,
439 that exists */
440
441 DPRINTF("ppa_print_page: chkpt 2\n");
442
443 reload[0] = 1;
444 DPRINTF("ppa_print_page: chkpt 3\n");
445 if (prev){
446 prev->next = curblack;
447 if (found[1] && !done[1])
448 waiting = curcolor;
449 else
450 waiting = NULL;
451 #ifdef DEBUG
452 DPRINTF("*** ppa_print_sweep 1, %p, dir=%d (last=%d),"
453 "color=%d, vpos=%d, lines [%d-%d]\n",
454 prev,prev->direction, last_dir,
455 prev->in_color,prev->vertical_pos,
456 prev->first_data_line,prev->last_data_line);
457 #endif
458 if(!NoPrint)
459 ppa_print_sweep (printer, prev);
460 if (!gUnimode && last_dir == prev->direction){
461 DPRINTF("***SWEEP DIRECTION DID NOT CHANGE!!!***\n");
462 }
463 last_dir = prev->direction;
464 free (prev->image_data);
465 free (prev->nozzle_data);
466 prev->image_data = NULL;
467 prev->nozzle_data = NULL;
468 /* move the current sweep into the 'prev' position */
469 tmp = curblack;
470 curblack = prev;
471 prev = tmp;
472 } else {
473 /* move the current sweep into the 'prev' position */
474 prev = curblack;
475 assert (unused);
476 curblack = unused;
477 unused = NULL;
478 }
479 } else if ( (!done[1] && found[1]) ) {
480 /* print the current color swath, if it exists */
481 DPRINTF("ppa_print_page: chkpt 4 \n");
482
483 reload[1] = 1;
484
485 if (prev) {
486 prev->next = curcolor;
487 if (found[0] && !done[0])
488 waiting = curblack;
489 else
490 waiting = NULL;
491 #ifdef DEBUG
492 DPRINTF("*** ppa_print_sweep 2, %p, dir=%d (last=%d),"
493 "color=%d, vpos=%d, lines [%d-%d]\n",
494 prev,prev->direction, last_dir,
495 prev->in_color,prev->vertical_pos,
496 prev->first_data_line,prev->last_data_line);
497 #endif
498 if(!NoPrint)
499 ppa_print_sweep (printer, prev);
500 if (!gUnimode && last_dir == prev->direction){
501 DPRINTF("***SWEEP DIRECTION DID NOT CHANGE!!!***\n");
502 }
503 last_dir = prev->direction;
504 free (prev->image_data);
505 free (prev->nozzle_data);
506 prev->image_data = NULL;
507 prev->nozzle_data = NULL;
508 color[color_sweep] = prev;
509 } else {
510 assert (unused);
511 color[color_sweep] = unused;
512 unused = NULL;
513 }
514 /* move the current sweep into the 'prev' position */
515 prev = curcolor;
516 }
517 if(color_done && !color_todo)
518 done[1] = 1;
519 }
520
521 DPRINTF ("ppa_print_page: chkpt 5\n");
522
523 if (prev) {
524 DPRINTF ("ppa_print_page: chkpt 6 about to clear prev\n");
525
526 prev->next = NULL;
527 #ifdef DEBUG
528 DPRINTF("*** ppa_print_sweep 3, %p, dir=%d (last=%d),"
529 "color=%d, vpos=%d, lines [%d-%d]\n",
530 prev,prev->direction, last_dir,
531 prev->in_color,prev->vertical_pos,
532 prev->first_data_line,prev->last_data_line);
533 #endif
534 if(!NoPrint)
535 ppa_print_sweep (printer, prev);
536 if (!gUnimode && last_dir == prev->direction){
537 DPRINTF("***SWEEP DIRECTION DID NOT CHANGE!!!***\n");
538 }
539 last_dir = prev->direction;
540 free (prev->image_data);
541 free (prev->nozzle_data);
542 prev->image_data = NULL;
543 prev->nozzle_data = NULL;
544 DPRINTF ("ppa_print_page: chkpt 7 cleared prev\n");
545 }
546
547 DPRINTF ("ppa_print_page: chkpt 8 Finish.\n");
548
549 for (k=0; k < gMaxPass; k++)
550 free(image->buffer[k]);
551
552 free(image->LineType);
553 image->LineType = NULL;
554
555 return 0;
556 }
557
558 /* cutswath functions */
559
560 unsigned char *
561 l2r_black_sweep(unsigned char *place, unsigned char *data,
562 int data_width, ppaSwathLimits_t * swath_limits);
563 unsigned char *
564 r2l_black_sweep(unsigned char *place, unsigned char *data,
565 int data_width, ppaSwathLimits_t * swath_limits);
566 unsigned char *
567 l2r_color_sweep(unsigned char *place, unsigned char *data,
568 int data_width, ppaSwathLimits_t * swath_limits);
569 unsigned char *
570 r2l_color_sweep(unsigned char *place, unsigned char *data,
571 int data_width, ppaSwathLimits_t * swath_limits);
572
573 int
574 black_nozzle_data(ppaSweepData_t * sweep_data, int numlines, int margin_diff);
575
576 int
577 color_nozzle_data(ppaSweepData_t * sweep_data, int numlines);
578
579 int
580 read_black_image( unsigned char *data[], image_t *image,
581 ppaPrinter_t *printer, int byte_width,
582 int vpos_shift, int maxlines,
583 ppaSwathLimits_t *swath_limits,
584 int last_line);
585
586 int
587 read_color_image( unsigned char *data[], image_t *image,
588 ppaPrinter_t *printer, int byte_width,
589 int vpos_shift, int maxlines,
590 ppaSwathLimits_t *swath_limits);
591
37592
38593 /* Upon successful completion, sweep_data->image_data and
39594 sweep_data->nozzle_data have been set to pointers which this routine
40595 malloc()'d. */
41596
42597 /* Upon successful completion, all members of *sweep_data have been set
43 except direction, vertical_pos, and next. */
598 except next. */
44599
45600 /* Returns: 0 if unsuccessful
46601 1 if successful, but with non-printing result (end of page)
49604
50605 int
51606 cut_im_black_swath (image_t *image, ppaPrinter_t *printer,
52 int maxlines, ppaSweepData_t *sweep_data)
607 ppaSweepData_t *sweep_data, int last_line)
53608 {
54 unsigned char *data[4], *ppa, *place, *maxplace;
55 int width8, p_width8;
56 int k, i, j, left, right, numlines;
57 int left_limit , right_limit , bottom_limit, top_limit;
58 int top_vpos , bottom_vpos, sweep_offset;
59 int non_blanklines, pre_blanklines, post_blanklines ;
60 int even_non_blanklines, even_pre_blanklines, even_post_blanklines ;
61 int odd_non_blanklines, odd_pre_blanklines, odd_post_blanklines ;
62 int start_even, start_odd;
63 int vpos_shift=600; /* "vertical position" = line number - vpos_shift */
64 BOOLEAN at_bottom ;
65
66 BOOLEAN got_nonblank;
67 int horzpos, hp2;
68 ppaNozzleData_t nozzles[2];
69
70 /* better have (black) maxlines a multiple of 4;
71 color uses half this number, and that must be even !*/
72
73 assert ( !(maxlines %4));
74
75 /* safeguard against the user freeing these */
76 for (k = 0; k < gMaxPass; k++)
77 {
78 sweep_data->image_data[k] = NULL;
79 }
80 sweep_data->nozzle_data = NULL;
81
82 /* read the data from the input file */
83 width8 = (image->width + 7) / 8;
84 for (k = 0; k < gMaxPass; k++)
85 {
86 if ((data[k] = malloc (width8 * maxlines)) == NULL)
87 {
88 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
89 gMessages[E_CS_BADMALLOC]);
90 wrap_syslog (LOG_CRIT,"%s",syslog_message);
609 unsigned char *data[4] = { NULL, NULL, NULL, NULL};
610 unsigned char *ppa, *place, *maxplace;
611 int width, byte_width = (image->width + 7) / 8;
612 int vpos_shift=600; /* "vertical position" = line number - vpos_shift */
613 int horizpos;
614 ppaSwathLimits_t Swath_Limits;
615 ppaSwathLimits_t *swath_limits = &Swath_Limits;
616 int maxlines = 300; /* fixed by design of print head */
617
618 /* return if we are not yet allowed to read next part of
619 black image */
620 if(image->blackCurLine >= last_line)
621 return 3;
622
623 /*
624 if we need to use "legacy" mode for printing Calibration pages
625 produced by calibrate_ppa, set maxlines = 128 as in pnm2ppa-1.04.
626 */
627 if(gCalibrate && gColorMode)
628 maxlines = 128;
629
630
631
632 /* safeguard against the user freeing these */
633 sweep_data->image_data = NULL;
634 sweep_data->nozzle_data = NULL;
635
636
637 if ((data[0] = malloc (byte_width * maxlines)) == NULL) {
638 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
639 gMessages[E_CS_BADMALLOC]);
640 wrap_syslog (LOG_CRIT,"%s",syslog_message);
641 return 0;
642 }
643
644 /* read in and analyze image data for a black swath */
645 {
646 int retval = 0;
647 retval = read_black_image( data, image, printer, byte_width,
648 vpos_shift, maxlines, swath_limits, last_line);
649 if(retval != 2) {
650 free (data[0]);
651 return retval;
652 }
653 }
654 /* analysis of the image is now complete */
655
656 /* width of the swath in bytes */
657 /* change sweep params to ensure at least 4 bytes sweep width */
658 swath_limits->right += 3;
659 swath_limits->left-- ;
660
661 /* calculate vertical position */
662 sweep_data->vertical_pos = swath_limits->last_line +
663 swath_limits->post_blanklines;
664 /* subtract that 600 dot adjustment here */
665 sweep_data->vertical_pos -= vpos_shift;
666
667 /* fix sweep direction (right_to_left or left_to_right) */
668 sweep_data->direction = unknown;
669 /* always make left_to_right black sweeps if gUnimode is true */
670 /* also do this to avoid striping in multipass color print */
671 if (gUnimode || (gColorMode && !(gMaxPass %2) && !gCalibrate ))
672 sweep_data->direction = left_to_right;
673 else if (gCalibrate) {
674 /* use legacy direction choosing method from pnm2ppa-1.04 */
675 if (prev_color_dir == unknown &&
676 prev_black_dir == unknown )
677 sweep_data->direction = left_to_right;
678 else if (prev_black_vpos > prev_color_vpos ||
679 prev_color_vpos > sweep_data->vertical_pos ){
680 if (prev_black_dir == left_to_right)
681 sweep_data->direction = right_to_left;
682 else
683 sweep_data->direction = left_to_right;
684 } else {
685 if (prev_color_dir == left_to_right)
686 sweep_data->direction = right_to_left;
687 else
688 sweep_data->direction = left_to_right;
689 }
690 } else {
691 int opposite_dir = unknown;
692 if (current_swath) {
693 if (prev_color_dir != unknown &&
694 prev_color_vpos < sweep_data->vertical_pos
695 && current_swath->vertical_pos <= prev_color_vpos )
696 opposite_dir = prev_color_dir;
697 else
698 opposite_dir = current_swath->direction;
699 } else {
700 if (prev_black_dir != unknown)
701 opposite_dir = prev_black_dir;
702 else
703 opposite_dir = right_to_left;
704 }
705 if (opposite_dir == right_to_left)
706 sweep_data->direction = left_to_right;
707 else if (opposite_dir == left_to_right)
708 sweep_data->direction = right_to_left;
709 }
710
711 assert (sweep_data->direction != unknown);
712
713 sweep_data->in_color = false;
714
715 /*
716 create sweep image_data
717 "width" is horizontal swath width in bytes;
718 will add 12 null bytes on each side of black swath
719 */
720 width = swath_limits->right - swath_limits->left + 24;
721
722 if ((ppa = malloc (width * swath_limits->numlines)) == NULL) {
723 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
724 gMessages[E_CS_BADPPAMALLOC]);
725 wrap_syslog (LOG_CRIT,"%s",syslog_message);
726 free (data[0]);
727 return 0;
728 }
729 place = ppa;
730
731 if (sweep_data->direction == right_to_left) /* right-to-left */
732 maxplace = r2l_black_sweep(place, data[0], byte_width,
733 swath_limits);
734 else /* sweep_data->direction == left_to_right */
735 maxplace = l2r_black_sweep(place, data[0], byte_width,
736 swath_limits);
737 sweep_data->image_data = ppa;
738 sweep_data->data_size = maxplace - ppa;
739 sweep_data->first_data_line = swath_limits->first_line;
740 sweep_data->last_data_line = swath_limits->last_line;
741 sweep_data->pre_blanklines = swath_limits->pre_blanklines;
742 sweep_data->post_blanklines = swath_limits->post_blanklines;
743
744 /* done with data */
745 free (data[0]);
746
747 horizpos = swath_limits->left * 8 ;
748 horizpos += (sweep_data->direction == left_to_right) ? 1 : 0;
749 if (sweep_data->direction == right_to_left )
750 horizpos += printer->r2l_bw_offset ;/* correct bidirectional shearing */
751
752 sweep_data->left_margin = horizpos;
753 sweep_data->right_margin = horizpos + printer->marg_diff + width * 8;
754
755
756 if (!black_nozzle_data(sweep_data, swath_limits->numlines, printer->marg_diff )) {
757 DPRINTF("black_nozzle_data: malloc failed");
758 free(sweep_data->image_data);
759 return 0;
760 }
761 prev_black_vpos = sweep_data->vertical_pos;
762 prev_black_dir = sweep_data->direction;
763
764 DPRINTF ("cut_im_black_swath: created swath, return 2\n");
765 return 2;
766 }
767
768 int
769 read_black_image( unsigned char * data[], image_t *image,
770 ppaPrinter_t *printer, int byte_width,
771 int vpos_shift, int maxlines,
772 ppaSwathLimits_t *swath_limits,
773 int last_line)
774 {
775 BOOLEAN got_nonblank = false, after_color = false, ignore_color = false;
776 int i, j;
777 int max_vpos, min_vpos;
778 int left, right;
779 int numlines = 0;
780 BOOLEAN blackline = true;
781 int non_blanklines = 0, pre_blanklines = 0, post_blanklines = 0;
782 ppaPageLimits_t *page_limit = &BlackPageLimits;
783
784 min_vpos = image->blackCurLine - vpos_shift;
785 max_vpos = BlackPageLimits.bottom - vpos_shift;
786
787 /* test to see whether color swaths can be ignored */
788 if(!gColorMode ||
789 !(waiting_color ||
790 (current_swath && current_swath->in_color ) ||
791 image->colorCurLine < ColorPageLimits.bottom ) )
792 ignore_color = true;
793
794 /* eat all lines that are below the lower margin */
795 if (image->blackCurLine >= page_limit->bottom ){
796 while (image->blackCurLine < image->height)
797 if (!im_black_readline (image, data, 0)){
798 snprintf(syslog_message,message_size,"read_black_image(): %s",
799 gMessages[E_CS_BADBOTMARG]);
800 wrap_syslog (LOG_CRIT,"%s",syslog_message);
801
802 return 0;
803 }
804 return 1;
805 }
806
807 left = page_limit->right - 1;
808 right = page_limit->left;
809
810 /* eat all beginning blank lines and then up to maxlines or lower margin */
811
812 while (( image->blackCurLine + pre_blanklines < page_limit->bottom)
813 && (image->blackCurLine < last_line)
814 && (numlines + pre_blanklines + post_blanklines < maxlines)
815 && image->blackCurLine < max_vpos + vpos_shift
816 && (!gColorMode || got_nonblank
817 || ((image->buflines < MAXBUFFLINES)
818 || (image->buftype == bitmap)))) {
819 if (!im_black_readline (image, data, byte_width * numlines)) {
820 snprintf(syslog_message,message_size,"read_black_image(): %s",
821 gMessages[E_CS_BADNEXTLINE]);
822 wrap_syslog (LOG_CRIT,"%s",syslog_message);
823 return 0;
824 }
825 blackline = image->LineType[image->blackCurLine - 1] & BLACKLINE;
826 if (!got_nonblank) {
827 if (blackline){
828 for (i = page_limit->left ; i < page_limit->right; i++) {
829 if (data[0][i]){
830 left = i;
831 got_nonblank = true;
832 right = i;
833 for (j = page_limit->right - 1; j > left ; j--){
834 if (data[0][j]){
835 right = j;
836 break;
837 }
838 }
839 break;
840 }
841 }
842 }
843 if(got_nonblank) {
844 /* begin a new swath;, nonblank pixels occur in
845 * bytes "left" through "right", inclusive,
846 * where
847 * page_limit->left <= left <= right < page_limit->right.
848 * This range will be expanded if necessary
849 * as the swath is constructed
850 */
851 DPRINTF("read_black_image: begin swath, line %d\n",
852 image->blackCurLine ) ;
853
854 numlines = 1;
855 non_blanklines = 1;
856 swath_limits->first_line = image->blackCurLine;
857 min_vpos = image->blackCurLine - vpos_shift;
858 max_vpos = min_vpos + maxlines - 1 ;
859
860 /*
861 fix to avoid flashing lights on HP820C:
862 Empirical observation shows that on HP820C,
863 a new swath cannot have a vertical_position that differs from
864 the previous swath that was printed by 1, 2 or 3 lines.
865 This problem does not occur on HP71x/72xC.
866 */
867 if(current_swath && min_vpos < current_swath->vertical_pos + 4)
868 min_vpos = current_swath->vertical_pos + 4;
869
870 if(ignore_color) {
871 if (max_vpos >= BlackPageLimits.bottom - vpos_shift + 20)
872 max_vpos = BlackPageLimits.bottom - vpos_shift + 20;
873 } else if( waiting_color) {
874 if (max_vpos >= waiting_color->vertical_pos
875 && waiting_color->vertical_pos >= min_vpos) {
876 /*
877 design this swath to have the same vertical_pos
878 as the waiting color swath, and print immediately after it.
879 */
880 pre_blanklines = max_vpos - waiting_color->vertical_pos;
881 max_vpos = waiting_color->vertical_pos;
882 min_vpos = max_vpos;
883 after_color = true;
884 } else if (max_vpos < waiting_color->vertical_pos) {
885 /*
886 design this swath to print before the
887 waiting color swath, and to not be overprinted by
888 the waiting color swath.
889 */
890 if (max_vpos > waiting_color->vertical_pos - 4)
891 max_vpos = waiting_color->vertical_pos - 4;
892 assert (max_vpos >= min_vpos);
893 if (last_line > waiting_color->first_data_line - 1 )
894 last_line = waiting_color->first_data_line - 1;
895
896 if(max_vpos + vpos_shift + 1 - maxlines <
897 swath_limits->first_line) {
898 pre_blanklines = maxlines + swath_limits->first_line
899 - max_vpos - vpos_shift - 1;
900 }
901 } else if (waiting_color->vertical_pos < min_vpos) {
902 /*
903 design this swath to print with vpos
904 at least 4 greater than that of the waiting color swath.
905 */
906 if (min_vpos < waiting_color->vertical_pos + 4)
907 min_vpos = waiting_color->vertical_pos + 4;
908 assert (max_vpos >= min_vpos);
909 }
910 }
911 }
912 } else {
913 int newleft = left, newright = right;
914 if (blackline) {
915 /* find left-most nonblank */
916 for (i = page_limit->left ; i < left; i++){
917 if (data[0][byte_width * numlines + i]){
918 newleft = i;
919 break;
920 }
921 }
922 /* find right-most nonblank */
923 for (j = page_limit->right - 1; j > right; j--){
924 if (data[0][byte_width * numlines + j]){
925 newright = j;
926 break;
927 }
928 }
929 }
930 numlines++;
931
932 if (newright < newleft){
933 DPRINTF ("Code error! newleft=%d, newright=%d, left=%d, right=%d\n",
934 newleft, newright, left, right);
935 return 0;
936 }
937
938 /* if the next line might push us over the buffer size, stop here! */
939 /* ignore this test for the 720 right now. Will add better */
940 /* size-guessing for compressed data in the near future! */
941 if (numlines % 2 == 1 && printer->version != HP7X0) {
942 int l = newleft, r = newright, w;
943
944 l--;
945 r += 3;
946 w = r - l;
947
948 if ((w + 24) * numlines > printer->bufsize){
949 numlines--;
950 im_unreadline (image, data[0] + byte_width * numlines);
951 break;
952 } else {
953 left = newleft;
954 right = newright;
955 if (blackline)
956 non_blanklines = numlines;
957 }
958 } else {
959 left = newleft;
960 right = newright;
961 if (blackline)
962 non_blanklines = numlines;
963 }
964 }
965 }
966
967 if ((gColorMode) && (image->buflines >= MAXBUFFLINES)
968 && (image->buftype == color)){
969 DPRINTF ("read_black_image: exceeding buffer size: buflines=%d, MAX=%d\n",
970 image->buflines, MAXBUFFLINES);
971 if ((!got_nonblank)){
972 return 3;
973 }
974 }
975
976 if ((!got_nonblank)) {
977 /* eat all lines that are below the lower margin */
978 if (image->blackCurLine >= page_limit->bottom ){
979 while (image->blackCurLine < image->height)
980 if (!im_black_readline (image, data, 0)){
981 snprintf(syslog_message,message_size,"read_black_image(): %s",
982 gMessages[E_CS_BADBOTMARG]);
983 wrap_syslog (LOG_CRIT,"%s",syslog_message);
984
91985 return 0;
92 }
93 }
94
95 /* prevent weird user settings of the margins
96 * from causing segfaults
97 */
98 left_limit = printer->left_margin / 8;
99 if ( left_limit < 0 )
100 left_limit = 0;
101 right_limit = ( gWidth - printer->right_margin ) / 8;
102 if (right_limit > width8 )
103 right_limit = width8;
104 bottom_limit = gHeight - printer->bottom_margin ;
105 if (bottom_limit > gHeight )
106 bottom_limit = gHeight;
107 if ( bottom_limit < 0 )
108 bottom_limit = 0;
109 top_limit = printer->top_margin ;
110 if ( top_limit < 0 )
111 top_limit = 0 ;
112 if ( top_limit > bottom_limit )
113 top_limit = bottom_limit ;
114
115 /* ignore lines that are above the upper margin */
116 while (image->blackCurLine < top_limit)
117 {
118 if (!im_black_readline (image, data, 0))
119 {
120 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
121 gMessages[E_CS_BADTOPMARG]);
122 wrap_syslog (LOG_CRIT,"%s",syslog_message);
123
124 for (k = 0; k < gMaxPass; k++)
125 {
126 free (data[k]);
127 }
128 return 0;
129 }
130 }
131
132 /* eat all lines that are below the lower margin */
133 if (image->blackCurLine >= bottom_limit )
134 {
135 while (image->blackCurLine < image->height)
136 if (!im_black_readline (image, data, 0))
137 {
138 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
139 gMessages[E_CS_BADBOTMARG]);
140 wrap_syslog (LOG_CRIT,"%s",syslog_message);
141
142 for (k = 0; k < gMaxPass; k++)
143 {
144 free (data[k]);
145 }
146 return 0;
147 }
148 for (k = 0; k < gMaxPass; k++)
149 {
150 free (data[k]);
151 }
986 }
152987 return 1;
153 }
154
155 left = right_limit - 1;
156 right = left_limit;
157
158 /* eat all beginning blank lines and then up to maxlines or lower margin */
159 got_nonblank = false;
160 numlines = 0;
161 pre_blanklines = 0;
162 post_blanklines = 0;
163 sweep_offset = 0;
164 at_bottom = false ;
165 while (( image->blackCurLine + pre_blanklines < bottom_limit)
166 && ((numlines + pre_blanklines + post_blanklines ) < maxlines)
167 && ((!gColorMode) || got_nonblank
168 || ((image->buflines < MAXBUFFLINES)
169 || (image->buftype == bitmap))))
170 {
171 if (!im_black_readline (image, data, width8 * numlines))
172 {
173 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
174 gMessages[E_CS_BADNEXTLINE]);
175 wrap_syslog (LOG_CRIT,"%s",syslog_message);
176 for (k = 0; k < gMaxPass; k++)
177 {
178 free (data[k]);
179 }
180 return 0;
181 }
182 if (!got_nonblank)
183 {
184 for (i = left_limit ; i < right_limit; i++)
185 {
186 if (data[0][i])
187 {
188 left = i;
189 got_nonblank = true;
190 right = i;
191 for (j = right_limit - 1; j > left ; j--)
192 {
193 if (data[0][j])
194 {
195 right = j;
196 break;
197 }
198 }
199 /* begin a new swath;, nonblank pixels occur in
200 * bytes "left" through "right", inclusive,
201 * where
202 * left_limit <= left <= right < right_limit.
203 * This range will be expanded if necessary
204 * as the swath is constructed
205 */
206 DPRINTF("cut_im_black_swath: begin swath, line %d\n",
207 image->blackCurLine ) ;
208
209 /* vertical position of top of swath */
210 top_vpos = image->blackCurLine - vpos_shift ;
211
212 /* predicted vertical position of bottom of swath */
213 bottom_vpos = top_vpos + maxlines - 1 ;
214 if ( bottom_vpos > bottom_limit - vpos_shift)
215 {
216 at_bottom = true;
217 bottom_vpos = bottom_limit - vpos_shift ;
218 /* make sure we are at least 12 dots below the previous
219 black swath vertical position (this is only
220 a possible problem if we are at the bottom limit)*/
221 if ( b_vpos + 12 - bottom_vpos > 0 )
222 {
223 post_blanklines += (b_vpos + 12 - bottom_vpos) ;
224 bottom_vpos += post_blanklines ;
225 }
226 }
227
228 DPRINTF("cut_im_black_swath: shifted bottom_limit=%d, bottom_vpos=%d\n",
229 bottom_limit - vpos_shift , bottom_vpos) ;
230
231 /* sweep_offset is the difference in vertical position
232 of consecutive color and black sweeps.
233 Flashing lights happen on the HP820 if this
234 is -3, -2, -1, 1 , 2 or 3! */
235
236 /* test previous color swath vertical positions */
237 sweep_offset = bottom_vpos - c_vpos ;
238
239 if ( ( sweep_offset >= -4 ) &&
240 ( sweep_offset < 4 ) &&
241 ( sweep_offset != 0 || at_bottom) )
242 {
243 if ( ( at_bottom ) &&
244 ( c_vpos + 5 - sweep_offset < top_vpos + maxlines - 1 ))
245 {
246 /* we are at the bottom margin , and can add post_blanklines*/
247 post_blanklines += 4 - sweep_offset ;
248 }
249 else
250 {
251 /* we are in the middle of the page */
252 if ( ( sweep_offset > 0 ) && ( ! at_bottom ))
253 {
254 /* shift swath upward to have same vpos */
255 pre_blanklines = sweep_offset ;
256 }
257 else
258 {
259 /* shift swath up to have vertical position vpos - 5 */
260 pre_blanklines = 5 + sweep_offset ;
261 }
262 }
263 }
264 /* will add pre_blanklines blank lines at the top of the swath
265 and post_blanklines at the end of the swath. */
266 break;
267 }
268 }
269 }
270 if (got_nonblank)
271 {
272 int newleft = left, newright = right;
273
274 /* find left-most nonblank */
275 for (i = left_limit ; i < left; i++)
276 {
277 if (data[0][width8 * numlines + i])
278 {
279 newleft = i;
280 break;
281 }
282 }
283 /* find right-most nonblank */
284 for (j = right_limit - 1; j > right; j--)
285 {
286 if (data[0][width8 * numlines + j])
287 {
288 newright = j;
289 break;
290 }
291 }
292 numlines++;
293
294 if (newright < newleft)
295 {
296 DPRINTF ("Code error! newleft=%d, newright=%d, left=%d, right=%d\n",
297 newleft, newright, left, right);
298 for (k = 0; k < gMaxPass; k++)
299 {
300 free (data[k]);
301 }
302 return 0;
303 }
304
305 /* if the next line might push us over the buffer size, stop here! */
306 /* ignore this test for the 720 right now. Will add better */
307 /* size-guessing for compressed data in the near future! */
308 if (numlines % 2 == 1 && printer->version != HP7X0)
309 {
310 int l = newleft, r = newright, w;
311
312 l--;
313 r += 3;
314 w = r - l;
315
316 if ((w + 24) * numlines > printer->bufsize)
317 {
318 numlines--;
319 im_unreadline (image, data[0] + width8 * numlines);
320 break;
321 }
322 else
323 {
324 left = newleft;
325 right = newright;
326 }
327 }
328 else
329 {
330 left = newleft;
331 right = newright;
332 }
333 }
334 }
335
336 if ((gColorMode) && (image->buflines >= MAXBUFFLINES)
337 && (image->buftype == color))
338 {
339 DPRINTF ("cut_im_black_swath: exceeding buffer size: buflines=%d, MAX=%d\n",
340 image->buflines, MAXBUFFLINES);
341 if ((!got_nonblank))
342 {
343 for (k = 0; k < gMaxPass; k++)
344 {
345 free (data[k]);
346 }
347 return 3;
348 }
349 }
350
351 if ((!got_nonblank))
352 {
353 /* eat all lines that are below the lower margin */
354 if (image->blackCurLine >= bottom_limit )
355 {
356 while (image->blackCurLine < image->height)
357 if (!im_black_readline (image, data, 0))
358 {
359 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
360 gMessages[E_CS_BADBOTMARG]);
361 wrap_syslog (LOG_CRIT,"%s",syslog_message);
362
363 for (k = 0; k < gMaxPass; k++)
364 {
365 free (data[k]);
366 }
367 return 0;
368 }
369 for (k = 0; k < gMaxPass; k++)
370 {
371 free (data[k]);
372 }
373 return 1;
374 }
375 for (k = 0; k < gMaxPass; k++)
376 {
377 free (data[k]);
378 }
379 return 0;
380 /* error, since didn't get to lower margin, yet blank */
381 }
382
383
384 /* calculate vertical position */
385 sweep_data->vertical_pos = image->blackCurLine ;
386
387 /* subtract that 600 dot adjustment here */
388 sweep_data->vertical_pos -= vpos_shift;
389
390 DPRINTF("cut_im_black_swath: end swath, line %d numlines=%d left=%d right=%d\n",
391 image->blackCurLine, numlines, left, right) ;
392 /* width of the swath in bytes */
393
394
395 /* calculate number of blank lines added at top and bottom of swath */
396
397 non_blanklines = numlines ;
398 numlines += pre_blanklines ;
399 if ( (numlines + post_blanklines) % 2 )
400 post_blanklines++ ;
401 numlines += post_blanklines ;
402 assert (maxlines >= numlines );
403 sweep_data->vertical_pos += post_blanklines ;
404
405 even_pre_blanklines = odd_pre_blanklines = pre_blanklines / 2 ;
406 even_non_blanklines = odd_non_blanklines = non_blanklines / 2 ;
407 even_post_blanklines = odd_post_blanklines = post_blanklines / 2 ;
408
988 }
989 if(image->blackCurLine == last_line)
990 return 3;
991 return 0;
992 /* error, since didn't get to lower margin, yet blank */
993 }
994
995 /*
996 remove any blank lines at end of swath;
997 */
998
999 swath_limits->last_line = image->blackCurLine;
1000 swath_limits->last_line += (non_blanklines - numlines);
1001 /* calculate number of blank lines added at top and bottom of swath */
1002 numlines = non_blanklines;
1003
1004 assert (swath_limits->last_line - vpos_shift <= max_vpos);
1005 if (swath_limits->last_line - vpos_shift > min_vpos)
1006 min_vpos = swath_limits->last_line - vpos_shift;
1007 post_blanklines = min_vpos - swath_limits->last_line + vpos_shift;
1008 numlines += post_blanklines;
1009 pre_blanklines = numlines % 2;
1010 numlines += pre_blanklines;
1011
1012
1013 DPRINTF("read_black_image: end swath, line %d numlines=%d= "
1014 " (%d,%d,%d) left=%d right=%d\n",
1015 image->blackCurLine, numlines,
1016 pre_blanklines, non_blanklines, post_blanklines,
1017 left, right) ;
1018
1019
1020 assert(pre_blanklines >= 0
1021 && post_blanklines >= 0
1022 && non_blanklines >= 0
1023 && numlines <= maxlines
1024 && numlines % 2 == 0);
1025
1026 swath_limits->left = left;
1027 swath_limits->right = right;
1028 swath_limits->numlines = numlines;
1029 swath_limits->non_blanklines = non_blanklines;
1030 swath_limits->pre_blanklines = pre_blanklines;
1031 swath_limits->post_blanklines = post_blanklines;
1032
1033 return 2;
1034 }
1035
1036 int
1037 black_nozzle_data(ppaSweepData_t *sweep_data, int numlines, int margin_diff )
1038 {
1039 int i;
1040 ppaNozzleData_t nozzles[2];
1041 for (i = 0; i < 2; i++) {
1042 nozzles[i].DPI = 600;
1043 nozzles[i].pins_used_d2 = numlines / 2;
1044 nozzles[i].unused_pins_p1 = 301 - numlines;
1045 nozzles[i].first_pin = 1;
1046 if (i == 0) {
1047 nozzles[i].left_margin = sweep_data->left_margin + margin_diff;
1048 nozzles[i].right_margin = sweep_data->right_margin;
1049 if (sweep_data->direction == right_to_left)
1050 nozzles[i].nozzle_delay = 0;
1051 else
1052 nozzles[i].nozzle_delay = 6;
1053 } else {
1054 nozzles[i].left_margin = sweep_data->left_margin;
1055 nozzles[i].right_margin = sweep_data->right_margin - margin_diff;
1056 if (sweep_data->direction == right_to_left)
1057 nozzles[i].nozzle_delay = 2;
1058 else
1059 nozzles[i].nozzle_delay = 0;
1060 }
1061 }
1062
1063 sweep_data->nozzle_data_size = 2;
1064 sweep_data->nozzle_data = malloc (sizeof (nozzles));
1065 if (sweep_data->nozzle_data == NULL)
1066 return 0;
1067 memcpy (sweep_data->nozzle_data, nozzles, sizeof (nozzles));
1068 return 2;
1069 }
1070
1071 unsigned char *
1072 r2l_black_sweep(unsigned char *place, unsigned char *data,
1073 int data_width, ppaSwathLimits_t * swath_limits)
1074 {
1075 int i, j , width, evenlines, oddlines;
1076
1077 int left = swath_limits->left;
1078 int right = swath_limits->right;
1079 int non_blanklines = swath_limits->non_blanklines;
1080 int pre_blanklines = swath_limits->pre_blanklines;
1081 int post_blanklines = swath_limits->post_blanklines;
1082 int even_non_blanklines, even_pre_blanklines, even_post_blanklines;
1083 int odd_non_blanklines, odd_pre_blanklines, odd_post_blanklines;
1084 int start_even, start_odd;
1085 ppaPageLimits_t * page_limit = &BlackPageLimits;
1086
1087 #ifdef DEBUG
1088 int data_size = data_width * swath_limits->non_blanklines;
1089 #endif
1090
1091 even_pre_blanklines = odd_pre_blanklines = pre_blanklines / 2 ;
1092 even_non_blanklines = odd_non_blanklines = non_blanklines / 2 ;
1093 even_post_blanklines = odd_post_blanklines = post_blanklines / 2 ;
1094
1095 start_even= 0;
1096 start_odd = 1;
1097
1098 if ( (pre_blanklines %2 == 0) &&
1099 !(non_blanklines % 2 == 0) &&
1100 !(post_blanklines % 2 == 0) ){
1101 even_non_blanklines++ ;
1102 odd_post_blanklines++;
4091103 start_even= 0;
4101104 start_odd = 1;
411
412 if ( (pre_blanklines %2 == 0) &&
413 !(non_blanklines % 2 == 0) &&
414 !(post_blanklines % 2 == 0))
415 {
416 even_non_blanklines++ ;
417 odd_post_blanklines++;
418 start_even= 0;
419 start_odd = 1;
420 }
421 if ( !(pre_blanklines %2 == 0) &&
422 !(non_blanklines % 2 == 0) &&
423 (post_blanklines % 2 == 0))
424 {
1105 }
1106 if ( !(pre_blanklines %2 == 0) &&
1107 !(non_blanklines % 2 == 0) &&
1108 (post_blanklines % 2 == 0)){
4251109 even_pre_blanklines++;
4261110 odd_non_blanklines++;
4271111 start_even= 1;
4281112 start_odd = 0;
429 }
430 if ( !(pre_blanklines %2 == 0) &&
431 (non_blanklines % 2 == 0) &&
432 !(post_blanklines % 2 == 0))
433 {
434 even_pre_blanklines++;
435 odd_post_blanklines++;
436 start_even= 1;
437 start_odd = 0;
438 }
439
1113 }
1114 if ( !(pre_blanklines %2 == 0) &&
1115 (non_blanklines % 2 == 0) &&
1116 !(post_blanklines % 2 == 0)){
1117 even_pre_blanklines++;
1118 odd_post_blanklines++;
1119 start_even= 1;
1120 start_odd = 0;
1121 }
1122
1123 width = right - left ;
1124 evenlines = even_pre_blanklines + even_non_blanklines + even_post_blanklines;
1125 oddlines = odd_pre_blanklines + odd_non_blanklines + odd_post_blanklines;
1126
1127 assert ( oddlines == evenlines );
1128
1129 /* place 0's in the first 12 columns */
1130 memset (place, 0, evenlines * 12);
1131 place += evenlines * 12;
1132
1133 for (i = width + 11; i >= 0; i--) {
1134 int x ;
1135 if (i >= 12){
1136 x = i - 12;
1137 if( left + x < page_limit->left || left + x >= page_limit->right )
1138 {
1139 /* never print data outside the limits */
1140 memset (place, 0, evenlines);
1141 place += evenlines;
1142 } else {
1143 if ( even_pre_blanklines > 0) {
1144 /* first pre_blanklines lines are blank */
1145 memset (place, 0, even_pre_blanklines) ;
1146 place += even_pre_blanklines ;
1147 }
1148 for (j = 0; j < even_non_blanklines; j++) {
1149 int index = ((j * 2) + start_even ) * data_width + left + x;
1150 #ifdef DEBUG
1151 if (!( index < data_size && index >= 0) ){
1152 DPRINTF("index=%d, datasize= %d = %d x %d\n",
1153 index, data_size, data_width, swath_limits->non_blanklines);
1154 }
1155 assert ( index < data_size && index >= 0 );
1156 #endif
1157 *place++ = data[index];
1158 }
1159 if ( even_post_blanklines > 0 ) {
1160 /* last post_blanklines lines are blank */
1161 memset (place, 0, even_post_blanklines) ;
1162 place += even_post_blanklines ;
1163 }
1164 }
1165 } else {
1166 memset (place, 0, evenlines);
1167 place += evenlines;
1168 }
4401169
441 assert (( even_pre_blanklines + odd_pre_blanklines +
442 even_non_blanklines + odd_non_blanklines +
443 even_post_blanklines + odd_post_blanklines ) == numlines );
1170 if (i < width) {
1171 x = i ;
1172 if( left + x < page_limit->left || left + x >= page_limit->right ) {
1173 /* never print data outside the limits */
1174 memset (place, 0, evenlines);
1175 place += evenlines;
1176 } else {
1177 if ( odd_pre_blanklines > 0) {
1178 /* first pre_blanklines lines are blank */
1179 memset (place, 0, odd_pre_blanklines) ;
1180 place += odd_pre_blanklines ;
1181 }
1182 for (j = 0; j < odd_non_blanklines; j++) {
1183 int index = ((j * 2) + start_odd ) * data_width + left + x;
1184 #ifdef DEBUG
1185 if (!( index < data_size && index >= 0) ){
1186 DPRINTF("index=%d, datasize= %d = %d x %d\n",
1187 index, data_size, data_width, swath_limits->non_blanklines);
1188 }
1189 assert ( index < data_size && index >= 0 );
1190 #endif
1191 *place++ = data[index];
1192 }
1193 if ( odd_post_blanklines > 0 ){
1194 /* last post_blanklines lines are blank */
1195 memset (place, 0, odd_post_blanklines) ;
1196 place += odd_post_blanklines ;
1197 }
1198 }
1199 } else {
1200 memset (place, 0, evenlines);
1201 place += evenlines;
1202 }
1203 }
1204 /* place 0's in the last 12 columns */
1205 memset (place, 0, evenlines * 12);
1206 place += evenlines * 12;
1207 return place;
1208 }
1209
1210 unsigned char *
1211 l2r_black_sweep(unsigned char *place, unsigned char *data,
1212 int data_width, ppaSwathLimits_t * swath_limits)
1213 {
1214 int i, j , width, evenlines, oddlines;
1215
1216 int left = swath_limits->left;
1217 int right = swath_limits->right;
1218 int non_blanklines = swath_limits->non_blanklines;
1219 int pre_blanklines = swath_limits->pre_blanklines;
1220 int post_blanklines = swath_limits->post_blanklines;
1221 int even_non_blanklines, even_pre_blanklines, even_post_blanklines;
1222 int odd_non_blanklines, odd_pre_blanklines, odd_post_blanklines;
1223 int start_even, start_odd;
1224 ppaPageLimits_t * page_limit = &BlackPageLimits;
1225
1226 #ifdef DEBUG
1227 int data_size = data_width * swath_limits->non_blanklines;
1228 #endif
1229
1230 even_pre_blanklines = odd_pre_blanklines = pre_blanklines / 2 ;
1231 even_non_blanklines = odd_non_blanklines = non_blanklines / 2 ;
1232 even_post_blanklines = odd_post_blanklines = post_blanklines / 2 ;
1233
1234 start_even= 0;
1235 start_odd = 1;
1236
1237 if ( (pre_blanklines %2 == 0) &&
1238 !(non_blanklines % 2 == 0) &&
1239 !(post_blanklines % 2 == 0)) {
1240 even_non_blanklines++ ;
1241 odd_post_blanklines++;
1242 start_even= 0;
1243 start_odd = 1;
1244 }
1245 if ( !(pre_blanklines %2 == 0) &&
1246 !(non_blanklines % 2 == 0) &&
1247 (post_blanklines % 2 == 0)) {
1248 even_pre_blanklines++;
1249 odd_non_blanklines++;
1250 start_even= 1;
1251 start_odd = 0;
1252 }
1253 if ( !(pre_blanklines %2 == 0) &&
1254 (non_blanklines % 2 == 0) &&
1255 !(post_blanklines % 2 == 0)) {
1256 even_pre_blanklines++;
1257 odd_post_blanklines++;
1258 start_even= 1;
1259 start_odd = 0;
1260 }
1261
1262 width = right - left ;
1263 evenlines = even_pre_blanklines + even_non_blanklines + even_post_blanklines;
1264 oddlines = odd_pre_blanklines + odd_non_blanklines + odd_post_blanklines;
1265
1266 assert ( oddlines == evenlines );
1267
1268 /* place 0's in the first 12 columns */
1269 memset (place, 0, evenlines * 12);
1270 place += evenlines * 12;
1271
1272 for (i = 0; i < width + 12; i++) {
1273 int x;
1274 if (i < width) {
1275 x = i;
1276 if( left + x < page_limit->left || left + x >= page_limit->right ) {
1277 /* never print data outside the limits */
1278 memset (place, 0, evenlines);
1279 place += evenlines;
1280 } else {
1281 if ( odd_pre_blanklines > 0) {
1282 /* first pre_blanklines lines are blank */
1283 memset (place, 0, odd_pre_blanklines) ;
1284 place += odd_pre_blanklines ;
1285 }
1286 for (j = 0; j < odd_non_blanklines; j++){
1287 int index = ((j * 2) + start_odd) * data_width + left + x;
1288 #ifdef DEBUG
1289 if (!( index < data_size && index >= 0) ){
1290 DPRINTF("index=%d, datasize= %d = %d x %d\n",
1291 index, data_size, data_width, swath_limits->non_blanklines);
1292 }
1293 assert ( index < data_size && index >= 0 );
1294 #endif
1295 *place++ = data[index];
1296 }
1297 if ( odd_post_blanklines > 0 ){
1298 /* last post_blanklines lines are blank */
1299 memset (place, 0, odd_post_blanklines) ;
1300 place += odd_post_blanklines ;
1301 }
1302 }
1303 } else {
1304 memset (place, 0, evenlines);
1305 place += evenlines;
1306 }
4441307
445 if (pre_blanklines)
446 {
447 DPRINTF("cut_im_black_swath: offset %d; add pre_blanklines=%d lines\n",
448 sweep_offset, pre_blanklines);
449 }
450 if (post_blanklines)
451 {
452 DPRINTF("cut_im_black_swath: offset %d; add post_blanklines=%d lines\n",
453 sweep_offset, post_blanklines);
454 }
455
456
457 /* change sweep params */
458 /* ensures at least 4 bytes sweep width */
459 right +=3;
460 left-- ;
461 p_width8 = right - left;
462
1308 if (i >= 12){
1309 x = i - 12;
1310 if( left + x < page_limit->left || left + x >= page_limit->right ) {
1311 /* never print data outside the limits */
1312 memset (place, 0, evenlines);
1313 place += evenlines;
1314 } else {
1315 if ( even_pre_blanklines > 0) {
1316 /* first pre_blanklines lines are blank */
1317 memset (place, 0, even_pre_blanklines) ;
1318 place += even_pre_blanklines ;
1319 }
1320 for (j = 0; j < even_non_blanklines; j++) {
1321 int index = ((j * 2) + start_even) * data_width + left + x;
1322 #ifdef DEBUG
1323 if (!( index < data_size && index >= 0) ){
1324 DPRINTF("index=%d, datasize= %d = %d x %d\n",
1325 index, data_size, data_width, swath_limits->non_blanklines);
1326 }
1327 assert ( index < data_size && index >= 0 );
1328 #endif
1329 *place++ = data[index];
1330 }
1331 if ( even_post_blanklines > 0 ){
1332 /* last post_blanklines lines are blank */
1333 memset (place, 0, even_post_blanklines) ;
1334 place += even_post_blanklines ;
1335 }
1336 }
1337 } else {
1338 memset (place, 0, evenlines);
1339 place += evenlines;
1340 }
1341 }
1342 /* place 0's in the last 12 columns */
1343 memset (place, 0, evenlines * 12);
1344 place += evenlines * 12;
1345
1346 return place;
1347 }
1348
1349 int
1350 cut_im_color_swath (image_t *image, ppaPrinter_t *printer,
1351 ppaSweepData_t *sweep_data[4])
1352 {
1353 unsigned char *data[4], *ppa, *place, *maxplace;
1354 int j, k;
1355 int width, byte_width =(image->width / 2 + 7) / 8;
1356 int vpos_shift=600; /* "vertical position" = line number - vpos_shift */
1357 int sweep_dir, sweep_vpos;
1358 int horizpos;
1359 int maxlines = 64; /* fixed by design of print head */
1360 ppaSwathLimits_t Swath_Limits;
1361 ppaSwathLimits_t *swath_limits = &Swath_Limits;
1362 ppaPageLimits_t *page_limit = &ColorPageLimits;
1363
1364 place = NULL;
1365 ppa = NULL;
1366 maxplace = NULL;
1367
1368 /* safeguard against the user freeing these */
1369 for (k = 0; k < gMaxPass; k++) {
1370 sweep_data[k]->nozzle_data = NULL;
1371 sweep_data[k]->image_data = NULL;
1372 }
1373
1374 DPRINTF ("byte_width * 3 * maxlines = %d\n", byte_width * 3 * maxlines);
1375 for (k = 0; k < gMaxPass; k++) {
1376 if ((data[k] = malloc ( byte_width * 3 * maxlines + 8)) == NULL){
1377 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1378 gMessages[E_CS_BADMALLOC]);
1379 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1380 return 0;
1381 }
1382 }
1383 /* read the image data from the input file */
1384 {
1385 int retval;
1386 retval = read_color_image(data, image, printer, byte_width,
1387 vpos_shift, maxlines, swath_limits);
1388 if (retval != 2) {
1389 for (k = 0; k < gMaxPass; k++)
1390 free (data[k]);
1391 return retval;
1392 }
4631393
464 if ((ppa = malloc ((p_width8 + 24) * numlines)) == NULL)
465 {
466 snprintf(syslog_message,message_size,"cut_im_black_swath(): %s",
467 gMessages[E_CS_BADPPAMALLOC]);
1394 }
1395 /* analysis of the image is now complete */
1396
1397 /* now determine vertical position of swath */
1398 sweep_vpos = swath_limits->last_line + 2 * swath_limits->post_blanklines;
1399 sweep_vpos += printer->ColBwOffsY ;
1400 /* subtract that 600 dot adjustment here */
1401 sweep_vpos -= vpos_shift;
1402
1403 /* printing in the leftmost and rightmost bytes of the color
1404 * swath leads to problems, so expand the swath width to avoid
1405 * using these locations. Nothing will ever get printed in these
1406 * expanded ends of the swath. (They are either whitespace,
1407 * or outside the limits, where data is rejected below)
1408 */
1409 swath_limits->left -= 2;
1410 swath_limits->right += 3;
1411 /* enforce a minimum swath width of 8 bytes */
1412 if ( swath_limits->right - swath_limits->left < 8 ) {
1413 if (swath_limits->right > page_limit->left + 8 )
1414 swath_limits->left = swath_limits->right - 8 ;
1415 else
1416 swath_limits->right = swath_limits->left + 8 ;
1417 }
1418
1419 /* fix sweep direction (right_to_left or left_to_right) */
1420 sweep_dir = unknown;
1421 if (gCalibrate && !gUnimode) {
1422 /* legacy pnm2ppa-1.04 method for choosing sweep direction */
1423 if (prev_color_dir == unknown &&
1424 prev_black_dir == unknown )
1425 sweep_dir = left_to_right;
1426 else if ( prev_black_vpos > prev_color_vpos &&
1427 prev_black_vpos < sweep_vpos ) {
1428 if (prev_black_dir == left_to_right)
1429 sweep_dir = right_to_left;
1430 else
1431 sweep_dir = left_to_right;
1432 } else {
1433 if (prev_color_dir == left_to_right)
1434 sweep_dir = right_to_left;
1435 else
1436 sweep_dir = left_to_right;
1437 }
1438 } else if (!gUnimode && gMaxPass % 2){
1439 int opposite_dir = unknown;
1440 /* the correct sweep direction is not yet known, and must be
1441 guessed from sweep_vpos and the previous history
1442 (only for gMaxPass == 1) */
1443
1444 if (current_swath){
1445 if (prev_black_dir != unknown &&
1446 prev_black_vpos < sweep_vpos
1447 && current_swath->vertical_pos < prev_black_vpos )
1448 opposite_dir = prev_black_dir;
1449 else
1450 opposite_dir = current_swath->direction;
1451 } else {
1452 /* must be at beginning of page, when prev is still NULL */
1453 if (prev_black_dir != unknown )
1454 opposite_dir = prev_black_dir;
1455 else /* this is the first time data was found */
1456 opposite_dir= right_to_left;
1457 }
1458 if (opposite_dir == left_to_right)
1459 sweep_dir = right_to_left;
1460 else if (opposite_dir == right_to_left)
1461 sweep_dir = left_to_right;
1462 }
1463
1464 /* create sweep_data for gMaxPass sweeps of the color print head */
1465
1466 for (k = 0; k < gMaxPass; k++) {
1467 sweep_data[k]->direction = sweep_dir;
1468 if(!gUnimode && !(gMaxPass %2 ) && !gCalibrate) {
1469 if( k %2 )
1470 sweep_data[k]->direction = right_to_left;
1471 else
1472 sweep_data[k]->direction = left_to_right;
1473 }
1474 if (gUnimode){
1475 if (gPixmapMode)
1476 sweep_data[k]->direction = left_to_right;
1477 else
1478 sweep_data[k]->direction = right_to_left;
1479 }
1480
1481 assert ( sweep_data[k]->direction != unknown );
1482 sweep_data[k]->vertical_pos = sweep_vpos;
1483 sweep_data[k]->in_color = true;
1484 sweep_data[k]->image_data = NULL;
1485 sweep_data[k]->first_data_line = swath_limits->first_line;
1486 sweep_data[k]->last_data_line = swath_limits->last_line;
1487 sweep_data[k]->pre_blanklines = swath_limits->pre_blanklines;
1488 sweep_data[k]->post_blanklines = swath_limits->post_blanklines;
1489
1490 /* create sweep image_data */
1491 width = swath_limits->right - swath_limits->left + 3;
1492 if ((ppa = malloc ( width * swath_limits->numlines * 3)) == NULL){
1493 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1494 gMessages[E_CS_BADPPAMALLOC]);
1495 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1496
1497 for (j = k ; j < gMaxPass; j++)
1498 free (data[j]); /* free unprocessed data */
1499 for (j = 0; j < k; j++){
1500 free (sweep_data[j]->image_data);
1501 free (sweep_data[j]->nozzle_data);
1502 }
1503 return 0;
1504 }
1505 place = ppa;
1506 if (sweep_data[k]->direction == right_to_left)
1507 maxplace = r2l_color_sweep(place, data[k], byte_width,
1508 swath_limits);
1509 else /* sweep direction is left-to-right */
1510 maxplace = l2r_color_sweep(place, data[k], byte_width,
1511 swath_limits);
1512 free (data[k]); /* finished with data[k] */
1513 sweep_data[k]->image_data = ppa;
1514 sweep_data[k]->data_size = maxplace - ppa;
1515
1516 /*
1517 left and right limits of sweep
1518 (looks like some tweaks have been made!)
1519 */
1520
1521 horizpos = (swath_limits->left - 7 ) * 8 * 2;
1522 horizpos += printer->ColBwOffsX - 600;
1523 horizpos += (sweep_data[k]->direction == left_to_right) ? 2 : 12 ;
1524
1525 /*correct bidirectional shearing*/
1526 if (sweep_data[k]->direction == right_to_left )
1527 horizpos += printer->r2l_col_offset ;
1528
1529 sweep_data[k]->left_margin = horizpos;
1530 sweep_data[k]->right_margin = horizpos + 0x74 + (width - 2 ) * 2 * 8;
1531 /* 0x74 used to be "printer->color_marg_diff" */
1532
1533 DPRINTF("sweep data: left_margin = %d, right margin = %d\n",
1534 sweep_data[k]->left_margin, sweep_data[k]->right_margin);
1535
1536 if (!color_nozzle_data(sweep_data[k], swath_limits->numlines)){
1537 DPRINTF("color_nozzle_data: malloc failed");
1538 for (j=k; j < gMaxPass; j++)
1539 free(data[j]);
1540 for (j=0; j <= k; j++)
1541 free(sweep_data[k]->image_data);
1542 for (j = 0; j < k; j++)
1543 free(sweep_data[j]->nozzle_data);
1544 return 0;
1545 }
1546 prev_color_vpos = sweep_data[k]->vertical_pos;
1547 prev_color_dir = sweep_data[k]->direction;
1548 }
1549 DPRINTF ("cut_im_color_swath: created swath, return 2\n");
1550 return 2;
1551 }
1552
1553
1554 int
1555 read_color_image( unsigned char *data[], image_t *image,
1556 ppaPrinter_t *printer, int byte_width,
1557 int vpos_shift, int maxlines,
1558 ppaSwathLimits_t *swath_limits)
1559 {
1560 int i, j;
1561 int numlines;
1562 int left, right;
1563 int non_blanklines = 0, pre_blanklines = 0, post_blanklines = 0 ;
1564 int min_vpos;
1565 BOOLEAN got_nonblank;
1566 ppaPageLimits_t *page_limit = &ColorPageLimits;
1567 BOOLEAN colorline = true;;
1568
1569 /*
1570 Flashing lights happen on the HP820 if difference of consecutive
1571 vertical_pos of (different ink ?) sweeps
1572 is -3, -2, -1, 1 , 2 or 3!
1573 */
1574
1575 /* are there any circumstances which require that
1576 this swath has the same vertical_pos as current_swath?
1577 assume not, for the moment.
1578 */
1579 min_vpos = image->colorCurLine - vpos_shift + printer->ColBwOffsY;
1580 if (current_swath && !current_swath->in_color ) {
1581 if(min_vpos < current_swath->vertical_pos + 4)
1582 min_vpos = current_swath->vertical_pos + 4;
1583 }
1584 if (waiting_black) {
1585 if(min_vpos < waiting_black->vertical_pos + 4)
1586 min_vpos = waiting_black->vertical_pos + 4;
1587 }
1588
1589
1590 /* eat all lines that are below the lower margin */
1591 if (image->colorCurLine >= page_limit->bottom ) {
1592 while (image->colorCurLine < image->height)
1593 if (!im_color_readline (image, data, 0)){
1594 snprintf(syslog_message,message_size,"read_color_image(): %s",
1595 gMessages[E_CS_BADBOTMARG]);
4681596 wrap_syslog (LOG_CRIT,"%s",syslog_message);
469
470 for (k = 0; k < gMaxPass; k++)
471 {
472 free (data[k]);
1597 return 0;
1598 }
1599 DPRINTF (" read_color_image: return 1 on line %d\n", __LINE__);
1600 return 1;
1601 }
1602
1603
1604 left = page_limit->right - 1;
1605 right = page_limit->left;
1606
1607 got_nonblank = false;
1608 numlines = 0;
1609 pre_blanklines = 0;
1610 post_blanklines = 0;
1611 /* eat all beginning blank lines and then up to maxlines or lower margin */
1612 while (
1613 ( image->colorCurLine + (2* pre_blanklines) < page_limit->bottom ) &&
1614 ( (numlines + pre_blanklines + post_blanklines) < maxlines)
1615 && (got_nonblank ||
1616 ((image->buflines < MAXBUFFLINES) || (image->buftype == color)))){
1617
1618 if (!im_color_readline (image, data, byte_width * 3 * numlines)) {
1619 snprintf(syslog_message,message_size,"read_color_image(): %s",
1620 gMessages[E_CS_BADNEXTLINE]);
1621 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1622 return 0;
1623 }
1624 colorline = image->LineType[image->colorCurLine - 2] & COLORLINE;
1625 if (!got_nonblank){
1626 if (colorline) {
1627 for (i = page_limit->left * 3; i < page_limit->right * 3; i++){
1628 if ((data[gMaxPass - 1][i])){
1629 left = i / 3;
1630 got_nonblank = true;
1631 right = left;
1632 for (j = page_limit->right * 3 - 1; j > left * 3 + 2; j--) {
1633 if ((data[gMaxPass - 1][j])){
1634 right = j / 3;
1635 break;
1636 }
1637 }
1638 break;
4731639 }
474 return 0;
475 }
476
477 place = ppa;
478
479
480 /* always left-to-right if gUnimode is true */
481 if (gUnimode)
482 sweep_data->direction = left_to_right;
483 else if ((b_vpos > c_vpos) || (c_vpos > sweep_data->vertical_pos))
484 {
485 if (b_dir == left_to_right)
486 sweep_data->direction = right_to_left;
487 else
488 sweep_data->direction = left_to_right;
489 } else {
490 if (c_dir == left_to_right)
491 sweep_data->direction = right_to_left;
492 else
493 sweep_data->direction = left_to_right;
494 }
495
496 DPRINTF("cut_im_black_swath: prev b_left %d b_right %d b_vpos %d b_dir %d\n",
497 b_left, b_right, b_vpos, b_dir);
498 DPRINTF("cut_im_black_swath: cur left %d right %d vpos %d dir %d\n",
499 left, right, sweep_data->vertical_pos, sweep_data->direction);
500 b_left = left;
501 b_right = right;
502 b_vpos = sweep_data->vertical_pos;
503 b_dir = sweep_data->direction;
504 DPRINTF("cut_im_black_swath: c_left %d c_right %d c_vpos %d c_dir %d\n",
505 c_left, c_right, c_vpos, c_dir);
506
507 /* place 0's in the first 12 columns */
508 memset (place, 0, numlines / 2 * 12);
509 place += numlines / 2 * 12;
510
511 if (sweep_data->direction == left_to_right)
512 DPRINTF ("black: sweep_data->direction == left_to_right\n");
513 else if (sweep_data->direction == right_to_left)
514 DPRINTF ("black: sweep_data->direction == right_to_left\n");
515 else
516 DPRINTF ("black: sweep_data->direction == *** ERROR: NOT SET! \n");
517
518 if (sweep_data->direction == right_to_left) /* right-to-left */
519 {
520 for (i = p_width8 + 11; i >= 0; i--)
521 {
522 int x ;
523 if (i >= 12 )
524 {
525 x = i - 12;
526 if( left + x < left_limit || left + x >= right_limit )
527 {
528 /* never print data outside the limits */
529 memset (place, 0, numlines / 2);
530 place += numlines / 2;
531 }
532 else
533 {
534 if ( even_pre_blanklines > 0)
535 {
536 /* first pre_blanklines lines are blank */
537 memset (place, 0, even_pre_blanklines) ;
538 place += even_pre_blanklines ;
539 }
540 for (j = 0; j < even_non_blanklines; j++)
541 {
542 *place++ = data[0][((j * 2) + start_even ) * width8 + left + x];
543 }
544 if ( even_post_blanklines > 0 )
545 {
546 /* last post_blanklines lines are blank */
547 memset (place, 0, even_post_blanklines) ;
548 place += even_post_blanklines ;
549 }
550 }
551 }
552 else
553 {
554 memset (place, 0, numlines / 2);
555 place += numlines / 2;
556 }
557
558 if (i < p_width8)
559 {
560 x = i ;
561 if( left + x < left_limit || left + x >= right_limit )
562 {
563 /* never print data outside the limits */
564 memset (place, 0, numlines / 2);
565 place += numlines / 2;
566 }
567 else
568 {
569 if ( odd_pre_blanklines > 0)
570 {
571 /* first pre_blanklines lines are blank */
572 memset (place, 0, odd_pre_blanklines) ;
573 place += odd_pre_blanklines ;
574 }
575 for (j = 0; j < odd_non_blanklines; j++)
576 {
577 *place++ = data[0][((j * 2) + start_odd ) * width8 + left + x];
578 }
579 if ( odd_post_blanklines > 0 )
580 {
581 /* last post_blanklines lines are blank */
582 memset (place, 0, odd_post_blanklines) ;
583 place += odd_post_blanklines ;
584 }
585 }
586 }
587 else
588 {
589 memset (place, 0, numlines / 2);
590 place += numlines / 2;
591 }
1640 }
1641 }
1642 if(got_nonblank) {
1643 /* begin a new swath;, nonblank pixels occur in
1644 * bytes "left" through "right", inclusive,
1645 * where
1646 * page_limit->left <= left <= right < page_limit->right.
1647 * This range will be expanded if necessary
1648 * as the swath is constructed
1649 */
1650 DPRINTF("read_color_image: begin swath, line %d\n",
1651 image->colorCurLine ) ;
1652
1653 numlines = 1;
1654 non_blanklines = 1;
1655 swath_limits->first_line = image->colorCurLine;
1656 /* We assume this is true! */
1657 assert (image->colorCurLine - vpos_shift + printer->ColBwOffsY
1658 + -1 + ( 2 * maxlines) >= min_vpos);
1659 }
1660 } else {
1661 /* find left-most nonblank */
1662 if (colorline) {
1663 for (i = page_limit->left * 3; i < left * 3; i++) {
1664 if ((data[gMaxPass - 1][byte_width * 3 * numlines + i])){
1665 left = i / 3;
1666 break;
5921667 }
593 }
594 else /* sweep_data->direction == left_to_right */
595 {
596 for (i = 0; i < p_width8 + 12; i++)
597 {
598 int x;
599 if (i < p_width8)
600 {
601 x = i;
602 if( left + x < left_limit || left + x >= right_limit )
603 {
604 /* never print data outside the limits */
605 memset (place, 0, numlines / 2);
606 place += numlines / 2;
607 }
608 else
609 {
610 if ( odd_pre_blanklines > 0)
611 {
612 /* first pre_blanklines lines are blank */
613 memset (place, 0, odd_pre_blanklines) ;
614 place += odd_pre_blanklines ;
615 }
616 for (j = 0; j < odd_non_blanklines; j++)
617 {
618 *place++ = data[0][((j * 2) + start_odd) * width8 + left + x];
619 }
620 if ( odd_post_blanklines > 0 )
621 {
622 /* last post_blanklines lines are blank */
623 memset (place, 0, odd_post_blanklines) ;
624 place += odd_post_blanklines ;
625 }
626 }
627 }
628 else
629 {
630 memset (place, 0, numlines / 2);
631 place += numlines / 2;
632 }
633
634 if (i >= 12)
635 {
636 x = i - 12;
637 if( left + x < left_limit || left + x >= right_limit )
638 {
639 /* never print data outside the limits */
640 memset (place, 0, numlines / 2);
641 place += numlines / 2;
642 }
643 else
644 {
645 if ( even_pre_blanklines > 0)
646 {
647 /* first pre_blanklines lines are blank */
648 memset (place, 0, even_pre_blanklines) ;
649 place += even_pre_blanklines ;
650 }
651 for (j = 0; j < even_non_blanklines; j++)
652 {
653 *place++ = data[0][((j * 2) + start_even) * width8 + left + x];
654 }
655 if ( even_post_blanklines > 0 )
656 {
657 /* last post_blanklines lines are blank */
658 memset (place, 0, even_post_blanklines) ;
659 place += even_post_blanklines ;
660 }
661 }
662 }
663 else
664 {
665 memset (place, 0, numlines / 2);
666 place += numlines / 2;
667 }
1668 }
1669 /* find right-most nonblank */
1670 for (j = page_limit->right * 3 - 1 ; j > right * 3 + 2 ; j--){
1671 if ((data[gMaxPass - 1][byte_width * 3 * numlines + j])){
1672 right = j / 3;
1673 break;
6681674 }
669 }
670
671 /* done with data */
672 for (k = 0; k < gMaxPass; k++)
673 {
674 if (data[k] != NULL)
675 {
676 free (data[k]);
677 }
678 }
679
680 /* place 0's in the last 12 columns */
681 memset (place, 0, numlines / 2 * 12);
682 place += numlines / 2 * 12;
683 maxplace = place;
684
685 /* create sweep data */
686 sweep_data->image_data[0] = ppa;
687 sweep_data->data_size = maxplace - ppa;
688 sweep_data->in_color = false;
689
690 horzpos = left * 8 ;
691
692 horzpos += (sweep_data->direction == left_to_right) ? 1 : 0;
693
694 if (sweep_data->direction == right_to_left )
695 horzpos += printer->r2l_bw_offset ;/* correct bidirectional shearing */
696
697 hp2 = horzpos + (p_width8 + 24) * 8;
698
699
700 sweep_data->left_margin = horzpos;
701 sweep_data->right_margin = hp2 + printer->marg_diff;
702
703 for (i = 0; i < 2; i++)
704 {
705 nozzles[i].DPI = 600;
706 nozzles[i].pins_used_d2 = numlines / 2;
707 nozzles[i].unused_pins_p1 = 301 - numlines;
708 nozzles[i].first_pin = 1;
709 if (i == 0)
710 {
711 nozzles[i].left_margin = horzpos + printer->marg_diff;
712 nozzles[i].right_margin = hp2 + printer->marg_diff;
713 if (sweep_data->direction == right_to_left)
714 nozzles[i].nozzle_delay = 0;
715 else
716 nozzles[i].nozzle_delay = 6; //6
717 }
718 else
719 {
720 nozzles[i].left_margin = horzpos;
721 nozzles[i].right_margin = hp2;
722 if (sweep_data->direction == right_to_left)
723 nozzles[i].nozzle_delay = 2;
724 else
725 nozzles[i].nozzle_delay = 0;
726 }
727 }
728
729 sweep_data->nozzle_data_size = 2;
730 sweep_data->nozzle_data = malloc (sizeof (nozzles));
731 if (sweep_data->nozzle_data == NULL)
732 return 0;
733 memcpy (sweep_data->nozzle_data, nozzles, sizeof (nozzles));
734
735 return 2;
1675 }
1676 }
1677 numlines++;
1678 if (colorline)
1679 non_blanklines = numlines;
1680 }
1681 }
1682
1683 if ((image->buflines >= MAXBUFFLINES) && (image->buftype == bitmap)){
1684 DPRINTF
1685 ("read_color_image: exceeding buffer size: image.buflines=%d, MAX=%d\n",
1686 image->buflines, MAXBUFFLINES);
1687 if ((!got_nonblank))
1688 return 3;
1689 }
1690
1691
1692 if ((!got_nonblank)){
1693 /* eat all lines that are below the lower margin */
1694 if (image->colorCurLine >= page_limit->bottom){
1695 while (image->colorCurLine < image->height)
1696 if (!im_color_readline (image, data, 0)){
1697 snprintf(syslog_message,message_size,"read_color_image(): %s",
1698 gMessages[E_CS_BADBOTMARG]);
1699 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1700 return 0;
1701 }
1702 DPRINTF
1703 ("read_color_image: return 1 on line %d; ccl: %d; height: %d\n",
1704 __LINE__, image->colorCurLine, page_limit->bottom );
1705 return 1;
1706 }
1707 return 0;
1708 /* error, since didn't get to lower margin, yet blank */
1709 }
1710
1711 /*
1712 remove any blank lines at end of swath;
1713 */
1714
1715 swath_limits->last_line = image->colorCurLine;
1716 swath_limits->last_line += 2*(non_blanklines - numlines);
1717 numlines = non_blanklines;
1718
1719 post_blanklines = 0;
1720 if(swath_limits->last_line - vpos_shift + printer->ColBwOffsY < min_vpos)
1721 post_blanklines = min_vpos + vpos_shift - printer->ColBwOffsY
1722 - swath_limits->last_line;
1723
1724 numlines += post_blanklines;
1725 pre_blanklines = numlines % 2;
1726 numlines += pre_blanklines;
1727
1728 DPRINTF("read_color_image: end swath, line %d numlines=%d= "
1729 " (%d,%d,%d) left=%d right=%d\n",
1730 image->colorCurLine, numlines,
1731 pre_blanklines, non_blanklines, post_blanklines,
1732 left, right) ;
1733
1734 swath_limits->left = left;
1735 swath_limits->right = right;
1736 swath_limits->numlines = numlines;
1737 swath_limits->non_blanklines = non_blanklines;
1738 swath_limits->pre_blanklines = pre_blanklines;
1739 swath_limits->post_blanklines = post_blanklines;
1740
1741 return 2;
7361742 }
1743
1744 int
1745 color_nozzle_data(ppaSweepData_t * sweep_data, int numlines)
1746 {
1747 int i;
1748 ppaNozzleData_t nozzles[6];
1749
1750 /* create nozzle data for sweep */
1751
1752 for (i = 0; i < 6; i++){
1753 nozzles[i].DPI = 300;
1754 nozzles[i].pins_used_d2 = numlines / 2;
1755 nozzles[i].unused_pins_p1 = 65 - numlines;
1756 nozzles[i].first_pin = 1;
1757 if (i == 0){
1758 nozzles[i].left_margin = sweep_data->left_margin + 0x74;
1759 nozzles[i].right_margin = sweep_data->right_margin;
1760 if (sweep_data->direction == right_to_left)
1761 nozzles[i].nozzle_delay = 0;
1762 else
1763 nozzles[i].nozzle_delay = 0;
1764 }
1765 if (i == 1){
1766 nozzles[i].left_margin = sweep_data->left_margin + 0x64;
1767 nozzles[i].right_margin = sweep_data->right_margin - 0x10;
1768 if (sweep_data->direction == right_to_left)
1769 nozzles[i].nozzle_delay = 0;
1770 else
1771 nozzles[i].nozzle_delay = 0;
1772 }
1773 if (i == 2){
1774 nozzles[i].left_margin = sweep_data->left_margin + 0x3A;
1775 nozzles[i].right_margin = sweep_data->right_margin -0x3A;
1776 if (sweep_data->direction == right_to_left)
1777 nozzles[i].nozzle_delay = 0x0A;
1778 else
1779 nozzles[i].nozzle_delay = 0x0A;
1780 }
1781 if (i == 3){
1782 nozzles[i].left_margin = sweep_data->left_margin + 0x3A;
1783 nozzles[i].right_margin = sweep_data->right_margin - 0x3A;
1784 if (sweep_data->direction == right_to_left)
1785 nozzles[i].nozzle_delay = 0x0A;
1786 else
1787 nozzles[i].nozzle_delay = 0x0A;
1788
1789 }
1790 if (i == 4){
1791 nozzles[i].left_margin = sweep_data->left_margin + 0x10;
1792 nozzles[i].right_margin = sweep_data->right_margin - 0x64;
1793 if (sweep_data->direction == right_to_left)
1794 nozzles[i].nozzle_delay = 0x04;
1795 else
1796 nozzles[i].nozzle_delay = 0x04;
1797
1798 }
1799 if (i == 5){
1800 nozzles[i].left_margin = sweep_data->left_margin;
1801 nozzles[i].right_margin = sweep_data->right_margin - 0x74;
1802 if (sweep_data->direction == right_to_left)
1803 nozzles[i].nozzle_delay = 0x04;
1804 else
1805 nozzles[i].nozzle_delay = 0x04;
1806
1807 }
1808 }
1809
1810 sweep_data->nozzle_data_size = 6;
1811 sweep_data->nozzle_data = malloc (sizeof (nozzles));
1812 if (sweep_data->nozzle_data == NULL)
1813 return 0;
1814 memcpy (sweep_data->nozzle_data, nozzles, sizeof (nozzles));
1815 return 2;
1816 }
1817
1818
1819 #define GET_USABLE(A,i) (!(A[i] & 0x1))
1820 #define GET_COLOR(A,i) ((A[i] >> 1) & 0x3);
1821 #define GET_ODD(A,i) ((A[i] >> 3) & 0x1);
1822 #define GET_X(A,i) ((A[i] >> 4));
7371823
7381824 #define UNUSABLE 1
7391825 #define CYAN (0<<1)
7451831 #define XPOS(x) ((x)<<XSHIFT)
7461832
7471833
1834
7481835 /* number of "special" columns at left of sweep */
7491836 /* different versions for left-to-right and right-to-left sweeps */
7501837 static int Right_size = 42;
7921879 CYAN | ODD | XPOS (7),
7931880 CYAN | EVEN | XPOS (8)
7941881 };
795 static int Right_r2l[] = {
796 UNUSABLE,
797 UNUSABLE,
798 UNUSABLE,
799 CYAN | EVEN | XPOS (0),
800 UNUSABLE,
801 CYAN | EVEN | XPOS (1),
802 CYAN | ODD | XPOS (0),
803 UNUSABLE,
804 UNUSABLE,
805 CYAN | EVEN | XPOS (2),
806 CYAN | ODD | XPOS (1),
807 UNUSABLE,
808 UNUSABLE,
809 CYAN | EVEN | XPOS (3),
810 CYAN | ODD | XPOS (2),
811 MAGENTA | EVEN | XPOS (0),
812 UNUSABLE,
813 CYAN | EVEN | XPOS (4),
814 CYAN | ODD | XPOS (3),
815 UNUSABLE,
816 MAGENTA | EVEN | XPOS (1),
817 MAGENTA | ODD | XPOS (0),
818 CYAN | EVEN | XPOS (5),
819 CYAN | ODD | XPOS (4),
820 UNUSABLE,
821 UNUSABLE,
822 MAGENTA | EVEN | XPOS (2),
823 MAGENTA | ODD | XPOS (1),
824 CYAN | EVEN | XPOS (6),
825 CYAN | ODD | XPOS (5),
826 UNUSABLE,
827 UNUSABLE,
828 MAGENTA | EVEN | XPOS (3),
829 MAGENTA | ODD | XPOS (2),
830 CYAN | EVEN | XPOS (7),
831 CYAN | ODD | XPOS (6),
832 YELLOW | EVEN | XPOS (0),
833 UNUSABLE,
834 MAGENTA | EVEN | XPOS (4),
835 MAGENTA | ODD | XPOS (3),
836 CYAN | EVEN | XPOS (8),
837 CYAN | ODD | XPOS (7)
838 };
1882
8391883
8401884 /* number of "special" columns at left of sweep */
8411885 static int Left_size = 32;
8741918 CYAN | ODD | XPOS (1)
8751919 };
8761920
1921
1922 unsigned char *
1923 l2r_color_sweep(unsigned char *place, unsigned char *data,
1924 int data_width, ppaSwathLimits_t * swath_limits)
1925 {
1926 int i, j , width, evenlines, oddlines;
1927
1928 int left = swath_limits->left;
1929 int right = swath_limits->right;
1930 int non_blanklines = swath_limits->non_blanklines;
1931 int pre_blanklines = swath_limits->pre_blanklines;
1932 int post_blanklines = swath_limits->post_blanklines;
1933 int even_non_blanklines, even_pre_blanklines, even_post_blanklines;
1934 int odd_non_blanklines, odd_pre_blanklines, odd_post_blanklines;
1935 int start_even, start_odd;
1936 ppaPageLimits_t * page_limit = &ColorPageLimits;
1937
1938 #ifdef DEBUG
1939 int data_size = data_width * 3 * swath_limits->non_blanklines;
1940 #endif
1941
1942
1943 even_pre_blanklines = odd_pre_blanklines = pre_blanklines / 2 ;
1944 even_non_blanklines = odd_non_blanklines = non_blanklines / 2 ;
1945 even_post_blanklines = odd_post_blanklines = post_blanklines / 2 ;
1946
1947 start_even= 0;
1948 start_odd = 1;
1949
1950 if ( (pre_blanklines %2 == 0) &&
1951 !(non_blanklines % 2 == 0) &&
1952 !(post_blanklines % 2 == 0)) {
1953 even_non_blanklines++ ;
1954 odd_post_blanklines++;
1955 start_even= 0;
1956 start_odd = 1;
1957 }
1958 if ( !(pre_blanklines %2 == 0) &&
1959 !(non_blanklines % 2 == 0) &&
1960 (post_blanklines % 2 == 0)){
1961 even_pre_blanklines++;
1962 odd_non_blanklines++;
1963 start_even= 1;
1964 start_odd = 0;
1965 }
1966 if ( !(pre_blanklines %2 == 0) &&
1967 (non_blanklines % 2 == 0) &&
1968 !(post_blanklines % 2 == 0)){
1969 even_pre_blanklines++;
1970 odd_post_blanklines++;
1971 start_even= 1;
1972 start_odd = 0;
1973 }
1974
1975 width = right - left ;
1976 evenlines = even_pre_blanklines + even_non_blanklines + even_post_blanklines;
1977 oddlines = odd_pre_blanklines + odd_non_blanklines + odd_post_blanklines;
1978
1979 assert ( oddlines == evenlines );
1980
1981 for (i = 0; i < (width + 1) * 6 ; i++) {
1982 int color, x, odd, y;
1983 j = (width + 1) * 6 - 1 - i ;
1984 if (i < Left_size){
1985 if (!GET_USABLE (Left_l2r, i)){
1986 memset (place, 0x00, evenlines);
1987 place += evenlines;
1988 continue;
1989 }
1990 color = GET_COLOR (Left_l2r, i);
1991 odd = GET_ODD (Left_l2r, i);
1992 x = GET_X (Left_l2r, i);
1993 } else if ( j < Right_size ){
1994 if (!GET_USABLE (Right_l2r, j)){
1995 memset (place, 0x00, evenlines);
1996 place += evenlines;
1997 continue;
1998 }
1999 color = GET_COLOR (Right_l2r, j);
2000 odd = GET_ODD (Right_l2r, j);
2001 x = width -3 - GET_X (Right_l2r,j);
2002 } else {
2003 color = (i / 2 - 15) % 3;
2004 odd = i % 2;
2005 x = (i - 24) / 6 - 1 + odd + (color == 0 ? 0 :/* cyan */
2006 color == 1 ? 4 :/* magenta */
2007 8); /* yellow */
2008 }
2009 if (x + left < page_limit->left || x + left >= page_limit->right) {
2010 /* never print data that is outside the limits */
2011 memset (place, 0x00, evenlines);
2012 place += evenlines;
2013 } else {
2014 int new_pre_blanklines , new_non_blanklines , new_post_blanklines;
2015 int new_start;
2016 if (odd) {
2017 /* odd lines */
2018 new_pre_blanklines = odd_pre_blanklines ;
2019 new_non_blanklines = odd_non_blanklines ;
2020 new_post_blanklines = odd_post_blanklines ;
2021 new_start = start_odd;
2022 } else {
2023 /* even lines */
2024 new_pre_blanklines = even_pre_blanklines ;
2025 new_non_blanklines = even_non_blanklines ;
2026 new_post_blanklines = even_post_blanklines ;
2027 new_start = start_even;
2028 }
2029 if ( new_pre_blanklines > 0 ) {
2030 /* first pre_blanklines lines are blank */
2031 memset (place, 0x00, new_pre_blanklines ) ;
2032 place += new_pre_blanklines ;
2033 }
2034 for (y = 0; y < new_non_blanklines; y++) {
2035 int index = ((y * 2 + new_start) * data_width * 3 +
2036 (x + left ) * 3 + color);
2037 #ifdef DEBUG
2038 if (!( index < data_size && index >= 0) ){
2039 DPRINTF("index=%d, datasize= %d = %d x %d\n",
2040 index, data_size, data_width, swath_limits->non_blanklines);
2041 }
2042 assert ( index < data_size && index >= 0 );
2043 #endif
2044 *place++ = data[index];
2045 }
2046 if ( new_post_blanklines > 0 ){
2047 /* last post_blanklines lines are blank */
2048 memset(place, 0x00, new_post_blanklines) ;
2049 place += new_post_blanklines ;
2050 }
2051 }
2052 }
2053 return place;
2054 }
2055
2056 static int Right_r2l[] = {
2057 UNUSABLE,
2058 UNUSABLE,
2059 UNUSABLE,
2060 CYAN | EVEN | XPOS (0),
2061 UNUSABLE,
2062 CYAN | EVEN | XPOS (1),
2063 CYAN | ODD | XPOS (0),
2064 UNUSABLE,
2065 UNUSABLE,
2066 CYAN | EVEN | XPOS (2),
2067 CYAN | ODD | XPOS (1),
2068 UNUSABLE,
2069 UNUSABLE,
2070 CYAN | EVEN | XPOS (3),
2071 CYAN | ODD | XPOS (2),
2072 MAGENTA | EVEN | XPOS (0),
2073 UNUSABLE,
2074 CYAN | EVEN | XPOS (4),
2075 CYAN | ODD | XPOS (3),
2076 UNUSABLE,
2077 MAGENTA | EVEN | XPOS (1),
2078 MAGENTA | ODD | XPOS (0),
2079 CYAN | EVEN | XPOS (5),
2080 CYAN | ODD | XPOS (4),
2081 UNUSABLE,
2082 UNUSABLE,
2083 MAGENTA | EVEN | XPOS (2),
2084 MAGENTA | ODD | XPOS (1),
2085 CYAN | EVEN | XPOS (6),
2086 CYAN | ODD | XPOS (5),
2087 UNUSABLE,
2088 UNUSABLE,
2089 MAGENTA | EVEN | XPOS (3),
2090 MAGENTA | ODD | XPOS (2),
2091 CYAN | EVEN | XPOS (7),
2092 CYAN | ODD | XPOS (6),
2093 YELLOW | EVEN | XPOS (0),
2094 UNUSABLE,
2095 MAGENTA | EVEN | XPOS (4),
2096 MAGENTA | ODD | XPOS (3),
2097 CYAN | EVEN | XPOS (8),
2098 CYAN | ODD | XPOS (7)
2099 };
2100
2101
8772102 /* the final odd yellow swing buffer doesnt fit in right-to-left
8782103 * color sweeps. Instead of redesigning the structure of the Left of
8792104 * the sweep (If it works, dont fix it ...)
8822107 */
8832108
8842109 static int Left_r2l[] = {
885 UNUSABLE,//YELLOW | ODD | XPOS (0), //this data doesnt fit, what to do?
2110 UNUSABLE,/*YELLOW | ODD | XPOS (0), this data doesnt fit, what to do?*/
8862111 YELLOW | ODD | XPOS (1),
8872112 YELLOW | EVEN | XPOS (0),
8882113 YELLOW | ODD | XPOS (2),
9162141 CYAN | EVEN | XPOS (0)
9172142 };
9182143
919 #define GET_USABLE(A,i) (!(A[i] & 0x1))
920 #define GET_COLOR(A,i) ((A[i] >> 1) & 0x3);
921 #define GET_ODD(A,i) ((A[i] >> 3) & 0x1);
922 #define GET_X(A,i) ((A[i] >> 4));
923
924 int
925 cut_im_color_swath (image_t *image, ppaPrinter_t *printer, int maxlines,
926 ppaSweepData_t *sweep_data)
2144
2145 unsigned char *
2146 r2l_color_sweep(unsigned char *place, unsigned char *data,
2147 int data_width, ppaSwathLimits_t * swath_limits)
9272148 {
928 unsigned char *data[4], *ppa, *place, *maxplace;
929 int width8, p_width8;
930 int k, i, j, left , right, numlines;
931 int left_limit, right_limit, bottom_limit, top_limit ;
932 int top_vpos , bottom_vpos, sweep_offset ;
933 int non_blanklines, pre_blanklines, post_blanklines ;
934 int even_non_blanklines, even_pre_blanklines, even_post_blanklines ;
935 int odd_non_blanklines, odd_pre_blanklines, odd_post_blanklines ;
936 BOOLEAN at_bottom ;
2149 int i, j , width, evenlines, oddlines;
2150
2151 int left = swath_limits->left;
2152 int right = swath_limits->right;
2153 int non_b