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