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_tlsv12/sys/src/cmd/gs/src/zdpnext.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) 1997, 1998, 1999 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: zdpnext.c,v 1.8 2005/03/14 18:08:37 dan Exp $ */
18
/* NeXT Display PostScript extensions */
19
#include "math_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gscoord.h"
23
#include "gscspace.h"		/* for iimage.h */
24
#include "gsdpnext.h"
25
#include "gsmatrix.h"
26
#include "gsiparam.h"		/* for iimage.h */
27
#include "gsiparm2.h"
28
#include "gspath2.h"
29
#include "gxcvalue.h"
30
#include "gxdevice.h"
31
#include "gxsample.h"
32
#include "ialloc.h"
33
#include "igstate.h"
34
#include "iimage.h"
35
#include "iimage2.h"
36
#include "store.h"
37
 
38
/* ------ alpha channel ------ */
39
 
40
/* - currentalpha <alpha> */
41
private int
42
zcurrentalpha(i_ctx_t *i_ctx_p)
43
{
44
    os_ptr op = osp;
45
 
46
    push(1);
47
    make_real(op, gs_currentalpha(igs));
48
    return 0;
49
}
50
 
51
/* <alpha> setalpha - */
52
private int
53
zsetalpha(i_ctx_t *i_ctx_p)
54
{
55
    os_ptr op = osp;
56
    double alpha;
57
    int code;
58
 
59
    if (real_param(op, &alpha) < 0)
60
	return_op_typecheck(op);
61
    if ((code = gs_setalpha(igs, alpha)) < 0)
62
	return code;
63
    pop(1);
64
    return 0;
65
}
66
 
67
/* ------ Imaging/compositing ------ */
68
 
69
/*
70
 * Miscellaneous notes:
71
 *
72
 * composite / dissolve respect destination clipping (both clip & viewclip),
73
 *   but ignore source clipping.
74
 * composite / dissolve must handle overlapping source/destination correctly.
75
 * compositing converts the source to the destination's color model
76
 *   (including halftoning if needed).
77
 */
78
 
79
/*
80
 * Define the operand and bookeeping structure for a compositing operation.
81
 */
82
typedef struct alpha_composite_state_s {
83
    /* Compositing parameters */
84
    gs_composite_alpha_params_t params;
85
    /* Temporary structures */
86
    gs_composite_t *pcte;
87
    gx_device *cdev;
88
    gx_device *orig_dev;
89
} alpha_composite_state_t;
90
 
91
/* Forward references */
92
private int begin_composite(i_ctx_t *, alpha_composite_state_t *);
93
private void end_composite(i_ctx_t *, alpha_composite_state_t *);
94
private int xywh_param(os_ptr, double[4]);
95
 
96
/* <dict> .alphaimage - */
97
/* This is the dictionary version of the alphaimage operator, which is */
98
/* now a pseudo-operator (see gs_dpnxt.ps). */
99
private int
100
zalphaimage(i_ctx_t *i_ctx_p)
101
{
102
    return image1_setup(i_ctx_p, true);
103
}
104
 
105
/* <destx> <desty> <width> <height> <op> compositerect - */
106
private int
107
zcompositerect(i_ctx_t *i_ctx_p)
108
{
109
    os_ptr op = osp;
110
    double dest_rect[4];
111
    alpha_composite_state_t cstate;
112
    int code = xywh_param(op - 1, dest_rect);
113
 
114
    if (code < 0)
115
	return code;
116
    check_int_leu(*op, compositerect_last);
117
    cstate.params.op = (gs_composite_op_t) op->value.intval;
118
    code = begin_composite(i_ctx_p, &cstate);
119
    if (code < 0)
120
	return code;
121
    {
122
	gs_rect rect;
123
 
124
	rect.q.x = (rect.p.x = dest_rect[0]) + dest_rect[2];
125
	rect.q.y = (rect.p.y = dest_rect[1]) + dest_rect[3];
126
	code = gs_rectfill(igs, &rect, 1);
127
    }
128
    end_composite(i_ctx_p, &cstate);
129
    if (code >= 0)
130
	pop(5);
131
    return code;
132
}
133
 
