Bug 692691 - Inserting PostScript commands from options in PPD files into "ps2write"-generated PostScript does not have any effect
Summary: Inserting PostScript commands from options in PPD files into "ps2write"-gener...
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: PS Writer (show other bugs)
Version: 9.04
Hardware: PC Linux
: P4 normal
Assignee: Ken Sharp
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-18 21:09 UTC by Till Kamppeter
Modified: 2011-11-22 08:34 UTC (History)
1 user (show)

See Also:
Customer:
Word Size: ---


Attachments
printout-lp885118.pdf (12.48 KB, application/pdf)
2011-11-18 21:09 UTC, Till Kamppeter
Details
printout-lp885118.ps (108.56 KB, text/plain)
2011-11-18 21:11 UTC, Till Kamppeter
Details
printout-lp885118-duplex-hand-edited.ps (108.70 KB, text/plain)
2011-11-18 21:13 UTC, Till Kamppeter
Details
printout-lp885118-duplex-cups-pstops.ps (109.78 KB, text/plain)
2011-11-18 21:14 UTC, Till Kamppeter
Details
ML-2850-Series.ppd (9.57 KB, text/plain)
2011-11-18 21:15 UTC, Till Kamppeter
Details
potential fix (2.20 KB, patch)
2011-11-21 16:51 UTC, Ken Sharp
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Till Kamppeter 2011-11-18 21:09:47 UTC
Created attachment 8130 [details]
printout-lp885118.pdf

In the CUPS filtering workflow in Ubuntu Oneiric I use Ghostscript with the "ps2write" output device to convert PDF into PostScript, for PostScript printers and legacy drivers which require PostScript as input.

Problem is that if the PPD file executes option settings by inserting PostScript code snippets, the common way for PostScript printer PPDs, the code seems not to get respected.

An example is the attached PostScript file. "ps2write" generated it from the attached PDF file and afterwards

