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: gsdevmem.c 8022 2007-06-05 22:23:38Z giles $ */
15
/* Memory device creation for Ghostscript library */
16
#include "math_.h" /* for fabs */
20
#include "gsdevice.h" /* for prototypes */
25
/* Make a memory (image) device. */
26
/* If colors_size = -16, -24, or -32, this is a true-color device; */
27
/* otherwise, colors_size is the size of the palette in bytes */
28
/* (2^N for gray scale, 3*2^N for RGB color). */
29
/* We separate device allocation and initialization at customer request. */
31
gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat,
32
uint width, uint height, const byte * colors, int colors_size,
33
bool word_oriented, bool page_device, gs_memory_t * mem)
35
const gx_device_memory *proto_dev;
36
int palette_count = colors_size;
37
int num_components = 1;
40
float x_pixels_per_unit, y_pixels_per_unit;
41
byte palette[256 * 3];
44
switch (colors_size) {
82
return_error(gs_error_rangecheck);
84
proto_dev = (word_oriented ?
85
gdev_mem_word_device_for_bits(bits_per_pixel) :
86
gdev_mem_device_for_bits(bits_per_pixel));
87
if (proto_dev == 0) /* no suitable device */
88
return_error(gs_error_rangecheck);
89
pcount = palette_count * 3;
90
/* Check to make sure the palette contains white and black, */
91
/* and, if it has any colors, the six primaries. */
92
if (bits_per_pixel <= 8) {
99
for (i = 0, p = colors, q = palette;
100
i < palette_count; i++, q += 3
104
switch (num_components) {
106
q[0] = q[1] = q[2] = *p++;
108
default /* case 3 */ : /* RGB */
109
q[0] = p[0], q[1] = p[1], q[2] = p[2];
112
#define shift_mask(b,n)\
113
switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; }
118
primary_mask |= mask;
119
if (q[0] != q[1] || q[0] != q[2])
122
switch (primary_mask) {
123
case 129: /* just black and white */
124
if (has_color) /* color but no primaries */
125
return_error(gs_error_rangecheck);
126
case 255: /* full color */
129
return_error(gs_error_rangecheck);
134
* The initial transformation matrix must map 1 user unit to
135
* 1/72". Let W and H be the width and height in pixels, and
136
* assume the initial matrix is of the form [A 0 0 B X Y].
137
* Then the size of the image in user units is (W/|A|,H/|B|),
138
* hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so
139
* the number of pixels per inch is
140
* (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72).
141
* Similarly, if the initial matrix is [0 A B 0 X Y] for a 90
142
* or 270 degree rotation, the size of the image in user
143
* units is (W/|B|,H/|A|), so the pixels per inch are
144
* (|B|*72,|A|*72). We forbid non-orthogonal transformation
147
if (is_fzero2(pmat->xy, pmat->yx))
148
x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy;
149
else if (is_fzero2(pmat->xx, pmat->yy))
150
x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy;
152
return_error(gs_error_undefinedresult);
153
/* All checks done, initialize the device. */
154
if (bits_per_pixel == 1) {
155
/* Determine the polarity from the palette. */
156
gs_make_mem_device(new_dev, proto_dev, mem,
157
(page_device ? 1 : -1), 0);
158
/* This is somewhat bogus, but does the right thing */
159
/* in the only cases we care about. */
160
gdev_mem_mono_set_inverted(new_dev,
161
(palette[0] | palette[1] | palette[2]) != 0);
163
byte *dev_palette = gs_alloc_string(mem, pcount,
164
"gs_makeimagedevice(palette)");
166
if (dev_palette == 0)
167
return_error(gs_error_VMerror);
168
gs_make_mem_device(new_dev, proto_dev, mem,
169
(page_device ? 1 : -1), 0);
170
new_dev->palette.size = pcount;
171
new_dev->palette.data = dev_palette;
172
memcpy(dev_palette, palette, pcount);
174
new_dev->color_info.num_components = 1;
175
new_dev->color_info.max_color = 0;
176
new_dev->color_info.dither_colors = 0;
177
new_dev->color_info.gray_index = 0;
180
/* Memory defice is always initialised as an internal device but */
181
/* this is an external device */
182
new_dev->retained = true;
183
rc_init(new_dev, new_dev->memory, 1);
185
new_dev->initial_matrix = *pmat;
186
new_dev->MarginsHWResolution[0] = new_dev->HWResolution[0] =
187
fabs(x_pixels_per_unit) * 72;
188
new_dev->MarginsHWResolution[1] = new_dev->HWResolution[1] =
189
fabs(y_pixels_per_unit) * 72;
190
gx_device_set_width_height((gx_device *) new_dev, width, height);
191
/* Set the ImagingBBox so we get a correct clipping region. */
199
gs_bbox_transform_inverse(&bbox, pmat, &bbox);
200
new_dev->ImagingBBox[0] = bbox.p.x;
201
new_dev->ImagingBBox[1] = bbox.p.y;
202
new_dev->ImagingBBox[2] = bbox.q.x;
203
new_dev->ImagingBBox[3] = bbox.q.y;
204
new_dev->ImagingBBox_set = true;
206
/* The bitmap will be allocated when the device is opened. */
207
new_dev->is_open = false;
208
new_dev->bitmap_memory = mem;
213
gs_makewordimagedevice(gx_device ** pnew_dev, const gs_matrix * pmat,
214
uint width, uint height, const byte * colors, int num_colors,
215
bool word_oriented, bool page_device, gs_memory_t * mem)
218
gx_device_memory *pnew =
219
gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
220
"gs_makeimagedevice(device)");
223
return_error(gs_error_VMerror);
224
code = gs_initialize_wordimagedevice(pnew, pmat, width, height,
225
colors, num_colors, word_oriented,
228
gs_free_object(mem, pnew, "gs_makeimagedevice(device)");
231
*pnew_dev = (gx_device *) pnew;