| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* pdfmake_interpreter.c - Content stream interpreter implementation |
|
3
|
|
|
|
|
|
|
* |
|
4
|
|
|
|
|
|
|
* Reference: PDF 32000-1:2008 |
|
5
|
|
|
|
|
|
|
* - §8.4 Graphics state |
|
6
|
|
|
|
|
|
|
* - §9.3 Text state parameters |
|
7
|
|
|
|
|
|
|
* - §9.4 Text objects |
|
8
|
|
|
|
|
|
|
* - Annex A Operators |
|
9
|
|
|
|
|
|
|
*/ |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#include "pdfmake_interpreter.h" |
|
12
|
|
|
|
|
|
|
#include "pdfmake_arena.h" |
|
13
|
|
|
|
|
|
|
#include "pdfmake_tokenizer.h" |
|
14
|
|
|
|
|
|
|
#include "pdfmake_reader.h" |
|
15
|
|
|
|
|
|
|
#include "pdfmake_parser.h" |
|
16
|
|
|
|
|
|
|
#include "pdfmake_buf.h" |
|
17
|
|
|
|
|
|
|
#include |
|
18
|
|
|
|
|
|
|
#include |
|
19
|
|
|
|
|
|
|
#include |
|
20
|
|
|
|
|
|
|
#include |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
/* Forward declaration — defined later in this file and used by interpret_form. */ |
|
23
|
|
|
|
|
|
|
static pdfmake_err_t parse_content_stream(pdfmake_interp_t *interp, |
|
24
|
|
|
|
|
|
|
const uint8_t *buf, size_t len); |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
/*============================================================================ |
|
27
|
|
|
|
|
|
|
* Constants |
|
28
|
|
|
|
|
|
|
*==========================================================================*/ |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#define OPERAND_STACK_INIT 32 |
|
31
|
|
|
|
|
|
|
#define PATH_INIT_CAP 64 |
|
32
|
|
|
|
|
|
|
#define MC_STACK_INIT 16 |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
/*============================================================================ |
|
35
|
|
|
|
|
|
|
* Matrix operations |
|
36
|
|
|
|
|
|
|
*==========================================================================*/ |
|
37
|
|
|
|
|
|
|
|
|
38
|
7424
|
|
|
|
|
|
void pdfmake_matrix_identity(double m[6]) { |
|
39
|
7424
|
|
|
|
|
|
m[0] = 1.0; m[1] = 0.0; |
|
40
|
7424
|
|
|
|
|
|
m[2] = 0.0; m[3] = 1.0; |
|
41
|
7424
|
|
|
|
|
|
m[4] = 0.0; m[5] = 0.0; |
|
42
|
7424
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
845
|
|
|
|
|
|
void pdfmake_matrix_copy(double dst[6], const double src[6]) { |
|
45
|
845
|
|
|
|
|
|
memcpy(dst, src, 6 * sizeof(double)); |
|
46
|
845
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
/* |
|
49
|
|
|
|
|
|
|
* Matrix multiplication for 3x3 affine matrices stored as [a b c d e f]: |
|
50
|
|
|
|
|
|
|
* | a b 0 | | a' b' 0 | | aa'+cb' ab'+db' 0 | |
|
51
|
|
|
|
|
|
|
* | c d 0 | × | c' d' 0 | = | ac'+cd' bc'+dd' 0 | |
|
52
|
|
|
|
|
|
|
* | e f 1 | | e' f' 1 | | ae'+cf'+e' be'+df'+f' 1 | |
|
53
|
|
|
|
|
|
|
*/ |
|
54
|
6641
|
|
|
|
|
|
void pdfmake_matrix_multiply(double result[6], const double a[6], const double b[6]) { |
|
55
|
|
|
|
|
|
|
double r[6]; |
|
56
|
6641
|
|
|
|
|
|
r[0] = a[0] * b[0] + a[1] * b[2]; |
|
57
|
6641
|
|
|
|
|
|
r[1] = a[0] * b[1] + a[1] * b[3]; |
|
58
|
6641
|
|
|
|
|
|
r[2] = a[2] * b[0] + a[3] * b[2]; |
|
59
|
6641
|
|
|
|
|
|
r[3] = a[2] * b[1] + a[3] * b[3]; |
|
60
|
6641
|
|
|
|
|
|
r[4] = a[4] * b[0] + a[5] * b[2] + b[4]; |
|
61
|
6641
|
|
|
|
|
|
r[5] = a[4] * b[1] + a[5] * b[3] + b[5]; |
|
62
|
6641
|
|
|
|
|
|
memcpy(result, r, 6 * sizeof(double)); |
|
63
|
6641
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
19
|
|
|
|
|
|
void pdfmake_matrix_concat(double m[6], const double other[6]) { |
|
66
|
19
|
|
|
|
|
|
pdfmake_matrix_multiply(m, m, other); |
|
67
|
19
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
6618
|
|
|
|
|
|
void pdfmake_matrix_translate(double m[6], double tx, double ty) { |
|
70
|
6618
|
|
|
|
|
|
pdfmake_matrix_identity(m); |
|
71
|
6618
|
|
|
|
|
|
m[4] = tx; |
|
72
|
6618
|
|
|
|
|
|
m[5] = ty; |
|
73
|
6618
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
0
|
|
|
|
|
|
void pdfmake_matrix_scale(double m[6], double sx, double sy) { |
|
76
|
0
|
|
|
|
|
|
pdfmake_matrix_identity(m); |
|
77
|
0
|
|
|
|
|
|
m[0] = sx; |
|
78
|
0
|
|
|
|
|
|
m[3] = sy; |
|
79
|
0
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
void pdfmake_matrix_rotate(double m[6], double angle) { |
|
82
|
0
|
|
|
|
|
|
double c = cos(angle); |
|
83
|
0
|
|
|
|
|
|
double s = sin(angle); |
|
84
|
0
|
|
|
|
|
|
m[0] = c; m[1] = s; |
|
85
|
0
|
|
|
|
|
|
m[2] = -s; m[3] = c; |
|
86
|
0
|
|
|
|
|
|
m[4] = 0; m[5] = 0; |
|
87
|
0
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
|
int pdfmake_matrix_invert(double result[6], const double m[6]) { |
|
90
|
|
|
|
|
|
|
double det; |
|
91
|
|
|
|
|
|
|
double inv_det; |
|
92
|
0
|
|
|
|
|
|
det = m[0] * m[3] - m[1] * m[2]; |
|
93
|
0
|
0
|
|
|
|
|
if (fabs(det) < 1e-10) return -1; /* Singular */ |
|
94
|
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
|
inv_det = 1.0 / det; |
|
96
|
0
|
|
|
|
|
|
result[0] = m[3] * inv_det; |
|
97
|
0
|
|
|
|
|
|
result[1] = -m[1] * inv_det; |
|
98
|
0
|
|
|
|
|
|
result[2] = -m[2] * inv_det; |
|
99
|
0
|
|
|
|
|
|
result[3] = m[0] * inv_det; |
|
100
|
0
|
|
|
|
|
|
result[4] = (m[2] * m[5] - m[3] * m[4]) * inv_det; |
|
101
|
0
|
|
|
|
|
|
result[5] = (m[1] * m[4] - m[0] * m[5]) * inv_det; |
|
102
|
0
|
|
|
|
|
|
return 0; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
|
void pdfmake_matrix_transform_point(const double m[6], double *x, double *y) { |
|
106
|
0
|
|
|
|
|
|
double px = *x, py = *y; |
|
107
|
0
|
|
|
|
|
|
*x = m[0] * px + m[2] * py + m[4]; |
|
108
|
0
|
|
|
|
|
|
*y = m[1] * px + m[3] * py + m[5]; |
|
109
|
0
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
/*============================================================================ |
|
112
|
|
|
|
|
|
|
* Graphics state helpers |
|
113
|
|
|
|
|
|
|
*==========================================================================*/ |
|
114
|
|
|
|
|
|
|
|
|
115
|
162
|
|
|
|
|
|
static void gstate_init(pdfmake_gstate_t *gs) { |
|
116
|
162
|
|
|
|
|
|
memset(gs, 0, sizeof(*gs)); |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
/* CTM = identity */ |
|
119
|
162
|
|
|
|
|
|
pdfmake_matrix_identity(gs->ctm); |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
/* Line state defaults (§8.4.3) */ |
|
122
|
162
|
|
|
|
|
|
gs->line_width = 1.0; |
|
123
|
162
|
|
|
|
|
|
gs->line_cap = PDFMAKE_CAP_BUTT; |
|
124
|
162
|
|
|
|
|
|
gs->line_join = PDFMAKE_JOIN_MITER; |
|
125
|
162
|
|
|
|
|
|
gs->miter_limit = 10.0; |
|
126
|
162
|
|
|
|
|
|
gs->dash_array = NULL; |
|
127
|
162
|
|
|
|
|
|
gs->dash_count = 0; |
|
128
|
162
|
|
|
|
|
|
gs->dash_phase = 0.0; |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
/* Color defaults - black */ |
|
131
|
162
|
|
|
|
|
|
gs->stroke_color.space = PDFMAKE_CS_GRAY; |
|
132
|
162
|
|
|
|
|
|
gs->stroke_color.components[0] = 0.0; |
|
133
|
162
|
|
|
|
|
|
gs->stroke_color.n_components = 1; |
|
134
|
162
|
|
|
|
|
|
gs->fill_color.space = PDFMAKE_CS_GRAY; |
|
135
|
162
|
|
|
|
|
|
gs->fill_color.components[0] = 0.0; |
|
136
|
162
|
|
|
|
|
|
gs->fill_color.n_components = 1; |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
/* Text state defaults (§9.3) */ |
|
139
|
162
|
|
|
|
|
|
gs->char_space = 0.0; |
|
140
|
162
|
|
|
|
|
|
gs->word_space = 0.0; |
|
141
|
162
|
|
|
|
|
|
gs->h_scale = 100.0; /* 100% */ |
|
142
|
162
|
|
|
|
|
|
gs->leading = 0.0; |
|
143
|
162
|
|
|
|
|
|
gs->font_size = 0.0; |
|
144
|
162
|
|
|
|
|
|
gs->render_mode = PDFMAKE_RENDER_FILL; |
|
145
|
162
|
|
|
|
|
|
gs->rise = 0.0; |
|
146
|
162
|
|
|
|
|
|
gs->font_name = 0; |
|
147
|
162
|
|
|
|
|
|
gs->font = NULL; |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
/* Text matrices = identity */ |
|
150
|
162
|
|
|
|
|
|
pdfmake_matrix_identity(gs->text_matrix); |
|
151
|
162
|
|
|
|
|
|
pdfmake_matrix_identity(gs->text_line_matrix); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
/* Other */ |
|
154
|
162
|
|
|
|
|
|
gs->clip_depth = 0; |
|
155
|
162
|
|
|
|
|
|
gs->flatness = 1.0; |
|
156
|
162
|
|
|
|
|
|
gs->rendering_intent = 0; |
|
157
|
162
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
|
|
159
|
42
|
|
|
|
|
|
static void gstate_copy(pdfmake_gstate_t *dst, const pdfmake_gstate_t *src) { |
|
160
|
|
|
|
|
|
|
/* Copy everything except dash array */ |
|
161
|
42
|
|
|
|
|
|
double *old_dash = dst->dash_array; |
|
162
|
42
|
|
|
|
|
|
memcpy(dst, src, sizeof(*dst)); |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
/* Deep copy dash array */ |
|
165
|
42
|
50
|
|
|
|
|
if (src->dash_array && src->dash_count > 0) { |
|
|
|
0
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
dst->dash_array = malloc(src->dash_count * sizeof(double)); |
|
167
|
0
|
0
|
|
|
|
|
if (dst->dash_array) { |
|
168
|
0
|
|
|
|
|
|
memcpy(dst->dash_array, src->dash_array, |
|
169
|
0
|
|
|
|
|
|
src->dash_count * sizeof(double)); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
} else { |
|
172
|
42
|
|
|
|
|
|
dst->dash_array = NULL; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
/* Free old dash array if it was allocated */ |
|
176
|
42
|
|
|
|
|
|
free(old_dash); |
|
177
|
42
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
162
|
|
|
|
|
|
static void gstate_cleanup(pdfmake_gstate_t *gs) { |
|
180
|
162
|
|
|
|
|
|
free(gs->dash_array); |
|
181
|
162
|
|
|
|
|
|
gs->dash_array = NULL; |
|
182
|
162
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
/*============================================================================ |
|
185
|
|
|
|
|
|
|
* Interpreter lifecycle |
|
186
|
|
|
|
|
|
|
*==========================================================================*/ |
|
187
|
|
|
|
|
|
|
|
|
188
|
60
|
|
|
|
|
|
pdfmake_interp_t *pdfmake_interp_new(pdfmake_arena_t *arena) { |
|
189
|
60
|
|
|
|
|
|
pdfmake_interp_t *interp = calloc(1, sizeof(*interp)); |
|
190
|
60
|
50
|
|
|
|
|
if (!interp) return NULL; |
|
191
|
|
|
|
|
|
|
|
|
192
|
60
|
|
|
|
|
|
interp->arena = arena; |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
/* Allocate graphics state stack */ |
|
195
|
60
|
|
|
|
|
|
interp->stack_cap = PDFMAKE_GSTATE_STACK_MAX; |
|
196
|
60
|
|
|
|
|
|
interp->stack = calloc(interp->stack_cap, sizeof(pdfmake_gstate_t)); |
|
197
|
60
|
50
|
|
|
|
|
if (!interp->stack) { |
|
198
|
0
|
|
|
|
|
|
free(interp); |
|
199
|
0
|
|
|
|
|
|
return NULL; |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
/* Initialize first state on stack */ |
|
203
|
60
|
|
|
|
|
|
interp->stack_size = 1; |
|
204
|
60
|
|
|
|
|
|
gstate_init(&interp->stack[0]); |
|
205
|
60
|
|
|
|
|
|
interp->gs = &interp->stack[0]; |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
/* Allocate operand stack */ |
|
208
|
60
|
|
|
|
|
|
interp->op_cap = OPERAND_STACK_INIT; |
|
209
|
60
|
|
|
|
|
|
interp->operands = calloc(interp->op_cap, sizeof(pdfmake_obj_t)); |
|
210
|
60
|
50
|
|
|
|
|
if (!interp->operands) { |
|
211
|
0
|
|
|
|
|
|
free(interp->stack); |
|
212
|
0
|
|
|
|
|
|
free(interp); |
|
213
|
0
|
|
|
|
|
|
return NULL; |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
/* Allocate path buffer */ |
|
217
|
60
|
|
|
|
|
|
interp->path_cap = PATH_INIT_CAP; |
|
218
|
60
|
|
|
|
|
|
interp->path = calloc(interp->path_cap, sizeof(pdfmake_path_segment_t)); |
|
219
|
60
|
50
|
|
|
|
|
if (!interp->path) { |
|
220
|
0
|
|
|
|
|
|
free(interp->operands); |
|
221
|
0
|
|
|
|
|
|
free(interp->stack); |
|
222
|
0
|
|
|
|
|
|
free(interp); |
|
223
|
0
|
|
|
|
|
|
return NULL; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
/* Allocate marked content stack */ |
|
227
|
60
|
|
|
|
|
|
interp->mc_cap = MC_STACK_INIT; |
|
228
|
60
|
|
|
|
|
|
interp->mc_stack = calloc(interp->mc_cap, sizeof(uint32_t)); |
|
229
|
60
|
50
|
|
|
|
|
if (!interp->mc_stack) { |
|
230
|
0
|
|
|
|
|
|
free(interp->path); |
|
231
|
0
|
|
|
|
|
|
free(interp->operands); |
|
232
|
0
|
|
|
|
|
|
free(interp->stack); |
|
233
|
0
|
|
|
|
|
|
free(interp); |
|
234
|
0
|
|
|
|
|
|
return NULL; |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
60
|
|
|
|
|
|
return interp; |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
60
|
|
|
|
|
|
void pdfmake_interp_free(pdfmake_interp_t *interp) { |
|
241
|
|
|
|
|
|
|
size_t i; |
|
242
|
60
|
50
|
|
|
|
|
if (!interp) return; |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
/* Clean up graphics states */ |
|
245
|
120
|
100
|
|
|
|
|
for (i = 0; i < interp->stack_size; i++) { |
|
246
|
60
|
|
|
|
|
|
gstate_cleanup(&interp->stack[i]); |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
|
|
249
|
60
|
|
|
|
|
|
free(interp->stack); |
|
250
|
60
|
|
|
|
|
|
free(interp->operands); |
|
251
|
60
|
|
|
|
|
|
free(interp->path); |
|
252
|
60
|
|
|
|
|
|
free(interp->mc_stack); |
|
253
|
60
|
|
|
|
|
|
free(interp); |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
60
|
|
|
|
|
|
void pdfmake_interp_set_resources(pdfmake_interp_t *interp, pdfmake_obj_t *resources) { |
|
257
|
60
|
50
|
|
|
|
|
if (interp) { |
|
258
|
60
|
|
|
|
|
|
interp->resources = resources; |
|
259
|
|
|
|
|
|
|
} |
|
260
|
60
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
60
|
|
|
|
|
|
void pdfmake_interp_set_visitor(pdfmake_interp_t *interp, const pdfmake_visitor_t *visitor) { |
|
263
|
60
|
50
|
|
|
|
|
if (interp) { |
|
264
|
60
|
|
|
|
|
|
interp->visitor = visitor; |
|
265
|
|
|
|
|
|
|
} |
|
266
|
60
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
60
|
|
|
|
|
|
void pdfmake_interp_set_reader(pdfmake_interp_t *interp, void *reader) { |
|
269
|
60
|
50
|
|
|
|
|
if (interp) interp->reader = reader; |
|
270
|
60
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
60
|
|
|
|
|
|
void pdfmake_interp_reset(pdfmake_interp_t *interp) { |
|
273
|
|
|
|
|
|
|
size_t i; |
|
274
|
60
|
50
|
|
|
|
|
if (!interp) return; |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
/* Clean up all graphics states */ |
|
277
|
120
|
100
|
|
|
|
|
for (i = 0; i < interp->stack_size; i++) { |
|
278
|
60
|
|
|
|
|
|
gstate_cleanup(&interp->stack[i]); |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
/* Reset to single identity state */ |
|
282
|
60
|
|
|
|
|
|
interp->stack_size = 1; |
|
283
|
60
|
|
|
|
|
|
gstate_init(&interp->stack[0]); |
|
284
|
60
|
|
|
|
|
|
interp->gs = &interp->stack[0]; |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
/* Clear other state */ |
|
287
|
60
|
|
|
|
|
|
interp->in_text_object = 0; |
|
288
|
60
|
|
|
|
|
|
interp->path_size = 0; |
|
289
|
60
|
|
|
|
|
|
interp->cur_x = interp->cur_y = 0; |
|
290
|
60
|
|
|
|
|
|
interp->have_cur_point = 0; |
|
291
|
60
|
|
|
|
|
|
interp->mc_depth = 0; |
|
292
|
60
|
|
|
|
|
|
interp->op_count = 0; |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
/* Clear error */ |
|
295
|
60
|
|
|
|
|
|
interp->last_err = PDFMAKE_OK; |
|
296
|
60
|
|
|
|
|
|
interp->errmsg[0] = '\0'; |
|
297
|
60
|
|
|
|
|
|
interp->erroffset = 0; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
|
|
300
|
0
|
|
|
|
|
|
const char *pdfmake_interp_errmsg(pdfmake_interp_t *interp) { |
|
301
|
0
|
0
|
|
|
|
|
return interp ? interp->errmsg : ""; |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
|
|
304
|
0
|
|
|
|
|
|
size_t pdfmake_interp_erroffset(pdfmake_interp_t *interp) { |
|
305
|
0
|
0
|
|
|
|
|
return interp ? interp->erroffset : 0; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
|
const pdfmake_gstate_t *pdfmake_interp_gstate(pdfmake_interp_t *interp) { |
|
309
|
0
|
0
|
|
|
|
|
return interp ? interp->gs : NULL; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
0
|
|
|
|
|
|
int pdfmake_interp_in_text_object(pdfmake_interp_t *interp) { |
|
313
|
0
|
0
|
|
|
|
|
return interp ? interp->in_text_object : 0; |
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
|
|
316
|
0
|
|
|
|
|
|
int pdfmake_interp_get_current_point(pdfmake_interp_t *interp, double *x, double *y) { |
|
317
|
0
|
0
|
|
|
|
|
if (!interp || !interp->have_cur_point) return 0; |
|
|
|
0
|
|
|
|
|
|
|
318
|
0
|
0
|
|
|
|
|
if (x) *x = interp->cur_x; |
|
319
|
0
|
0
|
|
|
|
|
if (y) *y = interp->cur_y; |
|
320
|
0
|
|
|
|
|
|
return 1; |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
/*============================================================================ |
|
324
|
|
|
|
|
|
|
* Error handling |
|
325
|
|
|
|
|
|
|
*==========================================================================*/ |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
static void set_error(pdfmake_interp_t *interp, pdfmake_err_t err, |
|
328
|
|
|
|
|
|
|
size_t offset, const char *msg) { |
|
329
|
0
|
|
|
|
|
|
interp->last_err = err; |
|
330
|
0
|
|
|
|
|
|
interp->erroffset = offset; |
|
331
|
0
|
0
|
|
|
|
|
if (msg) { |
|
332
|
0
|
|
|
|
|
|
strncpy(interp->errmsg, msg, sizeof(interp->errmsg) - 1); |
|
333
|
0
|
|
|
|
|
|
interp->errmsg[sizeof(interp->errmsg) - 1] = '\0'; |
|
334
|
|
|
|
|
|
|
} |
|
335
|
0
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
/*============================================================================ |
|
338
|
|
|
|
|
|
|
* Operand stack operations |
|
339
|
|
|
|
|
|
|
*==========================================================================*/ |
|
340
|
|
|
|
|
|
|
|
|
341
|
6072
|
|
|
|
|
|
static int push_operand(pdfmake_interp_t *interp, pdfmake_obj_t obj) { |
|
342
|
6072
|
50
|
|
|
|
|
if (interp->op_count >= interp->op_cap) { |
|
343
|
0
|
|
|
|
|
|
size_t new_cap = interp->op_cap * 2; |
|
344
|
0
|
|
|
|
|
|
pdfmake_obj_t *new_ops = realloc(interp->operands, |
|
345
|
|
|
|
|
|
|
new_cap * sizeof(pdfmake_obj_t)); |
|
346
|
0
|
0
|
|
|
|
|
if (!new_ops) return 0; |
|
347
|
0
|
|
|
|
|
|
interp->operands = new_ops; |
|
348
|
0
|
|
|
|
|
|
interp->op_cap = new_cap; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
6072
|
|
|
|
|
|
interp->operands[interp->op_count++] = obj; |
|
351
|
6072
|
|
|
|
|
|
return 1; |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
6072
|
|
|
|
|
|
static pdfmake_obj_t pop_operand(pdfmake_interp_t *interp) { |
|
355
|
6072
|
50
|
|
|
|
|
if (interp->op_count == 0) { |
|
356
|
0
|
|
|
|
|
|
return pdfmake_null(); |
|
357
|
|
|
|
|
|
|
} |
|
358
|
6072
|
|
|
|
|
|
return interp->operands[--interp->op_count]; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
static void clear_operands(pdfmake_interp_t *interp) { |
|
362
|
0
|
|
|
|
|
|
interp->op_count = 0; |
|
363
|
0
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
/* Helper to get numeric operand */ |
|
366
|
7838
|
|
|
|
|
|
static double get_number(pdfmake_obj_t obj) { |
|
367
|
7838
|
100
|
|
|
|
|
if (obj.kind == PDFMAKE_INT) return (double)obj.as.i; |
|
368
|
5151
|
50
|
|
|
|
|
if (obj.kind == PDFMAKE_REAL) return obj.as.r; |
|
369
|
0
|
|
|
|
|
|
return 0.0; |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
/*============================================================================ |
|
373
|
|
|
|
|
|
|
* Graphics state stack operations (q/Q) |
|
374
|
|
|
|
|
|
|
*==========================================================================*/ |
|
375
|
|
|
|
|
|
|
|
|
376
|
42
|
|
|
|
|
|
static pdfmake_err_t gstate_push(pdfmake_interp_t *interp) { |
|
377
|
|
|
|
|
|
|
pdfmake_gstate_t *new_gs; |
|
378
|
42
|
50
|
|
|
|
|
if (interp->stack_size >= PDFMAKE_GSTATE_STACK_MAX) { |
|
379
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ESTACK_OVER, 0, |
|
380
|
|
|
|
|
|
|
"Graphics state stack overflow"); |
|
381
|
0
|
|
|
|
|
|
return PDFMAKE_ESTACK_OVER; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
/* Deep copy current state to new top */ |
|
385
|
42
|
|
|
|
|
|
new_gs = &interp->stack[interp->stack_size]; |
|
386
|
42
|
|
|
|
|
|
gstate_init(new_gs); /* Initialize to clear any garbage */ |
|
387
|
42
|
|
|
|
|
|
gstate_copy(new_gs, interp->gs); |
|
388
|
|
|
|
|
|
|
|
|
389
|
42
|
|
|
|
|
|
interp->stack_size++; |
|
390
|
42
|
|
|
|
|
|
interp->gs = new_gs; |
|
391
|
|
|
|
|
|
|
|
|
392
|
42
|
|
|
|
|
|
return PDFMAKE_OK; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
42
|
|
|
|
|
|
static pdfmake_err_t gstate_pop(pdfmake_interp_t *interp) { |
|
396
|
42
|
50
|
|
|
|
|
if (interp->stack_size <= 1) { |
|
397
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ESTACK_UNDER, 0, |
|
398
|
|
|
|
|
|
|
"Graphics state stack underflow"); |
|
399
|
0
|
|
|
|
|
|
return PDFMAKE_ESTACK_UNDER; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
/* Clean up current state */ |
|
403
|
42
|
|
|
|
|
|
gstate_cleanup(interp->gs); |
|
404
|
|
|
|
|
|
|
|
|
405
|
42
|
|
|
|
|
|
interp->stack_size--; |
|
406
|
42
|
|
|
|
|
|
interp->gs = &interp->stack[interp->stack_size - 1]; |
|
407
|
|
|
|
|
|
|
|
|
408
|
42
|
|
|
|
|
|
return PDFMAKE_OK; |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
/*============================================================================ |
|
412
|
|
|
|
|
|
|
* Path operations |
|
413
|
|
|
|
|
|
|
*==========================================================================*/ |
|
414
|
|
|
|
|
|
|
|
|
415
|
127
|
|
|
|
|
|
static int path_ensure_cap(pdfmake_interp_t *interp, size_t need) { |
|
416
|
|
|
|
|
|
|
size_t new_cap; |
|
417
|
|
|
|
|
|
|
pdfmake_path_segment_t *new_path; |
|
418
|
127
|
50
|
|
|
|
|
if (interp->path_size + need > interp->path_cap) { |
|
419
|
0
|
|
|
|
|
|
new_cap = interp->path_cap * 2; |
|
420
|
0
|
0
|
|
|
|
|
while (new_cap < interp->path_size + need) new_cap *= 2; |
|
421
|
0
|
|
|
|
|
|
new_path = realloc(interp->path, |
|
422
|
|
|
|
|
|
|
new_cap * sizeof(pdfmake_path_segment_t)); |
|
423
|
0
|
0
|
|
|
|
|
if (!new_path) return 0; |
|
424
|
0
|
|
|
|
|
|
interp->path = new_path; |
|
425
|
0
|
|
|
|
|
|
interp->path_cap = new_cap; |
|
426
|
|
|
|
|
|
|
} |
|
427
|
127
|
|
|
|
|
|
return 1; |
|
428
|
|
|
|
|
|
|
} |
|
429
|
|
|
|
|
|
|
|
|
430
|
127
|
|
|
|
|
|
static void path_add_segment(pdfmake_interp_t *interp, pdfmake_path_segment_t seg) { |
|
431
|
127
|
50
|
|
|
|
|
if (path_ensure_cap(interp, 1)) { |
|
432
|
127
|
|
|
|
|
|
interp->path[interp->path_size++] = seg; |
|
433
|
|
|
|
|
|
|
} |
|
434
|
127
|
|
|
|
|
|
} |
|
435
|
|
|
|
|
|
|
|
|
436
|
127
|
|
|
|
|
|
static void path_clear(pdfmake_interp_t *interp) { |
|
437
|
127
|
|
|
|
|
|
interp->path_size = 0; |
|
438
|
127
|
|
|
|
|
|
interp->have_cur_point = 0; |
|
439
|
127
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
/*============================================================================ |
|
442
|
|
|
|
|
|
|
* Resource lookup |
|
443
|
|
|
|
|
|
|
*==========================================================================*/ |
|
444
|
|
|
|
|
|
|
|
|
445
|
380
|
|
|
|
|
|
static pdfmake_obj_t *lookup_resource(pdfmake_interp_t *interp, |
|
446
|
|
|
|
|
|
|
const char *category, |
|
447
|
|
|
|
|
|
|
uint32_t name_id) { |
|
448
|
|
|
|
|
|
|
uint32_t cat_id; |
|
449
|
|
|
|
|
|
|
pdfmake_obj_t *cat_dict; |
|
450
|
380
|
50
|
|
|
|
|
if (!interp->resources || interp->resources->kind != PDFMAKE_DICT) { |
|
|
|
50
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
|
return NULL; |
|
452
|
|
|
|
|
|
|
} |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
/* Get category dict */ |
|
455
|
380
|
|
|
|
|
|
cat_id = pdfmake_arena_intern_name(interp->arena, category, strlen(category)); |
|
456
|
380
|
|
|
|
|
|
cat_dict = pdfmake_dict_get(interp->resources, cat_id); |
|
457
|
380
|
50
|
|
|
|
|
if (!cat_dict || cat_dict->kind != PDFMAKE_DICT) { |
|
|
|
50
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
|
return NULL; |
|
459
|
|
|
|
|
|
|
} |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
/* Get resource by name */ |
|
462
|
380
|
|
|
|
|
|
return pdfmake_dict_get(cat_dict, name_id); |
|
463
|
|
|
|
|
|
|
} |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
/*============================================================================ |
|
466
|
|
|
|
|
|
|
* Text operators |
|
467
|
|
|
|
|
|
|
*==========================================================================*/ |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
/* BT - Begin text object */ |
|
470
|
160
|
|
|
|
|
|
static pdfmake_err_t op_BT(pdfmake_interp_t *interp) { |
|
471
|
160
|
50
|
|
|
|
|
if (interp->in_text_object) { |
|
472
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ETEXTOBJ, 0, "Nested BT"); |
|
473
|
0
|
|
|
|
|
|
return PDFMAKE_ETEXTOBJ; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
160
|
|
|
|
|
|
interp->in_text_object = 1; |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
/* Reset text matrices to identity */ |
|
478
|
160
|
|
|
|
|
|
pdfmake_matrix_identity(interp->gs->text_matrix); |
|
479
|
160
|
|
|
|
|
|
pdfmake_matrix_identity(interp->gs->text_line_matrix); |
|
480
|
|
|
|
|
|
|
|
|
481
|
160
|
|
|
|
|
|
return PDFMAKE_OK; |
|
482
|
|
|
|
|
|
|
} |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
/* ET - End text object */ |
|
485
|
160
|
|
|
|
|
|
static pdfmake_err_t op_ET(pdfmake_interp_t *interp) { |
|
486
|
160
|
50
|
|
|
|
|
if (!interp->in_text_object) { |
|
487
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ETEXTOBJ, 0, "ET without BT"); |
|
488
|
0
|
|
|
|
|
|
return PDFMAKE_ETEXTOBJ; |
|
489
|
|
|
|
|
|
|
} |
|
490
|
160
|
|
|
|
|
|
interp->in_text_object = 0; |
|
491
|
160
|
|
|
|
|
|
return PDFMAKE_OK; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
/* Tc - Set character spacing */ |
|
495
|
290
|
|
|
|
|
|
static pdfmake_err_t op_Tc(pdfmake_interp_t *interp) { |
|
496
|
290
|
|
|
|
|
|
pdfmake_obj_t charSpace = pop_operand(interp); |
|
497
|
290
|
|
|
|
|
|
interp->gs->char_space = get_number(charSpace); |
|
498
|
290
|
|
|
|
|
|
return PDFMAKE_OK; |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
/* Tw - Set word spacing */ |
|
502
|
256
|
|
|
|
|
|
static pdfmake_err_t op_Tw(pdfmake_interp_t *interp) { |
|
503
|
256
|
|
|
|
|
|
pdfmake_obj_t wordSpace = pop_operand(interp); |
|
504
|
256
|
|
|
|
|
|
interp->gs->word_space = get_number(wordSpace); |
|
505
|
256
|
|
|
|
|
|
return PDFMAKE_OK; |
|
506
|
|
|
|
|
|
|
} |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
/* Tz - Set horizontal scaling */ |
|
509
|
0
|
|
|
|
|
|
static pdfmake_err_t op_Tz(pdfmake_interp_t *interp) { |
|
510
|
0
|
|
|
|
|
|
pdfmake_obj_t scale = pop_operand(interp); |
|
511
|
0
|
|
|
|
|
|
interp->gs->h_scale = get_number(scale); |
|
512
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
/* TL - Set text leading */ |
|
516
|
1
|
|
|
|
|
|
static pdfmake_err_t op_TL(pdfmake_interp_t *interp) { |
|
517
|
1
|
|
|
|
|
|
pdfmake_obj_t leading = pop_operand(interp); |
|
518
|
1
|
|
|
|
|
|
interp->gs->leading = get_number(leading); |
|
519
|
1
|
|
|
|
|
|
return PDFMAKE_OK; |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
/* Tf - Set text font and size */ |
|
523
|
366
|
|
|
|
|
|
static pdfmake_err_t op_Tf(pdfmake_interp_t *interp) { |
|
524
|
366
|
|
|
|
|
|
pdfmake_obj_t size = pop_operand(interp); |
|
525
|
366
|
|
|
|
|
|
pdfmake_obj_t font = pop_operand(interp); |
|
526
|
|
|
|
|
|
|
|
|
527
|
366
|
|
|
|
|
|
interp->gs->font_size = get_number(size); |
|
528
|
|
|
|
|
|
|
|
|
529
|
366
|
50
|
|
|
|
|
if (font.kind == PDFMAKE_NAME) { |
|
530
|
366
|
|
|
|
|
|
interp->gs->font_name = font.as.name.id; |
|
531
|
|
|
|
|
|
|
/* Look up font in resources */ |
|
532
|
366
|
|
|
|
|
|
interp->gs->font = lookup_resource(interp, "Font", font.as.name.id); |
|
533
|
|
|
|
|
|
|
} |
|
534
|
|
|
|
|
|
|
|
|
535
|
366
|
|
|
|
|
|
return PDFMAKE_OK; |
|
536
|
|
|
|
|
|
|
} |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
/* Tr - Set text rendering mode */ |
|
539
|
6
|
|
|
|
|
|
static pdfmake_err_t op_Tr(pdfmake_interp_t *interp) { |
|
540
|
6
|
|
|
|
|
|
pdfmake_obj_t render = pop_operand(interp); |
|
541
|
6
|
|
|
|
|
|
int mode = (int)get_number(render); |
|
542
|
6
|
50
|
|
|
|
|
if (mode >= 0 && mode <= 7) { |
|
|
|
50
|
|
|
|
|
|
|
543
|
6
|
|
|
|
|
|
interp->gs->render_mode = mode; |
|
544
|
|
|
|
|
|
|
} |
|
545
|
6
|
|
|
|
|
|
return PDFMAKE_OK; |
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
/* Ts - Set text rise */ |
|
549
|
0
|
|
|
|
|
|
static pdfmake_err_t op_Ts(pdfmake_interp_t *interp) { |
|
550
|
0
|
|
|
|
|
|
pdfmake_obj_t rise = pop_operand(interp); |
|
551
|
0
|
|
|
|
|
|
interp->gs->rise = get_number(rise); |
|
552
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
553
|
|
|
|
|
|
|
} |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
/* Td - Move text position */ |
|
556
|
37
|
|
|
|
|
|
static pdfmake_err_t op_Td(pdfmake_interp_t *interp) { |
|
557
|
37
|
|
|
|
|
|
pdfmake_obj_t ty = pop_operand(interp); |
|
558
|
37
|
|
|
|
|
|
pdfmake_obj_t tx = pop_operand(interp); |
|
559
|
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
double m[6]; |
|
561
|
37
|
|
|
|
|
|
pdfmake_matrix_translate(m, get_number(tx), get_number(ty)); |
|
562
|
37
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->text_line_matrix, |
|
563
|
37
|
|
|
|
|
|
m, interp->gs->text_line_matrix); |
|
564
|
37
|
|
|
|
|
|
pdfmake_matrix_copy(interp->gs->text_matrix, interp->gs->text_line_matrix); |
|
565
|
|
|
|
|
|
|
|
|
566
|
37
|
|
|
|
|
|
return PDFMAKE_OK; |
|
567
|
|
|
|
|
|
|
} |
|
568
|
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
/* TD - Move text position and set leading */ |
|
570
|
381
|
|
|
|
|
|
static pdfmake_err_t op_TD(pdfmake_interp_t *interp) { |
|
571
|
381
|
|
|
|
|
|
pdfmake_obj_t ty = pop_operand(interp); |
|
572
|
381
|
|
|
|
|
|
pdfmake_obj_t tx = pop_operand(interp); |
|
573
|
|
|
|
|
|
|
double m[6]; |
|
574
|
|
|
|
|
|
|
|
|
575
|
381
|
|
|
|
|
|
interp->gs->leading = -get_number(ty); |
|
576
|
|
|
|
|
|
|
|
|
577
|
381
|
|
|
|
|
|
pdfmake_matrix_translate(m, get_number(tx), get_number(ty)); |
|
578
|
381
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->text_line_matrix, |
|
579
|
381
|
|
|
|
|
|
m, interp->gs->text_line_matrix); |
|
580
|
381
|
|
|
|
|
|
pdfmake_matrix_copy(interp->gs->text_matrix, interp->gs->text_line_matrix); |
|
581
|
|
|
|
|
|
|
|
|
582
|
381
|
|
|
|
|
|
return PDFMAKE_OK; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
/* Tm - Set text matrix */ |
|
586
|
349
|
|
|
|
|
|
static pdfmake_err_t op_Tm(pdfmake_interp_t *interp) { |
|
587
|
349
|
|
|
|
|
|
pdfmake_obj_t f = pop_operand(interp); |
|
588
|
349
|
|
|
|
|
|
pdfmake_obj_t e = pop_operand(interp); |
|
589
|
349
|
|
|
|
|
|
pdfmake_obj_t d = pop_operand(interp); |
|
590
|
349
|
|
|
|
|
|
pdfmake_obj_t c = pop_operand(interp); |
|
591
|
349
|
|
|
|
|
|
pdfmake_obj_t b = pop_operand(interp); |
|
592
|
349
|
|
|
|
|
|
pdfmake_obj_t a = pop_operand(interp); |
|
593
|
|
|
|
|
|
|
|
|
594
|
349
|
|
|
|
|
|
interp->gs->text_matrix[0] = get_number(a); |
|
595
|
349
|
|
|
|
|
|
interp->gs->text_matrix[1] = get_number(b); |
|
596
|
349
|
|
|
|
|
|
interp->gs->text_matrix[2] = get_number(c); |
|
597
|
349
|
|
|
|
|
|
interp->gs->text_matrix[3] = get_number(d); |
|
598
|
349
|
|
|
|
|
|
interp->gs->text_matrix[4] = get_number(e); |
|
599
|
349
|
|
|
|
|
|
interp->gs->text_matrix[5] = get_number(f); |
|
600
|
|
|
|
|
|
|
|
|
601
|
349
|
|
|
|
|
|
pdfmake_matrix_copy(interp->gs->text_line_matrix, interp->gs->text_matrix); |
|
602
|
|
|
|
|
|
|
|
|
603
|
349
|
|
|
|
|
|
return PDFMAKE_OK; |
|
604
|
|
|
|
|
|
|
} |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
/* T* - Move to start of next line */ |
|
607
|
78
|
|
|
|
|
|
static pdfmake_err_t op_Tstar(pdfmake_interp_t *interp) { |
|
608
|
|
|
|
|
|
|
double m[6]; |
|
609
|
78
|
|
|
|
|
|
pdfmake_matrix_translate(m, 0, -interp->gs->leading); |
|
610
|
78
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->text_line_matrix, |
|
611
|
78
|
|
|
|
|
|
m, interp->gs->text_line_matrix); |
|
612
|
78
|
|
|
|
|
|
pdfmake_matrix_copy(interp->gs->text_matrix, interp->gs->text_line_matrix); |
|
613
|
78
|
|
|
|
|
|
return PDFMAKE_OK; |
|
614
|
|
|
|
|
|
|
} |
|
615
|
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
/* Helper: advance text matrix by string width */ |
|
617
|
3484
|
|
|
|
|
|
static void advance_text_matrix(pdfmake_interp_t *interp, |
|
618
|
|
|
|
|
|
|
const uint8_t *bytes, size_t len) { |
|
619
|
|
|
|
|
|
|
double width; |
|
620
|
|
|
|
|
|
|
size_t char_count; |
|
621
|
|
|
|
|
|
|
size_t space_count; |
|
622
|
|
|
|
|
|
|
size_t i; |
|
623
|
|
|
|
|
|
|
double avg_glyph_width; |
|
624
|
|
|
|
|
|
|
int vertical; |
|
625
|
|
|
|
|
|
|
double m[6]; |
|
626
|
|
|
|
|
|
|
|
|
627
|
3484
|
|
|
|
|
|
width = 0; |
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
/* Phase 8: if the visitor can compute the real text-space advance |
|
630
|
|
|
|
|
|
|
* (using resolved font widths), use that. This keeps text_matrix in |
|
631
|
|
|
|
|
|
|
* sync with the visitor's glyph positions across Tj/TJ calls, which |
|
632
|
|
|
|
|
|
|
* is essential for accurate inter-run gap detection. */ |
|
633
|
3484
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->get_string_advance) { |
|
|
|
50
|
|
|
|
|
|
|
634
|
3484
|
|
|
|
|
|
width = interp->visitor->get_string_advance( |
|
635
|
3484
|
|
|
|
|
|
interp->visitor->ctx, interp->gs, bytes, len); |
|
636
|
|
|
|
|
|
|
} |
|
637
|
|
|
|
|
|
|
|
|
638
|
3484
|
50
|
|
|
|
|
if (width <= 0) { |
|
639
|
|
|
|
|
|
|
/* Fallback: 0.6-em placeholder per character, plus char/word space */ |
|
640
|
0
|
|
|
|
|
|
char_count = len; |
|
641
|
0
|
|
|
|
|
|
space_count = 0; |
|
642
|
0
|
0
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
643
|
0
|
0
|
|
|
|
|
if (bytes[i] == ' ') space_count++; |
|
644
|
|
|
|
|
|
|
} |
|
645
|
0
|
|
|
|
|
|
avg_glyph_width = 0.6 * interp->gs->font_size; |
|
646
|
0
|
|
|
|
|
|
width = char_count * avg_glyph_width |
|
647
|
0
|
|
|
|
|
|
+ char_count * interp->gs->char_space |
|
648
|
0
|
|
|
|
|
|
+ space_count * interp->gs->word_space; |
|
649
|
|
|
|
|
|
|
} |
|
650
|
|
|
|
|
|
|
|
|
651
|
3484
|
|
|
|
|
|
width *= interp->gs->h_scale / 100.0; |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
/* Phase 14: vertical writing advances along -y, not +x. */ |
|
654
|
3484
|
|
|
|
|
|
vertical = 0; |
|
655
|
3484
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->is_vertical_writing) { |
|
|
|
50
|
|
|
|
|
|
|
656
|
3484
|
|
|
|
|
|
vertical = interp->visitor->is_vertical_writing( |
|
657
|
3484
|
|
|
|
|
|
interp->visitor->ctx, interp->gs); |
|
658
|
|
|
|
|
|
|
} |
|
659
|
|
|
|
|
|
|
|
|
660
|
3484
|
100
|
|
|
|
|
if (vertical) { |
|
661
|
1
|
|
|
|
|
|
pdfmake_matrix_translate(m, 0, -width); |
|
662
|
|
|
|
|
|
|
} else { |
|
663
|
3483
|
|
|
|
|
|
pdfmake_matrix_translate(m, width, 0); |
|
664
|
|
|
|
|
|
|
} |
|
665
|
3484
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->text_matrix, |
|
666
|
3484
|
|
|
|
|
|
m, interp->gs->text_matrix); |
|
667
|
3484
|
|
|
|
|
|
} |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
/* Tj - Show text string */ |
|
670
|
|
|
|
|
|
|
/* Convert ASCII hex-digit byte to its 0-15 value, or -1 if not a hex digit. */ |
|
671
|
124
|
|
|
|
|
|
static int hex_val(uint8_t c) { |
|
672
|
124
|
50
|
|
|
|
|
if (c >= '0' && c <= '9') return c - '0'; |
|
|
|
100
|
|
|
|
|
|
|
673
|
16
|
50
|
|
|
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
|
|
|
50
|
|
|
|
|
|
|
674
|
0
|
0
|
|
|
|
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
|
|
|
0
|
|
|
|
|
|
|
675
|
0
|
|
|
|
|
|
return -1; |
|
676
|
|
|
|
|
|
|
} |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
/* If the string is a hex string (`` form), decode it into a fresh |
|
679
|
|
|
|
|
|
|
* arena-backed byte array. Whitespace is skipped; odd trailing nibble is |
|
680
|
|
|
|
|
|
|
* padded with 0 per PDF spec. |
|
681
|
|
|
|
|
|
|
* Returns 1 if decoded (caller uses *out_bytes), 0 if not a hex string. */ |
|
682
|
6
|
|
|
|
|
|
static int maybe_decode_hex_string(pdfmake_arena_t *arena, |
|
683
|
|
|
|
|
|
|
const pdfmake_obj_t *str, |
|
684
|
|
|
|
|
|
|
const uint8_t **out_bytes, |
|
685
|
|
|
|
|
|
|
size_t *out_len) |
|
686
|
|
|
|
|
|
|
{ |
|
687
|
|
|
|
|
|
|
const uint8_t *in; |
|
688
|
|
|
|
|
|
|
size_t in_len; |
|
689
|
|
|
|
|
|
|
uint8_t *out; |
|
690
|
|
|
|
|
|
|
size_t written; |
|
691
|
|
|
|
|
|
|
int nibble; |
|
692
|
|
|
|
|
|
|
size_t i; |
|
693
|
|
|
|
|
|
|
|
|
694
|
6
|
50
|
|
|
|
|
if (!str || str->kind != PDFMAKE_STR || !str->as.str.hex) return 0; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|
|
696
|
6
|
|
|
|
|
|
in = str->as.str.bytes; |
|
697
|
6
|
|
|
|
|
|
in_len = str->as.str.len; |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
/* Max output is ceil(in_len / 2) — safe upper bound */ |
|
700
|
6
|
|
|
|
|
|
out = pdfmake_arena_alloc(arena, (in_len / 2) + 1); |
|
701
|
6
|
50
|
|
|
|
|
if (!out) return 0; |
|
702
|
|
|
|
|
|
|
|
|
703
|
6
|
|
|
|
|
|
written = 0; |
|
704
|
6
|
|
|
|
|
|
nibble = -1; |
|
705
|
130
|
100
|
|
|
|
|
for (i = 0; i < in_len; i++) { |
|
706
|
124
|
|
|
|
|
|
int v = hex_val(in[i]); |
|
707
|
124
|
50
|
|
|
|
|
if (v < 0) continue; /* skip whitespace, ignore garbage */ |
|
708
|
124
|
100
|
|
|
|
|
if (nibble < 0) { |
|
709
|
62
|
|
|
|
|
|
nibble = v; |
|
710
|
|
|
|
|
|
|
} else { |
|
711
|
62
|
|
|
|
|
|
out[written++] = (uint8_t)((nibble << 4) | v); |
|
712
|
62
|
|
|
|
|
|
nibble = -1; |
|
713
|
|
|
|
|
|
|
} |
|
714
|
|
|
|
|
|
|
} |
|
715
|
6
|
50
|
|
|
|
|
if (nibble >= 0) out[written++] = (uint8_t)(nibble << 4); |
|
716
|
|
|
|
|
|
|
|
|
717
|
6
|
|
|
|
|
|
*out_bytes = out; |
|
718
|
6
|
|
|
|
|
|
*out_len = written; |
|
719
|
6
|
|
|
|
|
|
return 1; |
|
720
|
|
|
|
|
|
|
} |
|
721
|
|
|
|
|
|
|
|
|
722
|
437
|
|
|
|
|
|
static pdfmake_err_t op_Tj(pdfmake_interp_t *interp) { |
|
723
|
|
|
|
|
|
|
pdfmake_obj_t str; |
|
724
|
|
|
|
|
|
|
const uint8_t *bytes; |
|
725
|
|
|
|
|
|
|
size_t len; |
|
726
|
|
|
|
|
|
|
|
|
727
|
437
|
50
|
|
|
|
|
if (!interp->in_text_object) { |
|
728
|
|
|
|
|
|
|
/* Lenient: just skip */ |
|
729
|
0
|
|
|
|
|
|
clear_operands(interp); |
|
730
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
731
|
|
|
|
|
|
|
} |
|
732
|
|
|
|
|
|
|
|
|
733
|
437
|
|
|
|
|
|
str = pop_operand(interp); |
|
734
|
|
|
|
|
|
|
|
|
735
|
437
|
|
|
|
|
|
bytes = NULL; |
|
736
|
437
|
|
|
|
|
|
len = 0; |
|
737
|
|
|
|
|
|
|
|
|
738
|
437
|
50
|
|
|
|
|
if (str.kind == PDFMAKE_STR) { |
|
739
|
437
|
100
|
|
|
|
|
if (str.as.str.hex) { |
|
740
|
|
|
|
|
|
|
/* Decode → raw bytes */ |
|
741
|
1
|
50
|
|
|
|
|
if (!maybe_decode_hex_string(interp->arena, &str, &bytes, &len)) { |
|
742
|
0
|
|
|
|
|
|
bytes = str.as.str.bytes; |
|
743
|
0
|
|
|
|
|
|
len = str.as.str.len; |
|
744
|
|
|
|
|
|
|
} |
|
745
|
|
|
|
|
|
|
} else { |
|
746
|
436
|
|
|
|
|
|
bytes = str.as.str.bytes; |
|
747
|
436
|
|
|
|
|
|
len = str.as.str.len; |
|
748
|
|
|
|
|
|
|
} |
|
749
|
|
|
|
|
|
|
} |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
/* Fire visitor callback */ |
|
752
|
437
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_text_show && bytes) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
753
|
437
|
|
|
|
|
|
interp->visitor->on_text_show(interp->visitor->ctx, |
|
754
|
437
|
|
|
|
|
|
interp->gs, bytes, len); |
|
755
|
|
|
|
|
|
|
} |
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
/* Advance text matrix */ |
|
758
|
437
|
50
|
|
|
|
|
if (bytes && len > 0) { |
|
|
|
50
|
|
|
|
|
|
|
759
|
437
|
|
|
|
|
|
advance_text_matrix(interp, bytes, len); |
|
760
|
|
|
|
|
|
|
} |
|
761
|
|
|
|
|
|
|
|
|
762
|
437
|
|
|
|
|
|
return PDFMAKE_OK; |
|
763
|
|
|
|
|
|
|
} |
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
/* TJ - Show text with positioning */ |
|
766
|
409
|
|
|
|
|
|
static pdfmake_err_t op_TJ(pdfmake_interp_t *interp) { |
|
767
|
|
|
|
|
|
|
pdfmake_obj_t arr; |
|
768
|
|
|
|
|
|
|
size_t arr_len; |
|
769
|
|
|
|
|
|
|
size_t i; |
|
770
|
|
|
|
|
|
|
|
|
771
|
409
|
50
|
|
|
|
|
if (!interp->in_text_object) { |
|
772
|
0
|
|
|
|
|
|
clear_operands(interp); |
|
773
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
774
|
|
|
|
|
|
|
} |
|
775
|
|
|
|
|
|
|
|
|
776
|
409
|
|
|
|
|
|
arr = pop_operand(interp); |
|
777
|
|
|
|
|
|
|
|
|
778
|
409
|
50
|
|
|
|
|
if (arr.kind != PDFMAKE_ARRAY) { |
|
779
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
780
|
|
|
|
|
|
|
} |
|
781
|
|
|
|
|
|
|
|
|
782
|
409
|
|
|
|
|
|
arr_len = pdfmake_array_len(&arr); |
|
783
|
|
|
|
|
|
|
|
|
784
|
6094
|
100
|
|
|
|
|
for (i = 0; i < arr_len; i++) { |
|
785
|
5685
|
|
|
|
|
|
pdfmake_obj_t *elem = pdfmake_array_get(&arr, i); |
|
786
|
5685
|
50
|
|
|
|
|
if (!elem) continue; |
|
787
|
|
|
|
|
|
|
|
|
788
|
5685
|
100
|
|
|
|
|
if (elem->kind == PDFMAKE_STR) { |
|
789
|
|
|
|
|
|
|
/* String element - show text. Decode hex strings first. */ |
|
790
|
|
|
|
|
|
|
const uint8_t *bytes; |
|
791
|
|
|
|
|
|
|
size_t len; |
|
792
|
3047
|
100
|
|
|
|
|
if (elem->as.str.hex) { |
|
793
|
5
|
50
|
|
|
|
|
if (!maybe_decode_hex_string(interp->arena, elem, &bytes, &len)) { |
|
794
|
0
|
|
|
|
|
|
bytes = elem->as.str.bytes; |
|
795
|
0
|
|
|
|
|
|
len = elem->as.str.len; |
|
796
|
|
|
|
|
|
|
} |
|
797
|
|
|
|
|
|
|
} else { |
|
798
|
3042
|
|
|
|
|
|
bytes = elem->as.str.bytes; |
|
799
|
3042
|
|
|
|
|
|
len = elem->as.str.len; |
|
800
|
|
|
|
|
|
|
} |
|
801
|
|
|
|
|
|
|
|
|
802
|
3047
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_text_show) { |
|
|
|
50
|
|
|
|
|
|
|
803
|
3047
|
|
|
|
|
|
interp->visitor->on_text_show(interp->visitor->ctx, |
|
804
|
3047
|
|
|
|
|
|
interp->gs, bytes, len); |
|
805
|
|
|
|
|
|
|
} |
|
806
|
|
|
|
|
|
|
|
|
807
|
3047
|
|
|
|
|
|
advance_text_matrix(interp, bytes, len); |
|
808
|
|
|
|
|
|
|
|
|
809
|
2638
|
100
|
|
|
|
|
} else if (elem->kind == PDFMAKE_INT || elem->kind == PDFMAKE_REAL) { |
|
|
|
50
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
/* Numeric element - adjust position. |
|
811
|
|
|
|
|
|
|
* Value is in thousandths of a text space unit. |
|
812
|
|
|
|
|
|
|
* Positive moves left (decreases position). */ |
|
813
|
2638
|
|
|
|
|
|
double adj = get_number(*elem); |
|
814
|
2638
|
|
|
|
|
|
double tx = -adj * interp->gs->font_size / 1000.0 |
|
815
|
2638
|
|
|
|
|
|
* interp->gs->h_scale / 100.0; |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
double m[6]; |
|
818
|
2638
|
|
|
|
|
|
pdfmake_matrix_translate(m, tx, 0); |
|
819
|
2638
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->text_matrix, |
|
820
|
2638
|
|
|
|
|
|
m, interp->gs->text_matrix); |
|
821
|
|
|
|
|
|
|
} |
|
822
|
|
|
|
|
|
|
} |
|
823
|
|
|
|
|
|
|
|
|
824
|
409
|
|
|
|
|
|
return PDFMAKE_OK; |
|
825
|
|
|
|
|
|
|
} |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
/* ' - Move to next line and show text */ |
|
828
|
0
|
|
|
|
|
|
static pdfmake_err_t op_quote(pdfmake_interp_t *interp) { |
|
829
|
0
|
|
|
|
|
|
op_Tstar(interp); |
|
830
|
0
|
|
|
|
|
|
return op_Tj(interp); |
|
831
|
|
|
|
|
|
|
} |
|
832
|
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
/* " - Set spacing, move to next line, show text */ |
|
834
|
0
|
|
|
|
|
|
static pdfmake_err_t op_dquote(pdfmake_interp_t *interp) { |
|
835
|
0
|
|
|
|
|
|
pdfmake_obj_t str = pop_operand(interp); |
|
836
|
0
|
|
|
|
|
|
pdfmake_obj_t ac = pop_operand(interp); |
|
837
|
0
|
|
|
|
|
|
pdfmake_obj_t aw = pop_operand(interp); |
|
838
|
|
|
|
|
|
|
|
|
839
|
0
|
|
|
|
|
|
interp->gs->word_space = get_number(aw); |
|
840
|
0
|
|
|
|
|
|
interp->gs->char_space = get_number(ac); |
|
841
|
|
|
|
|
|
|
|
|
842
|
0
|
|
|
|
|
|
push_operand(interp, str); |
|
843
|
0
|
|
|
|
|
|
op_Tstar(interp); |
|
844
|
0
|
|
|
|
|
|
return op_Tj(interp); |
|
845
|
|
|
|
|
|
|
} |
|
846
|
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
/*============================================================================ |
|
848
|
|
|
|
|
|
|
* Graphics state operators |
|
849
|
|
|
|
|
|
|
*==========================================================================*/ |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
/* q - Save graphics state */ |
|
852
|
38
|
|
|
|
|
|
static pdfmake_err_t op_q(pdfmake_interp_t *interp) { |
|
853
|
38
|
|
|
|
|
|
return gstate_push(interp); |
|
854
|
|
|
|
|
|
|
} |
|
855
|
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
/* Q - Restore graphics state */ |
|
857
|
38
|
|
|
|
|
|
static pdfmake_err_t op_Q(pdfmake_interp_t *interp) { |
|
858
|
38
|
|
|
|
|
|
return gstate_pop(interp); |
|
859
|
|
|
|
|
|
|
} |
|
860
|
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
/* cm - Concatenate matrix */ |
|
862
|
19
|
|
|
|
|
|
static pdfmake_err_t op_cm(pdfmake_interp_t *interp) { |
|
863
|
19
|
|
|
|
|
|
pdfmake_obj_t f = pop_operand(interp); |
|
864
|
19
|
|
|
|
|
|
pdfmake_obj_t e = pop_operand(interp); |
|
865
|
19
|
|
|
|
|
|
pdfmake_obj_t d = pop_operand(interp); |
|
866
|
19
|
|
|
|
|
|
pdfmake_obj_t c = pop_operand(interp); |
|
867
|
19
|
|
|
|
|
|
pdfmake_obj_t b = pop_operand(interp); |
|
868
|
19
|
|
|
|
|
|
pdfmake_obj_t a = pop_operand(interp); |
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
double m[6]; |
|
871
|
19
|
|
|
|
|
|
m[0] = get_number(a); |
|
872
|
19
|
|
|
|
|
|
m[1] = get_number(b); |
|
873
|
19
|
|
|
|
|
|
m[2] = get_number(c); |
|
874
|
19
|
|
|
|
|
|
m[3] = get_number(d); |
|
875
|
19
|
|
|
|
|
|
m[4] = get_number(e); |
|
876
|
19
|
|
|
|
|
|
m[5] = get_number(f); |
|
877
|
|
|
|
|
|
|
|
|
878
|
19
|
|
|
|
|
|
pdfmake_matrix_concat(interp->gs->ctm, m); |
|
879
|
|
|
|
|
|
|
|
|
880
|
19
|
|
|
|
|
|
return PDFMAKE_OK; |
|
881
|
|
|
|
|
|
|
} |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
/* w - Set line width */ |
|
884
|
0
|
|
|
|
|
|
static pdfmake_err_t op_w(pdfmake_interp_t *interp) { |
|
885
|
0
|
|
|
|
|
|
pdfmake_obj_t width = pop_operand(interp); |
|
886
|
0
|
|
|
|
|
|
interp->gs->line_width = get_number(width); |
|
887
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
888
|
|
|
|
|
|
|
} |
|
889
|
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
/* J - Set line cap */ |
|
891
|
0
|
|
|
|
|
|
static pdfmake_err_t op_J(pdfmake_interp_t *interp) { |
|
892
|
0
|
|
|
|
|
|
pdfmake_obj_t cap = pop_operand(interp); |
|
893
|
0
|
|
|
|
|
|
int c = (int)get_number(cap); |
|
894
|
0
|
0
|
|
|
|
|
if (c >= 0 && c <= 2) { |
|
|
|
0
|
|
|
|
|
|
|
895
|
0
|
|
|
|
|
|
interp->gs->line_cap = c; |
|
896
|
|
|
|
|
|
|
} |
|
897
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
898
|
|
|
|
|
|
|
} |
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
/* j - Set line join */ |
|
901
|
0
|
|
|
|
|
|
static pdfmake_err_t op_j(pdfmake_interp_t *interp) { |
|
902
|
0
|
|
|
|
|
|
pdfmake_obj_t join = pop_operand(interp); |
|
903
|
0
|
|
|
|
|
|
int j = (int)get_number(join); |
|
904
|
0
|
0
|
|
|
|
|
if (j >= 0 && j <= 2) { |
|
|
|
0
|
|
|
|
|
|
|
905
|
0
|
|
|
|
|
|
interp->gs->line_join = j; |
|
906
|
|
|
|
|
|
|
} |
|
907
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
908
|
|
|
|
|
|
|
} |
|
909
|
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
/* M - Set miter limit */ |
|
911
|
0
|
|
|
|
|
|
static pdfmake_err_t op_M(pdfmake_interp_t *interp) { |
|
912
|
0
|
|
|
|
|
|
pdfmake_obj_t ml = pop_operand(interp); |
|
913
|
0
|
|
|
|
|
|
interp->gs->miter_limit = get_number(ml); |
|
914
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
915
|
|
|
|
|
|
|
} |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
/* d - Set dash pattern */ |
|
918
|
0
|
|
|
|
|
|
static pdfmake_err_t op_d(pdfmake_interp_t *interp) { |
|
919
|
0
|
|
|
|
|
|
pdfmake_obj_t phase = pop_operand(interp); |
|
920
|
0
|
|
|
|
|
|
pdfmake_obj_t array = pop_operand(interp); |
|
921
|
|
|
|
|
|
|
size_t i; |
|
922
|
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
/* Free old dash array */ |
|
924
|
0
|
|
|
|
|
|
free(interp->gs->dash_array); |
|
925
|
0
|
|
|
|
|
|
interp->gs->dash_array = NULL; |
|
926
|
0
|
|
|
|
|
|
interp->gs->dash_count = 0; |
|
927
|
0
|
|
|
|
|
|
interp->gs->dash_phase = get_number(phase); |
|
928
|
|
|
|
|
|
|
|
|
929
|
0
|
0
|
|
|
|
|
if (array.kind == PDFMAKE_ARRAY) { |
|
930
|
0
|
|
|
|
|
|
size_t n = pdfmake_array_len(&array); |
|
931
|
0
|
0
|
|
|
|
|
if (n > 0) { |
|
932
|
0
|
|
|
|
|
|
interp->gs->dash_array = malloc(n * sizeof(double)); |
|
933
|
0
|
0
|
|
|
|
|
if (interp->gs->dash_array) { |
|
934
|
0
|
|
|
|
|
|
interp->gs->dash_count = n; |
|
935
|
0
|
0
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
936
|
0
|
|
|
|
|
|
pdfmake_obj_t *v = pdfmake_array_get(&array, i); |
|
937
|
0
|
0
|
|
|
|
|
interp->gs->dash_array[i] = v ? get_number(*v) : 0; |
|
938
|
|
|
|
|
|
|
} |
|
939
|
|
|
|
|
|
|
} |
|
940
|
|
|
|
|
|
|
} |
|
941
|
|
|
|
|
|
|
} |
|
942
|
|
|
|
|
|
|
|
|
943
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
944
|
|
|
|
|
|
|
} |
|
945
|
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
/* i - Set flatness */ |
|
947
|
3
|
|
|
|
|
|
static pdfmake_err_t op_i(pdfmake_interp_t *interp) { |
|
948
|
3
|
|
|
|
|
|
pdfmake_obj_t flat = pop_operand(interp); |
|
949
|
3
|
|
|
|
|
|
interp->gs->flatness = get_number(flat); |
|
950
|
3
|
|
|
|
|
|
return PDFMAKE_OK; |
|
951
|
|
|
|
|
|
|
} |
|
952
|
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
/* gs - Set graphics state from ExtGState dict */ |
|
954
|
14
|
|
|
|
|
|
static pdfmake_err_t op_gs(pdfmake_interp_t *interp) { |
|
955
|
14
|
|
|
|
|
|
pdfmake_obj_t name = pop_operand(interp); |
|
956
|
|
|
|
|
|
|
pdfmake_obj_t *dict; |
|
957
|
|
|
|
|
|
|
|
|
958
|
14
|
50
|
|
|
|
|
if (name.kind != PDFMAKE_NAME) { |
|
959
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
960
|
|
|
|
|
|
|
} |
|
961
|
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
/* Look up in ExtGState resources */ |
|
963
|
14
|
|
|
|
|
|
dict = lookup_resource(interp, "ExtGState", name.as.name.id); |
|
964
|
14
|
50
|
|
|
|
|
if (!dict || dict->kind != PDFMAKE_DICT) { |
|
|
|
50
|
|
|
|
|
|
|
965
|
14
|
|
|
|
|
|
return PDFMAKE_OK; |
|
966
|
|
|
|
|
|
|
} |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
/* Apply relevant settings from dict */ |
|
969
|
|
|
|
|
|
|
/* This is simplified - full implementation would handle all ExtGState keys */ |
|
970
|
|
|
|
|
|
|
|
|
971
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
972
|
|
|
|
|
|
|
} |
|
973
|
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
/*============================================================================ |
|
975
|
|
|
|
|
|
|
* Path construction operators |
|
976
|
|
|
|
|
|
|
*==========================================================================*/ |
|
977
|
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
/* m - moveto */ |
|
979
|
0
|
|
|
|
|
|
static pdfmake_err_t op_m(pdfmake_interp_t *interp) { |
|
980
|
0
|
|
|
|
|
|
pdfmake_obj_t y = pop_operand(interp); |
|
981
|
0
|
|
|
|
|
|
pdfmake_obj_t x = pop_operand(interp); |
|
982
|
|
|
|
|
|
|
|
|
983
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
984
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_MOVE; |
|
985
|
0
|
|
|
|
|
|
seg.x1 = get_number(x); |
|
986
|
0
|
|
|
|
|
|
seg.y1 = get_number(y); |
|
987
|
|
|
|
|
|
|
|
|
988
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
989
|
0
|
|
|
|
|
|
interp->cur_x = seg.x1; |
|
990
|
0
|
|
|
|
|
|
interp->cur_y = seg.y1; |
|
991
|
0
|
|
|
|
|
|
interp->have_cur_point = 1; |
|
992
|
|
|
|
|
|
|
|
|
993
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
994
|
|
|
|
|
|
|
} |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
/* l - lineto */ |
|
997
|
0
|
|
|
|
|
|
static pdfmake_err_t op_l(pdfmake_interp_t *interp) { |
|
998
|
0
|
|
|
|
|
|
pdfmake_obj_t y = pop_operand(interp); |
|
999
|
0
|
|
|
|
|
|
pdfmake_obj_t x = pop_operand(interp); |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1002
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_LINE; |
|
1003
|
0
|
|
|
|
|
|
seg.x1 = get_number(x); |
|
1004
|
0
|
|
|
|
|
|
seg.y1 = get_number(y); |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1007
|
0
|
|
|
|
|
|
interp->cur_x = seg.x1; |
|
1008
|
0
|
|
|
|
|
|
interp->cur_y = seg.y1; |
|
1009
|
|
|
|
|
|
|
|
|
1010
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1011
|
|
|
|
|
|
|
} |
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
/* c - curveto (cubic Bézier) */ |
|
1014
|
0
|
|
|
|
|
|
static pdfmake_err_t op_c(pdfmake_interp_t *interp) { |
|
1015
|
0
|
|
|
|
|
|
pdfmake_obj_t y3 = pop_operand(interp); |
|
1016
|
0
|
|
|
|
|
|
pdfmake_obj_t x3 = pop_operand(interp); |
|
1017
|
0
|
|
|
|
|
|
pdfmake_obj_t y2 = pop_operand(interp); |
|
1018
|
0
|
|
|
|
|
|
pdfmake_obj_t x2 = pop_operand(interp); |
|
1019
|
0
|
|
|
|
|
|
pdfmake_obj_t y1 = pop_operand(interp); |
|
1020
|
0
|
|
|
|
|
|
pdfmake_obj_t x1 = pop_operand(interp); |
|
1021
|
|
|
|
|
|
|
|
|
1022
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1023
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_CURVE; |
|
1024
|
0
|
|
|
|
|
|
seg.x1 = get_number(x1); |
|
1025
|
0
|
|
|
|
|
|
seg.y1 = get_number(y1); |
|
1026
|
0
|
|
|
|
|
|
seg.x2 = get_number(x2); |
|
1027
|
0
|
|
|
|
|
|
seg.y2 = get_number(y2); |
|
1028
|
0
|
|
|
|
|
|
seg.x3 = get_number(x3); |
|
1029
|
0
|
|
|
|
|
|
seg.y3 = get_number(y3); |
|
1030
|
|
|
|
|
|
|
|
|
1031
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1032
|
0
|
|
|
|
|
|
interp->cur_x = seg.x3; |
|
1033
|
0
|
|
|
|
|
|
interp->cur_y = seg.y3; |
|
1034
|
|
|
|
|
|
|
|
|
1035
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1036
|
|
|
|
|
|
|
} |
|
1037
|
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
/* v - curveto (initial point replicated) */ |
|
1039
|
0
|
|
|
|
|
|
static pdfmake_err_t op_v(pdfmake_interp_t *interp) { |
|
1040
|
0
|
|
|
|
|
|
pdfmake_obj_t y3 = pop_operand(interp); |
|
1041
|
0
|
|
|
|
|
|
pdfmake_obj_t x3 = pop_operand(interp); |
|
1042
|
0
|
|
|
|
|
|
pdfmake_obj_t y2 = pop_operand(interp); |
|
1043
|
0
|
|
|
|
|
|
pdfmake_obj_t x2 = pop_operand(interp); |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1046
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_CURVE_V; |
|
1047
|
0
|
|
|
|
|
|
seg.x1 = interp->cur_x; /* First control point = current point */ |
|
1048
|
0
|
|
|
|
|
|
seg.y1 = interp->cur_y; |
|
1049
|
0
|
|
|
|
|
|
seg.x2 = get_number(x2); |
|
1050
|
0
|
|
|
|
|
|
seg.y2 = get_number(y2); |
|
1051
|
0
|
|
|
|
|
|
seg.x3 = get_number(x3); |
|
1052
|
0
|
|
|
|
|
|
seg.y3 = get_number(y3); |
|
1053
|
|
|
|
|
|
|
|
|
1054
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1055
|
0
|
|
|
|
|
|
interp->cur_x = seg.x3; |
|
1056
|
0
|
|
|
|
|
|
interp->cur_y = seg.y3; |
|
1057
|
|
|
|
|
|
|
|
|
1058
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1059
|
|
|
|
|
|
|
} |
|
1060
|
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
/* y - curveto (final point replicated) */ |
|
1062
|
0
|
|
|
|
|
|
static pdfmake_err_t op_y(pdfmake_interp_t *interp) { |
|
1063
|
0
|
|
|
|
|
|
pdfmake_obj_t y3 = pop_operand(interp); |
|
1064
|
0
|
|
|
|
|
|
pdfmake_obj_t x3 = pop_operand(interp); |
|
1065
|
0
|
|
|
|
|
|
pdfmake_obj_t y1 = pop_operand(interp); |
|
1066
|
0
|
|
|
|
|
|
pdfmake_obj_t x1 = pop_operand(interp); |
|
1067
|
|
|
|
|
|
|
|
|
1068
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1069
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_CURVE_Y; |
|
1070
|
0
|
|
|
|
|
|
seg.x1 = get_number(x1); |
|
1071
|
0
|
|
|
|
|
|
seg.y1 = get_number(y1); |
|
1072
|
0
|
|
|
|
|
|
seg.x2 = get_number(x3); /* Second control point = endpoint */ |
|
1073
|
0
|
|
|
|
|
|
seg.y2 = get_number(y3); |
|
1074
|
0
|
|
|
|
|
|
seg.x3 = get_number(x3); |
|
1075
|
0
|
|
|
|
|
|
seg.y3 = get_number(y3); |
|
1076
|
|
|
|
|
|
|
|
|
1077
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1078
|
0
|
|
|
|
|
|
interp->cur_x = seg.x3; |
|
1079
|
0
|
|
|
|
|
|
interp->cur_y = seg.y3; |
|
1080
|
|
|
|
|
|
|
|
|
1081
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1082
|
|
|
|
|
|
|
} |
|
1083
|
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
/* h - closepath */ |
|
1085
|
0
|
|
|
|
|
|
static pdfmake_err_t op_h(pdfmake_interp_t *interp) { |
|
1086
|
0
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1087
|
0
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_CLOSE; |
|
1088
|
0
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1089
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1090
|
|
|
|
|
|
|
} |
|
1091
|
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
/* re - rectangle */ |
|
1093
|
127
|
|
|
|
|
|
static pdfmake_err_t op_re(pdfmake_interp_t *interp) { |
|
1094
|
127
|
|
|
|
|
|
pdfmake_obj_t height = pop_operand(interp); |
|
1095
|
127
|
|
|
|
|
|
pdfmake_obj_t width = pop_operand(interp); |
|
1096
|
127
|
|
|
|
|
|
pdfmake_obj_t y = pop_operand(interp); |
|
1097
|
127
|
|
|
|
|
|
pdfmake_obj_t x = pop_operand(interp); |
|
1098
|
|
|
|
|
|
|
|
|
1099
|
127
|
|
|
|
|
|
pdfmake_path_segment_t seg = {0}; |
|
1100
|
127
|
|
|
|
|
|
seg.op = PDFMAKE_PATH_RECT; |
|
1101
|
127
|
|
|
|
|
|
seg.x1 = get_number(x); |
|
1102
|
127
|
|
|
|
|
|
seg.y1 = get_number(y); |
|
1103
|
127
|
|
|
|
|
|
seg.width = get_number(width); |
|
1104
|
127
|
|
|
|
|
|
seg.height = get_number(height); |
|
1105
|
|
|
|
|
|
|
|
|
1106
|
127
|
|
|
|
|
|
path_add_segment(interp, seg); |
|
1107
|
127
|
|
|
|
|
|
interp->cur_x = seg.x1; |
|
1108
|
127
|
|
|
|
|
|
interp->cur_y = seg.y1; |
|
1109
|
127
|
|
|
|
|
|
interp->have_cur_point = 1; |
|
1110
|
|
|
|
|
|
|
|
|
1111
|
127
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1112
|
|
|
|
|
|
|
} |
|
1113
|
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
/*============================================================================ |
|
1115
|
|
|
|
|
|
|
* Path painting operators |
|
1116
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1117
|
|
|
|
|
|
|
|
|
1118
|
127
|
|
|
|
|
|
static void fire_path_callback(pdfmake_interp_t *interp, |
|
1119
|
|
|
|
|
|
|
int stroke, int fill, int even_odd) { |
|
1120
|
127
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_path && interp->path_size > 0) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1121
|
0
|
|
|
|
|
|
interp->visitor->on_path(interp->visitor->ctx, |
|
1122
|
0
|
|
|
|
|
|
interp->gs, |
|
1123
|
0
|
|
|
|
|
|
interp->path, |
|
1124
|
|
|
|
|
|
|
interp->path_size, |
|
1125
|
|
|
|
|
|
|
stroke, fill, even_odd); |
|
1126
|
|
|
|
|
|
|
} |
|
1127
|
127
|
|
|
|
|
|
path_clear(interp); |
|
1128
|
127
|
|
|
|
|
|
} |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
/* S - Stroke path */ |
|
1131
|
0
|
|
|
|
|
|
static pdfmake_err_t op_S(pdfmake_interp_t *interp) { |
|
1132
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 0, 0); |
|
1133
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1134
|
|
|
|
|
|
|
} |
|
1135
|
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
/* s - Close and stroke path */ |
|
1137
|
0
|
|
|
|
|
|
static pdfmake_err_t op_s(pdfmake_interp_t *interp) { |
|
1138
|
0
|
|
|
|
|
|
op_h(interp); |
|
1139
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 0, 0); |
|
1140
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1141
|
|
|
|
|
|
|
} |
|
1142
|
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
/* f / F - Fill path (nonzero winding) */ |
|
1144
|
127
|
|
|
|
|
|
static pdfmake_err_t op_f(pdfmake_interp_t *interp) { |
|
1145
|
127
|
|
|
|
|
|
fire_path_callback(interp, 0, 1, 0); |
|
1146
|
127
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1147
|
|
|
|
|
|
|
} |
|
1148
|
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
/* f* - Fill path (even-odd rule) */ |
|
1150
|
0
|
|
|
|
|
|
static pdfmake_err_t op_fstar(pdfmake_interp_t *interp) { |
|
1151
|
0
|
|
|
|
|
|
fire_path_callback(interp, 0, 1, 1); |
|
1152
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1153
|
|
|
|
|
|
|
} |
|
1154
|
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
/* B - Fill and stroke path (nonzero winding) */ |
|
1156
|
0
|
|
|
|
|
|
static pdfmake_err_t op_B(pdfmake_interp_t *interp) { |
|
1157
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 1, 0); |
|
1158
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1159
|
|
|
|
|
|
|
} |
|
1160
|
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
/* B* - Fill and stroke path (even-odd rule) */ |
|
1162
|
0
|
|
|
|
|
|
static pdfmake_err_t op_Bstar(pdfmake_interp_t *interp) { |
|
1163
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 1, 1); |
|
1164
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1165
|
|
|
|
|
|
|
} |
|
1166
|
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
/* b - Close, fill, and stroke path (nonzero winding) */ |
|
1168
|
0
|
|
|
|
|
|
static pdfmake_err_t op_b(pdfmake_interp_t *interp) { |
|
1169
|
0
|
|
|
|
|
|
op_h(interp); |
|
1170
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 1, 0); |
|
1171
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1172
|
|
|
|
|
|
|
} |
|
1173
|
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
/* b* - Close, fill, and stroke path (even-odd rule) */ |
|
1175
|
0
|
|
|
|
|
|
static pdfmake_err_t op_bstar(pdfmake_interp_t *interp) { |
|
1176
|
0
|
|
|
|
|
|
op_h(interp); |
|
1177
|
0
|
|
|
|
|
|
fire_path_callback(interp, 1, 1, 1); |
|
1178
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1179
|
|
|
|
|
|
|
} |
|
1180
|
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
/* n - End path without filling or stroking */ |
|
1182
|
0
|
|
|
|
|
|
static pdfmake_err_t op_n(pdfmake_interp_t *interp) { |
|
1183
|
0
|
|
|
|
|
|
path_clear(interp); |
|
1184
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1185
|
|
|
|
|
|
|
} |
|
1186
|
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
/*============================================================================ |
|
1188
|
|
|
|
|
|
|
* Clipping path operators |
|
1189
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1190
|
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
/* W - Set clipping path (nonzero) */ |
|
1192
|
0
|
|
|
|
|
|
static pdfmake_err_t op_W(pdfmake_interp_t *interp) { |
|
1193
|
0
|
|
|
|
|
|
interp->gs->clip_depth++; |
|
1194
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1195
|
|
|
|
|
|
|
} |
|
1196
|
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
/* W* - Set clipping path (even-odd) */ |
|
1198
|
0
|
|
|
|
|
|
static pdfmake_err_t op_Wstar(pdfmake_interp_t *interp) { |
|
1199
|
0
|
|
|
|
|
|
interp->gs->clip_depth++; |
|
1200
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1201
|
|
|
|
|
|
|
} |
|
1202
|
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
/*============================================================================ |
|
1204
|
|
|
|
|
|
|
* Color operators (simplified) |
|
1205
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1206
|
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
/* g - Set gray fill color */ |
|
1208
|
0
|
|
|
|
|
|
static pdfmake_err_t op_g(pdfmake_interp_t *interp) { |
|
1209
|
0
|
|
|
|
|
|
pdfmake_obj_t gray = pop_operand(interp); |
|
1210
|
0
|
|
|
|
|
|
interp->gs->fill_color.space = PDFMAKE_CS_GRAY; |
|
1211
|
0
|
|
|
|
|
|
interp->gs->fill_color.components[0] = get_number(gray); |
|
1212
|
0
|
|
|
|
|
|
interp->gs->fill_color.n_components = 1; |
|
1213
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1214
|
|
|
|
|
|
|
} |
|
1215
|
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
/* G - Set gray stroke color */ |
|
1217
|
0
|
|
|
|
|
|
static pdfmake_err_t op_G(pdfmake_interp_t *interp) { |
|
1218
|
0
|
|
|
|
|
|
pdfmake_obj_t gray = pop_operand(interp); |
|
1219
|
0
|
|
|
|
|
|
interp->gs->stroke_color.space = PDFMAKE_CS_GRAY; |
|
1220
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[0] = get_number(gray); |
|
1221
|
0
|
|
|
|
|
|
interp->gs->stroke_color.n_components = 1; |
|
1222
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1223
|
|
|
|
|
|
|
} |
|
1224
|
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
/* rg - Set RGB fill color */ |
|
1226
|
115
|
|
|
|
|
|
static pdfmake_err_t op_rg(pdfmake_interp_t *interp) { |
|
1227
|
115
|
|
|
|
|
|
pdfmake_obj_t b = pop_operand(interp); |
|
1228
|
115
|
|
|
|
|
|
pdfmake_obj_t g = pop_operand(interp); |
|
1229
|
115
|
|
|
|
|
|
pdfmake_obj_t r = pop_operand(interp); |
|
1230
|
115
|
|
|
|
|
|
interp->gs->fill_color.space = PDFMAKE_CS_RGB; |
|
1231
|
115
|
|
|
|
|
|
interp->gs->fill_color.components[0] = get_number(r); |
|
1232
|
115
|
|
|
|
|
|
interp->gs->fill_color.components[1] = get_number(g); |
|
1233
|
115
|
|
|
|
|
|
interp->gs->fill_color.components[2] = get_number(b); |
|
1234
|
115
|
|
|
|
|
|
interp->gs->fill_color.n_components = 3; |
|
1235
|
115
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1236
|
|
|
|
|
|
|
} |
|
1237
|
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
/* RG - Set RGB stroke color */ |
|
1239
|
0
|
|
|
|
|
|
static pdfmake_err_t op_RG(pdfmake_interp_t *interp) { |
|
1240
|
0
|
|
|
|
|
|
pdfmake_obj_t b = pop_operand(interp); |
|
1241
|
0
|
|
|
|
|
|
pdfmake_obj_t g = pop_operand(interp); |
|
1242
|
0
|
|
|
|
|
|
pdfmake_obj_t r = pop_operand(interp); |
|
1243
|
0
|
|
|
|
|
|
interp->gs->stroke_color.space = PDFMAKE_CS_RGB; |
|
1244
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[0] = get_number(r); |
|
1245
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[1] = get_number(g); |
|
1246
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[2] = get_number(b); |
|
1247
|
0
|
|
|
|
|
|
interp->gs->stroke_color.n_components = 3; |
|
1248
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1249
|
|
|
|
|
|
|
} |
|
1250
|
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
/* k - Set CMYK fill color */ |
|
1252
|
0
|
|
|
|
|
|
static pdfmake_err_t op_k(pdfmake_interp_t *interp) { |
|
1253
|
0
|
|
|
|
|
|
pdfmake_obj_t kk = pop_operand(interp); |
|
1254
|
0
|
|
|
|
|
|
pdfmake_obj_t y = pop_operand(interp); |
|
1255
|
0
|
|
|
|
|
|
pdfmake_obj_t m = pop_operand(interp); |
|
1256
|
0
|
|
|
|
|
|
pdfmake_obj_t c = pop_operand(interp); |
|
1257
|
0
|
|
|
|
|
|
interp->gs->fill_color.space = PDFMAKE_CS_CMYK; |
|
1258
|
0
|
|
|
|
|
|
interp->gs->fill_color.components[0] = get_number(c); |
|
1259
|
0
|
|
|
|
|
|
interp->gs->fill_color.components[1] = get_number(m); |
|
1260
|
0
|
|
|
|
|
|
interp->gs->fill_color.components[2] = get_number(y); |
|
1261
|
0
|
|
|
|
|
|
interp->gs->fill_color.components[3] = get_number(kk); |
|
1262
|
0
|
|
|
|
|
|
interp->gs->fill_color.n_components = 4; |
|
1263
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1264
|
|
|
|
|
|
|
} |
|
1265
|
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
/* K - Set CMYK stroke color */ |
|
1267
|
0
|
|
|
|
|
|
static pdfmake_err_t op_K(pdfmake_interp_t *interp) { |
|
1268
|
0
|
|
|
|
|
|
pdfmake_obj_t kk = pop_operand(interp); |
|
1269
|
0
|
|
|
|
|
|
pdfmake_obj_t y = pop_operand(interp); |
|
1270
|
0
|
|
|
|
|
|
pdfmake_obj_t m = pop_operand(interp); |
|
1271
|
0
|
|
|
|
|
|
pdfmake_obj_t c = pop_operand(interp); |
|
1272
|
0
|
|
|
|
|
|
interp->gs->stroke_color.space = PDFMAKE_CS_CMYK; |
|
1273
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[0] = get_number(c); |
|
1274
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[1] = get_number(m); |
|
1275
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[2] = get_number(y); |
|
1276
|
0
|
|
|
|
|
|
interp->gs->stroke_color.components[3] = get_number(kk); |
|
1277
|
0
|
|
|
|
|
|
interp->gs->stroke_color.n_components = 4; |
|
1278
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1279
|
|
|
|
|
|
|
} |
|
1280
|
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
/*============================================================================ |
|
1282
|
|
|
|
|
|
|
* XObject operators |
|
1283
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1284
|
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
/* Look up XObject in resources, returning (obj, num, gen). |
|
1286
|
|
|
|
|
|
|
* If the resource is stored by reference, num/gen are filled; otherwise 0. */ |
|
1287
|
21
|
|
|
|
|
|
static pdfmake_obj_t *lookup_xobject_with_ref(pdfmake_interp_t *interp, |
|
1288
|
|
|
|
|
|
|
uint32_t name_id, |
|
1289
|
|
|
|
|
|
|
uint32_t *out_num, |
|
1290
|
|
|
|
|
|
|
uint16_t *out_gen) { |
|
1291
|
|
|
|
|
|
|
uint32_t cat_id; |
|
1292
|
|
|
|
|
|
|
pdfmake_obj_t *cat; |
|
1293
|
|
|
|
|
|
|
pdfmake_obj_t *entry; |
|
1294
|
|
|
|
|
|
|
|
|
1295
|
21
|
|
|
|
|
|
*out_num = 0; |
|
1296
|
21
|
|
|
|
|
|
*out_gen = 0; |
|
1297
|
21
|
50
|
|
|
|
|
if (!interp->resources || interp->resources->kind != PDFMAKE_DICT) |
|
|
|
50
|
|
|
|
|
|
|
1298
|
0
|
|
|
|
|
|
return NULL; |
|
1299
|
|
|
|
|
|
|
|
|
1300
|
21
|
|
|
|
|
|
cat_id = pdfmake_arena_intern_name(interp->arena, "XObject", 7); |
|
1301
|
21
|
|
|
|
|
|
cat = pdfmake_dict_get(interp->resources, cat_id); |
|
1302
|
21
|
50
|
|
|
|
|
if (!cat) return NULL; |
|
1303
|
|
|
|
|
|
|
/* Follow indirect ref */ |
|
1304
|
21
|
50
|
|
|
|
|
if (cat->kind == PDFMAKE_REF && interp->reader) { |
|
|
|
0
|
|
|
|
|
|
|
1305
|
0
|
|
|
|
|
|
pdfmake_reader_t *rd = (pdfmake_reader_t *)interp->reader; |
|
1306
|
0
|
0
|
|
|
|
|
if (rd->parser) { |
|
1307
|
0
|
|
|
|
|
|
cat = pdfmake_parser_resolve(rd->parser, cat->as.ref); |
|
1308
|
|
|
|
|
|
|
} |
|
1309
|
|
|
|
|
|
|
} |
|
1310
|
21
|
50
|
|
|
|
|
if (!cat || cat->kind != PDFMAKE_DICT) return NULL; |
|
|
|
50
|
|
|
|
|
|
|
1311
|
|
|
|
|
|
|
|
|
1312
|
21
|
|
|
|
|
|
entry = pdfmake_dict_get(cat, name_id); |
|
1313
|
21
|
50
|
|
|
|
|
if (!entry) return NULL; |
|
1314
|
21
|
50
|
|
|
|
|
if (entry->kind == PDFMAKE_REF) { |
|
1315
|
21
|
|
|
|
|
|
*out_num = entry->as.ref.num; |
|
1316
|
21
|
|
|
|
|
|
*out_gen = entry->as.ref.gen; |
|
1317
|
|
|
|
|
|
|
/* Resolve to concrete object via the reader's parser */ |
|
1318
|
21
|
50
|
|
|
|
|
if (interp->reader) { |
|
1319
|
21
|
|
|
|
|
|
pdfmake_reader_t *rd = (pdfmake_reader_t *)interp->reader; |
|
1320
|
21
|
50
|
|
|
|
|
if (rd->parser) |
|
1321
|
21
|
|
|
|
|
|
return pdfmake_parser_resolve(rd->parser, entry->as.ref); |
|
1322
|
|
|
|
|
|
|
} |
|
1323
|
0
|
|
|
|
|
|
return NULL; |
|
1324
|
|
|
|
|
|
|
} |
|
1325
|
0
|
|
|
|
|
|
return entry; |
|
1326
|
|
|
|
|
|
|
} |
|
1327
|
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
/* Interpret a Form XObject's content stream with the form's Matrix + Resources |
|
1329
|
|
|
|
|
|
|
* pushed onto the current state. Depth-guarded to prevent pathological cycles. */ |
|
1330
|
4
|
|
|
|
|
|
static pdfmake_err_t interpret_form(pdfmake_interp_t *interp, |
|
1331
|
|
|
|
|
|
|
pdfmake_obj_t *form, |
|
1332
|
|
|
|
|
|
|
uint32_t form_num, |
|
1333
|
|
|
|
|
|
|
uint16_t form_gen) { |
|
1334
|
|
|
|
|
|
|
pdfmake_buf_t content; |
|
1335
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
1336
|
|
|
|
|
|
|
pdfmake_obj_t *saved_resources; |
|
1337
|
|
|
|
|
|
|
int saved_in_text; |
|
1338
|
|
|
|
|
|
|
pdfmake_obj_t stream_dict; |
|
1339
|
|
|
|
|
|
|
uint32_t matrix_k; |
|
1340
|
|
|
|
|
|
|
pdfmake_obj_t *mat; |
|
1341
|
|
|
|
|
|
|
uint32_t res_k; |
|
1342
|
|
|
|
|
|
|
pdfmake_obj_t *form_res; |
|
1343
|
|
|
|
|
|
|
int i; |
|
1344
|
|
|
|
|
|
|
|
|
1345
|
4
|
50
|
|
|
|
|
if (!form || form->kind != PDFMAKE_STREAM) return PDFMAKE_OK; |
|
|
|
50
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
|
|
1347
|
4
|
50
|
|
|
|
|
if (interp->form_depth >= 32) { |
|
1348
|
|
|
|
|
|
|
/* Cycle guard — spec doesn't allow cycles; silently stop. */ |
|
1349
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1350
|
|
|
|
|
|
|
} |
|
1351
|
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
/* Decode the form's content stream (decrypt + FlateDecode). */ |
|
1353
|
4
|
50
|
|
|
|
|
if (pdfmake_buf_init(&content) != PDFMAKE_OK) return PDFMAKE_ENOMEM; |
|
1354
|
|
|
|
|
|
|
|
|
1355
|
4
|
|
|
|
|
|
err = PDFMAKE_OK; |
|
1356
|
4
|
50
|
|
|
|
|
if (interp->reader && form_num > 0) { |
|
|
|
50
|
|
|
|
|
|
|
1357
|
4
|
|
|
|
|
|
err = pdfmake_reader_resolve_stream( |
|
1358
|
4
|
|
|
|
|
|
(pdfmake_reader_t *)interp->reader, form_num, form_gen, &content); |
|
1359
|
|
|
|
|
|
|
} else { |
|
1360
|
|
|
|
|
|
|
/* No reader attached: use parser-level decode without decryption. |
|
1361
|
|
|
|
|
|
|
* Will likely fail for encrypted PDFs but works for simple ones. */ |
|
1362
|
0
|
|
|
|
|
|
err = PDFMAKE_EINVAL; |
|
1363
|
|
|
|
|
|
|
} |
|
1364
|
|
|
|
|
|
|
|
|
1365
|
4
|
50
|
|
|
|
|
if (err != PDFMAKE_OK || pdfmake_buf_len(&content) == 0) { |
|
|
|
50
|
|
|
|
|
|
|
1366
|
0
|
|
|
|
|
|
pdfmake_buf_free(&content); |
|
1367
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1368
|
|
|
|
|
|
|
} |
|
1369
|
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
/* Save state: push gstate, stash current resources. */ |
|
1371
|
4
|
|
|
|
|
|
gstate_push(interp); |
|
1372
|
4
|
|
|
|
|
|
saved_resources = interp->resources; |
|
1373
|
4
|
|
|
|
|
|
saved_in_text = interp->in_text_object; |
|
1374
|
4
|
|
|
|
|
|
interp->in_text_object = 0; |
|
1375
|
|
|
|
|
|
|
|
|
1376
|
|
|
|
|
|
|
/* Apply form's /Matrix to CTM (default = identity). */ |
|
1377
|
4
|
|
|
|
|
|
stream_dict.kind = PDFMAKE_DICT; |
|
1378
|
4
|
|
|
|
|
|
stream_dict.as.dict = form->as.stream->dict; |
|
1379
|
|
|
|
|
|
|
|
|
1380
|
4
|
|
|
|
|
|
matrix_k = pdfmake_arena_intern_name(interp->arena, "Matrix", 6); |
|
1381
|
4
|
|
|
|
|
|
mat = pdfmake_dict_get(&stream_dict, matrix_k); |
|
1382
|
4
|
50
|
|
|
|
|
if (mat && mat->kind == PDFMAKE_ARRAY && pdfmake_array_len(mat) == 6) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
double m[6]; |
|
1384
|
28
|
100
|
|
|
|
|
for (i = 0; i < 6; i++) { |
|
1385
|
24
|
|
|
|
|
|
pdfmake_obj_t *v = pdfmake_array_get(mat, i); |
|
1386
|
24
|
50
|
|
|
|
|
if (!v) { m[i] = 0; continue; } |
|
1387
|
24
|
50
|
|
|
|
|
if (v->kind == PDFMAKE_INT) m[i] = (double)v->as.i; |
|
1388
|
0
|
0
|
|
|
|
|
else if (v->kind == PDFMAKE_REAL) m[i] = v->as.r; |
|
1389
|
0
|
|
|
|
|
|
else m[i] = 0; |
|
1390
|
|
|
|
|
|
|
} |
|
1391
|
|
|
|
|
|
|
/* CTM = form_matrix × CTM */ |
|
1392
|
4
|
|
|
|
|
|
pdfmake_matrix_multiply(interp->gs->ctm, m, interp->gs->ctm); |
|
1393
|
|
|
|
|
|
|
} |
|
1394
|
|
|
|
|
|
|
|
|
1395
|
|
|
|
|
|
|
/* Swap resources: form's /Resources (if any) overlays. If the form has |
|
1396
|
|
|
|
|
|
|
* no /Resources, keep the outer page's — matches §7.8.3 "If the form |
|
1397
|
|
|
|
|
|
|
* XObject does not have its own Resources dictionary, the form uses |
|
1398
|
|
|
|
|
|
|
* the page's". */ |
|
1399
|
4
|
|
|
|
|
|
res_k = pdfmake_arena_intern_name(interp->arena, "Resources", 9); |
|
1400
|
4
|
|
|
|
|
|
form_res = pdfmake_dict_get(&stream_dict, res_k); |
|
1401
|
4
|
50
|
|
|
|
|
if (form_res && form_res->kind == PDFMAKE_REF && interp->reader) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1402
|
2
|
|
|
|
|
|
pdfmake_reader_t *rd = (pdfmake_reader_t *)interp->reader; |
|
1403
|
2
|
50
|
|
|
|
|
if (rd->parser) |
|
1404
|
2
|
|
|
|
|
|
form_res = pdfmake_parser_resolve(rd->parser, form_res->as.ref); |
|
1405
|
|
|
|
|
|
|
} |
|
1406
|
4
|
50
|
|
|
|
|
if (form_res && form_res->kind == PDFMAKE_DICT) { |
|
|
|
50
|
|
|
|
|
|
|
1407
|
4
|
|
|
|
|
|
interp->resources = form_res; |
|
1408
|
|
|
|
|
|
|
} |
|
1409
|
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
/* Recurse with the already-initialized interpreter */ |
|
1411
|
4
|
|
|
|
|
|
interp->form_depth++; |
|
1412
|
4
|
|
|
|
|
|
(void)parse_content_stream(interp, |
|
1413
|
|
|
|
|
|
|
pdfmake_buf_data(&content), |
|
1414
|
|
|
|
|
|
|
pdfmake_buf_len(&content)); |
|
1415
|
4
|
|
|
|
|
|
interp->form_depth--; |
|
1416
|
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
/* Restore */ |
|
1418
|
4
|
|
|
|
|
|
interp->in_text_object = saved_in_text; |
|
1419
|
4
|
|
|
|
|
|
interp->resources = saved_resources; |
|
1420
|
4
|
|
|
|
|
|
gstate_pop(interp); |
|
1421
|
|
|
|
|
|
|
|
|
1422
|
4
|
|
|
|
|
|
pdfmake_buf_free(&content); |
|
1423
|
4
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1424
|
|
|
|
|
|
|
} |
|
1425
|
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
/* Do - Paint XObject */ |
|
1427
|
21
|
|
|
|
|
|
static pdfmake_err_t op_Do(pdfmake_interp_t *interp) { |
|
1428
|
21
|
|
|
|
|
|
pdfmake_obj_t name = pop_operand(interp); |
|
1429
|
|
|
|
|
|
|
uint32_t xobj_num; |
|
1430
|
|
|
|
|
|
|
uint16_t xobj_gen; |
|
1431
|
|
|
|
|
|
|
pdfmake_obj_t *xobj; |
|
1432
|
|
|
|
|
|
|
|
|
1433
|
21
|
50
|
|
|
|
|
if (name.kind != PDFMAKE_NAME) { |
|
1434
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1435
|
|
|
|
|
|
|
} |
|
1436
|
|
|
|
|
|
|
|
|
1437
|
21
|
|
|
|
|
|
xobj_num = 0; |
|
1438
|
21
|
|
|
|
|
|
xobj_gen = 0; |
|
1439
|
21
|
|
|
|
|
|
xobj = lookup_xobject_with_ref(interp, name.as.name.id, |
|
1440
|
|
|
|
|
|
|
&xobj_num, &xobj_gen); |
|
1441
|
21
|
50
|
|
|
|
|
if (!xobj) { |
|
1442
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1443
|
|
|
|
|
|
|
} |
|
1444
|
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
/* Check subtype */ |
|
1446
|
21
|
50
|
|
|
|
|
if (xobj->kind == PDFMAKE_STREAM) { |
|
1447
|
|
|
|
|
|
|
/* Get /Subtype from stream dict */ |
|
1448
|
21
|
|
|
|
|
|
uint32_t subtype_id = pdfmake_arena_intern_name(interp->arena, "Subtype", 7); |
|
1449
|
|
|
|
|
|
|
pdfmake_obj_t stream_dict; |
|
1450
|
|
|
|
|
|
|
pdfmake_obj_t *subtype; |
|
1451
|
21
|
|
|
|
|
|
stream_dict.kind = PDFMAKE_DICT; |
|
1452
|
21
|
|
|
|
|
|
stream_dict.as.dict = xobj->as.stream->dict; |
|
1453
|
21
|
|
|
|
|
|
subtype = pdfmake_dict_get(&stream_dict, subtype_id); |
|
1454
|
|
|
|
|
|
|
|
|
1455
|
21
|
50
|
|
|
|
|
if (subtype && subtype->kind == PDFMAKE_NAME) { |
|
|
|
50
|
|
|
|
|
|
|
1456
|
21
|
|
|
|
|
|
const char *subtype_str = pdfmake_arena_name_bytes(interp->arena, |
|
1457
|
|
|
|
|
|
|
subtype->as.name.id); |
|
1458
|
21
|
50
|
|
|
|
|
if (subtype_str) { |
|
1459
|
21
|
100
|
|
|
|
|
if (strcmp(subtype_str, "Image") == 0) { |
|
1460
|
|
|
|
|
|
|
/* Image XObject */ |
|
1461
|
17
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_image) { |
|
|
|
50
|
|
|
|
|
|
|
1462
|
0
|
|
|
|
|
|
interp->visitor->on_image(interp->visitor->ctx, |
|
1463
|
0
|
|
|
|
|
|
interp->gs, |
|
1464
|
|
|
|
|
|
|
name.as.name.id, xobj); |
|
1465
|
|
|
|
|
|
|
} |
|
1466
|
4
|
50
|
|
|
|
|
} else if (strcmp(subtype_str, "Form") == 0) { |
|
1467
|
|
|
|
|
|
|
/* Form XObject - recursive interpretation */ |
|
1468
|
4
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_form_begin) { |
|
|
|
50
|
|
|
|
|
|
|
1469
|
0
|
|
|
|
|
|
interp->visitor->on_form_begin(interp->visitor->ctx, |
|
1470
|
0
|
|
|
|
|
|
interp->gs, |
|
1471
|
|
|
|
|
|
|
name.as.name.id, xobj); |
|
1472
|
|
|
|
|
|
|
} |
|
1473
|
|
|
|
|
|
|
|
|
1474
|
4
|
|
|
|
|
|
interpret_form(interp, xobj, xobj_num, xobj_gen); |
|
1475
|
|
|
|
|
|
|
|
|
1476
|
4
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_form_end) { |
|
|
|
50
|
|
|
|
|
|
|
1477
|
0
|
|
|
|
|
|
interp->visitor->on_form_end(interp->visitor->ctx, |
|
1478
|
0
|
|
|
|
|
|
interp->gs, |
|
1479
|
|
|
|
|
|
|
name.as.name.id); |
|
1480
|
|
|
|
|
|
|
} |
|
1481
|
|
|
|
|
|
|
} |
|
1482
|
|
|
|
|
|
|
} |
|
1483
|
|
|
|
|
|
|
} |
|
1484
|
|
|
|
|
|
|
} |
|
1485
|
|
|
|
|
|
|
|
|
1486
|
21
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1487
|
|
|
|
|
|
|
} |
|
1488
|
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
/*============================================================================ |
|
1490
|
|
|
|
|
|
|
* Marked content operators |
|
1491
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1492
|
|
|
|
|
|
|
|
|
1493
|
3
|
|
|
|
|
|
static int mc_push(pdfmake_interp_t *interp, uint32_t tag) { |
|
1494
|
3
|
50
|
|
|
|
|
if (interp->mc_depth >= interp->mc_cap) { |
|
1495
|
0
|
|
|
|
|
|
size_t new_cap = interp->mc_cap * 2; |
|
1496
|
0
|
|
|
|
|
|
uint32_t *new_stack = realloc(interp->mc_stack, |
|
1497
|
|
|
|
|
|
|
new_cap * sizeof(uint32_t)); |
|
1498
|
0
|
0
|
|
|
|
|
if (!new_stack) return 0; |
|
1499
|
0
|
|
|
|
|
|
interp->mc_stack = new_stack; |
|
1500
|
0
|
|
|
|
|
|
interp->mc_cap = new_cap; |
|
1501
|
|
|
|
|
|
|
} |
|
1502
|
3
|
|
|
|
|
|
interp->mc_stack[interp->mc_depth++] = tag; |
|
1503
|
3
|
|
|
|
|
|
return 1; |
|
1504
|
|
|
|
|
|
|
} |
|
1505
|
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
/* BMC - Begin marked content */ |
|
1507
|
0
|
|
|
|
|
|
static pdfmake_err_t op_BMC(pdfmake_interp_t *interp) { |
|
1508
|
0
|
|
|
|
|
|
pdfmake_obj_t tag = pop_operand(interp); |
|
1509
|
|
|
|
|
|
|
|
|
1510
|
0
|
|
|
|
|
|
uint32_t tag_id = 0; |
|
1511
|
0
|
0
|
|
|
|
|
if (tag.kind == PDFMAKE_NAME) { |
|
1512
|
0
|
|
|
|
|
|
tag_id = tag.as.name.id; |
|
1513
|
|
|
|
|
|
|
} |
|
1514
|
|
|
|
|
|
|
|
|
1515
|
0
|
|
|
|
|
|
mc_push(interp, tag_id); |
|
1516
|
|
|
|
|
|
|
|
|
1517
|
0
|
0
|
|
|
|
|
if (interp->visitor && interp->visitor->on_marked_content_begin) { |
|
|
|
0
|
|
|
|
|
|
|
1518
|
0
|
|
|
|
|
|
interp->visitor->on_marked_content_begin(interp->visitor->ctx, |
|
1519
|
0
|
|
|
|
|
|
interp->gs, tag_id, NULL); |
|
1520
|
|
|
|
|
|
|
} |
|
1521
|
|
|
|
|
|
|
|
|
1522
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1523
|
|
|
|
|
|
|
} |
|
1524
|
|
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
/* BDC - Begin marked content with properties */ |
|
1526
|
3
|
|
|
|
|
|
static pdfmake_err_t op_BDC(pdfmake_interp_t *interp) { |
|
1527
|
3
|
|
|
|
|
|
pdfmake_obj_t props = pop_operand(interp); |
|
1528
|
3
|
|
|
|
|
|
pdfmake_obj_t tag = pop_operand(interp); |
|
1529
|
|
|
|
|
|
|
uint32_t tag_id; |
|
1530
|
|
|
|
|
|
|
pdfmake_obj_t *props_ptr; |
|
1531
|
|
|
|
|
|
|
|
|
1532
|
3
|
|
|
|
|
|
tag_id = 0; |
|
1533
|
3
|
50
|
|
|
|
|
if (tag.kind == PDFMAKE_NAME) { |
|
1534
|
3
|
|
|
|
|
|
tag_id = tag.as.name.id; |
|
1535
|
|
|
|
|
|
|
} |
|
1536
|
|
|
|
|
|
|
|
|
1537
|
3
|
|
|
|
|
|
props_ptr = NULL; |
|
1538
|
3
|
50
|
|
|
|
|
if (props.kind == PDFMAKE_DICT) { |
|
1539
|
3
|
|
|
|
|
|
props_ptr = &props; |
|
1540
|
0
|
0
|
|
|
|
|
} else if (props.kind == PDFMAKE_NAME) { |
|
1541
|
|
|
|
|
|
|
/* Look up in Properties resource */ |
|
1542
|
0
|
|
|
|
|
|
props_ptr = lookup_resource(interp, "Properties", props.as.name.id); |
|
1543
|
|
|
|
|
|
|
} |
|
1544
|
|
|
|
|
|
|
|
|
1545
|
3
|
|
|
|
|
|
mc_push(interp, tag_id); |
|
1546
|
|
|
|
|
|
|
|
|
1547
|
3
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_marked_content_begin) { |
|
|
|
50
|
|
|
|
|
|
|
1548
|
3
|
|
|
|
|
|
interp->visitor->on_marked_content_begin(interp->visitor->ctx, |
|
1549
|
3
|
|
|
|
|
|
interp->gs, tag_id, props_ptr); |
|
1550
|
|
|
|
|
|
|
} |
|
1551
|
|
|
|
|
|
|
|
|
1552
|
3
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1553
|
|
|
|
|
|
|
} |
|
1554
|
|
|
|
|
|
|
|
|
1555
|
|
|
|
|
|
|
/* EMC - End marked content */ |
|
1556
|
3
|
|
|
|
|
|
static pdfmake_err_t op_EMC(pdfmake_interp_t *interp) { |
|
1557
|
3
|
50
|
|
|
|
|
if (interp->mc_depth > 0) { |
|
1558
|
3
|
|
|
|
|
|
interp->mc_depth--; |
|
1559
|
|
|
|
|
|
|
} |
|
1560
|
|
|
|
|
|
|
|
|
1561
|
3
|
50
|
|
|
|
|
if (interp->visitor && interp->visitor->on_marked_content_end) { |
|
|
|
50
|
|
|
|
|
|
|
1562
|
3
|
|
|
|
|
|
interp->visitor->on_marked_content_end(interp->visitor->ctx, interp->gs); |
|
1563
|
|
|
|
|
|
|
} |
|
1564
|
|
|
|
|
|
|
|
|
1565
|
3
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1566
|
|
|
|
|
|
|
} |
|
1567
|
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
/* MP - Marked content point */ |
|
1569
|
0
|
|
|
|
|
|
static pdfmake_err_t op_MP(pdfmake_interp_t *interp) { |
|
1570
|
0
|
|
|
|
|
|
pop_operand(interp); /* tag */ |
|
1571
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1572
|
|
|
|
|
|
|
} |
|
1573
|
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
/* DP - Marked content point with properties */ |
|
1575
|
0
|
|
|
|
|
|
static pdfmake_err_t op_DP(pdfmake_interp_t *interp) { |
|
1576
|
0
|
|
|
|
|
|
pop_operand(interp); /* properties */ |
|
1577
|
0
|
|
|
|
|
|
pop_operand(interp); /* tag */ |
|
1578
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1579
|
|
|
|
|
|
|
} |
|
1580
|
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
/*============================================================================ |
|
1582
|
|
|
|
|
|
|
* Compatibility operators |
|
1583
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1584
|
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
/* BX - Begin compatibility section */ |
|
1586
|
0
|
|
|
|
|
|
static pdfmake_err_t op_BX(pdfmake_interp_t *interp) { |
|
1587
|
|
|
|
|
|
|
(void)interp; |
|
1588
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1589
|
|
|
|
|
|
|
} |
|
1590
|
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
/* EX - End compatibility section */ |
|
1592
|
0
|
|
|
|
|
|
static pdfmake_err_t op_EX(pdfmake_interp_t *interp) { |
|
1593
|
|
|
|
|
|
|
(void)interp; |
|
1594
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1595
|
|
|
|
|
|
|
} |
|
1596
|
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
/*============================================================================ |
|
1598
|
|
|
|
|
|
|
* Color space operators (simplified - just consume operands) |
|
1599
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1600
|
|
|
|
|
|
|
|
|
1601
|
|
|
|
|
|
|
/* cs - Set fill color space */ |
|
1602
|
0
|
|
|
|
|
|
static pdfmake_err_t op_cs(pdfmake_interp_t *interp) { |
|
1603
|
0
|
|
|
|
|
|
pop_operand(interp); |
|
1604
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1605
|
|
|
|
|
|
|
} |
|
1606
|
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
/* CS - Set stroke color space */ |
|
1608
|
0
|
|
|
|
|
|
static pdfmake_err_t op_CS(pdfmake_interp_t *interp) { |
|
1609
|
0
|
|
|
|
|
|
pop_operand(interp); |
|
1610
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1611
|
|
|
|
|
|
|
} |
|
1612
|
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
/* sc/scn - Set fill color (arbitrary color space) */ |
|
1614
|
0
|
|
|
|
|
|
static pdfmake_err_t op_sc(pdfmake_interp_t *interp) { |
|
1615
|
|
|
|
|
|
|
/* Just consume operands for now */ |
|
1616
|
0
|
|
|
|
|
|
clear_operands(interp); |
|
1617
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1618
|
|
|
|
|
|
|
} |
|
1619
|
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
/* SC/SCN - Set stroke color (arbitrary color space) */ |
|
1621
|
0
|
|
|
|
|
|
static pdfmake_err_t op_SC(pdfmake_interp_t *interp) { |
|
1622
|
0
|
|
|
|
|
|
clear_operands(interp); |
|
1623
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1624
|
|
|
|
|
|
|
} |
|
1625
|
|
|
|
|
|
|
|
|
1626
|
|
|
|
|
|
|
/*============================================================================ |
|
1627
|
|
|
|
|
|
|
* Rendering intent |
|
1628
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1629
|
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
/* ri - Set rendering intent */ |
|
1631
|
0
|
|
|
|
|
|
static pdfmake_err_t op_ri(pdfmake_interp_t *interp) { |
|
1632
|
0
|
|
|
|
|
|
pdfmake_obj_t intent = pop_operand(interp); |
|
1633
|
0
|
0
|
|
|
|
|
if (intent.kind == PDFMAKE_NAME) { |
|
1634
|
0
|
|
|
|
|
|
interp->gs->rendering_intent = intent.as.name.id; |
|
1635
|
|
|
|
|
|
|
} |
|
1636
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1637
|
|
|
|
|
|
|
} |
|
1638
|
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
/*============================================================================ |
|
1640
|
|
|
|
|
|
|
* Inline image operators (simplified) |
|
1641
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1642
|
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
/* BI - Begin inline image */ |
|
1644
|
0
|
|
|
|
|
|
static pdfmake_err_t op_BI(pdfmake_interp_t *interp) { |
|
1645
|
|
|
|
|
|
|
/* Inline images are handled specially during tokenization */ |
|
1646
|
|
|
|
|
|
|
(void)interp; |
|
1647
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1648
|
|
|
|
|
|
|
} |
|
1649
|
|
|
|
|
|
|
|
|
1650
|
|
|
|
|
|
|
/*============================================================================ |
|
1651
|
|
|
|
|
|
|
* Shading operator |
|
1652
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1653
|
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
/* sh - Paint shading */ |
|
1655
|
0
|
|
|
|
|
|
static pdfmake_err_t op_sh(pdfmake_interp_t *interp) { |
|
1656
|
0
|
|
|
|
|
|
pop_operand(interp); |
|
1657
|
0
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1658
|
|
|
|
|
|
|
} |
|
1659
|
|
|
|
|
|
|
|
|
1660
|
|
|
|
|
|
|
/*============================================================================ |
|
1661
|
|
|
|
|
|
|
* Operator dispatch table |
|
1662
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1663
|
|
|
|
|
|
|
|
|
1664
|
|
|
|
|
|
|
typedef pdfmake_err_t (*op_handler_t)(pdfmake_interp_t *interp); |
|
1665
|
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
typedef struct { |
|
1667
|
|
|
|
|
|
|
const char *name; |
|
1668
|
|
|
|
|
|
|
op_handler_t handler; |
|
1669
|
|
|
|
|
|
|
} op_entry_t; |
|
1670
|
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
static const op_entry_t op_table[] = { |
|
1672
|
|
|
|
|
|
|
/* Graphics state */ |
|
1673
|
|
|
|
|
|
|
{"q", op_q}, |
|
1674
|
|
|
|
|
|
|
{"Q", op_Q}, |
|
1675
|
|
|
|
|
|
|
{"cm", op_cm}, |
|
1676
|
|
|
|
|
|
|
{"w", op_w}, |
|
1677
|
|
|
|
|
|
|
{"J", op_J}, |
|
1678
|
|
|
|
|
|
|
{"j", op_j}, |
|
1679
|
|
|
|
|
|
|
{"M", op_M}, |
|
1680
|
|
|
|
|
|
|
{"d", op_d}, |
|
1681
|
|
|
|
|
|
|
{"ri", op_ri}, |
|
1682
|
|
|
|
|
|
|
{"i", op_i}, |
|
1683
|
|
|
|
|
|
|
{"gs", op_gs}, |
|
1684
|
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
/* Text state */ |
|
1686
|
|
|
|
|
|
|
{"Tc", op_Tc}, |
|
1687
|
|
|
|
|
|
|
{"Tw", op_Tw}, |
|
1688
|
|
|
|
|
|
|
{"Tz", op_Tz}, |
|
1689
|
|
|
|
|
|
|
{"TL", op_TL}, |
|
1690
|
|
|
|
|
|
|
{"Tf", op_Tf}, |
|
1691
|
|
|
|
|
|
|
{"Tr", op_Tr}, |
|
1692
|
|
|
|
|
|
|
{"Ts", op_Ts}, |
|
1693
|
|
|
|
|
|
|
|
|
1694
|
|
|
|
|
|
|
/* Text positioning */ |
|
1695
|
|
|
|
|
|
|
{"Td", op_Td}, |
|
1696
|
|
|
|
|
|
|
{"TD", op_TD}, |
|
1697
|
|
|
|
|
|
|
{"Tm", op_Tm}, |
|
1698
|
|
|
|
|
|
|
{"T*", op_Tstar}, |
|
1699
|
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
/* Text showing */ |
|
1701
|
|
|
|
|
|
|
{"Tj", op_Tj}, |
|
1702
|
|
|
|
|
|
|
{"TJ", op_TJ}, |
|
1703
|
|
|
|
|
|
|
{"'", op_quote}, |
|
1704
|
|
|
|
|
|
|
{"\"", op_dquote}, |
|
1705
|
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
/* Text object */ |
|
1707
|
|
|
|
|
|
|
{"BT", op_BT}, |
|
1708
|
|
|
|
|
|
|
{"ET", op_ET}, |
|
1709
|
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
/* Path construction */ |
|
1711
|
|
|
|
|
|
|
{"m", op_m}, |
|
1712
|
|
|
|
|
|
|
{"l", op_l}, |
|
1713
|
|
|
|
|
|
|
{"c", op_c}, |
|
1714
|
|
|
|
|
|
|
{"v", op_v}, |
|
1715
|
|
|
|
|
|
|
{"y", op_y}, |
|
1716
|
|
|
|
|
|
|
{"h", op_h}, |
|
1717
|
|
|
|
|
|
|
{"re", op_re}, |
|
1718
|
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
/* Path painting */ |
|
1720
|
|
|
|
|
|
|
{"S", op_S}, |
|
1721
|
|
|
|
|
|
|
{"s", op_s}, |
|
1722
|
|
|
|
|
|
|
{"f", op_f}, |
|
1723
|
|
|
|
|
|
|
{"F", op_f}, /* F is same as f */ |
|
1724
|
|
|
|
|
|
|
{"f*", op_fstar}, |
|
1725
|
|
|
|
|
|
|
{"B", op_B}, |
|
1726
|
|
|
|
|
|
|
{"B*", op_Bstar}, |
|
1727
|
|
|
|
|
|
|
{"b", op_b}, |
|
1728
|
|
|
|
|
|
|
{"b*", op_bstar}, |
|
1729
|
|
|
|
|
|
|
{"n", op_n}, |
|
1730
|
|
|
|
|
|
|
|
|
1731
|
|
|
|
|
|
|
/* Clipping */ |
|
1732
|
|
|
|
|
|
|
{"W", op_W}, |
|
1733
|
|
|
|
|
|
|
{"W*", op_Wstar}, |
|
1734
|
|
|
|
|
|
|
|
|
1735
|
|
|
|
|
|
|
/* Color */ |
|
1736
|
|
|
|
|
|
|
{"g", op_g}, |
|
1737
|
|
|
|
|
|
|
{"G", op_G}, |
|
1738
|
|
|
|
|
|
|
{"rg", op_rg}, |
|
1739
|
|
|
|
|
|
|
{"RG", op_RG}, |
|
1740
|
|
|
|
|
|
|
{"k", op_k}, |
|
1741
|
|
|
|
|
|
|
{"K", op_K}, |
|
1742
|
|
|
|
|
|
|
{"cs", op_cs}, |
|
1743
|
|
|
|
|
|
|
{"CS", op_CS}, |
|
1744
|
|
|
|
|
|
|
{"sc", op_sc}, |
|
1745
|
|
|
|
|
|
|
{"SC", op_SC}, |
|
1746
|
|
|
|
|
|
|
{"scn", op_sc}, |
|
1747
|
|
|
|
|
|
|
{"SCN", op_SC}, |
|
1748
|
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
/* XObject */ |
|
1750
|
|
|
|
|
|
|
{"Do", op_Do}, |
|
1751
|
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
/* Marked content */ |
|
1753
|
|
|
|
|
|
|
{"BMC", op_BMC}, |
|
1754
|
|
|
|
|
|
|
{"BDC", op_BDC}, |
|
1755
|
|
|
|
|
|
|
{"EMC", op_EMC}, |
|
1756
|
|
|
|
|
|
|
{"MP", op_MP}, |
|
1757
|
|
|
|
|
|
|
{"DP", op_DP}, |
|
1758
|
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
/* Compatibility */ |
|
1760
|
|
|
|
|
|
|
{"BX", op_BX}, |
|
1761
|
|
|
|
|
|
|
{"EX", op_EX}, |
|
1762
|
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
/* Inline image */ |
|
1764
|
|
|
|
|
|
|
{"BI", op_BI}, |
|
1765
|
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
/* Shading */ |
|
1767
|
|
|
|
|
|
|
{"sh", op_sh}, |
|
1768
|
|
|
|
|
|
|
|
|
1769
|
|
|
|
|
|
|
{NULL, NULL} |
|
1770
|
|
|
|
|
|
|
}; |
|
1771
|
|
|
|
|
|
|
|
|
1772
|
3438
|
|
|
|
|
|
static op_handler_t find_operator(const char *name, size_t len) { |
|
1773
|
|
|
|
|
|
|
const op_entry_t *e; |
|
1774
|
75827
|
50
|
|
|
|
|
for (e = op_table; e->name; e++) { |
|
1775
|
75827
|
100
|
|
|
|
|
if (strlen(e->name) == len && memcmp(e->name, name, len) == 0) { |
|
|
|
100
|
|
|
|
|
|
|
1776
|
3438
|
|
|
|
|
|
return e->handler; |
|
1777
|
|
|
|
|
|
|
} |
|
1778
|
|
|
|
|
|
|
} |
|
1779
|
0
|
|
|
|
|
|
return NULL; |
|
1780
|
|
|
|
|
|
|
} |
|
1781
|
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
/*============================================================================ |
|
1783
|
|
|
|
|
|
|
* Content stream tokenizer (simplified) |
|
1784
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1785
|
|
|
|
|
|
|
|
|
1786
|
|
|
|
|
|
|
/* Build a pdfmake_obj_t from a token (numbers, names, strings, booleans, |
|
1787
|
|
|
|
|
|
|
* null). Returns 1 if populated, 0 if the token isn't a primitive value |
|
1788
|
|
|
|
|
|
|
* (arrays/dicts are handled inline by the callers because they recurse via |
|
1789
|
|
|
|
|
|
|
* the tokenizer). */ |
|
1790
|
3
|
|
|
|
|
|
static int token_to_primitive(const uint8_t *bytes, |
|
1791
|
|
|
|
|
|
|
pdfmake_tok_t t, |
|
1792
|
|
|
|
|
|
|
pdfmake_obj_t *out) |
|
1793
|
|
|
|
|
|
|
{ |
|
1794
|
3
|
|
|
|
|
|
switch (t.kind) { |
|
1795
|
3
|
|
|
|
|
|
case PDFMAKE_TOK_INT: |
|
1796
|
3
|
|
|
|
|
|
*out = pdfmake_int(t.payload.int_val); |
|
1797
|
3
|
|
|
|
|
|
return 1; |
|
1798
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_REAL: |
|
1799
|
0
|
|
|
|
|
|
*out = pdfmake_real(t.payload.real_val); |
|
1800
|
0
|
|
|
|
|
|
return 1; |
|
1801
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_LSTR: |
|
1802
|
0
|
|
|
|
|
|
out->kind = PDFMAKE_STR; |
|
1803
|
0
|
|
|
|
|
|
out->as.str.bytes = bytes + t.offset + 1; |
|
1804
|
0
|
|
|
|
|
|
out->as.str.len = t.length - 2; |
|
1805
|
0
|
|
|
|
|
|
out->as.str.hex = 0; |
|
1806
|
0
|
|
|
|
|
|
return 1; |
|
1807
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_HSTR: |
|
1808
|
0
|
|
|
|
|
|
out->kind = PDFMAKE_STR; |
|
1809
|
0
|
|
|
|
|
|
out->as.str.bytes = bytes + t.offset + 1; |
|
1810
|
0
|
|
|
|
|
|
out->as.str.len = t.length - 2; |
|
1811
|
0
|
|
|
|
|
|
out->as.str.hex = 1; |
|
1812
|
0
|
|
|
|
|
|
return 1; |
|
1813
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_TRUE: *out = pdfmake_bool(1); return 1; |
|
1814
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_FALSE: *out = pdfmake_bool(0); return 1; |
|
1815
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_NULL: *out = pdfmake_null(); return 1; |
|
1816
|
0
|
|
|
|
|
|
default: return 0; |
|
1817
|
|
|
|
|
|
|
} |
|
1818
|
|
|
|
|
|
|
} |
|
1819
|
|
|
|
|
|
|
|
|
1820
|
|
|
|
|
|
|
/* Parse an inline dictionary starting just after the '<<' token. |
|
1821
|
|
|
|
|
|
|
* Handles nested dicts and arrays so BDC property dicts like |
|
1822
|
|
|
|
|
|
|
* `/P << /MCID 7 /Lang (en) >>` are usable by visitors. */ |
|
1823
|
|
|
|
|
|
|
static pdfmake_obj_t parse_inline_dict(pdfmake_interp_t *interp, |
|
1824
|
|
|
|
|
|
|
const uint8_t *bytes, |
|
1825
|
|
|
|
|
|
|
pdfmake_tokenizer_t *tok); |
|
1826
|
|
|
|
|
|
|
|
|
1827
|
0
|
|
|
|
|
|
static pdfmake_obj_t parse_inline_array(pdfmake_interp_t *interp, |
|
1828
|
|
|
|
|
|
|
const uint8_t *bytes, |
|
1829
|
|
|
|
|
|
|
pdfmake_tokenizer_t *tok) |
|
1830
|
|
|
|
|
|
|
{ |
|
1831
|
|
|
|
|
|
|
pdfmake_obj_t arr; |
|
1832
|
|
|
|
|
|
|
pdfmake_tok_t t; |
|
1833
|
|
|
|
|
|
|
pdfmake_obj_t v; |
|
1834
|
|
|
|
|
|
|
|
|
1835
|
0
|
|
|
|
|
|
arr = pdfmake_array_new(interp->arena); |
|
1836
|
|
|
|
|
|
|
while (1) { |
|
1837
|
0
|
|
|
|
|
|
t = pdfmake_tok_next_significant(tok); |
|
1838
|
0
|
0
|
|
|
|
|
if (t.kind == PDFMAKE_TOK_EOF || t.kind == PDFMAKE_TOK_ARR_CLOSE) break; |
|
|
|
0
|
|
|
|
|
|
|
1839
|
0
|
0
|
|
|
|
|
if (t.kind == PDFMAKE_TOK_ARR_OPEN) { |
|
1840
|
0
|
|
|
|
|
|
v = parse_inline_array(interp, bytes, tok); |
|
1841
|
0
|
0
|
|
|
|
|
} else if (t.kind == PDFMAKE_TOK_DICT_OPEN) { |
|
1842
|
0
|
|
|
|
|
|
v = parse_inline_dict(interp, bytes, tok); |
|
1843
|
0
|
0
|
|
|
|
|
} else if (t.kind == PDFMAKE_TOK_NAME) { |
|
1844
|
0
|
|
|
|
|
|
const char *name_str = (const char *)(bytes + t.offset + 1); |
|
1845
|
0
|
|
|
|
|
|
uint32_t id = pdfmake_arena_intern_name( |
|
1846
|
0
|
|
|
|
|
|
interp->arena, name_str, t.length - 1); |
|
1847
|
0
|
|
|
|
|
|
v.kind = PDFMAKE_NAME; |
|
1848
|
0
|
|
|
|
|
|
v.as.name.id = id; |
|
1849
|
0
|
0
|
|
|
|
|
} else if (!token_to_primitive(bytes, t, &v)) { |
|
1850
|
0
|
|
|
|
|
|
continue; |
|
1851
|
|
|
|
|
|
|
} |
|
1852
|
0
|
|
|
|
|
|
pdfmake_array_push(interp->arena, &arr, v); |
|
1853
|
|
|
|
|
|
|
} |
|
1854
|
0
|
|
|
|
|
|
return arr; |
|
1855
|
|
|
|
|
|
|
} |
|
1856
|
|
|
|
|
|
|
|
|
1857
|
3
|
|
|
|
|
|
static pdfmake_obj_t parse_inline_dict(pdfmake_interp_t *interp, |
|
1858
|
|
|
|
|
|
|
const uint8_t *bytes, |
|
1859
|
|
|
|
|
|
|
pdfmake_tokenizer_t *tok) |
|
1860
|
|
|
|
|
|
|
{ |
|
1861
|
|
|
|
|
|
|
pdfmake_obj_t dict; |
|
1862
|
|
|
|
|
|
|
pdfmake_tok_t kt; |
|
1863
|
|
|
|
|
|
|
pdfmake_tok_t vt; |
|
1864
|
|
|
|
|
|
|
const char *name_str; |
|
1865
|
|
|
|
|
|
|
uint32_t key; |
|
1866
|
|
|
|
|
|
|
pdfmake_obj_t v; |
|
1867
|
|
|
|
|
|
|
|
|
1868
|
3
|
|
|
|
|
|
dict = pdfmake_dict_new(interp->arena); |
|
1869
|
|
|
|
|
|
|
while (1) { |
|
1870
|
6
|
|
|
|
|
|
kt = pdfmake_tok_next_significant(tok); |
|
1871
|
6
|
50
|
|
|
|
|
if (kt.kind == PDFMAKE_TOK_EOF || kt.kind == PDFMAKE_TOK_DICT_CLOSE) break; |
|
|
|
100
|
|
|
|
|
|
|
1872
|
3
|
50
|
|
|
|
|
if (kt.kind != PDFMAKE_TOK_NAME) continue; /* malformed — skip */ |
|
1873
|
3
|
|
|
|
|
|
name_str = (const char *)(bytes + kt.offset + 1); |
|
1874
|
3
|
|
|
|
|
|
key = pdfmake_arena_intern_name( |
|
1875
|
3
|
|
|
|
|
|
interp->arena, name_str, kt.length - 1); |
|
1876
|
|
|
|
|
|
|
|
|
1877
|
3
|
|
|
|
|
|
vt = pdfmake_tok_next_significant(tok); |
|
1878
|
3
|
50
|
|
|
|
|
if (vt.kind == PDFMAKE_TOK_EOF || vt.kind == PDFMAKE_TOK_DICT_CLOSE) break; |
|
|
|
50
|
|
|
|
|
|
|
1879
|
3
|
50
|
|
|
|
|
if (vt.kind == PDFMAKE_TOK_DICT_OPEN) { |
|
1880
|
0
|
|
|
|
|
|
v = parse_inline_dict(interp, bytes, tok); |
|
1881
|
3
|
50
|
|
|
|
|
} else if (vt.kind == PDFMAKE_TOK_ARR_OPEN) { |
|
1882
|
0
|
|
|
|
|
|
v = parse_inline_array(interp, bytes, tok); |
|
1883
|
3
|
50
|
|
|
|
|
} else if (vt.kind == PDFMAKE_TOK_NAME) { |
|
1884
|
0
|
|
|
|
|
|
const char *vstr = (const char *)(bytes + vt.offset + 1); |
|
1885
|
0
|
|
|
|
|
|
uint32_t vid = pdfmake_arena_intern_name( |
|
1886
|
0
|
|
|
|
|
|
interp->arena, vstr, vt.length - 1); |
|
1887
|
0
|
|
|
|
|
|
v.kind = PDFMAKE_NAME; |
|
1888
|
0
|
|
|
|
|
|
v.as.name.id = vid; |
|
1889
|
3
|
50
|
|
|
|
|
} else if (!token_to_primitive(bytes, vt, &v)) { |
|
1890
|
0
|
|
|
|
|
|
continue; /* unknown — drop the key/value pair */ |
|
1891
|
|
|
|
|
|
|
} |
|
1892
|
3
|
|
|
|
|
|
pdfmake_dict_set(interp->arena, &dict, key, v); |
|
1893
|
|
|
|
|
|
|
} |
|
1894
|
3
|
|
|
|
|
|
return dict; |
|
1895
|
|
|
|
|
|
|
} |
|
1896
|
|
|
|
|
|
|
|
|
1897
|
|
|
|
|
|
|
/* Simple content stream parser using the existing tokenizer */ |
|
1898
|
64
|
|
|
|
|
|
static pdfmake_err_t parse_content_stream(pdfmake_interp_t *interp, |
|
1899
|
|
|
|
|
|
|
const uint8_t *bytes, |
|
1900
|
|
|
|
|
|
|
size_t len) { |
|
1901
|
|
|
|
|
|
|
pdfmake_tokenizer_t tok; |
|
1902
|
64
|
|
|
|
|
|
pdfmake_tokenizer_init(&tok, bytes, len); |
|
1903
|
|
|
|
|
|
|
|
|
1904
|
9510
|
|
|
|
|
|
while (1) { |
|
1905
|
9574
|
|
|
|
|
|
pdfmake_tok_t t = pdfmake_tok_next_significant(&tok); |
|
1906
|
|
|
|
|
|
|
|
|
1907
|
9574
|
100
|
|
|
|
|
if (t.kind == PDFMAKE_TOK_EOF) { |
|
1908
|
64
|
|
|
|
|
|
break; |
|
1909
|
|
|
|
|
|
|
} |
|
1910
|
|
|
|
|
|
|
|
|
1911
|
9510
|
|
|
|
|
|
switch (t.kind) { |
|
1912
|
2517
|
|
|
|
|
|
case PDFMAKE_TOK_INT: { |
|
1913
|
2517
|
|
|
|
|
|
pdfmake_obj_t obj = pdfmake_int(t.payload.int_val); |
|
1914
|
2517
|
50
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
1915
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
1916
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1917
|
|
|
|
|
|
|
} |
|
1918
|
2517
|
|
|
|
|
|
break; |
|
1919
|
|
|
|
|
|
|
} |
|
1920
|
|
|
|
|
|
|
|
|
1921
|
2302
|
|
|
|
|
|
case PDFMAKE_TOK_REAL: { |
|
1922
|
2302
|
|
|
|
|
|
pdfmake_obj_t obj = pdfmake_real(t.payload.real_val); |
|
1923
|
2302
|
50
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
1924
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
1925
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1926
|
|
|
|
|
|
|
} |
|
1927
|
2302
|
|
|
|
|
|
break; |
|
1928
|
|
|
|
|
|
|
} |
|
1929
|
|
|
|
|
|
|
|
|
1930
|
404
|
|
|
|
|
|
case PDFMAKE_TOK_NAME: { |
|
1931
|
|
|
|
|
|
|
/* Intern the name */ |
|
1932
|
404
|
|
|
|
|
|
const char *name_str = (const char *)(bytes + t.offset + 1); /* Skip / */ |
|
1933
|
404
|
|
|
|
|
|
uint32_t name_id = pdfmake_arena_intern_name(interp->arena, |
|
1934
|
404
|
|
|
|
|
|
name_str, t.length - 1); |
|
1935
|
|
|
|
|
|
|
pdfmake_obj_t obj; |
|
1936
|
404
|
|
|
|
|
|
obj.kind = PDFMAKE_NAME; |
|
1937
|
404
|
|
|
|
|
|
obj.as.name.id = name_id; |
|
1938
|
404
|
50
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
1939
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
1940
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1941
|
|
|
|
|
|
|
} |
|
1942
|
404
|
|
|
|
|
|
break; |
|
1943
|
|
|
|
|
|
|
} |
|
1944
|
|
|
|
|
|
|
|
|
1945
|
436
|
|
|
|
|
|
case PDFMAKE_TOK_LSTR: { |
|
1946
|
|
|
|
|
|
|
pdfmake_obj_t obj; |
|
1947
|
436
|
|
|
|
|
|
obj.kind = PDFMAKE_STR; |
|
1948
|
436
|
|
|
|
|
|
obj.as.str.bytes = bytes + t.offset + 1; /* Skip ( */ |
|
1949
|
436
|
|
|
|
|
|
obj.as.str.len = t.length - 2; /* Exclude parens */ |
|
1950
|
436
|
|
|
|
|
|
obj.as.str.hex = 0; |
|
1951
|
436
|
50
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
1952
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
1953
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1954
|
|
|
|
|
|
|
} |
|
1955
|
436
|
|
|
|
|
|
break; |
|
1956
|
|
|
|
|
|
|
} |
|
1957
|
|
|
|
|
|
|
|
|
1958
|
1
|
|
|
|
|
|
case PDFMAKE_TOK_HSTR: { |
|
1959
|
|
|
|
|
|
|
pdfmake_obj_t obj; |
|
1960
|
1
|
|
|
|
|
|
obj.kind = PDFMAKE_STR; |
|
1961
|
1
|
|
|
|
|
|
obj.as.str.bytes = bytes + t.offset + 1; /* Skip < */ |
|
1962
|
1
|
|
|
|
|
|
obj.as.str.len = t.length - 2; /* Exclude angle brackets */ |
|
1963
|
1
|
|
|
|
|
|
obj.as.str.hex = 1; |
|
1964
|
1
|
50
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
1965
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
1966
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1967
|
|
|
|
|
|
|
} |
|
1968
|
1
|
|
|
|
|
|
break; |
|
1969
|
|
|
|
|
|
|
} |
|
1970
|
|
|
|
|
|
|
|
|
1971
|
409
|
|
|
|
|
|
case PDFMAKE_TOK_ARR_OPEN: { |
|
1972
|
|
|
|
|
|
|
/* Parse array - simple recursive handling */ |
|
1973
|
|
|
|
|
|
|
/* For now, use a temporary array */ |
|
1974
|
409
|
|
|
|
|
|
pdfmake_obj_t arr = pdfmake_array_new(interp->arena); |
|
1975
|
409
|
|
|
|
|
|
int depth = 1; |
|
1976
|
6503
|
100
|
|
|
|
|
while (depth > 0) { |
|
1977
|
6094
|
|
|
|
|
|
pdfmake_tok_t at = pdfmake_tok_next_significant(&tok); |
|
1978
|
6094
|
50
|
|
|
|
|
if (at.kind == PDFMAKE_TOK_EOF) { |
|
1979
|
0
|
|
|
|
|
|
break; |
|
1980
|
|
|
|
|
|
|
} |
|
1981
|
6094
|
50
|
|
|
|
|
if (at.kind == PDFMAKE_TOK_ARR_OPEN) { |
|
1982
|
0
|
|
|
|
|
|
depth++; |
|
1983
|
|
|
|
|
|
|
/* Nested arrays not fully handled */ |
|
1984
|
6094
|
100
|
|
|
|
|
} else if (at.kind == PDFMAKE_TOK_ARR_CLOSE) { |
|
1985
|
409
|
|
|
|
|
|
depth--; |
|
1986
|
5685
|
100
|
|
|
|
|
} else if (at.kind == PDFMAKE_TOK_INT) { |
|
1987
|
150
|
|
|
|
|
|
pdfmake_obj_t elem = pdfmake_int(at.payload.int_val); |
|
1988
|
150
|
|
|
|
|
|
pdfmake_array_push(interp->arena, &arr, elem); |
|
1989
|
5535
|
100
|
|
|
|
|
} else if (at.kind == PDFMAKE_TOK_REAL) { |
|
1990
|
2488
|
|
|
|
|
|
pdfmake_obj_t elem = pdfmake_real(at.payload.real_val); |
|
1991
|
2488
|
|
|
|
|
|
pdfmake_array_push(interp->arena, &arr, elem); |
|
1992
|
3047
|
100
|
|
|
|
|
} else if (at.kind == PDFMAKE_TOK_LSTR) { |
|
1993
|
|
|
|
|
|
|
pdfmake_obj_t elem; |
|
1994
|
3042
|
|
|
|
|
|
elem.kind = PDFMAKE_STR; |
|
1995
|
3042
|
|
|
|
|
|
elem.as.str.bytes = bytes + at.offset + 1; |
|
1996
|
3042
|
|
|
|
|
|
elem.as.str.len = at.length - 2; |
|
1997
|
3042
|
|
|
|
|
|
elem.as.str.hex = 0; |
|
1998
|
3042
|
|
|
|
|
|
pdfmake_array_push(interp->arena, &arr, elem); |
|
1999
|
5
|
50
|
|
|
|
|
} else if (at.kind == PDFMAKE_TOK_HSTR) { |
|
2000
|
|
|
|
|
|
|
pdfmake_obj_t elem; |
|
2001
|
5
|
|
|
|
|
|
elem.kind = PDFMAKE_STR; |
|
2002
|
5
|
|
|
|
|
|
elem.as.str.bytes = bytes + at.offset + 1; |
|
2003
|
5
|
|
|
|
|
|
elem.as.str.len = at.length - 2; |
|
2004
|
5
|
|
|
|
|
|
elem.as.str.hex = 1; |
|
2005
|
5
|
|
|
|
|
|
pdfmake_array_push(interp->arena, &arr, elem); |
|
2006
|
|
|
|
|
|
|
} |
|
2007
|
|
|
|
|
|
|
} |
|
2008
|
409
|
50
|
|
|
|
|
if (!push_operand(interp, arr)) { |
|
2009
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
2010
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2011
|
|
|
|
|
|
|
} |
|
2012
|
409
|
|
|
|
|
|
break; |
|
2013
|
|
|
|
|
|
|
} |
|
2014
|
|
|
|
|
|
|
|
|
2015
|
3
|
|
|
|
|
|
case PDFMAKE_TOK_DICT_OPEN: { |
|
2016
|
3
|
|
|
|
|
|
pdfmake_obj_t dict = parse_inline_dict(interp, bytes, &tok); |
|
2017
|
3
|
50
|
|
|
|
|
if (!push_operand(interp, dict)) { |
|
2018
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
2019
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2020
|
|
|
|
|
|
|
} |
|
2021
|
3
|
|
|
|
|
|
break; |
|
2022
|
|
|
|
|
|
|
} |
|
2023
|
|
|
|
|
|
|
|
|
2024
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_TRUE: { |
|
2025
|
0
|
|
|
|
|
|
pdfmake_obj_t obj = pdfmake_bool(1); |
|
2026
|
0
|
0
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
2027
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
2028
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2029
|
|
|
|
|
|
|
} |
|
2030
|
0
|
|
|
|
|
|
break; |
|
2031
|
|
|
|
|
|
|
} |
|
2032
|
|
|
|
|
|
|
|
|
2033
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_FALSE: { |
|
2034
|
0
|
|
|
|
|
|
pdfmake_obj_t obj = pdfmake_bool(0); |
|
2035
|
0
|
0
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
2036
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
2037
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2038
|
|
|
|
|
|
|
} |
|
2039
|
0
|
|
|
|
|
|
break; |
|
2040
|
|
|
|
|
|
|
} |
|
2041
|
|
|
|
|
|
|
|
|
2042
|
0
|
|
|
|
|
|
case PDFMAKE_TOK_KW_NULL: { |
|
2043
|
0
|
|
|
|
|
|
pdfmake_obj_t obj = pdfmake_null(); |
|
2044
|
0
|
0
|
|
|
|
|
if (!push_operand(interp, obj)) { |
|
2045
|
0
|
|
|
|
|
|
set_error(interp, PDFMAKE_ENOMEM, t.offset, "Operand stack overflow"); |
|
2046
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2047
|
|
|
|
|
|
|
} |
|
2048
|
0
|
|
|
|
|
|
break; |
|
2049
|
|
|
|
|
|
|
} |
|
2050
|
|
|
|
|
|
|
|
|
2051
|
3438
|
|
|
|
|
|
case PDFMAKE_TOK_ERROR: |
|
2052
|
|
|
|
|
|
|
default: { |
|
2053
|
|
|
|
|
|
|
/* Try to interpret as operator */ |
|
2054
|
3438
|
|
|
|
|
|
const char *op_str = (const char *)(bytes + t.offset); |
|
2055
|
3438
|
|
|
|
|
|
op_handler_t handler = find_operator(op_str, t.length); |
|
2056
|
|
|
|
|
|
|
|
|
2057
|
3438
|
50
|
|
|
|
|
if (handler) { |
|
2058
|
3438
|
|
|
|
|
|
pdfmake_err_t err = handler(interp); |
|
2059
|
3438
|
50
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
2060
|
0
|
|
|
|
|
|
return err; |
|
2061
|
|
|
|
|
|
|
} |
|
2062
|
|
|
|
|
|
|
} else { |
|
2063
|
|
|
|
|
|
|
/* Unknown operator - skip */ |
|
2064
|
|
|
|
|
|
|
} |
|
2065
|
3438
|
|
|
|
|
|
break; |
|
2066
|
|
|
|
|
|
|
} |
|
2067
|
|
|
|
|
|
|
} |
|
2068
|
|
|
|
|
|
|
} |
|
2069
|
|
|
|
|
|
|
|
|
2070
|
64
|
|
|
|
|
|
return PDFMAKE_OK; |
|
2071
|
|
|
|
|
|
|
} |
|
2072
|
|
|
|
|
|
|
|
|
2073
|
|
|
|
|
|
|
/*============================================================================ |
|
2074
|
|
|
|
|
|
|
* Main interpret function |
|
2075
|
|
|
|
|
|
|
*==========================================================================*/ |
|
2076
|
|
|
|
|
|
|
|
|
2077
|
60
|
|
|
|
|
|
pdfmake_err_t pdfmake_interpret(pdfmake_interp_t *interp, |
|
2078
|
|
|
|
|
|
|
const uint8_t *bytes, |
|
2079
|
|
|
|
|
|
|
size_t len) { |
|
2080
|
60
|
50
|
|
|
|
|
if (!interp || !bytes) { |
|
|
|
50
|
|
|
|
|
|
|
2081
|
0
|
|
|
|
|
|
return PDFMAKE_EINVAL; |
|
2082
|
|
|
|
|
|
|
} |
|
2083
|
|
|
|
|
|
|
|
|
2084
|
60
|
|
|
|
|
|
pdfmake_interp_reset(interp); |
|
2085
|
|
|
|
|
|
|
|
|
2086
|
60
|
|
|
|
|
|
return parse_content_stream(interp, bytes, len); |
|
2087
|
|
|
|
|
|
|
} |