Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/gs/src/zdps1.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1990, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: zdps1.c,v 1.8 2005/10/04 06:30:02 ray Exp $ */
18
/* Level 2 / Display PostScript graphics extensions */
19
#include "ghost.h"
20
#include "oper.h"
21
#include "gsmatrix.h"
22
#include "gspath.h"
23
#include "gspath2.h"
24
#include "gsstate.h"
25
#include "ialloc.h"
26
#include "igstate.h"
27
#include "ivmspace.h"
28
#include "store.h"
29
#include "stream.h"
30
#include "ibnum.h"
31
 
32
/* Forward references */
33
private int gstate_unshare(i_ctx_t *);
34
 
35
/* Declare exported procedures (for zupath.c) */
36
int zsetbbox(i_ctx_t *);
37
 
38
/* Structure descriptors */
39
public_st_igstate_obj();
40
 
41
/* Extend the `copy' operator to deal with gstates. */
42
/* This is done with a hack -- we know that gstates are the only */
43
/* t_astruct subtype that implements copy. */
44
private int
45
z1copy(i_ctx_t *i_ctx_p)
46
{
47
    os_ptr op = osp;
48
    int code = zcopy(i_ctx_p);
49
 
50
    if (code >= 0)
51
	return code;
52
    if (!r_has_type(op, t_astruct))
53
	return code;
54
    return zcopy_gstate(i_ctx_p);
55
}
56
 
57
/* ------ Graphics state ------ */
58
 
59
/* <bool> setstrokeadjust - */
60
private int
61
zsetstrokeadjust(i_ctx_t *i_ctx_p)
62
{
63
    os_ptr op = osp;
64
 
65
    check_type(*op, t_boolean);
66
    gs_setstrokeadjust(igs, op->value.boolval);
67
    pop(1);
68
    return 0;
69
}
70
 
71
/* - currentstrokeadjust <bool> */
72
private int
73
zcurrentstrokeadjust(i_ctx_t *i_ctx_p)
74
{
75
    os_ptr op = osp;
76
 
77
    push(1);
78
    make_bool(op, gs_currentstrokeadjust(igs));
79
    return 0;
80
}
81
 
82
/* ------ Graphics state objects ------ */
83
 
84
/*
85
 * Check to make sure that all the elements of a graphics state
86
 * can be stored in the given allocation space.
87
 */
88
/* ****** DOESN'T CHECK THE NON-REFS. ****** */
89
private int
90
gstate_check_space(i_ctx_t *i_ctx_p, int_gstate *isp, uint space)
91
{
92
    /*
93
     * ****** WORKAROUND ALERT ******
94
     * This code doesn't check the space of the non-refs, or copy their
95
     * contents, so it can create dangling references from global VM to
96
     * local VM.  Because of this, we simply disallow writing into gstates
97
     * in global VM (including creating them in the first place) if the
98
     * save level is greater than 0.
99
     * ****** WORKAROUND ALERT ******
100
     */
101
#if 1				/* ****** WORKAROUND ****** */
102
    if (space != avm_local && imemory_save_level(iimemory) > 0)
103
	return_error(e_invalidaccess);
104
#endif				/* ****** END ****** */
105
#define gsref_check(p) store_check_space(space, p)
106
    int_gstate_map_refs(isp, gsref_check);
107
#undef gsref_check
108
    return 0;
109
}
110
 
111
/* - gstate <gstate> */
112
int
113
zgstate(i_ctx_t *i_ctx_p)
114
{
115
    os_ptr op = osp;
116
 
117
    int code = gstate_check_space(i_ctx_p, istate, icurrent_space);
118
    igstate_obj *pigo;
119
    gs_state *pnew;
120
    int_gstate *isp;
121
 
122
    if (code < 0)
123
	return code;
124
    pigo = ialloc_struct(igstate_obj, &st_igstate_obj, "gstate");
125
    if (pigo == 0)
126
	return_error(e_VMerror);
127
    pnew = gs_state_copy(igs, imemory);
128
    if (pnew == 0) {
129
	ifree_object(pigo, "gstate");
130
	return_error(e_VMerror);
131
    }
132
    isp = gs_int_gstate(pnew);
133
    int_gstate_map_refs(isp, ref_mark_new);
134
    push(1);
135
    /*
136
     * Since igstate_obj isn't a ref, but only contains a ref, save won't
137
     * clear its l_new bit automatically, and restore won't set it
138
     * automatically; we have to make sure this ref is on the changes chain.
139
     */
140
    make_iastruct(op, a_all, pigo);
141
    make_null(&pigo->gstate);
142
    ref_save(op, &pigo->gstate, "gstate");
143
    make_istruct_new(&pigo->gstate, 0, pnew);
144
    return 0;
145
}
146
 
