Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zfjbig2.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
18
/* this is the ps interpreter interface to the jbig2decode filter
19
   used for (1bpp) scanned image compression. PDF only specifies
20
   a decoder filter, and we don't currently implement anything else */
21
22
#include "memory_.h"
23
#include "ghost.h"
24
#include "oper.h"
25
#include "gsstruct.h"
26
#include "gstypes.h"
27
#include "ialloc.h"
28
#include "idict.h"
29
#include "store.h"
30
#include "stream.h"
31
#include "strimpl.h"
32
#include "ifilter.h"
33
34
#include "sjbig2.h"
35
36
/* We define a structure, s_jbig2_global_data_t,
37
   allocated in the postscript
38
   memory space, to hold a pointer to the global decoder
39
   context (which is allocated by libjbig2). This allows
40
   us to pass the reference through postscript code to
41
   the filter initializer. The opaque data pointer is not
42
   enumerated and will not be garbage collected. We use
43
   a finalize method to deallocate it when the reference
44
   is no longer in use. */
45
46
static void jbig2_global_data_finalize(const gs_memory_t *cmem, void *vptr);
47
gs_private_st_simple_final(st_jbig2_global_data_t, s_jbig2_global_data_t,
48
        "jbig2globaldata", jbig2_global_data_finalize);
49
50
/* <source> /JBIG2Decode <file> */
51
/* <source> <dict> /JBIG2Decode <file> */
52
static int
53
z_jbig2decode(i_ctx_t * i_ctx_p)
54
0
{
55
0
    os_ptr op = osp;
56
0
    ref *sop = NULL;
57
0
    s_jbig2_global_data_t *gref;
58
0
    stream_jbig2decode_state state;
59
60
    /* Extract the global context reference, if any, from the parameter
61
       dictionary and embed it in our stream state. The original object
62
       ref is under the JBIG2Globals key.
63
       We expect the postscript code to resolve this and call
64
       z_jbig2makeglobalctx() below to create an astruct wrapping the
65
       global decoder data and store it under the .jbig2globalctx key
66
     */
67
0
    s_jbig2decode_set_global_data((stream_state*)&state, NULL, NULL);
68
0
    if (r_has_type(op, t_dictionary)) {
69
0
        check_dict_read(*op);
70
0
        if ( dict_find_string(op, ".jbig2globalctx", &sop) > 0) {
71
0
            if (!r_is_struct(sop) || !r_has_stype(sop, imemory, st_jbig2_global_data_t))
72
0
                return_error(gs_error_typecheck);
73
0
            gref = r_ptr(sop, s_jbig2_global_data_t);
74
0
            s_jbig2decode_set_global_data((stream_state*)&state, gref, gref->data);
75
0
        }
76
0
    }
77
78
    /* we pass npop=0, since we've no arguments left to consume */
79
0
    return filter_read(i_ctx_p, 0, &s_jbig2decode_template,
80
0
                       (stream_state *) & state, (sop ? r_space(sop) : 0));
81
0
}
82
83
/* <bytestring> .jbig2makeglobalctx <jbig2globalctx> */
84
/* we call this from ps code to instantiate a jbig2_global_context
85
   object which the JBIG2Decode filter uses if available. The
86
   pointer to the global context is stored in an astruct object
87
   and returned that way since it lives outside the interpreters
88
   memory management */
89
static int
90
z_jbig2makeglobalctx(i_ctx_t * i_ctx_p)
91
0
{
92
0
        void *global = NULL;
93
0
        s_jbig2_global_data_t *st;
94
0
        os_ptr op = osp;
95
0
        byte *data;
96
0
        int size;
97
0
        int code = 0;
98
99
0
        check_type(*op, t_astruct);
100
0
        size = gs_object_size(imemory, op->value.pstruct);
101
0
        data = r_ptr(op, byte);
102
103
0
        code = s_jbig2decode_make_global_data(imemory->non_gc_memory, data, size,
104
0
                        &global);
105
0
        if (size > 0 && global == NULL) {
106
0
            dmlprintf(imemory, "failed to create parsed JBIG2GLOBALS object.");
107
0
            return_error(gs_error_unknownerror);
108
0
        }
109
110
0
        st = ialloc_struct(s_jbig2_global_data_t,
111
0
                &st_jbig2_global_data_t,
112
0
                "jbig2decode parsed global context");
113
0
        if (st == NULL) return_error(gs_error_VMerror);
114
115
0
        st->data = global;
116
0
        make_astruct(op, a_readonly | icurrent_space, (byte*)st);
117
118
0
        return code;
119
0
}
120
121
/* free our referenced global context data */
122
static void jbig2_global_data_finalize(const gs_memory_t *cmem, void *vptr)
123
0
{
124
0
        s_jbig2_global_data_t *st = vptr;
125
0
        (void)cmem; /* unused */
126
127
0
        if (st->data) s_jbig2decode_free_global_data(st->data);
128
0
        st->data = NULL;
129
0
}
130
131
/* Match the above routine to the corresponding filter name.
132
   This is how our static routines get called externally. */
133
const op_def zfjbig2_op_defs[] = {
134
    {"1.jbig2makeglobalctx", z_jbig2makeglobalctx},
135
    op_def_begin_filter(),
136
    {"2JBIG2Decode", z_jbig2decode},
137
    op_def_end(0)
138
};