Bug 691029

Summary: Back sides not correct when duplexing, probably due to CTM recalculation not done in time
Product: Ghostscript Reporter: Till Kamppeter <till.kamppeter>
Component: CUPS driverAssignee: Ray Johnston <ray.johnston>
Status: RESOLVED FIXED    
Severity: normal CC: ralph.giles, twaugh
Priority: P4    
Version: 8.70   
Hardware: All   
OS: All   
Customer: Word Size: ---
Attachments: frontback.pdf
hp990-2.ppd
pdftops-out.ps
pstops-out.ps
4.pdf
ppd.ppd
pdftops.ps
pstoraster.rast.bz2
cups/gdevcups.c

Description Till Kamppeter 2009-12-29 02:58:09 UTC
The CUPS Raster output device ("cups", cups/gdevcups.c) supports flipped raster
data output for the back sides of the pages when printing duplex, especially
used by the HP inkjets which print the back sides backwards when duplexing.

It makes use of an extra parameter given by the cupsBackSide PPD keyword
described on http://www.cups.org/documentation.php/doc-1.4/spec-ppd.html. To
implement this parameter cups/gdevcups.c adapts the CTM via the
cups_get_matrix() function, making the CTM not only dependent on things like
page size and margins but also on the page number (odd are front sides and even
are back sides). This means that the CTM must be recomputed always exactly after
the previous page has completed and before the transformation of the current
page with the CTM and that also if page size and margins do not change.

With PDF code as input this works perfectly, as the PDF interpreter of GS seems
to trigger the recomputation of the matrix much more often as the PS
interpreter. With PostScript input one still sees that the matrix is often
recomputed, but probably too late, after the transfer done with the matrix, as
the resulting raster output shows that the old matrix (of page 1) was used for
page 2.

So what I am looking for is a small change on cups/gdevcups.c which makes the
matrix recomputation being triggered at the right moment, like a function call
somewhere, a pseudo page size change, ...

Do you have any idea?

Or did Mike Sweet commit a big design flaw when he implemented this device?

In general, not nice from him leaving us with this device, with a lot of bugs,
and not taking care of it any more, but recommending to everyone to write CUPS
Raster drivers.

Thanks in advance for any help.
Comment 1 Ray Johnston 2009-12-29 12:21:53 UTC
Looking at the documentation on the cupsBackSide it looks like it provides
extensions beyond the PostScript 'Duplex' and 'Tumble'. It may be that the 
standard 'LeadingEdge' parameter is the missing piece.

Unfortunately, the testing of this is difficult since I don't have the stated
printer, so I'll just have to try and 'guess' if it is working since it isn't
clear (to me) what is meant by:

> This means that the CTM must be recomputed always exactly after
> the previous page has completed and before the transformation of the current
> page with the CTM and that also if page size and margins do not change.

in terms of the device calls to 'outputpage' and 'get_initial_matrix'
and the PostScript level setpagedevice 'BeginPage' and 'EndPage'. If possible,
please provide the output with the following BeginPage and EndPage procs in
the pagedevice:

<< /BeginPage {
     (BeginPage page ) print =print
     matrix currentmatrix (, matrix: ) print == flush
   }
   /EndPage {
     (EndPage code=) print dup =print
     initmatrix matrix currentmatrix (, matrix: ) print == flush
     exch pop 2 lt
   }
>> setpagedevice


Comment 2 Till Kamppeter 2009-12-29 12:33:19 UTC
The problem here is that the matrix does not only depend on the options set by
the user (duplex, tumble, resolution, ...) but also on whether the page is a
front side (odd page) or a back side (even page). So the matrix also needs to be
recomputed even if the input PostScript code has no command which changes an
option between two pages (probably no "setpagedevice").
Comment 3 Till Kamppeter 2009-12-29 12:47:59 UTC
See also https://bugs.launchpad.net/hplip/+bug/484928
Comment 4 Till Kamppeter 2009-12-29 12:59:48 UTC
Here is the stderr output with the modified BeginPage and EndPage procs:

BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6525.0]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6525.0]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 1, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
BeginPage page 2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]

