PDF-Make
view release on metacpan or search on metacpan
src/pdfmake_page.c view on Meta::CPAN
if (!pdfmake_stream_set_data(arena, &stream, data, len)) {
return PDFMAKE_ENOMEM;
}
/* Add as indirect object */
contents_num = pdfmake_doc_add(doc, stream);
if (contents_num == 0) return PDFMAKE_ENOMEM;
page->contents_num = contents_num;
page->has_content = 1;
return PDFMAKE_OK;
}
pdfmake_err_t pdfmake_page_set_content_str(pdfmake_page_t *page,
const char *content) {
if (!content) return PDFMAKE_EINVAL;
return pdfmake_page_set_content(page, (const uint8_t *)content, strlen(content));
}
pdfmake_err_t pdfmake_page_append_content(pdfmake_page_t *page,
const uint8_t *data,
size_t len)
{
pdfmake_doc_t *doc;
pdfmake_arena_t *arena;
pdfmake_obj_t *existing;
pdfmake_stream_t *stm;
const uint8_t *old_bytes;
size_t old_len;
size_t cap;
uint8_t *combined;
size_t off;
if (!page || !data) return PDFMAKE_EINVAL;
if (!page->has_content || page->contents_num == 0) {
return pdfmake_page_set_content(page, data, len);
}
doc = page->doc;
arena = pdfmake_doc_arena(doc);
/* Fetch the existing content stream so we can concatenate. Its raw
* bytes may be compressed (e.g. /Filter /FlateDecode imported from a
* source PDF); we decompress before concatenating so the combined
* stream is plain and we don't have to synthesize the filter chain. */
existing = pdfmake_doc_get(doc, page->contents_num);
if (!existing || existing->kind != PDFMAKE_STREAM) {
return pdfmake_page_set_content(page, data, len);
}
/* Use the stream's raw bytes directly. Pages created via
* pdfmake_page_set_content always store plain (unfiltered) content,
* and pdfmake_doc_import_page feeds pre-decoded bytes in through the
* same path â so the raw pointer is the content we need, regardless
* of how the page was built. */
stm = existing->as.stream;
old_bytes = stm->raw;
old_len = stm->raw_len;
/* Build `<<existing>>\nq\n<<overlay>>\nQ\n` so overlay starts from a
* clean graphics state but the existing content is preserved. */
cap = old_len + 1 + 2 + 1 + len + 1 + 2 + 1;
combined = pdfmake_arena_alloc(arena, cap);
if (!combined) return PDFMAKE_ENOMEM;
off = 0;
memcpy(combined + off, old_bytes, old_len); off += old_len;
if (old_len == 0 || old_bytes[old_len - 1] != '\n') combined[off++] = '\n';
combined[off++] = 'q'; combined[off++] = '\n';
memcpy(combined + off, data, len); off += len;
if (len == 0 || data[len - 1] != '\n') combined[off++] = '\n';
combined[off++] = 'Q'; combined[off++] = '\n';
return pdfmake_page_set_content(page, combined, off);
}
/*----------------------------------------------------------------------------
* Internal: build Resources dictionary for a page
*--------------------------------------------------------------------------*/
static pdfmake_obj_t build_resources_dict(pdfmake_page_t *page) {
pdfmake_doc_t *doc = page->doc;
pdfmake_arena_t *arena = pdfmake_doc_arena(doc);
pdfmake_obj_t resources;
pdfmake_obj_t font_dict;
pdfmake_obj_t xobj_dict;
pdfmake_obj_t prop_dict;
pdfmake_obj_t gs_dict;
size_t i;
uint32_t font_key;
uint32_t xobj_key;
uint32_t prop_key;
uint32_t gs_key;
resources = pdfmake_dict_new(arena);
if (resources.kind != PDFMAKE_DICT) return resources;
/* Build /Font subdictionary if page has fonts */
if (page->font_count > 0) {
font_dict = pdfmake_dict_new(arena);
if (font_dict.kind != PDFMAKE_DICT) return font_dict;
for (i = 0; i < page->font_count; i++) {
pdfmake_font_entry_t *entry = &page->fonts[i];
uint32_t key = pdfmake_arena_intern_name(arena, entry->name, strlen(entry->name));
pdfmake_obj_t ref = pdfmake_ref(entry->font_num, 0);
pdfmake_dict_set(arena, &font_dict, key, ref);
}
font_key = pdfmake_arena_intern_name(arena, "Font", 4);
pdfmake_dict_set(arena, &resources, font_key, font_dict);
}
/* Build /XObject subdictionary if page has images */
if (page->image_count > 0) {
xobj_dict = pdfmake_dict_new(arena);
if (xobj_dict.kind != PDFMAKE_DICT) return xobj_dict;
for (i = 0; i < page->image_count; i++) {
pdfmake_image_entry_t *entry = &page->images[i];
( run in 0.463 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )