Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

src/main/sequence.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: sequence.c,v 1.18 2004/08/03 17:57:52 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 #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; /* Do we need to recompute the min and max? */
00045   double blo;          /* Lower bound */
00046   double bhi;          /* Upper bound */
00047   double rlo;          /* Lower range limit */
00048   double rhi;          /* Upper range limit */
00049   size_t size;         /* Number of points */
00050   double *data;        /* Array of doubles */
00051   float *float_data;   /* Data converted to other form */
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  * We could do more sanity checks here if we want.
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  * Find the minimum and maximum points on the curve.
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; /* Don't recompute unless the data changes */
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) /* Don't recompute the range if we don't
00194                                need to. */
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) /* Free old data */
00206     {
00207       stp_free(sequence->data);
00208       sequence->data = NULL;
00209     }
00210   sequence->size = size;
00211   sequence->recompute_range = 1; /* Always recompute on change */
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) /* Exceeds data 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   /* Get curve point count */
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   /* Get lower bound */
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   /* Get upper bound */
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   /* Now read in the data points */
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               /* Datum was valid, so now add to the sequence */
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)   /* The sequence */
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;                 /* loop counter */
00424 
00425   pointcount = stp_sequence_get_size(seq);
00426   stp_sequence_get_bounds(seq, &low, &high);
00427 
00428   /* should count be of greater precision? */
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   /* Write the curve points into the node content */
00443   if (pointcount) /* Is there any data to write? */
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 /* "Overloaded" functions */
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   /* Validate the data before we commit to it. */                            \
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 /* ISO constant, from <math.h> */
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)

Generated on Wed Aug 25 07:56:15 2004 for libgimpprint API Reference by doxygen 1.3.6