One sees that for page 2 the matrix did not get switched.
Comment 5 Till Kamppeter 2009-12-29 13:13:35 UTC
Now I have left in several debug output lines of the CUPS Raster output device
(the ones which contain "Processing page " and "matrix"). Now you can see where
the output device driver starts to work on a new page (First page is page 1, in
contrary to Ghostscript's internal counting starting with 0) and where it
recomputed the CTM. One sees clearly that the CUPS output device uses a matrix
with a positive 4th component (YY) for the second page but Ghostscript's page
device did not overtake it, It continues with the matrix of the first page, with
negative YY.

INFO: Processing page 1...
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -0.000 1100.000 ]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -12.500 1050.000 ]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
EndPage code=2, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
BeginPage page 0, matrix: [1.38888884 0.0 0.0 -1.38888884 -25.0 1087.5]
DEBUG2: matrix = [ 1.389 0.000 0.000 -1.389 -25.000 1087.500 ]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6525.000 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6525.0]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6525.000 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6525.0]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6525.000 ]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
BeginPage page 0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
EndPage code=0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
INFO: Processing page 2...
DEBUG2: matrix = [ 8.333 0.000 0.000 8.333 -150.000 -300.000 ]
BeginPage page 1, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 8.333 -150.000 -75.000 ]
EndPage code=0, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 8.333 -150.000 -75.000 ]
INFO: Processing page 3...
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6708.333 ]
BeginPage page 2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -75.000 6708.333 ]
DEBUG2: matrix = [ 8.333 0.000 0.000 -8.333 -150.000 6933.333 ]
EndPage code=2, matrix: [8.33333302 0.0 0.0 -8.33333302 -150.0 6933.3335]
Comment 6 Ray Johnston 2009-12-29 13:20:07 UTC
Thanks, Till. One last request. Please show a 2(or more) page PDF so I
can see what that does.
Comment 7 Till Kamppeter 2009-12-29 13:30:48 UTC
I use the attached PDF as input file and the attached PPD file (with your
BeginPage/EndPage redefinitions as a *JobPatchFile) and run

export PPD=/etc/cups/ppd/hp990-2.ppd
cat frontback.pdf | /usr/lib/cups/filter/pdftops 1 1 1 1 'Duplex=DuplexNoTumble
PageSize=A4Duplex' | /usr/lib/cups/filter/pstops 1 1 1 1 'Duplex=DuplexNoTumble
PageSize=A4Duplex' | /usr/lib/cups/filter/pstoraster 1 1 1 1
'Duplex=DuplexNoTumble PageSize=A4Duplex' > out.raster 2>log

Then I do

egrep '\b((Begin|End)Page|Processing page |matrix)\b' log | uniq > importantlog

to get the output which I have posted in my previous comment. The result is a
file in CUPS Raster format which one can visualize with rasterview from

http://www.easysw.com/~mike/rasterview/index.html

To show what one can observe in the CUPS Raster output I post some ASCII art
here which is from the original mail which Tim Waugh from Red Hat sent to me:

Assuming that this is the original document

+-----+  +-----+
|  /->|  |  /->|
| /   |  | /   |
|/    |  |/    |
+-----+  +-----+

we want to have this in the raster output:

+-----+  +-----+
|  /->|  |    /|
| /   |  |   / |
|/    |  |<-/  |
+-----+  +-----+

But this is what we get:

+-----+  +-----+
|  /->|  |<-\  |
| /   |  |   \ |
|/    |  |    \|
+-----+  +-----+

So the Y-axis of the back side is flipped.
Comment 8 Till Kamppeter 2009-12-29 13:34:33 UTC
Created attachment 5825 [details]
frontback.pdf

PDF file used as input for the example in the previous comment.
Comment 9 Till Kamppeter 2009-12-29 13:36:08 UTC
Created attachment 5826 [details]
hp990-2.ppd

PPD file with the needed duplex setting and the BeginPage/EndPage debug code as
*JobPatchFile
Comment 10 Hin-Tak Leung 2009-12-29 17:03:02 UTC
Till: Ray gave me a tips about a somewhat similiar bug in PXL - 
http://bugs.ghostscript.com/show_bug.cgi?id=690948#c2
- the background is that most <<...>> setdevice has no effect on PXL because
page parameters can't be altered after the PXL BeginBage instruction is emitted. 

