1/* 2 * "$Id: array.c,v 1.17 2010/08/04 00:33:55 rlk Exp $" 3 * 4 * Array data type. This type is designed to be derived from by 5 * the curve and dither matrix types. 6 * 7 * Copyright 2002-2003 Robert Krawitz (rlk@alum.mit.edu) 8 * Copyright 2003 Roger Leigh (rleigh@debian.org) 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 * for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include <config.h> 27#endif 28#include <gutenprint/gutenprint.h> 29#include "gutenprint-internal.h" 30#include <gutenprint/gutenprint-intl-internal.h> 31#include <math.h> 32#include <string.h> 33#include <stdlib.h> 34#include <limits.h> 35 36 37struct stp_array 38{ 39 stp_sequence_t *data; /* First member, to allow typecasting to sequence. */ 40 int x_size; 41 int y_size; 42}; 43 44/* 45 * We could do more sanity checks here if we want. 46 */ 47#define CHECK_ARRAY(array) STPI_ASSERT(array != NULL, NULL) 48 49static void array_ctor(stp_array_t *array) 50{ 51 array->data = stp_sequence_create(); 52 stp_sequence_set_size(array->data, array->x_size * array->y_size); 53} 54 55stp_array_t * 56stp_array_create(int x_size, int y_size) 57{ 58 stp_array_t *ret; 59 ret = stp_zalloc(sizeof(stp_array_t)); 60 ret->x_size = x_size; 61 ret->y_size = y_size; 62 ret->data = NULL; 63 array_ctor(ret); 64 return ret; 65} 66 67 68static void 69array_dtor(stp_array_t *array) 70{ 71 if (array->data) 72 stp_sequence_destroy(array->data); 73 memset(array, 0, sizeof(stp_array_t)); 74} 75 76void 77stp_array_destroy(stp_array_t *array) 78{ 79 CHECK_ARRAY(array); 80 array_dtor(array); 81 stp_free(array); 82} 83 84void 85stp_array_copy(stp_array_t *dest, const stp_array_t *source) 86{ 87 CHECK_ARRAY(dest); 88 CHECK_ARRAY(source); 89 90 dest->x_size = source->x_size; 91 dest->y_size = source->y_size; 92 if (dest->data) 93 stp_sequence_destroy(dest->data); 94 dest->data = stp_sequence_create_copy(source->data); 95} 96 97stp_array_t * 98stp_array_create_copy(const stp_array_t *array) 99{ 100 stp_array_t *ret; 101 CHECK_ARRAY(array); 102 ret = stp_array_create(0, 0); /* gets freed next */ 103 stp_array_copy(ret, array); 104 return ret; 105} 106 107 108void 109stp_array_set_size(stp_array_t *array, int x_size, int y_size) 110{ 111 CHECK_ARRAY(array); 112 if (array->data) /* Free old data */ 113 stp_sequence_destroy(array->data); 114 array->x_size = x_size; 115 array->y_size = y_size; 116 array->data = stp_sequence_create(); 117 stp_sequence_set_size(array->data, array->x_size * array->y_size); 118} 119 120void 121stp_array_get_size(const stp_array_t *array, int *x_size, int *y_size) 122{ 123 CHECK_ARRAY(array); 124 *x_size = array->x_size; 125 *y_size = array->y_size; 126 return; 127} 128 129void 130stp_array_set_data(stp_array_t *array, const double *data) 131{ 132 CHECK_ARRAY(array); 133 stp_sequence_set_data(array->data, array->x_size * array->y_size, 134 data); 135} 136 137void 138stp_array_get_data(const stp_array_t *array, size_t *size, const double **data) 139{ 140 CHECK_ARRAY(array); 141 stp_sequence_get_data(array->data, size, data); 142} 143 144int 145stp_array_set_point(stp_array_t *array, int x, int y, double data) 146{ 147 CHECK_ARRAY(array); 148 149 if (((array->x_size * x) + y) >= (array->x_size * array->y_size)) 150 return 0; 151 152 return stp_sequence_set_point(array->data, (array->x_size * x) + y, data);} 153 154int 155stp_array_get_point(const stp_array_t *array, int x, int y, double *data) 156{ 157 CHECK_ARRAY(array); 158 159 if (((array->x_size * x) + y) >= array->x_size * array->y_size) 160 return 0; 161 return stp_sequence_get_point(array->data, 162 (array->x_size * x) + y, data); 163} 164 165const stp_sequence_t * 166stp_array_get_sequence(const stp_array_t *array) 167{ 168 CHECK_ARRAY(array); 169 170 return array->data; 171} 172 173stp_array_t * 174stp_array_create_from_xmltree(stp_mxml_node_t *array) /* The array node */ 175{ 176 const char *stmp; /* Temporary string */ 177 stp_mxml_node_t *child; /* Child sequence node */ 178 int x_size, y_size; 179 size_t count; 180 stp_sequence_t *seq = NULL; 181 stp_array_t *ret = NULL; 182 183 stmp = stp_mxmlElementGetAttr(array, "x-size"); 184 if (stmp) 185 { 186 x_size = (int) strtoul(stmp, NULL, 0); 187 } 188 else 189 { 190 stp_erprintf("stp_array_create_from_xmltree: \"x-size\" missing\n"); 191 goto error; 192 } 193 /* Get y-size */ 194 stmp = stp_mxmlElementGetAttr(array, "y-size"); 195 if (stmp) 196 { 197 y_size = (int) strtoul(stmp, NULL, 0); 198 } 199 else 200 { 201 stp_erprintf("stp_array_create_from_xmltree: \"y-size\" missing\n"); 202 goto error; 203 } 204 205 /* Get the sequence data */ 206 207 child = stp_mxmlFindElement(array, array, "sequence", NULL, NULL, STP_MXML_DESCEND); 208 if (child) 209 seq = stp_sequence_create_from_xmltree(child); 210 211 if (seq == NULL) 212 goto error; 213 214 ret = stp_array_create(x_size, y_size); 215 if (ret->data) 216 stp_sequence_destroy(ret->data); 217 ret->data = seq; 218 219 count = stp_sequence_get_size(seq); 220 if (count != (x_size * y_size)) 221 { 222 stp_erprintf("stp_array_create_from_xmltree: size mismatch between array and sequence\n"); 223 goto error; 224 } 225 226 return ret; 227 228 error: 229 stp_erprintf("stp_array_create_from_xmltree: error during array read\n"); 230 if (ret) 231 stp_array_destroy(ret); 232 return NULL; 233} 234 235stp_mxml_node_t * 236stp_xmltree_create_from_array(const stp_array_t *array) /* The array */ 237{ 238 int x_size, y_size; 239 char *xs, *ys; 240 241 stp_mxml_node_t *arraynode = NULL; 242 stp_mxml_node_t *child = NULL; 243 244 stp_xml_init(); 245 246 /* Get array details */ 247 stp_array_get_size(array, &x_size, &y_size); 248 249 /* Construct the allocated strings required */ 250 stp_asprintf(&xs, "%d", x_size); 251 stp_asprintf(&ys, "%d", y_size); 252 253 arraynode = stp_mxmlNewElement(NULL, "array"); 254 stp_mxmlElementSetAttr(arraynode, "x-size", xs); 255 stp_mxmlElementSetAttr(arraynode, "y-size", ys); 256 stp_free(xs); 257 stp_free(ys); 258 259 child = stp_xmltree_create_from_sequence(stp_array_get_sequence(array)); 260 261 if (child) 262 stp_mxmlAdd(arraynode, STP_MXML_ADD_AFTER, NULL, child); 263 else 264 { 265 stp_mxmlDelete(arraynode); 266 arraynode = NULL; 267 } 268 269 stp_xml_exit(); 270 271 return arraynode; 272} 273