134
/* Common code for composite and dissolve. */
135
private int
136
composite_image(i_ctx_t *i_ctx_p, const gs_composite_alpha_params_t * params)
137
{
138
    os_ptr op = osp;
139
    alpha_composite_state_t cstate;
140
    gs_image2_t image;
141
    double src_rect[4];
142
    double dest_pt[2];
143
    gs_matrix save_ctm;
144
    int code = xywh_param(op - 4, src_rect);
145
 
146
    cstate.params = *params;
147
    gs_image2_t_init(&image);
148
    if (code < 0 ||
149
	(code = num_params(op - 1, 2, dest_pt)) < 0
150
	)
151
	return code;
152
    if (r_has_type(op - 3, t_null))
153
	image.DataSource = igs;
154
    else {
155
	check_stype(op[-3], st_igstate_obj);
156
	check_read(op[-3]);
157
	image.DataSource = igstate_ptr(op - 3);
158
    }
159
    image.XOrigin = src_rect[0];
160
    image.YOrigin = src_rect[1];
161
    image.Width = src_rect[2];
162
    image.Height = src_rect[3];
163
    image.PixelCopy = true;
164
    /* Compute appropriate transformations. */
165
    gs_currentmatrix(igs, &save_ctm);
166
    gs_translate(igs, dest_pt[0], dest_pt[1]);
167
    gs_make_identity(&image.ImageMatrix);
168
    if (image.DataSource == igs) {
169
	image.XOrigin -= dest_pt[0];
170
	image.YOrigin -= dest_pt[1];
171
    }
172
    code = begin_composite(i_ctx_p, &cstate);
173
    if (code >= 0) {
174
	code = process_non_source_image(i_ctx_p,
175
					(const gs_image_common_t *)&image,
176
					"composite_image");
177
	end_composite(i_ctx_p, &cstate);
178
	if (code >= 0)
179
	    pop(8);
180
    }
181
    gs_setmatrix(igs, &save_ctm);
182
    return code;
183
}
184
 
185
/* <srcx> <srcy> <width> <height> <srcgstate|null> <destx> <desty> <op> */
186
/*   composite - */
187
private int
188
zcomposite(i_ctx_t *i_ctx_p)
189
{
190
    os_ptr op = osp;
191
    gs_composite_alpha_params_t params;
192
 
193
    check_int_leu(*op, composite_last);
194
    params.op = (gs_composite_op_t) op->value.intval;
195
    return composite_image(i_ctx_p, &params);
196
}
197
 
198
/* <srcx> <srcy> <width> <height> <srcgstate|null> <destx> <desty> <delta> */
199
/*   dissolve - */
200
private int
201
zdissolve(i_ctx_t *i_ctx_p)
202
{
203
    os_ptr op = osp;
204
    gs_composite_alpha_params_t params;
205
    double delta;
206
    int code = real_param(op, &delta);
207
 
208
    if (code < 0)
209
	return code;
210
    if (delta < 0 || delta > 1)
211
	return_error(e_rangecheck);
212
    params.op = composite_Dissolve;
213
    params.delta = delta;
214
    return composite_image(i_ctx_p, &params);
215
}
216
 
217
/* ------ Image reading ------ */
218
 
219
private int device_is_true_color(gx_device * dev);
220
 
221
/* <x> <y> <width> <height> <matrix> .sizeimagebox */
222
/*   <dev_x> <dev_y> <dev_width> <dev_height> <matrix> */
223
private void box_confine(int *pp, int *pq, int wh);
224
private int
225
zsizeimagebox(i_ctx_t *i_ctx_p)
226
{
227
    os_ptr op = osp;
228
    const gx_device *dev = gs_currentdevice(igs);
229
    gs_rect srect, drect;
230
    gs_matrix mat;
231
    gs_int_rect rect;
232
    int w, h;
233
    int code;
234
 
235
    check_type(op[-4], t_integer);
236
    check_type(op[-3], t_integer);
237
    check_type(op[-2], t_integer);
238
    check_type(op[-1], t_integer);
239
    srect.p.x = op[-4].value.intval;
240
    srect.p.y = op[-3].value.intval;
241
    srect.q.x = srect.p.x + op[-2].value.intval;
242
    srect.q.y = srect.p.y + op[-1].value.intval;
243
    gs_currentmatrix(igs, &mat);
244
    gs_bbox_transform(&srect, &mat, &drect);
245
    /*
246
     * We want the dimensions of the image as a source, not a
247
     * destination, so we need to expand it rather than pixround.
248
     */
249
    rect.p.x = (int)floor(drect.p.x);
250
    rect.p.y = (int)floor(drect.p.y);
251
    rect.q.x = (int)ceil(drect.q.x);
252
    rect.q.y = (int)ceil(drect.q.y);
253
    /*
254
     * Clip the rectangle to the device boundaries, since that's what
255
     * the NeXT implementation does.
256
     */
257
    box_confine(&rect.p.x, &rect.q.x, dev->width);
258
    box_confine(&rect.p.y, &rect.q.y, dev->height);
259
    w = rect.q.x - rect.p.x;
260
    h = rect.q.y - rect.p.y;
261
    /*
262
     * The NeXT documentation doesn't specify very clearly what is
263
     * supposed to be in the matrix: the following produces results
264
     * that match testing on an actual NeXT system.
265
     */
266
    mat.tx -= rect.p.x;
267
    mat.ty -= rect.p.y;
268
    code = write_matrix(op, &mat);
269
    if (code < 0)
270
	return code;
271
    make_int(op - 4, rect.p.x);
272
    make_int(op - 3, rect.p.y);
273
    make_int(op - 2, w);
274
    make_int(op - 1, h);
275
    return 0;
276
}
277
private void
278
box_confine(int *pp, int *pq, int wh)
279
{
280
    if ( *pq <= 0 )
281
	*pp = *pq = 0;
282
    else if ( *pp >= wh )
283
	*pp = *pq = wh;
284
    else {
285
	if ( *pp < 0 )
286
	    *pp = 0;
287
	if ( *pq > wh )
288
	    *pq = wh;
289
    }
290
}
291
 
