From f09105dd3fab2920d6c021b015b4247b79c2268f Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Thu, 20 Feb 2025 18:18:53 -0500 Subject: [PATCH] Add support for writing the PCLm subset of PDF (Issue #99) --- CHANGES.md | 1 + doc/pdfio.3 | 22 ++++++++++++++++++---- doc/pdfio.html | 42 +++++++++++++++++++++++++++++++++++++----- pdfio-file.c | 33 +++++++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7ec59a7..735ee58 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ v1.5.0 - YYYY-MM-DD (Issue #10) - Added `pdfioFileGetModDate()` API (Issue #88) - Added support for using libpng to embed PNG images in PDF output (Issue #90) +- Added support for writing the PCLm subset of PDF (Issue #99) - Now support opening damaged PDF files (Issue #45) - Updated the pdf2txt example to support font encodings. diff --git a/doc/pdfio.3 b/doc/pdfio.3 index 837f56c..30aea17 100644 --- a/doc/pdfio.3 +++ b/doc/pdfio.3 @@ -1,4 +1,4 @@ -.TH pdfio 3 "pdf read/write library" "2025-02-13" "pdf read/write library" +.TH pdfio 3 "pdf read/write library" "2025-02-20" "pdf read/write library" .SH NAME pdfio \- pdf read/write library .SH Introduction @@ -3561,7 +3561,8 @@ This function creates a new PDF file. The "filename" argument specifies the name of the PDF file to create. .PP The "version" argument specifies the PDF version number for the file or -\fBNULL\fR for the default ("2.0"). +\fBNULL\fR for the default ("2.0"). The value "PCLm-1.0" can be specified to +produce the PCLm subset of PDF. .PP The "media_box" and "crop_box" arguments specify the default MediaBox and CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size @@ -3643,8 +3644,19 @@ This function embeds a TrueType/OpenType font into a PDF file. The characters (potentially full Unicode, but more typically a subset) or to only support the Windows CP1252 (ISO-8859-1 with additional characters such as the Euro symbol) subset of Unicode. +.SS pdfioFileCreateICCObjFromData +Add ICC profile data to a PDF file. +.PP +.nf +pdfio_obj_t * pdfioFileCreateICCObjFromData ( + pdfio_file_t *pdf, + const unsigned char *data, + size_t datalen, + size_t num_colors +); +.fi .SS pdfioFileCreateICCObjFromFile -Add an ICC profile object to a PDF file. +Add an ICC profile file to a PDF file. .PP .nf pdfio_obj_t * pdfioFileCreateICCObjFromFile ( @@ -3767,7 +3779,9 @@ written: .fi The "version" argument specifies the PDF version number for the file or -\fBNULL\fR for the default ("2.0"). +\fBNULL\fR for the default ("2.0"). Unlike \fIpdfioFileCreate\fR and +\fIpdfioFileCreateTemporary\fR, it is generally not safe to pass the +"PCLm-1.0" version string. .PP The "media_box" and "crop_box" arguments specify the default MediaBox and CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size diff --git a/doc/pdfio.html b/doc/pdfio.html index c3bc4c4..d695b88 100644 --- a/doc/pdfio.html +++ b/doc/pdfio.html @@ -400,6 +400,7 @@ span.string {
  • pdfioFileCreateArrayObj
  • pdfioFileCreateFontObjFromBase
  • pdfioFileCreateFontObjFromFile
  • +
  • pdfioFileCreateICCObjFromData
  • pdfioFileCreateICCObjFromFile
  • pdfioFileCreateImageObjFromData
  • pdfioFileCreateImageObjFromFile
  • @@ -3814,7 +3815,8 @@ have been iterated.

    name of the PDF file to create.

    The "version" argument specifies the PDF version number for the file or -NULL for the default ("2.0").
    +NULL for the default ("2.0"). The value "PCLm-1.0" can be specified to +produce the PCLm subset of PDF.

    The "media_box" and "crop_box" arguments specify the default MediaBox and CropBox for pages in the PDF file - if NULL then a default "Universal" size @@ -3909,8 +3911,25 @@ Unicode.

    characters (potentially full Unicode, but more typically a subset) or to only support the Windows CP1252 (ISO-8859-1 with additional characters such as the Euro symbol) subset of Unicode.

    +

    pdfioFileCreateICCObjFromData

    +

    Add ICC profile data to a PDF file.

    +

    +pdfio_obj_t *pdfioFileCreateICCObjFromData(pdfio_file_t *pdf, const unsigned char *data, size_t datalen, size_t num_colors);

    +

    Parameters

    + + + + + + + + + +
    pdfPDF file
    dataICC profile buffer
    datalenLength of ICC profile
    num_colorsNumber of color components (1, 3, or 4)
    +

    Return Value

    +

    Object

    pdfioFileCreateICCObjFromFile

    -

    Add an ICC profile object to a PDF file.

    +

    Add an ICC profile file to a PDF file.

    pdfio_obj_t *pdfioFileCreateICCObjFromFile(pdfio_file_t *pdf, const char *filename, size_t num_colors);

    Parameters

    @@ -4071,7 +4090,9 @@ output_cb(void *output_cbdata, const void *buffer, size_t bytes) The "version" argument specifies the PDF version number for the file or -NULL for the default ("2.0").
    +NULL for the default ("2.0"). Unlike pdfioFileCreate and +pdfioFileCreateTemporary, it is generally not safe to pass the +"PCLm-1.0" version string.

    The "media_box" and "crop_box" arguments specify the default MediaBox and CropBox for pages in the PDF file - if NULL then a default "Universal" size @@ -4139,8 +4160,19 @@ You must call pdfioObjClose to write t

    Create a temporary PDF file.

    This function creates a PDF file with a unique filename in the current temporary directory. The temporary file is stored in the string "buffer" an -will have a ".pdf" extension. Otherwise, this function works the same as -the pdfioFileCreate function. +will have a ".pdf" extension.
    +
    +The "version" argument specifies the PDF version number for the file or +NULL for the default ("2.0"). The value "PCLm-1.0" can be specified to +produce the PCLm subset of PDF.
    +
    +The "media_box" and "crop_box" arguments specify the default MediaBox and +CropBox for pages in the PDF file - if NULL then a default "Universal" size +of 8.27x11in (the intersection of US Letter and ISO A4) is used.
    +
    +The "error_cb" and "error_cbdata" arguments specify an error handler callback +and its data pointer - if NULL the default error handler is used that +writes error messages to stderr.

    pdfioFileFindObj

    diff --git a/pdfio-file.c b/pdfio-file.c index eba6a95..7af5617 100644 --- a/pdfio-file.c +++ b/pdfio-file.c @@ -165,7 +165,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file // name of the PDF file to create. // // The "version" argument specifies the PDF version number for the file or -// `NULL` for the default ("2.0"). +// `NULL` for the default ("2.0"). The value "PCLm-1.0" can be specified to +// produce the PCLm subset of PDF. // // The "media_box" and "crop_box" arguments specify the default MediaBox and // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size @@ -397,7 +398,9 @@ _pdfioFileCreateObj( // ``` // // The "version" argument specifies the PDF version number for the file or -// `NULL` for the default ("2.0"). +// `NULL` for the default ("2.0"). Unlike @link pdfioFileCreate@ and +// @link pdfioFileCreateTemporary@, it is generally not safe to pass the +// "PCLm-1.0" version string. // // The "media_box" and "crop_box" arguments specify the default MediaBox and // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size @@ -532,8 +535,19 @@ pdfioFileCreateStringObj( // // This function creates a PDF file with a unique filename in the current // temporary directory. The temporary file is stored in the string "buffer" an -// will have a ".pdf" extension. Otherwise, this function works the same as -// the @link pdfioFileCreate@ function. +// will have a ".pdf" extension. +// +// The "version" argument specifies the PDF version number for the file or +// `NULL` for the default ("2.0"). The value "PCLm-1.0" can be specified to +// produce the PCLm subset of PDF. +// +// The "media_box" and "crop_box" arguments specify the default MediaBox and +// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size +// of 8.27x11in (the intersection of US Letter and ISO A4) is used. +// +// The "error_cb" and "error_cbdata" arguments specify an error handler callback +// and its data pointer - if `NULL` the default error handler is used that +// writes error messages to `stderr`. // // @since PDFio v1.1@ // @@ -1396,7 +1410,7 @@ create_common( pdf->output_cb = output_cb; pdf->output_ctx = output_cbdata; pdf->filename = strdup(filename); - pdf->version = strdup(version); + pdf->version = strdup(!strncmp(version, "PCLm-", 5) ? "1.4" : version); pdf->mode = _PDFIO_MODE_WRITE; pdf->error_cb = error_cb; pdf->error_data = error_cbdata; @@ -1427,8 +1441,15 @@ create_common( } // Write a standard PDF header... - if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version)) + if (!strncmp(version, "PCLm-", 5)) + { + if (!_pdfioFilePrintf(pdf, "%%PDF-1.4\n%%%s\n", version)) + goto error; + } + else if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version)) + { goto error; + } // Create the pages object... if ((dict = pdfioDictCreate(pdf)) == NULL)