147
/* copy for gstates */
148
int
149
zcopy_gstate(i_ctx_t *i_ctx_p)
150
{
151
    os_ptr op = osp;
152
    os_ptr op1 = op - 1;
153
    gs_state *pgs;
154
    gs_state *pgs1;
155
    int_gstate *pistate;
156
    gs_memory_t *mem;
157
    int code;
158
 
159
    check_stype(*op, st_igstate_obj);
160
    check_stype(*op1, st_igstate_obj);
161
    check_write(*op);
162
    code = gstate_unshare(i_ctx_p);
163
    if (code < 0)
164
	return code;
165
    pgs = igstate_ptr(op);
166
    pgs1 = igstate_ptr(op1);
167
    pistate = gs_int_gstate(pgs);
168
    code = gstate_check_space(i_ctx_p, gs_int_gstate(pgs1), r_space(op));
169
    if (code < 0)
170
	return code;
171
#define gsref_save(p) ref_save(op, p, "copygstate")
172
    int_gstate_map_refs(pistate, gsref_save);
173
#undef gsref_save
174
    mem = gs_state_swap_memory(pgs, imemory);
175
    code = gs_copygstate(pgs, pgs1);
176
    gs_state_swap_memory(pgs, mem);
177
    if (code < 0)
178
	return code;
179
    int_gstate_map_refs(pistate, ref_mark_new);
180
    *op1 = *op;
181
    pop(1);
182
    return 0;
183
}
184
 
185
/* <gstate> currentgstate <gstate> */
186
int
187
zcurrentgstate(i_ctx_t *i_ctx_p)
188
{
189
    os_ptr op = osp;
190
    gs_state *pgs;
191
    int_gstate *pistate;
192
    int code;
193
    gs_memory_t *mem;
194
 
195
    check_stype(*op, st_igstate_obj);
196
    check_write(*op);
197
    code = gstate_unshare(i_ctx_p);
198
    if (code < 0)
199
	return code;
200
    pgs = igstate_ptr(op);
201
    pistate = gs_int_gstate(pgs);
202
    code = gstate_check_space(i_ctx_p, istate, r_space(op));
203
    if (code < 0)
204
	return code;
205
#define gsref_save(p) ref_save(op, p, "currentgstate")
206
    int_gstate_map_refs(pistate, gsref_save);
207
#undef gsref_save
208
    mem = gs_state_swap_memory(pgs, imemory);
209
    code = gs_currentgstate(pgs, igs);
210
    gs_state_swap_memory(pgs, mem);
211
    if (code < 0)
212
	return code;
213
    int_gstate_map_refs(pistate, ref_mark_new);
214
    return 0;
215
}
216
 
217
/* <gstate> setgstate - */
218
int
219
zsetgstate(i_ctx_t *i_ctx_p)
220
{
221
    os_ptr op = osp;
222
    int code;
223
 
224
    check_stype(*op, st_igstate_obj);
225
    check_read(*op);
226
    code = gs_setgstate(igs, igstate_ptr(op));
227
    if (code < 0)
228
	return code;
229
    pop(1);
230
    return 0;
231
}
232
 
233
/* ------ Rectangles ------- */
234
 
235
/*
236
 * We preallocate a short list for rectangles, because
237
 * the rectangle operators usually will involve very few rectangles.
238
 */
239
#define MAX_LOCAL_RECTS 5
240
typedef struct local_rects_s {
241
    gs_rect *pr;
242
    uint count;
243
    gs_rect rl[MAX_LOCAL_RECTS];
244
} local_rects_t;
245
 
