/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 | | }; |