[{
%%BeginFeature: *Duplex DuplexNoTumble
<</Duplex true /Tumble false>>setpagedevice
%%EndFeature
} stopped cleartomark

got inserted into the "%%BeginSetup ... %%EndSetup" section. It does not matter where in the section these lines get inserted, the problem always occurs. I tried different places.

When trying to print this file unfiltered on a PostScript printer (HP Color LaserJet CM3530 MFP in my case) the two pages come out on separate sheet and not on the front and back of one sheet.

I am using Ghostscript 9.04 on Ubuntu Oneiric (11.10). This causes especially the following Ubuntu bug:

https://bugs.launchpad.net/ubuntu/+source/cups/+bug/885118

To reproduce:

Convert the attached PDF file into PostScript via

pdf2ps printout-lp885118.pdf

Then edit the resulting PostScript file adding the lines

%%BeginSetup
[{
%%BeginFeature: *Duplex DuplexNoTumble
<</Duplex true /Tumble false>>setpagedevice
%%EndFeature
} stopped cleartomark
%%EndSetup

right after the line "%%EndProlog".

The lines are what gets inserted if the PPD contains

*OpenUI *Duplex/Double-Sided Printing: PickOne
*OrderDependency: 130 AnySetup *Duplex
*DefaultDuplex: None
*Duplex DuplexNoTumble/Long Edge (Standard): "<</Duplex true /Tumble false>>setpagedevice"
*Duplex DuplexTumble/Short Edge (Flip): "<</Duplex true /Tumble true>>setpagedevice"
*Duplex None/Off: "<</Duplex false>>setpagedevice"
*CloseUI: *Duplex

and the job is sent with the option setting "Duplex=DuplexNoTumble".

This file is supposed to come out double-sided on a PostScript printer with Duplex unit. What happens is that it comes out single-sided on two sheets.

Alternatively to editing the PostScript file you can also apply the option setting by running it through the appropriate CUPS filter:

PPD=ML-2850-Series.ppd /usr/lib/cups/filter/pstops 1 1 1 1 "Duplex=DuplexNoTumble" printout-lp885118.ps > printout-lp885118-duplex.ps
Comment 1 Till Kamppeter 2011-11-18 21:11:29 UTC
Created attachment 8131 [details]
printout-lp885118.ps

Result of PDF file being converted with "pdf2ps"
Comment 2 Till Kamppeter 2011-11-18 21:13:02 UTC
Created attachment 8132 [details]
printout-lp885118-duplex-hand-edited.ps

PostScript file with lines for duplex printing added by hand
Comment 3 Till Kamppeter 2011-11-18 21:14:31 UTC
Created attachment 8133 [details]
printout-lp885118-duplex-cups-pstops.ps

PostScript file with the PPD option code, including Duplex, added by the "pstops" CUPS filter
Comment 4 Till Kamppeter 2011-11-18 21:15:57 UTC
Created attachment 8134 [details]
ML-2850-Series.ppd

PPD file used for the sample "pstops" command line to insert option code
Comment 5 Till Kamppeter 2011-11-18 21:17:44 UTC
This is also a rather important bug which I would like to fix with a patch release of Ghostscript for Ubuntu Oneiric, as it makes option settings not being respected for all PostScript printers.
Comment 6 Alex Cherepanov 2011-11-19 03:16:12 UTC
Do these options work at all?
For instance, how what does the following program print?

%!
<</Duplex true /Tumble false>>setpagedevice
0 0 100 100 rectfill
showpage
100 100 100 100 rectfill
showpage

How about this one?

%!
<</Duplex true /Tumble false>>setpagedevice
0 0 100 100 rectfill
showpage
<</Duplex true /Tumble false>>setpagedevice
100 100 100 100 rectfill
showpage
Comment 7 Till Kamppeter 2011-11-19 09:05:33 UTC
Alex, the first of your simple programs, and that is the equivalent of the command insertion in "%%BeginSetup ... %%EndSetup" in this bug report, prints perfectly duplex for me. The second, which is the equivalent of command insertion in "%%BeginPageSetup ... %%EndPageSetup" for each page, does not work. It seems that every new execution of the command resets the duplex and starts a new sheet.

So principally command insertion works, but not for the particular file attached to this bug. The PDF file is generated by Cairo and the problem is generally found when converting Cairo-generated PDF to PostScript using GS with the "ps2write" output device. It seems that the "ps2write"-generated PostScript somehow removes/overwrites the duplex setting.
Comment 8 Ken Sharp 2011-11-19 09:18:01 UTC
(In reply to comment #7)

> So principally command insertion works, but not for the particular file
> attached to this bug. The PDF file is generated by Cairo and the problem is
> generally found when converting Cairo-generated PDF to PostScript using GS with
> the "ps2write" output device. It seems that the "ps2write"-generated PostScript
> somehow removes/overwrites the duplex setting.

This is caused by the fact that the ps2write output executes setpagedevice on every page, in order to set media size. This is an absolute requirement, because each page may be a different size. However, each invocation of setpagedevice resets /Duplex, it flushes any pending pages and starts the duplexing over.

I don't think this is anything to do with the PDF source, its simply an artefact of the way the code works.

If we don't do the setpagedevice, and the media size changes, then the output will be incorrect in a different way. So this is going to need some thinking about.
Comment 9 Till Kamppeter 2011-11-19 09:28:40 UTC
Ken, can we let "ps2write" execute setpagedevice only if the page size actually changes? In general the PostScript needs to be compatible with the manipulations done when using PPD files.
Comment 10 Ken Sharp 2011-11-19 09:41:19 UTC
(In reply to comment #9)
> Ken, can we let "ps2write" execute setpagedevice only if the page size actually
> changes? 

That's what I'm considering, but I don't know yet what sort of changes will be required for that. I doubt we store the 'last page size' anywhere at the moment. I haven't looked into this yet as I'm still working on your other problem.


> In general the PostScript needs to be compatible with the
> manipulations done when using PPD files.

Duplex is a 'special case', normally executing setpagedevice only changes the keys which are passed in as an argument, and so have no effect on anything else. 

However specifically because setpagedevice can cause a media switch, duplexing is handled differently, and any duplexing in train is aborted, just in case the page size (or other media parameters) did change.

To extend Alex's test, I very strongly suspect that this:

%!
<</Duplex true /Tumble false>>setpagedevice
0 0 100 100 rectfill
showpage
<</Duplex true /Tumble false>>setpagedevice
100 100 100 100 rectfill
showpage
100 100 100 100 rectfill
showpage

Would give you two pages of output, the second one duplexed. This is because we don't emit a setpagedevice. Don't bother to try that, I'm pretty confident of the result.
Comment 11 Alex Cherepanov 2011-11-19 15:00:32 UTC
In fact, we do store the page device attributes.
They are stored by the page device itself.
The following procedure checks whether setpagedevice has any effect and
drops ineffective ones. deep_eg is not yet implemented. It should recursively
compare objects for equality.

/setpagedevice {
  currentpagedevice //false  % <<>> bool <<pd>>
  2 index {                  % <<>> bool <<pd>> /key val
     2 index 2 index known {
       2 index 2 index get deep_eq {
         pop pop
       } {
         pop pop not exit
       } ifelse
       % Unknown keys propagate to setpagedevice
       pop pop pop not exit
     } ifelse
  } forall {
    setpagedevice
  } {
    pop
  } ifelse
} bind def
Comment 12 Ken Sharp 2011-11-21 11:37:12 UTC
(In reply to comment #11)
> In fact, we do store the page device attributes.
> They are stored by the page device itself.

I meant in the pdfwrite/ps2write C code. However because pdfwrite and ps2write share so much code we can't at the moment simply omit the MediaBox, as this is a required key for PDF files.


> The following procedure checks whether setpagedevice has any effect and
> drops ineffective ones. deep_eg is not yet implemented. It should recursively
> compare objects for equality.

Because of the various additional switches (RotatePages, FitPages and CenterPages) this is not as simple as I would like. Simply testing the requested and current PageSize isn't enough.

Looks like I might be able to modify the SetPageSize procedure though.
Comment 13 Ken Sharp 2011-11-21 16:51:21 UTC
Created attachment 8140 [details]
potential fix

Till, can you try this patch please ? I think it should work with Duplexing, provided the printer supports the requested page size.

There is a little 'wiggle room', as it converts to integer and drops fractional differences.

There are no differences from our regression suite (didn't expect any) So if this works for you I'll commit it.
Comment 14 Till Kamppeter 2011-11-21 19:07:14 UTC
I have checked the patch, duplex command insertion works for me now. Thank you very much.
Comment 15 Ken Sharp 2011-11-21 19:31:46 UTC
(In reply to comment #14)
> I have checked the patch, duplex command insertion works for me now. Thank you
> very much.

Thanks Till, I will commit the change and close the bug tomorrow.
Comment 16 Ken Sharp 2011-11-22 08:34:11 UTC
Fixed in commit: 5cce07051c3616c250a960ae48759a1c1af2fb47