00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 #include <gimp-print/gimp-print.h>
00029 #include <gimp-print/sequence.h>
00030 #include "gimp-print-internal.h"
00031 #include <gimp-print/gimp-print-intl-internal.h>
00032 #include <math.h>
00033 #ifdef sun
00034 #include <ieeefp.h>
00035 #endif
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <limits.h>
00039 #include <errno.h>
00040 #include <ctype.h>
00041
00042 struct stp_sequence
00043 {
00044 int recompute_range;
00045 double blo;
00046 double bhi;
00047 double rlo;
00048 double rhi;
00049 size_t size;
00050 double *data;
00051 float *float_data;
00052 long *long_data;
00053 unsigned long *ulong_data;
00054 int *int_data;
00055 unsigned *uint_data;
00056 short *short_data;
00057 unsigned short *ushort_data;
00058 };
00059
00060
00061
00062
00063 static inline void
00064 check_sequence(const stp_sequence_t *v)
00065 {
00066 if (v == NULL)
00067 {
00068 stp_erprintf("Null stp_sequence_t! Please report this bug.\n");
00069 stp_abort();
00070 }
00071 }
00072
00073 static void
00074 sequence_ctor(stp_sequence_t *sequence)
00075 {
00076 sequence->rlo = sequence->blo = 0.0;
00077 sequence->rhi = sequence->bhi = 1.0;
00078 sequence->recompute_range = 1;
00079 sequence->size = 0;
00080 sequence->data = NULL;
00081 }
00082
00083 stp_sequence_t *
00084 stp_sequence_create(void)
00085 {
00086 stp_sequence_t *ret;
00087 ret = stp_zalloc(sizeof(stp_sequence_t));
00088 sequence_ctor(ret);
00089 return ret;
00090 }
00091
00092 static void
00093 invalidate_auxilliary_data(stp_sequence_t *sequence)
00094 {
00095 STP_SAFE_FREE(sequence->float_data);
00096 STP_SAFE_FREE(sequence->long_data);
00097 STP_SAFE_FREE(sequence->ulong_data);
00098 STP_SAFE_FREE(sequence->int_data);
00099 STP_SAFE_FREE(sequence->uint_data);
00100 STP_SAFE_FREE(sequence->short_data);
00101 STP_SAFE_FREE(sequence->ushort_data);
00102 }
00103
00104 static void
00105 sequence_dtor(stp_sequence_t *sequence)
00106 {
00107 invalidate_auxilliary_data(sequence);
00108 if (sequence->data)
00109 stp_free(sequence->data);
00110 memset(sequence, 0, sizeof(stp_sequence_t));
00111 }
00112
00113 void
00114 stp_sequence_destroy(stp_sequence_t *sequence)
00115 {
00116 check_sequence(sequence);
00117 sequence_dtor(sequence);
00118 stp_free(sequence);
00119 }
00120
00121 void
00122 stp_sequence_copy(stp_sequence_t *dest, const stp_sequence_t *source)
00123 {
00124 check_sequence(dest);
00125 check_sequence(source);
00126
00127 dest->recompute_range = source->recompute_range;
00128 dest->blo = source->blo;
00129 dest->bhi = source->bhi;
00130 dest->rlo = source->rlo;
00131 dest->rhi = source->rhi;
00132 dest->size = source->size;
00133 dest->data = stp_zalloc(sizeof(double) * source->size);
00134 memcpy(dest->data, source->data, (sizeof(double) * source->size));
00135 }
00136
00137 stp_sequence_t *
00138 stp_sequence_create_copy(const stp_sequence_t *sequence)
00139 {
00140 stp_sequence_t *ret;
00141 check_sequence(sequence);
00142 ret = stp_sequence_create();
00143 stp_sequence_copy(ret, sequence);
00144 return ret;
00145 }
00146
00147 int
00148 stp_sequence_set_bounds(stp_sequence_t *sequence, double low, double high)
00149 {
00150 check_sequence(sequence);
00151 if (low > high)
00152 return 0;
00153 sequence->rlo = sequence->blo = low;
00154 sequence->rhi = sequence->bhi = high;
00155 sequence->recompute_range = 1;
00156 return 1;
00157 }
00158
00159 void
00160 stp_sequence_get_bounds(const stp_sequence_t *sequence,
00161 double *low, double *high)
00162 {
00163 check_sequence(sequence);
00164 *low = sequence->blo;
00165 *high = sequence->bhi;
00166 }
00167
00168
00169
00170
00171
00172 static void
00173 scan_sequence_range(stp_sequence_t *sequence)
00174 {
00175 int i;
00176 sequence->rlo = sequence->bhi;
00177 sequence->rhi = sequence->blo;
00178 if (sequence->size)
00179 for (i = 0; i < sequence->size; i++)
00180 {
00181 if (sequence->data[i] < sequence->rlo)
00182 sequence->rlo = sequence->data[i];
00183 if (sequence->data[i] > sequence->rhi)
00184 sequence->rhi = sequence->data[i];
00185 }
00186 sequence->recompute_range = 0;
00187 }
00188
00189 void
00190 stp_sequence_get_range(const stp_sequence_t *sequence,
00191 double *low, double *high)
00192 {
00193 if (sequence->recompute_range)
00194
00195 scan_sequence_range((stp_sequence_t *) sequence);
00196 *low = sequence->rlo;
00197 *high = sequence->rhi;
00198 }
00199
00200
00201 int
00202 stp_sequence_set_size(stp_sequence_t *sequence, size_t size)
00203 {
00204 check_sequence(sequence);
00205 if (sequence->data)
00206 {
00207 stp_free(sequence->data);
00208 sequence->data = NULL;
00209 }
00210 sequence->size = size;
00211 sequence->recompute_range = 1;
00212 if (size == 0)
00213 return 1;
00214 invalidate_auxilliary_data(sequence);
00215 sequence->data = stp_zalloc(sizeof(double) * size);
00216 return 1;
00217 }
00218
00219
00220 size_t
00221 stp_sequence_get_size(const stp_sequence_t *sequence)
00222 {
00223 check_sequence(sequence);
00224 return sequence->size;
00225 }
00226
00227
00228
00229 int
00230 stp_sequence_set_data(stp_sequence_t *sequence,
00231 size_t size, const double *data)
00232 {
00233 check_sequence(sequence);
00234 sequence->size = size;
00235 if (sequence->data)
00236 stp_free(sequence->data);
00237 sequence->data = stp_zalloc(sizeof(double) * size);
00238 memcpy(sequence->data, data, (sizeof(double) * size));
00239 invalidate_auxilliary_data(sequence);
00240 sequence->recompute_range = 1;
00241 return 1;
00242 }
00243
00244 int
00245 stp_sequence_set_subrange(stp_sequence_t *sequence, size_t where,
00246 size_t size, const double *data)
00247 {
00248 check_sequence(sequence);
00249 if (where + size > sequence->size)
00250 return 0;
00251 memcpy(sequence->data+where, data, (sizeof(double) * size));
00252 invalidate_auxilliary_data(sequence);
00253 sequence->recompute_range = 1;
00254 return 1;
00255 }
00256
00257
00258 void
00259 stp_sequence_get_data(const stp_sequence_t *sequence, size_t *size,
00260 const double **data)
00261 {
00262 check_sequence(sequence);
00263 *size = sequence->size;
00264 *data = sequence->data;
00265 }
00266
00267
00268 int
00269 stp_sequence_set_point(stp_sequence_t *sequence, size_t where,
00270 double data)
00271 {
00272 check_sequence(sequence);
00273
00274 if (where >= sequence->size || ! finite(data) ||
00275 data < sequence->blo || data > sequence->bhi)
00276 return 0;
00277
00278 if (sequence->recompute_range == 0 && (data < sequence->rlo ||
00279 data > sequence->rhi ||
00280 sequence->data[where] == sequence->rhi ||
00281 sequence->data[where] == sequence->rlo))
00282 sequence->recompute_range = 1;
00283
00284 sequence->data[where] = data;
00285 invalidate_auxilliary_data(sequence);
00286 return 1;
00287 }
00288
00289 int
00290 stp_sequence_get_point(const stp_sequence_t *sequence, size_t where,
00291 double *data)
00292 {
00293 check_sequence(sequence);
00294
00295 if (where >= sequence->size)
00296 return 0;
00297 *data = sequence->data[where];
00298 return 1;
00299 }
00300
00301 stp_sequence_t *
00302 stp_sequence_create_from_xmltree(stp_mxml_node_t *da)
00303 {
00304 const char *stmp;
00305 stp_sequence_t *ret = NULL;
00306 size_t point_count;
00307 double low, high;
00308 int i;
00309
00310 ret = stp_sequence_create();
00311
00312
00313 stmp = stp_mxmlElementGetAttr(da, "count");
00314 if (stmp)
00315 {
00316 point_count = (size_t) stp_xmlstrtoul(stmp);
00317 if ((stp_xmlstrtol(stmp)) < 0)
00318 {
00319 stp_erprintf("stp_sequence_create_from_xmltree: \"count\" is less than zero\n");
00320 goto error;
00321 }
00322 }
00323 else
00324 {
00325 stp_erprintf("stp_sequence_create_from_xmltree: \"count\" missing\n");
00326 goto error;
00327 }
00328
00329 stmp = stp_mxmlElementGetAttr(da, "lower-bound");
00330 if (stmp)
00331 {
00332 low = stp_xmlstrtod(stmp);
00333 }
00334 else
00335 {
00336 stp_erprintf("stp_sequence_create_from_xmltree: \"lower-bound\" missing\n");
00337 goto error;
00338 }
00339
00340 stmp = stp_mxmlElementGetAttr(da, "upper-bound");
00341 if (stmp)
00342 {
00343 high = stp_xmlstrtod(stmp);
00344 }
00345 else
00346 {
00347 stp_erprintf("stp_sequence_create_from_xmltree: \"upper-bound\" missing\n");
00348 goto error;
00349 }
00350
00351 stp_deprintf(STP_DBG_XML,
00352 "stp_sequence_create_from_xmltree: stp_sequence_set_size: %d\n",
00353 point_count);
00354 stp_sequence_set_size(ret, point_count);
00355 stp_sequence_set_bounds(ret, low, high);
00356
00357
00358 if (point_count)
00359 {
00360 stp_mxml_node_t *child = da->child;
00361 i = 0;
00362 while (child && i < point_count)
00363 {
00364 if (child->type == STP_MXML_TEXT)
00365 {
00366 char *endptr;
00367 double tmpval = strtod(child->value.text.string, &endptr);
00368 if (endptr == child->value.text.string)
00369 {
00370 stp_erprintf
00371 ("stp_sequence_create_from_xmltree: bad data %s\n",
00372 child->value.text.string);
00373 goto error;
00374 }
00375 if (! finite(tmpval)
00376 || ( tmpval == 0 && errno == ERANGE )
00377 || tmpval < low
00378 || tmpval > high)
00379 {
00380 stp_erprintf("stp_sequence_create_from_xmltree: "
00381 "read aborted: datum out of bounds: "
00382 "%g (require %g <= x <= %g), n = %d\n",
00383 tmpval, low, high, i);
00384 goto error;
00385 }
00386
00387 stp_sequence_set_point(ret, i, tmpval);
00388 i++;
00389 child = child->next;
00390 }
00391 }
00392 if (i < point_count)
00393 {
00394 stp_erprintf("stp_sequence_create_from_xmltree: "
00395 "read aborted: too little data "
00396 "(n=%d, needed %d)\n", i, point_count);
00397 goto error;
00398 }
00399 }
00400
00401 return ret;
00402
00403 error:
00404 stp_erprintf("stp_sequence_create_from_xmltree: error during sequence read\n");
00405 if (ret)
00406 stp_sequence_destroy(ret);
00407 return NULL;
00408 }
00409
00410 stp_mxml_node_t *
00411 stp_xmltree_create_from_sequence(const stp_sequence_t *seq)
00412 {
00413 size_t pointcount;
00414 double low;
00415 double high;
00416
00417 char *count;
00418 char *lower_bound;
00419 char *upper_bound;
00420
00421 stp_mxml_node_t *seqnode;
00422
00423 int i;
00424
00425 pointcount = stp_sequence_get_size(seq);
00426 stp_sequence_get_bounds(seq, &low, &high);
00427
00428
00429 stp_asprintf(&count, "%lu", (unsigned long) pointcount);
00430 stp_asprintf(&lower_bound, "%g", low);
00431 stp_asprintf(&upper_bound, "%g", high);
00432
00433 seqnode = stp_mxmlNewElement(NULL, "sequence");
00434 (void) stp_mxmlElementSetAttr(seqnode, "count", count);
00435 (void) stp_mxmlElementSetAttr(seqnode, "lower-bound", lower_bound);
00436 (void) stp_mxmlElementSetAttr(seqnode, "upper-bound", upper_bound);
00437
00438 stp_free(count);
00439 stp_free(lower_bound);
00440 stp_free(upper_bound);
00441
00442
00443 if (pointcount)
00444 {
00445 for (i = 0; i < pointcount; i++)
00446 {
00447 double dval;
00448 char *sval;
00449
00450 if ((stp_sequence_get_point(seq, i, &dval)) != 1)
00451 goto error;
00452
00453 stp_asprintf(&sval, "%g", dval);
00454 stp_mxmlNewText(seqnode, 1, sval);
00455 stp_free(sval);
00456 }
00457 }
00458 return seqnode;
00459
00460 error:
00461 if (seqnode)
00462 stp_mxmlDelete(seqnode);
00463 return NULL;
00464 }
00465
00466
00467
00468
00469 #define DEFINE_DATA_SETTER(t, name) \
00470 int \
00471 stp_sequence_set_##name##_data(stp_sequence_t *sequence, \
00472 size_t count, const t *data) \
00473 { \
00474 int i; \
00475 check_sequence(sequence); \
00476 if (count < 2) \
00477 return 0; \
00478 \
00479 \
00480 for (i = 0; i < count; i++) \
00481 if (! finite(data[i]) || \
00482 data[i] < sequence->blo || \
00483 data[i] > sequence->bhi) \
00484 return 0; \
00485 stp_sequence_set_size(sequence, count); \
00486 for (i = 0; i < count; i++) \
00487 stp_sequence_set_point(sequence, i, (double) data[i]); \
00488 return 1; \
00489 }
00490
00491 DEFINE_DATA_SETTER(float, float)
00492 DEFINE_DATA_SETTER(long, long)
00493 DEFINE_DATA_SETTER(unsigned long, ulong)
00494 DEFINE_DATA_SETTER(int, int)
00495 DEFINE_DATA_SETTER(unsigned int, uint)
00496 DEFINE_DATA_SETTER(short, short)
00497 DEFINE_DATA_SETTER(unsigned short, ushort)
00498
00499
00500 #define DEFINE_DATA_ACCESSOR(t, lb, ub, name) \
00501 const t * \
00502 stp_sequence_get_##name##_data(const stp_sequence_t *sequence, size_t *count) \
00503 { \
00504 int i; \
00505 if (sequence->blo < (double) lb || sequence->bhi > (double) ub) \
00506 return NULL; \
00507 if (!sequence->name##_data) \
00508 { \
00509 ((stp_sequence_t *)sequence)->name##_data = stp_zalloc(sizeof(t) * sequence->size); \
00510 for (i = 0; i < sequence->size; i++) \
00511 ((stp_sequence_t *)sequence)->name##_data[i] = (t) sequence->data[i]; \
00512 } \
00513 *count = sequence->size; \
00514 return sequence->name##_data; \
00515 }
00516
00517 #ifndef HUGE_VALF
00518 #define HUGE_VALF 3.402823466E+38F
00519 #endif
00520
00521 DEFINE_DATA_ACCESSOR(float, -HUGE_VALF, HUGE_VALF, float)
00522 DEFINE_DATA_ACCESSOR(long, LONG_MIN, LONG_MAX, long)
00523 DEFINE_DATA_ACCESSOR(unsigned long, 0, ULONG_MAX, ulong)
00524 DEFINE_DATA_ACCESSOR(int, INT_MIN, INT_MAX, int)
00525 DEFINE_DATA_ACCESSOR(unsigned int, 0, UINT_MAX, uint)
00526 DEFINE_DATA_ACCESSOR(short, SHRT_MIN, SHRT_MAX, short)
00527 DEFINE_DATA_ACCESSOR(unsigned short, 0, USHRT_MAX, ushort)