static void free_list_element(void *item) { stp_param_string_t *string = (stp_param_string_t *) (item); stp_free((char *) string->name); stp_free((char *) string->text); stp_free(string); }
static void free_list_element(void *item) { stp_param_string_t *string = (stp_param_string_t *) (item); stp_free(stpi_cast_safe(string->name)); stp_free(stpi_cast_safe(string->text)); stp_free(string); }
void stp_curve_reverse(stp_curve_t *dest, const stp_curve_t *source) { CHECK_CURVE(dest); CHECK_CURVE(source); curve_dtor(dest); dest->curve_type = source->curve_type; dest->wrap_mode = source->wrap_mode; dest->gamma = source->gamma; if (source->piecewise) { const double *source_data; size_t size; double *new_data; int i; stp_sequence_get_data(source->seq, &size, &source_data); new_data = stp_malloc(sizeof(double) * size); for (i = 0; i < size; i += 2) { int j = size - i - 2; new_data[i] = 1.0 - source_data[j]; new_data[i + 1] = source_data[j + 1]; } dest->seq = stp_sequence_create(); stp_sequence_set_data(dest->seq, size, new_data); stp_free(new_data); } else dest->seq = stp_sequence_create_reverse(source->seq); dest->piecewise = source->piecewise; dest->recompute_interval = 1; }
stpi_escp2_printer_t * stp_escp2_get_printer(const stp_vars_t *v) { int model = stp_get_model_id(v); STPI_ASSERT(model >= 0, v); if (!escp2_model_capabilities) { escp2_model_capabilities = stp_zalloc(sizeof(stpi_escp2_printer_t) * (model + 1)); escp2_model_count = model + 1; } else if (model >= escp2_model_count) { escp2_model_capabilities = stp_realloc(escp2_model_capabilities, sizeof(stpi_escp2_printer_t) * (model + 1)); (void) memset(escp2_model_capabilities + escp2_model_count, 0, sizeof(stpi_escp2_printer_t) * (model + 1 - escp2_model_count)); escp2_model_count = model + 1; } if (!(escp2_model_capabilities[model].active)) { #ifdef HAVE_LOCALE_H char *locale = stp_strdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, "C"); #endif escp2_model_capabilities[model].active = 1; stp_escp2_load_model(v, model); #ifdef HAVE_LOCALE_H setlocale(LC_ALL, locale); stp_free(locale); #endif } return &(escp2_model_capabilities[model]); }
void stp_array_destroy(stp_array_t *array) { check_array(array); array_dtor(array); stp_free(array); }
static inkgroup_t * load_inkgroup(const char *name) { stp_list_t *dirlist = stpi_data_path(); stp_list_item_t *item; inkgroup_t *igl = NULL; item = stp_list_get_start(dirlist); while (item) { const char *dn = (const char *) stp_list_item_get_data(item); char *ffn = stpi_path_merge(dn, name); stp_mxml_node_t *inkgroup = stp_mxmlLoadFromFile(NULL, ffn, STP_MXML_NO_CALLBACK); stp_free(ffn); if (inkgroup) { int count = 0; stp_mxml_node_t *node = stp_mxmlFindElement(inkgroup, inkgroup, "escp2InkGroup", NULL, NULL, STP_MXML_DESCEND); if (node) { stp_mxml_node_t *child = node->child; igl = stp_zalloc(sizeof(inkgroup_t)); while (child) { if (child->type == STP_MXML_ELEMENT && !strcmp(child->value.element.name, "InkList")) count++; child = child->next; } igl->n_inklists = count; if (stp_mxmlElementGetAttr(node, "name")) igl->name = stp_strdup(stp_mxmlElementGetAttr(node, "name")); else igl->name = stp_strdup(name); igl->inklists = stp_zalloc(sizeof(inklist_t) * count); child = node->child; count = 0; while (child) { if (child->type == STP_MXML_ELEMENT && !strcmp(child->value.element.name, "InkList")) load_inklist(child, node, &(igl->inklists[count++])); child = child->next; } } stp_mxmlDelete(inkgroup); break; } item = stp_list_item_next(item); } stp_list_destroy(dirlist); return igl; }
/** * Cache a list node by its long name. * @param list the list to use. * @param long_name the long name. * @param cache the node to cache. */ static void set_long_name_cache(stp_list_t *list, const char *long_name, stp_list_item_t *cache) { if (list->long_name_cache) stp_free(list->long_name_cache); list->long_name_cache = NULL; if (long_name) list->long_name_cache = stp_strdup(long_name); list->long_name_cache_node = cache; }
void stp_dither_matrix_destroy(stp_dither_matrix_impl_t *mat) { if (mat->i_own && mat->matrix) stp_free(mat->matrix); mat->matrix = NULL; mat->base = 0; mat->exp = 0; mat->x_size = 0; mat->y_size = 0; mat->total_size = 0; mat->i_own = 0; }
void save2xbm(const char *filename,char col, bitimage_t *img, int xmin, int ymin, int xmax, int ymax) { char *outfilename= (char*) stp_malloc(strlen(filename)+16); FILE *o; int i,j,k,i0,i1,j0,j1,w,h; if (!img) return; if (col) sprintf(outfilename,"%s_%c.xbm",filename,col); else sprintf(outfilename,"%s.xbm",filename); if (!(o= fopen(outfilename,"w"))) { stp_free(outfilename); return; } i0= (ymin>0) ? ymin-img->y0 : 0; i1= (ymax>0) ? ymax-img->y0 : img->height; j0= (xmin>0 && xmin<img->width*8) ? xmin/8 : 0; j1= (xmax>0 && xmax<img->width*8) ? xmax/8 : img->width-1; w= j1-j0+1; h= i1-i0; if (col) fprintf(o,"#define %s_%c_width %d\n#define %s_%c_height %d\nstatic char %s_%c_bits[] = {", outfilename,col,w*8, outfilename,col,h, outfilename,col); else fprintf(o,"#define %s_width %d\n#define %s_height %d\nstatic char %s_bits[] = {", outfilename,w*8, outfilename,h, outfilename); fprintf(stderr,"%d %d %d %d\n",i0,h,j0,w); for (i=i0,k=0; i<i1; i++) { for (j=j0; j<=j1; j++) { if (k%16 == 0) fprintf(o,"\n"); fprintf(o,"0x%02x, ",(i>=0 && i<img->height)? conv(img->buf[i*img->width+j])&0xff : 0); k++; } } fprintf(o," 0x00 };\n"); fclose(o); }
stp_mxml_node_t * stp_xmltree_create_from_array(const stp_array_t *array) /* The array */ { int x_size, y_size; char *xs, *ys; stp_mxml_node_t *arraynode = NULL; stp_mxml_node_t *child = NULL; stp_xml_init(); /* Get array details */ stp_array_get_size(array, &x_size, &y_size); /* Construct the allocated strings required */ stp_asprintf(&xs, "%d", x_size); stp_asprintf(&ys, "%d", y_size); arraynode = stp_mxmlNewElement(NULL, "array"); stp_mxmlElementSetAttr(arraynode, "x-size", xs); stp_mxmlElementSetAttr(arraynode, "y-size", ys); stp_free(xs); stp_free(ys); child = stp_xmltree_create_from_sequence(stp_array_get_sequence(array)); if (child) stp_mxmlAdd(arraynode, STP_MXML_ADD_AFTER, NULL, child); else { stp_mxmlDelete(arraynode); arraynode = NULL; } stp_xml_exit(); return arraynode; }
void stp_dither_matrix_shear(stp_dither_matrix_impl_t *mat, int x_shear, int y_shear) { int i; int j; int *tmp = stp_malloc(mat->x_size * mat->y_size * sizeof(int)); for (i = 0; i < mat->x_size; i++) for (j = 0; j < mat->y_size; j++) MATRIX_POINT(tmp, i, j, mat->x_size, mat->y_size) = MATRIX_POINT(mat->matrix, i, j * (x_shear + 1), mat->x_size, mat->y_size); for (i = 0; i < mat->x_size; i++) for (j = 0; j < mat->y_size; j++) MATRIX_POINT(mat->matrix, i, j, mat->x_size, mat->y_size) = MATRIX_POINT(tmp, i * (y_shear + 1), j, mat->x_size, mat->y_size); stp_free(tmp); }
static void initialize_global_parameters(void) { int i; for (i = 0; i < STP_CHANNEL_LIMIT; i++) { global_levels[i] = 1.0; global_gammas[i] = 1.0; } global_gamma = 1.0; global_steps = 256; global_ink_limit = 1.0; global_noblackline = 0; global_printer_width = 0; global_printer_height = 0; global_band_height = 0; global_n_testpatterns = -1; if (global_printer) free(global_printer); /* Allocated with strdup() */ global_printer = NULL; global_density = 1.0; global_xtop = 0; global_xleft = 0; global_hsize = 1.0; global_vsize = 1.0; global_bit_depth = 16; global_channel_depth = 0; global_image_type = "CMYK"; global_use_raw_cmyk = 0; global_did_something = 0; global_invert_data = 0; if (static_testpatterns) stp_free(static_testpatterns); static_testpatterns = NULL; if (global_vars) stp_vars_destroy(global_vars); global_vars = NULL; if (global_printer) free(global_printer); /* Allocated with strdup() */ global_printer = NULL; start_job = 0; end_job = 0; }
void stp_dither_set_inks_simple(stp_vars_t *v, int color, int nlevels, const double *levels, double density, double darkness) { stp_shade_t s; stp_dotsize_t *d = stp_malloc(nlevels * sizeof(stp_dotsize_t)); int i; s.dot_sizes = d; s.value = 65535.0; s.numsizes = nlevels; for (i = 0; i < nlevels; i++) { d[i].bit_pattern = i + 1; d[i].value = levels[i]; } stp_dither_set_inks_full(v, color, 1, &s, density, darkness); stp_free(d); }
/* 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; }
void stp_escp2_load_model(const stp_vars_t *v, int model) { stp_list_t *dirlist = stpi_data_path(); stp_list_item_t *item; char buf[1024]; int found = 0; stp_xml_init(); sprintf(buf, "escp2/model/model_%d.xml", model); item = stp_list_get_start(dirlist); while (item) { const char *dn = (const char *) stp_list_item_get_data(item); char *fn = stpi_path_merge(dn, buf); stp_mxml_node_t *doc = stp_mxmlLoadFromFile(NULL, fn, STP_MXML_NO_CALLBACK); stp_free(fn); if (doc) { stp_mxml_node_t *node = stp_mxmlFindElement(doc, doc, "escp2:model", NULL, NULL, STP_MXML_DESCEND); if (node) { const char *stmp = stp_mxmlElementGetAttr(node, "id"); STPI_ASSERT(stmp && stp_xmlstrtol(stmp) == model, v); load_model_from_file(v, node, model); found = 1; } stp_mxmlDelete(doc); if (found) break; } item = stp_list_item_next(item); } stp_xml_exit(); stp_list_destroy(dirlist); STPI_ASSERT(found, v); }
/* * Recompute the delta values for interpolation. * When we actually do support spline curves, this routine will * compute the second derivatives for that purpose, too. */ static void compute_intervals(stp_curve_t *curve) { if (curve->interval) { stp_free(curve->interval); curve->interval = NULL; } if (stp_sequence_get_size(curve->seq) > 0) { switch (curve->curve_type) { case STP_CURVE_TYPE_SPLINE: compute_spline_deltas(curve); break; case STP_CURVE_TYPE_LINEAR: compute_linear_deltas(curve); break; } } curve->recompute_interval = 0; }
static void insert_subchannel(stp_vars_t *v, stpi_dither_t *d, int channel, int subchannel) { int i; unsigned oc = d->subchannel_count[channel]; unsigned increment = subchannel - oc + 1; unsigned old_place = d->channel_index[channel] + oc; stpi_dither_channel_t *nc = stp_malloc(sizeof(stpi_dither_channel_t) * (d->total_channel_count + increment)); if (d->channel) { /* * Copy the old channels, including all subchannels of the current * channel that already existed. */ memcpy(nc, d->channel, sizeof(stpi_dither_channel_t) * old_place); if (old_place < d->total_channel_count) /* * If we're inserting a new subchannel in the middle somewhere, * we need to move everything else up */ memcpy(nc + old_place + increment, d->channel + old_place, (sizeof(stpi_dither_channel_t) * (d->total_channel_count - old_place))); stp_free(d->channel); } d->channel = nc; if (channel < d->channel_count - 1) /* Now fix up the subchannel offsets */ for (i = channel + 1; i < d->channel_count; i++) d->channel_index[i] += increment; d->subchannel_count[channel] = subchannel + 1; d->total_channel_count += increment; for (i = oc; i < oc + increment; i++) initialize_channel(v, channel, i); }
/* 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; }
int main(int argc, char **argv) { int status = 0; argv++; while (*argv) { stp_mxml_node_t *top = stp_mxmlLoadFromFile(NULL, *argv, STP_MXML_NO_CALLBACK); if (top) { stp_mxml_node_t *n = top; do { const char *attr = stp_mxmlElementGetAttr(n, "translate"); if (attr) { const char *str = stp_mxmlElementGetAttr(n, attr); char *s; stp_asprintf(&s, "N_(\"%s\");", str); printf("%-40s /* %s */\n", s, *argv); stp_free(s); } n = stp_mxmlWalkNext(n, top, STP_MXML_DESCEND); } while (n); stp_mxmlDelete(top); } else { fprintf(stderr, "Cannot read %s: %s\n", *argv, strerror(errno)); status = 1; } argv++; } return status; }
int stp_curve_compose(stp_curve_t **retval, stp_curve_t *a, stp_curve_t *b, stp_curve_compose_t mode, int points) { stp_curve_t *ret; double *tmp_data; double gamma_a = stp_curve_get_gamma(a); double gamma_b = stp_curve_get_gamma(b); unsigned points_a = stp_curve_count_points(a); unsigned points_b = stp_curve_count_points(b); double alo, ahi, blo, bhi; if (a->piecewise && b->piecewise) return 0; if (a->piecewise) { stp_curve_t *a_save = a; a = stp_curve_create_copy(a_save); stp_curve_resample(a, stp_curve_count_points(b)); } if (b->piecewise) { stp_curve_t *b_save = b; b = stp_curve_create_copy(b_save); stp_curve_resample(b, stp_curve_count_points(a)); } if (mode != STP_CURVE_COMPOSE_ADD && mode != STP_CURVE_COMPOSE_MULTIPLY) return 0; if (stp_curve_get_wrap(a) != stp_curve_get_wrap(b)) return 0; stp_curve_get_bounds(a, &alo, &ahi); stp_curve_get_bounds(b, &blo, &bhi); if (mode == STP_CURVE_COMPOSE_MULTIPLY && (alo < 0 || blo < 0)) return 0; if (stp_curve_get_wrap(a) == STP_CURVE_WRAP_AROUND) { points_a++; points_b++; } if (points == -1) { points = lcm(points_a, points_b); if (stp_curve_get_wrap(a) == STP_CURVE_WRAP_AROUND) points--; } if (points < 2 || points > curve_point_limit || ((stp_curve_get_wrap(a) == STP_CURVE_WRAP_AROUND) && points > curve_point_limit - 1)) return 0; if (gamma_a && gamma_b && gamma_a * gamma_b > 0 && mode == STP_CURVE_COMPOSE_MULTIPLY) return create_gamma_curve(retval, alo * blo, ahi * bhi, gamma_a + gamma_b, points); tmp_data = stp_malloc(sizeof(double) * points); if (!interpolate_points(a, b, mode, points, tmp_data)) { stp_free(tmp_data); return 0; } ret = stp_curve_create(stp_curve_get_wrap(a)); if (mode == STP_CURVE_COMPOSE_ADD) { stp_curve_rescale(ret, (ahi - alo) + (bhi - blo), STP_CURVE_COMPOSE_MULTIPLY, STP_CURVE_BOUNDS_RESCALE); stp_curve_rescale(ret, alo + blo, STP_CURVE_COMPOSE_ADD, STP_CURVE_BOUNDS_RESCALE); } else { stp_curve_rescale(ret, (ahi - alo) * (bhi - blo), STP_CURVE_COMPOSE_MULTIPLY, STP_CURVE_BOUNDS_RESCALE); stp_curve_rescale(ret, alo * blo, STP_CURVE_COMPOSE_ADD, STP_CURVE_BOUNDS_RESCALE); } if (! stp_curve_set_data(ret, points, tmp_data)) goto bad1; *retval = ret; stp_free(tmp_data); return 1; bad1: stp_curve_destroy(ret); stp_free(tmp_data); return 0; }
/* * 'escp2_print()' - Print an image to an EPSON printer. */ static int raw_print(const stp_vars_t *v, stp_image_t *image) { int model = stp_get_model_id(v); int width = stp_get_page_width(v); int height = stp_get_page_height(v); int i, j; int y; /* Looping vars */ stp_vars_t *nv = stp_vars_create_copy(v); int out_channels; unsigned short *final_out = NULL; int status = 1; int bytes_per_channel = raw_model_capabilities[model].output_bits / 8; int ink_channels = 1; int rotate_output = 0; const char *ink_type = stp_get_string_parameter(nv, "InkType"); stp_image_init(image); stp_prune_inactive_options(nv); if (!stp_verify(nv)) { stp_eprintf(nv, _("Print options not verified; cannot print.\n")); stp_vars_destroy(nv); stp_image_conclude(image); return 0; } if (width != stp_image_width(image) || height != stp_image_height(image)) { stp_eprintf(nv, _("Image dimensions must match paper dimensions")); stp_vars_destroy(nv); stp_image_conclude(image); return 0; } if (ink_type) { for (i = 0; i < ink_count; i++) if (strcmp(ink_type, inks[i].name) == 0) { stp_set_string_parameter(nv, "STPIOutputType", inks[i].output_type); ink_channels = inks[i].output_channels; rotate_output = inks[i].rotate_channels; break; } } stp_set_float_parameter(nv, "Density", 1.0); stp_set_boolean_parameter(nv, "SimpleGamma", 1); stp_channel_reset(nv); for (i = 0; i < ink_channels; i++) stp_channel_add(nv, i, 0, 1.0); if (bytes_per_channel == 1) out_channels = stp_color_init(nv, image, 256); else out_channels = stp_color_init(nv, image, 65536); if (out_channels != ink_channels && out_channels != 1 && ink_channels != 1) { stp_eprintf(nv, "Internal error! Output channels or input channels must be 1\n"); stp_vars_destroy(nv); stp_image_conclude(image); return 0; } if (out_channels != ink_channels) final_out = stp_malloc(width * ink_channels * 2); for (y = 0; y < height; y++) { unsigned short *out; unsigned short *real_out; unsigned zero_mask; if (stp_color_get_row(nv, image, y, &zero_mask)) { status = 2; break; } out = stp_channel_get_input(nv); real_out = out; if (rotate_output) { unsigned short *tmp_out = real_out; for (i = 0; i < width; i++) { unsigned short tmp = tmp_out[0]; for (j = 0; j < ink_channels - 1; j++) tmp_out[j] = tmp_out[j + 1]; tmp_out[ink_channels - 1] = tmp; tmp_out += ink_channels; } } if (out_channels != ink_channels) { real_out = final_out; if (out_channels < ink_channels) { for (i = 0; i < width; i++) { for (j = 0; j < ink_channels; j++) final_out[i * ink_channels + j] = out[i]; } } else { for (i = 0; i < width; i++) { int avg = 0; for (j = 0; j < out_channels; j++) avg += out[i * out_channels + j]; final_out[i] = avg / out_channels; } } } if (bytes_per_channel == 1) { unsigned char *char_out = (unsigned char *) real_out; for (i = 0; i < width * ink_channels; i++) char_out[i] = real_out[i] / 257; } stp_zfwrite((char *) real_out, width * ink_channels * bytes_per_channel, 1, nv); } stp_image_conclude(image); if (final_out) stp_free(final_out); stp_vars_destroy(nv); return status; }
static void xml_preload_freefunc(void *item) { stp_free(item); }
/* * 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; }
int stp_curve_rescale(stp_curve_t *curve, double scale, stp_curve_compose_t mode, stp_curve_bounds_t bounds_mode) { int i; double nblo; double nbhi; size_t count; CHECK_CURVE(curve); stp_sequence_get_bounds(curve->seq, &nblo, &nbhi); if (bounds_mode == STP_CURVE_BOUNDS_RESCALE) { switch (mode) { case STP_CURVE_COMPOSE_ADD: nblo += scale; nbhi += scale; break; case STP_CURVE_COMPOSE_MULTIPLY: if (scale < 0) { double tmp = nblo * scale; nblo = nbhi * scale; nbhi = tmp; } else { nblo *= scale; nbhi *= scale; } break; case STP_CURVE_COMPOSE_EXPONENTIATE: if (scale == 0.0) return 0; if (nblo < 0) return 0; nblo = pow(nblo, scale); nbhi = pow(nbhi, scale); break; default: return 0; } } if (! isfinite(nbhi) || ! isfinite(nblo)) return 0; count = get_point_count(curve); if (count) { double *tmp; size_t scount; int stride = 1; int offset = 0; const double *data; if (curve->piecewise) { stride = 2; offset = 1; } stp_sequence_get_data(curve->seq, &scount, &data); tmp = stp_malloc(sizeof(double) * scount); memcpy(tmp, data, scount * sizeof(double)); for (i = offset; i < scount; i += stride) { switch (mode) { case STP_CURVE_COMPOSE_ADD: tmp[i] = tmp[i] + scale; break; case STP_CURVE_COMPOSE_MULTIPLY: tmp[i] = tmp[i] * scale; break; case STP_CURVE_COMPOSE_EXPONENTIATE: tmp[i] = pow(tmp[i], scale); break; } if (tmp[i] > nbhi || tmp[i] < nblo) { if (bounds_mode == STP_CURVE_BOUNDS_ERROR) { stp_free(tmp); return(0); } else if (tmp[i] > nbhi) tmp[i] = nbhi; else tmp[i] = nblo; } } stp_sequence_set_bounds(curve->seq, nblo, nbhi); curve->gamma = 0.0; stpi_curve_set_points(curve, count); stp_sequence_set_subrange(curve->seq, 0, scount, tmp); stp_free(tmp); curve->recompute_interval = 1; invalidate_auxiliary_data(curve); } return 1; }
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_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; }
void stp_curve_destroy(stp_curve_t *curve) { curve_dtor(curve); stp_free(curve); }
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; }
static void compute_spline_deltas_dense(stp_curve_t *curve) { int i; int k; double *u; double *y2; const double *y; 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, &y); 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); int ip1 = (i + 1); int im1a = im1 % point_count; int ia = i % point_count; int ip1a = ip1 % point_count; sig = (i - im1) / (ip1 - im1); p = sig * y2a[im1] + 2.0; y2a[i] = (sig - 1.0) / p; ua[i] = y[ip1a] - 2 * y[ia] + y[im1a]; ua[i] = 3.0 * ua[i] - 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 * (y[1] - y[0]); for (i = 1; i < count; i++) { int im1 = (i - 1); int ip1 = (i + 1); sig = (i - im1) / (ip1 - im1); p = sig * y2[im1] + 2.0; y2[i] = (sig - 1.0) / p; u[i] = y[ip1] - 2 * y[i] + y[im1]; u[i] = 3.0 * u[i] - sig * u[im1] / p; } u[count] = 2 * (y[count] - y[count - 1]); 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); }
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); }