From what I understand of Ray's comment, it is possible to move most of what's
currently in the gs outputpage procedure to fillpage procedure (which currently
doesn't exist with pxl) including the PXL BeginBage instruction, thus delaying
it to a later stage. Maybe a similiar thing can be done for devcups. (the change
is quite invasive, that's why I am not spending much time on 690948 just yet,
since only one file is known to affected by it) 
Comment 11 Ray Johnston 2009-12-29 23:48:18 UTC
Now I am even _more_ confused. The original report stated:

> With PDF code as input this works perfectly

but the example attached with comments 7 & 8 are a PDF file, and comment 7 says
that the output is not "what we want".

The pictures go on to show that the back side does not have the Y-axis inverted,
which is what 'Tumble' is for, but the options to pdftops and cups specify:
Duplex=DuplexNoTumble which seems to contradict the desired 'Tumble' action.

Please try with the /Tumble true. Note that I don't know how these filters
change from Duplex=DuplexNoTumble to the setpagedevice /Duplex true /Tumble true
PostScript standard features.
Comment 12 Till Kamppeter 2009-12-30 01:05:19 UTC
The "With PDF code as input this works perfectly" means that it works perfectly
if PDF is fed directly into the Ghostscript process which uses the CUPS Raster
output device. In our example the original PDF file is turned into PostScript by
another process (pdftops), then all settings from the PPD file and the
BeginPage/EndPage debug code get injected (pstops) and afterwards Ghostscript
gets called with PostScript as input and using the "cups" output device to
produce CUPS Raster as output. In this situation (and this is the way most Linux
distributions handle print jobs) the problem occurs, also if the an applications
send PostScript directly the problem occurs. If PDF gets converted directly with

export PPD=/etc/cups/ppd/hp990-2.ppd
cat frontback.pdf | /usr/lib/cups/filter/pdftoraster 1 1 1 1
'Duplex=DuplexNoTumble PageSize=A4Duplex' > out.raster 2>log

The problem does not occur.

The HP inkjet printers print the back sides backwards (printing the bottom at
first) when duplexing. Therefore the back side must be turned over, which is
signaled to the "cups" output device by the cupsBackSide PPD keyword set to
"Rotated". The CUPS Raster output (second line of ASCII arts) looks like that
DuplexNoTumble and DuplexTumble is the wrong way around but on the paper it
comes out correctly.

The thing which goes wrong is that there is an extra flip in the Y-axis (compare
the second line of ASCII arts with the third line) and this is due to the CTM
not being applied in time. See the log output in comment #5.

Comment 13 Ray Johnston 2009-12-30 09:14:26 UTC
Please attach the output from the pdftops step so that we have the actual
input to Ghostscript. 
Comment 14 Till Kamppeter 2009-12-30 10:37:19 UTC
Created attachment 5832 [details]
pdftops-out.ps

Output of the pdftops filter step of the command line shown in comment #7.
Comment 15 Till Kamppeter 2009-12-30 10:38:55 UTC
Created attachment 5833 [details]
pstops-out.ps

Output of the pstops filter step of the command line in comment #7.
Comment 16 Till Kamppeter 2009-12-30 10:42:28 UTC
The Ghostscript command line called by the pstoraster CUPS filter forthe example
from comment #7 is

/usr/bin/gs -dQUIET -dDEBUG -dPARANOIDSAFER -dNOPAUSE -dBATCH -dNOMEDIAATTRS
-sDEVICE=cups -sstdout=%stderr -sOUTPUTFILE=%stdout -c  -f -_

The input file is supplied via stdin and the output file is sent to stdout.
Comment 17 Till Kamppeter 2010-01-20 11:12:38 UTC
Fix committed as SVN revision 10625.

Please test and report here.

Now the y-axis flipping is moved from the matrix to the cups_print_...()
functions, where the x-axis flipping already takes place. The matrix does not
depend on duplex parameters any more.

In addition, the recognition of the used page size was improved, also working
whe the margins of the previous page were flipped due to duplex requirements.
Comment 18 Tim Waugh 2010-01-21 09:31:44 UTC
Thanks for working on this.  It works fine for simple portrait duplexing but
fails when trying to print 2-up jobs.  I'll attach:

1. 4.pdf, my source document
2. The PPD I'm using (using "PageSetup *Duplex", but "AnySetup *Duplex" also
fails in the same way)
3. pdftops.ps, the result of filtering through the CUPS pdftops filter with the
options number-up=2 and Duplex=DuplexTumble
4. pstoraster.rast, the result of filtering pdftops.ps through pstoraster with
the same options

As you can see from the raster file, the reverse side has a great deal of
repeated data and weird lines on it, and is no good at all.
Comment 19 Tim Waugh 2010-01-21 09:32:09 UTC
Created attachment 5899 [details]
4.pdf
Comment 20 Tim Waugh 2010-01-21 09:33:14 UTC
Created attachment 5900 [details]
ppd.ppd
Comment 21 Tim Waugh 2010-01-21 09:33:34 UTC
Created attachment 5901 [details]
pdftops.ps
Comment 22 Tim Waugh 2010-01-21 09:34:28 UTC
Created attachment 5902 [details]
pstoraster.rast.bz2
Comment 23 Till Kamppeter 2010-01-21 13:09:53 UTC
It seems that rasterview is somewhat buggy. I also get unusable pages from the
second page on in rasterview. On a real printer all was OK for me. Please retry
your tests on a real printer.
Comment 24 Tim Waugh 2010-01-22 00:27:35 UTC
I tried on a real printer (HP DeskJet 990C) with HPLIP 3.9.8 before posting my
feedback here.

