Codebase list pnm2ppa / upstream/1.04
Imported Upstream version 1.04 Didier Raboud 11 years ago
99 changed file(s) with 19826 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 19991002 ajv created CVS repository
1 19991002 ajv Started work on debugging issues
2 19991003 ajv Moved main() to getopt for maintainability
3 19991003 ajv Added all the support files, and ported the
4 calibration suite
5 19991003 ajv Removed multiple target support, debugged other printers
6 Made recompilation to change things unnecessary
7 19991013 ajv Added internationalisation support
8 Added English man page
9 Reduced getopt() to *BSD friendly version
10 Fixed a bug that ajv found, and Giorgio fixed
11 Updated the usage to include build version and all
12 arguments
13 19991020 ajv Added back '-' and post-option file parsing
14 Added I18N stuff
15 Added "verbose" option to output to stderr
16 19991021 giorgio Added all of Giorgio's patches
17 Added X & Y offsets
18 19991021 ajv FreeBSD fixes in Makefile
19 Documentation update, including man page
20 19991105 ajv Documentation update
21 Dutch support - Jimmy Tak
22 "letter" added as valid paper size - Ionutz Borcoman
23 RedHat doco updated - Duncan Haldane
24 19991120 giorgio Much faster output
25 Much better printing in dark regions
26 compression reenabled for black mode
27 --eco mode
28 bug fixes
29 19991127 giorgio Changed back to standard Cartesian distance for colors
30 Gamma correction tool (see separate archive)
31 bug fixes in black printing
32 19991128 ajv re-merged with Giorgio's code base
33 All patches from 19991105 are back
34 updated shift sizes in pnm2ppa.conf
35 fixed permission problem with make install
36 fixed "verbose" and "dump" pnm2ppa.conf keywords
37 19991204 duncan "legal" (US Legal, 8.5in x 14in) added as a valid paper
38 size - Duncan Haldane <duncan_haldane@users.sourceforge.net>
39 20000113 ajv broke out image.c into several files in an attempt
40 to add pgm support without major breakage
41 20000114 ajv Finally fixed annoying memory bug. Both MAXLINES and
42 Max Buf Lines must agree.
43 20000120 klamer Patches to allow calibration to work again.
44 mancini BeOS support
45 duncan RedHat Print filters added to CVS tree
46 ajv Fixed -v and moved yet another global into a struct
47 20000306 duncan Lots of little fixes; --fd working right now;
48 bidirectional shearing adjustments added (user
49 configurable entries "blackshear" and colorshear"
50 in pnm2ppa.conf.
51 20000311 duncan added : -B n option and "blackness n" config file
52 entry to control black ink density (drops per
53 pixel n = 0,1,2,3,4 ) default is 2. Also there are
54 now config file entries blackshear and colorshear
55 for adjusting shearing in bidirectional printing.
56 Fixed various bugs that broke HP820/1000 printing.
57 20000318 duncan Color EcoMode printing now uses bidirectional
58 printsweeps (formerly only FastMode did this)
59 If gMaxPass = 1, you now get bidirectional sweeps
60 (in cut_im_color_swath() , cutswath.c)
61 20000326 duncan ** changes to dither.c:
62 on odd lines, black is
63 now processed (not color), even black pixels are
64 duplicated, so if either of two successive pixels are
65 black, they both are. Changes also fix Tim's report
66 about blurry black/white boundaries.
67 ** changes to image.c
68 If the odd line is not printed
69 (PixMap or EcoMode), image.c now stores the line, and
70 adds the black parts to the next even line.
71 This fixes a bug in where thin (one-pixel wide) black
72 lines (like enscript borders) could be lost because
73 black ink only printed every second pixel, and odd
74 black lines were just copies of the preceeding even
75 line which had been stored.
76 20000331 duncan added support for large papersizes 11x17 and a3
77 (for the 1000 series printers). Added a
78 printer-specific max_pagewidth so papersizes that
79 are too wide for a printer series will not print
80 on that printer.
81 20000402 duncan tweaked bidirectional sweep shearing correction.
82 (removed the +1 right-to-left black shift in
83 cut_im_black_swath() in cutswath.c ).
84 I am not sure if the shearing correction is
85 model or individual printer-specific. (I suspect
86 the second case, in which case it is a calibration
87 issue (The HP Win9x software seems to have calibration
88 adjustments for blackshear.) if any corrections
89 turn out to be generic to a given printer family,
90 (rather than specific to a particular printer)
91 the default can be changed in defaults.h (the
92 variables are:
93 printer->r2l_bw_offset (=blackshear)
94 printer->r2l_color_offset (=colorshear).
95 20000404 duncan added support for pbmraw and pgmraw formats.
96 all three pnmraw formats now work.
97 (changes in image.c, image.h )
98 20000405 duncan added support for pgm, ppm, pbm nonraw formats.
99 added papersize autoconfiguring from the pnm
100 header, so all ghostscript papersizes are now
101 supported (if the printer can accomodate them)
102 The -s option now only controls the gammafile
103 creation papersize. Made bidirectional
104 printing the default (but this can be configured
105 with a "unimode 1" in pnm2ppa.conf, or --uni,
106 --bi command line options.
107 20000408 duncan graceful termination of print run if pnm
108 input is truncated (i.e., if read_line()
109 encounters EOF). printer no longer hangs.
110 Moved text strings to lang.h/text-en.h
111 20000423 duncan clean up way things near sides of swath are
112 handled in cutswath.c
113 20000710 duncan in FS_Color_Dither(), use line[]= (1,1,1)
114 not (0,0,0) for black replacement of dark
115 pixels for which no color match is found.
116 (fixes flashing LED on certain images - those with
117 no black - with --eco on HP820)
118 (0,0,0) = black ink, (1,1,1) = gMaxPass drops of
119 each color.
120 20000928 duncan in cutswath.c, if the vertical position
121 of the black and color sweeps differed by 1 , 2 or 3
122 dots, HP820 got "flashing light syndrome".
123 Fixed by testing for this possibility, and
124 if found, by reducing numlines, and padding the top
125 of a swath with an (even) number of blank lines
126 to keep the height the same.
127 (Thanks to Steven Elliott <selliott4@austin.rr.com>
128 for reporting this bug, and testing the fix.
129 20001010 ajv made input of paths to gamma and config files secure
130 against buffer overruns.
131 duncan In -g mode, check that gamma.ppm is not a symbolic
132 link, and is a regular file, before writing to it
133 (but after opening it).
134
135 20001018 duncan clean up calibration program. now called
136 calibrate_ppa. It does most calibration now.
137
138 moved the job of writing gamma.ppm for color
139 calibration to a new utility calibrate_ppa.c.
140 pnm2ppa -g now just prints the corresponding
141 test page.
142
143 secured syslog messages. No user input is
144 sent to syslog. syslog messages are wrapped, and can
145 be suppressed with a new keyword "silent 1"
146 in /etc/pnm2ppa.conf (but not in subsequently-read
147 config files). all syslog activity now occurs
148 in syslog.c.
149 20001106 reduce memory footprint of calibrate_ppa
150 (it was 36MB!).
151 20001112 fix syslog silent/verbose usage; fix alignment
152 pattern bug in calibrate_ppa. repaired the HP820
153 fix that got broken when the vertical offset was
154 redefined by 600 dots...
155
156
157
158
159
160
161
162
0 English
1
2 You can find the build instructions in ./docs/en/INSTALL
3
4
0 #
1 # Makefile for pnm2ppa
2 #
3
4 INSTALLDIR=/usr/local/bin
5 CONFDIR=/etc
6 MANDIR=/usr/local/man/man1
7
8 CC=gcc
9 INSTALL=install
10
11 # production build
12 CFLAGS=-Wall -pedantic -O2 -g -DNDEBUG
13 LDFLAGS=-lm
14 OBJS = pnm2ppa.o syslog.o ppa.o image.o dither.o cutswath.o hash_ink.o gamma.o
15 SRC = pnm2ppa.c syslog.c ppa.c image.c dither.c cutswath.c hash_ink.c gamma.c
16
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
21
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
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
35 # If you have FreeBSD, you need to uncomment the next LDFLAG.
36 # You may also need to install libgnugetopt from the ports collection.
37 # LDFLAGS+=-L/usr/local/lib -lgnugetopt
38
39 # Install under Linux and other versions with the -b (backup) option
40 INSTALL=install -b
41 INSTALLD=install -b -d
42
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
52 LANG=EN
53 #LANG=CZ
54 #LANG=ES
55 #LANG=FR
56 #LANG=IT
57 #LANG=NL
58
59 # Normal Users!
60 #
61 # Do not edit below this line! No user servicable parts below!
62
63 CFLAGS+=-DLANG_$(LANG)
64
65 default: all
66
67 profile:
68 make "CFLAGS=-Wall -pedantic -O2 -g -pg -DNDEBUG"
69
70 debug:
71 make "CFLAGS=-Wall -pedantic -g -O2 -DDEBUG=1 -DLANG_EN" "LDFLAGS=-lm -lefence" "OBJS=$(DOBJS)"
72
73 # the following have been left in for those with good memories
74
75 720: all
76 @@echo After running make install, edit /etc/pnm2ppa.conf and set your printer
77
78 820: all
79 @@echo After running make install, edit /etc/pnm2ppa.conf and set your printer
80
81 1000: all
82 @@echo After running make install, edit /etc/pnm2ppa.conf and set your printer
83
84 all: pnm2ppa calibrate_ppa
85
86 clean:
87 rm -f *.o *~ calibrate_ppa pnm2ppa make_hash_ink gmon.out hash_ink.c
88
89
90 install: pnm2ppa calibrate_ppa
91 $(INSTALL) -m 755 pnm2ppa $(INSTALLDIR)
92 $(INSTALLD) $(MANDIR)
93 $(INSTALL) -m 644 docs/en/pnm2ppa.1 $(MANDIR)
94 # development only - allows root to edit
95 $(INSTALL) -m 644 pnm2ppa.conf $(CONFDIR)
96 # calibration tool
97 $(INSTALL) -m 755 calibrate_ppa $(INSTALLDIR)
98 # final production - much tighter
99 # $(INSTALL) -m 444 pnm2ppa.conf $(CONFDIR)
100 @@echo
101 @@echo Now, edit /etc/pnm2ppa.conf to choose your printer
102
103 uninstall:
104 rm -f $(INSTALLDIR)/pnm2ppa
105 rm -f $(INSTALLDIR)/calibrate_ppa
106 rm -f $(MANDIR)/pnm2ppa.1
107 rm -f $(CONFDIR)/pnm2ppa.conf
108
109 pnm2ppa: $(OBJS)
110 $(CC) $(LDFLAGS) $(CFLAGS) -o pnm2ppa $(OBJS)
111
112 calibrate_ppa: calibrate_ppa.o pnmtools.o gamma.o
113 $(CC) $(LDFLAGS) $(CFLAGS) -o calibrate_ppa calibrate_ppa.o pnmtools.o gamma.o
114
115 calibrate_ppa.o: calibrate_ppa.c global.h image.h defaults.h pnmtools.h
116 $(CC) $(CFLAGS) -c calibrate_ppa.c
117
118 pnmtools.o: pnmtools.c pnmtools.h
119 $(CC) $(CFLAGS) -c pnmtools.c
120
121 cutswath.o: cutswath.c debug.h ppa.h image.h global.h syslog.h
122 $(CC) $(CFLAGS) -c cutswath.c
123
124 image.o: image.c image.h palette.h debug.h fscoeff.h global.h gamma.h syslog.h
125 $(CC) $(CFLAGS) -c image.c
126
127 gamma.o: gamma.c image.h global.h gamma.h
128 $(CC) $(CFLAGS) -c gamma.c
129
130 dither.o: dither.c dither.h image.h palette.h debug.h fscoeff.h global.h hash_ink.h
131 $(CC) $(CFLAGS) -c dither.c
132
133 pnm2ppa.o: pnm2ppa.c pnm2ppa.h image.h ppa.h debug.h global.h gamma.h syslog.h
134 $(CC) $(CFLAGS) -c pnm2ppa.c
135
136 ppa.o: ppa.c ppa.h debug.h global.h syslog.h
137 $(CC) $(CFLAGS) -c ppa.c
138
139 debug.o: debug.c debug.h global.h
140 $(CC) $(CFLAGS) -c debug.c
141
142 syslog.o: syslog.c syslog.h global.h
143 $(CC) $(CFLAGS) -c syslog.c
144
145 make_hash_ink: make_hash_ink.c palette.h hash_ink.h
146 $(CC) $(CFLAGS) -o make_hash_ink make_hash_ink.c
147
148 hash_ink.c: make_hash_ink
149 ./make_hash_ink 4 3 > hash_ink.c
150 ./make_hash_ink 1 5 >> hash_ink.c
151
152 hash_ink.o: hash_ink.c hash_ink.c
153 $(CC) $(CFLAGS) -c hash_ink.c
154
155 # a default rule, in case new .c files pop in
156
157 .c.o: $*.c ppa.h image.h enh-curve.h palette.h debug.h global.h
158 $(CC) $(CFLAGS) -c $*.c
159
160 distrib: clean
161 cd .. && tar cf - pnm2ppa/ | gzip -9 > pnm2ppa.tar.gz
162 sync
163
164
165
166
167
168
169
170
171
172
173
174
175
176
0 English
1
2 Please read the README in ./docs/en/README
3
0 These notes are for the guidance of distributions that include pnm2ppa:
1 ---------------------------------------------------------------------
2
3 Notes on secure installation of pnm2ppa.
4
5 What pnm2ppa does:
6
7 1. It attempts to open and read a configuration file
8 "/etc/pnm2ppa.conf", and then any additional configuration
9 files with paths specified by the -f command line option.
10
11 These paths are checked to be shorter than MAXPATHLEN before
12 they are used, otherwise pnm2ppa terminates.
13
14 GNU getopt() is used to process options.
15
16 2. It opens an input file (-i option) to receive pnm data.
17 The pnm format and page size is taken from the header.
18
19 If the header does not correspond to a valid pnm format, the rest
20 of the data is rejected, and pnm2ppa terminates.
21
22 The input file path is checked to have a length less than
23 MAXPATHLEN, as determined at compilation time.
24
25 3. It opens an output file (-o option) to send ppa data
26 (for the printer).
27
28 The output file path is checked to have a length less than
29 MAXPATHLEN.
30
31
32 4. (unless the --noGamma option is specified) it tries to read color
33 correction data from "/etc/pnm2ppa.gamma", or an alternate file with
34 a path specified by the -F command line option.
35
36 Such paths are also checked to be shorter than MAXPATHLEN before
37 they are used.
38
39 If this data exists, but is not successfully read, pnm2ppa terminates.
40 (See COLOR.txt).
41
42 5. pnm2ppa opens and writes to the syslog with informational messages
43 about its progress, or, if it terminates, with an error message.
44 If it is working in --verbose mode, these messages are also sent
45 to stderr.
46
47 No strings derived from user input to pnm2ppa are included in syslog
48 messages. Syslog messages must fit in a string of length < 128.
49 They can be suppressed with a keyword "silent 1" in the default
50 system configuration file (/etc/pnm2ppa.conf), but not from
51 user-specified config files (from -f option).
52
53 All syslog actions by pnm2ppa are "wrapped": message strings
54 produces in the rest of the program are only sent to the syslog by
55 code in syslog.c. This is also where openlog() and closelog() are
56 called.
57
58
59 ----------------------------------------------------------------------
60 Recommendations:
61
62 -- do *NOT* install pnm2ppa suid/guid, if is possible that a
63 "malicious user" might run it. The output file specified
64 with the -o option could overwrite files to which the user
65 has no write permission.
66
67
68 -- since pnm2ppa works as an output filter for gs, it only needs the
69 same privileges that gs would need. If lpr is available, pipe
70 the pnm2ppa output though "lpr -l ..." to the appropriate printer
71 rather than directly sending it to e.g. /dev/lp0 (in the latter case,
72 write privileges on /dev/lp0 would be needed.)
73
74 --------------------------------------------------------------
75
76 Other (optional) programs in the distribution:
77
78 Do NOT install these suid/gid!
79
80 calibrate.c: This is used to produce various ppmraw format PixMap images
81 used with pnm2ppa for printer calibration. Note: these
82 PixMaps are LARGE (100MB!!) and should generally be piped
83 directly to pnm2ppa.
84
85 THIS SHOULD USUALLY BE INSTALLED.
86
87 parse_vlink.c a utility useful in debugging pnm2ppa that can interpret
88 ppa format output instructions to the printer, whether
89 produced by pnm2ppa, or captured from the Windows9x drivers.
90 It is in the ppa_protocol subdirectory, and is not compiled
91 by default.
92
93 THIS IS NOT USUALY INSTALLED.
94
0 /***************************************************************************
1 calibrate_ppa.c - program to produce PPM data for pnm2ppa calibration
2 -------------------
3 begin : Thu Oct 12 2000
4 copyright : (C) 1998-2000 by the pnm2ppa project
5 email :
6 ***************************************************************************/
7
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
19 /* incorporates color features added by Bruno ALIX */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <getopt.h>
26 #include <sys/param.h>
27
28 #define __PNM2PPA_C__
29 #define __CALIBRATE_PPA_C__
30 #include "global.h"
31 #include "image.h"
32 #include "defaults.h"
33 #include "pnmtools.h"
34
35 int make_ppm_file ( FILE * , image_t *, char *) ;
36
37 int make_test_pattern ( FILE *, int, char * );
38
39
40 //int black_maxlines = 300;
41 int black_maxlines = 128; //put this back to old value for now (duncan)
42
43
44 void
45 show_usage (char *prog)
46 {
47 printf ("usage: %s [ options ] [ -o <outfile> ]] \n\n",
48 prog);
49 printf
50 (" Produces various PixMap (PPM) files used for calibrating pnm2ppa.\n\n");
51 printf (" NOTE: The size of a full-page PixMap is 100MB!!.\n");
52 printf (" These PixMaps should be piped directly to pnm2ppa, except in the case of\n");
53 printf (" the -g option, where the PixMap should be viewed or printed by other means.\n\n");
54 printf (" -g, --gamma produce gamma.ppm (10MB, used in color calibration).\n");
55 printf (" -h, --help displays this help text.\n");
56 printf (" -o <outfile> output to file <outfile>, \"-o -\" means stdout (default)\n");
57 printf (" -p <n> create test pattern number <n>\n");
58 printf (" --align pattern 0: align print heads. (default) \n");
59 printf (" --test pattern 1: test alignment. \n");
60 printf (" --clean pattern 2: clean print head. \n");
61 printf (" --center pattern 3: center paper. \n");
62 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");
64 printf ("\n");
65 }
66
67 int
68 main (int argc, char *argv[])
69 {
70 int opt_index;
71 image_t image ;
72 char *progname = NULL;
73 BOOLEAN use_stdout = true ;
74 BOOLEAN gamma = false ;
75 FILE *outFile = NULL ;
76 int testPattern = 0;
77 char *out_filepath = NULL;
78 char c;
79 static struct option long_opts[] = {
80 {"gamma",0,0,'g'},
81 {"align",0,0,0},
82 {"test",0,0,0},
83 {"clean",0,0,0},
84 {"center",0,0,0},
85 {"help",0,0,'h'},
86 {0, 0, 0, 0}
87 };
88
89 gWidth = LETTERWIDTH;
90 gHeight = LETTERHEIGHT ;
91
92
93 // read through the optional arguments before tring to find filenames
94
95 while ((c = getopt_long (argc, argv, "gho:p:s:v:",
96 long_opts, &opt_index)) != EOF)
97 {
98 progname = *argv;
99 switch (c)
100 {
101 case 0:
102 // long options
103 switch (opt_index)
104 {
105 case 0:
106 // --gamma
107 gamma = true;
108 break;
109 case 1:
110 // --align
111 gamma = false;
112 testPattern = 0;
113 break;
114 case 2:
115 // --test
116 gamma = false;
117 testPattern = 1;
118 break;
119 case 3:
120 // --clean
121 gamma = false;
122 testPattern = 2;
123 break;
124 case 4:
125 // --center
126 gamma = false;
127 testPattern = 3;
128 break;
129 case 5:
130 // --help
131 show_usage (*argv);
132 return 0;
133 break;
134
135 default:
136 break;
137 }
138 break;
139
140 case 'g':
141 gamma = true;
142 break;
143
144 case 'h':
145 show_usage (*argv);
146 return 0;
147 break;
148
149
150 case 'o':
151 if (strncmp (optarg, "-", MAXPATHLEN) == 0)
152 {
153 use_stdout = true ;
154 }
155 else
156 {
157 if ( strlen(optarg) < MAXPATHLEN )
158 {
159 char filepath[MAXPATHLEN];
160 strncpy(filepath, optarg, MAXPATHLEN);
161 out_filepath = filepath ;
162 use_stdout = false ;
163 }
164 }
165 break;
166
167 case 'p':
168 // select alternate test pattern
169 gamma = false;
170 testPattern = atoi( optarg );
171 break;
172
173
174 case 's':
175 // paper size stuffer
176 if (!strncmp (optarg, "us", 2) || !strncmp (optarg, "letter", 6))
177 {
178 gWidth = LETTERWIDTH;
179 gHeight = LETTERHEIGHT;
180 }
181 else if (!strncmp (optarg, "legal", 5))
182 {
183 gWidth = LEGALWIDTH;
184 gHeight = LEGALHEIGHT;
185 }
186 else if (!strncmp (optarg, "a4", 2))
187 {
188 gWidth = A4WIDTH;
189 gHeight = A4HEIGHT;
190 }
191 else
192 {
193 fprintf(stderr,"%s: unknown paper size \"%s\"\n",
194 progname, optarg);
195 exit (0);
196 }
197 break;
198
199 case 'v':
200 // printer model
201 if (!strncmp (optarg, "820", 3) || !strncmp (optarg, "1000", 4))
202 black_maxlines = 128;
203 else if (!strncmp (optarg, "71", 2) || !strncmp (optarg, "72", 2))
204 // black_maxlines = 300;
205 black_maxlines = 128; //reverted for the moment
206 else
207 {
208 fprintf(stderr,"%s: unknown printer model \"%s\"\n",
209 progname, optarg);
210 exit (0);
211 }
212 break;
213
214 default:
215 exit (0);
216 break;
217 }
218 }
219
220
221 if (use_stdout)
222 outFile = stdout;
223 else
224 {
225 outFile = fopen( out_filepath , "w");
226 fprintf(stderr,"%s: writing requested PPM data to \"%s\"\n",
227 progname, out_filepath);
228 }
229
230 if (outFile == NULL )
231 {
232 fprintf(stderr,"%s: cannot open output file \"%s\"\n",
233 progname, out_filepath);
234 return 0;
235 }
236
237 if ( gamma )
238 {
239 /* production of PixMap gamma.ppm */
240 make_ppm_file( outFile , &image, progname );
241 }
242 else
243 {
244 /* make PixMap test patterns for printer */
245 make_test_pattern( outFile, testPattern, progname ) ;
246 }
247
248
249 fclose (outFile);
250 return 1 ;
251
252 }
253
254 int
255 make_ppm_file (FILE *outFile , image_t *image , char * progname)
256 {
257 unsigned char *line = NULL ;
258 image->width = gWidth;
259 image->height = gHeight;
260 image->bufferCurLine = 0;
261
262 fprintf (outFile,
263 "P6\n#PPM (PixMap) Image for comparison with printed output of \"pnm2ppa -g\"\n%d %d\n255\n",
264 image->width, 64 + image->height / 20);
265
266 line = malloc (image->width * 3);
267 if (!(line))
268 {
269 fprintf(stderr,"%s: malloc failed\n",
270 progname);
271 exit (1);
272 }
273 else
274 {
275 while ( image->bufferCurLine < image->height)
276 {
277 if ( ProduceGamma (image, line ))
278 {
279 fwrite (line, sizeof (unsigned char), (image->width * 3),
280 outFile);
281 }
282 image->bufferCurLine++;
283 }
284 free (line);
285 }
286 return 1;
287 }
288
289
290 /* various test patterns */
291
292 void centering_grid( void );
293 void make_big_x( void );
294 void make_vertical_line( void );
295 void color_alignment( void );
296 void check_alignment( void );
297 void head_cleaning( void );
298 void color_squares( void );
299 void centering( void );
300
301 /* color coding scheme used */
302
303 /* each color is coded on 2 bits of 1 byte rrggbbxx
304 (light grey is for head cleaning)
305 */
306 enum {
307 WHITE = 0xfc, /* white 11 11 11 00 = 000 = (255,255,255) */
308 BLACK = 0x00, /* black 00 00 00 00 = 444 = (000,000,000) */
309 CYAN = 0xbc, /* cyan 10 11 11 00 = 100 = (128,255,255) */
310 MAGENTA = 0xec, /* magenta 11 10 11 00 = 010 = (255,128,255) */
311 YELLOW = 0xf8, /* yellow 11 11 10 00 = 001 = (255,255,128) */
312 RED = 0xc0, /* red 11 00 00 00 = 044 = (255,000,000) */
313 GREEN = 0x30, /* green 00 11 00 00 = 404 = (000,255,000) */
314 BLUE = 0x0c, /* blue 00 00 11 00 = 004 = (000,000,255) */
315 GREY = 0xa8 /* light grey 10 10 10 00 = 111 = (128,128,128) */
316 };
317
318
319 int
320 make_test_pattern (FILE *outFile, int testPattern , char * progname )
321 {
322 int x;
323 int line, maxlines = 128 ;
324
325 /* create the pattern in strips starting at line line,
326 with a maximum number of lines maxlines in the strip.
327 */
328
329 Width = 8*(gWidth/8); /* make Width a multiple of 8 */
330 Height = gHeight;
331
332 /* pixel dimensions */
333 // Pwidth = Width ;
334 // Pheight = Height ;
335
336 /* each color is coded on 2 bits if 1 byte rrggbbxx */
337
338 fprintf(outFile,"P6\n%d %d\n255\n",Width,Height);
339
340 for ( line = 0; line < Height ; line += maxlines )
341 {
342 BitMap_topline = line;
343 BitMap_bottomline = line + maxlines;
344 if ( BitMap_bottomline > Height)
345 BitMap_bottomline = Height;
346 BitMap_Height = BitMap_bottomline - BitMap_topline;
347 BitMap_Width = Width;
348
349 color_bitmap = (char *)malloc(BitMap_Width*BitMap_Height);
350
351
352 /* set strip to white */
353 memset(color_bitmap,0xff,(BitMap_Width*BitMap_Height));
354
355
356 switch(testPattern)
357 {
358 case 0:
359 color_alignment();
360 break;
361 case 1:
362 check_alignment();
363 break;
364 case 2:
365 head_cleaning();
366 break;
367 case 3:
368 centering();
369 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
383 default:
384 fprintf(stderr,"%s: unknown test pattern (%d)\n",progname,testPattern);
385 fprintf(stderr,"test pattern 0 : cartridge alignment (default)\n");
386 fprintf(stderr," 1 : check alignment\n");
387 fprintf(stderr," 2 : colored stripes, use for head cleaning\n");
388 fprintf(stderr," 3 : center paper \n");
389 return 1;
390 }
391
392
393 for(x=0; x<BitMap_Width*BitMap_Height; x++)
394 {
395 int v, mask, i;
396
397 /* extract the data from the first 6 bits of each byte
398 of color_bitmap, convert to ppm format, and output it.
399 Each color has 4 intensities, coded in 2 bits):
400 0x00 : 4 drops of ink - ppm value 0
401 0x01 : 3 drops of ink - ppm value 8
402 0x02 : 1 drop of ink - ppm value 128
403 0x03 : 0 drops of ink - ppm value 255
404 */
405
406 for(i=6 ; i > 0 ; i-=2 )
407 {
408 mask = ( 0x03 << i );
409
410 v = ((color_bitmap [x] & mask) >> i);
411 switch(v)
412 {
413 case 0x00: // 4 drops of ink
414 v=0x00;
415 break;
416 case 0x01: // 3 drops of ink
417 v=0x08;
418 break;
419 case 0x02: // 1 drops of ink
420 v=0x80;
421 break;
422 case 0x03: // 0 drops of ink
423 v=0xff;
424 }
425 putc(v, outFile);
426 }
427 }
428 free(color_bitmap);
429 }
430 return 0;
431 }
432
433
434
435
436
437 void
438 centering_grid( void )
439 {
440 /* this pattern is a grid that can be used for centering the page*/
441 int x,y;
442 char buf[128];
443
444
445 for(x=0; x<Width; x+=100)
446 for(y=0; y<Height; y+=100)
447 setplus(x,y,4);
448 for(x=0; x<Width; x+=100)
449 {
450 sprintf(buf,"%d",x);
451 setstring(x+3,(Height/200)*100+3,buf,3);
452 }
453 for(y=0; y<Height; y+=100)
454 {
455 sprintf(buf,"%d",y);
456 setstring((Width/200)*100+3,y+3,buf,3);
457 }
458 for(x=0; x<Width; x+=10)
459
460 for(y=0; y<Height; y+=100)
461 setplus(x,y,((x%100)==50) ? 2 : 1);
462 for(x=0; x<Width; x+=100)
463 for(y=0; y<Height; y+=10)
464 setplus(x,y,((y%100)==50) ? 2 : 1);
465 setCG(Width/2,Height/2);
466 }
467
468
469 void
470 make_vertical_line( void )
471 {
472 int y;
473 for(y=0; y<300; y++)
474 setpixel(Width/2,Height/2-y,BLACK);
475 }
476
477
478 void
479 make_big_x( void )
480 {
481 int y;
482 for(y=0; y<300; y++)
483 {
484 setpixel(y,y,BLACK);
485 setpixel(Width-1-y,Height-1-y,BLACK);
486 }
487 }
488
489
490
491
492
493
494
495 void
496 color_alignment( void )
497 {
498 //add for color test, alignment pattern
499 int x,y,t,shear,direction;
500 int vpos;
501 int hpos;
502 char buf[128];
503
504 /* horizontal black/color offset pattern */
505
506 vpos=300;
507 hpos=Width/2-2000;
508 for(y=1;y<20;y++)
509 {
510 for(x=0;x<100;x++)
511 {
512 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);
516 }
517 if ((y-10) > 0)
518 sprintf(buf,"+%d",y-10);
519 else
520 sprintf(buf,"%d",y-10);
521 setstring(y*200+hpos,vpos+350,buf,5);
522 }
523 setstring(Width/2 -200,vpos+450,"COLOFFSX",7);
524 /* vertical black/color offset pattern */
525
526 vpos=1200;
527 hpos=Width/2-2150;
528 for (t=1;t<10;t++)
529 {
530 for(y=0;y<101;y++)
531 {
532 setpixel(t*400+hpos+y,vpos,BLACK);
533 setpixel(t*400+hpos+105+y,vpos-5+t*1,BLUE);
534 setpixel(t*400+hpos+105+y,vpos-5+t*1+1,BLUE);
535 setpixel(t*400+hpos+210+y,vpos,BLACK);
536 }
537 if ((t-5) > 0)
538 sprintf(buf,"+%d",t-5);
539 else
540 sprintf(buf,"%d",t-5);
541 setstring(t*400+hpos+150,vpos+50,buf,5);
542
543 }
544 setstring(Width/2-200,vpos+150,"COLOFFSY",7);
545
546
547 /* colorshear setting (left-to-right / right-to-left sweep offsets) */
548
549
550 hpos=Width/2-2000;
551 vpos=2000;
552 direction = 1; /* this is determined by whether sweep is L2R or R2L */
553 for(y=1;y<20;y++)
554 {
555 shear= direction*(y-10);
556 for(x=0;x<128;x++)
557 {
558 setpixel(y*200+hpos,x+vpos+000,BLUE);
559 setpixel(y*200+hpos+1,x+vpos+000,BLUE);
560 setpixel(y*200+hpos+shear,x+vpos+128,BLUE);
561 setpixel(y*200+hpos+1+shear,x+vpos+128,BLUE);
562 setpixel(y*200+hpos,x+vpos+256,BLUE);
563 setpixel(y*200+hpos+1,x+vpos+256,BLUE);
564 setpixel(y*200+hpos+shear,x+vpos+384,BLUE);
565 setpixel(y*200+hpos+1+shear,x+vpos+384,BLUE);
566 setpixel(y*200+hpos,x+vpos+512,BLUE);
567 setpixel(y*200+hpos+1,x+vpos+512,BLUE);
568 }
569 if ((y-10) > 0)
570 sprintf(buf,"+%d",y-10);
571 else
572 sprintf(buf,"%d",y-10);
573 setstring(y*200+hpos,vpos+650,buf,5);
574 }
575 setstring(Width/2-200,vpos+750,"COLORSHEAR ",7);
576
577
578
579 /* blackshear setting (left-to-right / right-to-left sweep offsets) */
580
581 hpos=Width/2-2000;
582 vpos=3500;
583 direction = -1; /* this is determined by whether sweep is L2R or R2L */
584 for(y=1;y<20;y++)
585 {
586 shear = direction*(y-10);
587 for(x=0; x < black_maxlines ;x++)
588 {
589 setpixel(y*200+hpos,x+vpos+000,BLACK);
590 setpixel(y*200+hpos+shear,x+vpos+black_maxlines,BLACK);
591 setpixel(y*200+hpos,x+vpos+2*black_maxlines,BLACK);
592 setpixel(y*200+hpos+shear,x+vpos+3*black_maxlines,BLACK);
593 setpixel(y*200+hpos,x+vpos+4*black_maxlines,BLACK);
594 }
595 if ((y-10) > 0)
596 sprintf(buf,"+%d",y-10);
597 else
598 sprintf(buf,"%d",y-10);
599 setstring(y*200+hpos,vpos+650+5*(black_maxlines-128),buf,5);
600
601 }
602 vpos = vpos + 5*(black_maxlines -128) ;
603 setstring(Width/2-200,vpos+750,"BLACKSHEAR ",7);
604
605 hpos=Width/2;
606 vpos=4800;
607 for(x=0;x<640;x++)
608 {
609 setpixel(hpos,vpos+x,BLACK);
610 setpixel(hpos,vpos+640+x,BLUE);
611 }
612 }
613
614 void
615 check_alignment( void )
616 {
617 // alignment verification pattern
618 int x,y;
619 int vpos, vpos1, vpos2;
620 int hpos, hpos1,hpos2;
621
622
623 /* cross */
624
625 vpos=1000;
626 hpos=Width/2-384;
627 hpos+=384;
628 for (x=0;x<black_maxlines-2;x++)
629 setpixel(hpos,vpos+x,BLACK);
630 vpos += black_maxlines;
631 for (x=0;x<126;x++)
632 setpixel(hpos,vpos+x,BLUE);
633 vpos += 128;
634 for (x=0;x<black_maxlines-2;x++)
635 setpixel(hpos,vpos+x,BLACK);
636 vpos += black_maxlines;
637 for (x=0;x<black_maxlines-2;x++)
638 setpixel(hpos,vpos+x,BLACK);
639 vpos += black_maxlines;
640 for (x=0;x<126;x++)
641 setpixel(hpos,vpos+x,BLUE);
642 vpos += 128;
643 for (x=0;x<black_maxlines-2;x++)
644 setpixel(hpos,vpos+x,BLACK);
645 vpos += black_maxlines;
646
647 vpos-=128+2*black_maxlines;
648 hpos-=128+2*black_maxlines;
649
650 for (y=0;y<black_maxlines-2;y++)
651 setpixel(hpos+y,vpos,BLACK);
652 hpos += black_maxlines;
653 for (y=0;y<126;y++)
654 setpixel(hpos+y,vpos,BLUE);
655 hpos += 128;
656 for (y=0;y<black_maxlines-2;y++)
657 setpixel(hpos+y,vpos,BLACK);
658 hpos += black_maxlines;
659 for (y=0;y<black_maxlines-2;y++)
660 setpixel(hpos+y,vpos,BLACK);
661 hpos += black_maxlines;
662 for (y=0;y<126;y++)
663 setpixel(hpos+y,vpos,BLUE);
664 hpos += 128;
665 for (y=0;y<black_maxlines-2;y++)
666 setpixel(y+hpos,vpos,BLACK);
667
668
669 /* square */
670
671 vpos=3000;
672 hpos1=Width/2-3*(128+black_maxlines);
673 hpos2=Width/2+3*(128+black_maxlines);
674 for (x=0;x<2*black_maxlines -2;x++)
675 {
676 setpixel(hpos1,vpos+x,BLACK);
677 setpixel(hpos2,vpos+x,BLACK);
678 }
679 vpos += 2*black_maxlines;
680 for (x=0;x<254 ;x++)
681 {
682 setpixel(hpos1,vpos+x,BLUE);
683 setpixel(hpos2,vpos+x,BLUE);
684 }
685 vpos +=256;
686 for (x=0;x<2*black_maxlines -2;x++)
687 {
688 setpixel(hpos1,vpos+x,BLACK);
689 setpixel(hpos2,vpos+x,BLACK);
690 }
691 vpos += 2*black_maxlines;
692 for (x=0;x<254 ;x++)
693 {
694 setpixel(hpos1,vpos+x,BLUE);
695 setpixel(hpos2,vpos+x,BLUE);
696 }
697 vpos +=256;
698 for (x=0;x<2*black_maxlines -2;x++)
699 {
700 setpixel(hpos1,vpos+x,BLACK);
701 setpixel(hpos2,vpos+x,BLACK);
702 }
703 vpos += 2*black_maxlines;
704 for (x=0;x<254 ;x++)
705 {
706 setpixel(hpos1,vpos+x,BLUE);
707 setpixel(hpos2,vpos+x,BLUE);
708 }
709
710 vpos1=3000;
711 vpos2 = vpos1+6*(128+black_maxlines);
712 hpos = Width/2 - 3*(128+black_maxlines);
713 for (y=0;y<2*black_maxlines -2;y++)
714 {
715 setpixel(hpos+y,vpos1,BLACK);
716 setpixel(hpos+y,vpos2,BLACK);
717 }
718 hpos += 2*black_maxlines;
719 for (y=0;y<254 ;y++)
720 {
721 setpixel(hpos+y,vpos1,BLUE);
722 setpixel(hpos+y,vpos2,BLUE);
723 }
724 hpos +=256;
725 for (y=0;y<2*black_maxlines -2;y++)
726 {
727 setpixel(hpos+y,vpos1,BLACK);
728 setpixel(hpos+y,vpos2,BLACK);
729 }
730 hpos += 2*black_maxlines;
731 for (y=0;y<254 ;y++)
732 {
733 setpixel(hpos+y,vpos1,BLUE);
734 setpixel(hpos+y,vpos2,BLUE);
735 }
736 hpos +=256;
737 for (y=0;y<2*black_maxlines -2;y++)
738 {
739 setpixel(hpos+y,vpos1,BLACK);
740 setpixel(hpos+y,vpos2,BLACK);
741 }
742 hpos += 2*black_maxlines;
743 for (y=0;y<254 ;y++)
744 {
745 setpixel(hpos+y,vpos1,BLUE);
746 setpixel(hpos+y,vpos2,BLUE);
747 }
748 }
749
750 void
751 centering(void)
752 {
753 int x,y,z;
754 char buf[128];
755
756 for (y = Width/2; y > 0; y-- )
757 {
758 setpixel(y,y, BLACK);
759 setpixel(Width-y,y, BLACK);
760 setpixel(y,Height-y, BLACK);
761 setpixel(Width-y,Height-y, BLACK);
762 setpixel(y,Height/2, BLACK);
763 setpixel(Width-y,Height/2, BLACK);
764 }
765
766 for (x = 0; x < Height; x++)
767 setpixel(Width/2,x, BLACK );
768
769 for (z = 50; z < 601; z += 50)
770 {
771 for (x = z; x <= Height -z; x++)
772 {
773 setpixel(z,x,BLACK);
774 setpixel(Width-z,x,BLACK);
775 }
776 for (y = z; y <= Width -z;y++)
777 {
778 setpixel(y,z,BLACK);
779 setpixel(y,Height-z,BLACK);
780 }
781 sprintf(buf,"%d",z);
782 setstring (Width/2-30,z-15,buf,5);
783 setstring(Width/2-30,Height-z-15,buf,5);
784 setstringv(z-15,Height/2-60,buf,5);
785 setstringv(Width-z-15,Height/2-60,buf,5);
786
787 }
788 setstring(700,Height/2-100,"XOFFSET",7);
789 setstring(Width/2-150,800,"YOFFSET",7);
790
791 }
792
793
794 void
795 head_cleaning( void )
796 {
797 // test page for cleaning
798 int x,y,a,b,c;
799 int vpos;
800 char buf[128];
801
802 vpos=100;
803 for (y=0;y<2500;y++)
804 {
805 a=y%250 ;
806 b=y/50 ;
807 if (a==0)
808 {
809 for (x=0;x<300;x++)
810 {
811 setpixel ( y+100,x+vpos,BLACK);
812 }
813 }
814 else
815 {
816 for (x=0;x<6;x++)
817 {
818 a=x*50+b*1 ;
819 if (a>300) a=a-300;
820 setpixel (y+100,a+vpos,BLACK);
821 }
822 }
823 }
824 for (a=50;a<301;a+=50)
825 {
826 sprintf (buf,"%d",a);
827 setstring (2510+100,vpos-50+a,buf,3);
828 }
829
830 for (y=0;y<(240*8);y++)
831 {
832 a=y%240 ;
833
834 b=y/30 ;
835 vpos=500;
836 if (a==0)
837 {
838 for (x=0;x<128;x++)
839 {
840 setpixel ( y+100,x+vpos,MAGENTA);
841 setpixel ( y+100,x+vpos+128,YELLOW);
842 setpixel ( y+100,x+vpos+256,CYAN);
843 }
844 }
845 else
846 {
847 for (x=0;x<1;x++)
848 {
849 a=x*50+b*2 ;
850 if (a>128) a=a-128;
851 setpixel (y+100,a+vpos,MAGENTA);
852 setpixel (y+100,a+vpos+128,YELLOW);
853 setpixel (y+100,a+vpos+256,CYAN);
854 }
855 }
856 }
857
858 vpos=1300;
859 for (y=0;y<3500;y++)
860 {
861 a=y/500;
862
863 switch (a)
864 {
865 case 0 : b = RED; break;
866 case 1 : b = MAGENTA; break;
867 case 2 : b = BLUE; break;
868 case 3 : b = CYAN; break;
869 case 4 : b = GREEN; break;
870 case 5 : b = YELLOW; break;
871 case 6 : b = RED; break;
872 }
873 for (x=0;x<128;x++)
874 {
875 setpixel (y+100,x+vpos,b);
876 }
877 }
878
879 //grey
880 vpos=2000;
881 for (y=100;y<Width-1000;y++)
882 {
883 for (x=0;x<128;x++)
884 {
885 setpixel (y,x+vpos,GREY);
886 }
887 }
888
889 //magenta,yellow,cyan
890 vpos=2300;
891 for (y=100;y<Width-1000;y++)
892 {
893 for (x=0;x<128;x++)
894 {
895 setpixel (y,x+vpos,MAGENTA);
896 setpixel (y,x+vpos+128,YELLOW);
897 setpixel (y,x+vpos+256,CYAN);
898 }
899 }
900 //black
901 vpos=2800;
902 for (y=100;y<Width-1000;y++)
903 {
904 for (x=0;x<300;x++)
905 {
906 setpixel (y,x+vpos,BLACK);
907 }
908 }
909
910 vpos=3800;
911 for (y=0;y<600;y++)
912 {
913 a=y%50 ;
914 b=y/50 ;
915 c=y/100;
916 if (a==0)
917 {
918 for (x=0;x<300;x++)
919 {
920 setpixel ( y+100,x+vpos,BLACK);
921 }
922 }
923 else
924 {
925 for (x=0;x<25;x++)
926 {
927 a=x*2+c*50 ;
928 a=a+(b%2);
929 setpixel (y+100,a+vpos,BLACK);
930 }
931 }
932 }
933
934
935 for (y=600;y<1701;y++)
936 {
937 a=y%50 ;
938 b=y/50 ;
939 if (a==0)
940 {
941 for (x=0;x<300;x++)
942 {
943 setpixel ( y+100,x+vpos,BLACK);
944 }
945 }
946 else
947 {
948 for (x=0;x<7;x++)
949 {
950 a=(x*50+b*2)%300 ;
951 c=(a+3)%300;
952 setpixel (y+100,a+vpos,BLACK);
953 setpixel (y+100,c+vpos,BLACK);
954 }
955 }
956 }
957
958 for (y=1700;y<2400;y++)
959 {
960 a=(y-1700)/70 ;
961 for (x=0;x<30;x++)
962 {
963 setpixel (y+100,vpos+x*10+a,BLACK);
964 }
965 }
966
967 for (y=2400;y<3100;y++)
968 {
969 a=(y-2400)%70 ;
970 if (a==0)
971 {
972 for (x=0;x<300;x++)
973 {
974 setpixel ( y+100,x+vpos,BLACK);
975 }
976 }
977 }
978 }
979
980
981 void
982 color_squares( void )
983 {
984 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 ...
988
989
990 z=0;
991 for (x=0;x<5;x++)
992 for (y=0;y<5;y++)
993 {
994 setsquare( 300*(x+1), 300+300*(y),200, 1+x,1+y,1+z);
995 setchar( 300*(x+1), 270+300*(y), '0' + x,3);
996 setchar( 40+300*(x+1), 270+300*(y), '0' + y,3);
997 setchar( 80+300*(x+1), 270+300*(y), '0' + z,3);
998 }
999 z=1;
1000 for (x=0;x<5;x++)
1001 for (y=0;y<5;y++)
1002 {
1003 setsquare( 1500+300*(x+1), 300+300*(y),200, 1+x,1+y,1+z);
1004 setchar( 1500+300*(x+1), 270+300*(y), '0' + x,3);
1005 setchar( 1540+300*(x+1), 270+300*(y), '0' + y,3);
1006 setchar( 1580+300*(x+1), 270+300*(y), '0' + z,3);
1007 }
1008 z=2;
1009 for (x=0;x<5;x++)
1010 for (y=0;y<5;y++)
1011 {
1012 setsquare( 3000+300*(x+1), 300+300*(y),200, 1+x,1+y,1+z);
1013 setchar( 3000+300*(x+1), 270+300*(y), '0' + x,3);
1014 setchar( 3040+300*(x+1), 270+300*(y), '0' + y,3);
1015 setchar( 3080+300*(x+1), 270+300*(y), '0' + z,3);
1016 }
1017 z=3;
1018 for (x=0;x<5;x++)
1019 for (y=0;y<5;y++)
1020 {
1021 setsquare( 300*(x+1), 1800+300*(y),200, 1+x,1+y,1+z);
1022 setchar( 300*(x+1), 1770+300*(y), '0' + x,3);
1023 setchar( 40+300*(x+1), 1770+300*(y), '0' + y,3);
1024 setchar( 80+300*(x+1), 1770+300*(y), '0' + z,3);
1025 }
1026 z=4;
1027 for (x=0;x<5;x++)
1028 for (y=0;y<5;y++)
1029 {
1030 setsquare( 1500+300*(x+1), 1800+300*(y),200, 1+x,1+y,1+z);
1031 setchar( 1500+300*(x+1), 1770+300*(y), '0' + x,3);
1032 setchar( 1540+300*(x+1), 1770+300*(y), '0' + y,3);
1033 setchar( 1580+300*(x+1), 1770+300*(y), '0' + z,3);
1034 }
1035 }
1036
0 /***********************************************************************
1 cutswath.c - function to cut a swath of a PNM file for PPA printers
2 -------------------
3 begin : Thu Jan 13 2000
4 copyright : (C) 1998-2000 by the pnm2ppa project
5 email :
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21
22 #define __CUTSWATH_C__
23
24 #include "syslog.h"
25 #include "global.h"
26 #include "debug.h"
27 #include "defaults.h"
28 #include "ppa.h"
29 #include "image.h"
30
31 #include "lang.h"
32
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 */
37
38 /* Upon successful completion, sweep_data->image_data and
39 sweep_data->nozzle_data have been set to pointers which this routine
40 malloc()'d. */
41
42 /* Upon successful completion, all members of *sweep_data have been set
43 except direction, vertical_pos, and next. */
44
45 /* Returns: 0 if unsuccessful
46 1 if successful, but with non-printing result (end of page)
47 2 if successful, with printing result
48 3 if unsuccessful, exceeded buffer size */
49
50 int
51 cut_im_black_swath (image_t *image, ppaPrinter_t *printer,
52 int maxlines, ppaSweepData_t *sweep_data)
53 {
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);
91 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 }
152 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
409 start_even= 0;
410 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 {
425 even_pre_blanklines++;
426 odd_non_blanklines++;
427 start_even= 1;
428 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
440
441 assert (( even_pre_blanklines + odd_pre_blanklines +
442 even_non_blanklines + odd_non_blanklines +
443 even_post_blanklines + odd_post_blanklines ) == numlines );
444
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
463
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]);
468 wrap_syslog (LOG_CRIT,"%s",syslog_message);
469
470 for (k = 0; k < gMaxPass; k++)
471 {
472 free (data[k]);
473 }
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 }
592 }
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 }
668 }
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;
736 }
737
738 #define UNUSABLE 1
739 #define CYAN (0<<1)
740 #define MAGENTA (1<<1)
741 #define YELLOW (2<<1)
742 #define ODD (1<<3)
743 #define EVEN (0<<3)
744 #define XSHIFT 4
745 #define XPOS(x) ((x)<<XSHIFT)
746
747
748 /* number of "special" columns at left of sweep */
749 /* different versions for left-to-right and right-to-left sweeps */
750 static int Right_size = 42;
751 static int Right_l2r[] = {
752 UNUSABLE,
753 UNUSABLE,
754 UNUSABLE,
755 UNUSABLE,
756 CYAN | EVEN | XPOS (0),
757 CYAN | ODD | XPOS (0),
758 CYAN | EVEN | XPOS (1),
759 UNUSABLE,
760 UNUSABLE,
761 CYAN | ODD | XPOS (1),
762 CYAN | EVEN | XPOS (2),
763 UNUSABLE,
764 UNUSABLE,
765 CYAN | ODD | XPOS (2),
766 CYAN | EVEN | XPOS (3),
767 UNUSABLE,
768 MAGENTA | EVEN | XPOS (0),
769 CYAN | ODD | XPOS (3),
770 CYAN | EVEN | XPOS (4),
771 UNUSABLE,
772 MAGENTA | ODD | XPOS (0),
773 MAGENTA | EVEN | XPOS (1),
774 CYAN | ODD | XPOS (4),
775 CYAN | EVEN | XPOS (5),
776 UNUSABLE,
777 UNUSABLE,
778 MAGENTA | ODD | XPOS (1),
779 MAGENTA | EVEN | XPOS (2),
780 CYAN | ODD | XPOS (5),
781 CYAN | EVEN | XPOS (6),
782 UNUSABLE,
783 UNUSABLE,
784 MAGENTA | ODD | XPOS (2),
785 MAGENTA | EVEN | XPOS (3),
786 CYAN | ODD | XPOS (6),
787 CYAN | EVEN | XPOS (7),
788 UNUSABLE,
789 YELLOW | EVEN | XPOS (0),
790 MAGENTA | ODD | XPOS (3),
791 MAGENTA | EVEN | XPOS (4),
792 CYAN | ODD | XPOS (7),
793 CYAN | EVEN | XPOS (8)
794 };
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 };
839
840 /* number of "special" columns at left of sweep */
841 static int Left_size = 32;
842 static int Left_l2r[] = {
843 YELLOW | ODD | XPOS (0),
844 YELLOW | EVEN | XPOS (0),
845 YELLOW | ODD | XPOS (1),
846 YELLOW | EVEN | XPOS (1),
847 YELLOW | ODD | XPOS (2),
848 YELLOW | EVEN | XPOS (2),
849 YELLOW | ODD | XPOS (3),
850 UNUSABLE,
851 MAGENTA | ODD | XPOS (0),
852 YELLOW | EVEN | XPOS (3),
853 YELLOW | ODD | XPOS (4),
854 MAGENTA | EVEN | XPOS (0),
855 MAGENTA | ODD | XPOS (1),
856 YELLOW | EVEN | XPOS (4),
857 YELLOW | ODD | XPOS (5),
858 MAGENTA | EVEN | XPOS (1),
859 MAGENTA | ODD | XPOS (2),
860 YELLOW | EVEN | XPOS (5),
861 YELLOW | ODD | XPOS (6),
862 UNUSABLE,
863 MAGENTA | EVEN | XPOS (2),
864 MAGENTA | ODD | XPOS (3),
865 YELLOW | EVEN | XPOS (6),
866 YELLOW | ODD | XPOS (7),
867 UNUSABLE,
868 CYAN | ODD | XPOS (0),
869 MAGENTA | EVEN | XPOS (3),
870 MAGENTA | ODD | XPOS (4),
871 YELLOW | EVEN | XPOS (7),
872 YELLOW | ODD | XPOS (8),
873 CYAN | EVEN | XPOS (0),
874 CYAN | ODD | XPOS (1)
875 };
876
877 /* the final odd yellow swing buffer doesnt fit in right-to-left
878 * color sweeps. Instead of redesigning the structure of the Left of
879 * the sweep (If it works, dont fix it ...)
880 * I'll just arrange that no printable data ever uses
881 * this last position .. (the leftmost printed dot) (duncan)
882 */
883
884 static int Left_r2l[] = {
885 UNUSABLE,//YELLOW | ODD | XPOS (0), //this data doesnt fit, what to do?
886 YELLOW | ODD | XPOS (1),
887 YELLOW | EVEN | XPOS (0),
888 YELLOW | ODD | XPOS (2),
889 YELLOW | EVEN | XPOS (1),
890 YELLOW | ODD | XPOS (3),
891 YELLOW | EVEN | XPOS (2),
892 MAGENTA | ODD | XPOS (0),
893 UNUSABLE,
894 YELLOW | ODD | XPOS (4),
895 YELLOW | EVEN | XPOS (3),
896 MAGENTA | ODD | XPOS (1),
897 MAGENTA | EVEN | XPOS (0),
898 YELLOW | ODD | XPOS (5),
899 YELLOW | EVEN | XPOS (4),
900 MAGENTA | ODD | XPOS (2),
901 MAGENTA | EVEN | XPOS (1),
902 YELLOW | ODD | XPOS (6),
903 YELLOW | EVEN | XPOS (5),
904 UNUSABLE,
905 MAGENTA | ODD | XPOS (3),
906 MAGENTA | EVEN | XPOS (2),
907 YELLOW | ODD | XPOS (7),
908 YELLOW | EVEN | XPOS (6),
909 CYAN | ODD | XPOS (0),
910 UNUSABLE,
911 MAGENTA | ODD | XPOS (4),
912 MAGENTA | EVEN | XPOS (3),
913 YELLOW | ODD | XPOS (8),
914 YELLOW | EVEN | XPOS (7),
915 CYAN | ODD | XPOS (1),
916 CYAN | EVEN | XPOS (0)
917 };
918
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)
927 {
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 ;
937 int start_even, start_odd;
938 int vpos_shift=600; /* "vertical position" = line number - vpos_shift */
939
940 BOOLEAN got_nonblank;
941 int horzpos, hp2;
942 ppaNozzleData_t nozzles[6];
943
944 /* maxlines needs to be even */
945 assert( !(maxlines % 2 ));
946
947 place = NULL;
948 ppa = NULL;
949 maxplace = NULL;
950
951 /* safeguard against the user freeing these */
952 for (k = 0; k < gMaxPass; k++) //mocho
953 {
954 sweep_data->image_data[k] = NULL;
955 }
956 sweep_data->nozzle_data = NULL;
957
958 /* read the data from the input file */
959 width8 = (image->width / 2 + 7) / 8;
960 DPRINTF ("width8 * 3 * maxlines = %d\n", width8 * 3 * maxlines);
961 for (k = 0; k < gMaxPass; k++) //mocho
962 {
963 if ((data[k] = malloc (width8 * 3 * maxlines + 8)) == NULL)
964 {
965 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
966 gMessages[E_CS_BADMALLOC]);
967 wrap_syslog (LOG_CRIT,"%s",syslog_message);
968 return 0;
969 }
970 }
971
972 /* protect against weird margin settings */
973
974 left_limit = printer->left_margin / 2 / 8;
975 if ( left_limit < 0 )
976 left_limit = 0 ;
977 right_limit = (gWidth - printer->right_margin) / 2 / 8;
978 if ( right_limit > width8 )
979 right_limit = width8 ;
980 bottom_limit = gHeight - printer->bottom_margin ;
981 if ( bottom_limit > gHeight)
982 bottom_limit = gHeight ;
983 if ( bottom_limit < 0 )
984 bottom_limit = 0;
985 top_limit = printer->top_margin ;
986 if ( top_limit < 0 )
987 top_limit = 0 ;
988 if ( top_limit > bottom_limit )
989 top_limit = bottom_limit ;
990
991
992 /* ignore lines that are above the upper margin */
993 while (image->colorCurLine < top_limit )
994 if (!im_color_readline (image, data, 0))
995 {
996 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
997 gMessages[E_CS_BADTOPMARG]);
998 wrap_syslog (LOG_CRIT,"%s",syslog_message);
999
1000 for (k = 0; k < gMaxPass; k++) // mocho
1001 {
1002 free (data[k]);
1003 }
1004 return 0;
1005 }
1006
1007 /* eat all lines that are below the lower margin */
1008 if (image->colorCurLine >= bottom_limit )
1009 {
1010 while (image->colorCurLine < image->height)
1011 if (!im_color_readline (image, data, 0))
1012 {
1013 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1014 gMessages[E_CS_BADBOTMARG]);
1015 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1016
1017 for (k = 0; k < gMaxPass; k++)
1018 {
1019 free (data[k]); //mocho
1020 }
1021 return 0;
1022 }
1023 for (k = 0; k < gMaxPass; k++)
1024 {
1025 free (data[k]); //mocho
1026 }
1027 DPRINTF (" cut_im_color_swath: return 1 on line %d\n", __LINE__);
1028 return 1;
1029 }
1030
1031
1032 left = right_limit - 1;
1033 right = left_limit;
1034
1035 got_nonblank = false;
1036 numlines = 0;
1037 pre_blanklines = 0;
1038 post_blanklines = 0;
1039 at_bottom = false ;
1040 sweep_offset = 0;
1041 /* eat all beginning blank lines and then up to maxlines or lower margin */
1042 while (
1043 ( image->colorCurLine + (2* pre_blanklines) < bottom_limit ) &&
1044 ( (numlines + pre_blanklines + post_blanklines) < maxlines)
1045 && (got_nonblank ||
1046 ((image->buflines < MAXBUFFLINES) || (image->buftype == color))))
1047 {
1048 if (!im_color_readline (image, data, width8 * 3 * numlines)) //mocho
1049 {
1050 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1051 gMessages[E_CS_BADNEXTLINE]);
1052 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1053
1054 for (k = 0; k < gMaxPass; k++)
1055 {
1056 free (data[k]); //mocho
1057 }
1058 return 0;
1059 }
1060 if (!got_nonblank)
1061 {
1062 for (i = left_limit * 3; i < right_limit * 3; i++)
1063 {
1064 if ((data[gMaxPass - 1][i]))
1065 {
1066 left = i / 3;
1067 got_nonblank = true;
1068 right = left;
1069 for (j = right_limit * 3 - 1; j > left * 3 + 2; j--)
1070 {
1071 if ((data[gMaxPass - 1][j]))
1072 {
1073 right = j / 3;
1074 break;
1075 }
1076 }
1077 /* begin a new swath;, nonblank pixels occur in
1078 * bytes "left" through "right", inclusive,
1079 * where
1080 * left_limit <= left <= right < right_limit.
1081 * This range will be expanded if necessary
1082 * as the swath is constructed
1083 */
1084 DPRINTF("cut_im_color_swath: begin swath, line %d\n",
1085 image->colorCurLine ) ;
1086
1087 /* vertical position of top of swath */
1088 top_vpos = image->colorCurLine - vpos_shift + printer->ColBwOffsY ;
1089
1090 /* predicted vertical position of bottom of swath */
1091 bottom_vpos = top_vpos + 2* ( maxlines - 1);
1092 if ( bottom_vpos > bottom_limit - vpos_shift + printer->ColBwOffsY )
1093 {
1094 at_bottom = true;
1095 bottom_vpos = bottom_limit - vpos_shift + printer->ColBwOffsY ;
1096 /* make sure we are at least 20 dots below the previous
1097 color swath vertical position (this is only
1098 a possible problem if we are at the bottom limit)*/
1099 if ( ( c_vpos + 21 - bottom_vpos )/2 > 0)
1100 {
1101 post_blanklines += (c_vpos + 21 - bottom_vpos) /2 ;
1102 bottom_vpos += 2 * post_blanklines ;
1103 }
1104 }
1105
1106 DPRINTF("cut_im_color_swath: shifted bottom_limit=%d, bottom_vpos=%d\n",
1107 bottom_limit - vpos_shift, bottom_vpos) ;
1108
1109 /* sweep_offset is the difference in vertical position
1110 of consecutive color and black sweeps.
1111 Flashing lights happen on the HP820 if this
1112 is -3, -2, -1, 1 , 2 or 3! */
1113
1114 /* compare to last black vpos */
1115 sweep_offset = bottom_vpos - b_vpos ;
1116
1117 if ( ( sweep_offset >= -4 ) &&
1118 ( sweep_offset < 4 ) &&
1119 ( (sweep_offset !=0 ) || at_bottom ))
1120 {
1121 if ( (at_bottom) &&
1122 ( b_vpos + 2 * ((5 - sweep_offset ) / 2) < top_vpos + 2 * ( maxlines - 1 ) ) )
1123 {
1124 /* we are at bottom of page, and can add post_blanklines */
1125 post_blanklines += ( 5 - sweep_offset ) /2 ;
1126 }
1127 else
1128 {
1129 /* we are in the middle of the page ;
1130 add pre_blanklines to shift swath end up */
1131 if ( sweep_offset == 3 )
1132 {
1133 /* shift swath upward to vpos - 7 */
1134 pre_blanklines = 5;
1135 }
1136 else if ( sweep_offset == 2 )
1137 {
1138 /* shift swath upward to vpos - 6 */
1139 pre_blanklines = 4;
1140 }
1141 else if ( sweep_offset == 1 )
1142 {
1143 /* shift swath upward to vpos - 7 */
1144 pre_blanklines = 4;
1145 }
1146 else if ( sweep_offset == -1 )
1147 {
1148 /* shift swath upward to vpos -7 */
1149 pre_blanklines = 3;
1150 }
1151 else if ( sweep_offset == -2 )
1152 {
1153 /* shift swath upward to vpos -6 */
1154 pre_blanklines = 2;
1155 }
1156 else if ( sweep_offset == -3 )
1157 {
1158 /* shift swath upward to vpos - 7 */
1159 pre_blanklines = 2;
1160 }
1161 else if ( sweep_offset == -4 )
1162 {
1163 /* shift swath upward to vpos - 6 */
1164 pre_blanklines = 1;
1165 }
1166 }
1167 }
1168 /*will add pre_blanklines blank lines at the top of the swath
1169 and post_blanklines at the end of the swath.
1170 Note that allowance has been made for a possible
1171 extra post_blankline to compensate for odd numlines */
1172 break;
1173 }
1174 }
1175 }
1176
1177 if (got_nonblank)
1178 {
1179 /* find left-most nonblank */
1180 for (i = left_limit * 3; i < left * 3; i++)
1181 {
1182 // fprintf(stderr, "left: %d ", i);
1183 if ((data[gMaxPass - 1][width8 * 3 * numlines + i]))
1184 {
1185 left = i / 3;
1186 break;
1187 }
1188 }
1189 /* find right-most nonblank */
1190 for (j = right_limit * 3 - 1 ; j > right * 3 + 2 ; j--)
1191 {
1192 // fprintf(stderr, "right: %d ", i);
1193 if ((data[gMaxPass - 1][width8 * 3 * numlines + j]))
1194 {
1195 right = j / 3;
1196 break;
1197 }
1198 }
1199 numlines++;
1200 }
1201 }
1202
1203 if ((image->buflines >= MAXBUFFLINES) && (image->buftype == bitmap))
1204 {
1205 DPRINTF
1206 ("cut_im_color_swath: exceeding buffer size: image.buflines=%d, MAX=%d\n",
1207 image->buflines, MAXBUFFLINES);
1208 if ((!got_nonblank))
1209 {
1210 for (k = 0; k < gMaxPass; k++)
1211 free (data[k]);
1212 return 3;
1213 }
1214 }
1215
1216
1217 if ((!got_nonblank))
1218 {
1219 /* eat all lines that are below the lower margin */
1220 if (image->colorCurLine >= bottom_limit)
1221 {
1222 while (image->colorCurLine < image->height)
1223 if (!im_color_readline (image, data, 0))
1224 {
1225 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1226 gMessages[E_CS_BADBOTMARG]);
1227 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1228
1229 for (k = 0; k < gMaxPass; k++)
1230 {
1231 free (data[k]); //mocho
1232 }
1233 return 0;
1234 }
1235 for (k = 0; k < gMaxPass; k++)
1236 {
1237 free (data[k]); //mocho
1238 }
1239 DPRINTF
1240 ("cut_im_color_swath: return 1 on line %d; ccl: %d; height: %d\n",
1241 __LINE__, image->colorCurLine, bottom_limit );
1242 return 1;
1243 }
1244 for (k = 0; k < gMaxPass; k++)
1245 {
1246 free (data[k]); //mocho
1247 }
1248 return 0;
1249 /* error, since didn't get to lower margin, yet blank */
1250 }
1251
1252 sweep_data->vertical_pos = image->colorCurLine + printer->ColBwOffsY ;
1253
1254 /* subtract that 600 dot adjustment here */
1255 sweep_data->vertical_pos -= vpos_shift;
1256
1257 DPRINTF("cut_im_color_swath: end swath, line %d numlines=%d left=%d right=%d\n",
1258 image->colorCurLine, numlines, left, right ) ;
1259
1260
1261
1262 /* calculate number of blank lines added at top and bottom of swath */
1263
1264 non_blanklines = numlines ;
1265 numlines += pre_blanklines ;
1266 if ( (numlines + post_blanklines) % 2 )
1267 post_blanklines++ ;
1268 numlines += post_blanklines ;
1269 assert (maxlines >= numlines );
1270 sweep_data->vertical_pos += 2 * post_blanklines ;
1271
1272
1273 even_pre_blanklines = odd_pre_blanklines = pre_blanklines / 2 ;
1274 even_non_blanklines = odd_non_blanklines = non_blanklines / 2 ;
1275 even_post_blanklines = odd_post_blanklines = post_blanklines / 2 ;
1276
1277 start_even= 0;
1278 start_odd = 1;
1279
1280 if ( (pre_blanklines %2 == 0) &&
1281 !(non_blanklines % 2 == 0) &&
1282 !(post_blanklines % 2 == 0))
1283 {
1284 even_non_blanklines++ ;
1285 odd_post_blanklines++;
1286 start_even= 0;
1287 start_odd = 1;
1288 }
1289 if ( !(pre_blanklines %2 == 0) &&
1290 !(non_blanklines % 2 == 0) &&
1291 (post_blanklines % 2 == 0))
1292 {
1293 even_pre_blanklines++;
1294 odd_non_blanklines++;
1295 start_even= 1;
1296 start_odd = 0;
1297 }
1298 if ( !(pre_blanklines %2 == 0) &&
1299 (non_blanklines % 2 == 0) &&
1300 !(post_blanklines % 2 == 0))
1301 {
1302 even_pre_blanklines++;
1303 odd_post_blanklines++;
1304 start_even= 1;
1305 start_odd = 0;
1306 }
1307
1308
1309 assert ( numlines % 2 == 0);
1310 assert (( even_pre_blanklines +
1311 even_non_blanklines +
1312 even_post_blanklines ) == numlines/2 );
1313 assert (( odd_pre_blanklines +
1314 odd_non_blanklines +
1315 odd_post_blanklines ) == numlines/2 );
1316
1317
1318 if (pre_blanklines)
1319 {
1320 DPRINTF("cut_im_color_swath: offset %d; add pre_blanklines=%d lines\n",
1321 sweep_offset, pre_blanklines);
1322 }
1323 if (post_blanklines)
1324 {
1325 DPRINTF("cut_im_color_swath: offset %d; add post_blanklines=%d lines\n",
1326 sweep_offset, post_blanklines);
1327 }
1328
1329
1330 /* printing in the leftmost and rightmost bytes of the color
1331 * swath leads to problems, so expand the swath width to avoid
1332 * using these locations. Nothing will ever get printed in these
1333 * expanded ends of the swath. (They are either whitespace,
1334 * or outside the limits, where data is rejected below)
1335 */
1336 left -= 2;
1337 right += 3;
1338 p_width8 = right - left ;
1339
1340 /* enforce a minimum swath width of 8 bytes */
1341 if ( p_width8 < 8 )
1342 {
1343 if (left > left_limit + 8 )
1344 left = left - 8 + p_width8 ;
1345 else
1346 right = right + 8 - p_width8 ;
1347 }
1348 p_width8 = right - left ;
1349
1350 /* always left-to-right if gUnimode is true */
1351 if (gUnimode)
1352 sweep_data->direction = left_to_right;
1353 else if ((b_vpos > c_vpos) && (b_vpos < sweep_data->vertical_pos))
1354 {
1355 if (b_dir == left_to_right)
1356 sweep_data->direction = right_to_left;
1357 else
1358 sweep_data->direction = left_to_right;
1359 } else
1360 {
1361 if (c_dir == left_to_right)
1362 sweep_data->direction = right_to_left;
1363 else
1364 sweep_data->direction = left_to_right;
1365 }
1366
1367 DPRINTF("cut_im_color_swath: b_left %d b_right %d b_vpos %d b_dir %d\n",
1368 b_left, b_right, b_vpos, b_dir);
1369 DPRINTF("cut_im_color_swath: prev c_left %d c_right %d c_vpos %d c_dir %d\n",
1370 c_left, c_right, c_vpos, c_dir);
1371 DPRINTF("cut_im_color_swath: cur left %d right %d vpos %d dir %d\n",
1372 left, right, sweep_data->vertical_pos, sweep_data->direction);
1373 c_left = left;
1374 c_right = right;
1375 c_vpos = sweep_data->vertical_pos;
1376 c_dir = sweep_data->direction;
1377
1378
1379 for (k = 0; k < gMaxPass; k++)
1380 {
1381 if ((ppa = malloc ( (p_width8 + 3 ) * numlines * 3)) == NULL)
1382 {
1383 snprintf(syslog_message,message_size,"cut_im_color_swath(): %s",
1384 gMessages[E_CS_BADPPAMALLOC]);
1385 wrap_syslog (LOG_CRIT,"%s",syslog_message);
1386
1387 for (k = 0; k < gMaxPass; k++)
1388 free (data[k]);
1389 return 0;
1390 }
1391
1392 place = ppa;
1393
1394 if (sweep_data->direction == right_to_left)
1395 {
1396 for (i = (p_width8 + 1) * 6 - 1 ; i >= 0; i--)
1397 {
1398 int color, x, odd, y ;
1399 j = (p_width8 + 1) * 6 - 1 - i ;
1400 if (i < Left_size )
1401 {
1402 if (!GET_USABLE (Left_r2l, i))
1403 {
1404 memset (place, 0x00, numlines / 2);
1405 place += numlines / 2;
1406 continue;
1407 }
1408 odd = GET_ODD (Left_r2l, i );
1409 color = GET_COLOR (Left_r2l, i);
1410 x = GET_X (Left_r2l, i );
1411 }
1412 else if (j < Right_size )
1413 {
1414 if (!GET_USABLE (Right_r2l,j))
1415 {
1416 memset (place, 0x00, numlines / 2);
1417 place += numlines / 2;
1418 continue;
1419 }
1420 color = GET_COLOR (Right_r2l, j);
1421 odd = GET_ODD (Right_r2l, j);
1422 x = p_width8 - 3 - GET_X (Right_r2l, j);
1423 }
1424 else
1425 {
1426 color = (i / 2 - 15) % 3;
1427 odd = (i + 1) % 2;
1428 x = (i - 24) / 6 - 1 + odd + (color == 0 ? 0 :/* cyan */
1429 color == 1 ? 4 :/* magenta */
1430 8); /* yellow */
1431 }
1432 if (x + left < left_limit || x + left >= right_limit)
1433 {
1434 /* never print data that is outside the limits */
1435 memset (place, 0x00, numlines / 2);
1436 place += numlines / 2;
1437 }
1438 else
1439 {
1440 int new_pre_blanklines , new_non_blanklines , new_post_blanklines;
1441 int new_start;
1442 if (odd)
1443 {
1444 /* odd lines */
1445 new_pre_blanklines = odd_pre_blanklines ;
1446 new_non_blanklines = odd_non_blanklines ;
1447 new_post_blanklines = odd_post_blanklines ;
1448 new_start = start_odd;
1449 }
1450 else
1451 {
1452 /* even lines */
1453 new_pre_blanklines = even_pre_blanklines ;
1454 new_non_blanklines = even_non_blanklines ;
1455 new_post_blanklines = even_post_blanklines ;
1456 new_start = start_even;
1457 }
1458 if ( new_pre_blanklines > 0 )
1459 {
1460 /* first pre_blanklines lines are blank */
1461 memset(place, 0x00, new_pre_blanklines ) ;
1462 place += new_pre_blanklines ;
1463 }
1464 for (y = 0; y < new_non_blanklines ; y++)
1465 {
1466 int index ;
1467 index = ( (y * 2 + new_start) * width8 * 3 +
1468 (x + left ) * 3 + color ) ;
1469
1470 if (index >= (width8 * 3 * maxlines ))
1471 {
1472 DPRINTF ("index out of range! index = %d\n", index);
1473 index = (width8 * 3 * maxlines ) - 1;
1474 }
1475
1476 assert ( index < width8 * 3 * maxlines && index >= 0 );
1477 *place++ = data[k][index];
1478 }
1479 if ( new_post_blanklines > 0 )
1480 {
1481 /* last post_blanklines lines are blank */
1482 memset(place, 0x00, new_post_blanklines ) ;
1483 place += new_post_blanklines ;
1484 }
1485 }
1486 }
1487
1488 }
1489 else /* sweep direction is left-to-right */
1490 {
1491 for (i = 0; i < (p_width8 + 1) * 6 ; i++)
1492 {
1493 int color, x, odd, y;
1494 j = (p_width8 + 1) * 6 - 1 - i ;
1495 if (i < Left_size)
1496 {
1497 if (!GET_USABLE (Left_l2r, i))
1498 {
1499 memset (place, 0x00, numlines / 2);
1500 place += numlines / 2;
1501 continue;
1502 }
1503 color = GET_COLOR (Left_l2r, i);
1504 odd = GET_ODD (Left_l2r, i);
1505 x = GET_X (Left_l2r, i);
1506 }
1507 else if ( j < Right_size )
1508 {
1509 if (!GET_USABLE (Right_l2r, j))
1510 {
1511 memset (place, 0x00, numlines / 2);
1512 place += numlines / 2;
1513 continue;
1514 }
1515 color = GET_COLOR (Right_l2r, j);
1516 odd = GET_ODD (Right_l2r, j);
1517 x = p_width8 -3 - GET_X (Right_l2r,j);
1518 }
1519 else
1520 {
1521 color = (i / 2 - 15) % 3;
1522 odd = i % 2;
1523 x = (i - 24) / 6 - 1 + odd + (color == 0 ? 0 :/* cyan */
1524 color == 1 ? 4 :/* magenta */
1525 8); /* yellow */
1526 }
1527 if (x + left < left_limit || x + left >= right_limit)
1528 {
1529 /* never print data that is outside the limits */
1530 memset (place, 0x00, numlines / 2);
1531 place += numlines / 2;
1532 }
1533 else
1534 {
1535 int new_pre_blanklines , new_non_blanklines , new_post_blanklines;
1536 int new_start;
1537 if (odd)
1538 {
1539 /* odd lines */
1540 new_pre_blanklines = odd_pre_blanklines ;
1541 new_non_blanklines = odd_non_blanklines ;
1542 new_post_blanklines = odd_post_blanklines ;
1543 new_start = start_odd;
1544 }
1545 else
1546 {
1547 /* even lines */
1548 new_pre_blanklines = even_pre_blanklines ;
1549 new_non_blanklines = even_non_blanklines ;
1550 new_post_blanklines = even_post_blanklines ;
1551 new_start = start_even;
1552 }
1553 if ( new_pre_blanklines > 0 )
1554 {
1555 /* first pre_blanklines lines are blank */
1556 memset (place, 0x00, new_pre_blanklines ) ;
1557 place += new_pre_blanklines ;
1558 }
1559 for (y = 0; y < new_non_blanklines; y++)
1560 {
1561 int index ;
1562 index = ((y * 2 + new_start) * width8 * 3 +
1563 (x + left ) * 3 + color);
1564
1565 if (index >= (width8 * 3 * maxlines + 8))
1566 {
1567 DPRINTF ("index out of range! index = %d\n",index);
1568 index = (width8 * 3 * maxlines + 8) - 1;
1569 }
1570
1571 assert ( index < width8 * 3 * maxlines + 8 && index >= 0 );
1572 *place++ = data[k][index];
1573 }
1574 if ( new_post_blanklines > 0 )
1575 {
1576 /* last post_blanklines lines are blank */
1577 memset(place, 0x00, new_post_blanklines) ;
1578 place += new_post_blanklines ;
1579 }
1580 }
1581 }
1582 }
1583 maxplace = place;
1584
1585 /* create sweep data */
1586 sweep_data->image_data[k] = ppa;
1587 }
1588
1589 sweep_data->data_size = maxplace - ppa;
1590 sweep_data->in_color = true;
1591
1592 horzpos = (left - 7) * 8 * 2 + printer->ColBwOffsX - 600 ;
1593
1594 horzpos += (sweep_data->direction == left_to_right) ? 2 : 12 ;
1595
1596 if (sweep_data->direction == right_to_left )
1597 horzpos += printer->r2l_col_offset ; /*correct bidirectional shearing*/
1598
1599 hp2 = 16 + horzpos + p_width8 * 2 * 8;
1600 sweep_data->left_margin = horzpos;
1601 sweep_data->right_margin = hp2 + 0x74; /* printer->color_marg_diff */
1602
1603 DPRINTF("sweep data: left_margin = %d, right margin = %d\n",
1604 sweep_data->left_margin, sweep_data->right_margin);
1605
1606 for (i = 0; i < 6; i++)
1607 {
1608 nozzles[i].DPI = 300;
1609 nozzles[i].pins_used_d2 = numlines / 2;
1610 nozzles[i].unused_pins_p1 = 65 - numlines;
1611 nozzles[i].first_pin = 1;
1612 if (i == 0)
1613 {
1614 nozzles[i].left_margin = horzpos + 0x74;
1615 nozzles[i].right_margin = hp2 + 0x74;
1616 if (sweep_data->direction == right_to_left)
1617 nozzles[i].nozzle_delay = 0;
1618 else
1619 nozzles[i].nozzle_delay = 0;
1620 }
1621 if (i == 1)
1622 {
1623 nozzles[i].left_margin = horzpos + 0x64;
1624 nozzles[i].right_margin = hp2 + 0x64;
1625 if (sweep_data->direction == right_to_left)
1626 nozzles[i].nozzle_delay = 0;
1627 else
1628 nozzles[i].nozzle_delay = 0;
1629 }
1630 if (i == 2)
1631 {
1632 nozzles[i].left_margin = horzpos + 0x3A;
1633 nozzles[i].right_margin = hp2 + 0x3A;
1634 if (sweep_data->direction == right_to_left)
1635 nozzles[i].nozzle_delay = 0x0A;
1636 else
1637 nozzles[i].nozzle_delay = 0x0A;
1638 }
1639 if (i == 3)
1640 {
1641 nozzles[i].left_margin = horzpos + 0x3A;
1642 nozzles[i].right_margin = hp2 + 0x3A;
1643 if (sweep_data->direction == right_to_left)
1644 nozzles[i].nozzle_delay = 0x0A;
1645 else
1646 nozzles[i].nozzle_delay = 0x0A;
1647
1648 }
1649 if (i == 4)
1650 {
1651 nozzles[i].left_margin = horzpos + 0x10;
1652 nozzles[i].right_margin = hp2 + 0x10;
1653 if (sweep_data->direction == right_to_left)
1654 nozzles[i].nozzle_delay = 0x04;
1655 else
1656 nozzles[i].nozzle_delay = 0x04;
1657
1658 }
1659 if (i == 5)
1660 {
1661 nozzles[i].left_margin = horzpos + 0x00;
1662 nozzles[i].right_margin = hp2 + 0x00;
1663 if (sweep_data->direction == right_to_left)
1664 nozzles[i].nozzle_delay = 0x04;
1665 else
1666 nozzles[i].nozzle_delay = 0x04;
1667
1668 }
1669 }
1670
1671 sweep_data->nozzle_data_size = 6;
1672 sweep_data->nozzle_data = malloc (sizeof (nozzles));
1673 if (sweep_data->nozzle_data == NULL)
1674 return 0;
1675 memcpy (sweep_data->nozzle_data, nozzles, sizeof (nozzles));
1676
1677 DPRINTF ("cut_im_color_swath: return 2 on line %d\n", __LINE__);
1678
1679 for (k = 0; k < gMaxPass; k++)
1680 free (data[k]);
1681
1682 return 2;
1683
1684 }
1685
1686 /*
1687
1688 Here, we should call cut_im_black_swath and cut_im_color_swath to begin.
1689
1690 Then, we need to determine which of these swaths comes earlier on the page