1 // stb_easy_font.h - v1.0 - bitmap font for 3D rendering - public domain
2 // Sean Barrett, Feb 2015
3 //
4 // Easy-to-deploy,
5 // reasonably compact,
6 // extremely inefficient performance-wise,
7 // crappy-looking,
8 // ASCII-only,
9 // bitmap font for use in 3D APIs.
10 //
11 // Intended for when you just want to get some text displaying
12 // in a 3D app as quickly as possible.
13 //
14 // Doesn't use any textures, instead builds characters out of quads.
15 //
16 // DOCUMENTATION:
17 //
18 // int stb_easy_font_width(char *text)
19 // int stb_easy_font_height(char *text)
20 //
21 // Takes a string and returns the horizontal size and the
22 // vertical size (which can vary if 'text' has newlines).
23 //
24 // int stb_easy_font_print(float x, float y,
25 // char *text, unsigned char color[4],
26 // void *vertex_buffer, int vbuf_size)
27 //
28 // Takes a string (which can contain '\n') and fills out a
29 // vertex buffer with renderable data to draw the string.
30 // Output data assumes increasing x is rightwards, increasing y
31 // is downwards.
32 //
33 // The vertex data is divided into quads, i.e. there are four
34 // vertices in the vertex buffer for each quad.
35 //
36 // The vertices are stored in an interleaved format:
37 //
38 // x:float
39 // y:float
40 // z:float
41 // color:uint8[4]
42 //
43 // You can ignore z and color if you get them from elsewhere
44 // This format was chosen in the hopes it would make it
45 // easier for you to reuse existing vertex-buffer-drawing code.
46 //
47 // If you pass in NULL for color, it becomes 255,255,255,255.
48 //
49 // Returns the number of quads.
50 //
51 // If the buffer isn't large enough, it will truncate.
52 // Expect it to use an average of ~270 bytes per character.
53 //
54 // If your API doesn't draw quads, build a reusable index
55 // list that allows you to render quads as indexed triangles.
56 //
57 // void stb_easy_font_spacing(float spacing)
58 //
59 // Use positive values to expand the space between characters,
60 // and small negative values (no smaller than -1.5) to contract
61 // the space between characters.
62 //
63 // E.g. spacing = 1 adds one "pixel" of spacing between the
64 // characters. spacing = -1 is reasonable but feels a bit too
65 // compact to me; -0.5 is a reasonable compromise as long as
66 // you're scaling the font up.
67 //
68 // LICENSE
69 //
70 // See end of file for license information.
71 //
72 // VERSION HISTORY
73 //
74 // (2017-01-15) 1.0 space character takes same space as numbers; fix bad spacing of 'f'
75 // (2016-01-22) 0.7 width() supports multiline text; add height()
76 // (2015-09-13) 0.6 #include <math.h>; updated license
77 // (2015-02-01) 0.5 First release
78 //
79 // CONTRIBUTORS
80 //
81 // github:vassvik -- bug report
82
83 #if 0
84 // SAMPLE CODE:
85 //
86 // Here's sample code for old OpenGL; it's a lot more complicated
87 // to make work on modern APIs, and that's your problem.
88 //
89 void print_string(float x, float y, char *text, float r, float g, float b)
90 {
91 static char buffer[99999]; // ~500 chars
92 int num_quads;
93
94 num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer));
95
96 glColor3f(r,g,b);
97 glEnableClientState(GL_VERTEX_ARRAY);
98 glVertexPointer(2, GL_FLOAT, 16, buffer);
99 glDrawArrays(GL_QUADS, 0, num_quads*4);
100 glDisableClientState(GL_VERTEX_ARRAY);
101 }
102 #endif
103
104 #ifndef INCLUDE_STB_EASY_FONT_H
105 #define INCLUDE_STB_EASY_FONT_H
106
107 #include <stdlib.h>
108 #include <math.h>
109
110 struct stb_easy_font_info_struct {
111 unsigned char advance;
112 unsigned char h_seg;
113 unsigned char v_seg;
114 } stb_easy_font_charinfo[96] = {
115 { 6, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 },
116 { 7, 3, 7 }, { 7, 6, 12 }, { 7, 8, 19 }, { 4, 16, 21 },
117 { 4, 17, 22 }, { 4, 19, 23 }, { 23, 21, 24 }, { 23, 22, 31 },
118 { 20, 23, 34 }, { 22, 23, 36 }, { 19, 24, 36 }, { 21, 25, 36 },
119 { 6, 25, 39 }, { 6, 27, 43 }, { 6, 28, 45 }, { 6, 30, 49 },
120 { 6, 33, 53 }, { 6, 34, 57 }, { 6, 40, 58 }, { 6, 46, 59 },
121 { 6, 47, 62 }, { 6, 55, 64 }, { 19, 57, 68 }, { 20, 59, 68 },
122 { 21, 61, 69 }, { 22, 66, 69 }, { 21, 68, 69 }, { 7, 73, 69 },
123 { 9, 75, 74 }, { 6, 78, 81 }, { 6, 80, 85 }, { 6, 83, 90 },
124 { 6, 85, 91 }, { 6, 87, 95 }, { 6, 90, 96 }, { 7, 92, 97 },
125 { 6, 96,102 }, { 5, 97,106 }, { 6, 99,107 }, { 6,100,110 },
126 { 6,100,115 }, { 7,101,116 }, { 6,101,121 }, { 6,101,125 },
127 { 6,102,129 }, { 7,103,133 }, { 6,104,140 }, { 6,105,145 },
128 { 7,107,149 }, { 6,108,151 }, { 7,109,155 }, { 7,109,160 },
129 { 7,109,165 }, { 7,118,167 }, { 6,118,172 }, { 4,120,176 },
130 { 6,122,177 }, { 4,122,181 }, { 23,124,182 }, { 22,129,182 },
131 { 4,130,182 }, { 22,131,183 }, { 6,133,187 }, { 22,135,191 },
132 { 6,137,192 }, { 22,139,196 }, { 6,144,197 }, { 22,147,198 },
133 { 6,150,202 }, { 19,151,206 }, { 21,152,207 }, { 6,155,209 },
134 { 3,160,210 }, { 23,160,211 }, { 22,164,216 }, { 22,165,220 },
135 { 22,167,224 }, { 22,169,228 }, { 21,171,232 }, { 21,173,233 },
136 { 5,178,233 }, { 22,179,234 }, { 23,180,238 }, { 23,180,243 },
137 { 23,180,248 }, { 22,189,248 }, { 22,191,252 }, { 5,196,252 },
138 { 3,203,252 }, { 5,203,253 }, { 22,210,253 }, { 0,214,253 },
139 };
140
141 unsigned char stb_easy_font_hseg[214] = {
142 97,37,69,84,28,51,2,18,10,49,98,41,65,25,81,105,33,9,97,1,97,37,37,36,
143 81,10,98,107,3,100,3,99,58,51,4,99,58,8,73,81,10,50,98,8,73,81,4,10,50,
144 98,8,25,33,65,81,10,50,17,65,97,25,33,25,49,9,65,20,68,1,65,25,49,41,
145 11,105,13,101,76,10,50,10,50,98,11,99,10,98,11,50,99,11,50,11,99,8,57,
146 58,3,99,99,107,10,10,11,10,99,11,5,100,41,65,57,41,65,9,17,81,97,3,107,
147 9,97,1,97,33,25,9,25,41,100,41,26,82,42,98,27,83,42,98,26,51,82,8,41,
148 35,8,10,26,82,114,42,1,114,8,9,73,57,81,41,97,18,8,8,25,26,26,82,26,82,
149 26,82,41,25,33,82,26,49,73,35,90,17,81,41,65,57,41,65,25,81,90,114,20,
150 84,73,57,41,49,25,33,65,81,9,97,1,97,25,33,65,81,57,33,25,41,25,
151 };
152
153 unsigned char stb_easy_font_vseg[253] = {
154 4,2,8,10,15,8,15,33,8,15,8,73,82,73,57,41,82,10,82,18,66,10,21,29,1,65,
155 27,8,27,9,65,8,10,50,97,74,66,42,10,21,57,41,29,25,14,81,73,57,26,8,8,
156 26,66,3,8,8,15,19,21,90,58,26,18,66,18,105,89,28,74,17,8,73,57,26,21,
157 8,42,41,42,8,28,22,8,8,30,7,8,8,26,66,21,7,8,8,29,7,7,21,8,8,8,59,7,8,
158 8,15,29,8,8,14,7,57,43,10,82,7,7,25,42,25,15,7,25,41,15,21,105,105,29,
159 7,57,57,26,21,105,73,97,89,28,97,7,57,58,26,82,18,57,57,74,8,30,6,8,8,
160 14,3,58,90,58,11,7,74,43,74,15,2,82,2,42,75,42,10,67,57,41,10,7,2,42,
161 74,106,15,2,35,8,8,29,7,8,8,59,35,51,8,8,15,35,30,35,8,8,30,7,8,8,60,
162 36,8,45,7,7,36,8,43,8,44,21,8,8,44,35,8,8,43,23,8,8,43,35,8,8,31,21,15,
163 20,8,8,28,18,58,89,58,26,21,89,73,89,29,20,8,8,30,7,
164 };
165
166 typedef struct
167 {
168 unsigned char c[4];
169 } stb_easy_font_color;
170
stb_easy_font_draw_segs(float x,float y,unsigned char * segs,int num_segs,int vertical,stb_easy_font_color c,char * vbuf,int vbuf_size,int offset)171 static int stb_easy_font_draw_segs(float x, float y, unsigned char *segs, int num_segs, int vertical, stb_easy_font_color c, char *vbuf, int vbuf_size, int offset)
172 {
173 int i,j;
174 for (i=0; i < num_segs; ++i) {
175 int len = segs[i] & 7;
176 x += (float) ((segs[i] >> 3) & 1);
177 if (len && offset+64 <= vbuf_size) {
178 float y0 = y + (float) (segs[i]>>4);
179 for (j=0; j < 4; ++j) {
180 * (float *) (vbuf+offset+0) = x + (j==1 || j==2 ? (vertical ? 1 : len) : 0);
181 * (float *) (vbuf+offset+4) = y0 + ( j >= 2 ? (vertical ? len : 1) : 0);
182 * (float *) (vbuf+offset+8) = 0.f;
183 * (stb_easy_font_color *) (vbuf+offset+12) = c;
184 offset += 16;
185 }
186 }
187 }
188 return offset;
189 }
190
191 float stb_easy_font_spacing_val = 0;
stb_easy_font_spacing(float spacing)192 static void stb_easy_font_spacing(float spacing)
193 {
194 stb_easy_font_spacing_val = spacing;
195 }
196
stb_easy_font_print(float x,float y,char * text,unsigned char color[4],void * vertex_buffer,int vbuf_size)197 static int stb_easy_font_print(float x, float y, char *text, unsigned char color[4], void *vertex_buffer, int vbuf_size)
198 {
199 char *vbuf = (char *) vertex_buffer;
200 float start_x = x;
201 int offset = 0;
202
203 stb_easy_font_color c = { 255,255,255,255 }; // use structure copying to avoid needing depending on memcpy()
204 if (color) { c.c[0] = color[0]; c.c[1] = color[1]; c.c[2] = color[2]; c.c[3] = color[3]; }
205
206 while (*text && offset < vbuf_size) {
207 if (*text == '\n') {
208 y += 12;
209 x = start_x;
210 } else {
211 unsigned char advance = stb_easy_font_charinfo[*text-32].advance;
212 float y_ch = advance & 16 ? y+1 : y;
213 int h_seg, v_seg, num_h, num_v;
214 h_seg = stb_easy_font_charinfo[*text-32 ].h_seg;
215 v_seg = stb_easy_font_charinfo[*text-32 ].v_seg;
216 num_h = stb_easy_font_charinfo[*text-32+1].h_seg - h_seg;
217 num_v = stb_easy_font_charinfo[*text-32+1].v_seg - v_seg;
218 offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_hseg[h_seg], num_h, 0, c, vbuf, vbuf_size, offset);
219 offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_vseg[v_seg], num_v, 1, c, vbuf, vbuf_size, offset);
220 x += advance & 15;
221 x += stb_easy_font_spacing_val;
222 }
223 ++text;
224 }
225 return (unsigned) offset/64;
226 }
227
stb_easy_font_width(char * text)228 static int stb_easy_font_width(char *text)
229 {
230 float len = 0;
231 float max_len = 0;
232 while (*text) {
233 if (*text == '\n') {
234 if (len > max_len) max_len = len;
235 len = 0;
236 } else {
237 len += stb_easy_font_charinfo[*text-32].advance & 15;
238 len += stb_easy_font_spacing_val;
239 }
240 ++text;
241 }
242 if (len > max_len) max_len = len;
243 return (int) ceil(max_len);
244 }
245
stb_easy_font_height(char * text)246 static int stb_easy_font_height(char *text)
247 {
248 float y = 0;
249 int nonempty_line=0;
250 while (*text) {
251 if (*text == '\n') {
252 y += 12;
253 nonempty_line = 0;
254 } else {
255 nonempty_line = 1;
256 }
257 ++text;
258 }
259 return (int) ceil(y + (nonempty_line ? 12 : 0));
260 }
261 #endif
262
263 /*
264 ------------------------------------------------------------------------------
265 This software is available under 2 licenses -- choose whichever you prefer.
266 ------------------------------------------------------------------------------
267 ALTERNATIVE A - MIT License
268 Copyright (c) 2017 Sean Barrett
269 Permission is hereby granted, free of charge, to any person obtaining a copy of
270 this software and associated documentation files (the "Software"), to deal in
271 the Software without restriction, including without limitation the rights to
272 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
273 of the Software, and to permit persons to whom the Software is furnished to do
274 so, subject to the following conditions:
275 The above copyright notice and this permission notice shall be included in all
276 copies or substantial portions of the Software.
277 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
278 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
279 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
280 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
281 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
282 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
283 SOFTWARE.
284 ------------------------------------------------------------------------------
285 ALTERNATIVE B - Public Domain (www.unlicense.org)
286 This is free and unencumbered software released into the public domain.
287 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
288 software, either in source code form or as a compiled binary, for any purpose,
289 commercial or non-commercial, and by any means.
290 In jurisdictions that recognize copyright laws, the author or authors of this
291 software dedicate any and all copyright interest in the software to the public
292 domain. We make this dedication for the benefit of the public at large and to
293 the detriment of our heirs and successors. We intend this dedication to be an
294 overt act of relinquishment in perpetuity of all present and future rights to
295 this software under copyright law.
296 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
297 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
298 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
299 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
300 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
301 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
302 ------------------------------------------------------------------------------
303 */
304