Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ lib_LTLIBRARIES = libcupsfilters.la

check_SCRIPTS = \
cupsfilters/testfilters.sh \
cupsfilters/test-pclm-overflow.sh
cupsfilters/test-pclm-overflow.sh \
cupsfilters/test-pdftoraster-copy-height.sh

check_PROGRAMS = \
testcmyk \
Expand All @@ -105,8 +106,7 @@ check_PROGRAMS = \
test-analyze \
test-pdf \
test-ps \
testfilters \
test-pdftoraster-copy-height
testfilters

TESTS = \
testdither \
Expand All @@ -115,9 +115,9 @@ TESTS = \
test-analyze \
test-pdf \
test-ps \
test-pdftoraster-copy-height \
cupsfilters/testfilters.sh \
cupsfilters/test-pclm-overflow.sh
cupsfilters/test-pclm-overflow.sh \
cupsfilters/test-pdftoraster-copy-height.sh

# testcmyk # fails as it opens some image.ppm which is nowerhe to be found.
# testimage # requires also some ppm file as argument
Expand Down Expand Up @@ -323,9 +323,6 @@ test_ps_SOURCES = cupsfilters/fontembed/test-ps.c
test_ps_LDADD = libcupsfilters.la $(CUPS_LIBS)
test_ps_CFLAGS = $(CUPS_CFLAGS)

test_pdftoraster_copy_height_SOURCES = \
cupsfilters/test-pdftoraster-copy-height.c

testfilters_SOURCES = \
cupsfilters/testfilters.c \
$(pkgfiltersinclude_DATA)
Expand All @@ -343,6 +340,10 @@ testfilters_LDFLAGS = \
noinst_PROGRAMS = gen-lorem-text
gen_lorem_text_SOURCES = cupsfilters/gen-lorem-text.c
EXTRA_DIST += cupsfilters/gen-lorem-text.c
# Built by cupsfilters/test-pdftoraster-copy-height.sh under AddressSanitizer
# (not a check_PROGRAM, so it can skip when ASan is absent); named here so it
# ships in "make dist".
EXTRA_DIST += cupsfilters/test-pdftoraster-copy-height.c
# Generated deterministic lorem text for texttopdf tests
BUILT_SOURCES = cupsfilters/test_files/test_text_lorem.txt
CLEANFILES = cupsfilters/test_files/test_text_lorem.txt
Expand Down
172 changes: 99 additions & 73 deletions cupsfilters/pdftoraster.c
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,101 @@ read_ppm_data(FILE *img, // I - Image file
return data;
}

//
// 'copy_image_rows()' - Copy the rendered image rows into the CUPS raster
// page, clamped by copy_height/copy_width so a rendered
// image smaller than the page is padded with background
// rows. Extracted from write_page_image() so the
// copy_height boundary can be exercised directly by the
// unit test against a controlled buffer under ASan.
//

static void
copy_image_rows(cups_raster_t *raster, // I - CUPS raster output
pdftoraster_doc_t *doc, // I - Document attributes
pdf_conversion_function_t *convert, // I - conversion rules
int pageNo, // I - page number (parity)
unsigned char *colordata, // I - rendered image data
unsigned int image_rowsize, // I - bytes per image row
unsigned int copy_height, // I - image rows to copy
unsigned int copy_width, // I - width to copy
unsigned char *lineBuf, // I - scratch line buffer
int bg_color) // I - background fill value
{
unsigned char *dp;
convert_line_func convertLine;

if ((pageNo & 1) == 0)
convertLine = convert->convertLineEven;
else
convertLine = convert->convertLineOdd;

if (doc->header.Duplex && (pageNo & 1) == 0 && doc->swap_image_y)
{
for (unsigned int plane = 0; plane < doc->nplanes; plane ++)
{
unsigned char *bp = colordata + (copy_height - 1) * image_rowsize;

for (unsigned int h = doc->header.cupsHeight; h > 0; h--)
{
if (h <= copy_height) // inside valid page/image area
{
if (doc->allocLineBuf)
memset(lineBuf, bg_color, doc->bytesPerLine);
for (unsigned int band = 0; band < doc->nbands; band ++)
{
dp = convertLine(bp, lineBuf, h - 1, plane + band,
copy_width,
doc->bytesPerLine, doc, convert->convertCSpace);
cupsRasterWritePixels(raster, dp, doc->bytesPerLine);
}
bp -= image_rowsize;
}
else // Image shorter than page, thus whitespace
{
if (doc->allocLineBuf)
{
memset(lineBuf, bg_color, doc->bytesPerLine);
cupsRasterWritePixels(raster, lineBuf, doc->bytesPerLine);
}
}
}
}
}
else
{
for (unsigned int plane = 0; plane < doc->nplanes; plane++)
{
unsigned char *bp = colordata;
for (unsigned int h = 0; h < doc->header.cupsHeight; h++)
{
if (h < copy_height) // inside valid page/image area
{
if (doc->allocLineBuf)
memset(lineBuf, bg_color, doc->bytesPerLine);

for (unsigned int band = 0; band < doc->nbands; band++)
{
dp = convertLine(bp, lineBuf, h, plane + band, copy_width,
doc->bytesPerLine, doc, convert->convertCSpace);
cupsRasterWritePixels(raster, dp, doc->bytesPerLine);
}
bp += image_rowsize;
}
else // Image shorter than page, thus whitespace
{
if (doc->allocLineBuf)
{
memset(lineBuf, bg_color, doc->bytesPerLine);
cupsRasterWritePixels(raster, lineBuf, doc->bytesPerLine);
}
}
}
}
}
}


