-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy path1bitfont.html
203 lines (197 loc) · 7.03 KB
/
1bitfont.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<script src='jquery.min.js'></script>
<style type="text/css">
body, html {
background: #eee;
color: black;
font-family: monospace;
font-size: 11px;
text-align: center;
}
h2 {
font-size: 16px;
}
h3 {
font-size: 13px;
}
#main {
background: white;
margin: auto;
max-width: 520px;
text-align: left;
padding: 60px 40px;
}
#out {
font-size: 10px;
max-width: 100%;
overflow: auto;
}
li {
margin-bottom: 10px;
}
</style>
<script>
var ufont_image;
function generate() {
if (!ufont_image) {
alert("source image not valid");
return;
}
var canvas=document.createElement('canvas');
canvas.width=ufont_image.width;
canvas.height=ufont_image.height;
var ctx=canvas.getContext('2d');
ctx.drawImage(ufont_image, 0, 0);
var cdata = ctx.getImageData(0, 0, ufont_image.width, ufont_image.height);
var data=cdata.data;
var glyphs_def=[ { s: 0, e: null } ];
var maxbc=-1;
//find glyph separators
for (var x=0; x<cdata.width; x++) {
var sep=true;
for (var y=0; y<cdata.height; y++) {
var idx=(x+y*cdata.width) * 4;
var r = data[idx + 0];
var g = data[idx + 1];
var b = data[idx + 2];
if (!(r==g && g==b && b==255))
sep=false;
}
if (sep) {
var last=glyphs_def[glyphs_def.length-1];
last.e=x;
var bcount=Math.ceil((last.e-last.s)/8);
if (bcount>maxbc)
maxbc=bcount;
if (last.e<=last.s) {
last.s=x+1;
} else {
glyphs_def.push({ s: x+1, e: null });
}
}
}
var ostring="";
var bino=$('#binout').is(':checked');
var fmt=bino ? 'bin' : 'hex';
var packed=$('#single').is(':checked');
var gcount=0;
/*binary dump*/
for (var k=0; k!=glyphs_def.length; k++) {
var gd=glyphs_def[k];
var gdlen=gd.e-gd.s;
if (gdlen<0)
continue;
gcount++;
var gstring="{"+(packed ? ' ' : '\n')+(gdlen<10 ? ' ' : '')+gdlen+',0,0,0,'+(packed ? ' ' : '\n');
for (var y = 0; y < cdata.height; y++) {
var pshift=7;
var bi=0;
var bytes=[];
for (var v=0; v!=maxbc; v++)
bytes.push(0);
for (var x = gd.s; x < gd.e; x++) {
var idx = (x + y * cdata.width) * 4;
var r = data[idx + 0];
var g = data[idx + 1];
var b = data[idx + 2];
if (r==g && g==b && b==0)
bytes[bi]|=1<<pshift;
pshift--;
if (pshift<0) {
pshift=7;
bi++;
}
}
for (var v=0; v!=maxbc; v++) {
var outpixel=bytes[v];
if (fmt=='bin') {
var os=outpixel.toString(2);
while (os.length<8)
os='0'+os;
gstring+="0b"+os+",";
} else if (fmt=='hex') {
var os=outpixel.toString(16);
if (os.length<2)
os='0'+os;
gstring+="0x"+os+",";
} else {
var os=""+outpixel;
while (os.length<3)
os=" "+os;
gstring+=os+",";
}
}
gstring+=packed ? ' ' : '\n';
}
var s=String.fromCharCode(k==94 ? 163 : (k+33));
var comment="//glyph '"+s+"' code="+k+"\n";
gstring+="},";
if (packed)
ostring+=gstring+'\t'+comment;
else
ostring+=comment+gstring+'\n';
}
var fontname=$('#vname').val();
var header="//font generated from 1BITFONT - by Sandro Maffiodo\n"+
"#define FNT_"+fontname.toUpperCase()+"_HEIGHT "+cdata.height+"\n"+
"#define FNT_"+fontname.toUpperCase()+"_SYMBOLS_COUNT "+gcount+"\n"+
"#define FNT_"+fontname.toUpperCase()+"_GLYPH_WIDTH "+maxbc+"\n"+
"//data size="+(gcount*cdata.height)+" bytes\n"+
"const unsigned char ESPVGAX_ALIGN32 fnt_"+fontname+"_data[FNT_"+fontname.toUpperCase()+"_SYMBOLS_COUNT][4+FNT_"+fontname.toUpperCase()+"_HEIGHT*FNT_"+fontname.toUpperCase()+"_GLYPH_WIDTH] PROGMEM={\n";
var footer="};\n";
$('#out').text(header+ostring+footer);
}
function boot() {
$('#f').on('change', function(ev) {
var f = ev.target.files[0];
var fr = new FileReader();
fr.onload = function(ev2) {
console.dir(ev2);
ufont_image=new Image;
ufont_image.src=ev2.target.result;
$('#preview').attr('src', ev2.target.result);
$('#previewbox').show();
};
fr.readAsDataURL(f);
});
}
$(document).ready(boot);
</script>
<body>
<div id='main'>
<h2><b>1BITFONT</b></h2>
by Sandro Maffiodo
<h3>WHAT IS:</h3>
1BITFONT is a simple web tool to generate bit fonts for ESPVGAX library. <br>
<br>
1BITFONT read an image where all the fonts glyphs are layouted in a single
line. Each glyph must be separated from the next with a single white line.
The tool will autodetect the glyph boundaries and generate a byte table
where each byte is 8 horizontal pixels of the glyph. All glyphs will
have the same height but different widths. The first byte of the glyph,
inside the generated table, is the glyph width (in pixels, where 1pixel=1bit).
<h3>RULES:</h3>
<ul>
<li>source image must have all glyphs on a single line. black is foreground color, white is background</li>
<li>the image must contain only the ASCII characters from !(33) to £(128)</li>
<li>the height of the font is equal to the height of the source image</li>
<li>source image must use a single pixel to delimitate all glyphs (white line separator). <br> When a white line is part of the glyph (for example the glyph ") you can use a red pixel to join the two separated pixels</li>
<li>the maximum width of a single glyph must be less or equal 8</li>
</ul>
<h3>INPUT:</h3>
source image: <input id="f" type="file" /><br>
<div id='previewbox' style='display: none'>
<br>
<img id='preview' style='max-width: 100%'/>
</div>
<br>
<input id="single" type="checkbox" checked/> generate one glyph as a single line<br>
<br>
<input id="binout" type="checkbox" /> use binary numbers (0b0100)<br>
<BR>
output variable name:
<input value="varname" type='text' id='vname'/>
<h3>OUTPUT:</h3>
<button onclick='generate()'>GENERATE</button>
<pre id='out'></pre>
</div>
</body>