Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 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: zdevice.c,v 1.10 2004/09/15 19:41:01 ray Exp $ */
18
/* Device-related operators */
19
#include "string_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "ialloc.h"
23
#include "idict.h"
24
#include "igstate.h"
25
#include "iname.h"
26
#include "interp.h"
27
#include "iparam.h"
28
#include "ivmspace.h"
29
#include "gsmatrix.h"
30
#include "gsstate.h"
31
#include "gxdevice.h"
32
#include "gxgetbit.h"
33
#include "store.h"
34
 
35
/* <device> <keep_open> .copydevice2 <newdevice> */
36
private int
37
zcopydevice2(i_ctx_t *i_ctx_p)
38
{
39
    os_ptr op = osp;
40
    gx_device *new_dev;
41
    int code;
42
 
43
    check_read_type(op[-1], t_device);
44
    check_type(*op, t_boolean);
45
    code = gs_copydevice2(&new_dev, op[-1].value.pdevice, op->value.boolval,
46
			  imemory);
47
    if (code < 0)
48
	return code;
49
    new_dev->memory = imemory;
50
    make_tav(op - 1, t_device, icurrent_space | a_all, pdevice, new_dev);
51
    pop(1);
52
    return 0;
53
}
54
 
55
/* - currentdevice <device> */
56
int
57
zcurrentdevice(i_ctx_t *i_ctx_p)
58
{
59
    os_ptr op = osp;
60
    gx_device *dev = gs_currentdevice(igs);
61
    gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
62
 
63
    push(1);
64
    make_tav(op, t_device,
65
	     (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
66
	     pdevice, dev);
67
    return 0;
68
}
69
 
70
/* <device> .devicename <string> */
71
private int
72
zdevicename(i_ctx_t *i_ctx_p)
73
{
74
    os_ptr op = osp;
75
    const char *dname;
76
 
77
    check_read_type(*op, t_device);
78
    dname = op->value.pdevice->dname;
79
    make_const_string(op, avm_foreign | a_readonly, strlen(dname),
80
		      (const byte *)dname);
81
    return 0;
82
}
83
 
84
/* - .doneshowpage - */
85
private int
86
zdoneshowpage(i_ctx_t *i_ctx_p)
87
{
88
    gx_device *dev = gs_currentdevice(igs);
89
    gx_device *tdev = (*dev_proc(dev, get_page_device)) (dev);
90
 
91
    if (tdev != 0)
92
	tdev->ShowpageCount++;
93
    return 0;
94
}
95
 
96
/* - flushpage - */
97
int
98
zflushpage(i_ctx_t *i_ctx_p)
99
{
100
    return gs_flushpage(igs);
101
}
102
 
103
/* <device> <x> <y> <width> <max_height> <alpha?> <std_depth|null> <string> */
104
/*   .getbitsrect <height> <substring> */
105
private int
106
zgetbitsrect(i_ctx_t *i_ctx_p)
107
{	/*
108
	 * alpha? is 0 for no alpha, -1 for alpha first, 1 for alpha last.
109
	 * std_depth is null for native pixels, depth/component for
110
	 * standard color space.
111
	 */
112
    os_ptr op = osp;
113
    gx_device *dev;
114
    gs_int_rect rect;
115
    gs_get_bits_params_t params;
116
    int w, h;
117
    gs_get_bits_options_t options =
118
	GB_ALIGN_ANY | GB_RETURN_COPY | GB_OFFSET_0 | GB_RASTER_STANDARD |
119
	GB_PACKING_CHUNKY;
120
    int depth;
121
    uint raster;
122
    int num_rows;
123
    int code;
124
 
125
    check_read_type(op[-7], t_device);
126
    dev = op[-7].value.pdevice;
127
    check_int_leu(op[-6], dev->width);
128
    rect.p.x = op[-6].value.intval;
129
    check_int_leu(op[-5], dev->height);
130
    rect.p.y = op[-5].value.intval;
131
    check_int_leu(op[-4], dev->width);
132
    w = op[-4].value.intval;
133
    check_int_leu(op[-3], dev->height);
134
    h = op[-3].value.intval;
135
    check_type(op[-2], t_integer);
136
    /*
137
     * We use if/else rather than switch because the value is long,
138
     * which is not supported as a switch value in pre-ANSI C.
139
     */
140
    if (op[-2].value.intval == -1)
141
	options |= GB_ALPHA_FIRST;
142
    else if (op[-2].value.intval == 0)
143
	options |= GB_ALPHA_NONE;
144
    else if (op[-2].value.intval == 1)
145
	options |= GB_ALPHA_LAST;
146
    else
147
	return_error(e_rangecheck);
148
    if (r_has_type(op - 1, t_null)) {
149
	options |= GB_COLORS_NATIVE;
150
	depth = dev->color_info.depth;
151
    } else {
152
	static const gs_get_bits_options_t depths[17] = {
153
	    0, GB_DEPTH_1, GB_DEPTH_2, 0, GB_DEPTH_4, 0, 0, 0, GB_DEPTH_8,
154
	    0, 0, 0, GB_DEPTH_12, 0, 0, 0, GB_DEPTH_16
155
	};
156
	gs_get_bits_options_t depth_option;
157
	int std_depth;
158
 
159
	check_int_leu(op[-1], 16);
160
	std_depth = (int)op[-1].value.intval;
161
	depth_option = depths[std_depth];
162
	if (depth_option == 0)
163
	    return_error(e_rangecheck);
164
	options |= depth_option | GB_COLORS_NATIVE;
165
	depth = (dev->color_info.num_components +
166
		 (options & GB_ALPHA_NONE ? 0 : 1)) * std_depth;
167
    }
168
    if (w == 0)
169
	return_error(e_rangecheck);
170
    raster = (w * depth + 7) >> 3;
171
    check_write_type(*op, t_string);
172
    num_rows = r_size(op) / raster;
173
    h = min(h, num_rows);
174
    if (h == 0)
175
	return_error(e_rangecheck);
176
    rect.q.x = rect.p.x + w;
177
    rect.q.y = rect.p.y + h;
178
    params.options = options;
179
    params.data[0] = op->value.bytes;
180
    code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect, &params, NULL);
181
    if (code < 0)
182
	return code;
183
    make_int(op - 7, h);
184
    op[-6] = *op;
185
    r_set_size(op - 6, h * raster);
186
    pop(6);
187
    return 0;
188
}
189
 
