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 )