Reputation: 496
I'm trying to make an svg font for the unicode braille range. I want the black dots to be filled dots in (#fontcolor), and the non-dots to be circular lines.
"⠛" becomes the following svg:
<svg width="40" height="80">
<g
style="fill-opacity:1;fill:#000000;stroke:#000000;stroke-width:2;stroke-opacity:1"
>
<circle id="c0"
cx="10" cy="10" r="9" />
<circle id="c1"
cx="10" cy="30" r="9" />
<circle id="c2"
style="fill:none;"
cx="10" cy="50" r="9" />
<circle id="c3"
cx="30" cy="10" r="9" />
<circle id="c4"
cx="30" cy="30" r="9" />
<circle id="c5"
style="fill:none;"
cx="30" cy="50" r="9" />
<circle id="c6"
style="fill:none;"
cx="10" cy="70" r="9" />
<circle id="c7"
style="fill:none;"
cx="30" cy="70" r="9" />
</g>
</svg>
Here's an image of what I'm trying to copy:
As you can tell, the relation between braille glyphs is highly patern-ic. A brailly glyph has 8 possible dots, and each dot is like a bit: from 2800 to 28ff, or 00 to ff, the braille glpyhs appear to visibly map to an 8-bit binary number.
Making 256 glyphs is also a lot of work. So I wrote some C to generate svg glyphs automatically. However, the resulting svg font doesn't seem correct, because when using it, every glyph gets rendered as a single filled dot, but I don't know what the issue is. Is it a programming bug? Failure to follow the svg font spec?
One error is that I manually set the style to be "black". I want this to be the font's css color, but I don't know how to "access" that "variable" from within an svg font.
Compile and run without special flags, pipe the output into "font.svg".
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef unsigned char u8;
void generateSVG(){
/* unicode braille
8 "bits" per glyph.
pattern where each bit gets placed in the glyph:
0 3
1 4
2 5
6 7
*/
const char* prelude =
"<svg width=\"100%\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">"
"<defs>"
"<font id=\"Braille-font\" horiz-adv-x=\"40\">"
"<font-face"
" units-per-em=\"40\""
" cap-height=\"80\""
" x-height=\"80\""
" ascent=\"80\""
" descent=\"0\""
" bbox=\"0, 0, 40, 80\""
" unicode-range=\"U+2800-28ff\""
" font-variant = \"normal\""
">"
"<font-face-src>"
" <font-face-name name=\"Braille Font\" />"
"</font-face-src>"
"</font-face>";
const char* postlude = "</font></defs></svg>";
printf("%s\n", prelude);
const int poslut[8][2] = {
{10,10},
{10,30},
{10,50},
{30,10},
{30,30},
{30,50},
{10,70},
{30,70}
}; // {x,y}[]
const char* cfmt = "<circle cx=\"%d\" cy=\"%d\" r=\"9\" %s/>";
const char* gfmt = "<glyph glyph-name=\"uni28%02x\" unicode=\"(%02x;\" horiz-adv-x=\"40\">";
// [0] = override the fill to "none", [1] = don't override
const char* fills[2] = {"style=\"fill:none;\" ",""};
u8 i = 0;
do {
char buffer[1024] = {'\0'};
int pos = sprintf(buffer, gfmt, i,i);
u8 bits[8] = {
[0] = i & 0b00000001,
[1] = i & 0b00000010,
[2] = i & 0b00000100,
[3] = i & 0b00001000,
[4] = i & 0b00010000,
[5] = i & 0b00100000,
[6] = i & 0b01000000,
[7] = i & 0b10000000
};
// for some reason the bit shift method (i&(1<<bit)) does not work, so an ugly lut is required
for (u8 bit = 0; bit < 8; ++bit)
{
int x = poslut[bit][0];
int y = poslut[bit][1];
//const char* fill = i&(1<<bit) ? fills[1] : fills[0] ;
//const char* fill = fills[ i&(1<<bit) != 0 ];
const char* fill = fills[bits[bit] != 0];
pos += sprintf(&buffer[pos], cfmt,
x, y, fill
);
}
pos += sprintf(&buffer[pos], "</glyph>");
printf("%s\n", buffer);
i++;
} while (i != 0); // 256 mod 256 = 0
printf("%s\n", postlude);
}
Upvotes: 0
Views: 727
Reputation: 7210
Here is an example of 'filled' and 'hollow' circle paths:
Outer circle (Clockwise): 'M cx-or,cy A or,or 1 1 1 cx+or,cy A or,or 1 1 1 cx-or,cy'
Inner circle (Counter-clockwise): 'M cx+ir,cy A ir ir 1 1 0 cx-ir,cy A ir,ir 1 1 0 cx+ir,cy'
where cx,cy - center point coordinates, ir - inner radius, or - outer radius
Filled circle is outer only, hollow is a combination of both inner and outer.
<svg width="32" height="32">
<path d="M 6,12 A 6,6 1 1 1 18,12 A 6,6 1 1 1 6,12"/>
</svg>
<svg width="32" height="32">
<path d="M 6,12 A 6,6 1 1 1 18,12 A 6,6 1 1 1 6,12 M 16,12 A 4,4 1 1 0 8,12 A 4,4 1 1 0 16,12"/>
</svg>
Upvotes: 2