190
/* <int> .getdevice <device> */
191
private int
192
zgetdevice(i_ctx_t *i_ctx_p)
193
{
194
    os_ptr op = osp;
195
    const gx_device *dev;
196
 
197
    check_type(*op, t_integer);
198
    if (op->value.intval != (int)(op->value.intval))
199
	return_error(e_rangecheck);	/* won't fit in an int */
200
    dev = gs_getdevice((int)(op->value.intval));
201
    if (dev == 0)		/* index out of range */
202
	return_error(e_rangecheck);
203
    /* Device prototypes are read-only; */
204
    /* the cast is logically unnecessary. */
205
    make_tav(op, t_device, avm_foreign | a_readonly, pdevice,
206
	     (gx_device *) dev);
207
    return 0;
208
}
209
 
210
/* Common functionality of zgethardwareparms & zgetdeviceparams */
211
private int
212
zget_device_params(i_ctx_t *i_ctx_p, bool is_hardware)
213
{
214
    os_ptr op = osp;
215
    ref rkeys;
216
    gx_device *dev;
217
    stack_param_list list;
218
    int code;
219
    ref *pmark;
220
 
221
    check_read_type(op[-1], t_device);
222
    rkeys = *op;
223
    dev = op[-1].value.pdevice;
224
    pop(1);
225
    stack_param_list_write(&list, &o_stack, &rkeys, iimemory);
226
    code = gs_get_device_or_hardware_params(dev, (gs_param_list *) & list,
227
					    is_hardware);
228
    if (code < 0) {
229
	/* We have to put back the top argument. */
230
	if (list.count > 0)
231
	    ref_stack_pop(&o_stack, list.count * 2 - 1);
232
	else
233
	    ref_stack_push(&o_stack, 1);
234
	*osp = rkeys;
235
	return code;
236
    }
237
    pmark = ref_stack_index(&o_stack, list.count * 2);
238
    make_mark(pmark);
239
    return 0;
240
}
241
/* <device> <key_dict|null> .getdeviceparams <mark> <name> <value> ... */
242
private int
243
zgetdeviceparams(i_ctx_t *i_ctx_p)
244
{
245
    return zget_device_params(i_ctx_p, false);
246
}
247
/* <device> <key_dict|null> .gethardwareparams <mark> <name> <value> ... */
248
private int
249
zgethardwareparams(i_ctx_t *i_ctx_p)
250
{
251
    return zget_device_params(i_ctx_p, true);
252
}
253
 
