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/gsalphac.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: gsalphac.c,v 1.8 2005/03/14 18:08:36 dan Exp $ */
18
/* Alpha-compositing implementation */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsalphac.h"
23
#include "gsiparam.h"		/* for gs_image_alpha_t */
24
#include "gsutil.h"		/* for gs_next_ids */
25
#include "gxalpha.h"
26
#include "gxcomp.h"
27
#include "gxdevice.h"
28
#include "gxgetbit.h"
29
#include "gxlum.h"
30
 
31
/* ---------------- Internal definitions ---------------- */
32
 
33
/* Define the parameters for a compositing operation. */
34
typedef struct gs_composite_params_s {
35
    gs_composite_op_t cop;
36
    float delta;		/* only for dissolve */
37
    uint source_alpha;		/* only if !psource->alpha */
38
    uint source_values[4];	/* only if !psource->data */
39
} gs_composite_params_t;
40
 
41
/* Define the source or destination for a compositing operation. */
42
#define pixel_row_fields(elt_type)\
43
  elt_type *data;\
44
  int bits_per_value;	/* 1, 2, 4, 8, 12, 16 */\
45
  int initial_x;\
46
  gs_image_alpha_t alpha
47
typedef struct pixel_row_s {
48
    pixel_row_fields(byte);
49
} pixel_row_t;
50
typedef struct const_pixel_row_s {
51
    pixel_row_fields(const byte);
52
} const_pixel_row_t;
53
 
54
/*
55
 * Composite two arrays of (premultiplied) pixel values.  Legal values of
56
 * values_per_pixel are 1-4, not including alpha.  Note that if pdest->alpha
57
 * is "none", the alpha value for all destination pixels will be taken as
58
 * unity, and any operation that could generate alpha values other than
59
 * unity will return an error.  "Could generate" means that there are
60
 * possible values of the source and destination alpha values for which the
61
 * result has non-unity alpha: the error check does not scan the actual
62
 * alpha data to test whether there are any actual values that would
63
 * generate a non-unity alpha result.
64
 */
65
int composite_values(const pixel_row_t * pdest,
66
		     const const_pixel_row_t * psource,
67
		     int values_per_pixel, uint num_pixels,
68
		     const gs_composite_params_t * pcp);
69
 
70
/* ---------------- Alpha-compositing objects ---------------- */
71
 
72
/*
73
 * Define which operations can generate non-unity alpha values in 3 of the 4
74
 * cases of source and destination not having unity alphas.  (This is always
75
 * possible in the fourth case, both S & D non-unity, except for CLEAR.)  We
76
 * do this with a bit mask indexed by the operation, counting from the LSB.
77
 * The name indicates whether S and/or D has non-unity alphas.
78
 */
79
#define alpha_out_notS_notD\
80
  (1<<composite_Dissolve)
81
#define _alpha_out_either\
82
  (alpha_out_notS_notD|(1<<composite_Satop)|(1<<composite_Datop)|\
83
    (1<<composite_Xor)|(1<<composite_PlusD)|(1<<composite_PlusL))
84
#define alpha_out_S_notD\
85
  (_alpha_out_either|(1<<composite_Copy)|(1<<composite_Sover)|\
86
    (1<<composite_Din)|(1<<composite_Dout))
87
#define alpha_out_notS_D\
88
  (_alpha_out_either|(1<<composite_Sin)|(1<<composite_Sout)|\
89
    (1<<composite_Dover)|(1<<composite_Highlight))
90
 
91
/* ------ Object definition and creation ------ */
92
 
93
/* Define alpha-compositing objects. */
94
private composite_create_default_compositor_proc(c_alpha_create_default_compositor);
95
private composite_equal_proc(c_alpha_equal);
96
private composite_write_proc(c_alpha_write);
97
private composite_read_proc(c_alpha_read);
98
const gs_composite_type_t gs_composite_alpha_type =
99
{
100
    GX_COMPOSITOR_ALPHA,
101
    {
102
	c_alpha_create_default_compositor,
103
	c_alpha_equal,
104
	c_alpha_write,
105
	c_alpha_read,
106
	gx_default_composite_clist_write_update,
107
	gx_default_composite_clist_read_update
108
    }
109
};
110
typedef struct gs_composite_alpha_s {
111
    gs_composite_common;
112
    gs_composite_alpha_params_t params;
113
} gs_composite_alpha_t;
114
 
