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 +