mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-02-26 13:52:49 +01:00
Add xref stream support (Issue #10)
This commit is contained in:
parent
8d72f22efe
commit
aeee24b856
@ -6,6 +6,8 @@ v1.5.0 - YYYY-MM-DD
|
||||
|
||||
- Added support for embedded color profiles in JPEG images (Issue #7)
|
||||
- Added `pdfioFileCreateICCObjFromData` API.
|
||||
- Added support for writing cross-reference streams for PDF 1.5 and newer files
|
||||
(Issue #10)
|
||||
- Added `pdfioFileGetModDate()` API (Issue #88)
|
||||
- Added support for using libpng to embed PNG images in PDF output (Issue #90)
|
||||
- Now support opening damaged PDF files (Issue #45)
|
||||
|
159
pdfio-file.c
159
pdfio-file.c
@ -2358,12 +2358,166 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
||||
bool ret = true; // Return value
|
||||
off_t xref_offset; // Offset to xref table
|
||||
size_t i; // Looping var
|
||||
pdfio_obj_t *obj; // Current object
|
||||
|
||||
|
||||
// Write the xref table...
|
||||
// TODO: Look at adding support for xref streams...
|
||||
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)
|
||||
{
|
||||
// Write a cross-reference stream...
|
||||
pdfio_dict_t *xref_dict; // Object dictionary
|
||||
pdfio_array_t *w_array; // W array
|
||||
pdfio_obj_t *xref_obj; // Object
|
||||
pdfio_stream_t *xref_st; // Stream
|
||||
int offsize; // Size of object offsets
|
||||
unsigned char buffer[10]; // Buffer entry
|
||||
|
||||
// Figure out how many bytes are needed for the object numbers
|
||||
if (xref_offset < 0xff)
|
||||
offsize = 1;
|
||||
else if (xref_offset < 0xffff)
|
||||
offsize = 2;
|
||||
else if (xref_offset < 0xffffff)
|
||||
offsize = 3;
|
||||
else if (xref_offset < 0xffffffff)
|
||||
offsize = 4;
|
||||
else if (xref_offset < 0xffffffffff)
|
||||
offsize = 5;
|
||||
else if (xref_offset < 0xffffffffffff)
|
||||
offsize = 6;
|
||||
else if (xref_offset < 0xffffffffffffff)
|
||||
offsize = 7;
|
||||
else
|
||||
offsize = 8;
|
||||
|
||||
// Create the object...
|
||||
if ((w_array = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pdfioArrayAppendNumber(w_array, 1);
|
||||
pdfioArrayAppendNumber(w_array, offsize);
|
||||
pdfioArrayAppendNumber(w_array, 1);
|
||||
|
||||
if ((xref_dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pdfioDictSetName(xref_dict, "Type", "XRef");
|
||||
pdfioDictSetNumber(xref_dict, "Size", pdf->num_objs + 2);
|
||||
pdfioDictSetArray(xref_dict, "W", w_array);
|
||||
pdfioDictSetName(xref_dict, "Filter", "FlateDecode");
|
||||
|
||||
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)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xref_st = pdfioObjCreateStream(xref_obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Write the "free" 0 object...
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
pdfioStreamWrite(xref_st, buffer, offsize + 2);
|
||||
|
||||
// Then write the "allocated" objects...
|
||||
buffer[0] = 1;
|
||||
|
||||
for (i = 0; i < pdf->num_objs; i ++)
|
||||
{
|
||||
obj = pdf->objs[i]; // Current object
|
||||
|
||||
switch (offsize)
|
||||
{
|
||||
case 1 :
|
||||
buffer[1] = obj->offset & 255;
|
||||
break;
|
||||
case 2 :
|
||||
buffer[1] = (obj->offset >> 8) & 255;
|
||||
buffer[2] = obj->offset & 255;
|
||||
break;
|
||||
case 3 :
|
||||
buffer[1] = (obj->offset >> 16) & 255;
|
||||
buffer[2] = (obj->offset >> 8) & 255;
|
||||
buffer[3] = obj->offset & 255;
|
||||
break;
|
||||
case 4 :
|
||||
buffer[1] = (obj->offset >> 24) & 255;
|
||||
buffer[2] = (obj->offset >> 16) & 255;
|
||||
buffer[3] = (obj->offset >> 8) & 255;
|
||||
buffer[4] = obj->offset & 255;
|
||||
break;
|
||||
case 5 :
|
||||
buffer[1] = (obj->offset >> 32) & 255;
|
||||
buffer[2] = (obj->offset >> 24) & 255;
|
||||
buffer[3] = (obj->offset >> 16) & 255;
|
||||
buffer[4] = (obj->offset >> 8) & 255;
|
||||
buffer[5] = obj->offset & 255;
|
||||
break;
|
||||
case 6 :
|
||||
buffer[1] = (obj->offset >> 40) & 255;
|
||||
buffer[2] = (obj->offset >> 32) & 255;
|
||||
buffer[3] = (obj->offset >> 24) & 255;
|
||||
buffer[4] = (obj->offset >> 16) & 255;
|
||||
buffer[5] = (obj->offset >> 8) & 255;
|
||||
buffer[6] = obj->offset & 255;
|
||||
break;
|
||||
case 7 :
|
||||
buffer[1] = (obj->offset >> 48) & 255;
|
||||
buffer[2] = (obj->offset >> 40) & 255;
|
||||
buffer[3] = (obj->offset >> 32) & 255;
|
||||
buffer[4] = (obj->offset >> 24) & 255;
|
||||
buffer[5] = (obj->offset >> 16) & 255;
|
||||
buffer[6] = (obj->offset >> 8) & 255;
|
||||
buffer[7] = obj->offset & 255;
|
||||
break;
|
||||
default :
|
||||
buffer[1] = (obj->offset >> 56) & 255;
|
||||
buffer[2] = (obj->offset >> 48) & 255;
|
||||
buffer[3] = (obj->offset >> 40) & 255;
|
||||
buffer[4] = (obj->offset >> 32) & 255;
|
||||
buffer[5] = (obj->offset >> 24) & 255;
|
||||
buffer[6] = (obj->offset >> 16) & 255;
|
||||
buffer[7] = (obj->offset >> 8) & 255;
|
||||
buffer[8] = obj->offset & 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pdfioStreamWrite(xref_st, buffer, offsize + 2))
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
pdfioStreamClose(xref_st);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write a cross-reference table...
|
||||
if (!_pdfioFilePrintf(pdf, "xref\n0 %lu \n0000000000 65535 f \n", (unsigned long)pdf->num_objs + 1))
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to write cross-reference table.");
|
||||
@ -2373,7 +2527,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
||||
|
||||
for (i = 0; i < pdf->num_objs; i ++)
|
||||
{
|
||||
pdfio_obj_t *obj = pdf->objs[i]; // Current object
|
||||
obj = pdf->objs[i]; // Current object
|
||||
|
||||
if (!_pdfioFilePrintf(pdf, "%010lu %05u n \n", (unsigned long)obj->offset, obj->generation))
|
||||
{
|
||||
@ -2412,6 +2566,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_pdfioFilePrintf(pdf, "\nstartxref\n%lu\n%%EOF\n", (unsigned long)xref_offset))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user