115
gs_private_st_simple(st_composite_alpha, gs_composite_alpha_t,
116
		     "gs_composite_alpha_t");
117
 
118
/* Create an alpha-compositing object. */
119
int
120
gs_create_composite_alpha(gs_composite_t ** ppcte,
121
	      const gs_composite_alpha_params_t * params, gs_memory_t * mem)
122
{
123
    gs_composite_alpha_t *pcte;
124
 
125
    rc_alloc_struct_0(pcte, gs_composite_alpha_t, &st_composite_alpha,
126
		      mem, return_error(gs_error_VMerror),
127
		      "gs_create_composite_alpha");
128
    pcte->type = &gs_composite_alpha_type;
129
    pcte->id = gs_next_ids(mem, 1);
130
    pcte->params = *params;
131
    *ppcte = (gs_composite_t *) pcte;
132
    return 0;
133
}
134
 
135
/* ------ Object implementation ------ */
136
 
137
#define pacte ((const gs_composite_alpha_t *)pcte)
138
 
139
private bool
140
c_alpha_equal(const gs_composite_t * pcte, const gs_composite_t * pcte2)
141
{
142
    return (pcte2->type == pcte->type &&
143
#define pacte2 ((const gs_composite_alpha_t *)pcte2)
144
	    pacte2->params.op == pacte->params.op &&
145
	    (pacte->params.op != composite_Dissolve ||
146
	     pacte2->params.delta == pacte->params.delta));
147
#undef pacte2
148
}
149
 
150
private int
151
c_alpha_write(const gs_composite_t * pcte, byte * data, uint * psize)
152
{
153
    uint size = *psize;
154
    uint used;
155
 
156
    if (pacte->params.op == composite_Dissolve) {
157
	used = 1 + sizeof(pacte->params.delta);
158
	if (size < used) {
159
	    *psize = used;
160
	    return_error(gs_error_rangecheck);
161
	}
162
	memcpy(data + 1, &pacte->params.delta, sizeof(pacte->params.delta));
163
    } else {
164
	used = 1;
165
	if (size < used) {
166
	    *psize = used;
167
	    return_error(gs_error_rangecheck);
168
	}
169
    }
170
    *data = (byte) pacte->params.op;
171
    *psize = used;
172
    return 0;
173
}
174
 
175
private int
176
c_alpha_read(gs_composite_t ** ppcte, const byte * data, uint size,
177
	     gs_memory_t * mem)
178
{
179
    gs_composite_alpha_params_t params;
180
    int code, nbytes = 1;
181
 
182
    if (size < 1 || *data > composite_op_last)
183
	return_error(gs_error_rangecheck);
184
    params.op = *data;
185
    if (params.op == composite_Dissolve) {
186
	if (size < 1 + sizeof(params.delta))
187
	    return_error(gs_error_rangecheck);
188
	memcpy(&params.delta, data + 1, sizeof(params.delta));
189
	nbytes += sizeof(params.delta);
190
    }
191
    code = gs_create_composite_alpha(ppcte, &params, mem);
192
    return code < 0 ? code : nbytes;
193
}
194
 
195
/* ---------------- Alpha-compositing device ---------------- */
196
 
197
/* Define the default alpha-compositing device. */
198
typedef struct gx_device_composite_alpha_s {
199
    gx_device_forward_common;
200
    gs_composite_alpha_params_t params;
201
} gx_device_composite_alpha;
202
 
203
gs_private_st_suffix_add0_final(st_device_composite_alpha,
204
		     gx_device_composite_alpha, "gx_device_composite_alpha",
205
    device_c_alpha_enum_ptrs, device_c_alpha_reloc_ptrs, gx_device_finalize,
206
				st_device_forward);