292
/* - .sizeimageparams <bits/sample> <multiproc> <ncolors> */
293
private int
294
zsizeimageparams(i_ctx_t *i_ctx_p)
295
{
296
    os_ptr op = osp;
297
    gx_device *dev = gs_currentdevice(igs);
298
    int ncomp = dev->color_info.num_components;
299
    int bps;
300
 
301
    push(3);
302
    if (device_is_true_color(dev))
303
	bps = dev->color_info.depth / ncomp;
304
    else {
305
	/*
306
	 * Set bps to the smallest allowable number of bits that is
307
	 * sufficient to represent the number of different colors.
308
	 */
309
	gx_color_value max_value =
310
	    (dev->color_info.num_components == 1 ?
311
	     dev->color_info.max_gray :
312
	     max(dev->color_info.max_gray, dev->color_info.max_color));
313
	static const gx_color_value sizes[] = {
314
	    1, 2, 4, 8, 12, sizeof(gx_max_color_value) * 8
315
	};
316
	int i;
317
 
318
	for (i = 0;; ++i)
319
	    if (max_value <= ((ulong) 1 << sizes[i]) - 1)
320
		break;
321
	bps = sizes[i];
322
    }
323
    make_int(op - 2, bps);
324
    make_false(op - 1);
325
    make_int(op, ncomp);
326
    return 0;
327
}
328
 
329
/* ------ Initialization procedure ------ */
330
 
331
const op_def zdpnext_op_defs[] =
332
{
333
    {"0currentalpha", zcurrentalpha},
334
    {"1setalpha", zsetalpha},
335
    {"1.alphaimage", zalphaimage},
336
    {"8composite", zcomposite},
337
    {"5compositerect", zcompositerect},
338
    {"8dissolve", zdissolve},
339
    {"5.sizeimagebox", zsizeimagebox},
340
    {"0.sizeimageparams", zsizeimageparams},
341
    op_def_end(0)
342
};
343
 
344
/* ------ Internal routines ------ */
345
 
346
/* Collect a rect operand. */
347
private int
348
xywh_param(os_ptr op, double rect[4])
349
{
350
    int code = num_params(op, 4, rect);
351
 
352
    if (code < 0)
353
	return code;
354
    if (rect[2] < 0)
355
	rect[0] += rect[2], rect[2] = -rect[2];
356
    if (rect[3] < 0)
357
	rect[1] += rect[3], rect[3] = -rect[3];
358
    return code;
359
}
360
 
361
/* Begin a compositing operation. */
362
private int
363
begin_composite(i_ctx_t *i_ctx_p, alpha_composite_state_t * pcp)
364
{
365
    gx_device *dev = gs_currentdevice(igs);
366
    int code =
367
	gs_create_composite_alpha(&pcp->pcte, &pcp->params, imemory);
368
 
369
    if (code < 0)
370
	return code;
371
    pcp->orig_dev = pcp->cdev = dev;	/* for end_composite */
372
    code = (*dev_proc(dev, create_compositor))
373
	(dev, &pcp->cdev, pcp->pcte, (gs_imager_state *)igs, imemory);
374
    if (code < 0) {
375
	end_composite(i_ctx_p, pcp);
376
	return code;
377
    }
378
    gs_setdevice_no_init(igs, pcp->cdev);
379
    return 0;
380
}
381
 
