void stp_dither_set_inks(stp_vars_t *v, int color, double density, double darkness, int nshades, const double *svalues, int ndotsizes, const double *dvalues) { int i, j; stp_shade_t *shades = stp_malloc(sizeof(stp_shade_t) * nshades); stp_dotsize_t *dotsizes = stp_malloc(sizeof(stp_dotsize_t) * ndotsizes); j = 0; for (i = 0; i < ndotsizes; i++) { /* Skip over any zero-valued dot sizes */ if (dvalues[i] > 0) { dotsizes[j].value = dvalues[i]; dotsizes[j].bit_pattern = i + 1; j++; } } for (i = 0; i < nshades; i++) { shades[i].value = svalues[i]; shades[i].numsizes = j; shades[i].dot_sizes = dotsizes; } stp_dither_set_inks_full(v, color, nshades, shades, density, darkness); stp_free(dotsizes); stp_free(shades); }
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; }
void stp_dither_matrix_init_short(stp_dither_matrix_impl_t *mat, int x_size, int y_size, const unsigned short *array, int transpose, int prescaled) { int x, y; mat->base = x_size; mat->exp = 1; mat->x_size = x_size; mat->y_size = y_size; mat->total_size = mat->x_size * mat->y_size; mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size); for (x = 0; x < mat->x_size; x++) for (y = 0; y < mat->y_size; y++) { if (transpose) mat->matrix[x + y * mat->x_size] = array[y + x * mat->y_size]; else mat->matrix[x + y * mat->x_size] = array[x + y * mat->x_size]; if (!prescaled) mat->matrix[x + y * mat->x_size] = (double) mat->matrix[x + y * mat->x_size] * 65536.0 / (double) (mat->x_size * mat->y_size); } mat->last_x = mat->last_x_mod = 0; mat->last_y = mat->last_y_mod = 0; mat->index = 0; mat->i_own = 1; if (is_po2(mat->x_size)) mat->fast_mask = mat->x_size - 1; else mat->fast_mask = 0; }
static void compute_linear_deltas(stp_curve_t *curve) { int i; size_t delta_count; size_t seq_point_count; const double *data; stp_sequence_get_data(curve->seq, &seq_point_count, &data); if (data == NULL) return; delta_count = get_real_point_count(curve); if (delta_count <= 1) /* No intervals can be computed */ return; delta_count--; /* One less than the real point count. Note size_t is unsigned. */ curve->interval = stp_malloc(sizeof(double) * delta_count); for (i = 0; i < delta_count; i++) { if (curve->piecewise) curve->interval[i] = data[(2 * (i + 1)) + 1] - data[(2 * i) + 1]; else curve->interval[i] = data[i + 1] - data[i]; } }
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; }
/* 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_dither_matrix_iterated_init(stp_dither_matrix_impl_t *mat, size_t size, size_t expt, const unsigned *array) { int i; int x, y; mat->base = size; mat->exp = expt; mat->x_size = 1; for (i = 0; i < expt; i++) mat->x_size *= mat->base; mat->y_size = mat->x_size; mat->total_size = mat->x_size * mat->y_size; mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size); for (x = 0; x < mat->x_size; x++) for (y = 0; y < mat->y_size; y++) { mat->matrix[x + y * mat->x_size] = calc_ordered_point(x, y, mat->exp, 1, mat->base, array); mat->matrix[x + y * mat->x_size] = (double) mat->matrix[x + y * mat->x_size] * 65536.0 / (double) (mat->x_size * mat->y_size); } mat->last_x = mat->last_x_mod = 0; mat->last_y = mat->last_y_mod = 0; mat->index = 0; mat->i_own = 1; if (is_po2(mat->x_size)) mat->fast_mask = mat->x_size - 1; else mat->fast_mask = 0; }
static char * c_strndup(const char *s, int n) { char *ret; if (!s || n < 0) { ret = stp_malloc(1); ret[0] = 0; return ret; } else { ret = stp_malloc(n + 1); memcpy(ret, s, n); ret[n] = 0; return ret; } }
static void * copyfunc(const void *item) { const stp_param_string_t *string = (const stp_param_string_t *) (item); stp_param_string_t *new_string = stp_malloc(sizeof(stp_param_string_t)); new_string->name = stp_strdup(string->name); new_string->text = stp_strdup(string->text); return new_string; }
void stp_string_list_add_string_unsafe(stp_string_list_t *list, const char *name, const char *text) { stp_param_string_t *new_string = stp_malloc(sizeof(stp_param_string_t)); new_string->name = stp_strdup(name); new_string->text = stp_strdup(text); stp_list_item_create((stp_list_t *) list, NULL, new_string); }
bitimage_t *bitimage_new(void) { bitimage_t *tmp= (bitimage_t*) stp_malloc (sizeof(bitimage_t)); tmp->buf= 0; tmp->y0= 0; tmp->width= 0; tmp->height= 0; tmp->xmin= 0; tmp->xmax= 0; return tmp; }
scanline_t *scanline_store(scanline_t *line, int y, unsigned char *buf, int size) { if (!line && !(line= scanline_new())) return 0; line->size= size; line->buf= (unsigned char *) stp_malloc (size); memcpy(line->buf,buf,size); rle_info(buf,size,&line->xmin,&line->xmax,&line->width,&line->osize); /* fprintf(stderr,"%d %d %d %d ",size,line->xmin,line->xmax,line->width); */ line->y= y; return line; }
scanline_t* scanline_new(void) { scanline_t* tmp= (scanline_t*) stp_malloc (sizeof(scanline_t)); tmp->size= 0; tmp->osize= 0; tmp->buf= 0; tmp->xmin= 0; tmp->xmax= 0; tmp->width= 0; tmp->y= 0; tmp->next= 0; return tmp; }
char * c_strdup(const char *s) { char *ret; if (!s) { ret = stp_malloc(1); ret[0] = 0; return ret; } else return c_strndup(s, c_strlen(s)); }
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); }
void stp_register_xml_parser(const char *name, stp_xml_parse_func parse_func) { stpi_xml_parse_registry *xmlp; stp_list_item_t *item = stp_list_get_item_by_name(stpi_xml_registry, name); if (item) xmlp = (stpi_xml_parse_registry *) stp_list_item_get_data(item); else { xmlp = stp_malloc(sizeof(stpi_xml_parse_registry)); xmlp->name = stp_strdup(name); stp_list_item_create(stpi_xml_registry, NULL, xmlp); } xmlp->parse_func = parse_func; }
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); }
void stp_dither_matrix_init_from_dither_array(stp_dither_matrix_impl_t *mat, const stp_array_t *array, int transpose) { int x, y; size_t count; const unsigned short *vec; int x_size, y_size; const stp_sequence_t *seq = stp_array_get_sequence(array); stp_array_get_size(array, &x_size, &y_size); vec = stp_sequence_get_ushort_data(seq, &count); mat->base = x_size; mat->exp = 1; if (transpose) { mat->x_size = y_size; mat->y_size = x_size; } else { mat->x_size = x_size; mat->y_size = y_size; } mat->total_size = mat->x_size * mat->y_size; mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size); for (x = 0; x < x_size; x++) for (y = 0; y < y_size; y++) { if (transpose) mat->matrix[y + x * y_size] = vec[x + y * x_size]; else mat->matrix[x + y * x_size] = vec[x + y * x_size]; } mat->last_x = mat->last_x_mod = 0; mat->last_y = mat->last_y_mod = 0; mat->index = 0; mat->i_own = 1; if (is_po2(mat->x_size)) mat->fast_mask = mat->x_size - 1; else mat->fast_mask = 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); }
void stp_dither_matrix_copy(const stp_dither_matrix_impl_t *src, stp_dither_matrix_impl_t *dest) { int x; dest->base = src->base; dest->exp = src->exp; dest->x_size = src->x_size; dest->y_size = src->y_size; dest->total_size = src->total_size; dest->matrix = stp_malloc(sizeof(unsigned) * dest->x_size * dest->y_size); for (x = 0; x < dest->x_size * dest->y_size; x++) dest->matrix[x] = src->matrix[x]; dest->x_offset = 0; dest->y_offset = 0; dest->last_x = 0; dest->last_x_mod = 0; dest->last_y = 0; dest->last_y_mod = 0; dest->index = 0; dest->fast_mask = src->fast_mask; dest->i_own = 1; }
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); }
bitimage_t *scanlines2bitimage(scanline_t *slimg) { bitimage_t *img= 0; scanline_t *sl; int w= 0; int y0= -1; int y= 0; int h; for (sl=slimg; sl!=0; sl=sl->next) { if (sl->width) { if (w<sl->osize) w= sl->osize; if (y0<0) y0= sl->y; y= sl->y; } } h= y-y0+1; if ((!w) || (!h)) return 0; img= bitimage_new(); img->buf= (unsigned char*) stp_malloc(h*w); memset(img->buf,0,h*w); img->width= w; img->height= h; img->y0= y0; for (sl=slimg; sl!=0; sl=sl->next) { y= sl->y- y0; if ((y>=0) && (y<h)) { rle_decode(sl->buf,sl->size,img->buf+y*w,w); } } return img; }
testpattern_t * get_next_testpattern(void) { static int internal_n_testpatterns = 0; if (global_n_testpatterns == -1) { static_testpatterns = stp_malloc(sizeof(testpattern_t)); global_n_testpatterns = 0; internal_n_testpatterns = 1; clear_testpattern(&(static_testpatterns[0])); return &(static_testpatterns[0]); } else if (global_n_testpatterns + 1 >= internal_n_testpatterns) { internal_n_testpatterns *= 2; static_testpatterns = stp_realloc(static_testpatterns, internal_n_testpatterns * sizeof(testpattern_t)); } global_n_testpatterns++; clear_testpattern(&(static_testpatterns[global_n_testpatterns])); return &(static_testpatterns[global_n_testpatterns]); }
void stp_string_list_add_string(stp_string_list_t *list, const char *name, const char *text) { stp_param_string_t *new_string = stp_malloc(sizeof(stp_param_string_t)); do { const char *xname = name; while (*xname) { if (!isalnum(*xname) && *xname != '_' && *xname != '-' && *xname != '+') { stp_erprintf("Gutenprint: bad string %s (%s)\n", name, text); break; } xname++; } } while(0); new_string->name = stp_strdup(name); new_string->text = stp_strdup(text); stp_list_item_create((stp_list_t *) list, NULL, new_string); }
/* * '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; }
/* * 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; }
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); }
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; }