207
/* The device descriptor. */
208
private dev_proc_close_device(dca_close);
209
private dev_proc_fill_rectangle(dca_fill_rectangle);
210
private dev_proc_map_rgb_color(dca_map_rgb_color);
211
private dev_proc_map_color_rgb(dca_map_color_rgb);
212
private dev_proc_copy_mono(dca_copy_mono);
213
private dev_proc_copy_color(dca_copy_color);
214
private dev_proc_map_rgb_alpha_color(dca_map_rgb_alpha_color);
215
private dev_proc_map_color_rgb_alpha(dca_map_color_rgb_alpha);
216
private dev_proc_copy_alpha(dca_copy_alpha);
217
private const gx_device_composite_alpha gs_composite_alpha_device =
218
{std_device_std_body_open(gx_device_composite_alpha, 0,
219
			  "alpha compositor", 0, 0, 1, 1),
220
 {gx_default_open_device,
221
  gx_forward_get_initial_matrix,
222
  gx_default_sync_output,
223
  gx_default_output_page,
224
  dca_close,
225
  dca_map_rgb_color,
226
  dca_map_color_rgb,
227
  dca_fill_rectangle,
228
  gx_default_tile_rectangle,
229
  dca_copy_mono,
230
  dca_copy_color,
231
  gx_default_draw_line,
232
  gx_default_get_bits,
233
  gx_forward_get_params,
234
  gx_forward_put_params,
235
  gx_default_cmyk_map_cmyk_color,	/* only called for CMYK */
236
  gx_forward_get_xfont_procs,
237
  gx_forward_get_xfont_device,
238
  dca_map_rgb_alpha_color,
239
  gx_forward_get_page_device,
240
  gx_forward_get_alpha_bits,
241
  dca_copy_alpha,
242
  gx_forward_get_band,
243
  gx_default_copy_rop,
244
  gx_default_fill_path,
245
  gx_default_stroke_path,
246
  gx_default_fill_mask,
247
  gx_default_fill_trapezoid,
248
  gx_default_fill_parallelogram,
249
  gx_default_fill_triangle,
250
  gx_default_draw_thin_line,
251
  gx_default_begin_image,
252
  gx_default_image_data,
253
  gx_default_end_image,
254
  gx_default_strip_tile_rectangle,
255
  gx_default_strip_copy_rop,
256
  gx_forward_get_clipping_box,
257
  gx_default_begin_typed_image,
258
  gx_forward_get_bits_rectangle,
259
  dca_map_color_rgb_alpha,
260
  gx_no_create_compositor
261
 }
262
};
263
 
264
/* Create an alpha compositor. */
265
private int
266
c_alpha_create_default_compositor(const gs_composite_t * pcte,
267
	   gx_device ** pcdev, gx_device * dev, gs_imager_state * pis,
268
	   gs_memory_t * mem)
269
{
270
    gx_device_composite_alpha *cdev;
271
 
272
    if (pacte->params.op == composite_Copy) {
273
	/* Just use the original device. */
274
	*pcdev = dev;
275
	return 0;
276
    }
277
    cdev =
278
	gs_alloc_struct_immovable(mem, gx_device_composite_alpha,
279
				  &st_device_composite_alpha,
280
				  "create default alpha compositor");
281
    *pcdev = (gx_device *)cdev;
282
    if (cdev == 0)
283
	return_error(gs_error_VMerror);
284
    gx_device_init((gx_device *)cdev,
285
		   (const gx_device *)&gs_composite_alpha_device, mem, true);
286
    gx_device_copy_params((gx_device *)cdev, dev);
287
    /*
288
     * Set the color_info and depth to be compatible with the target,
289
     * but using standard chunky color storage, including alpha.
290
     ****** CURRENTLY ALWAYS USE 8-BIT COLOR ******
291
     */
292
    cdev->color_info.depth =
293
	(dev->color_info.num_components == 4 ? 32 /* CMYK, no alpha */ :
294
	 (dev->color_info.num_components + 1) * 8);
295
    cdev->color_info.max_gray = cdev->color_info.max_color = 255;
296
    /* No halftoning will occur, but we fill these in anyway.... */
297
    cdev->color_info.dither_grays = cdev->color_info.dither_colors = 256;
298
    /*
299
     * We could speed things up a little by tailoring the procedures in
300
     * the device to the specific num_components, but for simplicity,
301
     * we'll defer considering that until there is a demonstrated need.
302
     */
303
    gx_device_set_target((gx_device_forward *)cdev, dev);
304
    cdev->params = pacte->params;
305
    return 0;
306
}
307
 