246
/* Forward references */
247
private int rect_get(local_rects_t *, os_ptr, gs_memory_t *);
248
private void rect_release(local_rects_t *, gs_memory_t *);
249
 
250
/* <x> <y> <width> <height> .rectappend - */
251
/* <numarray|numstring> .rectappend - */
252
private int
253
zrectappend(i_ctx_t *i_ctx_p)
254
{
255
    os_ptr op = osp;
256
    local_rects_t lr;
257
    int npop = rect_get(&lr, op, imemory);
258
    int code;
259
 
260
    if (npop < 0)
261
	return npop;
262
    code = gs_rectappend(igs, lr.pr, lr.count);
263
    rect_release(&lr, imemory);
264
    if (code < 0)
265
	return code;
266
    pop(npop);
267
    return 0;
268
}
269
 
270
/* <x> <y> <width> <height> rectclip - */
271
/* <numarray|numstring> rectclip - */
272
private int
273
zrectclip(i_ctx_t *i_ctx_p)
274
{
275
    os_ptr op = osp;
276
    local_rects_t lr;
277
    int npop = rect_get(&lr, op, imemory);
278
    int code;
279
 
280
    if (npop < 0)
281
	return npop;
282
    code = gs_rectclip(igs, lr.pr, lr.count);
283
    rect_release(&lr, imemory);
284
    if (code < 0)
285
	return code;
286
    pop(npop);
287
    return 0;
288
}
289
 
290
/* <x> <y> <width> <height> rectfill - */
291
/* <numarray|numstring> rectfill - */
292
private int
293
zrectfill(i_ctx_t *i_ctx_p)
294
{
295
    os_ptr op = osp;
296
    local_rects_t lr;
297
    int npop = rect_get(&lr, op, imemory);
298
    int code;
299
 
300
    if (npop < 0)
301
	return npop;
302
    code = gs_rectfill(igs, lr.pr, lr.count);
303
    rect_release(&lr, imemory);
304
    if (code < 0)
305
	return code;
306
    pop(npop);
307
    return 0;
308
}
309
 
310
/* <x> <y> <width> <height> rectstroke - */
311
/* <numarray|numstring> rectstroke - */
312
private int
313
zrectstroke(i_ctx_t *i_ctx_p)
314
{
315
    os_ptr op = osp;
316
    gs_matrix mat;
317
    local_rects_t lr;
318
    int npop, code;
319
 
320
    if (read_matrix(imemory, op, &mat) >= 0) {
321
	/* Concatenate the matrix to the CTM just before stroking the path. */
322
	npop = rect_get(&lr, op - 1, imemory);
323
	if (npop < 0)
324
	    return npop;
325
	code = gs_rectstroke(igs, lr.pr, lr.count, &mat);
326
	npop++;
327
    } else {
328
	/* No matrix. */
329
	npop = rect_get(&lr, op, imemory);
330
	if (npop < 0)
331
	    return npop;
332
	code = gs_rectstroke(igs, lr.pr, lr.count, (gs_matrix *) 0);
333
    }
334
    rect_release(&lr, imemory);
335
    if (code < 0)
336
	return code;
337
    pop(npop);
338
    return 0;
339
}
340
 
341
/* --- Internal routines --- */
342
 
