Coverage Report

Created: 2026-08-08 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};