Could you double-check that the your real print was using the same raster data
as rasterview was given?
Comment 25 Till Kamppeter 2010-01-22 07:41:30 UTC
I can reproduce it by running all filters manually:

export PPD=/etc/cups/ppd/hp990-2.ppd
echo -en "Page 1\fPage 2\fPage 3\n" | /usr/lib/cups/filter/texttops 1 1 1 1
'cpi=5 lpi=3 Duplex=DuplexNoTumble PageSize=A4.Duplex' |
/usr/lib/cups/filter/pstops 1 1 1 1 'page-border=double Duplex=DuplexNoTumble
PageSize=A4.Duplex' | /usr/lib/cups/filter/pstoraster 1 1 1 1
'Duplex=DuplexNoTumble PageSize=A4.Duplex' > out.raster 2>log

And for testing on a real printer I run in addition

cat out.raster | /usr/lib/cups/filter/hpcups 1 1 1 1 'Duplex=DuplexNoTumble
PageSize=A4.Duplex' > out.prn 2>log
nc -w1 192.168.2.101 9100 < out.prn

with the IP being the one of the printer. The printed output is the samy broken
output as rasterview shows.
Comment 26 Till Kamppeter 2010-01-22 08:17:50 UTC
Created attachment 5907 [details]
cups/gdevcups.c

I have investigated the changes in cups/gdevcups.c. The messed up output is
caused when the recomputation of the margins is forced in cups_put_params(),
near line 2814 ("if (cups->page != lastpage) { ..."). The recomputation of the
margins works, but the memory reallocation (around line 3217) seems to mess up
the data.

I have attached a slightly modified cups/gdevcups.c trying to force the margin
recalculation another way (near line 2814, see debug ouput lines with "XXX"),
but this actually does not trigger a margin recalculation.

The margin recalculation is needed at every new page as it is possible that the
margins are flipped on the back side of the paper (= all even pages) when
duplex printing.

Ray, how do I get the margins recalculated at the right time and no mess caused
by memory reallocation?
Comment 27 Till Kamppeter 2010-01-22 09:49:03 UTC
Fixed the problem of bitmap data getting messed up. cups_put_params()
reallocated memory also if the bitmap size did not change (simply on every
margin recalculation). Now it is checked for the size actually changing before
reallocation and reallocation is skipped if the size did not change.

Committed fixed cups/gdevcups.c to SVN repository, rev 10631.
Comment 28 Till Kamppeter 2010-01-22 09:57:10 UTC
2-up comes out correctly on my HP PhotoSmart C8100 for me. I used the following
commands:

export PPD=/etc/cups/ppd/HP-Photosmart-C8100-series.ppd
echo -en "Page 1\fPage 2\fPage 3\fPage 4\n" | /usr/lib/cups/filter/texttops 1 1
1 1 'cpi=5 lpi=3 number-up=2 Duplex=DuplexTumble PageSize=A4.Duplex' |
/usr/lib/cups/filter/pstops 1 1 1 1 'page-border=double number-up=2
Duplex=DuplexTumble PageSize=A4.Duplex' | /usr/lib/cups/filter/pstoraster 1 1 1
1 'number-up=2 Duplex=DuplexTumble PageSize=A4.Duplex' > out.raster 2>log
cat out.raster | /usr/lib/cups/filter/hpcups 1 1 1 1 'number-up=2
Duplex=DuplexTumble PageSize=A4.Duplex' > out.prn 2>log
nc -w1 192.168.2.101 9100 < out.prn

Note the DuplexTumble, as 2-up makes a landscape document out of the original
portrait pages.
Comment 29 Tim Waugh 2010-02-12 07:34:03 UTC
This has introduced a regression.

When using '-r600x600' (as the turboprint driver does), the raster output is
garbled, mainly black.

Reported separately as bug #691108.
Comment 30 Till Kamppeter 2010-03-09 16:38:10 UTC
Fixed in SVN rev 10890.
Comment 31 Till Kamppeter 2010-03-09 17:07:10 UTC
The remaining problem was that the bitmap memory did not get reallocated when the color depth has changed. This also changes the bitmap size. The fix adds two static variables to track color depth changes. The test case in this bug did not reveal the problem, but the test case of bug #691108.
Comment 32 Till Kamppeter 2010-07-05 11:54:46 UTC
*** Bug 690392 has been marked as a duplicate of this bug. ***