diff options
Diffstat (limited to 'src/main/curve.c')
-rw-r--r-- | src/main/curve.c | 114 |
1 files changed, 97 insertions, 17 deletions
diff --git a/src/main/curve.c b/src/main/curve.c index a833376..2aeb15e 100644 --- a/src/main/curve.c +++ b/src/main/curve.c @@ -16,8 +16,7 @@ * for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H @@ -386,6 +385,25 @@ stpi_curve_set_points(stp_curve_t *curve, size_t points) return 1; } +static int +stpi_curve_set_data(stp_curve_t *curve, size_t points, const double *data) +{ + if (points < 2) + return 0; + if (points > curve_point_limit || + (curve->wrap_mode == STP_CURVE_WRAP_AROUND && + points > curve_point_limit - 1)) + return 0; + clear_curve_data(curve); + if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) + points++; + if (curve->piecewise) + points *= 2; + if ((stp_sequence_set_data(curve->seq, points, data)) == 0) + return 0; + return 1; +} + /* * Create a default curve */ @@ -553,7 +571,7 @@ int stp_curve_set_interpolation_type(stp_curve_t *curve, stp_curve_type_t itype) { CHECK_CURVE(curve); - if (itype < 0 || itype >= stpi_curve_type_count) + if (itype >= stpi_curve_type_count) return 0; curve->curve_type = itype; return 1; @@ -1031,7 +1049,7 @@ interpolate_gamma_internal(const stp_curve_t *curve, double where) double blo, bhi; size_t real_point_count; - real_point_count = get_real_point_count(curve);; + real_point_count = get_real_point_count(curve); if (real_point_count) where /= (real_point_count - 1); @@ -1232,20 +1250,61 @@ stp_curve_resample(stp_curve_t *curve, size_t points) } curve->piecewise = 0; } + else if (curve->gamma) + { + double fgamma = curve->gamma; + double blo, bhi; + int negative_gamma = 0; + stp_sequence_get_bounds(curve->seq, &blo, &bhi); + if (fgamma > 0) + { + fgamma = -fgamma; + negative_gamma = 1; + } + for (i = 0; i < limit; i++) + { + double where = ((double) i * (double) old / (double) (limit - 1)); + if (negative_gamma) + where = 1.0 - where; + new_vec[i] = blo + ((bhi - blo) * pow(where, fgamma)); + } + } else { + double blo, bhi; + const double *seq_data; + size_t seq_count; + size_t point_count = get_point_count(curve); + stp_sequence_get_data(curve->seq, &seq_count, &seq_data); + stp_sequence_get_bounds(curve->seq, &blo, &bhi); + if (curve->recompute_interval) + compute_intervals((stpi_cast_safe(curve))); 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); + { + double where = ((double) i * (double) old / (double) (limit - 1)); + int iwhere = (int) where; + double frac = where - (double) iwhere; + if (frac == 0.0) + new_vec[i] = seq_data[iwhere]; + else if (curve->curve_type == STP_CURVE_TYPE_LINEAR) + new_vec[i] = seq_data[iwhere] + (frac * curve->interval[iwhere]); + else + { + int iwhere1 = iwhere + 1; + while (iwhere1 > point_count) + iwhere1 -= point_count; + new_vec[i] = + do_interpolate_spline(seq_data[iwhere], seq_data[iwhere1], + frac, curve->interval[iwhere], + curve->interval[iwhere1], 1.0); + if (new_vec[i] > bhi) + new_vec[i] = bhi; + else if (new_vec[i] < blo) + new_vec[i] = blo; + } + } + } + stpi_curve_set_data(curve, points, new_vec); curve->recompute_interval = 1; stp_free(new_vec); return 1; @@ -1447,6 +1506,9 @@ stp_curve_create_from_xmltree(stp_mxml_node_t *curve) /* The curve node */ int piecewise = 0; stp_xml_init(); + /* FIXME Need protection against unlimited recursion */ + if ((stmp = stp_mxmlElementGetAttr(curve, "src")) != NULL) + return stp_curve_create_from_file(stmp); /* Get curve type */ stmp = stp_mxmlElementGetAttr(curve, "type"); if (stmp) @@ -1518,7 +1580,7 @@ stp_curve_create_from_xmltree(stp_mxml_node_t *curve) /* The curve node */ 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); + child = stp_xml_get_node(curve, "sequence", NULL); if (child) seq = stp_sequence_create_from_xmltree(child); @@ -1590,6 +1652,11 @@ stp_curve_create_from_xmltree(stp_mxml_node_t *curve) /* The curve node */ error: stp_deprintf(STP_DBG_CURVE_ERRORS, "stp_curve_create_from_xmltree: error during curve read\n"); + if (seq) + { + stp_sequence_destroy(seq); + seq = NULL; + } if (ret) stp_curve_destroy(ret); stp_xml_exit(); @@ -1862,7 +1929,20 @@ stp_curve_create_from_file(const char* file) { stp_curve_t *curve = NULL; stp_mxml_node_t *doc; - FILE *fp = fopen(file, "r"); + FILE *fp = NULL; + if (file[0] != '/' && strncmp(file, "./", 2) && strncmp(file, "../", 3)) + { + char *fn = stp_path_find_file(NULL, file); + if (fn) + { + fp = fopen(file, "r"); + free(fn); + } + } + else if (file) + { + fp = fopen(file, "r"); + } if (!fp) { stp_deprintf(STP_DBG_CURVE_ERRORS, |