308
/* Close the device and free its storage. */
309
private int
310
dca_close(gx_device * dev)
311
{				/*
312
				 * Finalization will call close again: avoid a recursion loop.
313
				 */
314
    set_dev_proc(dev, close_device, gx_default_close_device);
315
    gs_free_object(dev->memory, dev, "dca_close");
316
    return 0;
317
}
318
 
319
/* ------ (RGB) color mapping ------ */
320
 
321
private gx_color_index
322
dca_map_rgb_color(gx_device * dev, const gx_color_value cv[])
323
{
324
    return dca_map_rgb_alpha_color(dev, cv[0], cv[1], cv[2], gx_max_color_value);
325
}
326
private gx_color_index
327
dca_map_rgb_alpha_color(gx_device * dev,
328
	      gx_color_value red, gx_color_value green, gx_color_value blue,
329
			gx_color_value alpha)
330
{				/*
331
				 * We work exclusively with premultiplied color values, so we
332
				 * have to premultiply the color components by alpha here.
333
				 */
334
    byte a = gx_color_value_to_byte(alpha);
335
 
336
#define premult_(c)\
337
  (((c) * a + gx_max_color_value / 2) / gx_max_color_value)
338
#ifdef PREMULTIPLY_TOWARDS_WHITE
339
    byte bias = ~a;
340
 
341
#  define premult(c) (premult_(c) + bias)
342
#else
343
#  define premult(c) premult_(c)
344
#endif
345
    gx_color_index color;
346
 
347
    if (dev->color_info.num_components == 1) {
348
	uint lum =
349
	(red * lum_red_weight + green * lum_green_weight +
350
	 blue * lum_blue_weight + lum_all_weights / 2) /
351
	lum_all_weights;
352
 
353
	if (a == 0xff)
354
	    color = gx_color_value_to_byte(lum);
355
	else			/* Premultiplication is necessary. */
356
	    color = premult(lum);
357
    } else {
358
	if (a == 0xff)
359
	    color =
360
		((uint) gx_color_value_to_byte(red) << 16) +
361
		((uint) gx_color_value_to_byte(green) << 8) +
362
		gx_color_value_to_byte(blue);
363
	else			/* Premultiplication is necessary. */
364
	    color =
365
		(premult(red) << 16) + (premult(green) << 8) + premult(blue);
366
    }
367
#undef premult
368
    return (color << 8) + a;
369
}
370
private int
371
dca_map_color_rgb(gx_device * dev, gx_color_index color,
372
		  gx_color_value prgb[3])
373
{
374
    gx_color_value red = gx_color_value_from_byte((byte) (color >> 24));
375
    byte a = (byte) color;
376
 
377
#define postdiv_(c)\
378
  (((c) * 0xff + a / 2) / a)
379
#ifdef PREMULTIPLY_TOWARDS_WHITE
380
    byte bias = ~a;
381
 
382
#  define postdiv(c) postdiv_(c - bias)
383
#else
384
#  define postdiv(c) postdiv_(c)
385
#endif
386
 
387
    if (dev->color_info.num_components == 1) {
388
	if (a != 0xff) {
389
	    /* Undo premultiplication. */
390
	    if (a == 0)
391
		red = 0;
392
	    else
393
		red = postdiv(red);
394
	}
395
	prgb[0] = prgb[1] = prgb[2] = red;
396
    } else {
397
	gx_color_value
398
	    green = gx_color_value_from_byte((byte) (color >> 16)),
399
	    blue = gx_color_value_from_byte((byte) (color >> 8));
400
 
401
	if (a != 0xff) {
402
	    /* Undo premultiplication. */
403
/****** WHAT TO DO ABOUT BIG LOSS OF PRECISION? ******/
404
	    if (a == 0)
405
		red = green = blue = 0;
406
	    else {
407
		red = postdiv(red);
408
		green = postdiv(green);
409
		blue = postdiv(blue);
410
	    }
411
	}
412
	prgb[0] = red, prgb[1] = green, prgb[2] = blue;
413
    }
414
#undef postdiv
415
    return 0;
416
}
417
private int
418
dca_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
419
			gx_color_value prgba[4])