//
// 'write_page_image()' - bridge between PDF rendering tool and CUPS raster Output
//
Expand All @@ -1724,9 +1819,7 @@ write_page_image(cups_raster_t *raster, // I - Cups raster output data struct
void *icd)
{
int i;
convert_line_func convertLine;
unsigned char *lineBuf = NULL;
unsigned char *dp;
unsigned int image_rowsize = 0;
int fakeres[2];
int bg_color = 255;
Expand Down Expand Up @@ -1958,82 +2051,15 @@ write_page_image(cups_raster_t *raster, // I - Cups raster output data struct
}
}

if ((pageNo & 1) == 0)
convertLine = convert->convertLineEven;
else
convertLine = convert->convertLineOdd;

// This will be the safe copy limit;
// In some cases, the PDFtoppm might output where image sizes are
// This will be the safe copy limit;
// In some cases, the PDFtoppm might output where image sizes are
// smaller than expected page size.
// copy_height and copy_width act as safe copy limit in this.
unsigned int copy_height = (height < doc->header.cupsHeight) ? height : doc->header.cupsHeight;
unsigned int copy_width = (width < doc->header.cupsWidth) ? width : doc->header.cupsWidth;

if (doc->header.Duplex && (pageNo & 1) == 0 && doc->swap_image_y)
{
for (unsigned int plane = 0; plane < doc->nplanes; plane ++)
{
unsigned char *bp = colordata + (copy_height - 1) * image_rowsize;

for (unsigned int h = doc->header.cupsHeight; h > 0; h--)
{
if (h <= copy_height) // inside valid page/image area
{
if (doc->allocLineBuf)
memset(lineBuf, bg_color, doc->bytesPerLine);
for (unsigned int band = 0; band < doc->nbands; band ++)
{
dp = convertLine(bp, lineBuf, h - 1, plane + band,
copy_width,
doc->bytesPerLine, doc, convert->convertCSpace);
cupsRasterWritePixels(raster, dp, doc->bytesPerLine);
}
bp -= image_rowsize;
}
else // Image shorter than page, thus whitespace
{
if (doc->allocLineBuf)
{
memset(lineBuf, bg_color, doc->bytesPerLine);
cupsRasterWritePixels(raster, lineBuf, doc->bytesPerLine);
}
}
}
}
}
else
{
for (unsigned int plane = 0; plane < doc->nplanes; plane++)
{
unsigned char *bp = colordata;
for (unsigned int h = 0; h < doc->header.cupsHeight; h++)
{
if (h < copy_height) // inside valid page/image area
{
if (doc->allocLineBuf)
memset(lineBuf, bg_color, doc->bytesPerLine);

for (unsigned int band = 0; band < doc->nbands; band++)
{
dp = convertLine(bp, lineBuf, h, plane + band, copy_width,
doc->bytesPerLine, doc, convert->convertCSpace);
cupsRasterWritePixels(raster, dp, doc->bytesPerLine);
}
bp += image_rowsize;
}
else // Image shorter than page, thus whitespace
{
if (doc->allocLineBuf)
{
memset(lineBuf, bg_color, doc->bytesPerLine);
cupsRasterWritePixels(raster, lineBuf, doc->bytesPerLine);
}
}
}
}
}

copy_image_rows(raster, doc, convert, pageNo, colordata, image_rowsize,
copy_height, copy_width, lineBuf, bg_color);
free(colordata);
if (lineBuf)
free(lineBuf);
Expand Down
Loading
Loading