|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
#include <ctype.h></ctype.h>
|
|
|
8cdc05 |
#include <stdlib.h></stdlib.h>
|
|
|
8cdc05 |
#include <stdio.h></stdio.h>
|
|
|
8cdc05 |
|
|
|
8cdc05 |
#include "svg-track.inc.c"
|
|
|
8cdc05 |
#include "svg-save.inc.c"
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
typedef struct {
|
|
|
8cdc05 |
const char *base;
|
|
|
8cdc05 |
const char *link0;
|
|
|
8cdc05 |
const char *link1;
|
|
|
8cdc05 |
} Link;
|
|
|
8cdc05 |
|
|
|
8cdc05 |
typedef struct {
|
|
|
8cdc05 |
const char *name;
|
|
|
8cdc05 |
Link begin;
|
|
|
8cdc05 |
const char *mid;
|
|
|
8cdc05 |
Link end;
|
|
|
8cdc05 |
int linkMode;
|
|
|
8cdc05 |
const char *alias;
|
|
|
8cdc05 |
} Letter;
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
#include "letters.inc.c"
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
char path[1024*1024];
|
|
|
8cdc05 |
double pathX0 = 60, pathRowStep = 200, pathWidth = 5;
|
|
|
8cdc05 |
char *pathEnd;
|
|
|
8cdc05 |
double pathX, pathY;
|
|
|
8cdc05 |
FILE *pathFile;
|
|
|
8cdc05 |
int pathMode;
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
void putPath(const char *str) {
|
|
|
8cdc05 |
if (!str || !*str) return;
|
|
|
8cdc05 |
if (!*path) {
|
|
|
8cdc05 |
char buf[256] = {};
|
|
|
8cdc05 |
sprintf(buf, "M %g %g ", pathX, pathY);
|
|
|
8cdc05 |
char *c = buf;
|
|
|
8cdc05 |
while(*c) *pathEnd++ = *c++;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
spTrack(str, &pathX, &pathY);
|
|
|
8cdc05 |
while(*str) *pathEnd++ = *str++;
|
|
|
8cdc05 |
*pathEnd = 0;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
void splitPath(int mode) {
|
|
|
8cdc05 |
if (mode >= 2) {
|
|
|
8cdc05 |
if (pathMode >= 2) {
|
|
|
8cdc05 |
if (*path) svgAddPath(pathFile, path, pathWidth, 1);
|
|
|
8cdc05 |
*(pathEnd = path) = 0;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
} else
|
|
|
8cdc05 |
if (mode >= 1) {
|
|
|
8cdc05 |
pathX = pathX0;
|
|
|
8cdc05 |
pathY += pathRowStep;
|
|
|
8cdc05 |
if (pathMode >= 1) {
|
|
|
8cdc05 |
if (*path) svgAddPath(pathFile, path, pathWidth, 1);
|
|
|
8cdc05 |
*(pathEnd = path) = 0;
|
|
|
8cdc05 |
} else
|
|
|
8cdc05 |
if (*path) {
|
|
|
8cdc05 |
char buf[256] = {};
|
|
|
8cdc05 |
sprintf(buf, "M %g %g ", pathX, pathY);
|
|
|
8cdc05 |
putPath(buf);
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
} else {
|
|
|
8cdc05 |
if (*path) svgAddPath(pathFile, path, pathWidth, 1);
|
|
|
8cdc05 |
//*(pathEnd = path) = 0;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
void textToPath(const char *text) {
|
|
|
8cdc05 |
pathEnd = path;
|
|
|
8cdc05 |
*pathEnd = 0;
|
|
|
8cdc05 |
|
|
|
8cdc05 |
int cnt = sizeof(letters)/sizeof(*letters);
|
|
|
8cdc05 |
Letter *prev = NULL;
|
|
|
8cdc05 |
while(*text) {
|
|
|
8cdc05 |
Letter *curr = NULL;
|
|
|
8cdc05 |
do {
|
|
|
8cdc05 |
for(int i = 0; i < cnt; ++i) {
|
|
|
8cdc05 |
Letter *l = &letters[i];
|
|
|
8cdc05 |
const char *t = curr ? curr->alias : text;
|
|
|
8cdc05 |
const char *ln = l->name;
|
|
|
8cdc05 |
while(*t && *ln && *t == *ln) ++t, ++ln;
|
|
|
8cdc05 |
if (!*ln) {
|
|
|
8cdc05 |
if (!curr) text = t;
|
|
|
8cdc05 |
curr = l;
|
|
|
8cdc05 |
break;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
} while(curr && curr->alias);
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
if (prev) {
|
|
|
8cdc05 |
const char *link = curr && curr->linkMode == 1 ? prev->end.link1 : prev->end.link0;
|
|
|
8cdc05 |
putPath(curr && curr->linkMode != 2 && curr->linkMode != 3 && link ? link : prev->end.base);
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
splitPath(2);
|
|
|
8cdc05 |
|
|
|
8cdc05 |
if (curr) {
|
|
|
8cdc05 |
const char *link = curr->linkMode == 1 ? curr->begin.link1 : curr->begin.link0;
|
|
|
8cdc05 |
putPath(prev && prev->linkMode != 2 && link ? link : curr->begin.base);
|
|
|
8cdc05 |
putPath(curr->mid);
|
|
|
8cdc05 |
} else
|
|
|
8cdc05 |
if (*text == '\n') {
|
|
|
8cdc05 |
splitPath(1);
|
|
|
8cdc05 |
++text;
|
|
|
8cdc05 |
} else {
|
|
|
8cdc05 |
putPath(MSPACE);
|
|
|
8cdc05 |
++text;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
prev = curr;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
if (prev) putPath(prev->end.base);
|
|
|
8cdc05 |
splitPath(0);
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
int textFileToSVG(const char *textfile, const char *svgfile) {
|
|
|
8cdc05 |
FILE *sf = fopen(textfile, "r");
|
|
|
8cdc05 |
if (!sf) {
|
|
|
8cdc05 |
fprintf(stderr, "cannot open file '%s' for read\n", textfile);
|
|
|
8cdc05 |
return 1;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
char buf[1024*1024] = {};
|
|
|
8cdc05 |
char *str = buf, *end = buf + sizeof(buf) - 1;
|
|
|
8cdc05 |
while(1) {
|
|
|
8cdc05 |
int c = fgetc(sf);
|
|
|
8cdc05 |
if (c <= 0) break;
|
|
|
8cdc05 |
*str++ = c;
|
|
|
8cdc05 |
if (str == end) {
|
|
|
8cdc05 |
fprintf(stderr, "input file '%s' too large\n", textfile);
|
|
|
8cdc05 |
return 1;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
fclose(sf);
|
|
|
8cdc05 |
|
|
|
8cdc05 |
pathX = pathX0;
|
|
|
8cdc05 |
pathY = pathRowStep;
|
|
|
8cdc05 |
pathEnd = path;
|
|
|
8cdc05 |
pathFile = svgBegin(svgfile, 300, 300, 10);
|
|
|
8cdc05 |
if (!pathFile) {
|
|
|
8cdc05 |
fprintf(stderr, "cannot open file '%s' for write\n", svgfile);
|
|
|
8cdc05 |
return 1;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
pathMode = 2;
|
|
|
8cdc05 |
textToPath(buf);
|
|
|
8cdc05 |
svgEnd(pathFile);
|
|
|
8cdc05 |
|
|
|
8cdc05 |
pathX = pathX0;
|
|
|
8cdc05 |
pathY = pathRowStep;
|
|
|
8cdc05 |
pathEnd = path;
|
|
|
8cdc05 |
pathFile = NULL;
|
|
|
8cdc05 |
|
|
|
8cdc05 |
return 0;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
|
|
|
8cdc05 |
int main(int argc, char **argv) {
|
|
|
8cdc05 |
if (argc != 3) {
|
|
|
8cdc05 |
printf("usage: writing <input-text-file> <output-svg-file>\n");</output-svg-file></input-text-file>
|
|
|
8cdc05 |
return 1;
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|
|
|
8cdc05 |
return textFileToSVG(argv[1], argv[2]);
|
|
|
8cdc05 |
}
|
|
|
8cdc05 |
|