curvedraw

annotate src/curvefile.cc @ 16:7f795f7fecd6

readme and COPYING
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 20 Dec 2015 10:55:57 +0200
parents 37ab3a4c02f8
children
rev   line source
nuclear@16 1 /*
nuclear@16 2 curvedraw - a simple program to draw curves
nuclear@16 3 Copyright (C) 2015 John Tsiombikas <nuclear@member.fsf.org>
nuclear@16 4
nuclear@16 5 This program is free software: you can redistribute it and/or modify
nuclear@16 6 it under the terms of the GNU General Public License as published by
nuclear@16 7 the Free Software Foundation, either version 3 of the License, or
nuclear@16 8 (at your option) any later version.
nuclear@16 9
nuclear@16 10 This program is distributed in the hope that it will be useful,
nuclear@16 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@16 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@16 13 GNU General Public License for more details.
nuclear@16 14
nuclear@16 15 You should have received a copy of the GNU General Public License
nuclear@16 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@16 17 */
nuclear@15 18 #include <stdlib.h>
nuclear@15 19 #include <ctype.h>
nuclear@15 20 #include <string>
nuclear@15 21 #include "curvefile.h"
nuclear@15 22
nuclear@15 23 static bool save_curve(FILE *fp, const Curve *curve);
nuclear@15 24
nuclear@15 25 bool save_curves(const char *fname, const Curve * const *curves, int count)
nuclear@15 26 {
nuclear@15 27 FILE *fp = fopen(fname, "wb");
nuclear@15 28 if(!fp) return false;
nuclear@15 29
nuclear@15 30 bool res = save_curves(fp, curves, count);
nuclear@15 31 fclose(fp);
nuclear@15 32 return res;
nuclear@15 33 }
nuclear@15 34
nuclear@15 35 bool save_curves(FILE *fp, const Curve * const *curves, int count)
nuclear@15 36 {
nuclear@15 37 fprintf(fp, "GCURVES\n");
nuclear@15 38
nuclear@15 39 for(int i=0; i<count; i++) {
nuclear@15 40 if(!save_curve(fp, curves[i])) {
nuclear@15 41 return false;
nuclear@15 42 }
nuclear@15 43 }
nuclear@15 44 return true;
nuclear@15 45 }
nuclear@15 46
nuclear@15 47 static const char *curve_type_str(CurveType type)
nuclear@15 48 {
nuclear@15 49 switch(type) {
nuclear@15 50 case CURVE_LINEAR:
nuclear@15 51 return "polyline";
nuclear@15 52 case CURVE_HERMITE:
nuclear@15 53 return "hermite";
nuclear@15 54 case CURVE_BSPLINE:
nuclear@15 55 return "bspline";
nuclear@15 56 }
nuclear@15 57 abort();
nuclear@15 58 }
nuclear@15 59
nuclear@15 60 static bool save_curve(FILE *fp, const Curve *curve)
nuclear@15 61 {
nuclear@15 62 fprintf(fp, "curve {\n");
nuclear@15 63 fprintf(fp, " type %s\n", curve_type_str(curve->get_type()));
nuclear@15 64 fprintf(fp, " cpcount %d\n", curve->size());
nuclear@15 65 for(int i=0; i<curve->size(); i++) {
nuclear@15 66 Vector4 cp = curve->get_point(i);
nuclear@15 67 fprintf(fp, " cp %g %g %g %g\n", cp.x, cp.y, cp.z, cp.w);
nuclear@15 68 }
nuclear@15 69 fprintf(fp, "}\n");
nuclear@15 70 return true;
nuclear@15 71 }
nuclear@15 72
nuclear@15 73 std::list<Curve*> load_curves(const char *fname)
nuclear@15 74 {
nuclear@15 75 std::list<Curve*> res;
nuclear@15 76 FILE *fp = fopen(fname, "r");
nuclear@15 77 if(!fp) return res;
nuclear@15 78
nuclear@15 79 res = load_curves(fp);
nuclear@15 80 fclose(fp);
nuclear@15 81 return res;
nuclear@15 82 }
nuclear@15 83
nuclear@15 84 static std::string next_token(FILE *fp)
nuclear@15 85 {
nuclear@15 86 std::string s;
nuclear@15 87 int c;
nuclear@15 88 while((c = fgetc(fp)) != -1) {
nuclear@15 89 if(!isspace(c)) {
nuclear@15 90 ungetc(c, fp);
nuclear@15 91 break;
nuclear@15 92 }
nuclear@15 93 }
nuclear@15 94
nuclear@15 95 if(feof(fp)) return s;
nuclear@15 96 while((c = fgetc(fp)) != -1) {
nuclear@15 97 if(isspace(c)) {
nuclear@15 98 ungetc(c, fp);
nuclear@15 99 break;
nuclear@15 100 }
nuclear@15 101 s.push_back(c);
nuclear@15 102 }
nuclear@15 103 return s;
nuclear@15 104 }
nuclear@15 105
nuclear@15 106 static bool expect_str(FILE *fp, const char *s)
nuclear@15 107 {
nuclear@15 108 std::string tok = next_token(fp);
nuclear@15 109 if(tok != std::string(s)) {
nuclear@15 110 if(tok.empty() && feof(fp)) {
nuclear@15 111 fprintf(stderr, "expected: %s\n", s);
nuclear@15 112 }
nuclear@15 113 return false;
nuclear@15 114 }
nuclear@15 115 return true;
nuclear@15 116 }
nuclear@15 117
nuclear@15 118 static bool expect_float(FILE *fp, float *ret)
nuclear@15 119 {
nuclear@15 120 std::string tok = next_token(fp);
nuclear@15 121 const char *cs = tok.c_str();
nuclear@15 122 char *endp;
nuclear@15 123 *ret = strtod(cs, &endp);
nuclear@15 124 if(endp != cs + tok.length()) {
nuclear@15 125 if(!(tok.empty() && feof(fp))) {
nuclear@15 126 fprintf(stderr, "number expected\n");
nuclear@15 127 }
nuclear@15 128 return false;
nuclear@15 129 }
nuclear@15 130 return true;
nuclear@15 131 }
nuclear@15 132
nuclear@15 133 static bool expect_int(FILE *fp, int *ret)
nuclear@15 134 {
nuclear@15 135 std::string tok = next_token(fp);
nuclear@15 136 const char *cs = tok.c_str();
nuclear@15 137 char *endp;
nuclear@15 138 *ret = strtol(cs, &endp, 0);
nuclear@15 139 if(endp != cs + tok.length()) {
nuclear@15 140 if(!(tok.empty() && feof(fp))) {
nuclear@15 141 fprintf(stderr, "integer expected\n");
nuclear@15 142 }
nuclear@15 143 return false;
nuclear@15 144 }
nuclear@15 145 return true;
nuclear@15 146 }
nuclear@15 147
nuclear@15 148 static Curve *curve_block(FILE *fp)
nuclear@15 149 {
nuclear@15 150 if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
nuclear@15 151 return 0;
nuclear@15 152 }
nuclear@15 153
nuclear@15 154 Curve *curve = new Curve;
nuclear@15 155 int cpcount = -1;
nuclear@15 156 std::string tok;
nuclear@15 157 while(!(tok = next_token(fp)).empty() && tok != "}") {
nuclear@15 158 if(tok == "cpcount") {
nuclear@15 159 if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
nuclear@15 160 goto err;
nuclear@15 161 }
nuclear@15 162 } else if(tok == "type") {
nuclear@15 163 tok = next_token(fp);
nuclear@15 164 if(tok == "polyline") {
nuclear@15 165 curve->set_type(CURVE_LINEAR);
nuclear@15 166 } else if(tok == "hermite") {
nuclear@15 167 curve->set_type(CURVE_HERMITE);
nuclear@15 168 } else if(tok == "bspline") {
nuclear@15 169 curve->set_type(CURVE_BSPLINE);
nuclear@15 170 } else {
nuclear@15 171 goto err;
nuclear@15 172 }
nuclear@15 173 } else {
nuclear@15 174 if(tok != "cp") {
nuclear@15 175 goto err;
nuclear@15 176 }
nuclear@15 177 Vector4 cp;
nuclear@15 178 for(int i=0; i<4; i++) {
nuclear@15 179 if(!expect_float(fp, &cp[i])) {
nuclear@15 180 goto err;
nuclear@15 181 }
nuclear@15 182 }
nuclear@15 183 curve->add_point(Vector3(cp.x, cp.y, cp.z), cp.w);
nuclear@15 184 }
nuclear@15 185 }
nuclear@15 186
nuclear@15 187 if(curve->size() != cpcount) {
nuclear@15 188 fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
nuclear@15 189 }
nuclear@15 190
nuclear@15 191 return curve;
nuclear@15 192 err:
nuclear@15 193 fprintf(stderr, "failed to parse curve block\n");
nuclear@15 194 delete curve;
nuclear@15 195 return 0;
nuclear@15 196 }
nuclear@15 197
nuclear@15 198 std::list<Curve*> load_curves(FILE *fp)
nuclear@15 199 {
nuclear@15 200 std::list<Curve*> curves;
nuclear@15 201 if(!expect_str(fp, "GCURVES")) {
nuclear@15 202 fprintf(stderr, "load_curves: failed to load, invalid file format\n");
nuclear@15 203 return curves;
nuclear@15 204 }
nuclear@15 205
nuclear@15 206 Curve *curve;
nuclear@15 207 while((curve = curve_block(fp))) {
nuclear@15 208 curves.push_back(curve);
nuclear@15 209 }
nuclear@15 210
nuclear@15 211 if(!feof(fp)) {
nuclear@15 212 std::list<Curve*>::iterator it = curves.begin();
nuclear@15 213 while(it != curves.end()) {
nuclear@15 214 delete *it++;
nuclear@15 215 }
nuclear@15 216 return curves;
nuclear@15 217 }
nuclear@15 218
nuclear@15 219 return curves;
nuclear@15 220 }
nuclear@15 221