1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gsalphac.c 8585 2008-03-03 16:01:12Z leonardo $ */
15
/* Alpha-compositing implementation */
20
#include "gsiparam.h" /* for gs_image_alpha_t */
21
#include "gsutil.h" /* for gs_next_ids */
28
/* ---------------- Internal definitions ---------------- */
30
/* Define the parameters for a compositing operation. */
31
typedef struct gs_composite_params_s {
32
gs_composite_op_t cop;
33
float delta; /* only for dissolve */
34
uint source_alpha; /* only if !psource->alpha */
35
uint source_values[4]; /* only if !psource->data */
36
} gs_composite_params_t;
38
/* Define the source or destination for a compositing operation. */
39
#define pixel_row_fields(elt_type)\
41
int bits_per_value; /* 1, 2, 4, 8, 12, 16 */\
43
gs_image_alpha_t alpha
44
typedef struct pixel_row_s {
45
pixel_row_fields(byte);
47
typedef struct const_pixel_row_s {
48
pixel_row_fields(const byte);
52
* Composite two arrays of (premultiplied) pixel values. Legal values of
53
* values_per_pixel are 1-4, not including alpha. Note that if pdest->alpha
54
* is "none", the alpha value for all destination pixels will be taken as
55
* unity, and any operation that could generate alpha values other than
56
* unity will return an error. "Could generate" means that there are
57
* possible values of the source and destination alpha values for which the
58
* result has non-unity alpha: the error check does not scan the actual
59
* alpha data to test whether there are any actual values that would
60
* generate a non-unity alpha result.
62
int composite_values(const pixel_row_t * pdest,
63
const const_pixel_row_t * psource,
64
int values_per_pixel, uint num_pixels,
65
const gs_composite_params_t * pcp);
67
/* ---------------- Alpha-compositing objects ---------------- */
70
* Define which operations can generate non-unity alpha values in 3 of the 4
71
* cases of source and destination not having unity alphas. (This is always
72
* possible in the fourth case, both S & D non-unity, except for CLEAR.) We
73
* do this with a bit mask indexed by the operation, counting from the LSB.
74
* The name indicates whether S and/or D has non-unity alphas.
76
#define alpha_out_notS_notD\
77
(1<<composite_Dissolve)
78
#define _alpha_out_either\
79
(alpha_out_notS_notD|(1<<composite_Satop)|(1<<composite_Datop)|\
80
(1<<composite_Xor)|(1<<composite_PlusD)|(1<<composite_PlusL))
81
#define alpha_out_S_notD\
82
(_alpha_out_either|(1<<composite_Copy)|(1<<composite_Sover)|\
83
(1<<composite_Din)|(1<<composite_Dout))
84
#define alpha_out_notS_D\
85
(_alpha_out_either|(1<<composite_Sin)|(1<<composite_Sout)|\
86
(1<<composite_Dover)|(1<<composite_Highlight))
88
/* ------ Object definition and creation ------ */
90
/* Define alpha-compositing objects. */
91
static composite_create_default_compositor_proc(c_alpha_create_default_compositor);
92
static composite_equal_proc(c_alpha_equal);
93
static composite_write_proc(c_alpha_write);
94
static composite_read_proc(c_alpha_read);
95
const gs_composite_type_t gs_composite_alpha_type =
99
c_alpha_create_default_compositor,
103
gx_default_composite_adjust_ctm,
104
gx_default_composite_is_closing,
105
gx_default_composite_is_friendly,
106
gx_default_composite_clist_write_update,
107
gx_default_composite_clist_read_update,
108
gx_default_composite_get_cropping
111
typedef struct gs_composite_alpha_s {
113
gs_composite_alpha_params_t params;
114
} gs_composite_alpha_t;
116
gs_private_st_simple(st_composite_alpha, gs_composite_alpha_t,
117
"gs_composite_alpha_t");
119
/* Create an alpha-compositing object. */
121
gs_create_composite_alpha(gs_composite_t ** ppcte,
122
const gs_composite_alpha_params_t * params, gs_memory_t * mem)
124
gs_composite_alpha_t *pcte;
126
pcte = gs_alloc_struct(mem, gs_composite_alpha_t, &st_composite_alpha,
127
"gs_create_composite_alpha");
129
return_error(gs_error_VMerror);
130
pcte->type = &gs_composite_alpha_type;
131
pcte->id = gs_next_ids(mem, 1);
132
pcte->params = *params;
134
*ppcte = (gs_composite_t *) pcte;
138
/* ------ Object implementation ------ */
140
#define pacte ((const gs_composite_alpha_t *)pcte)
143
c_alpha_equal(const gs_composite_t * pcte, const gs_composite_t * pcte2)
145
return (pcte2->type == pcte->type &&
146
#define pacte2 ((const gs_composite_alpha_t *)pcte2)
147
pacte2->params.op == pacte->params.op &&
148
(pacte->params.op != composite_Dissolve ||
149
pacte2->params.delta == pacte->params.delta));
154
c_alpha_write(const gs_composite_t * pcte, byte * data, uint * psize, gx_device_clist_writer *cdev)
159
if_debug1('v', "[v]c_alpha_write(%d)\n", pacte->params.op);
160
if (pacte->params.op == composite_Dissolve) {
161
used = 1 + sizeof(pacte->params.delta);
164
return_error(gs_error_rangecheck);
166
memcpy(data + 1, &pacte->params.delta, sizeof(pacte->params.delta));
171
return_error(gs_error_rangecheck);
174
*data = (byte) pacte->params.op;
180
c_alpha_read(gs_composite_t ** ppcte, const byte * data, uint size,
183
gs_composite_alpha_params_t params;
184
int code, nbytes = 1;
186
if (size < 1 || *data > composite_op_last)
187
return_error(gs_error_rangecheck);
189
if_debug1('v', "[v]c_alpha_read(%d)\n", params.op);
190
if (params.op == composite_Dissolve) {
191
if (size < 1 + sizeof(params.delta))
192
return_error(gs_error_rangecheck);
193
memcpy(¶ms.delta, data + 1, sizeof(params.delta));
194
nbytes += sizeof(params.delta);
196
code = gs_create_composite_alpha(ppcte, ¶ms, mem);
197
return code < 0 ? code : nbytes;
200
/* ---------------- Alpha-compositing device ---------------- */
202
/* Define the default alpha-compositing device. */
203
typedef struct gx_device_composite_alpha_s {
204
gx_device_forward_common;
205
gs_composite_alpha_params_t params;
206
} gx_device_composite_alpha;
208
gs_private_st_suffix_add0_final(st_device_composite_alpha,
209
gx_device_composite_alpha, "gx_device_composite_alpha",
210
device_c_alpha_enum_ptrs, device_c_alpha_reloc_ptrs, gx_device_finalize,
212
/* The device descriptor. */
213
static dev_proc_close_device(dca_close);
214
static dev_proc_fill_rectangle(dca_fill_rectangle);
215
static dev_proc_map_rgb_color(dca_map_rgb_color);
216
static dev_proc_map_color_rgb(dca_map_color_rgb);
217
static dev_proc_copy_mono(dca_copy_mono);
218
static dev_proc_copy_color(dca_copy_color);
219
static dev_proc_map_rgb_alpha_color(dca_map_rgb_alpha_color);
220
static dev_proc_map_color_rgb_alpha(dca_map_color_rgb_alpha);
221
static dev_proc_copy_alpha(dca_copy_alpha);
222
static const gx_device_composite_alpha gs_composite_alpha_device =
223
{std_device_std_body_open(gx_device_composite_alpha, 0,
224
"alpha compositor", 0, 0, 1, 1),
225
{gx_default_open_device,
226
gx_forward_get_initial_matrix,
227
gx_default_sync_output,
228
gx_default_output_page,
233
gx_default_tile_rectangle,
236
gx_default_draw_line,
238
gx_forward_get_params,
239
gx_forward_put_params,
240
gx_default_cmyk_map_cmyk_color, /* only called for CMYK */
241
gx_forward_get_xfont_procs,
242
gx_forward_get_xfont_device,
243
dca_map_rgb_alpha_color,
244
gx_forward_get_page_device,
245
gx_forward_get_alpha_bits,
249
gx_default_fill_path,
250
gx_default_stroke_path,
251
gx_default_fill_mask,
252
gx_default_fill_trapezoid,
253
gx_default_fill_parallelogram,
254
gx_default_fill_triangle,
255
gx_default_draw_thin_line,
256
gx_default_begin_image,
257
gx_default_image_data,
258
gx_default_end_image,
259
gx_default_strip_tile_rectangle,
260
gx_default_strip_copy_rop,
261
gx_forward_get_clipping_box,
262
gx_default_begin_typed_image,
263
gx_forward_get_bits_rectangle,
264
dca_map_color_rgb_alpha,
265
gx_no_create_compositor
269
/* Create an alpha compositor. */
271
c_alpha_create_default_compositor(const gs_composite_t * pcte,
272
gx_device ** pcdev, gx_device * dev, gs_imager_state * pis,
275
gx_device_composite_alpha *cdev;
277
if (pacte->params.op == composite_Copy) {
278
/* Just use the original device. */
283
gs_alloc_struct_immovable(mem, gx_device_composite_alpha,
284
&st_device_composite_alpha,
285
"create default alpha compositor");
286
*pcdev = (gx_device *)cdev;
288
return_error(gs_error_VMerror);
289
gx_device_init((gx_device *)cdev,
290
(const gx_device *)&gs_composite_alpha_device, mem, true);
291
gx_device_copy_params((gx_device *)cdev, dev);
293
* Set the color_info and depth to be compatible with the target,
294
* but using standard chunky color storage, including alpha.
295
****** CURRENTLY ALWAYS USE 8-BIT COLOR ******
297
cdev->color_info.depth =
298
(dev->color_info.num_components == 4 ? 32 /* CMYK, no alpha */ :
299
(dev->color_info.num_components + 1) * 8);
300
cdev->color_info.max_gray = cdev->color_info.max_color = 255;
301
/* No halftoning will occur, but we fill these in anyway.... */
302
cdev->color_info.dither_grays = cdev->color_info.dither_colors = 256;
304
* We could speed things up a little by tailoring the procedures in
305
* the device to the specific num_components, but for simplicity,
306
* we'll defer considering that until there is a demonstrated need.
308
gx_device_set_target((gx_device_forward *)cdev, dev);
309
cdev->params = pacte->params;
313
/* Close the device and free its storage. */
315
dca_close(gx_device * dev)
317
* Finalization will call close again: avoid a recursion loop.
319
set_dev_proc(dev, close_device, gx_default_close_device);
320
gs_free_object(dev->memory, dev, "dca_close");
324
/* ------ (RGB) color mapping ------ */
326
static gx_color_index
327
dca_map_rgb_color(gx_device * dev, const gx_color_value cv[])
329
return dca_map_rgb_alpha_color(dev, cv[0], cv[1], cv[2], gx_max_color_value);
331
static gx_color_index
332
dca_map_rgb_alpha_color(gx_device * dev,
333
gx_color_value red, gx_color_value green, gx_color_value blue,
334
gx_color_value alpha)
336
* We work exclusively with premultiplied color values, so we
337
* have to premultiply the color components by alpha here.
339
byte a = gx_color_value_to_byte(alpha);
342
(((c) * a + gx_max_color_value / 2) / gx_max_color_value)
343
#ifdef PREMULTIPLY_TOWARDS_WHITE
346
# define premult(c) (premult_(c) + bias)
348
# define premult(c) premult_(c)
350
gx_color_index color;
352
if (dev->color_info.num_components == 1) {
354
(red * lum_red_weight + green * lum_green_weight +
355
blue * lum_blue_weight + lum_all_weights / 2) /
359
color = gx_color_value_to_byte(lum);
360
else /* Premultiplication is necessary. */
361
color = premult(lum);
365
((uint) gx_color_value_to_byte(red) << 16) +
366
((uint) gx_color_value_to_byte(green) << 8) +
367
gx_color_value_to_byte(blue);
368
else /* Premultiplication is necessary. */
370
(premult(red) << 16) + (premult(green) << 8) + premult(blue);
373
return (color << 8) + a;
376
dca_map_color_rgb(gx_device * dev, gx_color_index color,
377
gx_color_value prgb[3])
379
gx_color_value red = gx_color_value_from_byte((byte) (color >> 24));
380
byte a = (byte) color;
383
(((c) * 0xff + a / 2) / a)
384
#ifdef PREMULTIPLY_TOWARDS_WHITE
387
# define postdiv(c) postdiv_(c - bias)
389
# define postdiv(c) postdiv_(c)
392
if (dev->color_info.num_components == 1) {
394
/* Undo premultiplication. */
400
prgb[0] = prgb[1] = prgb[2] = red;
403
green = gx_color_value_from_byte((byte) (color >> 16)),
404
blue = gx_color_value_from_byte((byte) (color >> 8));
407
/* Undo premultiplication. */
408
/****** WHAT TO DO ABOUT BIG LOSS OF PRECISION? ******/
410
red = green = blue = 0;
413
green = postdiv(green);
414
blue = postdiv(blue);
417
prgb[0] = red, prgb[1] = green, prgb[2] = blue;
423
dca_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
424
gx_color_value prgba[4])
426
prgba[3] = gx_color_value_from_byte((byte) color);
427
return dca_map_color_rgb(dev, color, prgba);
430
/* ------ Imaging ------ */
433
dca_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
434
gx_color_index color)
435
{ /* This is where all the real work gets done! */
436
gx_device_composite_alpha *adev = (gx_device_composite_alpha *) dev;
437
gx_device *target = adev->target;
441
gs_get_bits_params_t std_params, native_params;
444
gs_composite_params_t cp;
445
const_pixel_row_t source;
448
fit_fill(dev, x, y, w, h);
449
std_row = gs_alloc_bytes(dev->memory,
450
(dev->color_info.depth * w + 7) >> 3,
451
"dca_fill_rectangle(std)");
452
native_row = gs_alloc_bytes(dev->memory,
453
(target->color_info.depth * w + 7) >> 3,
454
"dca_fill_rectangle(native)");
455
if (std_row == 0 || native_row == 0) {
456
code = gs_note_error(gs_error_VMerror);
459
rect.p.x = x, rect.q.x = x + w;
462
(GB_ALPHA_LAST | GB_DEPTH_8 | GB_PACKING_CHUNKY |
463
GB_RETURN_COPY | GB_RETURN_POINTER | GB_ALIGN_ANY |
464
GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD |
466
cp.cop = adev->params.op;
467
if (cp.cop == composite_Dissolve)
468
cp.delta = adev->params.delta;
470
gx_color_value rgba[4];
472
/****** DOESN'T HANDLE CMYK ******/
473
(*dev_proc(dev, map_color_rgb_alpha)) (dev, color, rgba);
474
cp.source_values[0] = gx_color_value_to_byte(rgba[0]);
475
cp.source_values[1] = gx_color_value_to_byte(rgba[1]);
476
cp.source_values[2] = gx_color_value_to_byte(rgba[2]);
477
cp.source_alpha = gx_color_value_to_byte(rgba[3]);
480
source.bits_per_value = 8;
481
source.alpha = gs_image_alpha_none;
482
for (yi = y; yi < y + h; ++yi) {
483
/* Read a row in standard representation. */
484
rect.p.y = yi, rect.q.y = yi + 1;
485
std_params.data[0] = std_row;
486
code = (*dev_proc(target, get_bits_rectangle))
487
(target, &rect, &std_params, NULL);
491
dest.data = std_params.data[0];
492
dest.bits_per_value = 8;
494
(std_params.options & GB_OFFSET_ANY ? std_params.x_offset : 0);
496
(std_params.options & GB_ALPHA_FIRST ? gs_image_alpha_first :
497
std_params.options & GB_ALPHA_LAST ? gs_image_alpha_last :
498
gs_image_alpha_none);
499
code = composite_values(&dest, &source,
500
dev->color_info.num_components, w, &cp);
503
if (std_params.data[0] == std_row) {
504
/* Convert the row back to native representation. */
505
/* (Otherwise, we had a direct pointer to device data.) */
506
native_params.options =
507
(GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_RETURN_COPY |
508
GB_OFFSET_0 | GB_RASTER_ALL | GB_ALIGN_STANDARD);
509
native_params.data[0] = native_row;
510
code = gx_get_bits_copy(target, 0, w, 1, &native_params,
511
&std_params, std_row,
512
0 /* raster is irrelevant */ );
515
code = (*dev_proc(target, copy_color))
516
(target, native_row, 0, 0 /* raster is irrelevant */ ,
517
gx_no_bitmap_id, x, yi, w, 1);
522
out:gs_free_object(dev->memory, native_row, "dca_fill_rectangle(native)");
523
gs_free_object(dev->memory, std_row, "dca_fill_rectangle(std)");
528
dca_copy_mono(gx_device * dev, const byte * data,
529
int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
530
gx_color_index zero, gx_color_index one)
532
/****** TEMPORARY ******/
533
return gx_default_copy_mono(dev, data, dx, raster, id, x, y, w, h,
538
dca_copy_color(gx_device * dev, const byte * data,
539
int dx, int raster, gx_bitmap_id id,
540
int x, int y, int w, int h)
542
/****** TEMPORARY ******/
543
return gx_default_copy_color(dev, data, dx, raster, id, x, y, w, h);
547
dca_copy_alpha(gx_device * dev, const byte * data, int data_x,
548
int raster, gx_bitmap_id id, int x, int y, int width, int height,
549
gx_color_index color, int depth)
551
/****** TEMPORARY ******/
552
return gx_default_copy_alpha(dev, data, data_x, raster, id, x, y,
553
width, height, color, depth);
557
* Composite two arrays of (premultiplied) pixel values.
558
* See gsdpnext.h for the specification.
560
* The current implementation is simple but inefficient. We'll speed it up
561
* later if necessary.
564
composite_values(const pixel_row_t * pdest, const const_pixel_row_t * psource,
565
int values_per_pixel, uint num_pixels, const gs_composite_params_t * pcp)
567
int dest_bpv = pdest->bits_per_value;
568
int source_bpv = psource->bits_per_value;
571
* source_alpha_j gives the source component index for the alpha value,
572
* if the source has alpha.
575
(psource->alpha == gs_image_alpha_last ? values_per_pixel :
576
psource->alpha == gs_image_alpha_first ? 0 : -1);
578
/* dest_alpha_j does the same for the destination. */
580
(pdest->alpha == gs_image_alpha_last ? values_per_pixel :
581
pdest->alpha == gs_image_alpha_first ? 0 : -1);
583
/* dest_vpp is the number of stored destination values. */
584
int dest_vpp = values_per_pixel + (dest_alpha_j >= 0);
586
/* source_vpp is the number of stored source values. */
587
int source_vpp = values_per_pixel + (source_alpha_j >= 0);
589
bool constant_colors = psource->data == 0;
590
uint highlight_value = (1 << dest_bpv) - 1;
592
sample_load_declare(sptr, sbit);
593
sample_store_declare(dptr, dbit, dbyte);
596
uint xbit = pdest->initial_x * dest_bpv * dest_vpp;
598
sample_store_setup(dbit, xbit & 7, dest_bpv);
599
dptr = pdest->data + (xbit >> 3);
602
uint xbit = psource->initial_x * source_bpv * source_vpp;
605
sptr = psource->data + (xbit >> 3);
608
uint source_max = (1 << source_bpv) - 1;
609
uint dest_max = (1 << dest_bpv) - 1;
612
* We could save a little work by only setting up source_delta
613
* and dest_delta if the operation is Dissolve.
615
float source_delta = pcp->delta * dest_max / source_max;
616
float dest_delta = 1.0 - pcp->delta;
617
uint source_alpha = pcp->source_alpha;
618
uint dest_alpha = dest_max;
620
#ifdef PREMULTIPLY_TOWARDS_WHITE
621
uint source_bias = source_max - source_alpha;
623
uint result_bias = 0;
630
(psource->alpha || source_alpha != source_max ?
631
alpha_out_S_notD : alpha_out_notS_notD);
633
if ((mask >> pcp->cop) & 1) {
635
* The operation could produce non-unity alpha values, but
636
* the destination can't store them. Return an error.
638
return_error(gs_error_rangecheck);
641
/* Preload the output byte buffer if necessary. */
642
sample_store_preload(dbyte, dptr, dbit, dest_bpv);
644
for (x = 0; x < num_pixels; ++x) {
646
uint result_alpha = dest_alpha;
648
/* get_value does not increment the source pointer. */
649
#define get_value(v, ptr, bit, bpv, vmax)\
650
sample_load16(v, ptr, bit, bpv)
652
/* put_value increments the destination pointer. */
653
#define put_value(v, ptr, bit, bpv, bbyte)\
654
sample_store_next16(v, ptr, bit, bpv, bbyte)
656
#define advance(ptr, bit, bpv)\
657
sample_next(ptr, bit, bpv)
659
/* Get destination alpha value. */
660
if (dest_alpha_j >= 0) {
661
int dabit = dbit + dest_bpv * dest_alpha_j;
662
const byte *daptr = dptr + (dabit >> 3);
664
get_value(dest_alpha, daptr, dabit & 7, dest_bpv, dest_max);
665
#ifdef PREMULTIPLY_TOWARDS_WHITE
666
dest_bias = dest_max - dest_alpha;
669
/* Get source alpha value. */
670
if (source_alpha_j >= 0) {
672
const byte *saptr = sptr;
674
if (source_alpha_j == 0)
675
advance(sptr, sbit, source_bpv);
677
advance(saptr, sabit, source_bpv * source_alpha_j);
678
get_value(source_alpha, saptr, sabit, source_bpv, source_max);
679
#ifdef PREMULTIPLY_TOWARDS_WHITE
680
source_bias = source_max - source_alpha;
684
* We are always multiplying a dest value by a source value to compute a
685
* dest value, so the denominator is always source_max. (Dissolve is the
688
#define fr(v, a) ((v) * (a) / source_max)
689
#define nfr(v, a, maxv) ((v) * (maxv - (a)) / source_max)
692
* Iterate over the components of a single pixel.
693
* j = 0 for alpha, 1 .. values_per_pixel for color
694
* components, regardless of the actual storage order;
695
* we arrange things so that sptr/sbit and dptr/dbit
696
* always point to the right place.
698
for (j = 0; j <= values_per_pixel; ++j) {
699
uint dest_v, source_v, result;
701
#define set_clamped(r, v)\
702
BEGIN if ( (r = (v)) > dest_max ) r = dest_max; END
705
source_v = source_alpha;
709
source_v = pcp->source_values[j - 1];
711
get_value(source_v, sptr, sbit, source_bpv, source_max);
712
advance(sptr, sbit, source_bpv);
714
get_value(dest_v, dptr, dbit, dest_bpv, dest_max);
715
#ifdef PREMULTIPLY_TOWARDS_WHITE
716
source_v -= source_bias;
722
case composite_Clear:
724
* The NeXT documentation doesn't say this, but the CLEAR
725
* operation sets not only alpha but also all the color
733
case composite_PlusD:
735
* This is the only case where we have to worry about
736
* clamping a possibly negative result.
738
result = source_v + dest_v;
739
result = (result < dest_max ? 0 : result - dest_max);
741
case composite_PlusL:
742
set_clamped(result, source_v + dest_v);
744
case composite_Sover:
745
set_clamped(result, source_v + nfr(dest_v, source_alpha, source_max));
747
case composite_Dover:
748
set_clamped(result, nfr(source_v, dest_alpha, dest_max) + dest_v);
751
result = fr(source_v, dest_alpha);
754
result = fr(dest_v, source_alpha);
757
result = nfr(source_v, dest_alpha, dest_max);
760
result = nfr(dest_v, source_alpha, source_max);
762
case composite_Satop:
763
set_clamped(result, fr(source_v, dest_alpha) +
764
nfr(dest_v, source_alpha, source_max));
766
case composite_Datop:
767
set_clamped(result, nfr(source_v, dest_alpha, dest_max) +
768
fr(dest_v, source_alpha));
771
set_clamped(result, nfr(source_v, dest_alpha, dest_max) +
772
nfr(dest_v, source_alpha, source_max));
774
case composite_Highlight:
776
* Bizarre but true: this operation converts white and
777
* light gray into each other, and leaves all other values
778
* unchanged. We only implement it properly for gray-scale
781
if (j != 0 && !((source_v ^ highlight_value) & ~1))
782
result = source_v ^ 1;
786
case composite_Dissolve:
788
* In this case, and only this case, we need to worry about
789
* source and dest having different bpv values. For the
790
* moment, we wimp out and do everything in floating point.
792
result = (uint) (source_v * source_delta + dest_v * dest_delta);
795
return_error(gs_error_rangecheck);
798
* Store the result. We don't have to worry about
799
* destinations that don't store alpha, because we don't
800
* even compute an alpha value in that case.
802
#ifdef PREMULTIPLY_TOWARDS_WHITE
804
result_alpha = result;
805
result_bias = dest_max - result_alpha;
806
if (dest_alpha_j != 0)
809
result += result_bias;
812
if (j == 0 && dest_alpha_j != 0) {
813
result_alpha = result;
817
put_value(result, dptr, dbit, dest_bpv, dbyte);
819
/* Skip a trailing source alpha value. */
820
if (source_alpha_j > 0)
821
advance(sptr, sbit, source_bpv);
822
/* Store a trailing destination alpha value. */
823
if (dest_alpha_j > 0)
824
put_value(result_alpha, dptr, dbit, dest_bpv, dbyte);
829
/* Store any partial output byte. */
830
sample_store_flush(dptr, dbit, dest_bpv, dbyte);