382
/* End a compositing operation. */
383
private void
384
end_composite(i_ctx_t *i_ctx_p, alpha_composite_state_t * pcp)
385
{
386
    /* Close and free the compositor and the compositing object. */
387
    if (pcp->cdev != pcp->orig_dev) {
388
	gs_closedevice(pcp->cdev);	/* also frees the device */
389
	gs_setdevice_no_init(igs, pcp->orig_dev);
390
    }
391
    ifree_object(pcp->pcte, "end_composite(gs_composite_t)");
392
}
393
 
394
/*
395
 * Determine whether a device has decomposed pixels with the components
396
 * in the standard PostScript order, and a 1-for-1 color map
397
 * (possibly inverted).  Return 0 if not true color, 1 if true color,
398
 * -1 if inverted true color.
399
 */
400
private int
401
device_is_true_color(gx_device * dev)
402
{
403
    int ncomp = dev->color_info.num_components;
404
    int depth = dev->color_info.depth;
405
    int i, max_v;
406
 
407
#define CV(i) (gx_color_value)((ulong)gx_max_color_value * i / max_v)
408
#define CV0 ((gx_color_value)0)
409
 
410
    /****** DOESN'T HANDLE INVERSION YET ******/
411
    switch (ncomp) {
412
	case 1:		/* gray-scale */
413
	    max_v = dev->color_info.max_gray;
414
	    if (max_v != (1 << depth) - 1)
415
		return 0;
416
	    for (i = 0; i <= max_v; ++i) {
417
		gx_color_value v[3];
418
                v[0] = v[1] = v[2] = CV(i);
419
		if ((*dev_proc(dev, map_rgb_color)) (dev, v) != i)
420
		    return 0;
421
	    }
422
	    return true;
423
	case 3:		/* RGB */
424
	    max_v = dev->color_info.max_color;
425
	    if (depth % 3 != 0 || max_v != (1 << (depth / 3)) - 1)
426
		return false;
427
	    {
428
		const int gs = depth / 3, rs = gs * 2;
429
 
430
		for (i = 0; i <= max_v; ++i) {
431
		    gx_color_value red[3];
432
                    gx_color_value green[3];
433
                    gx_color_value blue[3];
434
                    red[0] = CV(i); red[1] = CV0, red[2] = CV0;
435
                    green[0] = CV0; green[1] = CV(i); green[2] = CV0;
436
                    blue[0] = CV0; blue[1] = CV0; blue[2] = CV(i);
437
		    if ((*dev_proc(dev, map_rgb_color)) (dev, red) !=
438
			i << rs ||
439
			(*dev_proc(dev, map_rgb_color)) (dev, green) !=
440
			i << gs ||
441
			(*dev_proc(dev, map_rgb_color)) (dev, blue) !=
442
			i	/*<< bs */
443
			)
444
			return 0;
445
		}
446
	    }
447
	    return true;
448
	case 4:		/* CMYK */
449
	    max_v = dev->color_info.max_color;
450
	    if ((depth & 3) != 0 || max_v != (1 << (depth / 4)) - 1)
451
		return false;
452
	    {
453
		const int ys = depth / 4, ms = ys * 2, cs = ys * 3;
454
 
455
		for (i = 0; i <= max_v; ++i) {
456
 
457
		    gx_color_value cyan[4];
458
                    gx_color_value magenta[4];
459
                    gx_color_value yellow[4];
460
                    gx_color_value black[4];
461
                    cyan[0] = CV(i); cyan[1] = cyan[2] = cyan[3] = CV0;
462
                    magenta[1] = CV(i); magenta[0] = magenta[2] = magenta[3] = CV0;
463
                    yellow[2] = CV(i); yellow[0] = yellow[1] = yellow[3] = CV0;
464
                    black[3] = CV(i); black[0] = black[1] = black[2] = CV0;
465
		    if ((*dev_proc(dev, map_cmyk_color)) (dev, cyan) !=
466
			i << cs ||
467
			(*dev_proc(dev, map_cmyk_color)) (dev, magenta) !=
468
			i << ms ||
469
			(*dev_proc(dev, map_cmyk_color)) (dev, yellow) !=
470
			i << ys ||
471
			(*dev_proc(dev, map_cmyk_color)) (dev, black) !=
472
			i	/*<< ks */
473
			)
474
			return 0;
475
		}
476
	    }
477
	    return 1;
478
	default:
479
	    return 0;		/* DeviceN */
480
    }
481
#undef CV
482
#undef CV0
483
}