254
/* <matrix> <width> <height> <palette> <word?> makewordimagedevice <device> */
255
private int
256
zmakewordimagedevice(i_ctx_t *i_ctx_p)
257
{
258
    os_ptr op = osp;
259
    os_ptr op1 = op - 1;
260
    gs_matrix imat;
261
    gx_device *new_dev;
262
    const byte *colors;
263
    int colors_size;
264
    int code;
265
 
266
    check_int_leu(op[-3], max_uint >> 1);	/* width */
267
    check_int_leu(op[-2], max_uint >> 1);	/* height */
268
    check_type(*op, t_boolean);
269
    if (r_has_type(op1, t_null)) {	/* true color */
270
	colors = 0;
271
	colors_size = -24;	/* 24-bit true color */
272
    } else if (r_has_type(op1, t_integer)) {
273
	/*
274
	 * We use if/else rather than switch because the value is long,
275
	 * which is not supported as a switch value in pre-ANSI C.
276
	 */
277
	if (op1->value.intval != 16 && op1->value.intval != 24 &&
278
	    op1->value.intval != 32
279
	    )
280
	    return_error(e_rangecheck);
281
	colors = 0;
282
	colors_size = -op1->value.intval;
283
    } else {
284
	check_type(*op1, t_string);	/* palette */
285
	if (r_size(op1) > 3 * 256)
286
	    return_error(e_rangecheck);
287
	colors = op1->value.bytes;
288
	colors_size = r_size(op1);
289
    }
290
    if ((code = read_matrix(imemory, op - 4, &imat)) < 0)
291
	return code;
292
    /* Everything OK, create device */
293
    code = gs_makewordimagedevice(&new_dev, &imat,
294
				  (int)op[-3].value.intval,
295
				  (int)op[-2].value.intval,
296
				  colors, colors_size,
297
				  op->value.boolval, true, imemory);
298
    if (code == 0) {
299
	new_dev->memory = imemory;
300
	make_tav(op - 4, t_device, imemory_space(iimemory) | a_all,
301
		 pdevice, new_dev);
302
	pop(4);
303
    }
304
    return code;
305
}
306
 
307
/* - nulldevice - */
308
/* Note that nulldevice clears the current pagedevice. */
309
private int
310
znulldevice(i_ctx_t *i_ctx_p)
311
{
312
    gs_nulldevice(igs);
313
    clear_pagedevice(istate);
314
    return 0;
315
}
316
 
317
/* <num_copies> <flush_bool> .outputpage - */
318
private int
319
zoutputpage(i_ctx_t *i_ctx_p)
320
{
321
    os_ptr op = osp;
322
    int code;
323
 
324
    check_type(op[-1], t_integer);
325
    check_type(*op, t_boolean);
326
    code = gs_output_page(igs, (int)op[-1].value.intval,
327
			  op->value.boolval);
328
    if (code < 0)
329
	return code;
330
    pop(2);
331
    return 0;
332
}
333
 
