curvedraw

diff src/curvefile.cc @ 15:37ab3a4c02f8

merged
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 20 Dec 2015 09:06:04 +0200
parents 84a647283237
children 7f795f7fecd6
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/curvefile.cc	Sun Dec 20 09:06:04 2015 +0200
     1.3 @@ -0,0 +1,204 @@
     1.4 +#include <stdlib.h>
     1.5 +#include <ctype.h>
     1.6 +#include <string>
     1.7 +#include "curvefile.h"
     1.8 +
     1.9 +static bool save_curve(FILE *fp, const Curve *curve);
    1.10 +
    1.11 +bool save_curves(const char *fname, const Curve * const *curves, int count)
    1.12 +{
    1.13 +	FILE *fp = fopen(fname, "wb");
    1.14 +	if(!fp) return false;
    1.15 +
    1.16 +	bool res = save_curves(fp, curves, count);
    1.17 +	fclose(fp);
    1.18 +	return res;
    1.19 +}
    1.20 +
    1.21 +bool save_curves(FILE *fp, const Curve * const *curves, int count)
    1.22 +{
    1.23 +	fprintf(fp, "GCURVES\n");
    1.24 +
    1.25 +	for(int i=0; i<count; i++) {
    1.26 +		if(!save_curve(fp, curves[i])) {
    1.27 +			return false;
    1.28 +		}
    1.29 +	}
    1.30 +	return true;
    1.31 +}
    1.32 +
    1.33 +static const char *curve_type_str(CurveType type)
    1.34 +{
    1.35 +	switch(type) {
    1.36 +	case CURVE_LINEAR:
    1.37 +		return "polyline";
    1.38 +	case CURVE_HERMITE:
    1.39 +		return "hermite";
    1.40 +	case CURVE_BSPLINE:
    1.41 +		return "bspline";
    1.42 +	}
    1.43 +	abort();
    1.44 +}
    1.45 +
    1.46 +static bool save_curve(FILE *fp, const Curve *curve)
    1.47 +{
    1.48 +	fprintf(fp, "curve {\n");
    1.49 +	fprintf(fp, "    type %s\n", curve_type_str(curve->get_type()));
    1.50 +	fprintf(fp, "    cpcount %d\n", curve->size());
    1.51 +	for(int i=0; i<curve->size(); i++) {
    1.52 +		Vector4 cp = curve->get_point(i);
    1.53 +		fprintf(fp, "    cp %g %g %g %g\n", cp.x, cp.y, cp.z, cp.w);
    1.54 +	}
    1.55 +	fprintf(fp, "}\n");
    1.56 +	return true;
    1.57 +}
    1.58 +
    1.59 +std::list<Curve*> load_curves(const char *fname)
    1.60 +{
    1.61 +	std::list<Curve*> res;
    1.62 +	FILE *fp = fopen(fname, "r");
    1.63 +	if(!fp) return res;
    1.64 +
    1.65 +	res = load_curves(fp);
    1.66 +	fclose(fp);
    1.67 +	return res;
    1.68 +}
    1.69 +
    1.70 +static std::string next_token(FILE *fp)
    1.71 +{
    1.72 +	std::string s;
    1.73 +	int c;
    1.74 +	while((c = fgetc(fp)) != -1) {
    1.75 +		if(!isspace(c)) {
    1.76 +			ungetc(c, fp);
    1.77 +			break;
    1.78 +		}
    1.79 +	}
    1.80 +
    1.81 +	if(feof(fp)) return s;
    1.82 +	while((c = fgetc(fp)) != -1) {
    1.83 +		if(isspace(c)) {
    1.84 +			ungetc(c, fp);
    1.85 +			break;
    1.86 +		}
    1.87 +		s.push_back(c);
    1.88 +	}
    1.89 +	return s;
    1.90 +}
    1.91 +
    1.92 +static bool expect_str(FILE *fp, const char *s)
    1.93 +{
    1.94 +	std::string tok = next_token(fp);
    1.95 +	if(tok != std::string(s)) {
    1.96 +		if(tok.empty() && feof(fp)) {
    1.97 +			fprintf(stderr, "expected: %s\n", s);
    1.98 +		}
    1.99 +		return false;
   1.100 +	}
   1.101 +	return true;
   1.102 +}
   1.103 +
   1.104 +static bool expect_float(FILE *fp, float *ret)
   1.105 +{
   1.106 +	std::string tok = next_token(fp);
   1.107 +	const char *cs = tok.c_str();
   1.108 +	char *endp;
   1.109 +	*ret = strtod(cs, &endp);
   1.110 +	if(endp != cs + tok.length()) {
   1.111 +		if(!(tok.empty() && feof(fp))) {
   1.112 +			fprintf(stderr, "number expected\n");
   1.113 +		}
   1.114 +		return false;
   1.115 +	}
   1.116 +	return true;
   1.117 +}
   1.118 +
   1.119 +static bool expect_int(FILE *fp, int *ret)
   1.120 +{
   1.121 +	std::string tok = next_token(fp);
   1.122 +	const char *cs = tok.c_str();
   1.123 +	char *endp;
   1.124 +	*ret = strtol(cs, &endp, 0);
   1.125 +	if(endp != cs + tok.length()) {
   1.126 +		if(!(tok.empty() && feof(fp))) {
   1.127 +			fprintf(stderr, "integer expected\n");
   1.128 +		}
   1.129 +		return false;
   1.130 +	}
   1.131 +	return true;
   1.132 +}
   1.133 +
   1.134 +static Curve *curve_block(FILE *fp)
   1.135 +{
   1.136 +	if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
   1.137 +		return 0;
   1.138 +	}
   1.139 +
   1.140 +	Curve *curve = new Curve;
   1.141 +	int cpcount = -1;
   1.142 +	std::string tok;
   1.143 +	while(!(tok = next_token(fp)).empty() && tok != "}") {
   1.144 +		if(tok == "cpcount") {
   1.145 +			if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
   1.146 +				goto err;
   1.147 +			}
   1.148 +		} else if(tok == "type") {
   1.149 +			tok = next_token(fp);
   1.150 +			if(tok == "polyline") {
   1.151 +				curve->set_type(CURVE_LINEAR);
   1.152 +			} else if(tok == "hermite") {
   1.153 +				curve->set_type(CURVE_HERMITE);
   1.154 +			} else if(tok == "bspline") {
   1.155 +				curve->set_type(CURVE_BSPLINE);
   1.156 +			} else {
   1.157 +				goto err;
   1.158 +			}
   1.159 +		} else {
   1.160 +			if(tok != "cp") {
   1.161 +				goto err;
   1.162 +			}
   1.163 +			Vector4 cp;
   1.164 +			for(int i=0; i<4; i++) {
   1.165 +				if(!expect_float(fp, &cp[i])) {
   1.166 +					goto err;
   1.167 +				}
   1.168 +			}
   1.169 +			curve->add_point(Vector3(cp.x, cp.y, cp.z), cp.w);
   1.170 +		}
   1.171 +	}
   1.172 +
   1.173 +	if(curve->size() != cpcount) {
   1.174 +		fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
   1.175 +	}
   1.176 +
   1.177 +	return curve;
   1.178 +err:
   1.179 +	fprintf(stderr, "failed to parse curve block\n");
   1.180 +	delete curve;
   1.181 +	return 0;
   1.182 +}
   1.183 +
   1.184 +std::list<Curve*> load_curves(FILE *fp)
   1.185 +{
   1.186 +	std::list<Curve*> curves;
   1.187 +	if(!expect_str(fp, "GCURVES")) {
   1.188 +		fprintf(stderr, "load_curves: failed to load, invalid file format\n");
   1.189 +		return curves;
   1.190 +	}
   1.191 +
   1.192 +	Curve *curve;
   1.193 +	while((curve = curve_block(fp))) {
   1.194 +		curves.push_back(curve);
   1.195 +	}
   1.196 +
   1.197 +	if(!feof(fp)) {
   1.198 +		std::list<Curve*>::iterator it = curves.begin();
   1.199 +		while(it != curves.end()) {
   1.200 +			delete *it++;
   1.201 +		}
   1.202 +		return curves;
   1.203 +	}
   1.204 +
   1.205 +	return curves;
   1.206 +}
   1.207 +