Till Kamppeter [Sat, 27 Aug 2022 20:53:45 +0000 (22:53 +0200)]
libppd: In ppdFilterLoadPPD() correct check for final output type
To determine whether the PDF filter (usually cfFilterPDFToPDF()) has
to do the page logging for CUPS ("PAGE: XX YY" log messages) or the
driver filter, we check the final output type (FINAL_CONTENT_TYPE
environment cariable from CUPS) to see whether a driver filter is
involved which should log the pages by itself.
The code to compare the final output type with the "*cupsFilter(2):
..." lines in the PPD file was broken, which is fixed with this
commit.
Till Kamppeter [Thu, 25 Aug 2022 21:32:36 +0000 (23:32 +0200)]
libfontembed, libcupsfilters, libppd: assert() only if DEBUG is set
A failing assert() makes the whole program crash, a daemon (Printer
Application) crashes when a filter fails on a damaged input file, a
distro-packaged program sends automatic bug reports to the distro,
... Sometimes assert() is really overkill.
But assert() can be useful for debugging, as one gets easily aware
when some values are wrong somewhere (this probably made the
contributors yo cups-filters insert that many assert() calls).
At least, assert() should only be used for debugging, not in
production code.
Therefore we have replaced all assert() calls by the DEBUG_assert()
macro and the macro is set to assert() when the code is compiled with
the DEBUG macro set and to nothing otherwise. For setting this macro
and other debugging macros there are */debug-internal.h files for all
the 3 libraries now.
Also defined functions for DEBUG_printf and DEBUG_puts in
libcupsfilters (cupsfilters/debug.c).
On a compilation with DEBUG set ("CXXFLAGS=-DDEBUG CFLAGS=-DDEBUG
./configure ...") found some build failures and fixed them.
Till Kamppeter [Sat, 20 Aug 2022 20:38:08 +0000 (22:38 +0200)]
libppd: Added NULL checks when "libppd" extension not present
The functions ppdFilterExternalCUPS(), ppdFilterEmitJCL(), and
ppdFilterUniversal() get the PPD file via the "libppd" extension for
the filter data. There was no NULL check when the extension was not
present, without extension there was simply a crash, a hang, or other
unexpected behavior.
This commit adds NULL checks so that if the extension is missing, the
functions simply do what they can do without PPD file, but do not
cause a crash.
Till Kamppeter [Sat, 20 Aug 2022 15:29:37 +0000 (17:29 +0200)]
libppd: Make driverless printing PPDs from CUPS work correctly
If one sets up a driverless printer with CUPS, either manually by the
"-m everywhere" option for "lpadmin" (or equivalent functionality in
the web interface) or automatically when CUPS creates a temporary
queue, the generated PPD file did not work correctly with current
cups-filters.
CUPS' auto-generated PPD files to not contain "*cupsUrfSupported: ..."
or "*cupsPwgRaster..." lines, but instead, add pseudo-PostScript code
(as in PPDs for CUPS Raster drivers) to the "ColorModel" and
"cupsPrintQuality" options.
Therefore the ppdLoadAttributes() function should not create artifical
"urf-supported" or "pwg-raster-..." printer IPP attributes and the
ppdFilterLoadPPD() should instead create a sample Raster header as it
already does for PPDs for CUPS Raster drivers. This way color space,
depth, and resolution get supplied to the filters via the header.
Carlos Nihelton [Tue, 16 Aug 2022 14:47:52 +0000 (11:47 -0300)]
Makefile.am: Move the libppd declarations after cups-filters (#477)
When doing "sudo make install", the re-linking breaks because libppd depends on libcupsfilters (and not vice-versa, as before), not yet installed. Reordering the declarations in the Makefile.am seems to fix the bahavior.
To reproduce the issue try on a minimal Ubuntu environment, such as WSL or cloud images running on LXD or docker:
```
sudo apt install autotools-dev autoconf automake autopoint libavahi-client-dev libavahi-glib-dev libcurl4-gnutls-dev libglib2.0-dev libgnutls28-dev libjpeg-dev libpam0g-dev libpng-dev libusb-1.0-0-dev zlib1g-dev libcups2-dev libcupsimage2-dev libssl-dev libtool libqpdf-dev poppler-utils libfontconfig1-dev libpoppler-cpp-dev libtiff5-dev libdbus-1-dev libexif-dev librsvg2-bin sharutils liblcms2-dev ghostscript pkg-config g++ --no-install-recommends
git clone https://github.com/OpenPrinting/cups-filters
cd cups-filters
./autogen.sh
./configure --prefix=/usr --disable-ldap --disable-foomatic --disable-braille --disable-mutool
make
sudo make install
```
Only the install target should fail to relink the libppd against libcupsfilters due the latter not yet being installed. With this patch the order is corrected which should solve the problem.
Till Kamppeter [Thu, 11 Aug 2022 12:51:35 +0000 (14:51 +0200)]
libcupsfilters, libppd: Separated PPD file support from libcupsfilters
This commit reverses the dependencies of the libcupsfilters and libppd
libraries. Instead of libcupsfilters depending on libppd no libppd
depends on libcupsfilters.
This is important for removing PPD file support from OS distributions
and so allow discontinuing the maintenance of PPD-file-supporting code
in the future. In a later step libppd and the filter executables for
CUPS will get separated from the cups-filters project/repository into
their own projects/repositories.
CUPS will not use PPD files any more from version 3.0.0 on, but go
all-IPP instead. CUPS iteself will only support driverless IPP
printers (IPP Everywhere, AirPrint, Mopria) and no classic printer
drivers which consist of PPD files and filter/backend executables any
more. For printers which still need drivers Printer Applications ar
the new driver format. A Printer Application is a software emulation
of a driverless IPP printer which on the other end talks with the
physical printer.
These modifications introduce several changes on the APIs of
libcupsfilters and libppd. Software depending on these libraries (like
pappl-retrofit) needs to get adapted. All filter executables,
backends, and utilities included in cups-filters got already adapted
with this commit.
The following changes have been done:
- cf_filter_data_t gets support for an array of named extension data
structures and does not support field for the PPD name and data any
more. libppd defines an extension named "libppd" to hold PPD name
and data. Filter functions (of libppd) which explicitly use/support
PPD files access the PPD file through this extension, others simply
ignore the extension if present.
- All filter functions in libcupsfilters drop PPD support completely.
They get printer-specific data only by the printer IPP attributes
and by option settings in the option list of the cf_filter_data_t
structure. The full functionality of each filter function is
conserved.
- Filter functions which process or generate raster data can also get
the parameters for the raster data as a CUPS Raster sample header.
- To continue offering PPD-supporting CUPS filters libppd provides the
ppdLoadAttributes() to convert a PPD file into printer IPP
attributes, the ppdFilterLoadPPD() to convert further PPD attributes
which have no IPP equivalent into option settings and a CUPS Raster
sample header, and the wrapper function ppdFilterCUPSWrapper()
called by the CUPS filter executable, making the mentioned two
functions be called before the filter function itself (in most cases
from libcupsfilters) gets called.
- Filter functions which need PPD file support, especially those which
output PostScript, and also the former cfFilterExternalCUPS() (now
ppdFilterExternalCUPS()) filter function have moved to libppd.
- The support for PostScript output has also been removed. Nowadays it
only serves for printing on PostScript printers (where one usually
also has a PPD file), as document exchange format PostScript got
fully replaced by PDF.
- If PPD file support cannot be added to a filter function by only
extracting the printer's properties from the PPD via printer IPP
attributes and option settings, a wrapper filter function is created
in libppd. This we do for cfFilterUniversal() (to correct the output
format according to "*cupsFilters2: ..." lines in the PPD) and for
cfFilterPDFToPDF()/cfFilterImageToPDF() (to add JCL/PJL commands
from the PPD file for "classic" PDF printers).
- In raster driver support code moved the functions to read parameters
from the PPD file to libppd.
- Moved the PPD file generator used by cups-browsed and by the
driverless utility to libppd.
- Moved the handling of common parameters, like page size, duplex,
backside orientation, color spaces and depths, Raster headers, ...,
by the filter functions into separate functions to not duplicate the
code in each filter function.
- Improved the page size handling, especially accepting all types of
parameter supply (options, job attributes, printer attributes,
Raster headers, handling borderless printing and overspray,
specification of size by dimensions or by name, custom size,
margins, recognition whether user explicitly requested a page size
(if not, use input page size if possible) ...
- Made functions for handling human-readable/translation strings (of
the PPD generator) API functions of libcupsfilters.
Till Kamppeter [Fri, 20 May 2022 14:05:23 +0000 (16:05 +0200)]
libcupsfilters: In the env variables for cfFilterExternalCUPS() use CUPS 2.5.99
Use CUPS version 2.5.99 for the "SOFTWARE" environment variable when
calling CUPS filters or backends via the cfFilterExternalCUPS() filter
function. This is the last CUPS version which supports PPD files and
classic printer drivers.
Till Kamppeter [Fri, 20 May 2022 09:38:40 +0000 (11:38 +0200)]
libcupsfilters: Correct lengths of log message prefixes
In the cfFilterExternalCUPS() filter function we catch the stderr
(log) output of the called CUPS filter and convert it into log
function calls with correct log levels. here we need to compare
exactly the prefix, not more and not less, to safely identify the log
level of each line.
Sachin Thakan [Sat, 14 May 2022 07:12:36 +0000 (12:42 +0530)]
libcupsfilters: Read image resolution from EXIF data of JPEG, PNG, TIFF
If images are printed with "print-scaling=none" one wants to have their original size. To get an original size in absolute dimensions (inches, cm) one needs the pixel count and resolution (dpi, ppi). The resolution is supposed to be in the image's own header but in practice it is often not there.
Images from cameras, and also from some scanners, have additional metadata, the so-called EXIF data which usually contains a resolution. So we read out this with the help of libexif.
In Linux distributions there we usually have libexif and so it is no big effort to let libcupsfilters use it. But it is not required, so for low-resource systems libcupsfilters can be built without (and then not having this feature).
Till Kamppeter [Tue, 12 Apr 2022 08:37:40 +0000 (10:37 +0200)]
libcupsfilters: For ghostscript() require GS 9.56.0
Removed the conditionals for the presence or absemse of the
"appleraster" output device in Ghostscript (version 9.56.0 and
newer). We already require that the "pclm" device is there (GS version
9.55.0 and newer). So we remove the conditionals now and simply
require Ghostscript 9.56.0.
Till Kamppeter [Tue, 12 Apr 2022 08:00:28 +0000 (10:00 +0200)]
libcupsfilters: Added gray PCLm support to ghostscript()
PCLm does not only support 24-bit sRGB bur also 8-bit sGray. All PCLm
printers, regardless of whether they are color or monochrome accept
these two color spaces. Monochrome printers have to convert color into
gray if needed.
Ghhostscript has a grayscale PCLm output device, "pclm8" since version
9.56.0. We now make use of it if the job is monochrome. This also
allows us to supply the cortrecr sGray ICC profile instead of the sRGB
one.
Till Kamppeter [Tue, 12 Apr 2022 07:44:31 +0000 (09:44 +0200)]
libcupsfilters: Let ghostscript() do raster PDF in gray on bw jobs
The ghostscript() filter function did PDF Image (raster PDF) output in
color if the printer is a color printer, in gray only if the printer
is monochrome. Monochrome jobs were therefore printed in color on
color printers. This commit makes grayscale output also used if the
job is monochrome.
Till Kamppeter [Mon, 11 Apr 2022 18:18:15 +0000 (20:18 +0200)]
libcupsfilters: Let ghostscript() output Apple Raster directly
From version 9.56.0 on Ghostscript support direct Apple Raster (URF)
output.
Therefore now we check via ./configure whether the installed
Ghostscript has an "appleraster" output device and if so, we let the
ghostscript() filter function call Ghostscript using this output
device to directly output Apple Raster, so that we do not need to call
the rastertopwg() filter function any more.
In this case an extra MIME conversion rule taking into account the
Apple Raster output from the gstoraster CUPS filter gets installed and
also the universal() filter function gets built to not call the
rastertopwg() filter function after ghostscript() when Apple Raster
output is requested.
Till Kamppeter [Mon, 11 Apr 2022 14:38:55 +0000 (16:38 +0200)]
libfontembed: Renamed files to use "-", not "_", ¨-private.h" for non-API
Renamed all source files so that they do not use "_" but use "-"
instead.
Renamed header files which are not containing public API to
"*-private.h".
Let "make install" also install fontembed/embed-pdf.h as it is
included by the already installed fontembed/embed.h. This is also a
sign that no one has used libfontembed separate from cups-filters.
Till Kamppeter [Mon, 11 Apr 2022 12:12:55 +0000 (14:12 +0200)]
libcupsfilters: Renamed all C++ source files to *.cxx
This commit makes all our C++ source files having the same extension:
".cxx", once to reduce confusion and also as ".cxx" is commonly used
under Linux, macOS, Unix, and Windows, according to DEVELOPING.md
in the CUPS source code.
Till Kamppeter [Mon, 11 Apr 2022 11:25:38 +0000 (13:25 +0200)]
libcupsfilters: Do actual commit for the previous commit message
Normally, GIT does not accept the command "git commit" without
specifying files or "-a" for all modified files. Strangely enough, it
accepts it when files got deleted and then it only commits the
deletions. So the previous commit (f89c3136cb8) only contains the
deletions of the cupsfilters/image-sgi.h and
cupsfilters/image-sgilib.c and not the actual changes.
Till Kamppeter [Mon, 11 Apr 2022 11:12:34 +0000 (13:12 +0200)]
libcupsfilters: Renamed internal functions and data types
Renamed the internal functions and data types according to the rules
of the DEVELOPING.md file of the CUPS source code, to extend this
coding style to cups-filters.
1. Renamed source-file-local functions to all-lowercase with "_"
separators, also declared all these functions static (= valid only
for the same source file) if not yet done so. These functions do
not appear in *.h files.
2. Renamed library-local (non-API, but used in several files of the
library) to camel-case starting with "_cf...".
3. Renamed data types to all-lowercase with "_" separators, ending
with "..._e" for enumerations, "..._s" for structs, and "..._t" for
type definitions.
Also moved the content of the files cupsfilters/image-sgi.h and
cupsfilters/image-sgilib.c into cupsfilters/image-sgi.c and removed
unused code for outputting SGI images, and re-arranged the order of
the functions in the cupsfilters/texttopdf.c source file (to not have
the main function in the middle of the file).
Till Kamppeter [Sun, 10 Apr 2022 08:52:58 +0000 (10:52 +0200)]
libcupsfilters: Silenced warnings about deprecated uint16/uint32
The function to read TIFF image files via libtiff in
cupsfilters/image-tiff.c uses the deprecated types uint16 and
uint32. The replacements for these types are uint16_t and uint32_t.
This commit replaces the types and so silences the compiler warnings.
Till Kamppeter [Fri, 8 Apr 2022 23:32:23 +0000 (01:32 +0200)]
libcupsfilters: Joined cfFilterImageToPS() and cfFilterPSToPS() in one file
cfFilterImageToPS() and cfFilterPSToPS() have some common functions
which were implemented in both the imagetops.c and pstops.c
files. Joined the files into one imagetops-pstops.c file letting the
two filter functions share these functions. Also did some code
clean-up for more consistency.
Till Kamppeter [Fri, 8 Apr 2022 19:34:19 +0000 (21:34 +0200)]
Updated NEWS for new API functions cfFilterLoadPPD()/cfFilterFreePPD()
Added new API function cfFilterLoadPPD() and cfFilterFreePPD() for
easy setup of filter function (chain) calls. Call cfFilterLoadPPD()
when setting up the filter data structure before calling the filter
functions and call cfFilterFreePPD() when done.
Till Kamppeter [Fri, 8 Apr 2022 19:23:26 +0000 (21:23 +0200)]
libcupsfilters: Let filter functions not load or modify PPD file data
Let the filter functions not load the PPD file data and not mark
options in the PPD file data to make them better usable with Printer
Applications and to avoid race conditions in filter chains.
To keep the behavior of CUPS filters, changed the
cfFilterCUPSWrapper() function and the implicitclass CUPS backend
appropriately.
Also added support for direct Apple Raster output to the
cfFilterPDFToRaster() (Poppler) filter function and fixed a bug in the
output format selection in the cfFilterRasterToPWG() filter function.
The files cupsfilters/kmdevices.h and cupsfilters/kmdevices.cpp form
an interface for Kolor Manager, a KDE system settings component for
color management with Oyranos.
Kolor Manager is unmaintained for several years, same for Oyranos. The
kmdevices.* are not included in the build of libcupsfilters, only
shipped for optional use (requires uncommenting a line in
colormanager.c) and no one complained about their non-inclusion in the
build. They even contain a typo which would prevent them from
building. So one can assume that no one cares about them.
Therefore they get removed now, before the cups-filters 2.x release.
Till Kamppeter [Tue, 5 Apr 2022 15:38:43 +0000 (17:38 +0200)]
libcupsfilters: In pdftops() identify old LaserJets more precisely
Old HP LaserJet printers have a firmware bug which makes them not
working with Ghostscript's PostScript output, so in pdftops() we
switch to Poppler for them.
We consider an old LaserJet every "HP LaserJet XXXXY" printer with
XXXX being a number (not preceded by a letter), typically 1-4 digits
and Y being 0-2 letters, no separated from the numbers by a space.
Unfortunately, we checked only whether after "LaserJet" comes a number
and not the rest. This made also modern printers with names like "HP
LaserJet 500 color M551" considered old and these modern printers have
another PostScript interpreter bug which makes them not print some
files with Poppler, so they need Ghostscript's PostScript output.
Therefore we refine the check for the old-LaserJet quirk to see
whether after the number are extra words and if so, this is again a
modern printer and we do not switch to Poppler.
Till Kamppeter [Tue, 5 Apr 2022 15:01:02 +0000 (17:01 +0200)]
libcupsfilters: Updated comment about human-readable strings in PPD Generator
There is a longer comment about how to obtain and handle
human-readable strings and translations in the PPD file generator for
driverless printing, right before the source code of the PPD file
generator.
This comment tells that there are no human-readable strings for the
manual color space and depth choices in the ColorModel option wheras
IPP has only simple bi-level/grayscale/color choices and the exact
color space and depth the filters are supposed to select automatically
according to job and printer.
This part of the comment got already obsolete a few days later when I
made the filters auto-selecting color space and depth via the newly
introduced cupsRasterPrepareHeader() and cupsRasterSetColorSpace()
functions.
Now I discovered this forgotten comment and removed the obsolete part.
Till Kamppeter [Mon, 4 Apr 2022 17:43:18 +0000 (19:43 +0200)]
Build system: Bumped cups-filters version to 2.0b1
Bumped the version number to teh one of our first planned release of
2.x, 2.0b1.
Also changed the version number handling in configure.ac, to allow
both X.Y.Z version numbers and also X.Yb1 or X.Yrc1 version numbers.
Taken this part from PAPPL's configure.ac.
Till Kamppeter [Mon, 4 Apr 2022 17:40:04 +0000 (19:40 +0200)]
libcupsfilters: Bumped soname to 2
The libcupsfilters libraries of cups-filters 2.x and 1.x do not have
compatible APIs any more, not only additions of filter functions but
also changes of function's interfaces for new features like log
functions.
Till Kamppeter [Mon, 4 Apr 2022 13:39:43 +0000 (15:39 +0200)]
libcupsfilters, mupdftoraster, mupdftopwg: Renamed filter function
Renamed the filter function mupdftoraster() and the corresponding CUPS
filter to mupdftopwg(). This is because the "mutool" utility of MuPDF
only supports PWG Raster output, no CUPS Raster and no Apple Raster.
It also does not make the impression that this will change anytime
soon, as this is already this way for many years and there is also no
feature request posted asking for adding the other formats.
This way it is easily communicated that the filter function has to be
followed by the pwgtoraster() filter function to get CUPS Raster.
Note that the "outformat" parameter (the CUPS filter feeds in the
value of the FINAL_CONTENT_TYPE environment variable here) does not
change the actual output format (PWG Raster) of mupdftopwg(), it is
only to tell the final output format of the print job, so that
mupdftopwg() can grab color space, color depth, and resolution info
for this final format from the PPD file (or from the printer IPP
attributes) and call "mutool" according to this format.
Till Kamppeter [Sun, 3 Apr 2022 22:13:00 +0000 (00:13 +0200)]
libcupsfilters: Make pdftopdf() also work correctly with auro-rotating off
If one turns off auto-rotating in the pdftopdf() filter function
(option "nopdfAutoRotate") the orientation of the input page on the
output sheet is manually controlled by the options
"orientation-requested" and "landscape".
The cropping of the pages (with "print-scaling=none") did not work
correctly with auto-rotating turned off. This commit fixes this.
Till Kamppeter [Sun, 3 Apr 2022 17:28:17 +0000 (19:28 +0200)]
libcupsfilters: Make pdftopdf() correctly working with "landscape" option
The "landscape" option rotates the input pages by 90 degrees, in the
direction given by the "*LandscapeOrientation" in the PPD file.
The "orientation-requested" option/IPP attribute rotates the page
according to its value: 3: No rotation; 4: 90 degrees anticlockwise;
5: 90 dgrees clockwise; 6: 180 degrees (upside-down).
After that, at least when not suppressed via "nopdfAutoRotate"
("pdfAutoRotate=false") option, auto-rotation kicks in, rotating the
page by 90 degrees (direction according to "*LandscapeOrientation" in
the PPD file) if the orientations of the input page and the output
page mis-match.
If the output format is not supplied as parameter, ghostscript()
defaults to CUPS Raster now, as the ghostscript CUPS filter already
does.
rastertopwg does not support CUPS Raster output, so we changed the
CUPS filter rastertopwg to default to PWG Raster instead.
The rastertopwg() filter function errors out when NULL is supplied as
parameter. We let it also error out now if an unsupported output
format is supplied.
Till Kamppeter [Mon, 28 Mar 2022 18:00:59 +0000 (20:00 +0200)]
libcupsfilters: rastertopclm() fails if no default resolution given
Some PCLm printers, especially the ones which support only one
resolution in PCLm ("pclm-source-resolution-supported" IPP attribute)
do not have the "pclm-source-resolution-default" IPP attribute. This
broke rastertopclm().
This is fixed now for both direct use of the printer IPP attributes or
use via an auto-generated PPD file. The missing default resolution is
simply filles with the first item of
"pclm-source-resolution-supported" then. If this item is also missing,
we error out on this printer/PPD file.
Till Kamppeter [Mon, 28 Mar 2022 11:04:07 +0000 (13:04 +0200)]
libcupsfilters: Allow mupdftoraster() be used for all raster formats
The mupdftoraster() filter function only produces PWG Raster, due to
the fact that mutool of MuPDF produces PWG Raster but not Apple
Raster, CUPS Raster, or PCLm.
To obtain the other formats one needs post-filtering with pwgtoraster
and rastertopclm. To make this working in the best possible way and to
make it working at all with any PPD file (also those which do not have
information for generating the inbetween PWG Raster format) we have
prepared mupdftoraster appropriately.
Changes done:
- Get final output format via parameters
- Call cupsRasterPrepareHeader() with PWG Raster as header format and
the final output format as final format
- If the final format is not PWG Raster we need post-filtering. In
this case let mutool only generate output with a maximum of 3 color
channels (no CMYK) as the post filters pwgtoraster and rastertopclm
only support 1- or 3-color-channel input.
- Add explicit support for the RGBW color space (#17, used by HPLIP's
hpcups driver).
- On an unknown final output color space default to color instead of
mono output. A post filter can turn color into monochrome but not
vice-versa.
- Let the CUPS filter wrapper read the final output format from the
FINAL_CONTENT_TYPE environment variable. Default to CUPS Raster on
an unknown format, as those formats typically come from CUPS Raster
("rasterto...") drivers.
- Do not pass in the full list of environment variables any more. We
do not manipulate these. Instead we call mutool with execvp() to
simply use the caller's environment instead of execvpe() with a
supplied environment.
- Update the MIME rules: Remove rule telling that mupdftoraster
outputs CUPS Raster, add rules for pwgtoraster, and also rules to
reflect that rastertopclm also accepts Apple Raster or PWG Raster as
input.
Till Kamppeter [Sun, 27 Mar 2022 15:04:29 +0000 (17:04 +0200)]
libcupsfilters: In pdftopdf() fix N-up printing with long-edge-first
If the printer takes the paper long-edge-first and the number-up
option for printing multiple pages per sheet is used, the grid for the
shrinked pages onm the output sheet is set wrongly (number of lines
and number of columns swapped). This commit fixes the this bug.
Till Kamppeter [Sun, 27 Mar 2022 14:51:19 +0000 (16:51 +0200)]
libcupsfilters: In pdftopdf() fix cropping with long-edge-first
If the printer takes the paper long-edge-first (lasers and inkjets
usually take it short-edge first, but roll-fed large-formats or label
printers also take long-edge-first) the cropping of the page image for
crop-to-fit (print-scaling=none) and fill (print-scaling=fill) by the
pdftopdf() filter function did not work correctly. This is fixed now.
Till Kamppeter [Sat, 26 Mar 2022 00:49:20 +0000 (01:49 +0100)]
libcupsfilters: Added PWG/Apple Raster support to pwgtoraster()
The pwgtoraster() filter function is now able to also output PWG
Raster and Apple Raster, for direct conversion between PWG and Apple
Raster without inbetween CUPS Raster step. Also CUPS Raster based on
PCLm info in the PPD or in the printer IPP attributes for feeding into
rastertopclm is supported.
With this we can for example use MuPDF via the mupdftoraster() filter
function which has only PWG Raster output for all driverless printing
formats (Apple Raster, PWG Raster, PCLm) and also for classic CUPS
Raster drivers (CUPS Raster format).
Selection of the ourput format is done via the parameters, like with
the other filter functions.
We also allow the overspray/rounding correction kick in on jobs where
the output page size is not explicitly requested, as rounding errors
can always happen. Page size dimensions in the PPD can easily deviate
from the exact dimensions of the input pages.
Till Kamppeter [Fri, 25 Mar 2022 10:38:11 +0000 (11:38 +0100)]
libcupsfilters: In pwgtoraster() determine input format by ImagingBoundingBox
pwgtoraster() converts PWG or Apple Raster input to CUPS Raster output.
Before, it identified whether the input format is a supported one by
the "PwgRaster" in the MediaClass field of the CUPS Raster header data
structure, which is the case if the input file header contains this
"magic string" or if libcups creates a CUPS Raster Header for an Apple
Raster file it reads. Unfortunately, there are sources of PWG Raster
files omitting to put "PwgRaster" into the MediaClass field (like
MuPDF used in the mupdftoraster() filter function) and so
pwgtoraster() rejects the otherwise correct input as unsupported CUPS
Raster. So we need a new form of identifying PWG Raster.
In contrary to the CUPS Raster format the two supported formats have
no margin definition and contain a bitmap for the whole page including
the unprintable margins. Therefore the supported formats have se the
ImagingBoundingBox field to all-zero, which is illegal in CUPS Raster
as it spans a zero-size printing area. We now make use of this to
identify the input format and simply accept files with all-zero
ImagingBoundingBox and reject others, safely telling apart CUPS Raster
from PWG/Apple Raster.
Now mupdftoraster() and so MuPDF can be used with CUPS Raster drivers.
Till Kamppeter [Thu, 24 Mar 2022 22:47:27 +0000 (23:47 +0100)]
libcupsfilters: In the PPD generator removed check for presence of gstopxl
Generally gstopxl is part of cups-filters as cups-browsed is and so
they usually get installed together. So we remove the check for the
presence of the filter. The check will also not work in many cases,
especially when the program using the PPD generator is not called by
CUPS, for example if the PPD generator is called by cups-browsed (and
not by the driverless utility used by CUPS).
For cups-filters installations without Ghostscript, gstopxl is not
built/installed, for this case we will later add conditionals in the
PPD generator to not build the support for PCL-XL via gstopxl.
Till Kamppeter [Thu, 24 Mar 2022 16:16:15 +0000 (17:16 +0100)]
libcupsfilters: In universal() supply texttopdf parameters in parameters
When the universal() filter function calls the texttopdf() filter
function it grabs the parameters for texttopdf() from the environment
variables which CUPS usually sets. There is no way to supply these
parameters without environment variables (for non-CUPS applications).
With this commit the parameters data structure of universal() is
extended to also contain the parameter data structure of texttopdf()
so that one can supply these parameters on the universal() filter
function call. The environment variables are no checked by the CUPS
wrapper which is used to call universal() as a CUPS filter.
Till Kamppeter [Wed, 23 Mar 2022 19:53:41 +0000 (20:53 +0100)]
libcupsfilters: Added Apple Raster output to pclmtoraster()
The pclmtoraster() filter function outputs CUPS Raster and PWG Raster
using the Raster output functions of libcups. So it is trivial to add
Apple Raster using the appropriate mode in cupsRasterOpen(). We are
doing this now and by a parameter we can select the output format, as
with most other filter functions.
Before, the switching between CUPS Raster and PWG Raster was only
possible via the FINAL_CONTENT_TYPE environment variable which works
for a CUPS filter but not generally for a filter function.
Also switched to use cupsRasterPrepareHeader() instead of
ppdRasterInterpretPPD()/cupsRasterParseIPPOptions().
Till Kamppeter [Tue, 22 Mar 2022 21:16:32 +0000 (22:16 +0100)]
libcupsfilters: Corrected color management API
To the color management functions of cupsfilters/colormanager.c got a
pointer to a filter data record (filter_data_t) added to their
parameter lists to convey a log function to them, so that they log
into the caller's log function and not to stderr any more.
It was not taken into account that the data structure also contains
the print queue name and so the print queue name was continued to be
explicitly supplied as the second parameter.
This is not needed any more and so we have changed the parameter lists
of the functions, not explicitly taking the print queue name any more
and the functions use the print queue name from the data structure.
Also fixed some bugs:
- Do not use getenv("PRINTER") in filter functions. The print queue
name is part of the filter_data_t data structure.
- In foomatic-rip make sure that the correct print queue name gets
added to the data structure before the first call of a color
management function happens. Also make sure that color management
also works in spooler-less mode.
Till Kamppeter [Tue, 22 Mar 2022 12:59:34 +0000 (13:59 +0100)]
libcupsfilters: Let raster driver functions use log function
libcupsfilters contains a lot of functions for raster drivers, to
convert raster formats, handle colors with lookup tables (LUTs),
... See cupsfilters/driver.h for the API. These functions, originally
designed for the use in CUPS filters, had logged directly to
stderr. Now to allow easy use of them in filter functions we have
changed all logging to go into a provided filter function and
appropriately added parameters to the call schemes of the functions
which need it to supply the log function.
Also updated the printer drivers rastertopclx and rastertoescpx and
also the test programs testcmyk and testdither to use the changed API.
Till Kamppeter [Mon, 21 Mar 2022 20:00:24 +0000 (21:00 +0100)]
cupsfilters: Make bannertopdf() work without environment variables
bannertopdf() uses CUPS' environment variables to determine the
template file directory, and the printer description (info) and
location entries. To make it easier to use this filter function also
without CUPS, the directory is now supplied as a string pointed at by
the parameters pointer and the printer description and location fields
via the "printer-info" and "printer-location" options or IPP
attributes.
In addition fixed several bugs:
- Free options list correctly
- Free templates file field in banner data structure correctly
- Handle a missing template PDF file correctly, without crash
Till Kamppeter [Sun, 20 Mar 2022 23:09:14 +0000 (00:09 +0100)]
libcupsfilters: Fixed logging in the bannertopdf() filter function
The bannertopdf() filter function uses the functions in cupsfilters/pdf.cxx
and these emit various error messages directly to stderr.
Now the functions in cupsfilters/pdf.cxx are changed to return a
success/failure status and do not log any more. Instead the
bannertopdf() filter function logs failures of these functions via the
log function.
Till Kamppeter [Sun, 20 Mar 2022 23:03:31 +0000 (00:03 +0100)]
libcupsfilters: Removed stderr messages from cupsRasterParseIPPOptions()
cupsRasterParseIPPOptions() is parsing common options, especially IPP
options and for many but not all of them it emitted a log message
directly to stderr if the value of the attribute/option was not valid.
As the function is used by filter functions who should not log to
stderr we have removed this logging now. We decided for removing as
many other options did not produce log messages on invalid values.
Till Kamppeter [Sat, 19 Mar 2022 23:36:57 +0000 (00:36 +0100)]
libcupsfilters: In pdftops() use Poppler for all Apple LaserWriter models
We had already switched to Poppler to convert PDF to PostScript on
several Apple LaserWriter models as Ghostscript's PostScript did not
work on these printers, probably due to firmware bugs in the printers.
Now more Apple LaserWriter models were found which need the same
workaround. Therefore we use Poppler for all Apple LaserWriter models
now.
Till Kamppeter [Thu, 17 Mar 2022 12:55:26 +0000 (13:55 +0100)]
libcupsfilters: Let universal() correctly work with "*cupsFilter2:" in PPD
If we use the universal() filter function as CUPS filter (to replace
the chain of individual filters) we must tell from which format to
which other format universal() has to convert. For this universal()
grabs the CONTENT_TYPE and FINAL_CONTENT_TYPE environment variables to
get input format and output format resp.
But this does not work if the PPD file uses "*cupsFilter2: ..." lines
to tell which format is needed and what is the last filter to get the
printer's native data format. Problem is that the line specifies the
output format of the last filter in addition to its input format and
CUPS then sets FINAL_CONTENT_TYPE to the output format of the last
filter. This means that universal() has to find out what the input
format of the last filter is and generate this format.
So we do the following:
We check whether our output format (under CUPS it is taken from the
FINAL_CONTENT_TYPE env variable) is the destination format (2nd word)
of a "*cupsFilter2: ..." line (string has 4 words). In this case the
specified filter (4th word) does the last step, converting from the
input format (1st word) of the line to the destination format and so
we only need to convert to the input format. In this case we need to
correct our output format.
If there is more than one line with the given output format and an
input format we can produce, we select the one with the lowest cost
value (3rd word) as this is the one which CUPS should have chosen for
this job.
If we have "*cupsFilter: ..." lines (without "2", string with 3 words)
we do not need to do anything special, as the input format specified
is the FIMAL_CONTENT_TYPE which CUPS supplies to us and into which we
have to convert. So we quit parsing if the first line has only 3
words, as if CUPS uses the "*cupsFilter: ..." lines only if there is
no "*cupsFilter2: ..." line in the PPD, so if we encounter a line with
only 3 words the other lines will have only 3 words, too and nothing
has to be done.
We also take care that if our output format has to be CUPS Raster but
the final output format (of the last filter) is Apple Raster or PWG
Raster that we generate CUPS Raster which smoothly converts to
Apple/PWG Raster, by telling filters like ghostscript() and
imagetoraster() that the final format is Apple/PWG Raster.
In addition, some small string variables are now static and not
dynamic variables any more.
Till Kamppeter [Tue, 15 Mar 2022 22:43:12 +0000 (23:43 +0100)]
Build system: Install individual filter executables also with universal filter
If we use the "universal" CUPS filter which runs any needed filter
chain for CUPS out of a single executable, we also install the
executables to call the individual filter function, so that PPD files
specifying filter executables (of cups-filters) in their
"*cupsFilter(2):" lines will continue to work.
Also updated the wording of the help messages for universal/individual
filter executables use in the ./configure script.
Till Kamppeter [Tue, 15 Mar 2022 22:13:49 +0000 (23:13 +0100)]
libcupsfilters: Let generated PPD files only have one "*cupsFilter2:" line
To avoid any conflicts with the options, especially with the
resolutions, let the generated PPD only have one output format, even
if the printer has actually more.
We use always the most desirable (reliable) format: Apple Raster, PDF,
PWG Raster, PCLm, PCL-XL, PostScript, PCL 5c/e.
The additional "*cupsFilter2:" line(s) for JPG/PNG continue to be
added to the PPD.
Till Kamppeter [Tue, 8 Mar 2022 19:50:07 +0000 (20:50 +0100)]
libcupsfilters: In ghostscript() do not use gray profile on color PCLm
The "pclm" output device of Ghostscript only supports 8-bit sRGB
output, no sGray and also no color-to -monochrome conversion. There is
also no way to convert to grayscale by simply applying a gray color
profile.
Applying the gray color profile caused a crash in older versions of
Ghostscript and now is rejected with an error. See
Till Kamppeter [Fri, 25 Feb 2022 22:27:38 +0000 (23:27 +0100)]
libcupsfilters: In ghostscript() add monochrome PCLm printing
If a job for PCLm output is requested to be monochrome/grayscale (like
with "print-color-mode=monochrome"), use the sgray.icc color profile
instead of srgb.icc to get grayscale output.
Till Kamppeter [Fri, 25 Feb 2022 22:21:50 +0000 (23:21 +0100)]
libcupsfilters: In cupsRasterPrepareHeader() added monchrome PCLm support
PCLm supports exactly 2 color spaces, sRGB 8-bit for color and sGray
8-bit for monochrome printing. Up to now we only had supported the
sRGB space. This commit adds support for sGray.
This especially allows monchrome printing on color PCLm printers, and
faster (less data to handle) and more economic (use only black
toner/ink, not the colored ones) grayscale printing.
Principally all PCLm printers should support both color spaces.
Till Kamppeter [Thu, 17 Feb 2022 14:41:50 +0000 (15:41 +0100)]
libcupsfilters: Fixed imageto...() with print-scaling=auto
In the imageto...() filter functions with print-scaling=auto the image
size was not compared correctly with the page size to switch between
fit-to-page for large sizes and no scaling for small sizes. The image
size in pixels was compared with the page size in PostScript points
(1/72 inch).
Till Kamppeter [Thu, 17 Feb 2022 13:41:39 +0000 (14:41 +0100)]
libcupsfilters: Let imageto...() with print-scaling=none center correctly
In the imageto...() filter functions with print-scaling=none do the
math for centering the image on the page without the unprintable
margins, so that the image gets correctly centered relative to the
page, not to the printable area of the page.
As in imagetoraster we have to pass on a bitmap of the printable area
for CUPS Raster. we correct for the margins after calculating image
size and position without margins.
Till Kamppeter [Sun, 13 Feb 2022 14:31:56 +0000 (11:31 -0300)]
libcupsfilters: Do not always use high color depth for high quality
The cupsRasterPrepareHeader() function tries to set a high-color-depth
(16 bit per color) color mode for Apple Raster and PWG Raster if high
print quality is requested and the printer supports it.
We cannot do this all the time, as sometimes the filter function does
not support it (imagetoraster(), mupdftoraster()) or it could not be
worthwhile for the input file.
Therefore a new boolean argument is added to cupsRasterPrepareHeader()
to allow suppressing the selection of high color depth.
Currently we make use of this in the imagetoraster() and
mupdftoraster() filter functions.
Poppler's Raster output is 8-bit-sRGB-only, but as the color space
conversion to 16-bit AdobeRGB in pdftoraster is done by the color
space/profile conversion of LittleCMS we allow high color depth here
to allow a more precise color adjustment.
Ghostscript supports high color depth including LittleCMS color
management, therefore we keep support for it in the ghostscript()
filter function.
Till Kamppeter [Sun, 13 Feb 2022 02:39:57 +0000 (23:39 -0300)]
libcupsfilters: Many filter function fixes
- All filter functions, at least the ones producing CUPS/Apple/PWG
Raster output, work with cups-filters-generated PPD files now, where
no pseudo-PostScript code for the color space and depth is contained
any more but instead, copies of the printer IPP attributes telling
about supported color spaces and depths for Apple Raster and PWG
Raster (using cupsRasterPrepareHeader() function). Did this for
imagetoraster(), mupdftoraster(), and pdftoraster().
- In filter functions which only output CUPS Raster and not for
example Apple Raster or PCLm, cups-filters-generated PPD files
without Pseudo-PostScript code but copies of IPP attributes for
color spaces can also be used so that the generated CUPS Raster is
the one needed by rastertopwg() or rastertopdf() to generate the
final format. This is available in ghostscript(), imagetoraster(),
mupdftoraster(), and pdftoraster() now.
- In pdftoraster() and pwgtoraster() 16-bit-per color (high color
depth) modes printed in wrong colors, it was not taken account that
the color space/profile conversion by LittleCMS also converts to the
higher color depth, due to a bug in marking that no color depth
conversion is needed any more.
- In the imageto...() filter functions fixed the print-scaling=none
(crop-to-fit) mode, which prints the image in its original size
(based on PPI resolution stored in the image file or on 200 dpi
resolution, which is the standard resolution for shipping
labels). Also use crop-to-fit always when requested, do not fall
back to fit-to-page when the image is significantly larger or
smaller than the page.
- The cupsRasterPrepareHeader() function got enhanced to get separate
arguments for the actual format of the generated Raster header and
for the final output format of the job, to obtain color space and
depth, and the resolution according to that final output format.
Till Kamppeter [Fri, 11 Feb 2022 02:58:40 +0000 (23:58 -0300)]
libcupsfilters: fixes in cupsRasterSetColorSpace()
- Really do not do cspace_fallback = 0 with cspace = -1 (cspace
is an unsigned type, so -1 can only be checked via "==", not ">= 0")
- Advance search pointer in string of available color spaces after
a false positive (search term is part of the word) and not quit
loop then.
- Support more color spaces when parsing the color_mode string
(value of ColorModel or print-color-mode)
Now all color spaces supported by the printer in Apple/PWG Raster can
get auto-selected according to ColorModel or print-color-mode setting,
and results are more reliable (before we got grayscale on "RGB" color
mode).
Mohit Verma [Thu, 10 Feb 2022 17:47:41 +0000 (23:17 +0530)]
libcupsfilter: Added input-page-ranges attribute to pstops()
Pull request #445
As already to pdftopdf() we add the input-page-ranges attribute to be able to select pages of the input document before we do any re-arranging as number-up or booklet printing (Issue #365).
Till Kamppeter [Thu, 10 Feb 2022 17:37:50 +0000 (14:37 -0300)]
libcupsfilters: In mupdftoraster() direct output to outputfd
mupdftoraster() has called mutool in a forked sub-process but not
captured and re-directed stderr to the log function and stdout to the
outputfd file descriptor.
Till Kamppeter [Wed, 9 Feb 2022 17:37:03 +0000 (14:37 -0300)]
libcupsfilters: Don't call cupsRasterParseIPPOptions() if we have PPD
In a filter function, when we have a PPD file we should not call
cupsRasterParseIPPOptions() as this function guesses the meaning of
job options/attributes from their names.
This can easily cause problems, for example if we supply
"print-color-mode=monochrome" and the function chooses the wromg
monochrome color space, one not supported according to the PPD and so
not supported by the printer or the (rasterto...) driver.
Therefore we remove these calls and trust the PPD's options.
In retro-fitting Printer Applications job IPP attributes are
associated with appropriate PPD options anyway.
Till Kamppeter [Wed, 9 Feb 2022 17:14:52 +0000 (14:14 -0300)]
libcupsfilters: In mupdftoraster() removed ppdClose()
Filter functions should not close the PPD data structure which they
get supplied with the filter data, to once avoid crashes if the filter
function is called in a chain with other filter functions and common
filter data structure, and second, the filterCUPSWrapper() closes the
PPD data structure by itself.
Till Kamppeter [Sun, 6 Feb 2022 01:34:14 +0000 (22:34 -0300)]
implicitclass: If IPP poll of printer fails, use PPD file for capabilities
Member printers of a cups-browsed printer cluster are always IPP
printers, in most cases driverless IPP (IPP 2.x) printers and here a
get-printer-attributes IPP request gets all needed capability info
from the destination printer in order to run the filters to turn the
PDF input into the printer's data format.
If the destination printer is a legacy IPP (IPP 1.x) printer, our
get-printer-attributes IPP request fails (we accept only IPP 2.x here)
and then we fall back to using the PPD file. The PPD file is the
cluster's PPD, not the printer's, but all settings are supported by
our destination printer (otherwise it would not have gotten selected).
This way we recover support for legacy IPP printers which got dropped
with the recent commits to switch over to use filter functions instead
of external filter executables.
Till Kamppeter [Sat, 5 Feb 2022 18:34:21 +0000 (15:34 -0300)]
libcupsfilters: In pdftopdf() add 2% tolerance for input size larger output page
When "print-scaling=auto" or "print-scaling=auto-fit" is used, the
input pages are scaled when they do not fit into the output page
size. Often input ad out page sizes are supposed to be equal, for
example both A4, but rounding errors could make the input considered
larger and unnecessarily scaled.
Therefore we add 2% of tolerance before considering an input page too
large.
libcupsfilters: Changed the default ppi from 128 to 200
This is for image input files which have no PPI resolution in their metadata and are printed without scaling ("print-scaling=none"). In this case the default resolution is used. Formerly it was set to 128 PPI but we change it to 200 PPI now as many shipping labels come as image files with 200 PPI and so it is easier to print them in their original size. For photos this default value is not important though, as photos are usually printed with scaling ("print-scaling=fill" or "print-scaling=fit").
Till Kamppeter [Mon, 31 Jan 2022 16:39:15 +0000 (13:39 -0300)]
libcupsfilters: Undo previous commit of stderr message removal
We do not need to remove the stderr messages from cupsFindAttr(), the
function is only used by printer drivers not by filter functions. It
will be moved into a separate library.