curvedraw

changeset 8:8bf96e11ed1f

curves file format parsing (untested)
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 19 Dec 2015 08:00:09 +0200
parents 6e980fddbf3b
children c2008ba88d03
files src/curvefile.cc
diffstat 1 files changed, 134 insertions(+), 3 deletions(-) [+]
line diff
     1.1 --- a/src/curvefile.cc	Fri Dec 18 07:07:19 2015 +0200
     1.2 +++ b/src/curvefile.cc	Sat Dec 19 08:00:09 2015 +0200
     1.3 @@ -1,4 +1,6 @@
     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 @@ -15,7 +17,7 @@
    1.11  
    1.12  bool save_curves(FILE *fp, const Curve * const *curves, int count)
    1.13  {
    1.14 -	fprintf(stderr, "GCURVES\ncount %d\n", count);
    1.15 +	fprintf(stderr, "GCURVES\n");
    1.16  
    1.17  	for(int i=0; i<count; i++) {
    1.18  		if(!save_curve(fp, curves[i])) {
    1.19 @@ -53,7 +55,7 @@
    1.20  
    1.21  Curve **load_curves(const char *fname, int *countret)
    1.22  {
    1.23 -	FILE *fp = fopen(fname, "rb");
    1.24 +	FILE *fp = fopen(fname, "r");
    1.25  	if(!fp) return false;
    1.26  
    1.27  	Curve **res = load_curves(fp, countret);
    1.28 @@ -61,8 +63,137 @@
    1.29  	return res;
    1.30  }
    1.31  
    1.32 +static std::string next_token(FILE *fp)
    1.33 +{
    1.34 +	std::string s;
    1.35 +	int c;
    1.36 +	while((c = fgetc(fp)) != -1 && isspace(c));	// skip whitespace
    1.37 +	if(feof(fp)) return s;
    1.38 +	while((c = fgetc(fp)) != -1 && !isspace(c)) {
    1.39 +		s.push_back(c);
    1.40 +	}
    1.41 +	return s;
    1.42 +}
    1.43 +
    1.44 +static bool expect_str(FILE *fp, const char *s)
    1.45 +{
    1.46 +	std::string tok = next_token(fp);
    1.47 +	if(tok != std::string(s)) {
    1.48 +		if(!(tok.empty() && feof(fp))) {
    1.49 +			fprintf(stderr, "expected: %s\n", s);
    1.50 +		}
    1.51 +		return false;
    1.52 +	}
    1.53 +	return true;
    1.54 +}
    1.55 +
    1.56 +static bool expect_float(FILE *fp, float *ret)
    1.57 +{
    1.58 +	std::string tok = next_token(fp);
    1.59 +	const char *cs = tok.c_str();
    1.60 +	char *endp;
    1.61 +	*ret = strtod(cs, &endp);
    1.62 +	if(endp != cs + tok.length()) {
    1.63 +		if(!(tok.empty() && feof(fp))) {
    1.64 +			fprintf(stderr, "number expected\n");
    1.65 +		}
    1.66 +		return false;
    1.67 +	}
    1.68 +	return true;
    1.69 +}
    1.70 +
    1.71 +static bool expect_int(FILE *fp, int *ret)
    1.72 +{
    1.73 +	std::string tok = next_token(fp);
    1.74 +	const char *cs = tok.c_str();
    1.75 +	char *endp;
    1.76 +	*ret = strtol(cs, &endp, 0);
    1.77 +	if(endp != cs + tok.length()) {
    1.78 +		if(!(tok.empty() && feof(fp))) {
    1.79 +			fprintf(stderr, "integer expected\n");
    1.80 +		}
    1.81 +		return false;
    1.82 +	}
    1.83 +	return true;
    1.84 +}
    1.85 +
    1.86 +static Curve *curve_block(FILE *fp)
    1.87 +{
    1.88 +	if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
    1.89 +		return 0;
    1.90 +	}
    1.91 +
    1.92 +	Curve *curve = new Curve;
    1.93 +	int cpcount = -1;
    1.94 +	std::string tok;
    1.95 +	while(!(tok = next_token(fp)).empty() && tok != "}") {
    1.96 +		if(tok == "cpcount") {
    1.97 +			if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
    1.98 +				goto err;
    1.99 +			}
   1.100 +		} else if(tok == "type") {
   1.101 +			tok = next_token(fp);
   1.102 +			if(tok == "polyline") {
   1.103 +				curve->set_type(CURVE_LINEAR);
   1.104 +			} else if(tok == "hermite") {
   1.105 +				curve->set_type(CURVE_HERMITE);
   1.106 +			} else if(tok == "bspline") {
   1.107 +				curve->set_type(CURVE_BSPLINE);
   1.108 +			} else {
   1.109 +				goto err;
   1.110 +			}
   1.111 +		} else {
   1.112 +			if(!expect_str(fp, "cp")) {
   1.113 +				goto err;
   1.114 +			}
   1.115 +			Vector3 cp;
   1.116 +			for(int i=0; i<3; i++) {
   1.117 +				if(!expect_float(fp, &cp[i])) {
   1.118 +					goto err;
   1.119 +				}
   1.120 +			}
   1.121 +			curve->add_point(Vector2(cp.x, cp.y), cp.z);
   1.122 +		}
   1.123 +	}
   1.124 +
   1.125 +	if(curve->size() != cpcount) {
   1.126 +		fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
   1.127 +	}
   1.128 +
   1.129 +	return curve;
   1.130 +err:
   1.131 +	fprintf(stderr, "failed to parse curve block\n");
   1.132 +	delete curve;
   1.133 +	return 0;
   1.134 +}
   1.135 +
   1.136  Curve **load_curves(FILE *fp, int *countret)
   1.137  {
   1.138 -	return 0;	// TODO
   1.139 +	if(!expect_str(fp, "GCURVES")) {
   1.140 +		fprintf(stderr, "load_curves: failed to load, invalid file format\n");
   1.141 +		return 0;
   1.142 +	}
   1.143 +
   1.144 +	std::vector<Curve*> curves;
   1.145 +	Curve *curve;
   1.146 +
   1.147 +	while((curve = curve_block(fp))) {
   1.148 +		curves.push_back(curve);
   1.149 +	}
   1.150 +
   1.151 +	int ncurves = (int)curves.size();
   1.152 +	if(!feof(fp)) {
   1.153 +		for(int i=0; i<ncurves; i++) {
   1.154 +			delete curves[i];
   1.155 +		}
   1.156 +		return 0;
   1.157 +	}
   1.158 +
   1.159 +	Curve **carr = new Curve*[ncurves];
   1.160 +	for(int i=0; i<ncurves; i++) {
   1.161 +		carr[i] = curves[i];
   1.162 +	}
   1.163 +	*countret = ncurves;
   1.164 +	return carr;
   1.165  }
   1.166