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