Blob Blame Raw


#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

#include "svg-track.inc.c"
#include "svg-save.inc.c"


typedef struct {
  const char *base;
  const char *link0;
  const char *link1;
} Link;

typedef struct {
  const char *name;
  Link begin;
  const char *mid;
  Link end;
  int linkMode;
  const char *alias;
} Letter;


#include "letters.inc.c"


char path[1024*1024];
double pathX0 = 60, pathRowStep = 200, pathWidth = 5;
char *pathEnd;
double pathX, pathY;
FILE *pathFile;
int pathMode;


void putPath(const char *str) {
  if (!str || !*str) return;
  if (!*path) {
    char buf[256] = {};
    sprintf(buf, "M %g %g ", pathX, pathY);
    char *c = buf;
    while(*c) *pathEnd++ = *c++;
  }
  spTrack(str, &pathX, &pathY);
  while(*str) *pathEnd++ = *str++;
  *pathEnd = 0;
}


void splitPath(int mode) {
  if (mode >= 2) {
    if (pathMode >= 2) {
      if (*path) svgAddPath(pathFile, path, pathWidth, 1);
      *(pathEnd = path) = 0;
    }
  } else
  if (mode >= 1) {
    pathX = pathX0;
    pathY += pathRowStep;
    if (pathMode >= 1) {
      if (*path) svgAddPath(pathFile, path, pathWidth, 1);
      *(pathEnd = path) = 0;
    } else
    if (*path) {
      char buf[256] = {};
      sprintf(buf, "M %g %g ", pathX, pathY);
      putPath(buf);
    }
  } else {
    if (*path) svgAddPath(pathFile, path, pathWidth, 1);
    //*(pathEnd = path) = 0;
  }
}


void textToPath(const char *text) {
  pathEnd = path;
  *pathEnd = 0;

  int cnt = sizeof(letters)/sizeof(*letters);
  Letter *prev = NULL;
  while(*text) {
    Letter *curr = NULL;
    do {
      for(int i = 0; i < cnt; ++i) {
        Letter *l = &letters[i];
        const char *t = curr ? curr->alias : text;
        const char *ln = l->name;
        while(*t && *ln && *t == *ln) ++t, ++ln;
        if (!*ln) {
          if (!curr) text = t;
          curr = l;
          break;
        }
      }
    } while(curr && curr->alias);


    if (prev) {
      const char *link = curr && curr->linkMode == 1 ? prev->end.link1 : prev->end.link0;
      putPath(curr && curr->linkMode != 2 && curr->linkMode != 3 && link ? link : prev->end.base);
    }

    splitPath(2);

    if (curr) {
      const char *link = curr->linkMode == 1 ? curr->begin.link1 : curr->begin.link0;
      putPath(prev && prev->linkMode != 2 && link ? link : curr->begin.base);
      putPath(curr->mid);
    } else
    if (*text == '\n') {
      splitPath(1);
      ++text;
    } else {
      putPath(MSPACE);
      ++text;
    }

    prev = curr;
  }
  if (prev) putPath(prev->end.base);
  splitPath(0);
}


int textFileToSVG(const char *textfile, const char *svgfile) {
  FILE *sf = fopen(textfile, "r");
  if (!sf) {
    fprintf(stderr, "cannot open file '%s' for read\n", textfile);
    return 1;
  }
  char buf[1024*1024] = {};
  char *str = buf, *end = buf + sizeof(buf) - 1;
  while(1) {
    int c = fgetc(sf);
    if (c <= 0) break;
    *str++ = c;
    if (str == end) {
      fprintf(stderr, "input file '%s' too large\n", textfile);
      return 1;
    }
  }
  fclose(sf);

  pathX = pathX0;
  pathY = pathRowStep;
  pathEnd = path;
  pathFile = svgBegin(svgfile, 300, 300, 10);
  if (!pathFile) {
    fprintf(stderr, "cannot open file '%s' for write\n", svgfile);
    return 1;
  }

  pathMode = 2;
  textToPath(buf);
  svgEnd(pathFile);

  pathX = pathX0;
  pathY = pathRowStep;
  pathEnd = path;
  pathFile = NULL;

  return 0;
}


int main(int argc, char **argv) {
  if (argc != 3) {
    printf("usage: writing <input-text-file> <output-svg-file>\n");
    return 1;
  }

  return textFileToSVG(argv[1], argv[2]);
}