343
/* Get rectangles from the stack. */
344
/* Return the number of elements to pop (>0) if OK, <0 if error. */
345
private int
346
rect_get(local_rects_t * plr, os_ptr op, gs_memory_t *mem)
347
{
348
    int format, code;
349
    uint n, count;
350
    gs_rect *pr;
351
    double rv[4];
352
 
353
    switch (r_type(op)) {
354
	case t_array:
355
	case t_mixedarray:
356
	case t_shortarray:
357
	case t_string:
358
	    code = num_array_format(op);
359
	    if (code < 0)
360
		return code;
361
	    format = code;
362
	    count = num_array_size(op, format);
363
	    if (count % 4)
364
		return_error(e_rangecheck);
365
	    count /= 4;
366
	    break;
367
	default:		/* better be 4 numbers */
368
	    code = num_params(op, 4, rv);
369
	    if (code < 0)
370
		return code;
371
	    plr->pr = plr->rl;
372
	    plr->count = 1;
373
	    plr->rl[0].q.x = (plr->rl[0].p.x = rv[0]) + rv[2];
374
	    plr->rl[0].q.y = (plr->rl[0].p.y = rv[1]) + rv[3];
375
	    return 4;
376
    }
377
    plr->count = count;
378
    if (count <= MAX_LOCAL_RECTS)
379
	pr = plr->rl;
380
    else {
381
	pr = (gs_rect *)gs_alloc_byte_array(mem, count, sizeof(gs_rect),
382
					    "rect_get");
383
	if (pr == 0)
384
	    return_error(e_VMerror);
385
    }
386
    plr->pr = pr;
387
    for (n = 0; n < count; n++, pr++) {
388
	ref rnum;
389
	int i;
390
 
391
	for (i = 0; i < 4; i++) {
392
	    code = num_array_get(mem, (const ref *)op, format,
393
				 (n << 2) + i, &rnum);
394
	    switch (code) {
395
		case t_integer:
396
		    rv[i] = rnum.value.intval;
397
		    break;
398
		case t_real:
399
		    rv[i] = rnum.value.realval;
400
		    break;
401
		default:	/* code < 0 */
402
		    return code;
403
	    }
404
	}
405
	pr->q.x = (pr->p.x = rv[0]) + rv[2];
406
	pr->q.y = (pr->p.y = rv[1]) + rv[3];
407
    }
408
    return 1;
409
}
410
 
411
/* Release the rectangle list if needed. */
412
private void
413
rect_release(local_rects_t * plr, gs_memory_t *mem)
414
{
415
    if (plr->pr != plr->rl)
416
	gs_free_object(mem, plr->pr, "rect_release");
417
}
418
 
419
/* ------ Graphics state ------ */
420
 
421
/* <llx> <lly> <urx> <ury> setbbox - */
422
int
423
zsetbbox(i_ctx_t *i_ctx_p)
424
{
425
    os_ptr op = osp;
426
    double box[4];
427
 
428
    int code = num_params(op, 4, box);
429
 
430
    if (code < 0)
431
	return code;
432
    if ((code = gs_setbbox(igs, box[0], box[1], box[2], box[3])) < 0)
433
	return code;
434
    pop(4);
435
    return 0;
436
}
437
 
438
/* ------ Initialization procedure ------ */
439
 
440
const op_def zdps1_l2_op_defs[] =
441
{
442
    op_def_begin_level2(),
443
		/* Graphics state */
444
    {"0currentstrokeadjust", zcurrentstrokeadjust},
445
    {"1setstrokeadjust", zsetstrokeadjust},
446
		/* Graphics state objects */
447
    {"1copy", z1copy},
448
    {"1currentgstate", zcurrentgstate},
449
    {"0gstate", zgstate},
450
    {"1setgstate", zsetgstate},
451
		/* Rectangles */
452
    {"1.rectappend", zrectappend},
453
    {"1rectclip", zrectclip},
454
    {"1rectfill", zrectfill},
455
    {"1rectstroke", zrectstroke},
456
		/* Graphics state components */
457
    {"4setbbox", zsetbbox},
458
    op_def_end(0)
459
};
460
 
461
/* ------ Internal routines ------ */
462
 
463
/* Ensure that a gstate is not shared with an outer save level. */
464
/* *op is of type t_astruct(igstate_obj). */
465
private int
466
gstate_unshare(i_ctx_t *i_ctx_p)
467
{
468
    os_ptr op = osp;
469
    ref *pgsref = &r_ptr(op, igstate_obj)->gstate;
470
    gs_state *pgs = r_ptr(pgsref, gs_state);
471
    gs_state *pnew;
472
    int_gstate *isp;
473
 
474
    if (!ref_must_save(pgsref))
475
	return 0;
476
    /* Copy the gstate. */
477
    pnew = gs_gstate(pgs);
478
    if (pnew == 0)
479
	return_error(e_VMerror);
480
    isp = gs_int_gstate(pnew);
481
    int_gstate_map_refs(isp, ref_mark_new);
482
    ref_do_save(op, pgsref, "gstate_unshare");
483
    make_istruct_new(pgsref, 0, pnew);
484
    return 0;
485
}