static stp_curve_t * xml_doc_get_curve(stp_mxml_node_t *doc) { stp_mxml_node_t *cur; stp_mxml_node_t *xmlcurve; stp_curve_t *curve = NULL; if (doc == NULL ) { stp_deprintf(STP_DBG_CURVE_ERRORS, "xml_doc_get_curve: XML file not parsed successfully.\n"); return NULL; } cur = doc->child; if (cur == NULL) { stp_deprintf(STP_DBG_CURVE_ERRORS, "xml_doc_get_curve: empty document\n"); return NULL; } xmlcurve = stp_xml_get_node(cur, "gutenprint", "curve", NULL); if (xmlcurve) curve = stp_curve_create_from_xmltree(xmlcurve); return curve; }
stp_curve_t * stp_curve_create_from_file(const char* file) { stp_curve_t *curve = NULL; stp_mxml_node_t *doc; FILE *fp = fopen(file, "r"); if (!fp) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_file: unable to open %s: %s\n", file, strerror(errno)); return NULL; } stp_deprintf(STP_DBG_XML, "stp_curve_create_from_file: reading `%s'...\n", file); stp_xml_init(); doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK); curve = xml_doc_get_curve(doc); if (doc) stp_mxmlDelete(doc); stp_xml_exit(); (void) fclose(fp); return curve; }
static stp_xml_dither_cache_t * stp_xml_dither_cache_get(int x, int y) { stp_list_item_t *ln; stp_deprintf(STP_DBG_XML, "stp_xml_dither_cache_get: lookup %dx%d... ", x, y); if (!dither_matrix_cache) { stp_deprintf(STP_DBG_XML, "cache does not exist\n"); return NULL; } ln = stp_list_get_start(dither_matrix_cache); while (ln) { if (((stp_xml_dither_cache_t *) stp_list_item_get_data(ln))->x == x && ((stp_xml_dither_cache_t *) stp_list_item_get_data(ln))->y == y) { stp_deprintf(STP_DBG_XML, "found\n"); return ((stp_xml_dither_cache_t *) stp_list_item_get_data(ln)); } ln = stp_list_item_next(ln); } stp_deprintf(STP_DBG_XML, "missing\n"); return NULL; }
/* create a new list */ stp_list_t * stp_list_create(void) { stp_list_t *list = stp_malloc(sizeof(stp_list_t)); /* initialise an empty list */ list->index_cache = 0; list->length = 0; list->start = NULL; list->end = NULL; list->index_cache_node = NULL; list->freefunc = NULL; list->namefunc = NULL; list->long_namefunc = NULL; list->sortfunc = NULL; list->copyfunc = NULL; list->name_cache = NULL; list->name_cache_node = NULL; list->long_name_cache = NULL; list->long_name_cache_node = NULL; stp_deprintf(STP_DBG_LIST, "stp_list_head constructor\n"); return list; }
void stp_xml_parse_file_named(const char *name) { stp_list_t *dir_list; /* List of directories to scan */ stp_list_t *file_list; /* List of XML files */ stp_list_item_t *item; /* Pointer to current list item */ if (!(dir_list = stp_list_create())) return; stp_list_set_freefunc(dir_list, stp_list_node_free_data); if (getenv("STP_DATA_PATH")) stp_path_split(dir_list, getenv("STP_DATA_PATH")); else stp_path_split(dir_list, PKGXMLDATADIR); file_list = stp_path_search(dir_list, name); stp_list_destroy(dir_list); item = stp_list_get_start(file_list); while (item) { stp_deprintf(STP_DBG_XML, "stp_xml_parse_file_named: source file: %s\n", (const char *) stp_list_item_get_data(item)); stp_xml_parse_file((const char *) stp_list_item_get_data(item)); item = stp_list_item_next(item); } stp_list_destroy(file_list); }
static stp_array_t * stpi_dither_array_create_from_file(const char* file) { stp_mxml_node_t *doc; stp_array_t *ret = NULL; FILE *fp = fopen(file, "r"); if (!fp) { stp_erprintf("stp_curve_create_from_file: unable to open %s: %s\n", file, strerror(errno)); return NULL; } stp_xml_init(); stp_deprintf(STP_DBG_XML, "stpi_dither_array_create_from_file: reading `%s'...\n", file); doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK); (void) fclose(fp); if (doc) { ret = xml_doc_get_dither_array(doc); stp_mxmlDelete(doc); } stp_xml_exit(); return ret; }
static void stp_xml_dither_cache_set(int x, int y, const char *filename) { stp_xml_dither_cache_t *cacheval; assert(x && y && filename); stp_xml_init(); if (dither_matrix_cache == NULL) dither_matrix_cache = stp_list_create(); if (stp_xml_dither_cache_get(x, y)) /* Already cached for this x and y aspect */ return; cacheval = stp_malloc(sizeof(stp_xml_dither_cache_t)); cacheval->x = x; cacheval->y = y; cacheval->filename = stp_strdup(filename); cacheval->dither_array = NULL; stp_list_item_create(dither_matrix_cache, NULL, (void *) cacheval); stp_deprintf(STP_DBG_XML, "stp_xml_dither_cache_set: added %dx%d\n", x, y); stp_xml_exit(); return; }
static int stpi_curve_check_parameters(stp_curve_t *curve, size_t points) { double blo, bhi; if (curve->gamma && curve->wrap_mode) { stp_deprintf(STP_DBG_CURVE_ERRORS, "curve sets both gamma and wrap_mode\n"); return 0; } stp_sequence_get_bounds(curve->seq, &blo, &bhi); if (blo > bhi) { stp_deprintf(STP_DBG_CURVE_ERRORS, "curve low bound is greater than high bound\n"); return 0; } return 1; }
/* * Parse a single XML file. */ int stp_xml_parse_file(const char *file) /* File to parse */ { stp_mxml_node_t *doc; stp_mxml_node_t *cur; FILE *fp; stp_deprintf(STP_DBG_XML, "stp_xml_parse_file: reading `%s'...\n", file); fp = fopen(file, "r"); if (!fp) { stp_erprintf("stp_xml_parse_file: unable to open %s: %s\n", file, strerror(errno)); return 1; } stp_xml_init(); doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK); fclose(fp); cur = doc->child; while (cur && (cur->type != STP_MXML_ELEMENT || strcmp(cur->value.element.name, "gimp-print") != 0)) cur = cur->next; if (cur == NULL || cur->type != STP_MXML_ELEMENT) { stp_erprintf("stp_xml_parse_file: %s: parse error\n", file); stp_mxmlDelete(doc); return 1; } if (strcmp(cur->value.element.name, "gimp-print") != 0) { stp_erprintf ("XML file of the wrong type, root node is %s != gimp-print", cur->value.element.name); stp_mxmlDelete(doc); return 1; } /* The XML file was read and is the right format */ stpi_xml_process_gimpprint(cur, file); stp_mxmlDelete(doc); stp_xml_exit(); return 0; }
static int interpolate_points(stp_curve_t *a, stp_curve_t *b, stp_curve_compose_t mode, int points, double *tmp_data) { double pa, pb; int i; size_t points_a = stp_curve_count_points(a); size_t points_b = stp_curve_count_points(b); for (i = 0; i < points; i++) { if (!stp_curve_interpolate_value (a, (double) i * (points_a - 1) / (points - 1), &pa)) { stp_deprintf(STP_DBG_CURVE_ERRORS, "interpolate_points: interpolate curve a value failed\n"); return 0; } if (!stp_curve_interpolate_value (b, (double) i * (points_b - 1) / (points - 1), &pb)) { stp_deprintf(STP_DBG_CURVE_ERRORS, "interpolate_points: interpolate curve b value failed\n"); return 0; } if (mode == STP_CURVE_COMPOSE_ADD) pa += pb; else pa *= pb; if (! isfinite(pa)) { stp_deprintf(STP_DBG_CURVE_ERRORS, "interpolate_points: interpolated point %lu is invalid\n", (unsigned long) i); return 0; } tmp_data[i] = pa; } return 1; }
static stp_mxml_node_t * xmldoc_create_from_curve(const stp_curve_t *curve) { stp_mxml_node_t *xmldoc; stp_mxml_node_t *rootnode; stp_mxml_node_t *curvenode; /* Get curve details */ curvenode = stp_xmltree_create_from_curve(curve); if (curvenode == NULL) { stp_deprintf(STP_DBG_CURVE_ERRORS, "xmldoc_create_from_curve: error creating curve node\n"); return NULL; } /* Create the XML tree */ xmldoc = stp_xmldoc_create_generic(); if (xmldoc == NULL) { stp_deprintf(STP_DBG_CURVE_ERRORS, "xmldoc_create_from_curve: error creating XML document\n"); return NULL; } rootnode = xmldoc->child; if (rootnode == NULL) { stp_mxmlDelete(xmldoc); stp_deprintf(STP_DBG_CURVE_ERRORS, "xmldoc_create_from_curve: error getting XML document root node\n"); return NULL; } stp_mxmlAdd(rootnode, STP_MXML_ADD_AFTER, NULL, curvenode); return xmldoc; }
stp_curve_t * stp_curve_create_from_string(const char* string) { stp_curve_t *curve = NULL; stp_mxml_node_t *doc; stp_deprintf(STP_DBG_XML, "stp_curve_create_from_string: reading '%s'...\n", string); stp_xml_init(); doc = stp_mxmlLoadString(NULL, string, STP_MXML_NO_CALLBACK); curve = xml_doc_get_curve(doc); if (doc) stp_mxmlDelete(doc); stp_xml_exit(); return curve; }
stp_curve_t * stp_curve_create_from_stream(FILE* fp) { stp_curve_t *curve = NULL; stp_mxml_node_t *doc; stp_deprintf(STP_DBG_XML, "stp_curve_create_from_fp: reading...\n"); stp_xml_init(); doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK); curve = xml_doc_get_curve(doc); if (doc) stp_mxmlDelete(doc); stp_xml_exit(); return curve; }
/* free a list, freeing all child nodes first */ int stp_list_destroy(stp_list_t *list) { stp_list_item_t *cur; stp_list_item_t *next; check_list(list); clear_cache(list); cur = list->start; while(cur) { next = cur->next; stp_list_item_destroy(list, cur); cur = next; } stp_deprintf(STP_DBG_LIST, "stp_list_head destructor\n"); stp_free(list); return 0; }
/* * Parse the <dither-matrix> node. */ static int stp_xml_process_dither_matrix(stp_mxml_node_t *dm, /* The dither matrix node */ const char *file) /* Source file */ { const char *value; int x = -1; int y = -1; value = stp_mxmlElementGetAttr(dm, "x-aspect"); x = stp_xmlstrtol(value); value = stp_mxmlElementGetAttr(dm, "y-aspect"); y = stp_xmlstrtol(value); stp_deprintf(STP_DBG_XML, "stp_xml_process_dither_matrix: x=%d, y=%d\n", x, y); stp_xml_dither_cache_set(x, y, file); return 1; }
static inline double interpolate_gamma_internal(const stp_curve_t *curve, double where) { double fgamma = curve->gamma; double blo, bhi; size_t real_point_count; real_point_count = get_real_point_count(curve);; if (real_point_count) where /= (real_point_count - 1); if (fgamma < 0) { where = 1.0 - where; fgamma = -fgamma; } stp_sequence_get_bounds(curve->seq, &blo, &bhi); stp_deprintf(STP_DBG_CURVE, "interpolate_gamma %f %f %f %f %f\n", where, fgamma, blo, bhi, pow(where, fgamma)); return blo + (bhi - blo) * pow(where, fgamma); }
/* * Read all available XML files. */ int stp_xml_init_defaults(void) { stp_list_item_t *item; /* Pointer to current list item */ stp_xml_init(); /* Parse each XML file */ item = stp_list_get_start(stpi_xml_preloads); while (item) { stp_deprintf(STP_DBG_XML, "stp_xml_init_defaults: source file: %s\n", (const char *) stp_list_item_get_data(item)); stp_xml_parse_file_named((const char *) stp_list_item_get_data(item)); item = stp_list_item_next(item); } stp_list_destroy(stpi_xml_preloads); stp_xml_exit(); return 0; }
int stp_curve_set_data(stp_curve_t *curve, size_t count, const double *data) { size_t i; size_t real_count = count; double low, high; CHECK_CURVE(curve); if (count < 2) return 0; if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) real_count++; if (real_count > curve_point_limit) return 0; /* Validate the data before we commit to it. */ stp_sequence_get_bounds(curve->seq, &low, &high); for (i = 0; i < count; i++) if (! isfinite(data[i]) || data[i] < low || data[i] > high) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data: datum out of bounds: " "%g (require %g <= x <= %g), n = %ld\n", data[i], low, high, (long)i); return 0; } /* Allocate sequence; also accounts for WRAP_MODE */ stpi_curve_set_points(curve, count); curve->gamma = 0.0; stp_sequence_set_subrange(curve->seq, 0, count, data); if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) stp_sequence_set_point(curve->seq, count, data[0]); curve->recompute_interval = 1; curve->piecewise = 0; return 1; }
/* remove a node from list */ int stp_list_item_destroy(stp_list_t *list, stp_list_item_t *item) { check_list(list); clear_cache(list); /* decrement reference count */ list->length--; if (list->freefunc) list->freefunc((void *) item->data); if (item->prev) item->prev->next = item->next; else list->start = item->next; if (item->next) item->next->prev = item->prev; else list->end = item->prev; stp_free(item); stp_deprintf(STP_DBG_LIST, "stp_list_node destructor\n"); return 0; }
/* * create a new node in list, before next (may be null e.g. if sorting * next is calculated automatically, else defaults to end). Must be * initialised with data (null nodes are disallowed). The * stp_list_item_t type can not exist unless it is associated with an * stp_list_t list head. */ int stp_list_item_create(stp_list_t *list, stp_list_item_t *next, const void *data) { stp_list_item_t *ln; /* list node to add */ stp_list_item_t *lnn; /* list node next */ check_list(list); clear_cache(list); ln = stp_malloc(sizeof(stp_list_item_t)); ln->prev = ln->next = NULL; if (data) ln->data = stpi_cast_safe(data); else { stp_free(ln); return 1; } if (list->sortfunc) { /* set np to the previous node (before the insertion */ lnn = list->end; while (lnn) { if (list->sortfunc(lnn->data, ln->data) <= 0) break; lnn = lnn->prev; } } #if 0 /* * This code #ifdef'ed out by Robert Krawitz on April 3, 2004. * Setting a debug variable should not result in taking a materially * different code path. */ else if (stpi_get_debug_level() & STPI_DBG_LIST) { if (next) { lnn = list->start; while (lnn) { if (lnn == next) break; lnn = lnn->prev; } } else lnn = NULL; } #endif else lnn = next; /* got lnp; now insert the new ln */ /* set next */ ln->next = lnn; if (!ln->prev) /* insert at start of list */ { if (list->start) /* list not empty */ ln->prev = list->end; else list->start = ln; list->end = ln; } /* set prev (already set if at start of list) */ if (!ln->prev && ln->next) /* insert at end of list */ ln->prev = ln->next->prev; if (list->start == ln->next) /* prev was old end */ { list->start = ln; } /* set next->prev */ if (ln->next) ln->next->prev = ln; /* set prev->next */ if (ln->prev) ln->prev->next = ln; /* increment reference count */ list->length++; stp_deprintf(STP_DBG_LIST, "stp_list_node constructor\n"); return 0; }
static void compute_spline_deltas_piecewise(stp_curve_t *curve) { int i; int k; double *u; double *y2; const double *data = NULL; const stp_curve_point_t *dp; size_t point_count; size_t real_point_count; double sig; double p; point_count = get_point_count(curve); stp_sequence_get_data(curve->seq, &real_point_count, &data); dp = (const stp_curve_point_t *)data; real_point_count = real_point_count / 2; u = stp_malloc(sizeof(double) * real_point_count); y2 = stp_malloc(sizeof(double) * real_point_count); if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) { int reps = 3; int count = reps * real_point_count; double *y2a = stp_malloc(sizeof(double) * count); double *ua = stp_malloc(sizeof(double) * count); y2a[0] = 0.0; ua[0] = 0.0; for (i = 1; i < count - 1; i++) { int im1 = (i - 1) % point_count; int ia = i % point_count; int ip1 = (i + 1) % point_count; sig = (dp[ia].x - dp[im1].x) / (dp[ip1].x - dp[im1].x); p = sig * y2a[im1] + 2.0; y2a[i] = (sig - 1.0) / p; ua[i] = ((dp[ip1].y - dp[ia].y) / (dp[ip1].x - dp[ia].x)) - ((dp[ia].y - dp[im1].y) / (dp[ia].x - dp[im1].x)); ua[i] = (((6.0 * ua[ia]) / (dp[ip1].x - dp[im1].x)) - (sig * ua[im1])) / p; } y2a[count - 1] = 0.0; for (k = count - 2 ; k >= 0; k--) y2a[k] = y2a[k] * y2a[k + 1] + ua[k]; memcpy(u, ua + ((reps / 2) * point_count), sizeof(double) * real_point_count); memcpy(y2, y2a + ((reps / 2) * point_count), sizeof(double) * real_point_count); stp_free(y2a); stp_free(ua); } else { int count = real_point_count - 1; y2[0] = 0; u[0] = 2 * (dp[1].y - dp[0].y); for (i = 1; i < count; i++) { int im1 = (i - 1); int ip1 = (i + 1); sig = (dp[i].x - dp[im1].x) / (dp[ip1].x - dp[im1].x); p = sig * y2[im1] + 2.0; y2[i] = (sig - 1.0) / p; u[i] = ((dp[ip1].y - dp[i].y) / (dp[ip1].x - dp[i].x)) - ((dp[i].y - dp[im1].y) / (dp[i].x - dp[im1].x)); u[i] = (((6.0 * u[i]) / (dp[ip1].x - dp[im1].x)) - (sig * u[im1])) / p; stp_deprintf(STP_DBG_CURVE, "%d sig %f p %f y2 %f u %f x %f %f %f y %f %f %f\n", i, sig, p, y2[i], u[i], dp[im1].x, dp[i].x, dp[ip1].x, dp[im1].y, dp[i].y, dp[ip1].y); } y2[count] = 0.0; u[count] = 0.0; for (k = real_point_count - 2; k >= 0; k--) y2[k] = y2[k] * y2[k + 1] + u[k]; } curve->interval = y2; stp_free(u); }
int stp_curve_resample(stp_curve_t *curve, size_t points) { size_t limit = points; size_t old; size_t i; double *new_vec; CHECK_CURVE(curve); if (points == get_point_count(curve) && curve->seq && !(curve->piecewise)) return 1; if (points < 2) return 1; if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) limit++; if (limit > curve_point_limit) return 0; old = get_real_point_count(curve); if (old) old--; if (!old) old = 1; new_vec = stp_malloc(sizeof(double) * limit); /* * Be very careful how we calculate the location along the scale! * If we're not careful how we do it, we might get a small roundoff * error */ if (curve->piecewise) { double blo, bhi; int curpos = 0; stp_sequence_get_bounds(curve->seq, &blo, &bhi); if (curve->recompute_interval) compute_intervals(curve); for (i = 0; i < old; i++) { double low; double high; double low_y; double high_y; double x_delta; if (!stp_sequence_get_point(curve->seq, i * 2, &low)) { stp_free(new_vec); return 0; } if (i == old - 1) high = 1.0; else if (!stp_sequence_get_point(curve->seq, ((i + 1) * 2), &high)) { stp_free(new_vec); return 0; } if (!stp_sequence_get_point(curve->seq, (i * 2) + 1, &low_y)) { stp_free(new_vec); return 0; } if (!stp_sequence_get_point(curve->seq, ((i + 1) * 2) + 1, &high_y)) { stp_free(new_vec); return 0; } stp_deprintf(STP_DBG_CURVE, "Filling slots at %ld %d: %f %f %f %f %ld\n", (long)i,curpos, high, low, high_y, low_y, (long)limit); x_delta = high - low; high *= (limit - 1); low *= (limit - 1); while (curpos <= high) { double frac = (curpos - low) / (high - low); if (curve->curve_type == STP_CURVE_TYPE_LINEAR) new_vec[curpos] = low_y + frac * (high_y - low_y); else new_vec[curpos] = do_interpolate_spline(low_y, high_y, frac, curve->interval[i], curve->interval[i + 1], x_delta); if (new_vec[curpos] < blo) new_vec[curpos] = blo; if (new_vec[curpos] > bhi) new_vec[curpos] = bhi; stp_deprintf(STP_DBG_CURVE, " Filling slot %d %f %f\n", curpos, frac, new_vec[curpos]); curpos++; } } curve->piecewise = 0; } else { for (i = 0; i < limit; i++) if (curve->gamma) new_vec[i] = interpolate_gamma_internal(curve, ((double) i * (double) old / (double) (limit - 1))); else new_vec[i] = interpolate_point_internal(curve, ((double) i * (double) old / (double) (limit - 1))); } stpi_curve_set_points(curve, points); stp_sequence_set_subrange(curve->seq, 0, limit, new_vec); curve->recompute_interval = 1; stp_free(new_vec); return 1; }
stp_curve_t * stp_curve_create_from_xmltree(stp_mxml_node_t *curve) /* The curve node */ { const char *stmp; /* Temporary string */ stp_mxml_node_t *child; /* Child sequence node */ stp_curve_t *ret = NULL; /* Curve to return */ stp_curve_type_t curve_type; /* Type of curve */ stp_curve_wrap_mode_t wrap_mode; /* Curve wrap mode */ double fgamma; /* Gamma value */ stp_sequence_t *seq = NULL; /* Sequence data */ double low, high; /* Sequence bounds */ int piecewise = 0; stp_xml_init(); /* Get curve type */ stmp = stp_mxmlElementGetAttr(curve, "type"); if (stmp) { if (!strcmp(stmp, "linear")) curve_type = STP_CURVE_TYPE_LINEAR; else if (!strcmp(stmp, "spline")) curve_type = STP_CURVE_TYPE_SPLINE; else { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: %s: \"type\" invalid\n", stmp); goto error; } } else { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: \"type\" missing\n"); goto error; } /* Get curve wrap mode */ stmp = stp_mxmlElementGetAttr(curve, "wrap"); if (stmp) { if (!strcmp(stmp, "nowrap")) wrap_mode = STP_CURVE_WRAP_NONE; else if (!strcmp(stmp, "wrap")) { wrap_mode = STP_CURVE_WRAP_AROUND; } else { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: %s: \"wrap\" invalid\n", stmp); goto error; } } else { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: \"wrap\" missing\n"); goto error; } /* Get curve gamma */ stmp = stp_mxmlElementGetAttr(curve, "gamma"); if (stmp) { fgamma = stp_xmlstrtod(stmp); } else { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: \"gamma\" missing\n"); goto error; } /* If gamma is set, wrap_mode must be STP_CURVE_WRAP_NONE */ if (fgamma && wrap_mode != STP_CURVE_WRAP_NONE) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: " "gamma set and \"wrap\" is not STP_CURVE_WRAP_NONE\n"); goto error; } stmp = stp_mxmlElementGetAttr(curve, "piecewise"); if (stmp && strcmp(stmp, "true") == 0) piecewise = 1; /* Set up the curve */ ret = stp_curve_create(wrap_mode); stp_curve_set_interpolation_type(ret, curve_type); child = stp_mxmlFindElement(curve, curve, "sequence", NULL, NULL, STP_MXML_DESCEND); if (child) seq = stp_sequence_create_from_xmltree(child); if (seq == NULL) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: sequence read failed\n"); goto error; } /* Set curve bounds */ stp_sequence_get_bounds(seq, &low, &high); stp_curve_set_bounds(ret, low, high); if (fgamma) stp_curve_set_gamma(ret, fgamma); else /* Not a gamma curve, so set points */ { size_t seq_count; const double* data; stp_sequence_get_data(seq, &seq_count, &data); if (piecewise) { if ((seq_count % 2) != 0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: invalid data count %ld\n", (long)seq_count); goto error; } if (stp_curve_set_data_points(ret, seq_count / 2, (const stp_curve_point_t *) data) == 0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: failed to set curve data points\n"); goto error; } } else { if (stp_curve_set_data(ret, seq_count, data) == 0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: failed to set curve data\n"); goto error; } } } if (seq) { stp_sequence_destroy(seq); seq = NULL; } /* Validate curve */ if (stpi_curve_check_parameters(ret, stp_curve_count_points(ret)) == 0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: parameter check failed\n"); goto error; } stp_xml_exit(); return ret; error: stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: error during curve read\n"); if (ret) stp_curve_destroy(ret); stp_xml_exit(); return NULL; }
void stp_list_node_free_data (void *item) { stp_free(item); stp_deprintf(STP_DBG_LIST, "stp_list_node_free_data destructor\n"); }
int stp_curve_set_data_points(stp_curve_t *curve, size_t count, const stp_curve_point_t *data) { size_t i; size_t real_count = count; double low, high; double last_x = -1; CHECK_CURVE(curve); if (count < 2) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: too few points %ld\n", (long)count); return 0; } if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) real_count++; if (real_count > curve_point_limit) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: too many points %ld\n", (long)real_count); return 0; } /* Validate the data before we commit to it. */ stp_sequence_get_bounds(curve->seq, &low, &high); for (i = 0; i < count; i++) { if (! isfinite(data[i].y) || data[i].y < low || data[i].y > high) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: datum out of bounds: " "%g (require %g <= x <= %g), n = %ld\n", data[i].y, low, high, (long)i); return 0; } if (i == 0 && data[i].x != 0.0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: first point must have x=0\n"); return 0; } if (curve->wrap_mode == STP_CURVE_WRAP_NONE && i == count - 1 && data[i].x != 1.0) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: last point must have x=1\n"); return 0; } if (curve->wrap_mode == STP_CURVE_WRAP_AROUND && data[i].x >= 1.0 - .000001) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: horizontal value must " "not exceed .99999\n"); return 0; } if (data[i].x < 0 || data[i].x > 1) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: horizontal position out of bounds: " "%g, n = %ld\n", data[i].x, (long)i); return 0; } if (data[i].x - .000001 < last_x) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_set_data_points: horizontal position must " "exceed previous position by .000001: %g, %g, n = %ld\n", data[i].x, last_x, (long)i); return 0; } last_x = data[i].x; } /* Allocate sequence; also accounts for WRAP_MODE */ curve->piecewise = 1; stpi_curve_set_points(curve, count); curve->gamma = 0.0; stp_sequence_set_subrange(curve->seq, 0, count * 2, (const double *) data); if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) { stp_sequence_set_point(curve->seq, count * 2, data[0].x); stp_sequence_set_point(curve->seq, count * 2 + 1, data[0].y); } curve->recompute_interval = 1; return 1; }
stp_mxml_node_t * stp_xmltree_create_from_curve(const stp_curve_t *curve) /* The curve */ { stp_curve_wrap_mode_t wrapmode; stp_curve_type_t interptype; double gammaval, low, high; stp_sequence_t *seq; char *cgamma; stp_mxml_node_t *curvenode = NULL; stp_mxml_node_t *child = NULL; stp_xml_init(); /* Get curve details */ wrapmode = stp_curve_get_wrap(curve); interptype = stp_curve_get_interpolation_type(curve); gammaval = stp_curve_get_gamma(curve); if (gammaval && wrapmode != STP_CURVE_WRAP_NONE) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_xmltree_create_from_curve: " "curve sets gamma and wrap_mode is not STP_CURVE_WRAP_NONE\n"); goto error; } /* Construct the allocated strings required */ stp_asprintf(&cgamma, "%g", gammaval); curvenode = stp_mxmlNewElement(NULL, "curve"); stp_mxmlElementSetAttr(curvenode, "wrap", stpi_wrap_mode_names[wrapmode]); stp_mxmlElementSetAttr(curvenode, "type", stpi_curve_type_names[interptype]); stp_mxmlElementSetAttr(curvenode, "gamma", cgamma); if (curve->piecewise) stp_mxmlElementSetAttr(curvenode, "piecewise", "true"); else stp_mxmlElementSetAttr(curvenode, "piecewise", "false"); stp_free(cgamma); seq = stp_sequence_create(); stp_curve_get_bounds(curve, &low, &high); stp_sequence_set_bounds(seq, low, high); if (gammaval != 0) /* A gamma curve does not require sequence data */ { stp_sequence_set_size(seq, 0); } else { const double *data; size_t count; data = stpi_curve_get_data_internal(curve, &count); stp_sequence_set_data(seq, count, data); } child = stp_xmltree_create_from_sequence(seq); if (seq) { stp_sequence_destroy(seq); seq = NULL; } if (child == NULL) { stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_xmltree_create_from_curve: sequence node is NULL\n"); goto error; } stp_mxmlAdd(curvenode, STP_MXML_ADD_AFTER, NULL, child); stp_xml_exit(); return curvenode; error: stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_xmltree_create_from_curve: error during xmltree creation\n"); if (curvenode) stp_mxmlDelete(curvenode); if (child) stp_mxmlDelete(child); stp_xml_exit(); return NULL; }