curvedraw

annotate 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
rev   line source
nuclear@15 1 #include <stdlib.h>
nuclear@15 2 #include <ctype.h>
nuclear@15 3 #include <string>
nuclear@15 4 #include "curvefile.h"
nuclear@15 5
nuclear@15 6 static bool save_curve(FILE *fp, const Curve *curve);
nuclear@15 7
nuclear@15 8 bool save_curves(const char *fname, const Curve * const *curves, int count)
nuclear@15 9 {
nuclear@15 10 FILE *fp = fopen(fname, "wb");
nuclear@15 11 if(!fp) return false;
nuclear@15 12
nuclear@15 13 bool res = save_curves(fp, curves, count);
nuclear@15 14 fclose(fp);
nuclear@15 15 return res;
nuclear@15 16 }
nuclear@15 17
nuclear@15 18 bool save_curves(FILE *fp, const Curve * const *curves, int count)
nuclear@15 19 {
nuclear@15 20 fprintf(fp, "GCURVES\n");
nuclear@15 21
nuclear@15 22 for(int i=0; i<count; i++) {
nuclear@15 23 if(!save_curve(fp, curves[i])) {
nuclear@15 24 return false;
nuclear@15 25 }
nuclear@15 26 }
nuclear@15 27 return true;
nuclear@15 28 }
nuclear@15 29
nuclear@15 30 static const char *curve_type_str(CurveType type)
nuclear@15 31 {
nuclear@15 32 switch(type) {
nuclear@15 33 case CURVE_LINEAR:
nuclear@15 34 return "polyline";
nuclear@15 35 case CURVE_HERMITE:
nuclear@15 36 return "hermite";
nuclear@15 37 case CURVE_BSPLINE:
nuclear@15 38 return "bspline";
nuclear@15 39 }
nuclear@15 40 abort();
nuclear@15 41 }
nuclear@15 42
nuclear@15 43 static bool save_curve(FILE *fp, const Curve *curve)
nuclear@15 44 {
nuclear@15 45 fprintf(fp, "curve {\n");
nuclear@15 46 fprintf(fp, " type %s\n", curve_type_str(curve->get_type()));
nuclear@15 47 fprintf(fp, " cpcount %d\n", curve->size());
nuclear@15 48 for(int i=0; i<curve->size(); i++) {
nuclear@15 49 Vector4 cp = curve->get_point(i);
nuclear@15 50 fprintf(fp, " cp %g %g %g %g\n", cp.x, cp.y, cp.z, cp.w);
nuclear@15 51 }
nuclear@15 52 fprintf(fp, "}\n");
nuclear@15 53 return true;
nuclear@15 54 }
nuclear@15 55
nuclear@15 56 std::list<Curve*> load_curves(const char *fname)
nuclear@15 57 {
nuclear@15 58 std::list<Curve*> res;
nuclear@15 59 FILE *fp = fopen(fname, "r");
nuclear@15 60 if(!fp) return res;
nuclear@15 61
nuclear@15 62 res = load_curves(fp);
nuclear@15 63 fclose(fp);
nuclear@15 64 return res;
nuclear@15 65 }
nuclear@15 66
nuclear@15 67 static std::string next_token(FILE *fp)
nuclear@15 68 {
nuclear@15 69 std::string s;
nuclear@15 70 int c;
nuclear@15 71 while((c = fgetc(fp)) != -1) {
nuclear@15 72 if(!isspace(c)) {
nuclear@15 73 ungetc(c, fp);
nuclear@15 74 break;
nuclear@15 75 }
nuclear@15 76 }
nuclear@15 77
nuclear@15 78 if(feof(fp)) return s;
nuclear@15 79 while((c = fgetc(fp)) != -1) {
nuclear@15 80 if(isspace(c)) {
nuclear@15 81 ungetc(c, fp);
nuclear@15 82 break;
nuclear@15 83 }
nuclear@15 84 s.push_back(c);
nuclear@15 85 }
nuclear@15 86 return s;
nuclear@15 87 }
nuclear@15 88
nuclear@15 89 static bool expect_str(FILE *fp, const char *s)
nuclear@15 90 {
nuclear@15 91 std::string tok = next_token(fp);
nuclear@15 92 if(tok != std::string(s)) {
nuclear@15 93 if(tok.empty() && feof(fp)) {
nuclear@15 94 fprintf(stderr, "expected: %s\n", s);
nuclear@15 95 }
nuclear@15 96 return false;
nuclear@15 97 }
nuclear@15 98 return true;
nuclear@15 99 }
nuclear@15 100
nuclear@15 101 static bool expect_float(FILE *fp, float *ret)
nuclear@15 102 {
nuclear@15 103 std::string tok = next_token(fp);
nuclear@15 104 const char *cs = tok.c_str();
nuclear@15 105 char *endp;
nuclear@15 106 *ret = strtod(cs, &endp);
nuclear@15 107 if(endp != cs + tok.length()) {
nuclear@15 108 if(!(tok.empty() && feof(fp))) {
nuclear@15 109 fprintf(stderr, "number expected\n");
nuclear@15 110 }
nuclear@15 111 return false;
nuclear@15 112 }
nuclear@15 113 return true;
nuclear@15 114 }
nuclear@15 115
nuclear@15 116 static bool expect_int(FILE *fp, int *ret)
nuclear@15 117 {
nuclear@15 118 std::string tok = next_token(fp);
nuclear@15 119 const char *cs = tok.c_str();
nuclear@15 120 char *endp;
nuclear@15 121 *ret = strtol(cs, &endp, 0);
nuclear@15 122 if(endp != cs + tok.length()) {
nuclear@15 123 if(!(tok.empty() && feof(fp))) {
nuclear@15 124 fprintf(stderr, "integer expected\n");
nuclear@15 125 }
nuclear@15 126 return false;
nuclear@15 127 }
nuclear@15 128 return true;
nuclear@15 129 }
nuclear@15 130
nuclear@15 131 static Curve *curve_block(FILE *fp)
nuclear@15 132 {
nuclear@15 133 if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
nuclear@15 134 return 0;
nuclear@15 135 }
nuclear@15 136
nuclear@15 137 Curve *curve = new Curve;
nuclear@15 138 int cpcount = -1;
nuclear@15 139 std::string tok;
nuclear@15 140 while(!(tok = next_token(fp)).empty() && tok != "}") {
nuclear@15 141 if(tok == "cpcount") {
nuclear@15 142 if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
nuclear@15 143 goto err;
nuclear@15 144 }
nuclear@15 145 } else if(tok == "type") {
nuclear@15 146 tok = next_token(fp);
nuclear@15 147 if(tok == "polyline") {
nuclear@15 148 curve->set_type(CURVE_LINEAR);
nuclear@15 149 } else if(tok == "hermite") {
nuclear@15 150 curve->set_type(CURVE_HERMITE);
nuclear@15 151 } else if(tok == "bspline") {
nuclear@15 152 curve->set_type(CURVE_BSPLINE);
nuclear@15 153 } else {
nuclear@15 154 goto err;
nuclear@15 155 }
nuclear@15 156 } else {
nuclear@15 157 if(tok != "cp") {
nuclear@15 158 goto err;
nuclear@15 159 }
nuclear@15 160 Vector4 cp;
nuclear@15 161 for(int i=0; i<4; i++) {
nuclear@15 162 if(!expect_float(fp, &cp[i])) {
nuclear@15 163 goto err;
nuclear@15 164 }
nuclear@15 165 }
nuclear@15 166 curve->add_point(Vector3(cp.x, cp.y, cp.z), cp.w);
nuclear@15 167 }
nuclear@15 168 }
nuclear@15 169
nuclear@15 170 if(curve->size() != cpcount) {
nuclear@15 171 fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
nuclear@15 172 }
nuclear@15 173
nuclear@15 174 return curve;
nuclear@15 175 err:
nuclear@15 176 fprintf(stderr, "failed to parse curve block\n");
nuclear@15 177 delete curve;
nuclear@15 178 return 0;
nuclear@15 179 }
nuclear@15 180
nuclear@15 181 std::list<Curve*> load_curves(FILE *fp)
nuclear@15 182 {
nuclear@15 183 std::list<Curve*> curves;
nuclear@15 184 if(!expect_str(fp, "GCURVES")) {
nuclear@15 185 fprintf(stderr, "load_curves: failed to load, invalid file format\n");
nuclear@15 186 return curves;
nuclear@15 187 }
nuclear@15 188
nuclear@15 189 Curve *curve;
nuclear@15 190 while((curve = curve_block(fp))) {
nuclear@15 191 curves.push_back(curve);
nuclear@15 192 }
nuclear@15 193
nuclear@15 194 if(!feof(fp)) {
nuclear@15 195 std::list<Curve*>::iterator it = curves.begin();
nuclear@15 196 while(it != curves.end()) {
nuclear@15 197 delete *it++;
nuclear@15 198 }
nuclear@15 199 return curves;
nuclear@15 200 }
nuclear@15 201
nuclear@15 202 return curves;
nuclear@15 203 }
nuclear@15 204