334
/* <device> <policy_dict|null> <require_all> <mark> <name> <value> ... */
335
/*      .putdeviceparams */
336
/*   (on success) <device> <eraseflag> */
337
/*   (on failure) <device> <policy_dict|null> <require_all> <mark> */
338
/*       <name1> <error1> ... */
339
/* For a key that simply was not recognized, if require_all is true, */
340
/* the result will be an /undefined error; if require_all is false, */
341
/* the key will be ignored. */
342
/* Note that .putdeviceparams clears the current pagedevice. */
343
private int
344
zputdeviceparams(i_ctx_t *i_ctx_p)
345
{
346
    uint count = ref_stack_counttomark(&o_stack);
347
    ref *prequire_all;
348
    ref *ppolicy;
349
    ref *pdev;
350
    gx_device *dev;
351
    stack_param_list list;
352
    int code;
353
    int old_width, old_height;
354
    int i, dest;
355
 
356
    if (count == 0)
357
	return_error(e_unmatchedmark);
358
    prequire_all = ref_stack_index(&o_stack, count);
359
    ppolicy = ref_stack_index(&o_stack, count + 1);
360
    pdev = ref_stack_index(&o_stack, count + 2);
361
    if (pdev == 0)
362
	return_error(e_stackunderflow);
363
    check_type_only(*prequire_all, t_boolean);
364
    check_write_type_only(*pdev, t_device);
365
    dev = pdev->value.pdevice;
366
    code = stack_param_list_read(&list, &o_stack, 0, ppolicy,
367
				 prequire_all->value.boolval, iimemory);
368
    if (code < 0)
369
	return code;
370
    old_width = dev->width;
371
    old_height = dev->height;
372
    code = gs_putdeviceparams(dev, (gs_param_list *) & list);
373
    /* Check for names that were undefined or caused errors. */
374
    for (dest = count - 2, i = 0; i < count >> 1; i++)
375
	if (list.results[i] < 0) {
376
	    *ref_stack_index(&o_stack, dest) =
377
		*ref_stack_index(&o_stack, count - (i << 1) - 2);
378
	    gs_errorname(i_ctx_p, list.results[i],
379
			 ref_stack_index(&o_stack, dest - 1));
380
	    dest -= 2;
381
	}
382
    iparam_list_release(&list);
383
    if (code < 0) {		/* There were errors reported. */
384
	ref_stack_pop(&o_stack, dest + 1);
385
	return 0;
386
    }
387
    if (code > 0 || (code == 0 && (dev->width != old_width || dev->height != old_height))) {
388
	/*
389
	 * The device was open and is now closed, or its dimensions have
390
	 * changed.  If it was the current device, call setdevice to
391
	 * reinstall it and erase the page.
392
	 */
393
	/****** DOESN'T FIND ALL THE GSTATES THAT REFERENCE THE DEVICE. ******/
394
	if (gs_currentdevice(igs) == dev) {
395
	    bool was_open = dev->is_open;
396
 
397
	    code = gs_setdevice_no_erase(igs, dev);
398
	    /* If the device wasn't closed, setdevice won't erase the page. */
399
	    if (was_open && code >= 0)
400
		code = 1;
401
	}
402
    }
403
    if (code < 0)
404
	return code;
405
    ref_stack_pop(&o_stack, count + 1);
406
    make_bool(osp, code);
407
    clear_pagedevice(istate);
408
    return 0;
409
}
410
 
411
/* <device> .setdevice <eraseflag> */
412
/* Note that .setdevice clears the current pagedevice. */
413
int
414
zsetdevice(i_ctx_t *i_ctx_p)
415
{
416
    gx_device *dev = gs_currentdevice(igs);
417
    os_ptr op = osp;
418
    int code;
419
 
420
    check_write_type(*op, t_device);
421
    if (dev->LockSafetyParams) {	  /* do additional checking if locked  */
422
        if(op->value.pdevice != dev) 	  /* don't allow a different device    */
423
	    return_error(e_invalidaccess);
424
    }
425
    code = gs_setdevice_no_erase(igs, op->value.pdevice);
426
    if (code < 0)
427
	return code;
428
    make_bool(op, code != 0);	/* erase page if 1 */
429
    clear_pagedevice(istate);
430
    return code;
431
}
432
 
433
/* ------ Initialization procedure ------ */
434
 
435
const op_def zdevice_op_defs[] =
436
{
437
    {"1.copydevice2", zcopydevice2},
438
    {"0currentdevice", zcurrentdevice},
439
    {"1.devicename", zdevicename},
440
    {"0.doneshowpage", zdoneshowpage},
441
    {"0flushpage", zflushpage},
442
    {"7.getbitsrect", zgetbitsrect},
443
    {"1.getdevice", zgetdevice},
444
    {"2.getdeviceparams", zgetdeviceparams},
445
    {"2.gethardwareparams", zgethardwareparams},
446
    {"5makewordimagedevice", zmakewordimagedevice},
447
    {"0nulldevice", znulldevice},
448
    {"2.outputpage", zoutputpage},
449
    {"3.putdeviceparams", zputdeviceparams},
450
    {"1.setdevice", zsetdevice},
451
    op_def_end(0)
452
};