420
{
421
    prgba[3] = gx_color_value_from_byte((byte) color);
422
    return dca_map_color_rgb(dev, color, prgba);
423
}
424
 
425
/* ------ Imaging ------ */
426
 
427
private int
428
dca_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
429
		   gx_color_index color)
430
{				/* This is where all the real work gets done! */
431
    gx_device_composite_alpha *adev = (gx_device_composite_alpha *) dev;
432
    gx_device *target = adev->target;
433
    byte *std_row;
434
    byte *native_row;
435
    gs_int_rect rect;
436
    gs_get_bits_params_t std_params, native_params;
437
    int code = 0;
438
    int yi;
439
    gs_composite_params_t cp;
440
    const_pixel_row_t source;
441
    pixel_row_t dest;
442
 
443
    fit_fill(dev, x, y, w, h);
444
    std_row = gs_alloc_bytes(dev->memory,
445
			     (dev->color_info.depth * w + 7) >> 3,
446
			     "dca_fill_rectangle(std)");
447
    native_row = gs_alloc_bytes(dev->memory,
448
				(target->color_info.depth * w + 7) >> 3,
449
				"dca_fill_rectangle(native)");
450
    if (std_row == 0 || native_row == 0) {
451
	code = gs_note_error(gs_error_VMerror);
452
	goto out;
453
    }
454
    rect.p.x = x, rect.q.x = x + w;
455
    std_params.options =
456
	GB_COLORS_NATIVE |
457
	(GB_ALPHA_LAST | GB_DEPTH_8 | GB_PACKING_CHUNKY |
458
	 GB_RETURN_COPY | GB_RETURN_POINTER | GB_ALIGN_ANY |
459
	 GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD |
460
	 GB_RASTER_ANY);
461
    cp.cop = adev->params.op;
462
    if (cp.cop == composite_Dissolve)
463
	cp.delta = adev->params.delta;
464
    {
465
	gx_color_value rgba[4];
466
 
467
/****** DOESN'T HANDLE CMYK ******/
468
	(*dev_proc(dev, map_color_rgb_alpha)) (dev, color, rgba);
469
	cp.source_values[0] = gx_color_value_to_byte(rgba[0]);
470
	cp.source_values[1] = gx_color_value_to_byte(rgba[1]);
471
	cp.source_values[2] = gx_color_value_to_byte(rgba[2]);
472
	cp.source_alpha = gx_color_value_to_byte(rgba[3]);
473
    }
474
    source.data = 0;
475
    source.bits_per_value = 8;
476
    source.alpha = gs_image_alpha_none;
477
    for (yi = y; yi < y + h; ++yi) {
478
	/* Read a row in standard representation. */
479
	rect.p.y = yi, rect.q.y = yi + 1;
480
	std_params.data[0] = std_row;
481
	code = (*dev_proc(target, get_bits_rectangle))
482
	    (target, &rect, &std_params, NULL);
483
	if (code < 0)
484
	    break;
485
	/* Do the work. */
486
	dest.data = std_params.data[0];
487
	dest.bits_per_value = 8;
488
	dest.initial_x =
489
	    (std_params.options & GB_OFFSET_ANY ? std_params.x_offset : 0);
490
	dest.alpha =
491
	    (std_params.options & GB_ALPHA_FIRST ? gs_image_alpha_first :
492
	     std_params.options & GB_ALPHA_LAST ? gs_image_alpha_last :
493
	     gs_image_alpha_none);
494
	code = composite_values(&dest, &source,
495
				dev->color_info.num_components, w, &cp);
496
	if (code < 0)
497
	    break;
498
	if (std_params.data[0] == std_row) {
499
	    /* Convert the row back to native representation. */
500
	    /* (Otherwise, we had a direct pointer to device data.) */
501
	    native_params.options =
502
		(GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_RETURN_COPY |
503
		 GB_OFFSET_0 | GB_RASTER_ALL | GB_ALIGN_STANDARD);
504
	    native_params.data[0] = native_row;
505
	    code = gx_get_bits_copy(target, 0, w, 1, &native_params,
506
				    &std_params, std_row,
507
 
508
	    if (code < 0)
509
		break;
510
	    code = (*dev_proc(target, copy_color))
511
		(target, native_row, 0, 0 /* raster is irrelevant */ ,
512
		 gx_no_bitmap_id, x, yi, w, 1);
513
	    if (code < 0)
514
		break;
515
	}
516
    }
517
  out:gs_free_object(dev->memory, native_row, "dca_fill_rectangle(native)");
518
    gs_free_object(dev->memory, std_row, "dca_fill_rectangle(std)");
519
    return code;
520
}
521
 
522
private int
523
dca_copy_mono(gx_device * dev, const byte * data,
524
	    int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
525
	      gx_color_index zero, gx_color_index one)
526
{
527
/****** TEMPORARY ******/
528
    return gx_default_copy_mono(dev, data, dx, raster, id, x, y, w, h,
529
				zero, one);
530
}
531
 
532
private int
533
dca_copy_color(gx_device * dev, const byte * data,
534
	       int dx, int raster, gx_bitmap_id id,
535
	       int x, int y, int w, int h)
536
{
537
/****** TEMPORARY ******/
538
    return gx_default_copy_color(dev, data, dx, raster, id, x, y, w, h);
539
}
540
 
541
private int
542
dca_copy_alpha(gx_device * dev, const byte * data, int data_x,
543
	   int raster, gx_bitmap_id id, int x, int y, int width, int height,
544
	       gx_color_index color, int depth)
545
{
546
/****** TEMPORARY ******/
547
    return gx_default_copy_alpha(dev, data, data_x, raster, id, x, y,
548
				 width, height, color, depth);
549
}
550
 
551
/*
552
 * Composite two arrays of (premultiplied) pixel values.
553
 * See gsdpnext.h for the specification.
554
 *
555
 * The current implementation is simple but inefficient.  We'll speed it up
556
 * later if necessary.
557
 */
558
int
559
composite_values(const pixel_row_t * pdest, const const_pixel_row_t * psource,
560
   int values_per_pixel, uint num_pixels, const gs_composite_params_t * pcp)
561
{
562
    int dest_bpv = pdest->bits_per_value;
563
    int source_bpv = psource->bits_per_value;
564
 
565
    /*
566
     * source_alpha_j gives the source component index for the alpha value,
567
     * if the source has alpha.
568
     */
569
    int source_alpha_j =
570
    (psource->alpha == gs_image_alpha_last ? values_per_pixel :
571
     psource->alpha == gs_image_alpha_first ? 0 : -1);
572
 
573
    /* dest_alpha_j does the same for the destination. */
574
    int dest_alpha_j =
575
    (pdest->alpha == gs_image_alpha_last ? values_per_pixel :
576
     pdest->alpha == gs_image_alpha_first ? 0 : -1);
577
 
578
    /* dest_vpp is the number of stored destination values. */
579
    int dest_vpp = values_per_pixel + (dest_alpha_j >= 0);
580
 
581
    /* source_vpp is the number of stored source values. */
582
    int source_vpp = values_per_pixel + (source_alpha_j >= 0);
583
 
584
    bool constant_colors = psource->data == 0;
585
    uint highlight_value = (1 << dest_bpv) - 1;
586
 
587
    sample_load_declare(sptr, sbit);
588
    sample_store_declare(dptr, dbit, dbyte);
589
 
590
    {
591
	uint xbit = pdest->initial_x * dest_bpv * dest_vpp;
592
 
593
	sample_store_setup(dbit, xbit & 7, dest_bpv);
594
	dptr = pdest->data + (xbit >> 3);
595
    }
596
    {
597
	uint xbit = psource->initial_x * source_bpv * source_vpp;
598
 
599
	sbit = xbit & 7;
600
	sptr = psource->data + (xbit >> 3);
601
    }
602
    {
603
	uint source_max = (1 << source_bpv) - 1;
604
	uint dest_max = (1 << dest_bpv) - 1;
605
 
606
	/*
607
	 * We could save a little work by only setting up source_delta
608
	 * and dest_delta if the operation is Dissolve.
609
	 */
610
	float source_delta = pcp->delta * dest_max / source_max;
611
	float dest_delta = 1.0 - pcp->delta;
612
	uint source_alpha = pcp->source_alpha;
613
	uint dest_alpha = dest_max;
614
 
615
#ifdef PREMULTIPLY_TOWARDS_WHITE
616
	uint source_bias = source_max - source_alpha;
617
	uint dest_bias = 0;
618
	uint result_bias = 0;
619
 
620
#endif
621
	uint x;
622
 
623
	if (!pdest->alpha) {
624
	    uint mask =
625
	    (psource->alpha || source_alpha != source_max ?
626
	     alpha_out_S_notD : alpha_out_notS_notD);
627
 
628
	    if ((mask >> pcp->cop) & 1) {
629
		/*
630
		 * The operation could produce non-unity alpha values, but
631
		 * the destination can't store them.  Return an error.
632
		 */
633
		return_error(gs_error_rangecheck);
634
	    }
635
	}
636
	/* Preload the output byte buffer if necessary. */
637
	sample_store_preload(dbyte, dptr, dbit, dest_bpv);
638
 
639
	for (x = 0; x < num_pixels; ++x) {
640
	    int j;
641
	    uint result_alpha = dest_alpha;
642
 
643
/* get_value does not increment the source pointer. */
644
#define get_value(v, ptr, bit, bpv, vmax)\
645
  sample_load16(v, ptr, bit, bpv)
646
 
647
/* put_value increments the destination pointer. */
648
#define put_value(v, ptr, bit, bpv, bbyte)\
649
  sample_store_next16(v, ptr, bit, bpv, bbyte)
650
 
651
#define advance(ptr, bit, bpv)\
652
  sample_next(ptr, bit, bpv)
653
 
654
	    /* Get destination alpha value. */
655
	    if (dest_alpha_j >= 0) {
656
		int dabit = dbit + dest_bpv * dest_alpha_j;
657
		const byte *daptr = dptr + (dabit >> 3);
658
 
659
		get_value(dest_alpha, daptr, dabit & 7, dest_bpv, dest_max);
660
#ifdef PREMULTIPLY_TOWARDS_WHITE
661
		dest_bias = dest_max - dest_alpha;
662
#endif
663
	    }
664
	    /* Get source alpha value. */
665
	    if (source_alpha_j >= 0) {
666
		int sabit = sbit;
667
		const byte *saptr = sptr;
668
 
669
		if (source_alpha_j == 0)
670
		    advance(sptr, sbit, source_bpv);
671
		else
672
		    advance(saptr, sabit, source_bpv * source_alpha_j);
673
		get_value(source_alpha, saptr, sabit, source_bpv, source_max);
674
#ifdef PREMULTIPLY_TOWARDS_WHITE
675
		source_bias = source_max - source_alpha;
676
#endif
677
	    }
678
/*
679
 * We are always multiplying a dest value by a source value to compute a
680
 * dest value, so the denominator is always source_max.  (Dissolve is the
681
 * one exception.)
682
 */
683
#define fr(v, a) ((v) * (a) / source_max)
684
#define nfr(v, a, maxv) ((v) * (maxv - (a)) / source_max)
685
 
686
	    /*
687
	     * Iterate over the components of a single pixel.
688
	     * j = 0 for alpha, 1 .. values_per_pixel for color
689
	     * components, regardless of the actual storage order;
690
	     * we arrange things so that sptr/sbit and dptr/dbit
691
	     * always point to the right place.
692
	     */
693
	    for (j = 0; j <= values_per_pixel; ++j) {
694
		uint dest_v, source_v, result;
695
 
696
#define set_clamped(r, v)\
697
  BEGIN if ( (r = (v)) > dest_max ) r = dest_max; END
698
 
699
		if (j == 0) {
700
		    source_v = source_alpha;
701
		    dest_v = dest_alpha;
702
		} else {
703
		    if (constant_colors)
704
			source_v = pcp->source_values[j - 1];
705
		    else {
706
			get_value(source_v, sptr, sbit, source_bpv, source_max);
707
			advance(sptr, sbit, source_bpv);
708
		    }
709
		    get_value(dest_v, dptr, dbit, dest_bpv, dest_max);
710
#ifdef PREMULTIPLY_TOWARDS_WHITE
711
		    source_v -= source_bias;
712
		    dest_v -= dest_bias;
713
#endif
714
		}
715
 
716
		switch (pcp->cop) {
717
		    case composite_Clear:
718
			/*
719
			 * The NeXT documentation doesn't say this, but the CLEAR
720
			 * operation sets not only alpha but also all the color
721
			 * values to 0.
722
			 */
723
			result = 0;
724
			break;
725
		    case composite_Copy:
726
			result = source_v;
727
			break;
728
		    case composite_PlusD:
729
			/*
730
			 * This is the only case where we have to worry about
731
			 * clamping a possibly negative result.
732
			 */
733
			result = source_v + dest_v;
734
			result = (result < dest_max ? 0 : result - dest_max);
735
			break;
736
		    case composite_PlusL:
737
			set_clamped(result, source_v + dest_v);
738
			break;
739
		    case composite_Sover:
740
			set_clamped(result, source_v + nfr(dest_v, source_alpha, source_max));
741
			break;
742
		    case composite_Dover:
743
			set_clamped(result, nfr(source_v, dest_alpha, dest_max) + dest_v);
744
			break;
745
		    case composite_Sin:
746
			result = fr(source_v, dest_alpha);
747
			break;
748
		    case composite_Din:
749
			result = fr(dest_v, source_alpha);
750
			break;
751
		    case composite_Sout:
752
			result = nfr(source_v, dest_alpha, dest_max);
753
			break;
754
		    case composite_Dout:
755
			result = nfr(dest_v, source_alpha, source_max);
756
			break;
757
		    case composite_Satop:
758
			set_clamped(result, fr(source_v, dest_alpha) +
759
				    nfr(dest_v, source_alpha, source_max));
760
			break;
761
		    case composite_Datop:
762
			set_clamped(result, nfr(source_v, dest_alpha, dest_max) +
763
				    fr(dest_v, source_alpha));
764
			break;
765
		    case composite_Xor:
766
			set_clamped(result, nfr(source_v, dest_alpha, dest_max) +
767
				    nfr(dest_v, source_alpha, source_max));
768
			break;
769
		    case composite_Highlight:
770
			/*
771
			 * Bizarre but true: this operation converts white and
772
			 * light gray into each other, and leaves all other values
773
			 * unchanged.  We only implement it properly for gray-scale
774
			 * devices.
775
			 */
776
			if (j != 0 && !((source_v ^ highlight_value) & ~1))
777
			    result = source_v ^ 1;
778
			else
779
			    result = source_v;
780
			break;
781
		    case composite_Dissolve:
782
			/*
783
			 * In this case, and only this case, we need to worry about
784
			 * source and dest having different bpv values.  For the
785
			 * moment, we wimp out and do everything in floating point.
786
			 */
787
			result = (uint) (source_v * source_delta + dest_v * dest_delta);
788
			break;
789
		    default:
790
			return_error(gs_error_rangecheck);
791
		}
792
		/*
793
		 * Store the result.  We don't have to worry about
794
		 * destinations that don't store alpha, because we don't
795
		 * even compute an alpha value in that case.
796
		 */
797
#ifdef PREMULTIPLY_TOWARDS_WHITE
798
		if (j == 0) {
799
		    result_alpha = result;
800
		    result_bias = dest_max - result_alpha;
801
		    if (dest_alpha_j != 0)
802
			continue;
803
		} else {
804
		    result += result_bias;
805
		}
806
#else
807
		if (j == 0 && dest_alpha_j != 0) {
808
		    result_alpha = result;
809
		    continue;
810
		}
811
#endif
812
		put_value(result, dptr, dbit, dest_bpv, dbyte);
813
	    }
814
	    /* Skip a trailing source alpha value. */
815
	    if (source_alpha_j > 0)
816
		advance(sptr, sbit, source_bpv);
817
	    /* Store a trailing destination alpha value. */
818
	    if (dest_alpha_j > 0)
819
		put_value(result_alpha, dptr, dbit, dest_bpv, dbyte);
820
#undef get_value
821
#undef put_value
822
#undef advance
823
	}
824
	/* Store any partial output byte. */
825
	sample_store_flush(dptr, dbit, dest_bpv, dbyte);
826
    }
827
    return 0;
828
}