1 // stb_easy_font.h - v1.1 - 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 // (2020-02-02) 1.1 make everything static so can compile it in more than one src file
75 // (2017-01-15) 1.0 space character takes same space as numbers; fix bad spacing of 'f'
76 // (2016-01-22) 0.7 width() supports multiline text; add height()
77 // (2015-09-13) 0.6 #include <math.h>; updated license
78 // (2015-02-01) 0.5 First release
79 //
80 // CONTRIBUTORS
81 //
82 // github:vassvik -- bug report
83 // github:podsvirov -- fix multiple definition errors
84
85 #if 0
86 // SAMPLE CODE:
87 //
88 // Here's sample code for old OpenGL; it's a lot more complicated
89 // to make work on modern APIs, and that's your problem.
90 //
91 void print_string(float x, float y, char *text, float r, float g, float b)
92 {
93 static char buffer[99999]; // ~500 chars
94 int num_quads;
95
96 num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer));
97
98 glColor3f(r,g,b);
99 glEnableClientState(GL_VERTEX_ARRAY);
100 glVertexPointer(2, GL_FLOAT, 16, buffer);
101 glDrawArrays(GL_QUADS, 0, num_quads*4);
102 glDisableClientState(GL_VERTEX_ARRAY);
103 }
104 #endif
105
106 #ifndef INCLUDE_STB_EASY_FONT_H
107 #define INCLUDE_STB_EASY_FONT_H
108
109 #include <stdlib.h>
110 #include <math.h>
111
112 static struct stb_easy_font_info_struct {
113 unsigned char advance;
114 unsigned char h_seg;
115 unsigned char v_seg;
116 } stb_easy_font_charinfo[96] = {
117 { 6, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 },
118 { 7, 3, 7 }, { 7, 6, 12 }, { 7, 8, 19 }, { 4, 16, 21 },
119 { 4, 17, 22 }, { 4, 19, 23 }, { 23, 21, 24 }, { 23, 22, 31 },
120 { 20, 23, 34 }, { 22, 23, 36 }, { 19, 24, 36 }, { 21, 25, 36 },
121 { 6, 25, 39 }, { 6, 27, 43 }, { 6, 28, 45 }, { 6, 30, 49 },
122 { 6, 33, 53 }, { 6, 34, 57 }, { 6, 40, 58 }, { 6, 46, 59 },
123 { 6, 47, 62 }, { 6, 55, 64 }, { 19, 57, 68 }, { 20, 59, 68 },
124 { 21, 61, 69 }, { 22, 66, 69 }, { 21, 68, 69 }, { 7, 73, 69 },
125 { 9, 75, 74 }, { 6, 78, 81 }, { 6, 80, 85 }, { 6, 83, 90 },
126 { 6, 85, 91 }, { 6, 87, 95 }, { 6, 90, 96 }, { 7, 92, 97 },
127 { 6, 96,102 }, { 5, 97,106 }, { 6, 99,107 }, { 6,100,110 },
128 { 6,100,115 }, { 7,101,116 }, { 6,101,121 }, { 6,101,125 },
129 { 6,102,129 }, { 7,103,133 }, { 6,104,140 }, { 6,105,145 },
130 { 7,107,149 }, { 6,108,151 }, { 7,109,155 }, { 7,109,160 },
131 { 7,109,165 }, { 7,118,167 }, { 6,118,172 }, { 4,120,176 },
132 { 6,122,177 }, { 4,122,181 }, { 23,124,182 }, { 22,129,182 },
133 { 4,130,182 }, { 22,131,183 }, { 6,133,187 }, { 22,135,191 },
134 { 6,137,192 }, { 22,139,196 }, { 6,144,197 }, { 22,147,198 },
135 { 6,150,202 }, { 19,151,206 }, { 21,152,207 }, { 6,155,209 },
136 { 3,160,210 }, { 23,160,211 }, { 22,164,216 }, { 22,165,220 },
137 { 22,167,224 }, { 22,169,228 }, { 21,171,232 }, { 21,173,233 },
138 { 5,178,233 }, { 22,179,234 }, { 23,180,238 }, { 23,180,243 },
139 { 23,180,248 }, { 22,189,248 }, { 22,191,252 }, { 5,196,252 },
140 { 3,203,252 }, { 5,203,253 }, { 22,210,253 }, { 0,214,253 },
141 };
142
143 static unsigned char stb_easy_font_hseg[214] = {
144 97,37,69,84,28,51,2,18,10,49,98,41,65,25,81,105,33,9,97,1,97,37,37,36,
145 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,
146 98,8,25,33,65,81,10,50,17,65,97,25,33,25,49,9,65,20,68,1,65,25,49,41,
147 11,105,13,101,76,10,50,10,50,98,11,99,10,98,11,50,99,11,50,11,99,8,57,
148 58,3,99,99,107,10,10,11,10,99,11,5,100,41,65,57,41,65,9,17,81,97,3,107,
149 9,97,1,97,33,25,9,25,41,100,41,26,82,42,98,27,83,42,98,26,51,82,8,41,
150 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,
151 26,82,41,25,33,82,26,49,73,35,90,17,81,41,65,57,41,65,25,81,90,114,20,
152 84,73,57,41,49,25,33,65,81,9,97,1,97,25,33,65,81,57,33,25,41,25,
153 };
154
155 static unsigned char stb_easy_font_vseg[253] = {
156 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,
157 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,
158 26,66,3,8,8,15,19,21,90,58,26,18,66,18,105,89,28,74,17,8,73,57,26,21,
159 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,
160 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,
161 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,
162 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,
163 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,
164 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,
165 20,8,8,28,18,58,89,58,26,21,89,73,89,29,20,8,8,30,7,
166 };
167
168 typedef struct
169 {
170 unsigned char c[4];
171 } stb_easy_font_color;
172
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)173 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)
174 {
175 int i,j;
176 for (i=0; i < num_segs; ++i) {
177 int len = segs[i] & 7;
178 x += (float) ((segs[i] >> 3) & 1);
179 if (len && offset+64 <= vbuf_size) {
180 float y0 = y + (float) (segs[i]>>4);
181 for (j=0; j < 4; ++j) {
182 * (float *) (vbuf+offset+0) = x + (j==1 || j==2 ? (vertical ? 1 : len) : 0);
183 * (float *) (vbuf+offset+4) = y0 + ( j >= 2 ? (vertical ? len : 1) : 0);
184 * (float *) (vbuf+offset+8) = 0.f;
185 * (stb_easy_font_color *) (vbuf+offset+12) = c;
186 offset += 16;
187 }
188 }
189 }
190 return offset;
191 }
192
193 static float stb_easy_font_spacing_val = 0;
stb_easy_font_spacing(float spacing)194 static void stb_easy_font_spacing(float spacing)
195 {
196 stb_easy_font_spacing_val = spacing;
197 }
198
stb_easy_font_print(float x,float y,char * text,unsigned char color[4],void * vertex_buffer,int vbuf_size)199 static int stb_easy_font_print(float x, float y, char *text, unsigned char color[4], void *vertex_buffer, int vbuf_size)
200 {
201 char *vbuf = (char *) vertex_buffer;
202 float start_x = x;
203 int offset = 0;
204
205 stb_easy_font_color c = { 255,255,255,255 }; // use structure copying to avoid needing depending on memcpy()
206 if (color) { c.c[0] = color[0]; c.c[1] = color[1]; c.c[2] = color[2]; c.c[3] = color[3]; }
207
208 while (*text && offset < vbuf_size) {
209 if (*text == '\n') {
210 y += 12;
211 x = start_x;
212 } else {
213 unsigned char advance = stb_easy_font_charinfo[*text-32].advance;
214 float y_ch = advance & 16 ? y+1 : y;
215 int h_seg, v_seg, num_h, num_v;
216 h_seg = stb_easy_font_charinfo[*text-32 ].h_seg;
217 v_seg = stb_easy_font_charinfo[*text-32 ].v_seg;
218 num_h = stb_easy_font_charinfo[*text-32+1].h_seg - h_seg;
219 num_v = stb_easy_font_charinfo[*text-32+1].v_seg - v_seg;
220 offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_hseg[h_seg], num_h, 0, c, vbuf, vbuf_size, offset);
221 offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_vseg[v_seg], num_v, 1, c, vbuf, vbuf_size, offset);
222 x += advance & 15;
223 x += stb_easy_font_spacing_val;
224 }
225 ++text;
226 }
227 return (unsigned) offset/64;
228 }
229
stb_easy_font_width(char * text)230 static int stb_easy_font_width(char *text)
231 {
232 float len = 0;
233 float max_len = 0;
234 while (*text) {
235 if (*text == '\n') {
236 if (len > max_len) max_len = len;
237 len = 0;
238 } else {
239 len += stb_easy_font_charinfo[*text-32].advance & 15;
240 len += stb_easy_font_spacing_val;
241 }
242 ++text;
243 }
244 if (len > max_len) max_len = len;
245 return (int) ceil(max_len);
246 }
247
stb_easy_font_height(char * text)248 static int stb_easy_font_height(char *text)
249 {
250 float y = 0;
251 int nonempty_line=0;
252 while (*text) {
253 if (*text == '\n') {
254 y += 12;
255 nonempty_line = 0;
256 } else {
257 nonempty_line = 1;
258 }
259 ++text;
260 }
261 return (int) ceil(y + (nonempty_line ? 12 : 0));
262 }
263 #endif
264
265 /*
266 ------------------------------------------------------------------------------
267 This software is available under 2 licenses -- choose whichever you prefer.
268 ------------------------------------------------------------------------------
269 ALTERNATIVE A - MIT License
270 Copyright (c) 2017 Sean Barrett
271 Permission is hereby granted, free of charge, to any person obtaining a copy of
272 this software and associated documentation files (the "Software"), to deal in
273 the Software without restriction, including without limitation the rights to
274 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
275 of the Software, and to permit persons to whom the Software is furnished to do
276 so, subject to the following conditions:
277 The above copyright notice and this permission notice shall be included in all
278 copies or substantial portions of the Software.
279 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
280 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
281 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
282 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
283 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
284 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
285 SOFTWARE.
286 ------------------------------------------------------------------------------
287 ALTERNATIVE B - Public Domain (www.unlicense.org)
288 This is free and unencumbered software released into the public domain.
289 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
290 software, either in source code form or as a compiled binary, for any purpose,
291 commercial or non-commercial, and by any means.
292 In jurisdictions that recognize copyright laws, the author or authors of this
293 software dedicate any and all copyright interest in the software to the public
294 domain. We make this dedication for the benefit of the public at large and to
295 the detriment of our heirs and successors. We intend this dedication to be an
296 overt act of relinquishment in perpetuity of all present and future rights to
297 this software under copyright law.
298 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
299 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
300 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
301 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
302 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
303 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
304 ------------------------------------------------------------------------------
305 */
306