1 /* Copyright (C) 1995, 1999 Aladdin Enterprises. All rights reserved. 2 3 This file is part of AFPL Ghostscript. 4 5 AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or 6 distributor accepts any responsibility for the consequences of using it, or 7 for whether it serves any particular purpose or works at all, unless he or 8 she says so in writing. Refer to the Aladdin Free Public License (the 9 "License") for full details. 10 11 Every copy of AFPL Ghostscript must include a copy of the License, normally 12 in a plain ASCII text file named PUBLIC. The License grants you the right 13 to copy, modify and redistribute AFPL Ghostscript, but only under certain 14 conditions described in the License. Among other things, the License 15 requires that the copyright notice and this notice be preserved on all 16 copies. 17 */ 18 19 /*$Id: gsdevmem.c,v 1.2 2000/09/19 19:00:27 lpd Exp $ */ 20 /* Memory device creation for Ghostscript library */ 21 #include "math_.h" /* for fabs */ 22 #include "memory_.h" 23 #include "gx.h" 24 #include "gserrors.h" 25 #include "gsdevice.h" /* for prototypes */ 26 #include "gxarith.h" 27 #include "gxdevice.h" 28 #include "gxdevmem.h" 29 30 /* Make a memory (image) device. */ 31 /* If colors_size = -16, -24, or -32, this is a true-color device; */ 32 /* otherwise, colors_size is the size of the palette in bytes */ 33 /* (2^N for gray scale, 3*2^N for RGB color). */ 34 /* We separate device allocation and initialization at customer request. */ 35 int 36 gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat, 37 uint width, uint height, const byte * colors, int colors_size, 38 bool word_oriented, bool page_device, gs_memory_t * mem) 39 { 40 const gx_device_memory *proto_dev; 41 int palette_count = colors_size; 42 int num_components = 1; 43 int pcount; 44 int bits_per_pixel; 45 float x_pixels_per_unit, y_pixels_per_unit; 46 byte palette[256 * 3]; 47 bool has_color; 48 49 switch (colors_size) { 50 case 3 * 2: 51 palette_count = 2; 52 num_components = 3; 53 case 2: 54 bits_per_pixel = 1; 55 break; 56 case 3 * 4: 57 palette_count = 4; 58 num_components = 3; 59 case 4: 60 bits_per_pixel = 2; 61 break; 62 case 3 * 16: 63 palette_count = 16; 64 num_components = 3; 65 case 16: 66 bits_per_pixel = 4; 67 break; 68 case 3 * 256: 69 palette_count = 256; 70 num_components = 3; 71 case 256: 72 bits_per_pixel = 8; 73 break; 74 case -16: 75 bits_per_pixel = 16; 76 palette_count = 0; 77 break; 78 case -24: 79 bits_per_pixel = 24; 80 palette_count = 0; 81 break; 82 case -32: 83 bits_per_pixel = 32; 84 palette_count = 0; 85 break; 86 default: 87 return_error(gs_error_rangecheck); 88 } 89 proto_dev = (word_oriented ? 90 gdev_mem_word_device_for_bits(bits_per_pixel) : 91 gdev_mem_device_for_bits(bits_per_pixel)); 92 if (proto_dev == 0) /* no suitable device */ 93 return_error(gs_error_rangecheck); 94 pcount = palette_count * 3; 95 /* Check to make sure the palette contains white and black, */ 96 /* and, if it has any colors, the six primaries. */ 97 if (bits_per_pixel <= 8) { 98 const byte *p; 99 byte *q; 100 int primary_mask = 0; 101 int i; 102 103 has_color = false; 104 for (i = 0, p = colors, q = palette; 105 i < palette_count; i++, q += 3 106 ) { 107 int mask = 1; 108 109 switch (num_components) { 110 case 1: /* gray */ 111 q[0] = q[1] = q[2] = *p++; 112 break; 113 default /* case 3 */ : /* RGB */ 114 q[0] = p[0], q[1] = p[1], q[2] = p[2]; 115 p += 3; 116 } 117 #define shift_mask(b,n)\ 118 switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; } 119 shift_mask(q[0], 4); 120 shift_mask(q[1], 2); 121 shift_mask(q[2], 1); 122 #undef shift_mask 123 primary_mask |= mask; 124 if (q[0] != q[1] || q[0] != q[2]) 125 has_color = true; 126 } 127 switch (primary_mask) { 128 case 129: /* just black and white */ 129 if (has_color) /* color but no primaries */ 130 return_error(gs_error_rangecheck); 131 case 255: /* full color */ 132 break; 133 default: 134 return_error(gs_error_rangecheck); 135 } 136 } else 137 has_color = true; 138 /* 139 * The initial transformation matrix must map 1 user unit to 140 * 1/72". Let W and H be the width and height in pixels, and 141 * assume the initial matrix is of the form [A 0 0 B X Y]. 142 * Then the size of the image in user units is (W/|A|,H/|B|), 143 * hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so 144 * the number of pixels per inch is 145 * (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72). 146 * Similarly, if the initial matrix is [0 A B 0 X Y] for a 90 147 * or 270 degree rotation, the size of the image in user 148 * units is (W/|B|,H/|A|), so the pixels per inch are 149 * (|B|*72,|A|*72). We forbid non-orthogonal transformation 150 * matrices. 151 */ 152 if (is_fzero2(pmat->xy, pmat->yx)) 153 x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy; 154 else if (is_fzero2(pmat->xx, pmat->yy)) 155 x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy; 156 else 157 return_error(gs_error_undefinedresult); 158 /* All checks done, initialize the device. */ 159 if (bits_per_pixel == 1) { 160 /* Determine the polarity from the palette. */ 161 gs_make_mem_device(new_dev, proto_dev, mem, 162 (page_device ? 1 : -1), 0); 163 /* This is somewhat bogus, but does the right thing */ 164 /* in the only cases we care about. */ 165 gdev_mem_mono_set_inverted(new_dev, 166 (palette[0] | palette[1] | palette[2]) != 0); 167 } else { 168 byte *dev_palette = gs_alloc_string(mem, pcount, 169 "gs_makeimagedevice(palette)"); 170 171 if (dev_palette == 0) 172 return_error(gs_error_VMerror); 173 gs_make_mem_device(new_dev, proto_dev, mem, 174 (page_device ? 1 : -1), 0); 175 new_dev->palette.size = pcount; 176 new_dev->palette.data = dev_palette; 177 memcpy(dev_palette, palette, pcount); 178 if (!has_color) { 179 new_dev->color_info.num_components = 1; 180 new_dev->color_info.max_color = 0; 181 new_dev->color_info.dither_colors = 0; 182 } 183 } 184 new_dev->initial_matrix = *pmat; 185 new_dev->MarginsHWResolution[0] = new_dev->HWResolution[0] = 186 fabs(x_pixels_per_unit) * 72; 187 new_dev->MarginsHWResolution[1] = new_dev->HWResolution[1] = 188 fabs(y_pixels_per_unit) * 72; 189 gx_device_set_width_height((gx_device *) new_dev, width, height); 190 /* Set the ImagingBBox so we get a correct clipping region. */ 191 { 192 gs_rect bbox; 193 194 bbox.p.x = 0; 195 bbox.p.y = 0; 196 bbox.q.x = width; 197 bbox.q.y = height; 198 gs_bbox_transform_inverse(&bbox, pmat, &bbox); 199 new_dev->ImagingBBox[0] = bbox.p.x; 200 new_dev->ImagingBBox[1] = bbox.p.y; 201 new_dev->ImagingBBox[2] = bbox.q.x; 202 new_dev->ImagingBBox[3] = bbox.q.y; 203 new_dev->ImagingBBox_set = true; 204 } 205 /* The bitmap will be allocated when the device is opened. */ 206 new_dev->is_open = false; 207 new_dev->bitmap_memory = mem; 208 return 0; 209 } 210 211 int 212 gs_makewordimagedevice(gx_device ** pnew_dev, const gs_matrix * pmat, 213 uint width, uint height, const byte * colors, int num_colors, 214 bool word_oriented, bool page_device, gs_memory_t * mem) 215 { 216 int code; 217 gx_device_memory *pnew = 218 gs_alloc_struct(mem, gx_device_memory, &st_device_memory, 219 "gs_makeimagedevice(device)"); 220 221 if (pnew == 0) 222 return_error(gs_error_VMerror); 223 code = gs_initialize_wordimagedevice(pnew, pmat, width, height, 224 colors, num_colors, word_oriented, 225 page_device, mem); 226 if (code < 0) { 227 gs_free_object(mem, pnew, "gs_makeimagedevice(device)"); 228 return code; 229 } 230 *pnew_dev = (gx_device *) pnew; 231 return 0; 232 } 233