Compare commits

...

5 Commits

Author SHA1 Message Date
Michael R Sweet
f09105dd3f
Add support for writing the PCLm subset of PDF (Issue #99) 2025-02-20 18:18:53 -05:00
Michael R Sweet
5be5552b2b
Turn write_obj_header into private API. 2025-02-20 17:37:31 -05:00
Michael R Sweet
492a4f51b2
Allocate stream compression buffer. 2025-02-16 13:20:51 -05:00
Michael R Sweet
44827bac1a
Cleanup. 2025-02-16 12:40:39 -05:00
Michael R Sweet
3fad0d6f15
Support xref streams with encrypted output. 2025-02-16 12:35:45 -05:00
7 changed files with 149 additions and 54 deletions

View File

@ -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.

View File

@ -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

View File

@ -400,6 +400,7 @@ span.string {
<li><a href="#pdfioFileCreateArrayObj">pdfioFileCreateArrayObj</a></li>
<li><a href="#pdfioFileCreateFontObjFromBase">pdfioFileCreateFontObjFromBase</a></li>
<li><a href="#pdfioFileCreateFontObjFromFile">pdfioFileCreateFontObjFromFile</a></li>
<li><a href="#pdfioFileCreateICCObjFromData">pdfioFileCreateICCObjFromData</a></li>
<li><a href="#pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></li>
<li><a href="#pdfioFileCreateImageObjFromData">pdfioFileCreateImageObjFromData</a></li>
<li><a href="#pdfioFileCreateImageObjFromFile">pdfioFileCreateImageObjFromFile</a></li>
@ -3814,7 +3815,8 @@ have been iterated.</p>
name of the PDF file to create.<br>
<br>
The &quot;version&quot; argument specifies the PDF version number for the file or
<code>NULL</code> for the default (&quot;2.0&quot;).<br>
<code>NULL</code> for the default (&quot;2.0&quot;). The value &quot;PCLm-1.0&quot; can be specified to
produce the PCLm subset of PDF.<br>
<br>
The &quot;media_box&quot; and &quot;crop_box&quot; arguments specify the default MediaBox and
CropBox for pages in the PDF file - if <code>NULL</code> then a default &quot;Universal&quot; size
@ -3909,8 +3911,25 @@ Unicode.</p>
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.</p>
<h3 class="function"><a id="pdfioFileCreateICCObjFromData">pdfioFileCreateICCObjFromData</a></h3>
<p class="description">Add ICC profile data to a PDF file.</p>
<p class="code">
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateICCObjFromData(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, <span class="reserved">const</span> <span class="reserved">unsigned</span> <span class="reserved">char</span> *data, size_t datalen, size_t num_colors);</p>
<h4 class="parameters">Parameters</h4>
<table class="list"><tbody>
<tr><th>pdf</th>
<td class="description">PDF file</td></tr>
<tr><th>data</th>
<td class="description">ICC profile buffer</td></tr>
<tr><th>datalen</th>
<td class="description">Length of ICC profile</td></tr>
<tr><th>num_colors</th>
<td class="description">Number of color components (1, 3, or 4)</td></tr>
</tbody></table>
<h4 class="returnvalue">Return Value</h4>
<p class="description">Object</p>
<h3 class="function"><a id="pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></h3>
<p class="description">Add an ICC profile object to a PDF file.</p>
<p class="description">Add an ICC profile file to a PDF file.</p>
<p class="code">
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateICCObjFromFile(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, <span class="reserved">const</span> <span class="reserved">char</span> *filename, size_t num_colors);</p>
<h4 class="parameters">Parameters</h4>
@ -4071,7 +4090,9 @@ output_cb(void *output_cbdata, const void *buffer, size_t bytes)
</pre>
The &quot;version&quot; argument specifies the PDF version number for the file or
<code>NULL</code> for the default (&quot;2.0&quot;).<br>
<code>NULL</code> for the default (&quot;2.0&quot;). Unlike <a href="#pdfioFileCreate"><code>pdfioFileCreate</code></a> and
<a href="#pdfioFileCreateTemporary"><code>pdfioFileCreateTemporary</code></a>, it is generally not safe to pass the
&quot;PCLm-1.0&quot; version string.<br>
<br>
The &quot;media_box&quot; and &quot;crop_box&quot; arguments specify the default MediaBox and
CropBox for pages in the PDF file - if <code>NULL</code> then a default &quot;Universal&quot; size
@ -4139,8 +4160,19 @@ You must call <a href="#pdfioObjClose"><code>pdfioObjClose</code></a> to write t
<p class="description">Create a temporary PDF file.</p>
<p class="discussion">This function creates a PDF file with a unique filename in the current
temporary directory. The temporary file is stored in the string &quot;buffer&quot; an
will have a &quot;.pdf&quot; extension. Otherwise, this function works the same as
the <a href="#pdfioFileCreate"><code>pdfioFileCreate</code></a> function.
will have a &quot;.pdf&quot; extension.<br>
<br>
The &quot;version&quot; argument specifies the PDF version number for the file or
<code>NULL</code> for the default (&quot;2.0&quot;). The value &quot;PCLm-1.0&quot; can be specified to
produce the PCLm subset of PDF.<br>
<br>
The &quot;media_box&quot; and &quot;crop_box&quot; arguments specify the default MediaBox and
CropBox for pages in the PDF file - if <code>NULL</code> then a default &quot;Universal&quot; size
of 8.27x11in (the intersection of US Letter and ISO A4) is used.<br>
<br>
The &quot;error_cb&quot; and &quot;error_cbdata&quot; arguments specify an error handler callback
and its data pointer - if <code>NULL</code> the default error handler is used that
writes error messages to <code>stderr</code>.
</p>
<h3 class="function"><a id="pdfioFileFindObj">pdfioFileFindObj</a></h3>

View File

@ -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)
@ -2364,8 +2385,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
// Write the xref table...
xref_offset = _pdfioFileTell(pdf);
// TODO: Figure out how to do xref streams with encrypted output
if (strcmp(pdf->version, "1.5") >= 0 && !pdf->output_cb && !pdf->encrypt_obj)
if (strcmp(pdf->version, "1.5") >= 0 && !pdf->output_cb)
{
// Write a cross-reference stream...
pdfio_dict_t *xref_dict; // Object dictionary
@ -2374,6 +2394,11 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
pdfio_stream_t *xref_st; // Stream
int offsize; // Size of object offsets
unsigned char buffer[10]; // Buffer entry
pdfio_encryption_t encryption; // PDF encryption mode
// Disable encryption while we write the xref stream...
encryption = pdf->encryption;
pdf->encryption = PDFIO_ENCRYPTION_NONE;
// Figure out how many bytes are needed for the object numbers
if (xref_offset < 0xff)
@ -2416,13 +2441,14 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
pdfioDictSetNumber(xref_dict, "Size", pdf->num_objs + 2);
pdfioDictSetArray(xref_dict, "W", w_array);
pdfioDictSetName(xref_dict, "Filter", "FlateDecode");
pdfioDictSetObj(xref_dict, "Info", pdf->info_obj);
pdfioDictSetObj(xref_dict, "Root", pdf->root_obj);
if (pdf->encrypt_obj)
pdfioDictSetObj(xref_dict, "Encrypt", pdf->encrypt_obj);
if (pdf->id_array)
pdfioDictSetArray(xref_dict, "ID", pdf->id_array);
pdfioDictSetObj(xref_dict, "Info", pdf->info_obj);
pdfioDictSetObj(xref_dict, "Root", pdf->root_obj);
if ((xref_obj = pdfioFileCreateObj(pdf, xref_dict)) == NULL)
{
@ -2514,6 +2540,8 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
}
pdfioStreamClose(xref_st);
pdf->encryption = encryption;
}
else
{

View File

@ -1,7 +1,7 @@
//
// PDF object functions for PDFio.
//
// Copyright © 2021-2024 by Michael R Sweet.
// Copyright © 2021-2025 by Michael R Sweet.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
// information.
@ -10,13 +10,6 @@
#include "pdfio-private.h"
//
// Local functions...
//
static bool write_obj_header(pdfio_obj_t *obj);
//
// 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF
// file.
@ -42,7 +35,7 @@ pdfioObjClose(pdfio_obj_t *obj) // I - Object
if (!obj->offset)
{
// Write the object value
if (!write_obj_header(obj))
if (!_pdfioObjWriteHeader(obj))
return (false);
// Write the "endobj" line...
@ -195,7 +188,7 @@ pdfioObjCreateStream(
}
}
if (!write_obj_header(obj))
if (!_pdfioObjWriteHeader(obj))
return (NULL);
if (!_pdfioFilePuts(obj->pdf, "stream\n"))
@ -205,7 +198,7 @@ pdfioObjCreateStream(
obj->pdf->current_obj = obj;
// Return the new stream...
return (_pdfioStreamCreate(obj, length_obj, filter));
return (_pdfioStreamCreate(obj, length_obj, 0, filter));
}
@ -582,11 +575,11 @@ _pdfioObjSetExtension(
//
// 'write_obj_header()' - Write the object header...
// '_pdfioObjWriteHeader()' - Write the object header...
//
static bool // O - `true` on success, `false` on failure
write_obj_header(pdfio_obj_t *obj) // I - Object
bool // O - `true` on success, `false` on failure
_pdfioObjWriteHeader(pdfio_obj_t *obj) // I - Object
{
obj->offset = _pdfioFileTell(obj->pdf);

View File

@ -1,7 +1,7 @@
//
// Private header file for PDFio.
//
// Copyright © 2021-2024 by Michael R Sweet.
// Copyright © 2021-2025 by Michael R Sweet.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
// information.
@ -107,7 +107,7 @@ typedef enum _pdfio_mode_e // Read/write mode
typedef enum _pdfio_predictor_e // PNG predictor constants
{
_PDFIO_PREDICTOR_NONE = 1, // No predictor (default)
_PDFIO_PREDICTOR_TIFF2 = 2, // TIFF2 predictor (???)
_PDFIO_PREDICTOR_TIFF2 = 2, // TIFF predictor 2 (difference from left neighbor)
_PDFIO_PREDICTOR_PNG_NONE = 10, // PNG None predictor (same as `_PDFIO_PREDICTOR_NONE`)
_PDFIO_PREDICTOR_PNG_SUB = 11, // PNG Sub predictor
_PDFIO_PREDICTOR_PNG_UP = 12, // PNG Up predictor
@ -313,8 +313,9 @@ struct _pdfio_stream_s // Stream
z_stream flate; // Flate filter state
_pdfio_predictor_t predictor; // Predictor function, if any
size_t pbpixel, // Size of a pixel in bytes
pbsize; // Predictor buffer size, if any
unsigned char cbuffer[4096], // Compressed data buffer
pbsize, // Predictor buffer size, if any
cbsize; // Compressed data buffer size
unsigned char *cbuffer, // Compressed data buffer
*prbuffer, // Raw buffer (previous line), as needed
*psbuffer; // PNG filter buffer, as needed
_pdfio_crypto_cb_t crypto_cb; // Encryption/descryption callback, if any
@ -383,8 +384,9 @@ extern void _pdfioObjDelete(pdfio_obj_t *obj) _PDFIO_INTERNAL;
extern void *_pdfioObjGetExtension(pdfio_obj_t *obj) _PDFIO_INTERNAL;
extern bool _pdfioObjLoad(pdfio_obj_t *obj) _PDFIO_INTERNAL;
extern void _pdfioObjSetExtension(pdfio_obj_t *obj, void *data, _pdfio_extfree_t datafree) _PDFIO_INTERNAL;
extern bool _pdfioObjWriteHeader(pdfio_obj_t *obj) _PDFIO_INTERNAL;
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, pdfio_filter_t compression) _PDFIO_INTERNAL;
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, size_t cbsize, pdfio_filter_t compression) _PDFIO_INTERNAL;
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;

View File

@ -50,7 +50,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
while ((status = deflate(&st->flate, Z_FINISH)) != Z_STREAM_END)
{
size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out,
size_t bytes = st->cbsize - st->flate.avail_out,
// Bytes to write
outbytes; // Actual bytes written
@ -89,13 +89,13 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
}
st->flate.next_out = (Bytef *)st->cbuffer + bytes;
st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - bytes);
st->flate.avail_out = (uInt)(st->cbsize - bytes);
}
if (st->flate.avail_out < (uInt)sizeof(st->cbuffer))
if (st->flate.avail_out < (uInt)st->cbsize)
{
// Write any residuals...
size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out;
size_t bytes = st->cbsize - st->flate.avail_out;
// Bytes to write
if (st->crypto_cb)
@ -172,6 +172,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
st->pdf->current_obj = NULL;
free(st->cbuffer);
free(st->prbuffer);
free(st->psbuffer);
free(st);
@ -190,6 +191,7 @@ pdfio_stream_t * // O - Stream or `NULL` on error
_pdfioStreamCreate(
pdfio_obj_t *obj, // I - Object
pdfio_obj_t *length_obj, // I - Length object, if any
size_t cbsize, // I - Size of compression buffer
pdfio_filter_t compression) // I - Compression to apply
{
pdfio_stream_t *st; // Stream
@ -302,8 +304,21 @@ _pdfioStreamCreate(
else
st->predictor = _PDFIO_PREDICTOR_NONE;
if (cbsize == 0)
cbsize = 4096;
st->cbsize = cbsize;
if ((st->cbuffer = malloc(cbsize)) == NULL)
{
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Flate output buffer: %s", (unsigned long)cbsize, strerror(errno));
free(st->prbuffer);
free(st->psbuffer);
free(st);
return (NULL);
}
st->flate.next_out = (Bytef *)st->cbuffer;
st->flate.avail_out = (uInt)sizeof(st->cbuffer);
st->flate.avail_out = (uInt)cbsize;
if ((status = deflateInit(&(st->flate), 9)) != Z_OK)
{
@ -567,11 +582,21 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
else
st->predictor = _PDFIO_PREDICTOR_NONE;
st->cbsize = 4096;
if ((st->cbuffer = malloc(st->cbsize)) == NULL)
{
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Flate compression buffer.", (unsigned long)st->cbsize);
free(st->prbuffer);
free(st->psbuffer);
free(st);
return (NULL);
}
PDFIO_DEBUG("_pdfioStreamOpen: pos=%ld\n", (long)_pdfioFileTell(st->pdf));
if (sizeof(st->cbuffer) > st->remaining)
if (st->cbsize > st->remaining)
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
else
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
if (rbytes <= 0)
{
@ -1045,10 +1070,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
if (st->flate.avail_in == 0)
{
// Read more from the file...
if (sizeof(st->cbuffer) > st->remaining)
if (st->cbsize > st->remaining)
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
else
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
if (rbytes <= 0)
return (-1); // End of file...
@ -1101,10 +1126,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
if (st->flate.avail_in == 0)
{
// Read more from the file...
if (sizeof(st->cbuffer) > st->remaining)
if (st->cbsize > st->remaining)
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
else
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
if (rbytes <= 0)
return (-1); // End of file...
@ -1171,10 +1196,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
if (st->flate.avail_in == 0)
{
// Read more from the file...
if (sizeof(st->cbuffer) > st->remaining)
if (st->cbsize > st->remaining)
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
else
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
if (rbytes <= 0)
return (-1); // End of file...
@ -1278,10 +1303,10 @@ stream_write(pdfio_stream_t *st, // I - Stream
while (st->flate.avail_in > 0)
{
if (st->flate.avail_out < (sizeof(st->cbuffer) / 8))
if (st->flate.avail_out < (st->cbsize / 8))
{
// Flush the compression buffer...
size_t cbytes = sizeof(st->cbuffer) - st->flate.avail_out,
size_t cbytes = st->cbsize - st->flate.avail_out,
outbytes;
if (st->crypto_cb)
@ -1310,7 +1335,7 @@ stream_write(pdfio_stream_t *st, // I - Stream
}
st->flate.next_out = (Bytef *)st->cbuffer + cbytes;
st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - cbytes);
st->flate.avail_out = (uInt)(st->cbsize - cbytes);
}
// Deflate what we can this time...