Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/sequence.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: sequence.c,v 1.16 2004/05/07 19:20:34 rleigh Exp $"
00003  *
00004  *   Sequence data type.  This type is designed to be derived from by
00005  *   the curve and dither matrix types.
00006  *
00007  *   Copyright 2002-2003 Robert Krawitz (rlk@alum.mit.edu)
00008  *   Copyright 2003      Roger Leigh (rleigh@debian.org)
00009  *
00010  *   This program is free software; you can redistribute it and/or modify it
00011  *   under the terms of the GNU General Public License as published by the Free
00012  *   Software Foundation; either version 2 of the License, or (at your option)
00013  *   any later version.
00014  *
00015  *   This program is distributed in the hope that it will be useful, but
00016  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00017  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  *   for more details.
00019  *
00020  *   You should have received a copy of the GNU General Public License
00021  *   along with this program; if not, write to the Free Software
00022  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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; /* Do we need to recompute the min and max? */
00042   double blo;          /* Lower bound */
00043   double bhi;          /* Upper bound */
00044   double rlo;          /* Lower range limit */
00045   double rhi;          /* Upper range limit */
00046   size_t size;         /* Number of points */
00047   double *data;        /* Array of doubles */
00048   float *float_data;   /* Data converted to other form */
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  * We could do more sanity checks here if we want.
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  * Find the minimum and maximum points on the curve.
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; /* Don't recompute unless the data changes */
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) /* Don't recompute the range if we don't
00191                                need to. */
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) /* Free old data */
00203     {
00204       stp_free(sequence->data);
00205       sequence->data = NULL;
00206     }
00207   sequence->size = size;
00208   sequence->recompute_range = 1; /* Always recompute on change */
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) /* Exceeds data 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   /* Get curve point count */
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   /* Get lower bound */
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   /* Get upper bound */
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   /* Now read in the data points */
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               /* Datum was valid, so now add to the sequence */
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)   /* The sequence */
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;                 /* loop counter */
00421 
00422   pointcount = stp_sequence_get_size(seq);
00423   stp_sequence_get_bounds(seq, &low, &high);
00424 
00425   /* should count be of greater precision? */
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   /* Write the curve points into the node content */
00440   if (pointcount) /* Is there any data to write? */
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 /* "Overloaded" functions */
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   /* Validate the data before we commit to it. */                            \
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 /* ISO constant, from <math.h> */
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)

Generated on Wed May 12 20:21:33 2004 for libgimpprint API Reference by doxygen1.2.17