/src/ghostpdl/pcl/pcl/pgvector.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* pgvector.c */ |
18 | | /* HP-GL/2 vector commands */ |
19 | | |
20 | | #include "stdio_.h" /* for gdebug.h */ |
21 | | #include "gdebug.h" |
22 | | #include "pcparse.h" |
23 | | #include "pgmand.h" |
24 | | #include "pggeom.h" |
25 | | #include "pgdraw.h" |
26 | | #include "pgmisc.h" |
27 | | #include "gspath.h" |
28 | | #include "gscoord.h" |
29 | | #include "math_.h" |
30 | | |
31 | | /* ------ Internal procedures ------ */ |
32 | | |
33 | | /* Draw an arc (AA, AR). */ |
34 | | static int |
35 | | hpgl_arc(hpgl_args_t * pargs, hpgl_state_t * pgls, bool relative) |
36 | 2.94k | { |
37 | 2.94k | hpgl_real_t x_center, y_center, sweep, x_current, y_current, chord_angle = |
38 | 2.94k | 5; |
39 | 2.94k | hpgl_real_t radius, start_angle; |
40 | | |
41 | 2.94k | if (!hpgl_arg_units(pgls->memory, pargs, &x_center) || |
42 | 128 | !hpgl_arg_units(pgls->memory, pargs, &y_center) || |
43 | 100 | !hpgl_arg_c_real(pgls->memory, pargs, &sweep) |
44 | 2.94k | ) |
45 | 2.87k | return e_Range; |
46 | | |
47 | 76 | hpgl_arg_c_real(pgls->memory, pargs, &chord_angle); |
48 | | |
49 | 76 | if (current_units_out_of_range(x_center) || |
50 | 73 | current_units_out_of_range(y_center)) |
51 | 0 | return 0; |
52 | | |
53 | 76 | x_current = pgls->g.pos.x; |
54 | 76 | y_current = pgls->g.pos.y; |
55 | | |
56 | 76 | if (relative) { |
57 | 63 | x_center += x_current; |
58 | 63 | y_center += y_current; |
59 | 63 | } |
60 | | |
61 | 76 | radius = hpgl_compute_distance(x_current, y_current, x_center, y_center); |
62 | | |
63 | 76 | start_angle = radians_to_degrees * |
64 | 76 | hpgl_compute_angle(x_current - x_center, y_current - y_center); |
65 | | |
66 | 76 | hpgl_call(hpgl_add_arc_to_path(pgls, x_center, y_center, |
67 | 76 | radius, start_angle, sweep, |
68 | 76 | chord_angle, |
69 | 76 | false, pgls->g.move_or_draw, true)); |
70 | | |
71 | 76 | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
72 | 76 | return 0; |
73 | 76 | } |
74 | | |
75 | | /* Draw a 3-point arc (AT, RT). */ |
76 | | static int |
77 | | hpgl_arc_3_point(hpgl_args_t * pargs, hpgl_state_t * pgls, bool relative) |
78 | 3.98k | { |
79 | 3.98k | hpgl_real_t x_start = pgls->g.pos.x, y_start = pgls->g.pos.y; |
80 | 3.98k | hpgl_real_t x_inter, y_inter, x_end, y_end; |
81 | 3.98k | hpgl_real_t chord_angle = 5; |
82 | | |
83 | 3.98k | if (!hpgl_arg_units(pgls->memory, pargs, &x_inter) || |
84 | 396 | !hpgl_arg_units(pgls->memory, pargs, &y_inter) || |
85 | 1 | !hpgl_arg_units(pgls->memory, pargs, &x_end) || |
86 | 0 | !hpgl_arg_units(pgls->memory, pargs, &y_end) |
87 | 3.98k | ) |
88 | 3.98k | return e_Range; |
89 | | |
90 | 4 | hpgl_arg_c_real(pgls->memory, pargs, &chord_angle); |
91 | | |
92 | 4 | if (relative) { |
93 | 0 | x_inter += x_start; |
94 | 0 | y_inter += y_start; |
95 | 0 | x_end += x_start; |
96 | 0 | y_end += y_start; |
97 | 0 | } |
98 | | |
99 | 4 | hpgl_call(hpgl_add_arc_3point_to_path(pgls, |
100 | 4 | x_start, y_start, |
101 | 4 | x_inter, y_inter, |
102 | 4 | x_end, y_end, chord_angle, |
103 | 4 | pgls->g.move_or_draw)); |
104 | 4 | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
105 | 4 | return 0; |
106 | 4 | } |
107 | | |
108 | | /* Draw a Bezier (BR, BZ). */ |
109 | | static int |
110 | | hpgl_bezier(hpgl_args_t * pargs, hpgl_state_t * pgls, bool relative) |
111 | 97 | { |
112 | 97 | hpgl_real_t x_start, y_start; |
113 | | |
114 | | /* |
115 | | * Since these commands take an arbitrary number of arguments, |
116 | | * we reset the argument bookkeeping after each group. |
117 | | */ |
118 | | |
119 | 97 | for (;;) { |
120 | 97 | hpgl_real_t coords[6]; |
121 | 97 | int i; |
122 | | |
123 | 99 | for (i = 0; i < 6 && hpgl_arg_units(pgls->memory, pargs, &coords[i]); |
124 | 97 | ++i); |
125 | 97 | switch (i) { |
126 | 95 | case 0: /* done */ |
127 | 95 | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
128 | | /* draw the path */ |
129 | 95 | if (!pgls->g.polygon_mode) { |
130 | | /* apparently only round and beveled joins are |
131 | | allowed 5 is bevel and 4 is round */ |
132 | 68 | int save_join = pgls->g.line.join; |
133 | | |
134 | 68 | if (pgls->g.line.join != 1 && pgls->g.line.join != 4) |
135 | 0 | pgls->g.line.join = 1; /* bevel */ |
136 | 68 | hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); |
137 | 68 | pgls->g.line.join = save_join; |
138 | 68 | } |
139 | 95 | return 0; |
140 | 0 | case 6: |
141 | 0 | break; |
142 | 2 | default: |
143 | 2 | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
144 | 2 | return e_Range; |
145 | 97 | } |
146 | | |
147 | 0 | x_start = pgls->g.pos.x; |
148 | 0 | y_start = pgls->g.pos.y; |
149 | |
|
150 | 0 | if (relative) |
151 | 0 | hpgl_call(hpgl_add_bezier_to_path(pgls, x_start, y_start, |
152 | 0 | x_start + coords[0], |
153 | 0 | y_start + coords[1], |
154 | 0 | x_start + coords[2], |
155 | 0 | y_start + coords[3], |
156 | 0 | x_start + coords[4], |
157 | 0 | y_start + coords[5], |
158 | 0 | pgls->g.move_or_draw)); |
159 | 0 | else |
160 | 0 | hpgl_call(hpgl_add_bezier_to_path(pgls, x_start, y_start, |
161 | 0 | coords[0], coords[1], |
162 | 0 | coords[2], coords[3], |
163 | 0 | coords[4], coords[5], |
164 | 0 | pgls->g.move_or_draw)); |
165 | | /* Prepare for the next set of points. */ |
166 | 0 | hpgl_args_init(pargs); |
167 | 0 | } |
168 | 97 | } |
169 | | |
170 | | /* Plot points, symbols, or lines (PA, PD, PR, PU). */ |
171 | | static int |
172 | | hpgl_plot(hpgl_args_t * pargs, hpgl_state_t * pgls, |
173 | | hpgl_plot_function_t func, bool is_PA) |
174 | 394k | { |
175 | | /* |
176 | | * Since these commands take an arbitrary number of arguments, |
177 | | * we reset the argument bookkeeping after each group. |
178 | | */ |
179 | | /* bool first_loop = true; */ |
180 | 394k | hpgl_real_t x, y; |
181 | | |
182 | 394k | if (hpgl_plot_is_move(func) && !pgls->g.polygon_mode) { |
183 | 178k | hpgl_call(hpgl_close_path(pgls)); |
184 | 178k | } |
185 | 747k | while (hpgl_arg_units(pgls->memory, pargs, &x) && |
186 | 353k | hpgl_arg_units(pgls->memory, pargs, &y)) { |
187 | | |
188 | 352k | if (current_units_out_of_range(x) || current_units_out_of_range(y)) |
189 | 4 | return e_Range; |
190 | | |
191 | 352k | pargs->phase = 1; /* we have arguments */ |
192 | | |
193 | 352k | hpgl_call(hpgl_add_point_to_path(pgls, x, y, func, true)); |
194 | 352k | if (hpgl_plot_is_draw(func)) |
195 | 173k | pgls->g.have_drawn_in_path = true; |
196 | | |
197 | | /* Prepare for the next set of points. */ |
198 | 352k | if (pgls->g.symbol_mode != 0) |
199 | 352k | hpgl_call(hpgl_print_symbol_mode_char(pgls)); |
200 | 352k | hpgl_args_init(pargs); |
201 | 352k | } |
202 | | |
203 | | /* Check for no argument, no polygon, absolute PD will cause a |
204 | | point to be added to the path. A PA command without arguments |
205 | | will not add a point. NB this probably needs more testing. */ |
206 | | |
207 | 394k | if (!pargs->phase && hpgl_plot_is_absolute(func) && !pgls->g.polygon_mode |
208 | 37.0k | && !is_PA) { |
209 | 35.7k | gs_point cur_point; |
210 | | |
211 | 35.7k | hpgl_call(hpgl_get_current_position(pgls, &cur_point)); |
212 | 35.7k | hpgl_call(hpgl_add_point_to_path(pgls, cur_point.x, |
213 | 35.7k | cur_point.y, func, true)); |
214 | 35.7k | } |
215 | 394k | if (pgls->g.symbol_mode != 0) |
216 | 394k | hpgl_call(hpgl_print_symbol_mode_char(pgls)); |
217 | | |
218 | | /* don't update if no arguments */ |
219 | 394k | if (pargs->phase) |
220 | 394k | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
221 | 394k | return 0; |
222 | 394k | } |
223 | | |
224 | | /* ------ Commands ------ */ |
225 | | static int |
226 | | hpgl_draw_arc(hpgl_state_t * pgls) |
227 | 40.3k | { |
228 | 40.3k | if (!pgls->g.polygon_mode) |
229 | 40.3k | hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); |
230 | 40.3k | return 0; |
231 | 40.3k | } |
232 | | |
233 | | /* AA xcenter,ycenter,sweep[,chord]; */ |
234 | | int |
235 | | hpgl_AA(hpgl_args_t * pargs, hpgl_state_t * pgls) |
236 | 594 | { |
237 | 594 | hpgl_call(hpgl_arc(pargs, pgls, false)); |
238 | 594 | hpgl_call(hpgl_draw_arc(pgls)); |
239 | 594 | return 0; |
240 | 594 | } |
241 | | |
242 | | /* AR xcenter,ycenter,sweep[,chord]; */ |
243 | | int |
244 | | hpgl_AR(hpgl_args_t * pargs, hpgl_state_t * pgls) |
245 | 2.35k | { |
246 | 2.35k | hpgl_call(hpgl_arc(pargs, pgls, true)); |
247 | 2.35k | hpgl_call(hpgl_draw_arc(pgls)); |
248 | 2.35k | return 0; |
249 | 2.35k | } |
250 | | |
251 | | /* AT xinter,yinter,xend,yend[,chord]; */ |
252 | | int |
253 | | hpgl_AT(hpgl_args_t * pargs, hpgl_state_t * pgls) |
254 | 3.27k | { |
255 | 3.27k | hpgl_call(hpgl_arc_3_point(pargs, pgls, false)); |
256 | 3.27k | hpgl_call(hpgl_draw_arc(pgls)); |
257 | 3.27k | return 0; |
258 | 3.27k | } |
259 | | |
260 | | /* BR x1,y1,x2,y2,x3,y3...; */ |
261 | | int |
262 | | hpgl_BR(hpgl_args_t * pargs, hpgl_state_t * pgls) |
263 | 56 | { |
264 | 56 | return hpgl_bezier(pargs, pgls, true); |
265 | 56 | } |
266 | | |
267 | | /* BZ x1,y1,x2,y2,x3,y3...; */ |
268 | | int |
269 | | hpgl_BZ(hpgl_args_t * pargs, hpgl_state_t * pgls) |
270 | 41 | { |
271 | 41 | return hpgl_bezier(pargs, pgls, false); |
272 | 41 | } |
273 | | |
274 | | /* CI radius[,chord]; */ |
275 | | int |
276 | | hpgl_CI(hpgl_args_t * pargs, hpgl_state_t * pgls) |
277 | 36.3k | { |
278 | 36.3k | hpgl_real_t radius, chord = 5; |
279 | 36.3k | bool reset_ctm = true; |
280 | 36.3k | gs_point pos; |
281 | | |
282 | 36.3k | if (!hpgl_arg_units(pgls->memory, pargs, &radius)) |
283 | 407 | return e_Range; |
284 | | |
285 | | /* center; closing subpolygon can move center */ |
286 | 35.9k | pos = pgls->g.pos; |
287 | | |
288 | 35.9k | if (!pgls->g.polygon_mode) |
289 | 35.9k | hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); |
290 | | |
291 | 35.9k | hpgl_arg_c_real(pgls->memory, pargs, &chord); |
292 | | |
293 | | /* draw the arc/circle */ |
294 | 35.9k | hpgl_call(hpgl_add_arc_to_path(pgls, pos.x, pos.y, |
295 | 35.9k | radius, 0.0, 360.0, chord, true, |
296 | 35.9k | hpgl_plot_draw_absolute, reset_ctm)); |
297 | 35.9k | if (!pgls->g.polygon_mode) |
298 | 35.9k | hpgl_call(hpgl_draw_arc(pgls)); |
299 | | |
300 | 35.9k | hpgl_call(hpgl_close_current_path(pgls)); |
301 | 35.9k | pgls->g.have_drawn_in_path = false; /* prevent dot draw on close */ |
302 | 35.9k | hpgl_call(hpgl_set_current_position(pgls, &pos)); |
303 | | |
304 | 35.9k | if (!pgls->g.polygon_mode) |
305 | 35.9k | hpgl_call(hpgl_clear_current_path(pgls)); |
306 | | |
307 | 35.9k | return 0; |
308 | 35.9k | } |
309 | | |
310 | | /* PA x,y...; */ |
311 | | int |
312 | | hpgl_PA(hpgl_args_t * pargs, hpgl_state_t * pgls) |
313 | 55.6k | { |
314 | | |
315 | 55.6k | if (pgls->g.relative_coords != hpgl_plot_absolute) { |
316 | 857 | pgls->g.relative_coords = hpgl_plot_absolute; |
317 | 857 | if (!pgls->g.polygon_mode) { |
318 | 854 | hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); |
319 | 854 | hpgl_call(hpgl_clear_current_path(pgls)); |
320 | 854 | } |
321 | 857 | } |
322 | 55.6k | return hpgl_plot(pargs, pgls, |
323 | 55.6k | pgls->g.move_or_draw | hpgl_plot_absolute, |
324 | 55.6k | true /* is PA command */ ); |
325 | 55.6k | } |
326 | | |
327 | | /* PD (d)x,(d)y...; */ |
328 | | int |
329 | | hpgl_PD(hpgl_args_t * pargs, hpgl_state_t * pgls) |
330 | 211k | { |
331 | 211k | pgls->g.move_or_draw = hpgl_plot_draw; |
332 | 211k | return hpgl_plot(pargs, pgls, |
333 | 211k | hpgl_plot_draw | pgls->g.relative_coords, |
334 | 211k | false /* is PA command */ ); |
335 | 211k | } |
336 | | |
337 | | /* PE (flag|value|coord)*; */ |
338 | | /* |
339 | | * We record the state of the command in the 'phase' as follows: |
340 | | */ |
341 | | enum |
342 | | { |
343 | | pe_pen_up = 1, /* next coordinate are pen-up move */ |
344 | | pe_absolute = 2, /* next coordinates are absolute */ |
345 | | pe_7bit = 4, /* use 7-bit encoding */ |
346 | | pe_entered = 8 /* we have entered PE once */ |
347 | | }; |
348 | | |
349 | | /* convert pe fixed to float accounting for fractional bits */ |
350 | | static inline double |
351 | | pe_fixed2float(int32 x, int32 fbits) |
352 | 416k | { |
353 | 416k | return ((double) x * (1.0 / pow(2, fbits))); |
354 | 416k | } |
355 | | |
356 | | static int pe_args(const gs_memory_t * mem, hpgl_args_t *, |
357 | | int); |
358 | | |
359 | | static inline void |
360 | | pe_clear_args(hpgl_args_t * pargs) |
361 | 281k | { |
362 | 281k | pargs->pe_shift[0] = pargs->pe_shift[1] = 0; |
363 | 281k | pargs->pe_values[0] = pargs->pe_values[1] = 0; |
364 | 281k | pargs->pe_indx = 0; |
365 | 281k | } |
366 | | |
367 | | int |
368 | | hpgl_PE(hpgl_args_t * pargs, hpgl_state_t * pgls) |
369 | 195k | { |
370 | | /* |
371 | | * To simplify the control structure here, we require that |
372 | | * the input buffer be large enough to hold 2 coordinates |
373 | | * in the base 32 encoding, i.e., 14 bytes. We're counting on |
374 | | * there not being any whitespace within coordinate values.... |
375 | | */ |
376 | 195k | const byte *p = pargs->source.ptr; |
377 | 195k | const byte *rlimit = pargs->source.limit; |
378 | | /* count points to allow medium size paths, performance optimization |
379 | | * point_count_max should be smaller than input buffer |
380 | | */ |
381 | 195k | int point_count = 0; |
382 | 195k | static const int point_count_max = 100; |
383 | | |
384 | 195k | if (pargs->phase == 0) { |
385 | | /* After PE is executed, the previous plotting mode (absolute or |
386 | | relative) is restored. If the finnal move is made with the pen up, |
387 | | the pen remains in the up position; otherwise the pen is left in |
388 | | the down position. At least HP documented this bug. */ |
389 | 72.8k | hpgl_save_pen_state(pgls, &pgls->g.pen_state, hpgl_pen_relative); |
390 | 72.8k | pargs->phase |= pe_entered; |
391 | 72.8k | pgls->g.fraction_bits = 0; |
392 | 72.8k | pe_clear_args(pargs); |
393 | 72.8k | } |
394 | 546k | while (p < rlimit) { |
395 | 545k | byte ch = *(pargs->source.ptr = ++p); |
396 | | |
397 | 545k | switch (ch & 127 /* per spec */ ) { |
398 | 71.6k | case ';': |
399 | 71.6k | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
400 | 71.6k | if (pargs->phase & pe_entered) |
401 | 71.6k | hpgl_restore_pen_state(pgls, &pgls->g.pen_state, |
402 | 71.6k | hpgl_pen_relative); |
403 | | /* prevent paths from getting excessively large */ |
404 | 71.6k | if (!pgls->g.polygon_mode) |
405 | 71.6k | hpgl_call(hpgl_draw_current_path(pgls, hpgl_rm_vector)); |
406 | 71.6k | return 0; |
407 | 429 | case ':': |
408 | 429 | if_debug0m('i', pgls->memory, "\n PE SP"); |
409 | 429 | { |
410 | 429 | int32 pen; |
411 | 429 | int ret = pe_args(pgls->memory, pargs, 1); |
412 | | |
413 | 429 | if (ret != gs_error_ok) { |
414 | 405 | if (ret == gs_error_NeedInput) |
415 | 0 | pargs->source.ptr = p - 1; |
416 | 405 | break; |
417 | 405 | } |
418 | 24 | pen = pargs->pe_values[0]; |
419 | 24 | pe_clear_args(pargs); |
420 | 24 | if (!pgls->g.polygon_mode) { |
421 | 16 | hpgl_args_t args; |
422 | | |
423 | 16 | hpgl_args_set_int(&args, pen); |
424 | | /* Note SP is illegal in polygon mode we must handle that here */ |
425 | 16 | hpgl_call(hpgl_SP(&args, pgls)); |
426 | 16 | } |
427 | 24 | } |
428 | 24 | p = pargs->source.ptr; |
429 | 24 | continue; |
430 | 35.6k | case '<': |
431 | 35.6k | if_debug0m('i', pgls->memory, "\n PE PU"); |
432 | 35.6k | pargs->phase |= pe_pen_up; |
433 | 35.6k | continue; |
434 | 349 | case '>': |
435 | 349 | if_debug0m('i', pgls->memory, "\n PE PD"); |
436 | 349 | { |
437 | 349 | int32 fbits; |
438 | 349 | int ret = pe_args(pgls->memory, pargs, 1); |
439 | | |
440 | 349 | if (ret != gs_error_ok) { |
441 | 321 | if (ret == gs_error_NeedInput) |
442 | 0 | pargs->source.ptr = p - 1; |
443 | 321 | break; |
444 | 321 | } |
445 | 28 | fbits = pargs->pe_values[0]; |
446 | 28 | pe_clear_args(pargs); |
447 | 28 | if (fbits < -26 || fbits > 26) |
448 | 19 | return e_Range; |
449 | 9 | pgls->g.fraction_bits = fbits; |
450 | 9 | } |
451 | 0 | p = pargs->source.ptr; |
452 | 9 | continue; |
453 | 35.5k | case '=': |
454 | 35.5k | if_debug0m('i', pgls->memory, " PE ABS"); |
455 | 35.5k | pargs->phase |= pe_absolute; |
456 | 35.5k | continue; |
457 | 467 | case '7': |
458 | 467 | if_debug0m('i', pgls->memory, "\n PE 7bit"); |
459 | 467 | pargs->phase |= pe_7bit; |
460 | 467 | continue; |
461 | 1.46k | case ESC: |
462 | | /* |
463 | | * This is something of a hack. Apparently we're supposed |
464 | | * to parse all PCL commands embedded in the GL/2 stream, |
465 | | * and simply ignore everything except the 3 that end GL/2 |
466 | | * mode. Instead, we simply stop parsing PE arguments as |
467 | | * soon as we see an ESC. |
468 | | */ |
469 | 1.46k | if (ch == ESC) { /* (might be ESC+128) */ |
470 | 1.02k | pargs->source.ptr = p - 1; /* rescan ESC */ |
471 | 1.02k | if (pargs->phase & pe_entered) { |
472 | 1.02k | hpgl_restore_pen_state(pgls, &pgls->g.pen_state, |
473 | 1.02k | hpgl_pen_relative); |
474 | 1.02k | } |
475 | 1.02k | hpgl_call(hpgl_update_carriage_return_pos(pgls)); |
476 | 1.02k | return 0; |
477 | 1.02k | } |
478 | | /* falls through */ |
479 | 400k | default: |
480 | 400k | if ((ch & 127) <= 32 || (ch & 127) == 127) |
481 | 70.6k | continue; |
482 | 329k | pargs->source.ptr = p - 1; |
483 | 329k | { |
484 | 329k | int32 xy[2]; |
485 | 329k | hpgl_args_t args; |
486 | 329k | int32 fbits = pgls->g.fraction_bits; |
487 | | |
488 | 329k | if (pe_args(pgls->memory, pargs, 2) != gs_error_ok) |
489 | 121k | break; |
490 | 208k | xy[0] = pargs->pe_values[0]; |
491 | 208k | xy[1] = pargs->pe_values[1]; |
492 | 208k | pe_clear_args(pargs); |
493 | 208k | if (pargs->phase & pe_absolute) |
494 | 34.7k | pgls->g.relative_coords = hpgl_plot_absolute; |
495 | 173k | else |
496 | 173k | pgls->g.relative_coords = hpgl_plot_relative; |
497 | 208k | hpgl_args_set_real2(&args, pe_fixed2float(xy[0], fbits), |
498 | 208k | pe_fixed2float(xy[1], fbits)); |
499 | | /* prevent paths from getting excessively large */ |
500 | 208k | if (!pgls->g.polygon_mode |
501 | 40.5k | && point_count > point_count_max) { |
502 | 0 | hpgl_call(hpgl_draw_current_path |
503 | 0 | (pgls, hpgl_rm_vector)); |
504 | 0 | point_count = 0; |
505 | 0 | } |
506 | 208k | if (pargs->phase & pe_pen_up) { |
507 | 34.7k | hpgl_call(hpgl_PU(&args, pgls)); |
508 | 34.7k | } else |
509 | 208k | hpgl_call(hpgl_PD(&args, pgls)); |
510 | 208k | point_count++; |
511 | 208k | } |
512 | 0 | pargs->phase &= ~(pe_pen_up | pe_absolute); |
513 | 208k | p = pargs->source.ptr; |
514 | 208k | continue; |
515 | 545k | } |
516 | 122k | break; |
517 | 545k | } |
518 | 122k | return gs_error_NeedInput; |
519 | 195k | } |
520 | | /* Get an encoded value from the input. */ |
521 | | static int |
522 | | pe_args(const gs_memory_t * mem, hpgl_args_t * pargs, int count) |
523 | 330k | { |
524 | 330k | const byte *p = pargs->source.ptr; |
525 | 330k | const byte *rlimit = pargs->source.limit; |
526 | 330k | int i; |
527 | | |
528 | 749k | for (i = pargs->pe_indx; i < count; ++i) { |
529 | | |
530 | 2.00M | #define VALUE (pargs->pe_values[i]) |
531 | 2.35M | #define SHIFT (pargs->pe_shift[i]) |
532 | | |
533 | 892k | for (;;) { |
534 | 892k | int ch; |
535 | | |
536 | 892k | if (p >= rlimit) { |
537 | 306 | pargs->pe_indx = i; |
538 | 306 | pargs->source.ptr = p; |
539 | 306 | return gs_error_NeedInput; |
540 | 306 | } |
541 | 891k | ch = *++p; |
542 | 891k | if ((ch & 127) <= 32 || (ch & 127) == 127) |
543 | 26.0k | continue; |
544 | 865k | if (SHIFT > 30) |
545 | 101k | goto syntax_error; |
546 | 764k | if (pargs->phase & pe_7bit) { |
547 | 5.00k | ch -= 63; |
548 | 5.00k | if (ch & ~63) |
549 | 2.55k | goto syntax_error; |
550 | 2.45k | VALUE += (int32) (ch & 31) << SHIFT; |
551 | 2.45k | SHIFT += 5; |
552 | 2.45k | if (ch & 32) |
553 | 1.45k | break; |
554 | 759k | } else { |
555 | 759k | ch -= 63; |
556 | 759k | if (ch & ~191) |
557 | 18.7k | goto syntax_error; |
558 | 740k | VALUE += (int32) (ch & 63) << SHIFT; |
559 | 740k | SHIFT += 6; |
560 | 740k | if (ch & 128) |
561 | 417k | break; |
562 | 740k | } |
563 | 764k | } |
564 | 418k | VALUE = (VALUE & 1 ? -(VALUE >> 1) : VALUE >> 1); |
565 | 418k | if_debug1m('i', mem, " [%ld]", (long)VALUE); |
566 | 418k | } |
567 | 208k | pargs->source.ptr = p; |
568 | 208k | return gs_error_ok; |
569 | 122k | syntax_error: |
570 | | /* Just ignore everything we've parsed up to this point. */ |
571 | 122k | pargs->source.ptr = p; |
572 | 122k | return gs_error_syntaxerror; |
573 | 330k | } |
574 | | |
575 | | /* PR dx,dy...; */ |
576 | | int |
577 | | hpgl_PR(hpgl_args_t * pargs, hpgl_state_t * pgls) |
578 | 974 | { |
579 | 974 | if (pgls->g.relative_coords != hpgl_plot_relative) { |
580 | 929 | pgls->g.relative_coords = hpgl_plot_relative; |
581 | 929 | } |
582 | 974 | return hpgl_plot(pargs, pgls, |
583 | 974 | pgls->g.move_or_draw | hpgl_plot_relative, |
584 | 974 | false /* is PA command */ ); |
585 | 974 | } |
586 | | |
587 | | /* PU (d)x,(d)y...; */ |
588 | | int |
589 | | hpgl_PU(hpgl_args_t * pargs, hpgl_state_t * pgls) |
590 | 126k | { |
591 | 126k | int was = pgls->g.move_or_draw; |
592 | | |
593 | 126k | pgls->g.move_or_draw = hpgl_plot_move; |
594 | 126k | if (was == hpgl_plot_move) |
595 | 89.3k | return hpgl_plot(pargs, pgls, |
596 | 89.3k | hpgl_plot_move | pgls->g.relative_coords, |
597 | 89.3k | true /* is PA command */ ); |
598 | 36.7k | else |
599 | 36.7k | return hpgl_plot(pargs, pgls, |
600 | 36.7k | hpgl_plot_move | pgls->g.relative_coords, |
601 | 36.7k | false /* is PA command */ ); |
602 | 126k | } |
603 | | |
604 | | /* RT xinter,yinter,xend,yend[,chord]; */ |
605 | | int |
606 | | hpgl_RT(hpgl_args_t * pargs, hpgl_state_t * pgls) |
607 | 714 | { |
608 | 714 | hpgl_call(hpgl_arc_3_point(pargs, pgls, true)); |
609 | 714 | hpgl_call(hpgl_draw_arc(pgls)); |
610 | 714 | return 0; |
611 | 714 | } |
612 | | |
613 | | /* Initialization */ |
614 | | static int |
615 | | pgvector_do_registration(pcl_parser_state_t * pcl_parser_state, |
616 | | gs_memory_t * mem) |
617 | 16.1k | { |
618 | | /* Register commands */ |
619 | 16.1k | DEFINE_HPGL_COMMANDS(mem) |
620 | 16.1k | HPGL_COMMAND('A', 'A', |
621 | 16.1k | hpgl_AA, |
622 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | hpgl_cdf_pcl_rtl_both), |
623 | 16.1k | HPGL_COMMAND('A', 'R', |
624 | 16.1k | hpgl_AR, |
625 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | hpgl_cdf_pcl_rtl_both), |
626 | 16.1k | HPGL_COMMAND('A', 'T', |
627 | 16.1k | hpgl_AT, |
628 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | hpgl_cdf_pcl_rtl_both), |
629 | 16.1k | HPGL_COMMAND('B', 'R', |
630 | 16.1k | hpgl_BR, |
631 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
632 | 16.1k | HPGL_COMMAND('B', 'Z', |
633 | 16.1k | hpgl_BZ, |
634 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
635 | 16.1k | HPGL_COMMAND('C', 'I', |
636 | 16.1k | hpgl_CI, |
637 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | hpgl_cdf_pcl_rtl_both), |
638 | 16.1k | HPGL_COMMAND('P', 'A', |
639 | 16.1k | hpgl_PA, |
640 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
641 | 16.1k | HPGL_COMMAND('P', 'D', |
642 | 16.1k | hpgl_PD, |
643 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
644 | 16.1k | HPGL_COMMAND('P', 'E', |
645 | 16.1k | hpgl_PE, |
646 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), |
647 | 16.1k | HPGL_COMMAND('P', 'R', |
648 | 16.1k | hpgl_PR, |
649 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
650 | 16.1k | HPGL_COMMAND('P', 'U', |
651 | 16.1k | hpgl_PU, |
652 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_pcl_rtl_both), /* argument pattern can repeat */ |
653 | 16.1k | HPGL_COMMAND('R', 'T', |
654 | 16.1k | hpgl_RT, |
655 | 16.1k | hpgl_cdf_polygon | hpgl_cdf_lost_mode_cleared | |
656 | 16.1k | hpgl_cdf_pcl_rtl_both), |
657 | 16.1k | END_HPGL_COMMANDS |
658 | 16.1k | return 0; |
659 | 16.1k | } |
660 | | |
661 | | const pcl_init_t pgvector_init = { |
662 | | pgvector_do_registration, 0 |
663 | | }; |