1 /* Copyright (C) 1997, 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gdevalph.c,v 1.2.6.1.2.1 2003/01/17 00:49:00 giles Exp $ */
20 /* Alpha-channel storage device */
21 #include "memory_.h"
22 #include "gx.h"
23 #include "gserrors.h"
24 #include "gsdcolor.h"
25 #include "gxdevice.h"
26 #include "gxdevmem.h"
27 #include "gxgetbit.h"
28 
29 /*
30  * Very few devices (actually, none right now) actually store an alpha
31  * channel.  Here we provide a device that acts as a "wrapper" around
32  * another device, and adds alpha channel storage.
33  */
34 
35 /* Define the device. */
36 typedef struct gx_device_store_alpha_s {
37     gx_device_forward_common;
38     bool open_close_target;	/* if true, open/close target when opening/closing */
39     int alpha_depth;		/* # of bits of stored alpha */
40     gx_device_memory *adev;	/* stores the alpha values -- created when needed */
41 } gx_device_store_alpha;
42 
43 gs_private_st_suffix_add1_final(st_device_store_alpha,
44 			     gx_device_store_alpha, "gx_device_store_alpha",
45 		device_store_alpha_enum_ptrs, device_store_alpha_reloc_ptrs,
46 				gx_device_finalize, st_device_forward, adev);
47 /* The device descriptor. */
48 private dev_proc_open_device(dsa_open);
49 private dev_proc_close_device(dsa_close);
50 private dev_proc_fill_rectangle(dsa_fill_rectangle);
51 private dev_proc_map_rgb_color(dsa_map_rgb_color);
52 private dev_proc_map_color_rgb(dsa_map_color_rgb);
53 private dev_proc_copy_mono(dsa_copy_mono);
54 private dev_proc_copy_color(dsa_copy_color);
55 private dev_proc_put_params(dsa_put_params);
56 private dev_proc_map_rgb_alpha_color(dsa_map_rgb_alpha_color);
57 private dev_proc_map_color_rgb_alpha(dsa_map_color_rgb_alpha);
58 private dev_proc_copy_alpha(dsa_copy_alpha);
59 private dev_proc_fill_path(dsa_fill_path);
60 private dev_proc_stroke_path(dsa_stroke_path);
61 private dev_proc_get_bits_rectangle(dsa_get_bits_rectangle);
62 private const gx_device_store_alpha gs_store_alpha_device =
63 {std_device_std_body_open(gx_device_store_alpha, 0,
64 			  "alpha storage", 0, 0, 1, 1),
65  {dsa_open,
66   gx_forward_get_initial_matrix,
67   gx_forward_sync_output,
68   gx_forward_output_page,
69   dsa_close,
70   dsa_map_rgb_color,
71   dsa_map_color_rgb,
72   dsa_fill_rectangle,
73   gx_default_tile_rectangle,
74   dsa_copy_mono,
75   dsa_copy_color,
76   gx_default_draw_line,
77   gx_default_get_bits,
78   gx_forward_get_params,
79   dsa_put_params,
80   gx_default_cmyk_map_cmyk_color,	/* only called for CMYK */
81   gx_forward_get_xfont_procs,
82   gx_forward_get_xfont_device,
83   dsa_map_rgb_alpha_color,
84   gx_forward_get_page_device,
85   gx_forward_get_alpha_bits,
86   dsa_copy_alpha,
87   gx_forward_get_band,
88   gx_default_copy_rop,
89   dsa_fill_path,
90   dsa_stroke_path,
91 		/*
92 		 * We should do the same thing for the "mid-level"
93 		 * drawing operations that we do for fill_path and
94 		 * stroke_path, but we don't bother to do this yet.
95 		 */
96   gx_default_fill_mask,
97   gx_default_fill_trapezoid,
98   gx_default_fill_parallelogram,
99   gx_default_fill_triangle,
100   gx_default_draw_thin_line,
101   gx_default_begin_image,
102   gx_default_image_data,
103   gx_default_end_image,
104   gx_default_strip_tile_rectangle,
105   gx_default_strip_copy_rop,
106   gx_forward_get_clipping_box,
107   gx_default_begin_typed_image,
108   dsa_get_bits_rectangle,
109   dsa_map_color_rgb_alpha,
110   gx_default_create_compositor
111  }
112 };
113 
114 /* Forward references */
115 private int alloc_alpha_storage(P1(gx_device_store_alpha * sadev));
116 
117 #define sadev ((gx_device_store_alpha *)dev)
118 
119 /* ------ Open/close ------ */
120 
121 private int
dsa_open(gx_device * dev)122 dsa_open(gx_device * dev)
123 {
124     gx_device *tdev = sadev->target;
125     int max_value =
126     max(tdev->color_info.max_gray, tdev->color_info.max_color);
127     int adepth = (max_value <= 3 ? 2 : max_value <= 15 ? 4 : 8);
128     int depth = tdev->color_info.depth + adepth;
129     int code;
130 
131     if (depth > 32)
132 	return_error(gs_error_rangecheck);
133     code =
134 	(sadev->open_close_target ?
135 	 (*dev_proc(tdev, open_device)) (tdev) : 0);
136     if (code < 0)
137 	return code;
138     sadev->width = tdev->width;
139     sadev->height = tdev->height;
140     sadev->color_info = tdev->color_info;
141     sadev->color_info.depth = (depth <= 4 ? 4 : ROUND_UP(depth, 8));
142     sadev->alpha_depth = adepth;
143     sadev->adev = 0;
144     return 0;
145 }
146 
147 private int
dsa_close(gx_device * dev)148 dsa_close(gx_device * dev)
149 {
150     gx_device *adev = (gx_device *) sadev->adev;
151 
152     if (adev) {
153 	(*dev_proc(adev, close_device)) (adev);
154 	gs_free_object(dev->memory, adev, "dsa_close(adev)");
155 	sadev->adev = 0;
156     }
157     if (sadev->open_close_target) {
158 	gx_device *tdev = sadev->target;
159 
160 	return (*dev_proc(tdev, close_device)) (tdev);
161     }
162     return 0;
163 }
164 
165 /* ------ Color mapping ------ */
166 
167 private gx_color_index
dsa_map_rgb_color(gx_device * dev,gx_color_value red,gx_color_value green,gx_color_value blue)168 dsa_map_rgb_color(gx_device * dev,
169 	      gx_color_value red, gx_color_value green, gx_color_value blue)
170 {
171     return dsa_map_rgb_alpha_color(dev, red, green, blue,
172 				   gx_max_color_value);
173 }
174 
175 private int
dsa_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value rgb[3])176 dsa_map_color_rgb(gx_device * dev,
177 		  gx_color_index color, gx_color_value rgb[3])
178 {
179     gx_device *tdev = sadev->target;
180 
181     return (*dev_proc(tdev, map_color_rgb))
182 	(tdev, color >> sadev->alpha_depth, rgb);
183 }
184 
185 private gx_color_index
dsa_map_rgb_alpha_color(gx_device * dev,gx_color_value red,gx_color_value green,gx_color_value blue,gx_color_value alpha)186 dsa_map_rgb_alpha_color(gx_device * dev,
187 	      gx_color_value red, gx_color_value green, gx_color_value blue,
188 			gx_color_value alpha)
189 {
190     gx_device *tdev = sadev->target;
191     int adepth = sadev->alpha_depth;
192 
193     return
194 	((*dev_proc(tdev, map_rgb_color)) (tdev, red, green, blue)
195 	 << adepth) + (alpha * ((1 << adepth) - 1) / gx_max_color_value);
196 }
197 
198 private int
dsa_map_color_rgb_alpha(gx_device * dev,gx_color_index color,gx_color_value rgba[4])199 dsa_map_color_rgb_alpha(gx_device * dev,
200 			gx_color_index color, gx_color_value rgba[4])
201 {
202     int code = dsa_map_color_rgb(dev, color, rgba);
203     int amask = (1 << sadev->alpha_depth) - 1;
204 
205     if (code < 0)
206 	return code;
207     rgba[3] = (color & amask) * gx_max_color_value / amask;
208     return code;
209 }
210 
211 /* ------ Low-level drawing ------ */
212 
213 private int
dsa_fill_rectangle(gx_device * dev,int x,int y,int width,int height,gx_color_index color)214 dsa_fill_rectangle(gx_device * dev,
215 		   int x, int y, int width, int height, gx_color_index color)
216 {
217     gx_device *tdev = sadev->target;
218     gx_device *adev = (gx_device *) sadev->adev;
219     int adepth = sadev->alpha_depth;
220     uint amask = (1 << adepth) - 1;
221 
222     if ((~color & amask) && !adev) {
223 	int code = alloc_alpha_storage(sadev);
224 
225 	if (code < 0)
226 	    return code;
227 	adev = (gx_device *) sadev->adev;
228     }
229     if (adev)
230 	(*dev_proc(adev, fill_rectangle))
231 	    (adev, x, y, width, height, color & amask);
232     return (*dev_proc(tdev, fill_rectangle))
233 	(tdev, x, y, width, height, color >> adepth);
234 }
235 
236 private int
dsa_copy_mono(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color0,gx_color_index color1)237 dsa_copy_mono(gx_device * dev,
238 	      const byte * data, int data_x, int raster, gx_bitmap_id id,
239 	      int x, int y, int width, int height,
240 	      gx_color_index color0, gx_color_index color1)
241 {
242     gx_device *tdev = sadev->target;
243     gx_device *adev = (gx_device *) sadev->adev;
244     int adepth = sadev->alpha_depth;
245     uint amask = (1 << adepth) - 1;
246 
247     if ((((color0 != gx_no_color_index) && (~color0 & amask)) ||
248 	 ((color1 != gx_no_color_index) && (~color1 & amask))) && !adev
249 	) {
250 	int code = alloc_alpha_storage(sadev);
251 
252 	if (code < 0)
253 	    return code;
254 	adev = (gx_device *) sadev->adev;
255     }
256     if (adev)
257 	(*dev_proc(adev, copy_mono))
258 	    (adev, data, data_x, raster, id, x, y, width, height,
259 	     (color0 == gx_no_color_index ? color0 : color0 & amask),
260 	     (color1 == gx_no_color_index ? color1 : color1 & amask));
261     return (*dev_proc(tdev, copy_mono))
262 	(tdev, data, data_x, raster, id, x, y, width, height,
263 	 (color0 == gx_no_color_index ? color0 : color0 >> adepth),
264 	 (color1 == gx_no_color_index ? color1 : color1 >> adepth));
265 }
266 
267 private int
dsa_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height)268 dsa_copy_color(gx_device * dev,
269 	       const byte * data, int data_x, int raster, gx_bitmap_id id,
270 	       int x, int y, int width, int height)
271 {
272     int sdepth = dev->color_info.depth;
273     gx_device *tdev = sadev->target;
274     int tdepth = tdev->color_info.depth;
275     gx_device *adev = (gx_device *) sadev->adev;
276     int adepth = sadev->alpha_depth;	/* = adev->color_info.depth */
277     uint amask = (1 << adepth) - 1;
278     gs_memory_t *mem = dev->memory;
279     byte *color_row;
280     byte *alpha_row;
281     int code = 0;
282     int xbit, yi;
283 
284     fit_copy(dev, data, data_x, raster, id, x, y, width, height);
285     color_row =
286 	gs_alloc_bytes(mem, bitmap_raster(width * tdepth),
287 		       "dsa_copy_color(color)");
288     /*
289      * If we aren't already storing alpha, alpha_row remains 0 until we
290      * encounter a source value with a non-unity alpha.
291      */
292     alpha_row =
293 	(adev ?
294 	 gs_alloc_bytes(mem, bitmap_raster(width * adepth),
295 			"dsa_copy_color(color)") : 0);
296     if (color_row == 0 || (adev && alpha_row == 0)) {
297 	code = gs_note_error(gs_error_VMerror);
298 	goto out;
299     }
300     xbit = data_x * dev->color_info.depth;
301     for (yi = y; yi < y + height; ++yi) {
302 	const byte *source_row = data + (yi - y) * raster;
303 
304 	sample_load_declare_setup(sptr, sbit, source_row + (xbit >> 3),
305 				  xbit & 7, sdepth);
306 	sample_store_declare_setup(dcptr, dcbit, dcbyte,
307 				   color_row, 0, tdepth);
308 	sample_store_declare_setup(daptr, dabit, dabyte,
309 				   alpha_row, 0, adepth);
310 	int xi;
311 
312 	for (xi = 0; xi < width; ++xi) {
313 	    gx_color_index source;
314 
315 	    sample_load_next32(source, sptr, sbit, sdepth);
316 	    {
317 		gx_color_index dest_color = source >> adepth;
318 
319 		sample_store_next32(dest_color, dcptr, dcbit, tdepth, dcbyte);
320 	    }
321 	    {
322 		uint dest_alpha = source & amask;
323 
324 		if (dest_alpha != amask && !alpha_row) {
325 		    /*
326 		     * Create an alpha row (and, if necessary, alpha storage).
327 		     */
328 		    int axbit = (xi - x) * adepth;
329 
330 		    if (!adev) {
331 			code = alloc_alpha_storage(sadev);
332 			if (code < 0)
333 			    return code;
334 			adev = (gx_device *) sadev->adev;
335 		    }
336 		    alpha_row =
337 			gs_alloc_bytes(mem, bitmap_raster(width * adepth),
338 				       "dsa_copy_color(color)");
339 		    if (alpha_row == 0) {
340 			code = gs_note_error(gs_error_VMerror);
341 			goto out;
342 		    }
343 		    /*
344 		     * All the alpha values up to this point are unity, so we
345 		     * can fill them into the alpha row quickly.
346 		     */
347 		    memset(alpha_row, 0xff, (axbit + 7) >> 3);
348 		    daptr = alpha_row + (axbit >> 3);
349 		    sample_store_setup(dabit, axbit & 7, adepth);
350 		    sample_store_preload(dabyte, daptr, dabit, adepth);
351 		}
352 		if (alpha_row)
353 		    sample_store_next12(dest_alpha, daptr, dabit, adepth, dabyte);
354 	    }
355 	}
356 	if (alpha_row) {
357 	    sample_store_flush(daptr, dabit, adepth, dabyte);
358 	    (*dev_proc(adev, copy_color))
359 		(adev, alpha_row, 0, 0 /* irrelevant */ , gx_no_bitmap_id,
360 		 x, yi, width, 1);
361 	}
362 	sample_store_flush(dcptr, dcbit, adepth, dcbyte);
363 	(*dev_proc(tdev, copy_color))
364 	    (tdev, color_row, 0, 0 /* irrelevant */ , gx_no_bitmap_id,
365 	     x, yi, width, 1);
366     }
367   out:gs_free_object(mem, alpha_row, "dsa_copy_color(alpha)");
368     gs_free_object(mem, color_row, "dsa_copy_color(color)");
369     return code;
370 }
371 
372 private int
dsa_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)373 dsa_copy_alpha(gx_device * dev, const byte * data, int data_x,
374 	   int raster, gx_bitmap_id id, int x, int y, int width, int height,
375 	       gx_color_index color, int depth)
376 {
377     gx_device *tdev = sadev->target;
378     gx_device *adev = (gx_device *) sadev->adev;
379     int adepth = sadev->alpha_depth;
380     uint amask = (1 << adepth) - 1;
381 
382     if ((~color & amask) && !adev) {
383 	int code = alloc_alpha_storage(sadev);
384 
385 	if (code < 0)
386 	    return code;
387 	adev = (gx_device *) sadev->adev;
388     }
389     if (adev)
390 	(*dev_proc(adev, copy_alpha))
391 	    (adev, data, data_x, raster, id, x, y, width, height,
392 	     color & amask, depth);
393     return (*dev_proc(tdev, copy_alpha))
394 	(tdev, data, data_x, raster, id, x, y, width, height,
395 	 color >> adepth, depth);
396 }
397 
398 /* ------ High-level drawing ------ */
399 
400 private int
dsa_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)401 dsa_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
402 	    const gx_fill_params * params, const gx_drawing_color * pdcolor,
403 	      const gx_clip_path * pcpath)
404 {
405     if (!color_is_pure(pdcolor))
406 	return gx_default_fill_path(dev, pis, ppath, params, pdcolor,
407 				    pcpath);
408 
409     {
410 	gx_color_index color = gx_dc_pure_color(pdcolor);
411 	gx_drawing_color dcolor;
412 	gx_device *tdev = sadev->target;
413 	gx_device *adev = (gx_device *) sadev->adev;
414 	int adepth = sadev->alpha_depth;
415 	uint amask = (1 << adepth) - 1;
416 	int code;
417 
418 	if ((~color & amask) && !adev) {
419 	    code = alloc_alpha_storage(sadev);
420 	    if (code < 0)
421 		return code;
422 	    adev = (gx_device *) sadev->adev;
423 	}
424 	if (adev) {
425 	    color_set_pure(&dcolor, color & amask);
426 	    code = (*dev_proc(adev, fill_path))
427 		(adev, pis, ppath, params, &dcolor, pcpath);
428 	    if (code < 0)
429 		return code;
430 	}
431 	color_set_pure(&dcolor, color >> adepth);
432 	return (*dev_proc(tdev, fill_path))
433 	    (tdev, pis, ppath, params, &dcolor, pcpath);
434     }
435 }
436 
437 private int
dsa_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)438 dsa_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
439 	  const gx_stroke_params * params, const gx_drawing_color * pdcolor,
440 		const gx_clip_path * pcpath)
441 {
442     if (!color_is_pure(pdcolor))
443 	return gx_default_stroke_path(dev, pis, ppath, params, pdcolor,
444 				      pcpath);
445 
446     {
447 	gx_color_index color = gx_dc_pure_color(pdcolor);
448 	gx_drawing_color dcolor;
449 	gx_device *tdev = sadev->target;
450 	gx_device *adev = (gx_device *) sadev->adev;
451 	int adepth = sadev->alpha_depth;
452 	uint amask = (1 << adepth) - 1;
453 	int code;
454 
455 	if ((~color & amask) && !adev) {
456 	    code = alloc_alpha_storage(sadev);
457 	    if (code < 0)
458 		return code;
459 	    adev = (gx_device *) sadev->adev;
460 	}
461 	if (adev) {
462 	    color_set_pure(&dcolor, color & amask);
463 	    code = (*dev_proc(adev, stroke_path))
464 		(adev, pis, ppath, params, &dcolor, pcpath);
465 	    if (code < 0)
466 		return code;
467 	}
468 	color_set_pure(&dcolor, color >> adepth);
469 	return (*dev_proc(tdev, stroke_path))
470 	    (tdev, pis, ppath, params, &dcolor, pcpath);
471     }
472 }
473 
474 /* ------ Reading bits ------ */
475 
476 private int
dsa_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)477 dsa_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
478 		       gs_get_bits_params_t * params, gs_int_rect ** unread)
479 {
480     int ddepth = dev->color_info.depth;
481     gx_device *tdev = sadev->target;
482     int tdepth = tdev->color_info.depth;
483     gx_device *adev = (gx_device *) sadev->adev;
484     int adepth = sadev->alpha_depth;	/* = adev->color_info.depth */
485     uint alpha = (1 << adepth) - 1;
486     gs_get_bits_options_t options = params->options;
487     int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y;
488     int yi;
489     uint raster =
490     (options & gb_raster_standard ? bitmap_raster(w * ddepth) :
491      params->raster);
492 
493     if ((~options &
494 	 (gb_colors_native | gb_alpha_last | gb_packing_chunky |
495 	  gb_return_copy | gb_offset_0)) ||
496 	!(options & (gb_raster_standard | gb_raster_specified))
497 	) {
498 	if (options == 0) {
499 	    params->options =
500 		gb_colors_native | gb_alpha_last | gb_packing_chunky |
501 		gb_return_copy | gb_offset_0 |
502 		(gb_raster_standard | gb_raster_specified);
503 	    return_error(gs_error_rangecheck);
504 	}
505     }
506     if ((w <= 0) | (h <= 0)) {
507 	if ((w | h) < 0)
508 	    return_error(gs_error_rangecheck);
509 	return 0;
510     }
511     if (x < 0 || w > dev->width - x ||
512 	y < 0 || h > dev->height - y
513 	)
514 	return_error(gs_error_rangecheck);
515     for (yi = y; yi < y + h; ++yi) {
516 	sample_load_declare(scptr, scbit);
517 	sample_load_declare(saptr, sabit);
518 	sample_store_declare(dptr, dbit, dbbyte);
519 	byte *data = params->data[0] + (yi - y) * raster;
520 	gs_get_bits_params_t color_params;
521 	gs_int_rect rect;
522 	int code, xi;
523 
524 	rect.p.x = x, rect.p.y = yi;
525 	rect.q.x = x + w, rect.q.y = yi + 1;
526 	color_params.options =
527 	    gb_colors_native | gb_alpha_none | gb_packing_chunky |
528 	    (gb_return_copy | gb_return_pointer) | gb_offset_specified |
529 	    gb_raster_all /*irrelevant */  | gb_align_all /*irrelevant */ ;
530 	color_params.x_offset = w;
531 	code = (*dev_proc(tdev, get_bits_rectangle))
532 	    (tdev, &rect, &color_params, NULL);
533 	if (code < 0)
534 	    return code;
535 	dptr = data;
536 	sample_store_setup(dbit, 0, ddepth);
537 	sample_store_preload(dbbyte, dptr, dbit, ddepth);
538 	{
539 	    int cxbit = (color_params.data[0] == data ? w * tdepth : 0);
540 
541 	    scptr = data + (cxbit >> 3);
542 	    sample_load_setup(scbit, cxbit & 7, tdepth);
543 	}
544 	if (adev) {
545 	    int axbit = x * adepth;
546 
547 	    saptr = data + (axbit >> 3);
548 	    sample_load_setup(sabit, axbit & 7, adepth);
549 	}
550 	for (xi = 0; xi < w; ++xi) {
551 	    gx_color_index colors;
552 
553 	    sample_load_next32(colors, scptr, scbit, tdepth);
554 	    if (adev)
555 		sample_load_next12(alpha, saptr, sabit, adepth);
556 	    colors = (colors << adepth) + alpha;
557 	    sample_store_next32(colors, dptr, dbit, ddepth, dbbyte);
558 	}
559 	sample_store_flush(dptr, dbit, ddepth, dbbyte);
560     }
561     return 0;
562 }
563 
564 /* ------ Setting parameters ------ */
565 
566 private int
dsa_put_params(gx_device * dev,gs_param_list * plist)567 dsa_put_params(gx_device * dev, gs_param_list * plist)
568 {
569     gx_device *tdev = sadev->target;
570     int code = (*dev_proc(tdev, put_params)) (tdev, plist);
571 
572     if (code < 0)
573 	return code;
574     gx_device_copy_params(dev, tdev);
575     return code;
576 }
577 
578 #undef sadev
579 
580 /* ------ Internal utilities ------ */
581 
582 /* Allocate the alpha storage memory device. */
583 private int
alloc_alpha_storage(gx_device_store_alpha * sadev)584 alloc_alpha_storage(gx_device_store_alpha * sadev)
585 {
586     int adepth = sadev->alpha_depth;
587     const gx_device_memory *mdproto = gdev_mem_device_for_bits(adepth);
588     gs_memory_t *mem = sadev->memory;
589     gx_device_memory *mdev =
590     gs_alloc_struct(mem, gx_device_memory,
591 		    &st_device_memory, "alloc_alpha_storage(adev)");
592     int code;
593 
594     if (mdev == 0)
595 	return_error(gs_error_VMerror);
596     gs_make_mem_device(mdev, mdproto, mem, 0, NULL);
597     mdev->width = sadev->width;
598     mdev->height = sadev->height;
599     mdev->bitmap_memory = mem;
600     code = (*dev_proc(mdev, open_device)) ((gx_device *) mdev);
601     if (code < 0) {
602 	gs_free_object(mem, mdev, "alloc_alpha_storage(adev)");
603 	return_error(gs_error_VMerror);
604     }
605     sadev->adev = mdev;
606     return (*dev_proc(mdev, fill_rectangle))
607 	((gx_device *) mdev, 0, 0, mdev->width, mdev->height,
608 	 (gx_color_index) ((1 << adepth) - 1));
609 }
610