2021-04-10 14:00:52 +02:00
|
|
|
|
//
|
2021-04-17 02:41:46 +02:00
|
|
|
|
// PDF object functions for pdfio.
|
2021-04-10 14:00:52 +02:00
|
|
|
|
//
|
|
|
|
|
// Copyright © 2021 by Michael R Sweet.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
|
|
|
|
// information.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Include necessary headers...
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "pdfio-private.h"
|
2021-04-17 02:41:46 +02:00
|
|
|
|
|
|
|
|
|
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF
|
|
|
|
|
// file.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
pdfioObjClose(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-28 03:22:34 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)obj;
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
return (false);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// 'pdfioObjCreateStream()' - Create an object (data) stream for writing.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
pdfio_stream_t * // O - Stream or `NULL` on error
|
|
|
|
|
pdfioObjCreateStream(
|
|
|
|
|
pdfio_obj_t *obj, // I - Object
|
|
|
|
|
pdfio_filter_t filter) // I - Type of compression to apply
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-28 03:22:34 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)obj;
|
|
|
|
|
(void)filter;
|
|
|
|
|
|
|
|
|
|
return (NULL);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// '_pdfioObjDelete()' - Free memory used by an object.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
void
|
2021-04-28 03:22:34 +02:00
|
|
|
|
_pdfioObjDelete(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-26 16:42:01 +02:00
|
|
|
|
if (obj)
|
|
|
|
|
pdfioStreamClose(obj->stream);
|
|
|
|
|
|
|
|
|
|
free(obj);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// 'pdfioObjGetDict()' - Get the dictionary associated with an object.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
pdfio_dict_t * // O - Dictionary or `NULL` on error
|
|
|
|
|
pdfioObjGetDict(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-05-05 03:31:58 +02:00
|
|
|
|
if (!obj)
|
|
|
|
|
return (NULL);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
|
2021-05-05 03:31:58 +02:00
|
|
|
|
if (obj->value.type == PDFIO_VALTYPE_NONE)
|
|
|
|
|
_pdfioObjLoad(obj);
|
|
|
|
|
|
|
|
|
|
if (obj->value.type == PDFIO_VALTYPE_DICT)
|
|
|
|
|
return (obj->value.value.dict);
|
|
|
|
|
else
|
|
|
|
|
return (NULL);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-28 03:22:34 +02:00
|
|
|
|
// 'pdfioObjGetGeneration()' - Get the object's generation number.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-05-01 17:41:43 +02:00
|
|
|
|
unsigned short // O - Generation number (0 to 65535)
|
2021-04-28 03:22:34 +02:00
|
|
|
|
pdfioObjGetGeneration(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-28 03:22:34 +02:00
|
|
|
|
return (obj ? obj->generation : 0);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-28 03:22:34 +02:00
|
|
|
|
// 'pdfioObjGetNumber()' - Get the object's number.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
size_t // O - Object number (1 to 9999999999)
|
|
|
|
|
pdfioObjGetNumber(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-28 03:22:34 +02:00
|
|
|
|
return (obj ? obj->number : 0);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-28 03:22:34 +02:00
|
|
|
|
// 'pdfioObjGetType()' - Get an object's type.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
const char * // O - Object type
|
|
|
|
|
pdfioObjGetType(pdfio_obj_t *obj) // I - Object
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-05-05 03:31:58 +02:00
|
|
|
|
pdfio_dict_t *dict; // Object dictionary
|
2021-04-17 03:09:43 +02:00
|
|
|
|
|
|
|
|
|
|
2021-05-05 03:31:58 +02:00
|
|
|
|
if ((dict = pdfioObjGetDict(obj)) == NULL)
|
|
|
|
|
return (NULL);
|
|
|
|
|
else
|
|
|
|
|
return (pdfioDictGetName(dict, "Type"));
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
2021-05-04 23:04:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-05-05 03:31:58 +02:00
|
|
|
|
// '_pdfioObjLoad()' - Load an object dictionary/value.
|
2021-05-04 23:04:09 +02:00
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` otherwise
|
|
|
|
|
_pdfioObjLoad(pdfio_obj_t *obj) // I - Object
|
|
|
|
|
{
|
|
|
|
|
char line[1024], // Line from file
|
|
|
|
|
*ptr; // Pointer into line
|
2021-05-08 13:38:44 +02:00
|
|
|
|
_pdfio_token_t tb; // Token buffer/stack
|
2021-05-04 23:04:09 +02:00
|
|
|
|
|
|
|
|
|
|
2021-05-05 03:31:58 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioObjLoad(obj=%p(%lu)), offset=%lu\n", obj, (unsigned long)obj->number, (unsigned long)obj->offset);
|
|
|
|
|
|
2021-05-04 23:04:09 +02:00
|
|
|
|
// Seek to the start of the object and read its header...
|
|
|
|
|
if (_pdfioFileSeek(obj->pdf, obj->offset, SEEK_SET) != obj->offset)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Unable to seek to object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_pdfioFileGets(obj->pdf, line, sizeof(line)))
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Unable to read header for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strtoimax(line, &ptr, 10) != (intmax_t)obj->number)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Bad header for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strtol(ptr, &ptr, 10) != (long)obj->generation)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Bad header for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (isspace(*ptr & 255))
|
|
|
|
|
ptr ++;
|
|
|
|
|
|
|
|
|
|
if (strcmp(ptr, "obj"))
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Bad header for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Then grab the object value...
|
2021-05-08 13:38:44 +02:00
|
|
|
|
_pdfioTokenInit(&tb, obj->pdf, (_pdfio_tconsume_cb_t)_pdfioFileConsume, (_pdfio_tpeek_cb_t)_pdfioFilePeek, obj->pdf);
|
2021-05-05 03:31:58 +02:00
|
|
|
|
|
2021-05-08 13:38:44 +02:00
|
|
|
|
if (!_pdfioValueRead(obj->pdf, &tb, &obj->value))
|
2021-05-04 23:04:09 +02:00
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Unable to read value for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now see if there is an associated stream...
|
|
|
|
|
if (!_pdfioFileGets(obj->pdf, line, sizeof(line)))
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Early end-of-file for object %lu.", (unsigned long)obj->number);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp(line, "stream"))
|
|
|
|
|
{
|
|
|
|
|
// Yes, save its location...
|
|
|
|
|
obj->stream_offset = _pdfioFileTell(obj->pdf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
2021-05-05 03:31:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 'pdfioObjOpenStream()' - Open an object's (data) stream for reading.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
pdfio_stream_t * // O - Stream or `NULL` on error
|
2021-05-06 22:07:58 +02:00
|
|
|
|
pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
|
|
|
|
bool decode) // I - Decode/decompress data?
|
2021-05-05 03:31:58 +02:00
|
|
|
|
{
|
2021-05-07 14:47:49 +02:00
|
|
|
|
// Range check input...
|
|
|
|
|
if (!obj)
|
|
|
|
|
return (NULL);
|
2021-05-05 03:31:58 +02:00
|
|
|
|
|
2021-05-07 14:47:49 +02:00
|
|
|
|
// Make sure we've loaded the object dictionary...
|
|
|
|
|
if (!obj->value.type)
|
|
|
|
|
{
|
|
|
|
|
if (!_pdfioObjLoad(obj))
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No stream if there is no dict or offset to a stream...
|
|
|
|
|
if (obj->value.type != PDFIO_VALTYPE_DICT || !obj->stream_offset)
|
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
|
|
// Open the stream...
|
|
|
|
|
return (_pdfioStreamOpen(obj, decode));
|
2021-05-05 03:31:58 +02:00
|
|
|
|
}
|