1/*
2 * "$Id: curve.c,v 1.23 2008/01/21 23:19:41 rlk Exp $"
3 *
4 *   Copyright 2002 Robert Krawitz (rlk@alum.mit.edu)
5 *
6 *   This program is free software; you can redistribute it and/or modify it
7 *   under the terms of the GNU General Public License as published by the Free
8 *   Software Foundation; either version 2 of the License, or (at your option)
9 *   any later version.
10 *
11 *   This program is distributed in the hope that it will be useful, but
12 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 *   for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with this program; if not, write to the Free Software
18 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <stdlib.h>
25#include <stdio.h>
26#include <unistd.h>
27#include <string.h>
28#ifdef __GNU_LIBRARY__
29#include <getopt.h>
30#endif
31
32#define DEBUG_SIGNAL
33#define MIN(x, y) ((x) <= (y) ? (x) : (y))
34#include <gutenprint/gutenprint.h>
35
36int global_test_count = 0;
37int global_error_count = 0;
38int verbose = 0;
39int quiet = 0;
40
41#ifdef __GNU_LIBRARY__
42
43struct option optlist[] =
44{
45  { "quiet",		0,	NULL,	(int) 'q' },
46  { "verbose",		0,	NULL,	(int) 'v' },
47  { NULL,		0,	NULL,	0 	  }
48};
49#endif
50
51struct test_failure
52{
53  int test_number;
54  struct test_failure *next;
55};
56
57static struct test_failure *test_failure_head = NULL;
58static struct test_failure *test_failure_tail = NULL;
59
60static void
61TEST_internal(const char *name, int line)
62{
63  global_test_count++;
64  printf("%d.%d: Checking %s... ", global_test_count, line, name);
65  fflush(stdout);
66}
67
68#define TEST(name) TEST_internal(name, __LINE__)
69
70static void
71TEST_PASS(void)
72{
73  printf("PASS\n");
74  fflush(stdout);
75}
76
77static void
78TEST_FAIL(void)
79{
80  struct test_failure *test_failure_tmp = malloc(sizeof(struct test_failure));
81  test_failure_tmp->next = NULL;
82  test_failure_tmp->test_number = global_test_count;
83
84  if (!test_failure_head)
85    {
86      test_failure_head = test_failure_tmp;
87      test_failure_tail = test_failure_head;
88    }
89  else
90    {
91      test_failure_tail->next = test_failure_tmp;
92      test_failure_tail = test_failure_tmp;
93    }
94
95  global_error_count++;
96  printf("FAIL\n");
97  fflush(stdout);
98}
99
100#define SIMPLE_TEST_CHECK(conditional)		\
101do {						\
102  if ((conditional))				\
103    TEST_PASS();				\
104  else						\
105    TEST_FAIL();				\
106} while (0)
107
108static const double standard_sat_adjustment[] =
109{
110  0.50, 0.6,  0.7,  0.8,  0.9,  0.86, 0.82, 0.79, /* C */
111  0.78, 0.8,  0.83, 0.87, 0.9,  0.95, 1.05, 1.15, /* B */
112  1.3,  1.25, 1.2,  1.15, 1.12, 1.09, 1.06, 1.03, /* M */
113  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0, /* R */
114  1.0,  0.9,  0.8,  0.7,  0.65, 0.6,  0.55, 0.52, /* Y */
115  0.48, 0.47, 0.47, 0.49, 0.49, 0.49, 0.52, 0.51, /* G */
116};
117
118static const double reverse_sat_adjustment[] =
119{
120  0.50, 0.51, 0.52, 0.49, 0.49, 0.49, 0.47, 0.47,
121  0.48, 0.52, 0.55, 0.6,  0.65, 0.7,  0.8,  0.9,
122  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,
123  1.0,  1.03, 1.06, 1.09, 1.12, 1.15, 1.2,  1.25,
124  1.3,  1.15, 1.05, 0.95, 0.9,  0.87, 0.83, 0.8,
125  0.78, 0.79, 0.82, 0.86, 0.9 , 0.8,  0.7,  0.6,
126};
127
128static const stp_curve_point_t standard_piecewise_sat_adjustment[] =
129{
130  { 0.00, 0.50},
131  { 0.02, 0.6},
132  { 0.04, 0.7},
133  { 0.06, 0.8},
134  { 0.08, 0.9},
135  { 0.10, 0.86},
136  { 0.12, 0.82},
137  { 0.14, 0.79},
138  { 0.16, 0.78},
139  { 0.18, 0.8},
140  { 0.20, 0.83},
141  { 0.22, 0.87},
142  { 0.24, 0.9},
143  { 0.26, 0.95},
144  { 0.28, 1.05},
145  { 0.30, 1.15},
146  { 0.32, 0.05},
147  { 0.34, 3.95},
148  { 0.36, 0.05},
149  { 0.38, 1.15},
150  { 0.40, 1.12},
151  { 0.42, 1.09},
152  { 0.44, 1.06},
153  { 0.46, 1.03},
154  { 0.48, 1.0},
155  { 0.50, 1.0},
156  { 0.52, 1.0},
157  { 0.54, 1.0},
158  { 0.56, 1.0},
159  { 0.58, 1.0},
160  { 0.60, 1.0},
161  { 0.62, 1.0},
162  { 0.64, 1.0},
163  { 0.66, 0.9},
164  { 0.68, 0.8},
165  { 0.70, 0.7},
166  { 0.72, 0.65},
167  { 0.74, 0.6},
168  { 0.76, 0.55},
169  { 0.78, 0.52},
170  { 0.80, 0.48},
171  { 0.82, 0.47},
172  { 0.84, 0.47},
173  { 0.86, 0.49},
174  { 0.88, 0.49},
175  { 0.90, 0.49},
176  { 0.93, 0.52},
177  { 0.96, 0.51},
178  { 1.00, 2},
179};
180
181static const stp_curve_point_t reverse_piecewise_sat_adjustment[] =
182{
183  { 0.00, 0.50},
184  { 0.02, 0.6},
185  { 0.04, 0.7},
186  { 0.06, 0.8},
187  { 0.08, 0.9},
188  { 0.10, 0.86},
189  { 0.12, 0.82},
190  { 0.14, 0.79},
191  { 0.16, 0.78},
192  { 0.18, 0.8},
193  { 0.20, 0.83},
194  { 0.22, 0.87},
195  { 0.24, 0.9},
196  { 0.26, 0.95},
197  { 0.28, 1.05},
198  { 0.30, 1.15},
199  { 0.32, 0.05},
200  { 0.34, 3.95},
201  { 0.36, 0.05},
202  { 0.38, 1.15},
203  { 0.40, 1.12},
204  { 0.42, 1.09},
205  { 0.44, 1.06},
206  { 0.46, 1.03},
207  { 0.48, 1.0},
208  { 0.50, 1.0},
209  { 0.52, 1.0},
210  { 0.54, 1.0},
211  { 0.56, 1.0},
212  { 0.58, 1.0},
213  { 0.60, 1.0},
214  { 0.62, 1.0},
215  { 0.64, 1.0},
216  { 0.66, 0.9},
217  { 0.68, 0.8},
218  { 0.70, 0.7},
219  { 0.72, 0.65},
220  { 0.74, 0.6},
221  { 0.76, 0.55},
222  { 0.78, 0.52},
223  { 0.80, 0.48},
224  { 0.82, 0.47},
225  { 0.84, 0.47},
226  { 0.86, 0.49},
227  { 0.88, 0.49},
228  { 0.90, 0.49},
229  { 0.93, 0.52},
230  { 0.96, 0.51},
231  { 1.00, 2},
232};
233
234const char *small_piecewise_curve =
235"<?xml version=\"1.0\"?>\n"
236"<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
237"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
238"xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
239"<curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
240"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"4\">\n"
241"0 0.5 0.1 0.6 1.00 0.51\n"
242"</sequence>\n"
243"</curve>\n"
244"</gutenprint>\n";
245
246const char *good_curves[] =
247  {
248    /* Space separated, in same layout as output for comparison */
249    "<?xml version=\"1.0\"?>\n"
250    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
251    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
252    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
253    "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
254    "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
255    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8 0.83 0.87 0.9 0.95 1.05 1.15\n"
256    "1.3 1.25 1.2 1.15 1.12 1.09 1.06 1.03 1 1 1 1 1 1 1 1 1 0.9 0.8 0.7 0.65\n"
257    "0.6 0.55 0.52 0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
258    "</sequence>\n"
259    "</curve>\n"
260    "</gutenprint>\n",
261
262    /* Space separated, in same layout as output for comparison */
263    "<?xml version=\"1.0\"?>\n"
264    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
265    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
266    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
267    "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
268    "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
269    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8 0.83 0.87 0.9 0.95 1.05 1.15\n"
270    "1.3 1.25 1.2 1.15 1.12 1.09 1.06 1.03 1 1 1 1 1 1 1 1 1 0.9 0.8 0.7 0.65\n"
271    "0.6 0.55 0.52 0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
272    "</sequence>\n"
273    "</curve>\n"
274    "</gutenprint>\n",
275
276    /* Space separated, in same layout as output for comparison */
277    "<?xml version=\"1.0\"?>\n"
278    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
279    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
280    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
281    "<curve wrap=\"wrap\" type=\"spline\" gamma=\"0\" piecewise=\"false\">\n"
282    "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
283    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8 0.83 0.87 0.9 0.95 1.05 1.15\n"
284    "1.3 1.25 1.2 1.15 1.12 1.09 1.06 1.03 1 1 1 1 1 1 1 1 1 0.9 0.8 0.7 0.65\n"
285    "0.6 0.55 0.52 0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
286    "</sequence>\n"
287    "</curve>\n"
288    "</gutenprint>\n",
289
290    /* Space separated, in same layout as output for comparison */
291    "<?xml version=\"1.0\"?>\n"
292    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
293    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
294    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
295    "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\" piecewise=\"false\">\n"
296    "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
297    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8 0.83 0.87 0.9 0.95 1.05 1.15\n"
298    "1.3 1.25 1.2 1.15 1.12 1.09 1.06 1.03 1 1 1 1 1 1 1 1 1 0.9 0.8 0.7 0.65\n"
299    "0.6 0.55 0.52 0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
300    "</sequence>\n"
301    "</curve>\n"
302    "</gutenprint>\n",
303
304    "<?xml version=\"1.0\"?>\n"
305    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
306    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
307    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
308    "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
309    "<sequence count=\"96\" lower-bound=\"0\" upper-bound=\"4\">\n"
310    "0 0.5 0.02 0.6 0.04 0.7 0.06 0.8 0.08 0.9 0.1 0.86 0.12 0.82 0.14 0.79 0.16\n"
311    "0.78 0.18 0.8 0.2 0.83 0.22 0.87 0.24 0.9 0.26 0.95 0.28 1.05 0.3 1.15 0.32\n"
312    "1.3 0.34 1.25 0.36 1.2 0.38 1.15 0.4 1.12 0.42 1.09 0.44 1.06 0.46 1.03\n"
313    "0.48 1 0.5 1 0.52 1 0.54 1 0.56 1 0.58 1 0.6 1 0.62 1 0.64 1 0.66 0.9 0.68\n"
314    "0.8 0.7 0.7 0.72 0.65 0.74 0.6 0.76 0.55 0.78 0.52 0.8 0.48 0.82 0.47 0.84\n"
315    "0.47 0.86 0.49 0.88 0.49 0.9 0.49 0.93 0.52 0.96 0.51\n"
316    "</sequence>\n"
317    "</curve>\n"
318    "</gutenprint>\n",
319
320    "<?xml version=\"1.0\"?>\n"
321    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
322    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
323    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
324    "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
325    "<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"4\">\n"
326    "0 0.5 0.02 0.6 0.96 0.51\n"
327    "</sequence>\n"
328    "</curve>\n"
329    "</gutenprint>\n",
330
331    /* Gamma curve 1 */
332    "<?xml version=\"1.0\"?>\n"
333    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
334    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
335    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
336    "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"1\" piecewise=\"false\">\n"
337    "<sequence count=\"0\" lower-bound=\"0\" upper-bound=\"4\"/>\n"
338    "</curve>\n"
339    "</gutenprint>\n",
340
341    /* Gamma curve 2 */
342    "<?xml version=\"1.0\"?>\n"
343    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
344    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
345    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
346    "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"1\" piecewise=\"false\">\n"
347    "<sequence count=\"0\" lower-bound=\"0\" upper-bound=\"4\"/>\n"
348    "</curve>\n"
349    "</gutenprint>\n"
350  };
351
352static const int good_curve_count = sizeof(good_curves) / sizeof(const char *);
353
354const char *bad_curves[] =
355  {
356    /* Bad point count */
357    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
358    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
359    "<sequence count=\"-1\" lower-bound=\"0\" upper-bound=\"4\">\n"
360    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8\n"
361    "0.83 0.87 0.9 0.95 1.05 1.15 1.3 1.25 1.2 1.15\n"
362    "1.12 1.09 1.06 1.03 1 1 1 1 1 1\n"
363    "1 1 1 0.9 0.8 0.7 0.65 0.6 0.55 0.52\n"
364    "0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
365    "</sequence></curve></gutenprint>\n",
366
367    /* Bad point count */
368    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
369    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
370    "<sequence count=\"200\" lower-bound=\"0\" upper-bound=\"4\">\n"
371    "0.5 0.6 0.7 0.8 0.9 0.86 0.82 0.79 0.78 0.8\n"
372    "0.83 0.87 0.9 0.95 1.05 1.15 1.3 1.25 1.2 1.15\n"
373    "1.12 1.09 1.06 1.03 1 1 1 1 1 1\n"
374    "1 1 1 0.9 0.8 0.7 0.65 0.6 0.55 0.52\n"
375    "0.48 0.47 0.47 0.49 0.49 0.49 0.52 0.51\n"
376    "</sequence></curve></gutenprint>\n",
377
378    "<?xml version=\"1.0\"?>\n"
379    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
380    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
381    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
382    "<curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
383    "<sequence count=\"5\" lower-bound=\"0\" upper-bound=\"4\">\n"
384    "0 0.5 0.02 0.6 0.96\n"
385    "</sequence>\n"
386    "</curve>\n"
387    "</gutenprint>\n",
388
389    "<?xml version=\"1.0\"?>\n"
390    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
391    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
392    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
393    "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
394    "<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"4\">\n"
395    "0 0.5 0.02 0.6 0.96 0.51\n"
396    "</sequence>\n"
397    "</curve>\n"
398    "</gutenprint>\n",
399
400    "<?xml version=\"1.0\"?>\n"
401    "<gutenprint xmlns=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0\"\n"
402    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
403    "xsi:schemaLocation=\"http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gutenprint.xsd\">\n"
404    "<curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"true\">\n"
405    "<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"4\">\n"
406    "0.01 0.5 0.02 0.6 1.0 0.51\n"
407    "</sequence>\n"
408    "</curve>\n"
409    "</gutenprint>\n",
410
411    /* Gamma curves */
412    /* Incorrect wrap mode */
413    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
414    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"1.0\" piecewise=\"false\">\n"
415    "<sequence count=\"-1\" lower-bound=\"0\" upper-bound=\"4\">\n"
416    "</sequence></curve></gutenprint>\n",
417
418    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
419    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"1.0\" piecewise=\"false\">\n"
420    "<sequence count=\"1\" lower-bound=\"0\" upper-bound=\"4\">\n"
421    "</sequence></curve></gutenprint>\n",
422
423    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
424    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"1.0\" piecewise=\"false\">\n"
425    "<sequence count=\"48\" lower-bound=\"0\" upper-bound=\"4\">\n"
426    "</sequence></curve></gutenprint>\n",
427
428    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
429    "<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"1.0\" piecewise=\"false\">\n"
430    "<sequence count=\"0\" lower-bound=\"0\" upper-bound=\"4\">\n"
431    "</sequence></curve></gutenprint>\n"
432  };
433
434static const int bad_curve_count = sizeof(bad_curves) / sizeof(const char *);
435
436const char *linear_curve_1 =
437"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
438"<gutenprint><curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
439"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
440"0 0 0 1 1 1"
441"</sequence></curve></gutenprint>";
442
443const char *linear_curve_2 =
444"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
445"<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
446"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
447"0 0 0 1 1 1"
448"</sequence></curve></gutenprint>";
449
450const char *linear_curve_3 =
451"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
452"<gutenprint><curve wrap=\"nowrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
453"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
454"0 0 0 1 1 1"
455"</sequence></curve></gutenprint>";
456
457const char *linear_curve_4 =
458"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
459"<gutenprint><curve wrap=\"wrap\" type=\"linear\" gamma=\"0\" piecewise=\"false\">\n"
460"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
461"0 0 0 1 1 1"
462"</sequence></curve></gutenprint>";
463
464const char *spline_curve_1 =
465"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
466"<gutenprint><curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\" piecewise=\"false\">\n"
467"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
468"0 0 0 1 1 1"
469"</sequence></curve></gutenprint>";
470
471const char *spline_curve_2 =
472"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
473"<gutenprint><curve wrap=\"wrap\" type=\"spline\" gamma=\"0\" piecewise=\"false\">\n"
474"<sequence count=\"6\" lower-bound=\"0\" upper-bound=\"1\">\n"
475"0 0 0 1 1 1"
476"</sequence></curve></gutenprint>";
477
478static void
479piecewise_curve_checks(stp_curve_t *curve1, int resample_points, int expected)
480{
481  stp_curve_t *curve2;
482  const stp_curve_point_t *curve_points;
483  size_t count;
484  int i;
485  double low;
486
487  TEST("get data points of piecewise curve");
488  curve_points = stp_curve_get_data_points(curve1, &count);
489  if (curve_points)
490    {
491      int bad_compare = 0;
492      TEST_PASS();
493      TEST("Checking count of curve points");
494      if (count == expected)
495	TEST_PASS();
496      else
497	{
498	  TEST_FAIL();
499	  if (!quiet)
500	    printf("Expected %d points, got %d\n", expected, count);
501	}
502      TEST("Comparing data");
503      for (i = 0; i < count; i++)
504	{
505	  if (curve_points[i].x != standard_piecewise_sat_adjustment[i].x ||
506	      curve_points[i].y - .0000001 > standard_piecewise_sat_adjustment[i].y ||
507	      curve_points[i].y + .0000001 < standard_piecewise_sat_adjustment[i].y)
508	    {
509	      bad_compare = 1;
510	      if (!quiet)
511		printf("Miscompare at element %d: (%f, %f) (%f, %f)\n", i,
512		       standard_piecewise_sat_adjustment[i].x,
513		       standard_piecewise_sat_adjustment[i].y,
514		       curve_points[i].x, curve_points[i].y);
515	    }
516	}
517      SIMPLE_TEST_CHECK(!bad_compare);
518    }
519  else
520    TEST_FAIL();
521
522  TEST("get sequence of piecewise curve (PASS is an expected failure)");
523  SIMPLE_TEST_CHECK(!stp_curve_get_sequence(curve1));
524
525  TEST("get data of piecewise curve (PASS is an expected failure)");
526  SIMPLE_TEST_CHECK(!stp_curve_get_data(curve1, &count));
527
528  TEST("set data point of piecewise curve (PASS is an expected failure)");
529  SIMPLE_TEST_CHECK(!stp_curve_set_point(curve1, 2, 1.0));
530
531  TEST("get data point of piecewise curve (PASS is an expected failure)");
532  SIMPLE_TEST_CHECK(!stp_curve_get_point(curve1, 2, &low));
533
534  TEST("interpolate piecewise curve (PASS is an expected failure)");
535  SIMPLE_TEST_CHECK(!stp_curve_interpolate_value(curve1, .5, &low));
536
537  TEST("rescale piecewise curve");
538  SIMPLE_TEST_CHECK(stp_curve_rescale(curve1, .5, STP_CURVE_COMPOSE_ADD,
539				      STP_CURVE_BOUNDS_RESCALE));
540
541  TEST("get float data of piecewise curve (PASS is an expected failure)");
542  SIMPLE_TEST_CHECK(!stp_curve_get_float_data(curve1, &count));
543
544  TEST("get subrange on piecewise curve (PASS is an expected failure)");
545  SIMPLE_TEST_CHECK(!(curve2 = stp_curve_get_subrange(curve1, 0, 2)));
546  if (!quiet && curve2)
547    stp_curve_write(stdout, curve2);
548
549  TEST("set subrange on piecewise curve (PASS is an expected failure)");
550  curve2 = stp_curve_create_from_string(linear_curve_2);
551  if (stp_curve_set_subrange(curve1, curve2, 1))
552    {
553      TEST_FAIL();
554      if (!quiet)
555	stp_curve_write(stdout, curve2);
556    }
557  else
558    TEST_PASS();
559
560  if (resample_points > 0)
561    {
562      char tmpbuf[64];
563      sprintf(tmpbuf, "resample piecewise curve to %d points", resample_points);
564      TEST(tmpbuf);
565      SIMPLE_TEST_CHECK(stp_curve_resample(curve1, resample_points));
566
567      TEST("resampled curve is not piecewise");
568      SIMPLE_TEST_CHECK(!stp_curve_is_piecewise(curve1));
569
570      TEST("get data points of piecewise copy (PASS is an expected failure)");
571      SIMPLE_TEST_CHECK(!stp_curve_get_data_points(curve1, &count));
572
573      TEST("get sequence of piecewise copy");
574      SIMPLE_TEST_CHECK(stp_curve_get_sequence(curve1));
575
576      TEST("get data of piecewise copy");
577      SIMPLE_TEST_CHECK(stp_curve_get_data(curve1, &count));
578
579      TEST("set data point of piecewise copy");
580      SIMPLE_TEST_CHECK(stp_curve_set_point(curve1, 2, 0.51));
581
582      TEST("get data point of piecewise copy");
583      SIMPLE_TEST_CHECK(stp_curve_get_point(curve1, 2, &low));
584
585      TEST("interpolate piecewise copy");
586      SIMPLE_TEST_CHECK(stp_curve_interpolate_value(curve1, .5, &low));
587
588      TEST("rescale piecewise copy");
589      SIMPLE_TEST_CHECK(stp_curve_rescale(curve1, 2,
590					  STP_CURVE_COMPOSE_MULTIPLY,
591					  STP_CURVE_BOUNDS_RESCALE));
592
593      TEST("get float data of piecewise copy");
594      SIMPLE_TEST_CHECK(stp_curve_get_float_data(curve1, &count));
595
596      TEST("get subrange on piecewise copy");
597      SIMPLE_TEST_CHECK((curve2 = stp_curve_get_subrange(curve1, 0, 2)));
598      if (verbose && curve2)
599	stp_curve_write(stdout, curve2);
600
601      if (resample_points > 10)
602	{
603	  TEST("set subrange on piecewise copy");
604	  curve2 = stp_curve_create_from_string(linear_curve_2);
605	  if (verbose)
606	    stp_curve_write(stdout, curve1);
607	  if (stp_curve_set_subrange(curve1, curve2, 4))
608	    {
609	      TEST_PASS();
610	      if (verbose)
611		stp_curve_write(stdout, curve1);
612	    }
613	  else
614	    TEST_FAIL();
615	}
616    }
617}
618
619int
620main(int argc, char **argv)
621{
622  char *tmp;
623  int i;
624  size_t count;
625  double low, high;
626
627  stp_curve_t *curve1;
628  stp_curve_t *curve2;
629  stp_curve_t *curve3;
630  const stp_curve_point_t *curve_points;
631
632  while (1)
633    {
634#ifdef __GNU_LIBRARY__
635      int option_index = 0;
636      int c = getopt_long(argc, argv, "qv", optlist, &option_index);
637#else
638      int c = getopt(argc, argv, "qv");
639#endif
640      if (c == -1)
641	break;
642      switch (c)
643	{
644	case 'q':
645	  quiet = 1;
646	  verbose = 0;
647	  break;
648	case 'v':
649	  quiet = 0;
650	  verbose = 1;
651	  break;
652	default:
653	  break;
654	}
655    }
656
657  stp_init();
658
659  TEST("creation of XML string from curve");
660  curve1 = stp_curve_create(STP_CURVE_WRAP_AROUND);
661  stp_curve_set_bounds(curve1, 0.0, 4.0);
662  stp_curve_set_data(curve1, 48, standard_sat_adjustment);
663  tmp = stp_curve_write_string(curve1);
664  stp_curve_destroy(curve1);
665  curve1 = NULL;
666  SIMPLE_TEST_CHECK(tmp);
667  if (verbose)
668    printf("%s\n", tmp);
669
670
671  TEST("creation of curve from XML string (stp_curve_create_from_string)");
672  SIMPLE_TEST_CHECK((curve2 = stp_curve_create_from_string(tmp)));
673  free(tmp);
674
675  TEST("stp_curve_resample");
676  if (curve2 != NULL && stp_curve_resample(curve2, 95) == 0)
677    {
678      TEST_FAIL();
679    }
680  else
681    {
682      TEST_PASS();
683      if (verbose)
684	stp_curve_write(stdout, curve2);
685    }
686  if (curve2)
687    {
688      stp_curve_destroy(curve2);
689      curve2 = NULL;
690    }
691
692  if (!quiet)
693    printf("Testing known bad curves...\n");
694  for (i = 0; i < bad_curve_count; i++)
695    {
696      stp_curve_t *bad = NULL;
697      TEST("BAD curve (PASS is an expected failure)");
698      if ((bad = stp_curve_create_from_string(bad_curves[i])) != NULL)
699	{
700	  TEST_FAIL();
701	  if (!quiet)
702	    {
703	      stp_curve_write(stdout, bad);
704	      printf("\n");
705	    }
706	  stp_curve_destroy(bad);
707	  bad = NULL;
708	}
709      else
710	TEST_PASS();
711    }
712
713  if (!quiet)
714    printf("Testing known good curves...\n");
715  for (i = 0; i < good_curve_count; i++)
716    {
717      if (curve2)
718	{
719	  stp_curve_destroy(curve2);
720	  curve2 = NULL;
721	}
722      TEST("GOOD curve");
723      if ((curve2 = stp_curve_create_from_string(good_curves[i])) != NULL)
724	{
725	  TEST_PASS();
726	  tmp = stp_curve_write_string(curve2);
727	  TEST("whether XML curve is identical to original");
728	  if (tmp && strcmp((const char *) tmp, good_curves[i]))
729	    {
730	      TEST_FAIL();
731	      if (!quiet)
732		{
733		  printf("XML:\n");
734		  printf("%s", tmp);
735		  printf("Original:\n");
736		  printf("%s", good_curves[i]);
737		  printf("End:\n");
738		}
739	    }
740	  else
741	    {
742	      TEST_PASS();
743	      if (verbose)
744		printf("%s", tmp);
745	    }
746	  free(tmp);
747	}
748      else
749	TEST_FAIL();
750    }
751  if (curve2)
752    {
753      stp_curve_destroy(curve2);
754      curve2 = NULL;
755    }
756  if (verbose)
757    printf("Allocate 1\n");
758  curve1 = stp_curve_create(STP_CURVE_WRAP_NONE);
759  if (verbose)
760    printf("Allocate 2\n");
761  curve2 = stp_curve_create(STP_CURVE_WRAP_NONE);
762  TEST("set curve 1 gamma");
763  SIMPLE_TEST_CHECK(stp_curve_set_gamma(curve1, 1.2));
764  if (verbose)
765    stp_curve_write(stdout, curve1);
766  TEST("set curve 2 gamma");
767  SIMPLE_TEST_CHECK(stp_curve_set_gamma(curve2, -1.2));
768  if (verbose)
769    stp_curve_write(stdout, curve2);
770
771  TEST("compose add from gamma curves");
772  SIMPLE_TEST_CHECK(stp_curve_compose(&curve3, curve1, curve2,
773				      STP_CURVE_COMPOSE_ADD, 64));
774  if (verbose && curve3)
775    stp_curve_write(stdout, curve3);
776
777  TEST("resample curve 1");
778  SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 64));
779  if (verbose && curve1)
780    stp_curve_write(stdout, curve1);
781  if (curve3)
782    {
783      stp_curve_destroy(curve3);
784      curve3 = NULL;
785    }
786  TEST("compose multiply from gamma curves");
787  if (!stp_curve_compose(&curve3, curve1, curve2, STP_CURVE_COMPOSE_MULTIPLY, 64))
788    TEST_FAIL();
789  else
790    {
791      TEST_PASS();
792      if (verbose)
793	{
794	  stp_curve_write(stdout, curve1);
795	  stp_curve_write(stdout, curve2);
796	  stp_curve_write(stdout, curve3);
797	}
798    }
799
800  TEST("compose add from non-gamma curves");
801  stp_curve_destroy(curve1);
802  stp_curve_destroy(curve2);
803  stp_curve_destroy(curve3);
804  curve1 = stp_curve_create_from_string(good_curves[0]);
805  curve2 = stp_curve_create_from_string(linear_curve_2);
806  SIMPLE_TEST_CHECK(stp_curve_compose(&curve3, curve1, curve2,
807				      STP_CURVE_COMPOSE_ADD, 64));
808  if (verbose && curve3)
809    stp_curve_write(stdout, curve3);
810
811  TEST("resample curve 1");
812  SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 64));
813  if (verbose && curve1)
814    stp_curve_write(stdout, curve1);
815  if (curve3)
816    {
817      stp_curve_destroy(curve3);
818      curve3 = NULL;
819    }
820  TEST("compose multiply from non-gamma curves");
821  if (!stp_curve_compose(&curve3, curve1, curve2, STP_CURVE_COMPOSE_MULTIPLY, 64))
822    TEST_FAIL();
823  else
824    {
825      TEST_PASS();
826      if (verbose)
827	{
828	  stp_curve_write(stdout, curve1);
829	  stp_curve_write(stdout, curve2);
830	  stp_curve_write(stdout, curve3);
831	}
832    }
833  if (curve3)
834    {
835      stp_curve_destroy(curve3);
836      curve3 = NULL;
837    }
838
839  TEST("multiply rescale");
840  SIMPLE_TEST_CHECK(stp_curve_rescale(curve2, -1, STP_CURVE_COMPOSE_MULTIPLY,
841				      STP_CURVE_BOUNDS_RESCALE));
842  if (verbose && curve2)
843    stp_curve_write(stdout, curve2);
844  TEST("subtract compose");
845  SIMPLE_TEST_CHECK(stp_curve_compose(&curve3, curve1, curve2,
846				      STP_CURVE_COMPOSE_ADD, 64));
847  if (verbose && curve3)
848    stp_curve_write(stdout, curve3);
849
850  if (curve3)
851    {
852      stp_curve_destroy(curve3);
853      curve3 = NULL;
854    }
855  if (curve1)
856    {
857      stp_curve_destroy(curve1);
858      curve1 = NULL;
859    }
860  if (curve2)
861    {
862      stp_curve_destroy(curve2);
863      curve2 = NULL;
864    }
865
866  TEST("spline curve 1 creation");
867  SIMPLE_TEST_CHECK((curve1 = stp_curve_create_from_string(spline_curve_1)));
868  TEST("spline curve 2 creation");
869  SIMPLE_TEST_CHECK((curve2 = stp_curve_create_from_string(spline_curve_2)));
870  if (curve1)
871    {
872      if (verbose)
873	stp_curve_write(stdout, curve1);
874      TEST("spline curve 1 resample 1");
875      SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 41));
876      if (verbose && curve1)
877	stp_curve_write(stdout, curve1);
878      TEST("spline curve 1 resample 2");
879      SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 83));
880      if (verbose && curve1)
881	stp_curve_write(stdout, curve1);
882    }
883  if (curve2)
884    {
885      if (verbose)
886	stp_curve_write(stdout, curve2);
887      TEST("spline curve 2 resample");
888      SIMPLE_TEST_CHECK(stp_curve_resample(curve2, 48));
889      if (verbose && curve2)
890	stp_curve_write(stdout, curve2);
891    }
892  TEST("compose add (PASS is an expected failure)");
893  if (curve1 && curve2 &&
894      stp_curve_compose(&curve3, curve1, curve2, STP_CURVE_COMPOSE_MULTIPLY, -1))
895    {
896      TEST_FAIL();
897      if (!quiet)
898	printf("compose with different wrap mode should fail!\n");
899    }
900  else
901    TEST_PASS();
902  if (curve1)
903    {
904      stp_curve_destroy(curve1);
905      curve1 = NULL;
906    }
907  if (curve2)
908    {
909      stp_curve_destroy(curve2);
910      curve2 = NULL;
911    }
912
913  TEST("linear curve 1 creation");
914  SIMPLE_TEST_CHECK((curve1 = stp_curve_create_from_string(linear_curve_1)));
915  TEST("linear curve 2 creation");
916  SIMPLE_TEST_CHECK((curve2 = stp_curve_create_from_string(linear_curve_2)));
917
918  TEST("get data points of dense curve (PASS is an expected failure)");
919  curve_points = stp_curve_get_data_points(curve2, &count);
920  SIMPLE_TEST_CHECK(!curve_points);
921
922  if (curve1)
923    {
924      if (verbose)
925	stp_curve_write(stdout, curve1);
926      TEST("linear curve 1 resample");
927      SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 41));
928      if (verbose && curve1)
929	stp_curve_write(stdout, curve1);
930      stp_curve_destroy(curve1);
931      curve1 = NULL;
932    }
933  if (curve2)
934    {
935      if (verbose)
936	stp_curve_write(stdout, curve2);
937      TEST("linear curve 2 resample");
938      SIMPLE_TEST_CHECK(stp_curve_resample(curve2, 48));
939      if (verbose && curve2)
940	stp_curve_write(stdout, curve2);
941      stp_curve_destroy(curve2);
942      curve2 = NULL;
943    }
944
945  curve1 = stp_curve_create(STP_CURVE_WRAP_AROUND);
946  stp_curve_set_interpolation_type(curve1, STP_CURVE_TYPE_SPLINE);
947  stp_curve_set_bounds(curve1, 0.0, 4.0);
948  stp_curve_set_data(curve1, 48, standard_sat_adjustment);
949  TEST("setting curve data");
950  SIMPLE_TEST_CHECK(curve1 && (stp_curve_count_points(curve1) == 48));
951  if (verbose)
952    stp_curve_write(stdout, curve1);
953  TEST("curve resample");
954  SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 384));
955  if (verbose)
956    stp_curve_write(stdout, curve1);
957  TEST("very large curve resample");
958  SIMPLE_TEST_CHECK(stp_curve_resample(curve1, 65535));
959  TEST("offsetting large curve");
960#if 0
961  stp_curve_get_range(curve1, &low, &high);
962  fprintf(stderr, "Result original max %f min %f\n", high, low);
963  stp_curve_get_bounds(curve1, &low, &high);
964  fprintf(stderr, "Bounds original max %f min %f\n", high, low);
965#endif
966  SIMPLE_TEST_CHECK(stp_curve_rescale(curve1, 2.0, STP_CURVE_COMPOSE_ADD,
967				      STP_CURVE_BOUNDS_RESCALE));
968
969  stp_curve_rescale(curve1, 1.0, STP_CURVE_COMPOSE_ADD,
970		    STP_CURVE_BOUNDS_RESCALE);
971  stp_curve_get_bounds(curve1, &low, &high);
972  stp_curve_rescale(curve1, 0.0, STP_CURVE_COMPOSE_ADD,
973		    STP_CURVE_BOUNDS_RESCALE);
974  stp_curve_get_bounds(curve1, &low, &high);
975  stp_curve_rescale(curve1, 0.0, STP_CURVE_COMPOSE_ADD,
976		    STP_CURVE_BOUNDS_RESCALE);
977  stp_curve_get_bounds(curve1, &low, &high);
978  stp_curve_rescale(curve1, 0.0, STP_CURVE_COMPOSE_ADD,
979		    STP_CURVE_BOUNDS_RESCALE);
980  stp_curve_get_bounds(curve1, &low, &high);
981  TEST("writing very large curve to string");
982  tmp = stp_curve_write_string(curve1);
983  if (tmp == NULL)
984    TEST_FAIL();
985  else
986    TEST_PASS();
987  if (tmp)
988    {
989      TEST("reading back very large curve");
990      curve2 = stp_curve_create_from_string(tmp);
991      SIMPLE_TEST_CHECK(stp_curve_count_points(curve2) == 65535);
992
993      free(tmp);
994      TEST("Rescaling readback");
995      SIMPLE_TEST_CHECK(stp_curve_rescale(curve2, -1.0,
996					  STP_CURVE_COMPOSE_MULTIPLY,
997					  STP_CURVE_BOUNDS_RESCALE));
998      TEST("Adding curves");
999      SIMPLE_TEST_CHECK(stp_curve_compose(&curve3, curve1, curve2,
1000					  STP_CURVE_COMPOSE_ADD, 65535));
1001
1002      stp_curve_get_range(curve3, &low, &high);
1003      TEST("Comparing results");
1004      SIMPLE_TEST_CHECK(low < .00001 && low > -.00001 &&
1005			high < .00001 && high > -.00001);
1006
1007      if (curve1)
1008	{
1009	  stp_curve_destroy(curve1);
1010	  curve1 = NULL;
1011	}
1012    }
1013
1014  TEST("Creating piecewise wrap-around curve");
1015  curve1 = stp_curve_create(STP_CURVE_WRAP_AROUND);
1016  stp_curve_set_bounds(curve1, 0.0, 4.0);
1017
1018  SIMPLE_TEST_CHECK(stp_curve_set_data_points
1019		    (curve1, 48, standard_piecewise_sat_adjustment));
1020
1021  TEST("Writing piecewise wrap-around curve to string");
1022  tmp = stp_curve_write_string(curve1);
1023  SIMPLE_TEST_CHECK(tmp);
1024  if (verbose)
1025    printf("%s\n", tmp);
1026
1027  TEST("Check curve is piecewise");
1028  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve1));
1029
1030  TEST("Create copy of piecewise curve");
1031  curve2 = stp_curve_create_copy(curve1);
1032  SIMPLE_TEST_CHECK(curve2);
1033
1034  TEST("Check copy is piecewise");
1035  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve2));
1036
1037  piecewise_curve_checks(curve1, 0, 48);
1038  stp_curve_rescale(curve1, -.5, STP_CURVE_COMPOSE_ADD,
1039		    STP_CURVE_BOUNDS_RESCALE);
1040  piecewise_curve_checks(curve2, 3, 48);
1041
1042  TEST("Copy in place piecewise curve");
1043  stp_curve_copy(curve2, curve1);
1044  SIMPLE_TEST_CHECK(curve1);
1045  piecewise_curve_checks(curve2, 10, 48);
1046  stp_curve_copy(curve2, curve1);
1047  piecewise_curve_checks(curve2, 15, 48);
1048  stp_curve_copy(curve2, curve1);
1049  piecewise_curve_checks(curve2, 47, 48);
1050  stp_curve_copy(curve2, curve1);
1051  piecewise_curve_checks(curve2, 48, 48);
1052  stp_curve_copy(curve2, curve1);
1053  piecewise_curve_checks(curve2, 49, 48);
1054  stp_curve_copy(curve2, curve1);
1055  piecewise_curve_checks(curve2, 50, 48);
1056  stp_curve_copy(curve2, curve1);
1057  piecewise_curve_checks(curve2, 100, 48);
1058  stp_curve_destroy(curve1);
1059
1060  TEST("Creating piecewise no-wrap curve with not enough data (PASS is an expected failure)");
1061  curve1 = stp_curve_create(STP_CURVE_WRAP_NONE);
1062  stp_curve_set_bounds(curve1, 0.0, 4.0);
1063  SIMPLE_TEST_CHECK(!stp_curve_set_data_points
1064		    (curve1, 48, standard_piecewise_sat_adjustment));
1065
1066  TEST("Creating piecewise no-wrap curve correctly");
1067  SIMPLE_TEST_CHECK(stp_curve_set_data_points
1068		    (curve1, 49, standard_piecewise_sat_adjustment));
1069
1070  TEST("Writing piecewise no-wrap curve to string");
1071  tmp = stp_curve_write_string(curve1);
1072  SIMPLE_TEST_CHECK(tmp);
1073  if (verbose)
1074    printf("%s\n", tmp);
1075
1076  TEST("Check curve is piecewise");
1077  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve1));
1078
1079  TEST("Create copy of piecewise curve");
1080  curve2 = stp_curve_create_copy(curve1);
1081  SIMPLE_TEST_CHECK(curve2);
1082  TEST("Check copy is piecewise");
1083  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve2));
1084
1085  piecewise_curve_checks(curve1, 0, 49);
1086  stp_curve_rescale(curve1, -.5, STP_CURVE_COMPOSE_ADD,
1087		    STP_CURVE_BOUNDS_RESCALE);
1088  piecewise_curve_checks(curve2, 3, 49);
1089
1090  TEST("Copy in place piecewise curve");
1091  stp_curve_copy(curve2, curve1);
1092  piecewise_curve_checks(curve2, 10, 49);
1093  stp_curve_copy(curve2, curve1);
1094  piecewise_curve_checks(curve2, 15, 49);
1095  stp_curve_copy(curve2, curve1);
1096  piecewise_curve_checks(curve2, 47, 49);
1097  stp_curve_copy(curve2, curve1);
1098  piecewise_curve_checks(curve2, 48, 49);
1099  stp_curve_copy(curve2, curve1);
1100  piecewise_curve_checks(curve2, 49, 49);
1101  stp_curve_copy(curve2, curve1);
1102  piecewise_curve_checks(curve2, 50, 49);
1103  stp_curve_copy(curve2, curve1);
1104  piecewise_curve_checks(curve2, 100, 49);
1105
1106
1107  TEST("Creating piecewise spline wrap-around curve");
1108  curve1 = stp_curve_create(STP_CURVE_WRAP_AROUND);
1109  stp_curve_set_interpolation_type(curve1, STP_CURVE_TYPE_SPLINE);
1110  stp_curve_set_bounds(curve1, 0.0, 4.0);
1111
1112  SIMPLE_TEST_CHECK(stp_curve_set_data_points
1113		    (curve1, 48, standard_piecewise_sat_adjustment));
1114
1115  TEST("Writing piecewise wrap-around curve to string");
1116  tmp = stp_curve_write_string(curve1);
1117  SIMPLE_TEST_CHECK(tmp);
1118  if (verbose)
1119    printf("%s\n", tmp);
1120
1121  TEST("Check curve is piecewise");
1122  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve1));
1123
1124  TEST("Create copy of piecewise curve");
1125  curve2 = stp_curve_create_copy(curve1);
1126  SIMPLE_TEST_CHECK(curve2);
1127  TEST("Check copy is piecewise");
1128  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve2));
1129
1130  piecewise_curve_checks(curve1, 0, 48);
1131  stp_curve_rescale(curve1, -.5, STP_CURVE_COMPOSE_ADD,
1132		    STP_CURVE_BOUNDS_RESCALE);
1133  piecewise_curve_checks(curve2, 3, 48);
1134
1135  TEST("Copy in place piecewise curve");
1136  stp_curve_copy(curve2, curve1);
1137  piecewise_curve_checks(curve2, 10, 48);
1138  stp_curve_copy(curve2, curve1);
1139  piecewise_curve_checks(curve2, 15, 48);
1140  stp_curve_copy(curve2, curve1);
1141  piecewise_curve_checks(curve2, 47, 48);
1142  stp_curve_copy(curve2, curve1);
1143  piecewise_curve_checks(curve2, 48, 48);
1144  stp_curve_copy(curve2, curve1);
1145  piecewise_curve_checks(curve2, 49, 48);
1146  stp_curve_copy(curve2, curve1);
1147  piecewise_curve_checks(curve2, 50, 48);
1148  stp_curve_copy(curve2, curve1);
1149  piecewise_curve_checks(curve2, 100, 48);
1150  stp_curve_destroy(curve1);
1151
1152  TEST("Creating piecewise spline wrap-around curve");
1153  curve1 = stp_curve_create(STP_CURVE_WRAP_NONE);
1154  stp_curve_set_interpolation_type(curve1, STP_CURVE_TYPE_SPLINE);
1155  stp_curve_set_bounds(curve1, 0.0, 4.0);
1156
1157  SIMPLE_TEST_CHECK(stp_curve_set_data_points
1158		    (curve1, 49, standard_piecewise_sat_adjustment));
1159
1160  TEST("Writing piecewise no-wrap curve to string");
1161  tmp = stp_curve_write_string(curve1);
1162  SIMPLE_TEST_CHECK(tmp);
1163  if (verbose)
1164    printf("%s\n", tmp);
1165
1166  TEST("Check curve is piecewise");
1167  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve1));
1168
1169  TEST("Create copy of piecewise curve");
1170  curve2 = stp_curve_create_copy(curve1);
1171  SIMPLE_TEST_CHECK(curve2);
1172  TEST("Check copy is piecewise");
1173  SIMPLE_TEST_CHECK(stp_curve_is_piecewise(curve2));
1174
1175  piecewise_curve_checks(curve1, 0, 49);
1176  stp_curve_rescale(curve1, -.5, STP_CURVE_COMPOSE_ADD,
1177		    STP_CURVE_BOUNDS_RESCALE);
1178  piecewise_curve_checks(curve2, 3, 49);
1179
1180  TEST("Copy in place piecewise curve");
1181  stp_curve_copy(curve2, curve1);
1182  piecewise_curve_checks(curve2, 10, 49);
1183  stp_curve_copy(curve2, curve1);
1184  piecewise_curve_checks(curve2, 15, 49);
1185  stp_curve_copy(curve2, curve1);
1186  piecewise_curve_checks(curve2, 47, 49);
1187  stp_curve_copy(curve2, curve1);
1188  piecewise_curve_checks(curve2, 48, 49);
1189  stp_curve_copy(curve2, curve1);
1190  piecewise_curve_checks(curve2, 49, 49);
1191  stp_curve_copy(curve2, curve1);
1192  piecewise_curve_checks(curve2, 50, 49);
1193  stp_curve_copy(curve2, curve1);
1194  piecewise_curve_checks(curve2, 100, 49);
1195
1196  TEST("Create small piecewise curve");
1197  curve1 = stp_curve_create_from_string(small_piecewise_curve);
1198  SIMPLE_TEST_CHECK(curve1);
1199
1200  stp_curve_destroy(curve1);
1201  curve1 = NULL;
1202  stp_curve_destroy(curve2);
1203  curve2 = NULL;
1204  stp_curve_destroy(curve3);
1205  curve3 = NULL;
1206
1207  if (global_error_count)
1208    {
1209      printf("%d/%d tests FAILED.\n", global_error_count, global_test_count);
1210      printf("Failures:\n");
1211      while (test_failure_head)
1212	{
1213	  printf("  %3d\n", test_failure_head->test_number);
1214	  test_failure_head = test_failure_head->next;
1215	}
1216    }
1217  else
1218    printf("All tests passed successfully.\n");
1219  return global_error_count ? 1 : 0;
1220}
1221