Skip to content

Commit

Permalink
Manage page dimensions when no printer properties are given.
Browse files Browse the repository at this point in the history
If a filter function is called without printer IPP attributes (classic
CUPS filter wrapper without PPD file) any page size/media attributes
given are accepted, when no page dimensions are given, US Letter is
used, and when no margins are given, non-zero default margins are
used.
  • Loading branch information
tillkamppeter committed Dec 6, 2022
1 parent 2e25fb8 commit 8de58de
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 82 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## CHANGES IN V2.0b2 (TBA)

- Manage page dimensions when no printer properties are given.
If a filter function is called without printer IPP attributes
(classic CUPS filter wrapper without PPD file) any page size/media
attributes given are accepted, when no page dimensions are given, US
Letter is used, and when no margins are given, non-zero default
margins are used.

- cfFilterTextToPDF(): If no output page dimensions specified, use US
Letter. Before, the page dimensions were set to 0x0, ending up with
one empty page per character in the input file being produced.
Expand Down
12 changes: 10 additions & 2 deletions cupsfilters/bannertopdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ generate_banner_pdf(banner_t *banner,
void *ld,
FILE *outputfp)
{
int i;
char *buf;
size_t len;
FILE *s;
Expand All @@ -607,8 +608,9 @@ generate_banner_pdf(banner_t *banner,
return (1);
}

memset(media_limits, 0, sizeof(media_limits));
if (data != NULL && (data->printer_attrs) != NULL)
for (i = 0; i < 4; i ++)
media_limits[i] = -1.0;
if (data != NULL)
{
cfGetPageDimensions(data->printer_attrs, data->job_attrs,
num_options, options,
Expand All @@ -617,6 +619,12 @@ generate_banner_pdf(banner_t *banner,
&(media_limits[0]), &(media_limits[1]),
&(media_limits[2]), &(media_limits[3]),
NULL, NULL);

cfSetPageDimensionsToDefault(&(page_width), &(page_length),
&(media_limits[0]), &(media_limits[1]),
&(media_limits[2]), &(media_limits[3]),
log, ld);

media_limits[2] = page_width - media_limits[2];
media_limits[3] = page_length - media_limits[3];
}
Expand Down
170 changes: 141 additions & 29 deletions cupsfilters/ipp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1776,8 +1776,9 @@ cfGetPageDimensions(ipp_t *printer_attrs, // I - Printer attributes
{
if (*(attr_name + 1))
{
if ((attr = ippFindAttribute(printer_attrs, attr_name + 1,
IPP_TAG_ZERO)) != NULL)
if (printer_attrs &&
(attr = ippFindAttribute(printer_attrs, attr_name + 1,
IPP_TAG_ZERO)) != NULL)
{
// String from IPP attribute
ippAttributeString(attr, valstr, sizeof(valstr));
Expand Down Expand Up @@ -1970,6 +1971,94 @@ cfGetPageDimensions(ipp_t *printer_attrs, // I - Printer attributes
}


void
cfSetPageDimensionsToDefault(float *width, // IO - Width (in pt, 1/72 inches)
float *height, // IO - Height
float *left, // IO - Left margin
float *bottom, // IO - Bottom margin
float *right, // IO - Right margin
float *top, // IO - Top margin
cf_logfunc_t log, // I - Log function
void *ld) // I - Log function data
{
if (width && height && (*width <= 0.0 || *height <= 0.0))
{
if (log) log(ld, CF_LOGLEVEL_WARN,
"Could not determine the output page dimensions, falling back to US Letter format");
*width = 612.0;
*height = 792.0;
}

if (left && *left < 0.0)
{
if (log) log(ld, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the left margin, falling back to 18 pt/6.35 mm");
*left = 18.0;
}

if (bottom && *bottom < 0.0)
{
if (log) log(ld, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the bottom margin, falling back to 36 pt/12.7 mm");
*bottom = 36.0;
}

if (right && *right < 0.0)
{
if (log) log(ld, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the right margin, falling back to 18 pt/6.35 mm");
*right = 18.0;
}

if (top && *top < 0.0)
{
if (log) log(ld, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the top margin, falling back to 36 pt/12.7 mm");
*top = 36.0;
}
}


static pwg_media_t *
dimensions_for_name(char *size_name,
char *size_name_buf,
int *search_width,
int *search_length,
int *borderless)
{
// Find the dimensions for the page size name we got as search term
char *ptr;
pwg_media_t *search = NULL;
int is_transverse = (strcasestr(size_name, ".Transverse") ? 1 : 0);
*borderless = (strcasestr(size_name, ".Fullbleed") ||
strcasestr(size_name, ".Borderless") ||
strcasestr(size_name, ".FB")) ? 1 : 0;
if (size_name != size_name_buf)
strlcpy(size_name_buf, size_name, IPP_MAX_NAME);
if ((ptr = strchr(size_name_buf, '.')) != NULL &&
strncasecmp(size_name_buf, "Custom.", 7) != 0)
*ptr = '\0';
if ((search = pwgMediaForPWG(size_name_buf)) == NULL)
if ((search = pwgMediaForPPD(size_name_buf)) == NULL)
search = pwgMediaForLegacy(size_name_buf);
if (search != NULL)
{
// Set the appropriate dimensions
if (is_transverse)
{
*search_width = search->length;
*search_length = search->width;
}
else
{
*search_width = search->width;
*search_length = search->length;
}
}
return (search);
}


void
cfGenerateSizes(ipp_t *response,
cf_gen_sizes_mode_t mode,
Expand Down Expand Up @@ -2007,7 +2096,6 @@ cfGenerateSizes(ipp_t *response,
const char *psname;
const char *entry_name;
char size_name_buf[IPP_MAX_NAME + 1] = "";
pwg_media_t *search = NULL;
int search_width = 0,
search_length = 0,
search_left = -1,
Expand All @@ -2019,6 +2107,48 @@ cfGenerateSizes(ipp_t *response,
border_mismatch;


// If no printer attributes are suppied, we simply return without
// modifying the dimensions/margins to be checked, making the caller
// simply accepting them.
//
// If a size name (PWG/IPP, PPD, legacy) is supplied and dimensions
// are found by libcups, these dimensions are used. If the name is
// supplied with ".Borderless", ".Fullbleed", or ".FB" variant, we
// return zero borders instead of the originally given ones, and
// with the ".Transverse" variant we swap width and length
// dimensions.
if (!response)
{
int borderless = 0;
if (size_name == NULL || width == NULL || length == NULL)
// Name or variables to drop the size dimensions not supplied
return;
dimensions_for_name(size_name, size_name_buf, width, length, &borderless);
if (borderless)
{
if (left)
*left = 0;
if (bottom)
*bottom = 0;
if(right)
*right = 0;
if (top)
*top = 0;
}
else
{
if (left && *left < 0)
*left = 635;
if (bottom && *bottom < 0)
*bottom = 1270;
if (right && *right < 0)
*right = 635;
if (top && *top < 0)
*top = 1270;
}
return;
}

if (media_col_entry)
*media_col_entry = NULL;

Expand Down Expand Up @@ -2207,33 +2337,15 @@ cfGenerateSizes(ipp_t *response,
else
{
// Find the dimensions for the page size name we got as search term
char *ptr;
int is_transverse = (strcasestr(size_name, ".Transverse") ? 1 : 0);
if (strcasestr(size_name, ".Fullbleed") ||
strcasestr(size_name, ".Borderless") ||
strcasestr(size_name, ".FB"))
mode = CF_GEN_SIZES_SEARCH_BORDERLESS_ONLY;
if (size_name != size_name_buf)
strlcpy(size_name_buf, size_name, IPP_MAX_NAME);
if ((ptr = strchr(size_name_buf, '.')) != NULL &&
strncasecmp(size_name_buf, "Custom.", 7) != 0)
*ptr = '\0';
if ((search = pwgMediaForPWG(size_name_buf)) == NULL)
if ((search = pwgMediaForPPD(size_name_buf)) == NULL)
search = pwgMediaForLegacy(size_name_buf);
if (search != NULL)
int borderless = 0;
if (size_name[0] &&
dimensions_for_name(size_name, size_name_buf,
&search_width, &search_length, &borderless))
{
// Set the appropriate dimensions
if (is_transverse)
{
search_width = search->length;
search_length = search->width;
}
else
{
search_width = search->width;
search_length = search->length;
}
// Supplied size name was borderless variant, so search only for
// borderless sizes
if (borderless)
mode = CF_GEN_SIZES_SEARCH_BORDERLESS_ONLY;
}
else
{
Expand Down
8 changes: 8 additions & 0 deletions cupsfilters/ipp.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ int cfGetPageDimensions(ipp_t *printer_attrs,
float *top,
char *name,
ipp_t **media_col_entry);
void cfSetPageDimensionsToDefault(float *width,
float *height,
float *left,
float *bottom,
float *right,
float *top,
cf_logfunc_t log,
void *ld);
void cfGenerateSizes(ipp_t *response,
cf_gen_sizes_mode_t mode,
cups_array_t **sizes,
Expand Down
12 changes: 10 additions & 2 deletions cupsfilters/pclmtoraster.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,7 @@ out_page(cups_raster_t* raster, // I - Raster stream
cf_filter_data_t *filter_data, // I - filter data
conversion_function_t *convert)// I - Conversion functions
{
int i;
long long rotate = 0,
height,
width;
Expand Down Expand Up @@ -844,15 +845,22 @@ out_page(cups_raster_t* raster, // I - Raster stream
}

memset(paperdimensions, 0, sizeof(paperdimensions));
memset(margins, 0, sizeof(margins));
if (filter_data != NULL && (filter_data->printer_attrs) != NULL)
for (i = 0; i < 4; i ++)
margins[i] = -1.0;
if (filter_data != NULL)
{
cfGetPageDimensions(filter_data->printer_attrs, filter_data->job_attrs,
filter_data->num_options, filter_data->options,
&(data->header), 0,
&(paperdimensions[0]), &(paperdimensions[1]),
&(margins[0]), &(margins[1]),
&(margins[2]), &(margins[3]), NULL, NULL);

cfSetPageDimensionsToDefault(&(paperdimensions[0]), &(paperdimensions[1]),
&(margins[0]), &(margins[1]),
&(margins[2]), &(margins[3]),
log, ld);

if (data->outformat != CF_FILTER_OUT_FORMAT_CUPS_RASTER)
memset(margins, 0, sizeof(margins));
}
Expand Down
59 changes: 15 additions & 44 deletions cupsfilters/pdftopdf/pdftopdf.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -321,50 +321,21 @@ getParameters(cf_filter_data_t *data,
else
param.no_orientation = true;

if (printer_attrs != NULL)
param.pagesize_requested =
(cfGetPageDimensions(printer_attrs, job_attrs, num_options, options, NULL,
0,
&(param.page.width), &(param.page.height),
&(param.page.left), &(param.page.bottom),
&(param.page.right), &(param.page.top),
NULL, NULL) == 1);

if (param.page.width <= 0 || param.page.height <= 0)
{
if (doc->logfunc) doc->logfunc(doc->logdata, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the output page dimensions, falling back to US Letter format");
param.page.width = 612;
param.page.height = 792;
}
if (param.page.left < 0)
{
if (doc->logfunc) doc->logfunc(doc->logdata, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the left margin, falling back to 18 pt/6.35 mm");
param.page.left = 18.0;
}
if (param.page.bottom < 0)
{
if (doc->logfunc) doc->logfunc(doc->logdata, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the bottom margin, falling back to 36 pt/12.7 mm");
param.page.bottom = 36.0;
}
if (param.page.right < 0)
{
if (doc->logfunc) doc->logfunc(doc->logdata, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the right margin, falling back to 18 pt/6.35 mm");
param.page.right = param.page.width - 18.0;
}
else
param.page.right = param.page.width - param.page.right;
if (param.page.top < 0)
{
if (doc->logfunc) doc->logfunc(doc->logdata, CF_LOGLEVEL_WARN,
"cfFilterPDFToPDF: Could not determine the width of the top margin, falling back to 36 pt/12.7 mm");
param.page.top = param.page.height - 36.0;
}
else
param.page.top = param.page.height - param.page.top;
param.pagesize_requested =
(cfGetPageDimensions(printer_attrs, job_attrs, num_options, options, NULL,
0,
&(param.page.width), &(param.page.height),
&(param.page.left), &(param.page.bottom),
&(param.page.right), &(param.page.top),
NULL, NULL) == 1);

cfSetPageDimensionsToDefault(&(param.page.width), &(param.page.height),
&(param.page.left), &(param.page.bottom),
&(param.page.right), &(param.page.top),
doc->logfunc, doc->logdata);

param.page.right = param.page.width - param.page.right;
param.page.top = param.page.height - param.page.top;

param.paper_is_landscape = (param.page.width > param.page.height);

Expand Down
11 changes: 9 additions & 2 deletions cupsfilters/pdftoraster.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1633,15 +1633,22 @@ out_page(pdftoraster_doc_t *doc,
(unsigned)(doc->header.cupsImagingBBox[i]);

memset(paperdimensions, 0, sizeof(paperdimensions));
memset(margins, 0, sizeof(margins));
if (data != NULL && (data->printer_attrs) != NULL)
for (i = 0; i < 4; i ++)
margins[i] = -1.0;
if (data != NULL)
{
i = cfGetPageDimensions(data->printer_attrs, data->job_attrs,
data->num_options, data->options,
&(doc->header), 0,
&(paperdimensions[0]), &(paperdimensions[1]),
&(margins[0]), &(margins[1]),
&(margins[2]), &(margins[3]), NULL, NULL);

cfSetPageDimensionsToDefault(&(paperdimensions[0]), &(paperdimensions[1]),
&(margins[0]), &(margins[1]),
&(margins[2]), &(margins[3]),
log, ld);

// Overspray borderless page size: If the dimensions of the page
// size are up to 10% larger than the ones of the input page, zoom
// the image by rendering with an appropriately larger fake
Expand Down
Loading

0 comments on commit 8de58de

Please sign in to comment.