diff --git a/simple/writing/build.sh b/simple/writing/build.sh
new file mode 100755
index 0000000..66dc266
--- /dev/null
+++ b/simple/writing/build.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -e
+
+cc -O3 -Wall src/writing.c -o writing
+
+echo "build success"
\ No newline at end of file
diff --git a/simple/writing/src/letters.inc.c b/simple/writing/src/letters.inc.c
new file mode 100644
index 0000000..cb785f5
--- /dev/null
+++ b/simple/writing/src/letters.inc.c
@@ -0,0 +1,239 @@
+
+
+#define MSPACE "m 60 0"
+#define MDOTSP "m 20 0"
+#define MUP "m 10 -25 "
+#define MUP3 "m 30 -75 "
+#define MDN "m -10 25 "
+#define MUPE "m 4 -10 "
+#define MDNE "m -4 10 "
+
+#define Co1 "q 6 -15 -4 -15 "
+#define Co2 "q -10 0 -16 15 "
+#define Co3 "q -6 15 4 15 "
+#define Co4 "q 10 0 16 -15 "
+
+#define CO1 "q 10 -25 -5 -25 "
+#define CO2 "q -15 0 -25 25 "
+#define CO3 "q -10 25 5 25 "
+#define CO4 "q 15 0 25 -25 "
+
+#define CO1B "q 15 0 5 25 "
+#define CO2B "q 10 -25 25 -25 "
+#define CO3B "q -15 0 -5 -25 "
+#define CO4B "q -10 25 -25 25 "
+
+#define CFO1 CO1 CO2 CO3 CO4
+#define CFO2 CO2 CO3 CO4 CO1
+#define CFO3 CO3 CO4 CO1 CO2
+#define CFO4 CO4 CO1 CO2 CO3
+
+#define CLU "q 50 -50 30 0 "
+#define CLD "q -20 50 30 0 "
+#define CLLD "q -10 25 0 25 q 15 0 40 -50 "
+
+#define CKD1 "c 14 -35 44 -35 38 -20 "
+#define CKD2 "q -18 45 32 -5 "
+
+#define CJL0 "q -10 25 0 25 "
+#define CJL CJL0 "q 15 0 50 -50 "
+#define CJR CJL0 "c 15 0 40 -25 44 -35 " Co1 Co2 Co3 Co4 "l 6 -15 "
+
+#define CGD0 CLD CDN "q -10 25 -20 25 "
+#define CGD CGD0 "c -20 0 20 -25 45 -50 "
+#define CGDE CGD0 "c -20 0 19 -25 39 -35 "
+
+#define CQU1 "c 25 -25 51 -40 61 -65 "
+#define CQU2 "q 4 -10 -6 -10 q -10 0 -20 25 l -20 50 "
+#define CQU CQU1 CQU2
+
+#define CQD1 CDN2
+#define CQD2 "q -10 25 -20 25 q -10 0 -6 -10 "
+#define CQD3 "c 10 -25 36 -40 61 -65 "
+#define CQD3E "c 10 -25 35 -40 55 -50 "
+#define CQD CQD1 CQD2 CQD3
+
+#define CC1 "q 5 0 8 5 "
+#define CC2 "q -3 -5 -8 -5 " CO2 CO3
+#define CC CC1 CC2
+#define CXL CO1B CO4B "q -5 0 -8 -5 q 3 5 8 5 "
+
+#define Cb0 "l -4 10 " Co3 Co4 Co1
+#define Cb Cb0 Co2 Co3
+
+#define CUP "l 10 -25 "
+#define CDN "l -10 25 "
+#define CUP2 "l 20 -50 "
+#define CDN2 "l -20 50 "
+
+#define CEE "m -18 -65 l 2 -2 m 10 0 l -2 2 m 8 65 "
+#define CYY "m -28 -65 q 3 5 17 -5 m 11 70 "
+
+#define CDot "m 2 0 q 0 2 -2 2 q -2 0 -2 -2 q 0 -2 2 -2 q 2 0 2 2 "
+#define CComma CDot "q -1 5 -8 10 m 8 -10 "
+
+
+#define C_O1 "q 20 -50 0 -50 "
+#define C_O2 "q -20 0 -40 50 "
+#define C_O3 "q -20 50 0 50 "
+#define C_O4 "q 20 0 40 -50 "
+
+#define C_O1B "q 20 0 0 50 "
+#define C_O2B "q 20 -50 40 -50 "
+#define C_O3B "q -20 0 0 -50 "
+#define C_O4B "q -20 50 -40 50 "
+
+#define C_XL1 "m 36 -90 q 10 -10 18 -10 "
+#define C_XL2 C_O1B C_O4B
+#define C_XL3 "q -7.5 0 -14 -10 q 3.5 10 14 10 "
+#define C_XL C_XL1 C_XL2 C_XL3
+
+#define C_XR1 "q 7.5 0 14 10 "
+#define C_XR2 "q -3.5 -10 -14 -10 "
+#define C_XR3 C_O2 C_O3
+#define C_XR C_XR1 C_XR2 C_XR3
+
+#define C_AL0 "m 4 -10 q 1 10 11 10 "
+#define C_AL C_AL0 "q 30 0 95 -100 "
+
+#define C_LU CLU
+#define C_LD CLD
+#define C_LLD "q -10 25 0 25 q 15 0 70 -100 "
+
+#define C_J1 "m 64 -85 l -24 60 "
+#define C_J2 "l -4 10 q -6 15 -21 15 q -5 0 -11 -10 m 11 10 "
+#define C_JJ2 "l -4 10 q -6 15 -21 15 q -5 0 -11 -10 q 1 10 11 10 "
+#define C_J C_J1 C_J2
+
+#define C_T "m 28 -70 c -10 -10 -8 -30 12 -30 "
+
+#define C_E "m 69 -90 " C_XR2 "q -15 0 -23 20 q -3 25 15 25 q -25 0 -35 25 q -12 30 13 30 "
+
+#define C_3 C_XL1 "q 15 0 7 20 q -10 25 -25 25 q 15 0 5 25 q -12 30 -32 30 " C_XL3
+
+#define C_B1 "m 60 -100 " CDN CDN2 CQD2 "q 56 -90 71 -90 "
+#define C_B2 "q 15 0 7 20 q -10 25 -30 25 "
+#define C_B3 "q 25 0 15 25 q -12 30 -32 30 q -5 0 -8 -5 q 3 5 8 5 "
+#define C_B C_B1 C_B2 C_B3
+
+#define C_EE "m 31 -115 l 2 -2 m 10 0 l -2 2 m -41 115 "
+#define C_YY "m -26.5 -15 q 3 5 17 -5 m 9.5 20 "
+
+
+#define LLBO MUP "q 25 -25 35 -25 "
+
+
+#define LBL { MUP CLU }
+#define LBO { "m 35 -50 ", LLBO }
+#define LBA { "m 40 -25 ", LLBO CO1B }
+#define LBQ { MUP CQU }
+#define LBE { MUPE "c 46 -23 56 -40 41 -40 " }
+#define LBN { "m 20 -50 " CDN, MUP "l 25 -25 " CDN }
+#define LBX { "m 18 -45 q 7 -5 12 -5 ", LLBO }
+#define LBC { "m 38 -45 ", LLBO CC1 }
+#define LBJ { MUP CJL }
+#define LBr { MUP "l 25 -25 q 5 25 30 0 " }
+#define LBR { MUP CJR }
+
+#define LEL { CLD MDN, NULL, "c -14 35 4 25 24 15 " MDNE }
+#define LELY { CLD MDN CYY, NULL, "c -14 35 4 25 24 15 " MDNE CYY }
+#define LEO { "m 15 0 ", "q 15 0 40 -25 " MDN, "q 19 0 39 -10 " MDNE }
+#define LEE { "q 19 0 39 -10 " MDNE, "q 15 0 40 -25 " MDN }
+#define LEEE { "q 19 0 39 -10 " MDNE CEE, "q 15 0 40 -25 " MDN CEE }
+#define LEQ { CQD2 CQD3 MDN, NULL, CQD2 CQD3E MDNE }
+#define LEX { "q 15 0 40 -25 " MDN, NULL, "q 19 0 39 -10 " MDNE }
+#define LEK { CKD2 MDN, NULL, "c -12 30 2 20 22 10 " MDNE }
+#define LEG { CGD MDN, NULL, CGDE MDNE }
+
+
+#define L_EO1 { "m 30 0 ", "q 15 0 40 -25 " MDN, "q 19 0 39 -10 " MDNE }
+#define L_EO2 { "m 60 0 ", "q 15 0 40 -25 " MDN, "q 19 0 39 -10 " MDNE }
+#define L_EO3 { "m 75 0 ", "q 15 0 40 -25 " MDN, "q 19 0 39 -10 " MDNE }
+
+#define L_EA { "q 20 -50 -10 -50 c -20 0 -16 40 14 40 q 21 0 36 -15 " MDN, NULL, \
+ "q 20 -50 -10 -50 c -20 0 -18 45 12 45 q 22 0 32 -5 " MDNE }
+
+
+Letter letters[] = {
+ { "а", LBA, CFO1 CUP CDN, LEL },
+ { "б", LBA, CFO1 CUP2 "q 10 -25 25 -25 l 15 0 m -85 100", LEO },
+ { "в", LBQ, CFO3 CO3, LEO },
+ { "г", LBL, "", LEL },
+ { "д", LBA, CFO1 CUP CDN CQD1, LEQ },
+ { "е", LBE, CO2 CO3, LEE, 1 },
+ { "ё", LBE, CO2 CO3, LEEE, 1 },
+ { "ж", LBX, CXL "q 15 0 55 -50 " CDN2 "q 40 -50 55 -50 " CC, LEX },
+ { "з", LBX, CO1B "q -3 7.5 -19 15 q 18 -7.5 1 35 ", LEQ },
+ { "и", LBN, CLLD CDN, LEL },
+ { "й", LBN, CLLD CDN, LELY },
+ { "к", LBN, CDN "q 48 -70 46 -40 m -46 40 " CKD1, LEK },
+ { "л", LBJ, CDN, LEL },
+ { "м", LBJ, CDN CLLD CDN, LEL },
+ { "н", LBN, CDN CUP "q 30 0 40 -25" CDN, LEL },
+ { "о", LBO, CFO2 CO2 CO3, LEO },
+ { "п", LBN, CDN CUP CLU, LEL },
+ { "р", LBN, "l -30 75 l 30 -75 " CLU, LEL },
+ { "с", LBC, CC2, LEX },
+ { "т", LBN, CDN CUP CLU CDN CUP CLU, LEL },
+ { "у", LBN, CLLD CDN CQD1, LEQ },
+ { "ф", LBA, CFO1 CUP CDN CFO3 "l -30 75 m 35 -50 ", LEO },
+ { "х", LBX, CXL CO4 CO2B CC, LEX },
+ { "ц", LBN, CLLD CDN, LEG },
+ { "ч", LBr, CDN, LEL },
+ { "ш", LBN, CLLD CDN CLLD CDN, LEL },
+ { "щ", LBN, CLLD CDN CLLD CDN, LEG },
+ { "ъ", LBr, CDN Cb, LEO },
+ { "ы", LBN, Cb0 "q 20 0 28 -20 " CDN, LEL },
+ { "ь", LBN, Cb, LEO },
+ { "э", LBX, CXL "m 10 -25 l 15 0 m -25 25 ", LEO },
+ { "ю", LBN, CDN CUP "c 30 0 40 -25 55 -25 " CFO2 CO2 CO3, LEO },
+ { "я", LBR, CDN, LEL },
+
+
+ //{ "А", {""}, C_AL "m -64 60 l 50 0 m 14 -60 " CDN2 CDN, LEL, 3 },
+ { "А", {""}, C_AL CDN2 CDN2, L_EA, 3 },
+ { "Б", {""}, "m 53 -85 l -24 60 " CQD2 "q 33 -45 48 -45 " C_B3 "m -30 0 " C_T "l 50 0 m -60 100 ", L_EO2, 3 },
+ { "В", {""}, C_B, L_EO1, 3 },
+ { "Г", {""}, C_J "m -10 0 " C_T "l 60 0 m -90 100 ", L_EO3, 3 },
+ { "Д", {""}, C_J1 CO4B "c -15 0 -9 -15 1 -15 c 10 0 14 15 24 15 " C_O4 "q 20 -50 -15 -50 q -25 0 -37 30 m 12 70 ", L_EO1, 3 },
+ { "Е", {""}, C_E, LEX, 3 },
+ { "Ё", {""}, C_E C_EE, LEX, 3 },
+ { "Ж", {""}, C_XL "q 30 0 85 -100 " CDN2 CDN2 "q 55 -100 85 -100 " C_XR, LEX, 3 },
+ { "З", {""}, C_3, L_EO1, 3 },
+ { "И", {""}, MUP3 C_LU CDN2 C_LLD CDN2 CDN, LEL, 3 },
+ { "Й", {""}, MUP3 C_LU CDN2 C_LLD C_YY CDN2 CDN, LEL, 3 },
+ { "К", {""}, "m 40 -75 l 25 -25 " CDN CDN2 CQD2 "c 4 -10 76 -90 86 -90 q 2.5 0 1 10 m -56 55 " CO2B CO1B "l -4 10 ", LEL, 3 },
+ { "Л", {""}, C_AL CDN2 CDN, LEL, 3 },
+ { "М", {""}, C_AL CDN2 CDN C_LLD CDN2 CDN, LEL, 3 },
+ { "Н", {""}, "m 40 -75 l 25 -25 " CDN CDN2 CQD2 "c 8 -20 96 -60 102 -80 " CQU2, LEL, 3 },
+ { "О", {""}, "m 20 0 " C_O4 C_O1 C_O2 C_O3, L_EO1, 3 },
+ { "П", {""}, C_J "m -5 0 " C_T "l 60 0 m -90 100 " C_J1, LEL, 3 },
+ { "Р", {""}, C_J "m 18 -70 c -5 -5 7 -30 32 -30 c 35 0 25 30 15 35 m -65 65 ", L_EO2, 3 },
+ { "С", {""}, "m 74 -90 " C_XR2 C_XR3, LEX, 3 },
+ { "Т", {""}, C_J "m -5 0 " C_T "l 80 0 m -110 100 " C_J1 CDN "m -10 0 " C_J1, LEL, 3 },
+ { "У", {""}, MUP3 C_LU CLLD CDN2 CDN C_JJ2, LEO, 3 },
+ { "Ф", {""}, "m 60 -75 " CFO1 CUP CDN CFO3 CDN2 C_J2, L_EO2, 3 },
+ { "Х", {""}, C_XL C_O4 C_O2B C_XR, LEX, 3 },
+ { "Ц", {""}, MUP3 C_LU CDN2 C_LLD CDN2 CDN, LEG, 3 },
+ { "Ч", {""}, MUP3 C_LU CLLD CDN2 CDN, LEL, 3 },
+ { "Ш", {""}, MUP3 C_LU CDN2 C_LLD CDN2 CDN C_LLD CDN2 CDN, LEL, 3 },
+ { "Щ", {""}, MUP3 C_LU CDN2 C_LLD CDN2 CDN C_LLD CDN2 CDN, LEG, 3 },
+
+ { "Э", {""}, C_XL "m 20 -50 l 20 0 m -40 50 ", L_EO1, 3 },
+ { "Ю", {""}, "m 40 -75 l 25 -25 " CDN CDN2 CQD2 "c 8 -20 46 -35 56 -40 " C_O3 C_O4 C_O1 C_O2 C_O3, L_EO1, 3 },
+ { "Я", {""}, C_AL0 "c 15 0 55 -50 65 -75 " CFO1 CUP CDN2 CDN, LEL, 3 },
+
+ { "-", {""}, MDOTSP "m 10 -25 l 40 0 m -10 25 " MDOTSP, {""}, 2 },
+ { ".", {""}, MDOTSP CDot MDOTSP, {""}, 2 },
+ { ",", {""}, MDOTSP CComma MDOTSP, {""}, 2 },
+ { "\"",{""}, "m 40 -100 " CComma "m 10 0 " CComma "m -40 100 " MDOTSP, {""}, 2 },
+ { "»", {}, NULL, {}, 0, "\"" },
+ { "“", {}, NULL, {}, 0, "\"" },
+ { "«", {""}, MDOTSP CComma "m 10 0 " CComma MDOTSP, {""}, 2 },
+ { "„", {}, NULL, {}, 0, "«" },
+
+ { "!", {""}, MDOTSP "m 40 -100 l -34 85 m -6 15 " CDot MDOTSP, {""}, 2 },
+ { "?", {""}, MDOTSP "m 15 -75 " CO2B CO1B "c -10 25 -29 35 -39 60 m -6 15 " CDot MDOTSP, {""}, 2 },
+};
+
+
diff --git a/simple/writing/src/svg-save.inc.c b/simple/writing/src/svg-save.inc.c
new file mode 100644
index 0000000..3838bd2
--- /dev/null
+++ b/simple/writing/src/svg-save.inc.c
@@ -0,0 +1,32 @@
+
+
+FILE* svgBegin(const char *filename, double widthMM, double heightMM, double unitsPerMM) {
+ FILE *f = fopen(filename, "w");
+ if (f) {
+ fprintf(f, "\n");
+ fclose(f);
+}
+
+
+void svgAddText(FILE *f, double x, double y, double size, const char *text) {
+ if (!f) return;
+ fprintf(f, "%s\n", x, y, size, text);
+}
+
+
+void svgAddPath(FILE *f, const char *path, double width, int round) {
+ if (!f) return;
+ fprintf(f, "\n",
+ (round ? "stroke-linecap:round;stroke-linejoin:round;" : ""),
+ width, path );
+}
diff --git a/simple/writing/src/svg-track.inc.c b/simple/writing/src/svg-track.inc.c
new file mode 100644
index 0000000..36f1c09
--- /dev/null
+++ b/simple/writing/src/svg-track.inc.c
@@ -0,0 +1,64 @@
+
+
+void spSkipSpace(const char **pos)
+ { while(**pos && isspace(**pos)) ++*pos; }
+
+
+double spReadNum(const char **pos) {
+ spSkipSpace(pos);
+ char *end = "";
+ double x = strtod(*pos, &end);
+ *pos = end;
+ return x;
+}
+
+
+void spTrack(const char *path, double *x, double *y) {
+ double sx = *x, sy = *y;
+ const char *c = path;
+ spSkipSpace(&c);
+ while(*c) {
+ switch(*c++) {
+ case 'M':
+ sx = (*x = spReadNum(&c));
+ sy = (*y = spReadNum(&c));
+ break;
+ case 'm':
+ sx = (*x += spReadNum(&c));
+ sy = (*y += spReadNum(&c));
+ break;
+
+ case 'C':
+ spReadNum(&c);
+ spReadNum(&c);
+ case 'Q':
+ spReadNum(&c);
+ spReadNum(&c);
+ case 'L':
+ *x = spReadNum(&c);
+ *y = spReadNum(&c);
+ break;
+
+ case 'c':
+ spReadNum(&c);
+ spReadNum(&c);
+ case 'q':
+ spReadNum(&c);
+ spReadNum(&c);
+ case 'l':
+ *x += spReadNum(&c);
+ *y += spReadNum(&c);
+ break;
+
+ case 'Z':
+ case 'z':
+ *x = sx;
+ *y = sy;
+ break;
+ default:
+ printf("unknown path command \'%c\'\n", *(c - 1));
+ }
+ spSkipSpace(&c);
+ }
+}
+
diff --git a/simple/writing/src/writing.c b/simple/writing/src/writing.c
new file mode 100644
index 0000000..70a7063
--- /dev/null
+++ b/simple/writing/src/writing.c
@@ -0,0 +1,177 @@
+
+
+#include
+#include
+#include
+
+#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 \n");
+ return 1;
+ }
+
+ return textFileToSVG(argv[1], argv[2]);
+}
+
diff --git a/simple/writing/test/test-input.txt b/simple/writing/test/test-input.txt
new file mode 100644
index 0000000..b6c9055
--- /dev/null
+++ b/simple/writing/test/test-input.txt
@@ -0,0 +1,20 @@
+х х х х х х х х х х х х
+ж ж ж ж ж ж ж ж ж ж ж ж
+Х Х Х Х Х Х Х Х Х Х Х Х
+Ж Ж Ж Ж Ж Ж Ж Ж Ж Ж Ж Ж
+й й й й й й й й й й й й
+Й Й Й Й Й Й Й Й Й Й Й Й
+ч ч ч ч ч ч ч ч ч ч ч ч
+Ч Ч Ч Ч Ч Ч Ч Ч Ч Ч Ч Ч
+ц ц ц ц ц ц ц ц ц ц ц ц
+Ц Ц Ц Ц Ц Ц Ц Ц Ц Ц Ц Ц
+щ щ щ щ щ щ щ щ щ щ щ щ
+Щ Щ Щ Щ Щ Щ Щ Щ Щ Щ Щ Щ
+ф ф ф ф ф ф ф ф ф ф ф ф
+Ф Ф Ф Ф Ф Ф Ф Ф Ф Ф Ф Ф
+э э э э э э э э э э э э
+Э Э Э Э Э Э Э Э Э Э Э Э
+ю ю ю ю ю ю ю ю ю ю ю ю
+Ю Ю Ю Ю Ю Ю Ю Ю Ю Ю Ю Ю
+ь ь ь ь ь ь ь ь ь ь ь ь
+ъ ъ ъ ъ ъ ъ ъ ъ ъ ъ ъ ъ
diff --git a/simple/writing/test/test-output.svg b/simple/writing/test/test-output.svg
new file mode 100644
index 0000000..d847dd9
--- /dev/null
+++ b/simple/writing/test/test-output.svg
@@ -0,0 +1,922 @@
+