PDF-Make

 view release on metacpan or  search on metacpan

src/pdfmake_interpreter.c  view on Meta::CPAN

    pdfmake_err_t err;
    pdfmake_obj_t *saved_resources;
    int saved_in_text;
    pdfmake_obj_t stream_dict;
    uint32_t matrix_k;
    pdfmake_obj_t *mat;
    uint32_t res_k;
    pdfmake_obj_t *form_res;
    int i;

    if (!form || form->kind != PDFMAKE_STREAM) return PDFMAKE_OK;

    if (interp->form_depth >= 32) {
        /* Cycle guard — spec doesn't allow cycles; silently stop. */
        return PDFMAKE_OK;
    }

    /* Decode the form's content stream (decrypt + FlateDecode). */
    if (pdfmake_buf_init(&content) != PDFMAKE_OK) return PDFMAKE_ENOMEM;

    err = PDFMAKE_OK;
    if (interp->reader && form_num > 0) {
        err = pdfmake_reader_resolve_stream(
            (pdfmake_reader_t *)interp->reader, form_num, form_gen, &content);
    } else {
        /* No reader attached: use parser-level decode without decryption.
         * Will likely fail for encrypted PDFs but works for simple ones. */
        err = PDFMAKE_EINVAL;
    }

    if (err != PDFMAKE_OK || pdfmake_buf_len(&content) == 0) {
        pdfmake_buf_free(&content);
        return PDFMAKE_OK;
    }

    /* Save state: push gstate, stash current resources. */
    gstate_push(interp);
    saved_resources = interp->resources;
    saved_in_text = interp->in_text_object;
    interp->in_text_object = 0;

    /* Apply form's /Matrix to CTM (default = identity). */
    stream_dict.kind = PDFMAKE_DICT;
    stream_dict.as.dict = form->as.stream->dict;

    matrix_k = pdfmake_arena_intern_name(interp->arena, "Matrix", 6);
    mat = pdfmake_dict_get(&stream_dict, matrix_k);
    if (mat && mat->kind == PDFMAKE_ARRAY && pdfmake_array_len(mat) == 6) {
        double m[6];
        for (i = 0; i < 6; i++) {
            pdfmake_obj_t *v = pdfmake_array_get(mat, i);
            if (!v) { m[i] = 0; continue; }
            if (v->kind == PDFMAKE_INT)       m[i] = (double)v->as.i;
            else if (v->kind == PDFMAKE_REAL) m[i] = v->as.r;
            else                              m[i] = 0;
        }
        /* CTM = form_matrix × CTM */
        pdfmake_matrix_multiply(interp->gs->ctm, m, interp->gs->ctm);
    }

    /* Swap resources: form's /Resources (if any) overlays. If the form has
     * no /Resources, keep the outer page's — matches §7.8.3 "If the form
     * XObject does not have its own Resources dictionary, the form uses
     * the page's". */
    res_k = pdfmake_arena_intern_name(interp->arena, "Resources", 9);
    form_res = pdfmake_dict_get(&stream_dict, res_k);
    if (form_res && form_res->kind == PDFMAKE_REF && interp->reader) {
        pdfmake_reader_t *rd = (pdfmake_reader_t *)interp->reader;
        if (rd->parser)
            form_res = pdfmake_parser_resolve(rd->parser, form_res->as.ref);
    }
    if (form_res && form_res->kind == PDFMAKE_DICT) {
        interp->resources = form_res;
    }

    /* Recurse with the already-initialized interpreter */
    interp->form_depth++;
    (void)parse_content_stream(interp,
                               pdfmake_buf_data(&content),
                               pdfmake_buf_len(&content));
    interp->form_depth--;

    /* Restore */
    interp->in_text_object = saved_in_text;
    interp->resources = saved_resources;
    gstate_pop(interp);

    pdfmake_buf_free(&content);
    return PDFMAKE_OK;
}

/* Do - Paint XObject */
static pdfmake_err_t op_Do(pdfmake_interp_t *interp) {
    pdfmake_obj_t name = pop_operand(interp);
    uint32_t xobj_num;
    uint16_t xobj_gen;
    pdfmake_obj_t *xobj;

    if (name.kind != PDFMAKE_NAME) {
        return PDFMAKE_OK;
    }

    xobj_num = 0;
    xobj_gen = 0;
    xobj = lookup_xobject_with_ref(interp, name.as.name.id,
                                    &xobj_num, &xobj_gen);
    if (!xobj) {
        return PDFMAKE_OK;
    }

    /* Check subtype */
    if (xobj->kind == PDFMAKE_STREAM) {
        /* Get /Subtype from stream dict */
        uint32_t subtype_id = pdfmake_arena_intern_name(interp->arena, "Subtype", 7);
        pdfmake_obj_t stream_dict;
        pdfmake_obj_t *subtype;
        stream_dict.kind = PDFMAKE_DICT;
        stream_dict.as.dict = xobj->as.stream->dict;
        subtype = pdfmake_dict_get(&stream_dict, subtype_id);

        if (subtype && subtype->kind == PDFMAKE_NAME) {



( run in 1.343 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )