1 // [DEAR IMGUI]
2 // This is a slightly modified version of stb_truetype.h 1.20.
3 // Mostly fixing for compiler and static analyzer warnings.
4 // Grep for [DEAR IMGUI] to find the changes.
5
6 // stb_truetype.h - v1.20 - public domain
7 // authored from 2009-2016 by Sean Barrett / RAD Game Tools
8 //
9 // This library processes TrueType files:
10 // parse files
11 // extract glyph metrics
12 // extract glyph shapes
13 // render glyphs to one-channel bitmaps with antialiasing (box filter)
14 // render glyphs to one-channel SDF bitmaps (signed-distance field/function)
15 //
16 // Todo:
17 // non-MS cmaps
18 // crashproof on bad data
19 // hinting? (no longer patented)
20 // cleartype-style AA?
21 // optimize: use simple memory allocator for intermediates
22 // optimize: build edge-list directly from curves
23 // optimize: rasterize directly from curves?
24 //
25 // ADDITIONAL CONTRIBUTORS
26 //
27 // Mikko Mononen: compound shape support, more cmap formats
28 // Tor Andersson: kerning, subpixel rendering
29 // Dougall Johnson: OpenType / Type 2 font handling
30 // Daniel Ribeiro Maciel: basic GPOS-based kerning
31 //
32 // Misc other:
33 // Ryan Gordon
34 // Simon Glass
35 // github:IntellectualKitty
36 // Imanol Celaya
37 // Daniel Ribeiro Maciel
38 //
39 // Bug/warning reports/fixes:
40 // "Zer" on mollyrocket Fabian "ryg" Giesen
41 // Cass Everitt Martins Mozeiko
42 // stoiko (Haemimont Games) Cap Petschulat
43 // Brian Hook Omar Cornut
44 // Walter van Niftrik github:aloucks
45 // David Gow Peter LaValle
46 // David Given Sergey Popov
47 // Ivan-Assen Ivanov Giumo X. Clanjor
48 // Anthony Pesch Higor Euripedes
49 // Johan Duparc Thomas Fields
50 // Hou Qiming Derek Vinyard
51 // Rob Loach Cort Stratton
52 // Kenney Phillis Jr. github:oyvindjam
53 // Brian Costabile github:vassvik
54 //
55 // VERSION HISTORY
56 //
57 // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
58 // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
59 // 1.18 (2018-01-29) add missing function
60 // 1.17 (2017-07-23) make more arguments const; doc fix
61 // 1.16 (2017-07-12) SDF support
62 // 1.15 (2017-03-03) make more arguments const
63 // 1.14 (2017-01-16) num-fonts-in-TTC function
64 // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
65 // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
66 // 1.11 (2016-04-02) fix unused-variable warning
67 // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
68 // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
69 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
70 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
71 // variant PackFontRanges to pack and render in separate phases;
72 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
73 // fixed an assert() bug in the new rasterizer
74 // replace assert() with STBTT_assert() in new rasterizer
75 //
76 // Full history can be found at the end of this file.
77 //
78 // LICENSE
79 //
80 // See end of file for license information.
81 //
82 // USAGE
83 //
84 // Include this file in whatever places need to refer to it. In ONE C/C++
85 // file, write:
86 // #define STB_TRUETYPE_IMPLEMENTATION
87 // before the #include of this file. This expands out the actual
88 // implementation into that C/C++ file.
89 //
90 // To make the implementation private to the file that generates the implementation,
91 // #define STBTT_STATIC
92 //
93 // Simple 3D API (don't ship this, but it's fine for tools and quick start)
94 // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
95 // stbtt_GetBakedQuad() -- compute quad to draw for a given char
96 //
97 // Improved 3D API (more shippable):
98 // #include "stb_rect_pack.h" -- optional, but you really want it
99 // stbtt_PackBegin()
100 // stbtt_PackSetOversampling() -- for improved quality on small fonts
101 // stbtt_PackFontRanges() -- pack and renders
102 // stbtt_PackEnd()
103 // stbtt_GetPackedQuad()
104 //
105 // "Load" a font file from a memory buffer (you have to keep the buffer loaded)
106 // stbtt_InitFont()
107 // stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
108 // stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
109 //
110 // Render a unicode codepoint to a bitmap
111 // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
112 // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
113 // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
114 //
115 // Character advance/positioning
116 // stbtt_GetCodepointHMetrics()
117 // stbtt_GetFontVMetrics()
118 // stbtt_GetFontVMetricsOS2()
119 // stbtt_GetCodepointKernAdvance()
120 //
121 // Starting with version 1.06, the rasterizer was replaced with a new,
122 // faster and generally-more-precise rasterizer. The new rasterizer more
123 // accurately measures pixel coverage for anti-aliasing, except in the case
124 // where multiple shapes overlap, in which case it overestimates the AA pixel
125 // coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
126 // this turns out to be a problem, you can re-enable the old rasterizer with
127 // #define STBTT_RASTERIZER_VERSION 1
128 // which will incur about a 15% speed hit.
129 //
130 // ADDITIONAL DOCUMENTATION
131 //
132 // Immediately after this block comment are a series of sample programs.
133 //
134 // After the sample programs is the "header file" section. This section
135 // includes documentation for each API function.
136 //
137 // Some important concepts to understand to use this library:
138 //
139 // Codepoint
140 // Characters are defined by unicode codepoints, e.g. 65 is
141 // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
142 // the hiragana for "ma".
143 //
144 // Glyph
145 // A visual character shape (every codepoint is rendered as
146 // some glyph)
147 //
148 // Glyph index
149 // A font-specific integer ID representing a glyph
150 //
151 // Baseline
152 // Glyph shapes are defined relative to a baseline, which is the
153 // bottom of uppercase characters. Characters extend both above
154 // and below the baseline.
155 //
156 // Current Point
157 // As you draw text to the screen, you keep track of a "current point"
158 // which is the origin of each character. The current point's vertical
159 // position is the baseline. Even "baked fonts" use this model.
160 //
161 // Vertical Font Metrics
162 // The vertical qualities of the font, used to vertically position
163 // and space the characters. See docs for stbtt_GetFontVMetrics.
164 //
165 // Font Size in Pixels or Points
166 // The preferred interface for specifying font sizes in stb_truetype
167 // is to specify how tall the font's vertical extent should be in pixels.
168 // If that sounds good enough, skip the next paragraph.
169 //
170 // Most font APIs instead use "points", which are a common typographic
171 // measurement for describing font size, defined as 72 points per inch.
172 // stb_truetype provides a point API for compatibility. However, true
173 // "per inch" conventions don't make much sense on computer displays
174 // since different monitors have different number of pixels per
175 // inch. For example, Windows traditionally uses a convention that
176 // there are 96 pixels per inch, thus making 'inch' measurements have
177 // nothing to do with inches, and thus effectively defining a point to
178 // be 1.333 pixels. Additionally, the TrueType font data provides
179 // an explicit scale factor to scale a given font's glyphs to points,
180 // but the author has observed that this scale factor is often wrong
181 // for non-commercial fonts, thus making fonts scaled in points
182 // according to the TrueType spec incoherently sized in practice.
183 //
184 // DETAILED USAGE:
185 //
186 // Scale:
187 // Select how high you want the font to be, in points or pixels.
188 // Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
189 // a scale factor SF that will be used by all other functions.
190 //
191 // Baseline:
192 // You need to select a y-coordinate that is the baseline of where
193 // your text will appear. Call GetFontBoundingBox to get the baseline-relative
194 // bounding box for all characters. SF*-y0 will be the distance in pixels
195 // that the worst-case character could extend above the baseline, so if
196 // you want the top edge of characters to appear at the top of the
197 // screen where y=0, then you would set the baseline to SF*-y0.
198 //
199 // Current point:
200 // Set the current point where the first character will appear. The
201 // first character could extend left of the current point; this is font
202 // dependent. You can either choose a current point that is the leftmost
203 // point and hope, or add some padding, or check the bounding box or
204 // left-side-bearing of the first character to be displayed and set
205 // the current point based on that.
206 //
207 // Displaying a character:
208 // Compute the bounding box of the character. It will contain signed values
209 // relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
210 // then the character should be displayed in the rectangle from
211 // <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
212 //
213 // Advancing for the next character:
214 // Call GlyphHMetrics, and compute 'current_point += SF * advance'.
215 //
216 //
217 // ADVANCED USAGE
218 //
219 // Quality:
220 //
221 // - Use the functions with Subpixel at the end to allow your characters
222 // to have subpixel positioning. Since the font is anti-aliased, not
223 // hinted, this is very import for quality. (This is not possible with
224 // baked fonts.)
225 //
226 // - Kerning is now supported, and if you're supporting subpixel rendering
227 // then kerning is worth using to give your text a polished look.
228 //
229 // Performance:
230 //
231 // - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
232 // if you don't do this, stb_truetype is forced to do the conversion on
233 // every call.
234 //
235 // - There are a lot of memory allocations. We should modify it to take
236 // a temp buffer and allocate from the temp buffer (without freeing),
237 // should help performance a lot.
238 //
239 // NOTES
240 //
241 // The system uses the raw data found in the .ttf file without changing it
242 // and without building auxiliary data structures. This is a bit inefficient
243 // on little-endian systems (the data is big-endian), but assuming you're
244 // caching the bitmaps or glyph shapes this shouldn't be a big deal.
245 //
246 // It appears to be very hard to programmatically determine what font a
247 // given file is in a general way. I provide an API for this, but I don't
248 // recommend it.
249 //
250 //
251 // SOURCE STATISTICS (based on v0.6c, 2050 LOC)
252 //
253 // Documentation & header file 520 LOC \___ 660 LOC documentation
254 // Sample code 140 LOC /
255 // Truetype parsing 620 LOC ---- 620 LOC TrueType
256 // Software rasterization 240 LOC \.
257 // Curve tessellation 120 LOC \__ 550 LOC Bitmap creation
258 // Bitmap management 100 LOC /
259 // Baked bitmap interface 70 LOC /
260 // Font name matching & access 150 LOC ---- 150
261 // C runtime library abstraction 60 LOC ---- 60
262 //
263 //
264 // PERFORMANCE MEASUREMENTS FOR 1.06:
265 //
266 // 32-bit 64-bit
267 // Previous release: 8.83 s 7.68 s
268 // Pool allocations: 7.72 s 6.34 s
269 // Inline sort : 6.54 s 5.65 s
270 // New rasterizer : 5.63 s 5.00 s
271
272 //////////////////////////////////////////////////////////////////////////////
273 //////////////////////////////////////////////////////////////////////////////
274 ////
275 //// SAMPLE PROGRAMS
276 ////
277 //
278 // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
279 //
280 #if 0
281 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
282 #include "stb_truetype.h"
283
284 unsigned char ttf_buffer[1<<20];
285 unsigned char temp_bitmap[512*512];
286
287 stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
288 GLuint ftex;
289
290 void my_stbtt_initfont(void)
291 {
292 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
293 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
294 // can free ttf_buffer at this point
295 glGenTextures(1, &ftex);
296 glBindTexture(GL_TEXTURE_2D, ftex);
297 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
298 // can free temp_bitmap at this point
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
300 }
301
302 void my_stbtt_print(float x, float y, char *text)
303 {
304 // assume orthographic projection with units = screen pixels, origin at top left
305 glEnable(GL_TEXTURE_2D);
306 glBindTexture(GL_TEXTURE_2D, ftex);
307 glBegin(GL_QUADS);
308 while (*text) {
309 if (*text >= 32 && *text < 128) {
310 stbtt_aligned_quad q;
311 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
312 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
313 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
314 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
315 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
316 }
317 ++text;
318 }
319 glEnd();
320 }
321 #endif
322 //
323 //
324 //////////////////////////////////////////////////////////////////////////////
325 //
326 // Complete program (this compiles): get a single bitmap, print as ASCII art
327 //
328 #if 0
329 #include <stdio.h>
330 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
331 #include "stb_truetype.h"
332
333 char ttf_buffer[1<<25];
334
335 int main(int argc, char **argv)
336 {
337 stbtt_fontinfo font;
338 unsigned char *bitmap;
339 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
340
341 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
342
343 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
344 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
345
346 for (j=0; j < h; ++j) {
347 for (i=0; i < w; ++i)
348 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
349 putchar('\n');
350 }
351 return 0;
352 }
353 #endif
354 //
355 // Output:
356 //
357 // .ii.
358 // @@@@@@.
359 // V@Mio@@o
360 // :i. V@V
361 // :oM@@M
362 // :@@@MM@M
363 // @@o o@M
364 // :@@. M@M
365 // @@@o@@@@
366 // :M@@V:@@.
367 //
368 //////////////////////////////////////////////////////////////////////////////
369 //
370 // Complete program: print "Hello World!" banner, with bugs
371 //
372 #if 0
373 char buffer[24<<20];
374 unsigned char screen[20][79];
375
376 int main(int arg, char **argv)
377 {
378 stbtt_fontinfo font;
379 int i,j,ascent,baseline,ch=0;
380 float scale, xpos=2; // leave a little padding in case the character extends left
381 char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
382
383 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
384 stbtt_InitFont(&font, buffer, 0);
385
386 scale = stbtt_ScaleForPixelHeight(&font, 15);
387 stbtt_GetFontVMetrics(&font, &ascent,0,0);
388 baseline = (int) (ascent*scale);
389
390 while (text[ch]) {
391 int advance,lsb,x0,y0,x1,y1;
392 float x_shift = xpos - (float) floor(xpos);
393 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
394 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
395 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
396 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
397 // because this API is really for baking character bitmaps into textures. if you want to render
398 // a sequence of characters, you really need to render each bitmap to a temp buffer, then
399 // "alpha blend" that into the working buffer
400 xpos += (advance * scale);
401 if (text[ch+1])
402 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
403 ++ch;
404 }
405
406 for (j=0; j < 20; ++j) {
407 for (i=0; i < 78; ++i)
408 putchar(" .:ioVM@"[screen[j][i]>>5]);
409 putchar('\n');
410 }
411
412 return 0;
413 }
414 #endif
415
416
417 //////////////////////////////////////////////////////////////////////////////
418 //////////////////////////////////////////////////////////////////////////////
419 ////
420 //// INTEGRATION WITH YOUR CODEBASE
421 ////
422 //// The following sections allow you to supply alternate definitions
423 //// of C library functions used by stb_truetype, e.g. if you don't
424 //// link with the C runtime library.
425
426 #ifdef STB_TRUETYPE_IMPLEMENTATION
427 // #define your own (u)stbtt_int8/16/32 before including to override this
428 #ifndef stbtt_uint8
429 typedef unsigned char stbtt_uint8;
430 typedef signed char stbtt_int8;
431 typedef unsigned short stbtt_uint16;
432 typedef signed short stbtt_int16;
433 typedef unsigned int stbtt_uint32;
434 typedef signed int stbtt_int32;
435 #endif
436
437 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
438 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
439
440 // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
441 #ifndef STBTT_ifloor
442 #include <math.h>
443 #define STBTT_ifloor(x) ((int) floor(x))
444 #define STBTT_iceil(x) ((int) ceil(x))
445 #endif
446
447 #ifndef STBTT_sqrt
448 #include <math.h>
449 #define STBTT_sqrt(x) sqrt(x)
450 #define STBTT_pow(x,y) pow(x,y)
451 #endif
452
453 #ifndef STBTT_fmod
454 #include <math.h>
455 #define STBTT_fmod(x,y) fmod(x,y)
456 #endif
457
458 #ifndef STBTT_cos
459 #include <math.h>
460 #define STBTT_cos(x) cos(x)
461 #define STBTT_acos(x) acos(x)
462 #endif
463
464 #ifndef STBTT_fabs
465 #include <math.h>
466 #define STBTT_fabs(x) fabs(x)
467 #endif
468
469 // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
470 #ifndef STBTT_malloc
471 #include <stdlib.h>
472 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
473 #define STBTT_free(x,u) ((void)(u),free(x))
474 #endif
475
476 #ifndef STBTT_assert
477 #include <assert.h>
478 #define STBTT_assert(x) assert(x)
479 #endif
480
481 #ifndef STBTT_strlen
482 #include <string.h>
483 #define STBTT_strlen(x) strlen(x)
484 #endif
485
486 #ifndef STBTT_memcpy
487 #include <string.h>
488 #define STBTT_memcpy memcpy
489 #define STBTT_memset memset
490 #endif
491 #endif
492
493 ///////////////////////////////////////////////////////////////////////////////
494 ///////////////////////////////////////////////////////////////////////////////
495 ////
496 //// INTERFACE
497 ////
498 ////
499
500 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
501 #define __STB_INCLUDE_STB_TRUETYPE_H__
502
503 #ifdef STBTT_STATIC
504 #define STBTT_DEF static
505 #else
506 #define STBTT_DEF extern
507 #endif
508
509 #ifdef __cplusplus
510 extern "C" {
511 #endif
512
513 // private structure
514 typedef struct
515 {
516 unsigned char *data;
517 int cursor;
518 int size;
519 } stbtt__buf;
520
521 //////////////////////////////////////////////////////////////////////////////
522 //
523 // TEXTURE BAKING API
524 //
525 // If you use this API, you only have to call two functions ever.
526 //
527
528 typedef struct
529 {
530 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
531 float xoff,yoff,xadvance;
532 } stbtt_bakedchar;
533
534 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
535 float pixel_height, // height of font in pixels
536 unsigned char *pixels, int pw, int ph, // bitmap to be filled in
537 int first_char, int num_chars, // characters to bake
538 stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
539 // if return is positive, the first unused row of the bitmap
540 // if return is negative, returns the negative of the number of characters that fit
541 // if return is 0, no characters fit and no rows were used
542 // This uses a very crappy packing.
543
544 typedef struct
545 {
546 float x0,y0,s0,t0; // top-left
547 float x1,y1,s1,t1; // bottom-right
548 } stbtt_aligned_quad;
549
550 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
551 int char_index, // character to display
552 float *xpos, float *ypos, // pointers to current position in screen pixel space
553 stbtt_aligned_quad *q, // output: quad to draw
554 int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
555 // Call GetBakedQuad with char_index = 'character - first_char', and it
556 // creates the quad you need to draw and advances the current position.
557 //
558 // The coordinate system used assumes y increases downwards.
559 //
560 // Characters will extend both above and below the current position;
561 // see discussion of "BASELINE" above.
562 //
563 // It's inefficient; you might want to c&p it and optimize it.
564
565 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
566 // Query the font vertical metrics without having to create a font first.
567
568
569 //////////////////////////////////////////////////////////////////////////////
570 //
571 // NEW TEXTURE BAKING API
572 //
573 // This provides options for packing multiple fonts into one atlas, not
574 // perfectly but better than nothing.
575
576 typedef struct
577 {
578 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
579 float xoff,yoff,xadvance;
580 float xoff2,yoff2;
581 } stbtt_packedchar;
582
583 typedef struct stbtt_pack_context stbtt_pack_context;
584 typedef struct stbtt_fontinfo stbtt_fontinfo;
585 #ifndef STB_RECT_PACK_VERSION
586 typedef struct stbrp_rect stbrp_rect;
587 #endif
588
589 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
590 // Initializes a packing context stored in the passed-in stbtt_pack_context.
591 // Future calls using this context will pack characters into the bitmap passed
592 // in here: a 1-channel bitmap that is width * height. stride_in_bytes is
593 // the distance from one row to the next (or 0 to mean they are packed tightly
594 // together). "padding" is the amount of padding to leave between each
595 // character (normally you want '1' for bitmaps you'll use as textures with
596 // bilinear filtering).
597 //
598 // Returns 0 on failure, 1 on success.
599
600 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
601 // Cleans up the packing context and frees all memory.
602
603 #define STBTT_POINT_SIZE(x) (-(x))
604
605 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
606 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
607 // Creates character bitmaps from the font_index'th font found in fontdata (use
608 // font_index=0 if you don't know what that is). It creates num_chars_in_range
609 // bitmaps for characters with unicode values starting at first_unicode_char_in_range
610 // and increasing. Data for how to render them is stored in chardata_for_range;
611 // pass these to stbtt_GetPackedQuad to get back renderable quads.
612 //
613 // font_size is the full height of the character from ascender to descender,
614 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
615 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
616 // and pass that result as 'font_size':
617 // ..., 20 , ... // font max minus min y is 20 pixels tall
618 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
619
620 typedef struct
621 {
622 float font_size;
623 int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
624 int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
625 int num_chars;
626 stbtt_packedchar *chardata_for_range; // output
627 unsigned char h_oversample, v_oversample; // don't set these, they're used internally
628 } stbtt_pack_range;
629
630 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
631 // Creates character bitmaps from multiple ranges of characters stored in
632 // ranges. This will usually create a better-packed bitmap than multiple
633 // calls to stbtt_PackFontRange. Note that you can call this multiple
634 // times within a single PackBegin/PackEnd.
635
636 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
637 // Oversampling a font increases the quality by allowing higher-quality subpixel
638 // positioning, and is especially valuable at smaller text sizes.
639 //
640 // This function sets the amount of oversampling for all following calls to
641 // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
642 // pack context. The default (no oversampling) is achieved by h_oversample=1
643 // and v_oversample=1. The total number of pixels required is
644 // h_oversample*v_oversample larger than the default; for example, 2x2
645 // oversampling requires 4x the storage of 1x1. For best results, render
646 // oversampled textures with bilinear filtering. Look at the readme in
647 // stb/tests/oversample for information about oversampled fonts
648 //
649 // To use with PackFontRangesGather etc., you must set it before calls
650 // call to PackFontRangesGatherRects.
651
652 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
653 // If skip != 0, this tells stb_truetype to skip any codepoints for which
654 // there is no corresponding glyph. If skip=0, which is the default, then
655 // codepoints without a glyph recived the font's "missing character" glyph,
656 // typically an empty box by convention.
657
658 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
659 int char_index, // character to display
660 float *xpos, float *ypos, // pointers to current position in screen pixel space
661 stbtt_aligned_quad *q, // output: quad to draw
662 int align_to_integer);
663
664 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
665 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
666 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
667 // Calling these functions in sequence is roughly equivalent to calling
668 // stbtt_PackFontRanges(). If you more control over the packing of multiple
669 // fonts, or if you want to pack custom data into a font texture, take a look
670 // at the source to of stbtt_PackFontRanges() and create a custom version
671 // using these functions, e.g. call GatherRects multiple times,
672 // building up a single array of rects, then call PackRects once,
673 // then call RenderIntoRects repeatedly. This may result in a
674 // better packing than calling PackFontRanges multiple times
675 // (or it may not).
676
677 // this is an opaque structure that you shouldn't mess with which holds
678 // all the context needed from PackBegin to PackEnd.
679 struct stbtt_pack_context {
680 void *user_allocator_context;
681 void *pack_info;
682 int width;
683 int height;
684 int stride_in_bytes;
685 int padding;
686 int skip_missing;
687 unsigned int h_oversample, v_oversample;
688 unsigned char *pixels;
689 void *nodes;
690 };
691
692 //////////////////////////////////////////////////////////////////////////////
693 //
694 // FONT LOADING
695 //
696 //
697
698 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
699 // This function will determine the number of fonts in a font file. TrueType
700 // collection (.ttc) files may contain multiple fonts, while TrueType font
701 // (.ttf) files only contain one font. The number of fonts can be used for
702 // indexing with the previous function where the index is between zero and one
703 // less than the total fonts. If an error occurs, -1 is returned.
704
705 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
706 // Each .ttf/.ttc file may have more than one font. Each font has a sequential
707 // index number starting from 0. Call this function to get the font offset for
708 // a given index; it returns -1 if the index is out of range. A regular .ttf
709 // file will only define one font and it always be at offset 0, so it will
710 // return '0' for index 0, and -1 for all other indices.
711
712 // The following structure is defined publicly so you can declare one on
713 // the stack or as a global or etc, but you should treat it as opaque.
714 struct stbtt_fontinfo
715 {
716 void * userdata;
717 unsigned char * data; // pointer to .ttf file
718 int fontstart; // offset of start of font
719
720 int numGlyphs; // number of glyphs, needed for range checking
721
722 int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
723 int index_map; // a cmap mapping for our chosen character encoding
724 int indexToLocFormat; // format needed to map from glyph index to glyph
725
726 stbtt__buf cff; // cff font data
727 stbtt__buf charstrings; // the charstring index
728 stbtt__buf gsubrs; // global charstring subroutines index
729 stbtt__buf subrs; // private charstring subroutines index
730 stbtt__buf fontdicts; // array of font dicts
731 stbtt__buf fdselect; // map from glyph to fontdict
732 };
733
734 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
735 // Given an offset into the file that defines a font, this function builds
736 // the necessary cached info for the rest of the system. You must allocate
737 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
738 // need to do anything special to free it, because the contents are pure
739 // value data with no additional data structures. Returns 0 on failure.
740
741
742 //////////////////////////////////////////////////////////////////////////////
743 //
744 // CHARACTER TO GLYPH-INDEX CONVERSIOn
745
746 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
747 // If you're going to perform multiple operations on the same character
748 // and you want a speed-up, call this function with the character you're
749 // going to process, then use glyph-based functions instead of the
750 // codepoint-based functions.
751 // Returns 0 if the character codepoint is not defined in the font.
752
753
754 //////////////////////////////////////////////////////////////////////////////
755 //
756 // CHARACTER PROPERTIES
757 //
758
759 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
760 // computes a scale factor to produce a font whose "height" is 'pixels' tall.
761 // Height is measured as the distance from the highest ascender to the lowest
762 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
763 // and computing:
764 // scale = pixels / (ascent - descent)
765 // so if you prefer to measure height by the ascent only, use a similar calculation.
766
767 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
768 // computes a scale factor to produce a font whose EM size is mapped to
769 // 'pixels' tall. This is probably what traditional APIs compute, but
770 // I'm not positive.
771
772 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
773 // ascent is the coordinate above the baseline the font extends; descent
774 // is the coordinate below the baseline the font extends (i.e. it is typically negative)
775 // lineGap is the spacing between one row's descent and the next row's ascent...
776 // so you should advance the vertical position by "*ascent - *descent + *lineGap"
777 // these are expressed in unscaled coordinates, so you must multiply by
778 // the scale factor for a given size
779
780 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
781 // analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
782 // table (specific to MS/Windows TTF files).
783 //
784 // Returns 1 on success (table present), 0 on failure.
785
786 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
787 // the bounding box around all possible characters
788
789 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
790 // leftSideBearing is the offset from the current horizontal position to the left edge of the character
791 // advanceWidth is the offset from the current horizontal position to the next horizontal position
792 // these are expressed in unscaled coordinates
793
794 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
795 // an additional amount to add to the 'advance' value between ch1 and ch2
796
797 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
798 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates
799
800 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
801 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
802 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
803 // as above, but takes one or more glyph indices for greater efficiency
804
805
806 //////////////////////////////////////////////////////////////////////////////
807 //
808 // GLYPH SHAPES (you probably don't need these, but they have to go before
809 // the bitmaps for C declaration-order reasons)
810 //
811
812 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
813 enum {
814 STBTT_vmove=1,
815 STBTT_vline,
816 STBTT_vcurve,
817 STBTT_vcubic
818 };
819 #endif
820
821 #ifndef stbtt_vertex // you can predefine this to use different values
822 // (we share this with other code at RAD)
823 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
824 typedef struct
825 {
826 stbtt_vertex_type x,y,cx,cy,cx1,cy1;
827 unsigned char type,padding;
828 } stbtt_vertex;
829 #endif
830
831 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
832 // returns non-zero if nothing is drawn for this glyph
833
834 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
835 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
836 // returns # of vertices and fills *vertices with the pointer to them
837 // these are expressed in "unscaled" coordinates
838 //
839 // The shape is a series of contours. Each one starts with
840 // a STBTT_moveto, then consists of a series of mixed
841 // STBTT_lineto and STBTT_curveto segments. A lineto
842 // draws a line from previous endpoint to its x,y; a curveto
843 // draws a quadratic bezier from previous endpoint to
844 // its x,y, using cx,cy as the bezier control point.
845
846 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
847 // frees the data allocated above
848
849 //////////////////////////////////////////////////////////////////////////////
850 //
851 // BITMAP RENDERING
852 //
853
854 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
855 // frees the bitmap allocated below
856
857 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
858 // allocates a large-enough single-channel 8bpp bitmap and renders the
859 // specified character/glyph at the specified scale into it, with
860 // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
861 // *width & *height are filled out with the width & height of the bitmap,
862 // which is stored left-to-right, top-to-bottom.
863 //
864 // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
865
866 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
867 // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
868 // shift for the character
869
870 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
871 // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
872 // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
873 // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
874 // width and height and positioning info for it first.
875
876 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
877 // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
878 // shift for the character
879
880 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
881 // same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
882 // is performed (see stbtt_PackSetOversampling)
883
884 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
885 // get the bbox of the bitmap centered around the glyph origin; so the
886 // bitmap width is ix1-ix0, height is iy1-iy0, and location to place
887 // the bitmap top left is (leftSideBearing*scale,iy0).
888 // (Note that the bitmap uses y-increases-down, but the shape uses
889 // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
890
891 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
892 // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
893 // shift for the character
894
895 // the following functions are equivalent to the above functions, but operate
896 // on glyph indices instead of Unicode codepoints (for efficiency)
897 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
898 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
899 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
900 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
901 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
902 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
903 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
904
905
906 // @TODO: don't expose this structure
907 typedef struct
908 {
909 int w,h,stride;
910 unsigned char *pixels;
911 } stbtt__bitmap;
912
913 // rasterize a shape with quadratic beziers into a bitmap
914 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
915 float flatness_in_pixels, // allowable error of curve in pixels
916 stbtt_vertex *vertices, // array of vertices defining shape
917 int num_verts, // number of vertices in above array
918 float scale_x, float scale_y, // scale applied to input vertices
919 float shift_x, float shift_y, // translation applied to input vertices
920 int x_off, int y_off, // another translation applied to input
921 int invert, // if non-zero, vertically flip shape
922 void *userdata); // context for to STBTT_MALLOC
923
924 //////////////////////////////////////////////////////////////////////////////
925 //
926 // Signed Distance Function (or Field) rendering
927
928 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
929 // frees the SDF bitmap allocated below
930
931 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
932 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
933 // These functions compute a discretized SDF field for a single character, suitable for storing
934 // in a single-channel texture, sampling with bilinear filtering, and testing against
935 // larger than some threshold to produce scalable fonts.
936 // info -- the font
937 // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
938 // glyph/codepoint -- the character to generate the SDF for
939 // padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
940 // which allows effects like bit outlines
941 // onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
942 // pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
943 // if positive, > onedge_value is inside; if negative, < onedge_value is inside
944 // width,height -- output height & width of the SDF bitmap (including padding)
945 // xoff,yoff -- output origin of the character
946 // return value -- a 2D array of bytes 0..255, width*height in size
947 //
948 // pixel_dist_scale & onedge_value are a scale & bias that allows you to make
949 // optimal use of the limited 0..255 for your application, trading off precision
950 // and special effects. SDF values outside the range 0..255 are clamped to 0..255.
951 //
952 // Example:
953 // scale = stbtt_ScaleForPixelHeight(22)
954 // padding = 5
955 // onedge_value = 180
956 // pixel_dist_scale = 180/5.0 = 36.0
957 //
958 // This will create an SDF bitmap in which the character is about 22 pixels
959 // high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
960 // shape, sample the SDF at each pixel and fill the pixel if the SDF value
961 // is greater than or equal to 180/255. (You'll actually want to antialias,
962 // which is beyond the scope of this example.) Additionally, you can compute
963 // offset outlines (e.g. to stroke the character border inside & outside,
964 // or only outside). For example, to fill outside the character up to 3 SDF
965 // pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
966 // choice of variables maps a range from 5 pixels outside the shape to
967 // 2 pixels inside the shape to 0..255; this is intended primarily for apply
968 // outside effects only (the interior range is needed to allow proper
969 // antialiasing of the font at *smaller* sizes)
970 //
971 // The function computes the SDF analytically at each SDF pixel, not by e.g.
972 // building a higher-res bitmap and approximating it. In theory the quality
973 // should be as high as possible for an SDF of this size & representation, but
974 // unclear if this is true in practice (perhaps building a higher-res bitmap
975 // and computing from that can allow drop-out prevention).
976 //
977 // The algorithm has not been optimized at all, so expect it to be slow
978 // if computing lots of characters or very large sizes.
979
980
981
982 //////////////////////////////////////////////////////////////////////////////
983 //
984 // Finding the right font...
985 //
986 // You should really just solve this offline, keep your own tables
987 // of what font is what, and don't try to get it out of the .ttf file.
988 // That's because getting it out of the .ttf file is really hard, because
989 // the names in the file can appear in many possible encodings, in many
990 // possible languages, and e.g. if you need a case-insensitive comparison,
991 // the details of that depend on the encoding & language in a complex way
992 // (actually underspecified in truetype, but also gigantic).
993 //
994 // But you can use the provided functions in two possible ways:
995 // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
996 // unicode-encoded names to try to find the font you want;
997 // you can run this before calling stbtt_InitFont()
998 //
999 // stbtt_GetFontNameString() lets you get any of the various strings
1000 // from the file yourself and do your own comparisons on them.
1001 // You have to have called stbtt_InitFont() first.
1002
1003
1004 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
1005 // returns the offset (not index) of the font that matches, or -1 if none
1006 // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
1007 // if you use any other flag, use a font name like "Arial"; this checks
1008 // the 'macStyle' header field; i don't know if fonts set this consistently
1009 #define STBTT_MACSTYLE_DONTCARE 0
1010 #define STBTT_MACSTYLE_BOLD 1
1011 #define STBTT_MACSTYLE_ITALIC 2
1012 #define STBTT_MACSTYLE_UNDERSCORE 4
1013 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
1014
1015 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
1016 // returns 1/0 whether the first string interpreted as utf8 is identical to
1017 // the second string interpreted as big-endian utf16... useful for strings from next func
1018
1019 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
1020 // returns the string (which may be big-endian double byte, e.g. for unicode)
1021 // and puts the length in bytes in *length.
1022 //
1023 // some of the values for the IDs are below; for more see the truetype spec:
1024 // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
1025 // http://www.microsoft.com/typography/otspec/name.htm
1026
1027 enum { // platformID
1028 STBTT_PLATFORM_ID_UNICODE =0,
1029 STBTT_PLATFORM_ID_MAC =1,
1030 STBTT_PLATFORM_ID_ISO =2,
1031 STBTT_PLATFORM_ID_MICROSOFT =3
1032 };
1033
1034 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
1035 STBTT_UNICODE_EID_UNICODE_1_0 =0,
1036 STBTT_UNICODE_EID_UNICODE_1_1 =1,
1037 STBTT_UNICODE_EID_ISO_10646 =2,
1038 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
1039 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
1040 };
1041
1042 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
1043 STBTT_MS_EID_SYMBOL =0,
1044 STBTT_MS_EID_UNICODE_BMP =1,
1045 STBTT_MS_EID_SHIFTJIS =2,
1046 STBTT_MS_EID_UNICODE_FULL =10
1047 };
1048
1049 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
1050 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
1051 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
1052 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
1053 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
1054 };
1055
1056 enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
1057 // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
1058 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
1059 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
1060 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
1061 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
1062 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
1063 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
1064 };
1065
1066 enum { // languageID for STBTT_PLATFORM_ID_MAC
1067 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
1068 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
1069 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
1070 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
1071 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
1072 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
1073 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
1074 };
1075
1076 #ifdef __cplusplus
1077 }
1078 #endif
1079
1080 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
1081
1082 ///////////////////////////////////////////////////////////////////////////////
1083 ///////////////////////////////////////////////////////////////////////////////
1084 ////
1085 //// IMPLEMENTATION
1086 ////
1087 ////
1088
1089 #ifdef STB_TRUETYPE_IMPLEMENTATION
1090
1091 #ifndef STBTT_MAX_OVERSAMPLE
1092 #define STBTT_MAX_OVERSAMPLE 8
1093 #endif
1094
1095 #if STBTT_MAX_OVERSAMPLE > 255
1096 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
1097 #endif
1098
1099 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
1100
1101 #ifndef STBTT_RASTERIZER_VERSION
1102 #define STBTT_RASTERIZER_VERSION 2
1103 #endif
1104
1105 #ifdef _MSC_VER
1106 #define STBTT__NOTUSED(v) (void)(v)
1107 #else
1108 #define STBTT__NOTUSED(v) (void)sizeof(v)
1109 #endif
1110
1111 //////////////////////////////////////////////////////////////////////////
1112 //
1113 // stbtt__buf helpers to parse data from file
1114 //
1115
stbtt__buf_get8(stbtt__buf * b)1116 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
1117 {
1118 if (b->cursor >= b->size)
1119 return 0;
1120 return b->data[b->cursor++];
1121 }
1122
stbtt__buf_peek8(stbtt__buf * b)1123 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
1124 {
1125 if (b->cursor >= b->size)
1126 return 0;
1127 return b->data[b->cursor];
1128 }
1129
stbtt__buf_seek(stbtt__buf * b,int o)1130 static void stbtt__buf_seek(stbtt__buf *b, int o)
1131 {
1132 STBTT_assert(!(o > b->size || o < 0));
1133 b->cursor = (o > b->size || o < 0) ? b->size : o;
1134 }
1135
stbtt__buf_skip(stbtt__buf * b,int o)1136 static void stbtt__buf_skip(stbtt__buf *b, int o)
1137 {
1138 stbtt__buf_seek(b, b->cursor + o);
1139 }
1140
stbtt__buf_get(stbtt__buf * b,int n)1141 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
1142 {
1143 stbtt_uint32 v = 0;
1144 int i;
1145 STBTT_assert(n >= 1 && n <= 4);
1146 for (i = 0; i < n; i++)
1147 v = (v << 8) | stbtt__buf_get8(b);
1148 return v;
1149 }
1150
stbtt__new_buf(const void * p,size_t size)1151 static stbtt__buf stbtt__new_buf(const void *p, size_t size)
1152 {
1153 stbtt__buf r;
1154 STBTT_assert(size < 0x40000000);
1155 r.data = (stbtt_uint8*) p;
1156 r.size = (int) size;
1157 r.cursor = 0;
1158 return r;
1159 }
1160
1161 #define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
1162 #define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
1163
stbtt__buf_range(const stbtt__buf * b,int o,int s)1164 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
1165 {
1166 stbtt__buf r = stbtt__new_buf(NULL, 0);
1167 if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
1168 r.data = b->data + o;
1169 r.size = s;
1170 return r;
1171 }
1172
stbtt__cff_get_index(stbtt__buf * b)1173 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
1174 {
1175 int count, start, offsize;
1176 start = b->cursor;
1177 count = stbtt__buf_get16(b);
1178 if (count) {
1179 offsize = stbtt__buf_get8(b);
1180 STBTT_assert(offsize >= 1 && offsize <= 4);
1181 stbtt__buf_skip(b, offsize * count);
1182 stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
1183 }
1184 return stbtt__buf_range(b, start, b->cursor - start);
1185 }
1186
stbtt__cff_int(stbtt__buf * b)1187 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
1188 {
1189 int b0 = stbtt__buf_get8(b);
1190 if (b0 >= 32 && b0 <= 246) return b0 - 139;
1191 else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
1192 else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
1193 else if (b0 == 28) return stbtt__buf_get16(b);
1194 else if (b0 == 29) return stbtt__buf_get32(b);
1195 STBTT_assert(0);
1196 return 0;
1197 }
1198
stbtt__cff_skip_operand(stbtt__buf * b)1199 static void stbtt__cff_skip_operand(stbtt__buf *b) {
1200 int v, b0 = stbtt__buf_peek8(b);
1201 STBTT_assert(b0 >= 28);
1202 if (b0 == 30) {
1203 stbtt__buf_skip(b, 1);
1204 while (b->cursor < b->size) {
1205 v = stbtt__buf_get8(b);
1206 if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
1207 break;
1208 }
1209 } else {
1210 stbtt__cff_int(b);
1211 }
1212 }
1213
stbtt__dict_get(stbtt__buf * b,int key)1214 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
1215 {
1216 stbtt__buf_seek(b, 0);
1217 while (b->cursor < b->size) {
1218 int start = b->cursor, end, op;
1219 while (stbtt__buf_peek8(b) >= 28)
1220 stbtt__cff_skip_operand(b);
1221 end = b->cursor;
1222 op = stbtt__buf_get8(b);
1223 if (op == 12) op = stbtt__buf_get8(b) | 0x100;
1224 if (op == key) return stbtt__buf_range(b, start, end-start);
1225 }
1226 return stbtt__buf_range(b, 0, 0);
1227 }
1228
stbtt__dict_get_ints(stbtt__buf * b,int key,int outcount,stbtt_uint32 * out)1229 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
1230 {
1231 int i;
1232 stbtt__buf operands = stbtt__dict_get(b, key);
1233 for (i = 0; i < outcount && operands.cursor < operands.size; i++)
1234 out[i] = stbtt__cff_int(&operands);
1235 }
1236
stbtt__cff_index_count(stbtt__buf * b)1237 static int stbtt__cff_index_count(stbtt__buf *b)
1238 {
1239 stbtt__buf_seek(b, 0);
1240 return stbtt__buf_get16(b);
1241 }
1242
stbtt__cff_index_get(stbtt__buf b,int i)1243 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
1244 {
1245 int count, offsize, start, end;
1246 stbtt__buf_seek(&b, 0);
1247 count = stbtt__buf_get16(&b);
1248 offsize = stbtt__buf_get8(&b);
1249 STBTT_assert(i >= 0 && i < count);
1250 STBTT_assert(offsize >= 1 && offsize <= 4);
1251 stbtt__buf_skip(&b, i*offsize);
1252 start = stbtt__buf_get(&b, offsize);
1253 end = stbtt__buf_get(&b, offsize);
1254 return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
1255 }
1256
1257 //////////////////////////////////////////////////////////////////////////
1258 //
1259 // accessors to parse data from file
1260 //
1261
1262 // on platforms that don't allow misaligned reads, if we want to allow
1263 // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
1264
1265 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
1266 #define ttCHAR(p) (* (stbtt_int8 *) (p))
1267 #define ttFixed(p) ttLONG(p)
1268
ttUSHORT(stbtt_uint8 * p)1269 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
ttSHORT(stbtt_uint8 * p)1270 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
ttULONG(stbtt_uint8 * p)1271 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
ttLONG(stbtt_uint8 * p)1272 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1273
1274 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1275 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
1276
stbtt__isfont(stbtt_uint8 * font)1277 static int stbtt__isfont(stbtt_uint8 *font)
1278 {
1279 // check the version number
1280 if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
1281 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
1282 if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
1283 if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
1284 if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
1285 return 0;
1286 }
1287
1288 // @OPTIMIZE: binary search
stbtt__find_table(stbtt_uint8 * data,stbtt_uint32 fontstart,const char * tag)1289 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
1290 {
1291 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
1292 stbtt_uint32 tabledir = fontstart + 12;
1293 stbtt_int32 i;
1294 for (i=0; i < num_tables; ++i) {
1295 stbtt_uint32 loc = tabledir + 16*i;
1296 if (stbtt_tag(data+loc+0, tag))
1297 return ttULONG(data+loc+8);
1298 }
1299 return 0;
1300 }
1301
stbtt_GetFontOffsetForIndex_internal(unsigned char * font_collection,int index)1302 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
1303 {
1304 // if it's just a font, there's only one valid index
1305 if (stbtt__isfont(font_collection))
1306 return index == 0 ? 0 : -1;
1307
1308 // check if it's a TTC
1309 if (stbtt_tag(font_collection, "ttcf")) {
1310 // version 1?
1311 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1312 stbtt_int32 n = ttLONG(font_collection+8);
1313 if (index >= n)
1314 return -1;
1315 return ttULONG(font_collection+12+index*4);
1316 }
1317 }
1318 return -1;
1319 }
1320
stbtt_GetNumberOfFonts_internal(unsigned char * font_collection)1321 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
1322 {
1323 // if it's just a font, there's only one valid font
1324 if (stbtt__isfont(font_collection))
1325 return 1;
1326
1327 // check if it's a TTC
1328 if (stbtt_tag(font_collection, "ttcf")) {
1329 // version 1?
1330 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1331 return ttLONG(font_collection+8);
1332 }
1333 }
1334 return 0;
1335 }
1336
stbtt__get_subrs(stbtt__buf cff,stbtt__buf fontdict)1337 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
1338 {
1339 stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
1340 stbtt__buf pdict;
1341 stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
1342 if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
1343 pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
1344 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
1345 if (!subrsoff) return stbtt__new_buf(NULL, 0);
1346 stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
1347 return stbtt__cff_get_index(&cff);
1348 }
1349
stbtt_InitFont_internal(stbtt_fontinfo * info,unsigned char * data,int fontstart)1350 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
1351 {
1352 stbtt_uint32 cmap, t;
1353 stbtt_int32 i,numTables;
1354
1355 info->data = data;
1356 info->fontstart = fontstart;
1357 info->cff = stbtt__new_buf(NULL, 0);
1358
1359 cmap = stbtt__find_table(data, fontstart, "cmap"); // required
1360 info->loca = stbtt__find_table(data, fontstart, "loca"); // required
1361 info->head = stbtt__find_table(data, fontstart, "head"); // required
1362 info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
1363 info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
1364 info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
1365 info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
1366 info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
1367
1368 if (!cmap || !info->head || !info->hhea || !info->hmtx)
1369 return 0;
1370 if (info->glyf) {
1371 // required for truetype
1372 if (!info->loca) return 0;
1373 } else {
1374 // initialization for CFF / Type2 fonts (OTF)
1375 stbtt__buf b, topdict, topdictidx;
1376 stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
1377 stbtt_uint32 cff;
1378
1379 cff = stbtt__find_table(data, fontstart, "CFF ");
1380 if (!cff) return 0;
1381
1382 info->fontdicts = stbtt__new_buf(NULL, 0);
1383 info->fdselect = stbtt__new_buf(NULL, 0);
1384
1385 // @TODO this should use size from table (not 512MB)
1386 info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
1387 b = info->cff;
1388
1389 // read the header
1390 stbtt__buf_skip(&b, 2);
1391 stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
1392
1393 // @TODO the name INDEX could list multiple fonts,
1394 // but we just use the first one.
1395 stbtt__cff_get_index(&b); // name INDEX
1396 topdictidx = stbtt__cff_get_index(&b);
1397 topdict = stbtt__cff_index_get(topdictidx, 0);
1398 stbtt__cff_get_index(&b); // string INDEX
1399 info->gsubrs = stbtt__cff_get_index(&b);
1400
1401 stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
1402 stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
1403 stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
1404 stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
1405 info->subrs = stbtt__get_subrs(b, topdict);
1406
1407 // we only support Type 2 charstrings
1408 if (cstype != 2) return 0;
1409 if (charstrings == 0) return 0;
1410
1411 if (fdarrayoff) {
1412 // looks like a CID font
1413 if (!fdselectoff) return 0;
1414 stbtt__buf_seek(&b, fdarrayoff);
1415 info->fontdicts = stbtt__cff_get_index(&b);
1416 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
1417 }
1418
1419 stbtt__buf_seek(&b, charstrings);
1420 info->charstrings = stbtt__cff_get_index(&b);
1421 }
1422
1423 t = stbtt__find_table(data, fontstart, "maxp");
1424 if (t)
1425 info->numGlyphs = ttUSHORT(data+t+4);
1426 else
1427 info->numGlyphs = 0xffff;
1428
1429 // find a cmap encoding table we understand *now* to avoid searching
1430 // later. (todo: could make this installable)
1431 // the same regardless of glyph.
1432 numTables = ttUSHORT(data + cmap + 2);
1433 info->index_map = 0;
1434 for (i=0; i < numTables; ++i) {
1435 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1436 // find an encoding we understand:
1437 switch(ttUSHORT(data+encoding_record)) {
1438 case STBTT_PLATFORM_ID_MICROSOFT:
1439 switch (ttUSHORT(data+encoding_record+2)) {
1440 case STBTT_MS_EID_UNICODE_BMP:
1441 case STBTT_MS_EID_UNICODE_FULL:
1442 // MS/Unicode
1443 info->index_map = cmap + ttULONG(data+encoding_record+4);
1444 break;
1445 }
1446 break;
1447 case STBTT_PLATFORM_ID_UNICODE:
1448 // Mac/iOS has these
1449 // all the encodingIDs are unicode, so we don't bother to check it
1450 info->index_map = cmap + ttULONG(data+encoding_record+4);
1451 break;
1452 }
1453 }
1454 if (info->index_map == 0)
1455 return 0;
1456
1457 info->indexToLocFormat = ttUSHORT(data+info->head + 50);
1458 return 1;
1459 }
1460
stbtt_FindGlyphIndex(const stbtt_fontinfo * info,int unicode_codepoint)1461 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
1462 {
1463 stbtt_uint8 *data = info->data;
1464 stbtt_uint32 index_map = info->index_map;
1465
1466 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1467 if (format == 0) { // apple byte encoding
1468 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1469 if (unicode_codepoint < bytes-6)
1470 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1471 return 0;
1472 } else if (format == 6) {
1473 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1474 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1475 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1476 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1477 return 0;
1478 } else if (format == 2) {
1479 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1480 return 0;
1481 } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
1482 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1483 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1484 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1485 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1486
1487 // do a binary search of the segments
1488 stbtt_uint32 endCount = index_map + 14;
1489 stbtt_uint32 search = endCount;
1490
1491 if (unicode_codepoint > 0xffff)
1492 return 0;
1493
1494 // they lie from endCount .. endCount + segCount
1495 // but searchRange is the nearest power of two, so...
1496 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1497 search += rangeShift*2;
1498
1499 // now decrement to bias correctly to find smallest
1500 search -= 2;
1501 while (entrySelector) {
1502 stbtt_uint16 end;
1503 searchRange >>= 1;
1504 end = ttUSHORT(data + search + searchRange*2);
1505 if (unicode_codepoint > end)
1506 search += searchRange*2;
1507 --entrySelector;
1508 }
1509 search += 2;
1510
1511 {
1512 stbtt_uint16 offset, start;
1513 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1514
1515 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1516 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1517 if (unicode_codepoint < start)
1518 return 0;
1519
1520 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1521 if (offset == 0)
1522 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1523
1524 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1525 }
1526 } else if (format == 12 || format == 13) {
1527 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1528 stbtt_int32 low,high;
1529 low = 0; high = (stbtt_int32)ngroups;
1530 // Binary search the right group.
1531 while (low < high) {
1532 stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
1533 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1534 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1535 if ((stbtt_uint32) unicode_codepoint < start_char)
1536 high = mid;
1537 else if ((stbtt_uint32) unicode_codepoint > end_char)
1538 low = mid+1;
1539 else {
1540 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1541 if (format == 12)
1542 return start_glyph + unicode_codepoint-start_char;
1543 else // format == 13
1544 return start_glyph;
1545 }
1546 }
1547 return 0; // not found
1548 }
1549 // @TODO
1550 STBTT_assert(0);
1551 return 0;
1552 }
1553
stbtt_GetCodepointShape(const stbtt_fontinfo * info,int unicode_codepoint,stbtt_vertex ** vertices)1554 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
1555 {
1556 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1557 }
1558
stbtt_setvertex(stbtt_vertex * v,stbtt_uint8 type,stbtt_int32 x,stbtt_int32 y,stbtt_int32 cx,stbtt_int32 cy)1559 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1560 {
1561 v->type = type;
1562 v->x = (stbtt_int16) x;
1563 v->y = (stbtt_int16) y;
1564 v->cx = (stbtt_int16) cx;
1565 v->cy = (stbtt_int16) cy;
1566 }
1567
stbtt__GetGlyfOffset(const stbtt_fontinfo * info,int glyph_index)1568 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
1569 {
1570 int g1,g2;
1571
1572 STBTT_assert(!info->cff.size);
1573
1574 if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
1575 if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
1576
1577 if (info->indexToLocFormat == 0) {
1578 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1579 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1580 } else {
1581 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
1582 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
1583 }
1584
1585 return g1==g2 ? -1 : g1; // if length is 0, return -1
1586 }
1587
1588 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
1589
stbtt_GetGlyphBox(const stbtt_fontinfo * info,int glyph_index,int * x0,int * y0,int * x1,int * y1)1590 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
1591 {
1592 if (info->cff.size) {
1593 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
1594 } else {
1595 int g = stbtt__GetGlyfOffset(info, glyph_index);
1596 if (g < 0) return 0;
1597
1598 if (x0) *x0 = ttSHORT(info->data + g + 2);
1599 if (y0) *y0 = ttSHORT(info->data + g + 4);
1600 if (x1) *x1 = ttSHORT(info->data + g + 6);
1601 if (y1) *y1 = ttSHORT(info->data + g + 8);
1602 }
1603 return 1;
1604 }
1605
stbtt_GetCodepointBox(const stbtt_fontinfo * info,int codepoint,int * x0,int * y0,int * x1,int * y1)1606 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
1607 {
1608 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
1609 }
1610
stbtt_IsGlyphEmpty(const stbtt_fontinfo * info,int glyph_index)1611 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
1612 {
1613 stbtt_int16 numberOfContours;
1614 int g;
1615 if (info->cff.size)
1616 return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
1617 g = stbtt__GetGlyfOffset(info, glyph_index);
1618 if (g < 0) return 1;
1619 numberOfContours = ttSHORT(info->data + g);
1620 return numberOfContours == 0;
1621 }
1622
stbtt__close_shape(stbtt_vertex * vertices,int num_vertices,int was_off,int start_off,stbtt_int32 sx,stbtt_int32 sy,stbtt_int32 scx,stbtt_int32 scy,stbtt_int32 cx,stbtt_int32 cy)1623 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
1624 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1625 {
1626 if (start_off) {
1627 if (was_off)
1628 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1629 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
1630 } else {
1631 if (was_off)
1632 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
1633 else
1634 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
1635 }
1636 return num_vertices;
1637 }
1638
stbtt__GetGlyphShapeTT(const stbtt_fontinfo * info,int glyph_index,stbtt_vertex ** pvertices)1639 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
1640 {
1641 stbtt_int16 numberOfContours;
1642 stbtt_uint8 *endPtsOfContours;
1643 stbtt_uint8 *data = info->data;
1644 stbtt_vertex *vertices=0;
1645 int num_vertices=0;
1646 int g = stbtt__GetGlyfOffset(info, glyph_index);
1647
1648 *pvertices = NULL;
1649
1650 if (g < 0) return 0;
1651
1652 numberOfContours = ttSHORT(data + g);
1653
1654 if (numberOfContours > 0) {
1655 stbtt_uint8 flags=0,flagcount;
1656 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1657 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1658 stbtt_uint8 *points;
1659 endPtsOfContours = (data + g + 10);
1660 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1661 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1662
1663 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1664
1665 m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
1666 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1667 if (vertices == 0)
1668 return 0;
1669
1670 next_move = 0;
1671 flagcount=0;
1672
1673 // in first pass, we load uninterpreted data into the allocated array
1674 // above, shifted to the end of the array so we won't overwrite it when
1675 // we create our final data starting from the front
1676
1677 off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1678
1679 // first load flags
1680
1681 for (i=0; i < n; ++i) {
1682 if (flagcount == 0) {
1683 flags = *points++;
1684 if (flags & 8)
1685 flagcount = *points++;
1686 } else
1687 --flagcount;
1688 vertices[off+i].type = flags;
1689 }
1690
1691 // now load x coordinates
1692 x=0;
1693 for (i=0; i < n; ++i) {
1694 flags = vertices[off+i].type;
1695 if (flags & 2) {
1696 stbtt_int16 dx = *points++;
1697 x += (flags & 16) ? dx : -dx; // ???
1698 } else {
1699 if (!(flags & 16)) {
1700 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1701 points += 2;
1702 }
1703 }
1704 vertices[off+i].x = (stbtt_int16) x;
1705 }
1706
1707 // now load y coordinates
1708 y=0;
1709 for (i=0; i < n; ++i) {
1710 flags = vertices[off+i].type;
1711 if (flags & 4) {
1712 stbtt_int16 dy = *points++;
1713 y += (flags & 32) ? dy : -dy; // ???
1714 } else {
1715 if (!(flags & 32)) {
1716 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1717 points += 2;
1718 }
1719 }
1720 vertices[off+i].y = (stbtt_int16) y;
1721 }
1722
1723 // now convert them to our format
1724 num_vertices=0;
1725 sx = sy = cx = cy = scx = scy = 0;
1726 for (i=0; i < n; ++i) {
1727 flags = vertices[off+i].type;
1728 x = (stbtt_int16) vertices[off+i].x;
1729 y = (stbtt_int16) vertices[off+i].y;
1730
1731 if (next_move == i) {
1732 if (i != 0)
1733 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1734
1735 // now start the new one
1736 start_off = !(flags & 1);
1737 if (start_off) {
1738 // if we start off with an off-curve point, then when we need to find a point on the curve
1739 // where we can start, and we need to save some state for when we wraparound.
1740 scx = x;
1741 scy = y;
1742 if (!(vertices[off+i+1].type & 1)) {
1743 // next point is also a curve point, so interpolate an on-point curve
1744 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1745 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1746 } else {
1747 // otherwise just use the next point as our start point
1748 sx = (stbtt_int32) vertices[off+i+1].x;
1749 sy = (stbtt_int32) vertices[off+i+1].y;
1750 ++i; // we're using point i+1 as the starting point, so skip it
1751 }
1752 } else {
1753 sx = x;
1754 sy = y;
1755 }
1756 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
1757 was_off = 0;
1758 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1759 ++j;
1760 } else {
1761 if (!(flags & 1)) { // if it's a curve
1762 if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
1763 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1764 cx = x;
1765 cy = y;
1766 was_off = 1;
1767 } else {
1768 if (was_off)
1769 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
1770 else
1771 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
1772 was_off = 0;
1773 }
1774 }
1775 }
1776 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1777 } else if (numberOfContours == -1) {
1778 // Compound shapes.
1779 int more = 1;
1780 stbtt_uint8 *comp = data + g + 10;
1781 num_vertices = 0;
1782 vertices = 0;
1783 while (more) {
1784 stbtt_uint16 flags, gidx;
1785 int comp_num_verts = 0, i;
1786 stbtt_vertex *comp_verts = 0, *tmp = 0;
1787 float mtx[6] = {1,0,0,1,0,0}, m, n;
1788
1789 flags = ttSHORT(comp); comp+=2;
1790 gidx = ttSHORT(comp); comp+=2;
1791
1792 if (flags & 2) { // XY values
1793 if (flags & 1) { // shorts
1794 mtx[4] = ttSHORT(comp); comp+=2;
1795 mtx[5] = ttSHORT(comp); comp+=2;
1796 } else {
1797 mtx[4] = ttCHAR(comp); comp+=1;
1798 mtx[5] = ttCHAR(comp); comp+=1;
1799 }
1800 }
1801 else {
1802 // @TODO handle matching point
1803 STBTT_assert(0);
1804 }
1805 if (flags & (1<<3)) { // WE_HAVE_A_SCALE
1806 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1807 mtx[1] = mtx[2] = 0;
1808 } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
1809 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1810 mtx[1] = mtx[2] = 0;
1811 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1812 } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
1813 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1814 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1815 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1816 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1817 }
1818
1819 // Find transformation scales.
1820 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1821 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1822
1823 // Get indexed glyph.
1824 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1825 if (comp_num_verts > 0) {
1826 // Transform vertices.
1827 for (i = 0; i < comp_num_verts; ++i) {
1828 stbtt_vertex* v = &comp_verts[i];
1829 stbtt_vertex_type x,y;
1830 x=v->x; y=v->y;
1831 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1832 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1833 x=v->cx; y=v->cy;
1834 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1835 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1836 }
1837 // Append vertices.
1838 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
1839 if (!tmp) {
1840 if (vertices) STBTT_free(vertices, info->userdata);
1841 if (comp_verts) STBTT_free(comp_verts, info->userdata);
1842 return 0;
1843 }
1844 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595
1845 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1846 if (vertices) STBTT_free(vertices, info->userdata);
1847 vertices = tmp;
1848 STBTT_free(comp_verts, info->userdata);
1849 num_vertices += comp_num_verts;
1850 }
1851 // More components ?
1852 more = flags & (1<<5);
1853 }
1854 } else if (numberOfContours < 0) {
1855 // @TODO other compound variations?
1856 STBTT_assert(0);
1857 } else {
1858 // numberOfCounters == 0, do nothing
1859 }
1860
1861 *pvertices = vertices;
1862 return num_vertices;
1863 }
1864
1865 typedef struct
1866 {
1867 int bounds;
1868 int started;
1869 float first_x, first_y;
1870 float x, y;
1871 stbtt_int32 min_x, max_x, min_y, max_y;
1872
1873 stbtt_vertex *pvertices;
1874 int num_vertices;
1875 } stbtt__csctx;
1876
1877 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
1878
stbtt__track_vertex(stbtt__csctx * c,stbtt_int32 x,stbtt_int32 y)1879 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
1880 {
1881 if (x > c->max_x || !c->started) c->max_x = x;
1882 if (y > c->max_y || !c->started) c->max_y = y;
1883 if (x < c->min_x || !c->started) c->min_x = x;
1884 if (y < c->min_y || !c->started) c->min_y = y;
1885 c->started = 1;
1886 }
1887
stbtt__csctx_v(stbtt__csctx * c,stbtt_uint8 type,stbtt_int32 x,stbtt_int32 y,stbtt_int32 cx,stbtt_int32 cy,stbtt_int32 cx1,stbtt_int32 cy1)1888 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
1889 {
1890 if (c->bounds) {
1891 stbtt__track_vertex(c, x, y);
1892 if (type == STBTT_vcubic) {
1893 stbtt__track_vertex(c, cx, cy);
1894 stbtt__track_vertex(c, cx1, cy1);
1895 }
1896 } else {
1897 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
1898 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
1899 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
1900 }
1901 c->num_vertices++;
1902 }
1903
stbtt__csctx_close_shape(stbtt__csctx * ctx)1904 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
1905 {
1906 if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
1907 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
1908 }
1909
stbtt__csctx_rmove_to(stbtt__csctx * ctx,float dx,float dy)1910 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
1911 {
1912 stbtt__csctx_close_shape(ctx);
1913 ctx->first_x = ctx->x = ctx->x + dx;
1914 ctx->first_y = ctx->y = ctx->y + dy;
1915 stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1916 }
1917
stbtt__csctx_rline_to(stbtt__csctx * ctx,float dx,float dy)1918 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
1919 {
1920 ctx->x += dx;
1921 ctx->y += dy;
1922 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1923 }
1924
stbtt__csctx_rccurve_to(stbtt__csctx * ctx,float dx1,float dy1,float dx2,float dy2,float dx3,float dy3)1925 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
1926 {
1927 float cx1 = ctx->x + dx1;
1928 float cy1 = ctx->y + dy1;
1929 float cx2 = cx1 + dx2;
1930 float cy2 = cy1 + dy2;
1931 ctx->x = cx2 + dx3;
1932 ctx->y = cy2 + dy3;
1933 stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
1934 }
1935
stbtt__get_subr(stbtt__buf idx,int n)1936 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
1937 {
1938 int count = stbtt__cff_index_count(&idx);
1939 int bias = 107;
1940 if (count >= 33900)
1941 bias = 32768;
1942 else if (count >= 1240)
1943 bias = 1131;
1944 n += bias;
1945 if (n < 0 || n >= count)
1946 return stbtt__new_buf(NULL, 0);
1947 return stbtt__cff_index_get(idx, n);
1948 }
1949
stbtt__cid_get_glyph_subrs(const stbtt_fontinfo * info,int glyph_index)1950 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
1951 {
1952 stbtt__buf fdselect = info->fdselect;
1953 int nranges, start, end, v, fmt, fdselector = -1, i;
1954
1955 stbtt__buf_seek(&fdselect, 0);
1956 fmt = stbtt__buf_get8(&fdselect);
1957 if (fmt == 0) {
1958 // untested
1959 stbtt__buf_skip(&fdselect, glyph_index);
1960 fdselector = stbtt__buf_get8(&fdselect);
1961 } else if (fmt == 3) {
1962 nranges = stbtt__buf_get16(&fdselect);
1963 start = stbtt__buf_get16(&fdselect);
1964 for (i = 0; i < nranges; i++) {
1965 v = stbtt__buf_get8(&fdselect);
1966 end = stbtt__buf_get16(&fdselect);
1967 if (glyph_index >= start && glyph_index < end) {
1968 fdselector = v;
1969 break;
1970 }
1971 start = end;
1972 }
1973 }
1974 if (fdselector == -1) stbtt__new_buf(NULL, 0);
1975 return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
1976 }
1977
stbtt__run_charstring(const stbtt_fontinfo * info,int glyph_index,stbtt__csctx * c)1978 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
1979 {
1980 int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
1981 int has_subrs = 0, clear_stack;
1982 float s[48];
1983 stbtt__buf subr_stack[10], subrs = info->subrs, b;
1984 float f;
1985
1986 #define STBTT__CSERR(s) (0)
1987
1988 // this currently ignores the initial width value, which isn't needed if we have hmtx
1989 b = stbtt__cff_index_get(info->charstrings, glyph_index);
1990 while (b.cursor < b.size) {
1991 i = 0;
1992 clear_stack = 1;
1993 b0 = stbtt__buf_get8(&b);
1994 switch (b0) {
1995 // @TODO implement hinting
1996 case 0x13: // hintmask
1997 case 0x14: // cntrmask
1998 if (in_header)
1999 maskbits += (sp / 2); // implicit "vstem"
2000 in_header = 0;
2001 stbtt__buf_skip(&b, (maskbits + 7) / 8);
2002 break;
2003
2004 case 0x01: // hstem
2005 case 0x03: // vstem
2006 case 0x12: // hstemhm
2007 case 0x17: // vstemhm
2008 maskbits += (sp / 2);
2009 break;
2010
2011 case 0x15: // rmoveto
2012 in_header = 0;
2013 if (sp < 2) return STBTT__CSERR("rmoveto stack");
2014 stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
2015 break;
2016 case 0x04: // vmoveto
2017 in_header = 0;
2018 if (sp < 1) return STBTT__CSERR("vmoveto stack");
2019 stbtt__csctx_rmove_to(c, 0, s[sp-1]);
2020 break;
2021 case 0x16: // hmoveto
2022 in_header = 0;
2023 if (sp < 1) return STBTT__CSERR("hmoveto stack");
2024 stbtt__csctx_rmove_to(c, s[sp-1], 0);
2025 break;
2026
2027 case 0x05: // rlineto
2028 if (sp < 2) return STBTT__CSERR("rlineto stack");
2029 for (; i + 1 < sp; i += 2)
2030 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2031 break;
2032
2033 // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
2034 // starting from a different place.
2035
2036 case 0x07: // vlineto
2037 if (sp < 1) return STBTT__CSERR("vlineto stack");
2038 goto vlineto;
2039 case 0x06: // hlineto
2040 if (sp < 1) return STBTT__CSERR("hlineto stack");
2041 for (;;) {
2042 if (i >= sp) break;
2043 stbtt__csctx_rline_to(c, s[i], 0);
2044 i++;
2045 vlineto:
2046 if (i >= sp) break;
2047 stbtt__csctx_rline_to(c, 0, s[i]);
2048 i++;
2049 }
2050 break;
2051
2052 case 0x1F: // hvcurveto
2053 if (sp < 4) return STBTT__CSERR("hvcurveto stack");
2054 goto hvcurveto;
2055 case 0x1E: // vhcurveto
2056 if (sp < 4) return STBTT__CSERR("vhcurveto stack");
2057 for (;;) {
2058 if (i + 3 >= sp) break;
2059 stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
2060 i += 4;
2061 hvcurveto:
2062 if (i + 3 >= sp) break;
2063 stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
2064 i += 4;
2065 }
2066 break;
2067
2068 case 0x08: // rrcurveto
2069 if (sp < 6) return STBTT__CSERR("rcurveline stack");
2070 for (; i + 5 < sp; i += 6)
2071 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2072 break;
2073
2074 case 0x18: // rcurveline
2075 if (sp < 8) return STBTT__CSERR("rcurveline stack");
2076 for (; i + 5 < sp - 2; i += 6)
2077 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2078 if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
2079 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2080 break;
2081
2082 case 0x19: // rlinecurve
2083 if (sp < 8) return STBTT__CSERR("rlinecurve stack");
2084 for (; i + 1 < sp - 6; i += 2)
2085 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2086 if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
2087 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2088 break;
2089
2090 case 0x1A: // vvcurveto
2091 case 0x1B: // hhcurveto
2092 if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
2093 f = 0.0;
2094 if (sp & 1) { f = s[i]; i++; }
2095 for (; i + 3 < sp; i += 4) {
2096 if (b0 == 0x1B)
2097 stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
2098 else
2099 stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
2100 f = 0.0;
2101 }
2102 break;
2103
2104 case 0x0A: // callsubr
2105 if (!has_subrs) {
2106 if (info->fdselect.size)
2107 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2108 has_subrs = 1;
2109 }
2110 // fallthrough
2111 case 0x1D: // callgsubr
2112 if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
2113 v = (int) s[--sp];
2114 if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
2115 subr_stack[subr_stack_height++] = b;
2116 b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
2117 if (b.size == 0) return STBTT__CSERR("subr not found");
2118 b.cursor = 0;
2119 clear_stack = 0;
2120 break;
2121
2122 case 0x0B: // return
2123 if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
2124 b = subr_stack[--subr_stack_height];
2125 clear_stack = 0;
2126 break;
2127
2128 case 0x0E: // endchar
2129 stbtt__csctx_close_shape(c);
2130 return 1;
2131
2132 case 0x0C: { // two-byte escape
2133 float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
2134 float dx, dy;
2135 int b1 = stbtt__buf_get8(&b);
2136 switch (b1) {
2137 // @TODO These "flex" implementations ignore the flex-depth and resolution,
2138 // and always draw beziers.
2139 case 0x22: // hflex
2140 if (sp < 7) return STBTT__CSERR("hflex stack");
2141 dx1 = s[0];
2142 dx2 = s[1];
2143 dy2 = s[2];
2144 dx3 = s[3];
2145 dx4 = s[4];
2146 dx5 = s[5];
2147 dx6 = s[6];
2148 stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
2149 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
2150 break;
2151
2152 case 0x23: // flex
2153 if (sp < 13) return STBTT__CSERR("flex stack");
2154 dx1 = s[0];
2155 dy1 = s[1];
2156 dx2 = s[2];
2157 dy2 = s[3];
2158 dx3 = s[4];
2159 dy3 = s[5];
2160 dx4 = s[6];
2161 dy4 = s[7];
2162 dx5 = s[8];
2163 dy5 = s[9];
2164 dx6 = s[10];
2165 dy6 = s[11];
2166 //fd is s[12]
2167 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2168 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2169 break;
2170
2171 case 0x24: // hflex1
2172 if (sp < 9) return STBTT__CSERR("hflex1 stack");
2173 dx1 = s[0];
2174 dy1 = s[1];
2175 dx2 = s[2];
2176 dy2 = s[3];
2177 dx3 = s[4];
2178 dx4 = s[5];
2179 dx5 = s[6];
2180 dy5 = s[7];
2181 dx6 = s[8];
2182 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
2183 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
2184 break;
2185
2186 case 0x25: // flex1
2187 if (sp < 11) return STBTT__CSERR("flex1 stack");
2188 dx1 = s[0];
2189 dy1 = s[1];
2190 dx2 = s[2];
2191 dy2 = s[3];
2192 dx3 = s[4];
2193 dy3 = s[5];
2194 dx4 = s[6];
2195 dy4 = s[7];
2196 dx5 = s[8];
2197 dy5 = s[9];
2198 dx6 = dy6 = s[10];
2199 dx = dx1+dx2+dx3+dx4+dx5;
2200 dy = dy1+dy2+dy3+dy4+dy5;
2201 if (STBTT_fabs(dx) > STBTT_fabs(dy))
2202 dy6 = -dy;
2203 else
2204 dx6 = -dx;
2205 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2206 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2207 break;
2208
2209 default:
2210 return STBTT__CSERR("unimplemented");
2211 }
2212 } break;
2213
2214 default:
2215 if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560
2216 return STBTT__CSERR("reserved operator");
2217
2218 // push immediate
2219 if (b0 == 255) {
2220 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
2221 } else {
2222 stbtt__buf_skip(&b, -1);
2223 f = (float)(stbtt_int16)stbtt__cff_int(&b);
2224 }
2225 if (sp >= 48) return STBTT__CSERR("push stack overflow");
2226 s[sp++] = f;
2227 clear_stack = 0;
2228 break;
2229 }
2230 if (clear_stack) sp = 0;
2231 }
2232 return STBTT__CSERR("no endchar");
2233
2234 #undef STBTT__CSERR
2235 }
2236
stbtt__GetGlyphShapeT2(const stbtt_fontinfo * info,int glyph_index,stbtt_vertex ** pvertices)2237 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2238 {
2239 // runs the charstring twice, once to count and once to output (to avoid realloc)
2240 stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
2241 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
2242 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
2243 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
2244 output_ctx.pvertices = *pvertices;
2245 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
2246 STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
2247 return output_ctx.num_vertices;
2248 }
2249 }
2250 *pvertices = NULL;
2251 return 0;
2252 }
2253
stbtt__GetGlyphInfoT2(const stbtt_fontinfo * info,int glyph_index,int * x0,int * y0,int * x1,int * y1)2254 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
2255 {
2256 stbtt__csctx c = STBTT__CSCTX_INIT(1);
2257 int r = stbtt__run_charstring(info, glyph_index, &c);
2258 if (x0) *x0 = r ? c.min_x : 0;
2259 if (y0) *y0 = r ? c.min_y : 0;
2260 if (x1) *x1 = r ? c.max_x : 0;
2261 if (y1) *y1 = r ? c.max_y : 0;
2262 return r ? c.num_vertices : 0;
2263 }
2264
stbtt_GetGlyphShape(const stbtt_fontinfo * info,int glyph_index,stbtt_vertex ** pvertices)2265 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2266 {
2267 if (!info->cff.size)
2268 return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
2269 else
2270 return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
2271 }
2272
stbtt_GetGlyphHMetrics(const stbtt_fontinfo * info,int glyph_index,int * advanceWidth,int * leftSideBearing)2273 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
2274 {
2275 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
2276 if (glyph_index < numOfLongHorMetrics) {
2277 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
2278 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
2279 } else {
2280 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
2281 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
2282 }
2283 }
2284
stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo * info,int glyph1,int glyph2)2285 static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2286 {
2287 stbtt_uint8 *data = info->data + info->kern;
2288 stbtt_uint32 needle, straw;
2289 int l, r, m;
2290
2291 // we only look at the first table. it must be 'horizontal' and format 0.
2292 if (!info->kern)
2293 return 0;
2294 if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
2295 return 0;
2296 if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
2297 return 0;
2298
2299 l = 0;
2300 r = ttUSHORT(data+10) - 1;
2301 needle = glyph1 << 16 | glyph2;
2302 while (l <= r) {
2303 m = (l + r) >> 1;
2304 straw = ttULONG(data+18+(m*6)); // note: unaligned read
2305 if (needle < straw)
2306 r = m - 1;
2307 else if (needle > straw)
2308 l = m + 1;
2309 else
2310 return ttSHORT(data+22+(m*6));
2311 }
2312 return 0;
2313 }
2314
stbtt__GetCoverageIndex(stbtt_uint8 * coverageTable,int glyph)2315 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2316 {
2317 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2318 switch(coverageFormat) {
2319 case 1: {
2320 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2321
2322 // Binary search.
2323 stbtt_int32 l=0, r=glyphCount-1, m;
2324 int straw, needle=glyph;
2325 while (l <= r) {
2326 stbtt_uint8 *glyphArray = coverageTable + 4;
2327 stbtt_uint16 glyphID;
2328 m = (l + r) >> 1;
2329 glyphID = ttUSHORT(glyphArray + 2 * m);
2330 straw = glyphID;
2331 if (needle < straw)
2332 r = m - 1;
2333 else if (needle > straw)
2334 l = m + 1;
2335 else {
2336 return m;
2337 }
2338 }
2339 } break;
2340
2341 case 2: {
2342 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2343 stbtt_uint8 *rangeArray = coverageTable + 4;
2344
2345 // Binary search.
2346 stbtt_int32 l=0, r=rangeCount-1, m;
2347 int strawStart, strawEnd, needle=glyph;
2348 while (l <= r) {
2349 stbtt_uint8 *rangeRecord;
2350 m = (l + r) >> 1;
2351 rangeRecord = rangeArray + 6 * m;
2352 strawStart = ttUSHORT(rangeRecord);
2353 strawEnd = ttUSHORT(rangeRecord + 2);
2354 if (needle < strawStart)
2355 r = m - 1;
2356 else if (needle > strawEnd)
2357 l = m + 1;
2358 else {
2359 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2360 return startCoverageIndex + glyph - strawStart;
2361 }
2362 }
2363 } break;
2364
2365 default: {
2366 // There are no other cases.
2367 STBTT_assert(0);
2368 } break;
2369 }
2370
2371 return -1;
2372 }
2373
stbtt__GetGlyphClass(stbtt_uint8 * classDefTable,int glyph)2374 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
2375 {
2376 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2377 switch(classDefFormat)
2378 {
2379 case 1: {
2380 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2381 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2382 stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2383
2384 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2385 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2386
2387 // [DEAR IMGUI] Commented to fix static analyzer warning
2388 //classDefTable = classDef1ValueArray + 2 * glyphCount;
2389 } break;
2390
2391 case 2: {
2392 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2393 stbtt_uint8 *classRangeRecords = classDefTable + 4;
2394
2395 // Binary search.
2396 stbtt_int32 l=0, r=classRangeCount-1, m;
2397 int strawStart, strawEnd, needle=glyph;
2398 while (l <= r) {
2399 stbtt_uint8 *classRangeRecord;
2400 m = (l + r) >> 1;
2401 classRangeRecord = classRangeRecords + 6 * m;
2402 strawStart = ttUSHORT(classRangeRecord);
2403 strawEnd = ttUSHORT(classRangeRecord + 2);
2404 if (needle < strawStart)
2405 r = m - 1;
2406 else if (needle > strawEnd)
2407 l = m + 1;
2408 else
2409 return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2410 }
2411
2412 // [DEAR IMGUI] Commented to fix static analyzer warning
2413 //classDefTable = classRangeRecords + 6 * classRangeCount;
2414 } break;
2415
2416 default: {
2417 // There are no other cases.
2418 STBTT_assert(0);
2419 } break;
2420 }
2421
2422 return -1;
2423 }
2424
2425 // Define to STBTT_assert(x) if you want to break on unimplemented formats.
2426 #define STBTT_GPOS_TODO_assert(x)
2427
stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo * info,int glyph1,int glyph2)2428 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2429 {
2430 stbtt_uint16 lookupListOffset;
2431 stbtt_uint8 *lookupList;
2432 stbtt_uint16 lookupCount;
2433 stbtt_uint8 *data;
2434 stbtt_int32 i;
2435
2436 if (!info->gpos) return 0;
2437
2438 data = info->data + info->gpos;
2439
2440 if (ttUSHORT(data+0) != 1) return 0; // Major version 1
2441 if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
2442
2443 lookupListOffset = ttUSHORT(data+8);
2444 lookupList = data + lookupListOffset;
2445 lookupCount = ttUSHORT(lookupList);
2446
2447 for (i=0; i<lookupCount; ++i) {
2448 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2449 stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2450
2451 stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2452 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2453 stbtt_uint8 *subTableOffsets = lookupTable + 6;
2454 switch(lookupType) {
2455 case 2: { // Pair Adjustment Positioning Subtable
2456 stbtt_int32 sti;
2457 for (sti=0; sti<subTableCount; sti++) {
2458 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2459 stbtt_uint8 *table = lookupTable + subtableOffset;
2460 stbtt_uint16 posFormat = ttUSHORT(table);
2461 stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2462 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2463 if (coverageIndex == -1) continue;
2464
2465 switch (posFormat) {
2466 case 1: {
2467 stbtt_int32 l, r, m;
2468 int straw, needle;
2469 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2470 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2471 stbtt_int32 valueRecordPairSizeInBytes = 2;
2472 stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2473 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2474 stbtt_uint8 *pairValueTable = table + pairPosOffset;
2475 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2476 stbtt_uint8 *pairValueArray = pairValueTable + 2;
2477 // TODO: Support more formats.
2478 STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2479 if (valueFormat1 != 4) return 0;
2480 STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2481 if (valueFormat2 != 0) return 0;
2482
2483 STBTT_assert(coverageIndex < pairSetCount);
2484 STBTT__NOTUSED(pairSetCount);
2485
2486 needle=glyph2;
2487 r=pairValueCount-1;
2488 l=0;
2489
2490 // Binary search.
2491 while (l <= r) {
2492 stbtt_uint16 secondGlyph;
2493 stbtt_uint8 *pairValue;
2494 m = (l + r) >> 1;
2495 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2496 secondGlyph = ttUSHORT(pairValue);
2497 straw = secondGlyph;
2498 if (needle < straw)
2499 r = m - 1;
2500 else if (needle > straw)
2501 l = m + 1;
2502 else {
2503 stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2504 return xAdvance;
2505 }
2506 }
2507 } break;
2508
2509 case 2: {
2510 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2511 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2512
2513 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2514 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2515 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2516 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2517
2518 stbtt_uint16 class1Count = ttUSHORT(table + 12);
2519 stbtt_uint16 class2Count = ttUSHORT(table + 14);
2520 STBTT_assert(glyph1class < class1Count);
2521 STBTT_assert(glyph2class < class2Count);
2522
2523 // TODO: Support more formats.
2524 STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2525 if (valueFormat1 != 4) return 0;
2526 STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2527 if (valueFormat2 != 0) return 0;
2528
2529 if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
2530 stbtt_uint8 *class1Records = table + 16;
2531 stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
2532 stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2533 return xAdvance;
2534 }
2535 } break;
2536
2537 default: {
2538 // There are no other cases.
2539 STBTT_assert(0);
2540 break;
2541 };
2542 }
2543 }
2544 break;
2545 };
2546
2547 default:
2548 // TODO: Implement other stuff.
2549 break;
2550 }
2551 }
2552
2553 return 0;
2554 }
2555
stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * info,int g1,int g2)2556 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
2557 {
2558 int xAdvance = 0;
2559
2560 if (info->gpos)
2561 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2562
2563 if (info->kern)
2564 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2565
2566 return xAdvance;
2567 }
2568
stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * info,int ch1,int ch2)2569 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
2570 {
2571 if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
2572 return 0;
2573 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
2574 }
2575
stbtt_GetCodepointHMetrics(const stbtt_fontinfo * info,int codepoint,int * advanceWidth,int * leftSideBearing)2576 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
2577 {
2578 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
2579 }
2580
stbtt_GetFontVMetrics(const stbtt_fontinfo * info,int * ascent,int * descent,int * lineGap)2581 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
2582 {
2583 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
2584 if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
2585 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
2586 }
2587
stbtt_GetFontVMetricsOS2(const stbtt_fontinfo * info,int * typoAscent,int * typoDescent,int * typoLineGap)2588 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
2589 {
2590 int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
2591 if (!tab)
2592 return 0;
2593 if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
2594 if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
2595 if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
2596 return 1;
2597 }
2598
stbtt_GetFontBoundingBox(const stbtt_fontinfo * info,int * x0,int * y0,int * x1,int * y1)2599 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
2600 {
2601 *x0 = ttSHORT(info->data + info->head + 36);
2602 *y0 = ttSHORT(info->data + info->head + 38);
2603 *x1 = ttSHORT(info->data + info->head + 40);
2604 *y1 = ttSHORT(info->data + info->head + 42);
2605 }
2606
stbtt_ScaleForPixelHeight(const stbtt_fontinfo * info,float height)2607 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
2608 {
2609 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
2610 return (float) height / fheight;
2611 }
2612
stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo * info,float pixels)2613 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
2614 {
2615 int unitsPerEm = ttUSHORT(info->data + info->head + 18);
2616 return pixels / unitsPerEm;
2617 }
2618
stbtt_FreeShape(const stbtt_fontinfo * info,stbtt_vertex * v)2619 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
2620 {
2621 STBTT_free(v, info->userdata);
2622 }
2623
2624 //////////////////////////////////////////////////////////////////////////////
2625 //
2626 // antialiasing software rasterizer
2627 //
2628
stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo * font,int glyph,float scale_x,float scale_y,float shift_x,float shift_y,int * ix0,int * iy0,int * ix1,int * iy1)2629 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
2630 {
2631 int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
2632 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
2633 // e.g. space character
2634 if (ix0) *ix0 = 0;
2635 if (iy0) *iy0 = 0;
2636 if (ix1) *ix1 = 0;
2637 if (iy1) *iy1 = 0;
2638 } else {
2639 // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
2640 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
2641 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
2642 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
2643 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
2644 }
2645 }
2646
stbtt_GetGlyphBitmapBox(const stbtt_fontinfo * font,int glyph,float scale_x,float scale_y,int * ix0,int * iy0,int * ix1,int * iy1)2647 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2648 {
2649 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
2650 }
2651
stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo * font,int codepoint,float scale_x,float scale_y,float shift_x,float shift_y,int * ix0,int * iy0,int * ix1,int * iy1)2652 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
2653 {
2654 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
2655 }
2656
stbtt_GetCodepointBitmapBox(const stbtt_fontinfo * font,int codepoint,float scale_x,float scale_y,int * ix0,int * iy0,int * ix1,int * iy1)2657 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2658 {
2659 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
2660 }
2661
2662 //////////////////////////////////////////////////////////////////////////////
2663 //
2664 // Rasterizer
2665
2666 typedef struct stbtt__hheap_chunk
2667 {
2668 struct stbtt__hheap_chunk *next;
2669 } stbtt__hheap_chunk;
2670
2671 typedef struct stbtt__hheap
2672 {
2673 struct stbtt__hheap_chunk *head;
2674 void *first_free;
2675 int num_remaining_in_head_chunk;
2676 } stbtt__hheap;
2677
stbtt__hheap_alloc(stbtt__hheap * hh,size_t size,void * userdata)2678 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
2679 {
2680 if (hh->first_free) {
2681 void *p = hh->first_free;
2682 hh->first_free = * (void **) p;
2683 return p;
2684 } else {
2685 if (hh->num_remaining_in_head_chunk == 0) {
2686 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
2687 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
2688 if (c == NULL)
2689 return NULL;
2690 c->next = hh->head;
2691 hh->head = c;
2692 hh->num_remaining_in_head_chunk = count;
2693 }
2694 --hh->num_remaining_in_head_chunk;
2695 return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
2696 }
2697 }
2698
stbtt__hheap_free(stbtt__hheap * hh,void * p)2699 static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
2700 {
2701 *(void **) p = hh->first_free;
2702 hh->first_free = p;
2703 }
2704
stbtt__hheap_cleanup(stbtt__hheap * hh,void * userdata)2705 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
2706 {
2707 stbtt__hheap_chunk *c = hh->head;
2708 while (c) {
2709 stbtt__hheap_chunk *n = c->next;
2710 STBTT_free(c, userdata);
2711 c = n;
2712 }
2713 }
2714
2715 typedef struct stbtt__edge {
2716 float x0,y0, x1,y1;
2717 int invert;
2718 } stbtt__edge;
2719
2720
2721 typedef struct stbtt__active_edge
2722 {
2723 struct stbtt__active_edge *next;
2724 #if STBTT_RASTERIZER_VERSION==1
2725 int x,dx;
2726 float ey;
2727 int direction;
2728 #elif STBTT_RASTERIZER_VERSION==2
2729 float fx,fdx,fdy;
2730 float direction;
2731 float sy;
2732 float ey;
2733 #else
2734 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2735 #endif
2736 } stbtt__active_edge;
2737
2738 #if STBTT_RASTERIZER_VERSION == 1
2739 #define STBTT_FIXSHIFT 10
2740 #define STBTT_FIX (1 << STBTT_FIXSHIFT)
2741 #define STBTT_FIXMASK (STBTT_FIX-1)
2742
stbtt__new_active(stbtt__hheap * hh,stbtt__edge * e,int off_x,float start_point,void * userdata)2743 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2744 {
2745 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2746 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2747 STBTT_assert(z != NULL);
2748 if (!z) return z;
2749
2750 // round dx down to avoid overshooting
2751 if (dxdy < 0)
2752 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
2753 else
2754 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
2755
2756 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
2757 z->x -= off_x * STBTT_FIX;
2758
2759 z->ey = e->y1;
2760 z->next = 0;
2761 z->direction = e->invert ? 1 : -1;
2762 return z;
2763 }
2764 #elif STBTT_RASTERIZER_VERSION == 2
stbtt__new_active(stbtt__hheap * hh,stbtt__edge * e,int off_x,float start_point,void * userdata)2765 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2766 {
2767 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2768 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2769 STBTT_assert(z != NULL);
2770 //STBTT_assert(e->y0 <= start_point);
2771 if (!z) return z;
2772 z->fdx = dxdy;
2773 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
2774 z->fx = e->x0 + dxdy * (start_point - e->y0);
2775 z->fx -= off_x;
2776 z->direction = e->invert ? 1.0f : -1.0f;
2777 z->sy = e->y0;
2778 z->ey = e->y1;
2779 z->next = 0;
2780 return z;
2781 }
2782 #else
2783 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2784 #endif
2785
2786 #if STBTT_RASTERIZER_VERSION == 1
2787 // note: this routine clips fills that extend off the edges... ideally this
2788 // wouldn't happen, but it could happen if the truetype glyph bounding boxes
2789 // are wrong, or if the user supplies a too-small bitmap
stbtt__fill_active_edges(unsigned char * scanline,int len,stbtt__active_edge * e,int max_weight)2790 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
2791 {
2792 // non-zero winding fill
2793 int x0=0, w=0;
2794
2795 while (e) {
2796 if (w == 0) {
2797 // if we're currently at zero, we need to record the edge start point
2798 x0 = e->x; w += e->direction;
2799 } else {
2800 int x1 = e->x; w += e->direction;
2801 // if we went to zero, we need to draw
2802 if (w == 0) {
2803 int i = x0 >> STBTT_FIXSHIFT;
2804 int j = x1 >> STBTT_FIXSHIFT;
2805
2806 if (i < len && j >= 0) {
2807 if (i == j) {
2808 // x0,x1 are the same pixel, so compute combined coverage
2809 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
2810 } else {
2811 if (i >= 0) // add antialiasing for x0
2812 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
2813 else
2814 i = -1; // clip
2815
2816 if (j < len) // add antialiasing for x1
2817 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
2818 else
2819 j = len; // clip
2820
2821 for (++i; i < j; ++i) // fill pixels between x0 and x1
2822 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
2823 }
2824 }
2825 }
2826 }
2827
2828 e = e->next;
2829 }
2830 }
2831
stbtt__rasterize_sorted_edges(stbtt__bitmap * result,stbtt__edge * e,int n,int vsubsample,int off_x,int off_y,void * userdata)2832 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
2833 {
2834 stbtt__hheap hh = { 0, 0, 0 };
2835 stbtt__active_edge *active = NULL;
2836 int y,j=0;
2837 int max_weight = (255 / vsubsample); // weight per vertical scanline
2838 int s; // vertical subsample index
2839 unsigned char scanline_data[512], *scanline;
2840
2841 if (result->w > 512)
2842 scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
2843 else
2844 scanline = scanline_data;
2845
2846 y = off_y * vsubsample;
2847 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
2848
2849 while (j < result->h) {
2850 STBTT_memset(scanline, 0, result->w);
2851 for (s=0; s < vsubsample; ++s) {
2852 // find center of pixel for this scanline
2853 float scan_y = y + 0.5f;
2854 stbtt__active_edge **step = &active;
2855
2856 // update all active edges;
2857 // remove all active edges that terminate before the center of this scanline
2858 while (*step) {
2859 stbtt__active_edge * z = *step;
2860 if (z->ey <= scan_y) {
2861 *step = z->next; // delete from list
2862 STBTT_assert(z->direction);
2863 z->direction = 0;
2864 stbtt__hheap_free(&hh, z);
2865 } else {
2866 z->x += z->dx; // advance to position for current scanline
2867 step = &((*step)->next); // advance through list
2868 }
2869 }
2870
2871 // resort the list if needed
2872 for(;;) {
2873 int changed=0;
2874 step = &active;
2875 while (*step && (*step)->next) {
2876 if ((*step)->x > (*step)->next->x) {
2877 stbtt__active_edge *t = *step;
2878 stbtt__active_edge *q = t->next;
2879
2880 t->next = q->next;
2881 q->next = t;
2882 *step = q;
2883 changed = 1;
2884 }
2885 step = &(*step)->next;
2886 }
2887 if (!changed) break;
2888 }
2889
2890 // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
2891 while (e->y0 <= scan_y) {
2892 if (e->y1 > scan_y) {
2893 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
2894 if (z != NULL) {
2895 // find insertion point
2896 if (active == NULL)
2897 active = z;
2898 else if (z->x < active->x) {
2899 // insert at front
2900 z->next = active;
2901 active = z;
2902 } else {
2903 // find thing to insert AFTER
2904 stbtt__active_edge *p = active;
2905 while (p->next && p->next->x < z->x)
2906 p = p->next;
2907 // at this point, p->next->x is NOT < z->x
2908 z->next = p->next;
2909 p->next = z;
2910 }
2911 }
2912 }
2913 ++e;
2914 }
2915
2916 // now process all active edges in XOR fashion
2917 if (active)
2918 stbtt__fill_active_edges(scanline, result->w, active, max_weight);
2919
2920 ++y;
2921 }
2922 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
2923 ++j;
2924 }
2925
2926 stbtt__hheap_cleanup(&hh, userdata);
2927
2928 if (scanline != scanline_data)
2929 STBTT_free(scanline, userdata);
2930 }
2931
2932 #elif STBTT_RASTERIZER_VERSION == 2
2933
2934 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1
2935 // (i.e. it has already been clipped to those)
stbtt__handle_clipped_edge(float * scanline,int x,stbtt__active_edge * e,float x0,float y0,float x1,float y1)2936 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
2937 {
2938 if (y0 == y1) return;
2939 STBTT_assert(y0 < y1);
2940 STBTT_assert(e->sy <= e->ey);
2941 if (y0 > e->ey) return;
2942 if (y1 < e->sy) return;
2943 if (y0 < e->sy) {
2944 x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
2945 y0 = e->sy;
2946 }
2947 if (y1 > e->ey) {
2948 x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
2949 y1 = e->ey;
2950 }
2951
2952 if (x0 == x)
2953 STBTT_assert(x1 <= x+1);
2954 else if (x0 == x+1)
2955 STBTT_assert(x1 >= x);
2956 else if (x0 <= x)
2957 STBTT_assert(x1 <= x);
2958 else if (x0 >= x+1)
2959 STBTT_assert(x1 >= x+1);
2960 else
2961 STBTT_assert(x1 >= x && x1 <= x+1);
2962
2963 if (x0 <= x && x1 <= x)
2964 scanline[x] += e->direction * (y1-y0);
2965 else if (x0 >= x+1 && x1 >= x+1)
2966 ;
2967 else {
2968 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
2969 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
2970 }
2971 }
2972
stbtt__fill_active_edges_new(float * scanline,float * scanline_fill,int len,stbtt__active_edge * e,float y_top)2973 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
2974 {
2975 float y_bottom = y_top+1;
2976
2977 while (e) {
2978 // brute force every pixel
2979
2980 // compute intersection points with top & bottom
2981 STBTT_assert(e->ey >= y_top);
2982
2983 if (e->fdx == 0) {
2984 float x0 = e->fx;
2985 if (x0 < len) {
2986 if (x0 >= 0) {
2987 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
2988 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
2989 } else {
2990 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
2991 }
2992 }
2993 } else {
2994 float x0 = e->fx;
2995 float dx = e->fdx;
2996 float xb = x0 + dx;
2997 float x_top, x_bottom;
2998 float sy0,sy1;
2999 float dy = e->fdy;
3000 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
3001
3002 // compute endpoints of line segment clipped to this scanline (if the
3003 // line segment starts on this scanline. x0 is the intersection of the
3004 // line with y_top, but that may be off the line segment.
3005 if (e->sy > y_top) {
3006 x_top = x0 + dx * (e->sy - y_top);
3007 sy0 = e->sy;
3008 } else {
3009 x_top = x0;
3010 sy0 = y_top;
3011 }
3012 if (e->ey < y_bottom) {
3013 x_bottom = x0 + dx * (e->ey - y_top);
3014 sy1 = e->ey;
3015 } else {
3016 x_bottom = xb;
3017 sy1 = y_bottom;
3018 }
3019
3020 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
3021 // from here on, we don't have to range check x values
3022
3023 if ((int) x_top == (int) x_bottom) {
3024 float height;
3025 // simple case, only spans one pixel
3026 int x = (int) x_top;
3027 height = sy1 - sy0;
3028 STBTT_assert(x >= 0 && x < len);
3029 scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
3030 scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
3031 } else {
3032 int x,x1,x2;
3033 float y_crossing, step, sign, area;
3034 // covers 2+ pixels
3035 if (x_top > x_bottom) {
3036 // flip scanline vertically; signed area is the same
3037 float t;
3038 sy0 = y_bottom - (sy0 - y_top);
3039 sy1 = y_bottom - (sy1 - y_top);
3040 t = sy0, sy0 = sy1, sy1 = t;
3041 t = x_bottom, x_bottom = x_top, x_top = t;
3042 dx = -dx;
3043 dy = -dy;
3044 t = x0, x0 = xb, xb = t;
3045 // [DEAR IMGUI] Fix static analyzer warning
3046 (void)dx; // [ImGui: fix static analyzer warning]
3047 }
3048
3049 x1 = (int) x_top;
3050 x2 = (int) x_bottom;
3051 // compute intersection with y axis at x1+1
3052 y_crossing = (x1+1 - x0) * dy + y_top;
3053
3054 sign = e->direction;
3055 // area of the rectangle covered from y0..y_crossing
3056 area = sign * (y_crossing-sy0);
3057 // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
3058 scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
3059
3060 step = sign * dy;
3061 for (x = x1+1; x < x2; ++x) {
3062 scanline[x] += area + step/2;
3063 area += step;
3064 }
3065 y_crossing += dy * (x2 - (x1+1));
3066
3067 STBTT_assert(STBTT_fabs(area) <= 1.01f);
3068
3069 scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
3070
3071 scanline_fill[x2] += sign * (sy1-sy0);
3072 }
3073 } else {
3074 // if edge goes outside of box we're drawing, we require
3075 // clipping logic. since this does not match the intended use
3076 // of this library, we use a different, very slow brute
3077 // force implementation
3078 int x;
3079 for (x=0; x < len; ++x) {
3080 // cases:
3081 //
3082 // there can be up to two intersections with the pixel. any intersection
3083 // with left or right edges can be handled by splitting into two (or three)
3084 // regions. intersections with top & bottom do not necessitate case-wise logic.
3085 //
3086 // the old way of doing this found the intersections with the left & right edges,
3087 // then used some simple logic to produce up to three segments in sorted order
3088 // from top-to-bottom. however, this had a problem: if an x edge was epsilon
3089 // across the x border, then the corresponding y position might not be distinct
3090 // from the other y segment, and it might ignored as an empty segment. to avoid
3091 // that, we need to explicitly produce segments based on x positions.
3092
3093 // rename variables to clearly-defined pairs
3094 float y0 = y_top;
3095 float x1 = (float) (x);
3096 float x2 = (float) (x+1);
3097 float x3 = xb;
3098 float y3 = y_bottom;
3099
3100 // x = e->x + e->dx * (y-y_top)
3101 // (y-y_top) = (x - e->x) / e->dx
3102 // y = (x - e->x) / e->dx + y_top
3103 float y1 = (x - x0) / dx + y_top;
3104 float y2 = (x+1 - x0) / dx + y_top;
3105
3106 if (x0 < x1 && x3 > x2) { // three segments descending down-right
3107 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3108 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
3109 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3110 } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
3111 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3112 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
3113 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3114 } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
3115 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3116 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3117 } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
3118 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3119 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3120 } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
3121 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3122 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3123 } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
3124 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3125 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3126 } else { // one segment
3127 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
3128 }
3129 }
3130 }
3131 }
3132 e = e->next;
3133 }
3134 }
3135
3136 // directly AA rasterize edges w/o supersampling
stbtt__rasterize_sorted_edges(stbtt__bitmap * result,stbtt__edge * e,int n,int vsubsample,int off_x,int off_y,void * userdata)3137 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
3138 {
3139 stbtt__hheap hh = { 0, 0, 0 };
3140 stbtt__active_edge *active = NULL;
3141 int y,j=0, i;
3142 float scanline_data[129], *scanline, *scanline2;
3143
3144 STBTT__NOTUSED(vsubsample);
3145
3146 if (result->w > 64)
3147 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
3148 else
3149 scanline = scanline_data;
3150
3151 scanline2 = scanline + result->w;
3152
3153 y = off_y;
3154 e[n].y0 = (float) (off_y + result->h) + 1;
3155
3156 while (j < result->h) {
3157 // find center of pixel for this scanline
3158 float scan_y_top = y + 0.0f;
3159 float scan_y_bottom = y + 1.0f;
3160 stbtt__active_edge **step = &active;
3161
3162 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
3163 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
3164
3165 // update all active edges;
3166 // remove all active edges that terminate before the top of this scanline
3167 while (*step) {
3168 stbtt__active_edge * z = *step;
3169 if (z->ey <= scan_y_top) {
3170 *step = z->next; // delete from list
3171 STBTT_assert(z->direction);
3172 z->direction = 0;
3173 stbtt__hheap_free(&hh, z);
3174 } else {
3175 step = &((*step)->next); // advance through list
3176 }
3177 }
3178
3179 // insert all edges that start before the bottom of this scanline
3180 while (e->y0 <= scan_y_bottom) {
3181 if (e->y0 != e->y1) {
3182 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3183 if (z != NULL) {
3184 if (j == 0 && off_y != 0) {
3185 if (z->ey < scan_y_top) {
3186 // this can happen due to subpixel positioning and some kind of fp rounding error i think
3187 z->ey = scan_y_top;
3188 }
3189 }
3190 STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
3191 // insert at front
3192 z->next = active;
3193 active = z;
3194 }
3195 }
3196 ++e;
3197 }
3198
3199 // now process all active edges
3200 if (active)
3201 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
3202
3203 {
3204 float sum = 0;
3205 for (i=0; i < result->w; ++i) {
3206 float k;
3207 int m;
3208 sum += scanline2[i];
3209 k = scanline[i] + sum;
3210 k = (float) STBTT_fabs(k)*255 + 0.5f;
3211 m = (int) k;
3212 if (m > 255) m = 255;
3213 result->pixels[j*result->stride + i] = (unsigned char) m;
3214 }
3215 }
3216 // advance all the edges
3217 step = &active;
3218 while (*step) {
3219 stbtt__active_edge *z = *step;
3220 z->fx += z->fdx; // advance to position for current scanline
3221 step = &((*step)->next); // advance through list
3222 }
3223
3224 ++y;
3225 ++j;
3226 }
3227
3228 stbtt__hheap_cleanup(&hh, userdata);
3229
3230 if (scanline != scanline_data)
3231 STBTT_free(scanline, userdata);
3232 }
3233 #else
3234 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3235 #endif
3236
3237 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
3238
stbtt__sort_edges_ins_sort(stbtt__edge * p,int n)3239 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
3240 {
3241 int i,j;
3242 for (i=1; i < n; ++i) {
3243 stbtt__edge t = p[i], *a = &t;
3244 j = i;
3245 while (j > 0) {
3246 stbtt__edge *b = &p[j-1];
3247 int c = STBTT__COMPARE(a,b);
3248 if (!c) break;
3249 p[j] = p[j-1];
3250 --j;
3251 }
3252 if (i != j)
3253 p[j] = t;
3254 }
3255 }
3256
stbtt__sort_edges_quicksort(stbtt__edge * p,int n)3257 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
3258 {
3259 /* threshold for transitioning to insertion sort */
3260 while (n > 12) {
3261 stbtt__edge t;
3262 int c01,c12,c,m,i,j;
3263
3264 /* compute median of three */
3265 m = n >> 1;
3266 c01 = STBTT__COMPARE(&p[0],&p[m]);
3267 c12 = STBTT__COMPARE(&p[m],&p[n-1]);
3268 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
3269 if (c01 != c12) {
3270 /* otherwise, we'll need to swap something else to middle */
3271 int z;
3272 c = STBTT__COMPARE(&p[0],&p[n-1]);
3273 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
3274 /* 0<mid && mid>n: 0>n => 0; 0<n => n */
3275 z = (c == c12) ? 0 : n-1;
3276 t = p[z];
3277 p[z] = p[m];
3278 p[m] = t;
3279 }
3280 /* now p[m] is the median-of-three */
3281 /* swap it to the beginning so it won't move around */
3282 t = p[0];
3283 p[0] = p[m];
3284 p[m] = t;
3285
3286 /* partition loop */
3287 i=1;
3288 j=n-1;
3289 for(;;) {
3290 /* handling of equality is crucial here */
3291 /* for sentinels & efficiency with duplicates */
3292 for (;;++i) {
3293 if (!STBTT__COMPARE(&p[i], &p[0])) break;
3294 }
3295 for (;;--j) {
3296 if (!STBTT__COMPARE(&p[0], &p[j])) break;
3297 }
3298 /* make sure we haven't crossed */
3299 if (i >= j) break;
3300 t = p[i];
3301 p[i] = p[j];
3302 p[j] = t;
3303
3304 ++i;
3305 --j;
3306 }
3307 /* recurse on smaller side, iterate on larger */
3308 if (j < (n-i)) {
3309 stbtt__sort_edges_quicksort(p,j);
3310 p = p+i;
3311 n = n-i;
3312 } else {
3313 stbtt__sort_edges_quicksort(p+i, n-i);
3314 n = j;
3315 }
3316 }
3317 }
3318
stbtt__sort_edges(stbtt__edge * p,int n)3319 static void stbtt__sort_edges(stbtt__edge *p, int n)
3320 {
3321 stbtt__sort_edges_quicksort(p, n);
3322 stbtt__sort_edges_ins_sort(p, n);
3323 }
3324
3325 typedef struct
3326 {
3327 float x,y;
3328 } stbtt__point;
3329
stbtt__rasterize(stbtt__bitmap * result,stbtt__point * pts,int * wcount,int windings,float scale_x,float scale_y,float shift_x,float shift_y,int off_x,int off_y,int invert,void * userdata)3330 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
3331 {
3332 float y_scale_inv = invert ? -scale_y : scale_y;
3333 stbtt__edge *e;
3334 int n,i,j,k,m;
3335 #if STBTT_RASTERIZER_VERSION == 1
3336 int vsubsample = result->h < 8 ? 15 : 5;
3337 #elif STBTT_RASTERIZER_VERSION == 2
3338 int vsubsample = 1;
3339 #else
3340 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3341 #endif
3342 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
3343
3344 // now we have to blow out the windings into explicit edge lists
3345 n = 0;
3346 for (i=0; i < windings; ++i)
3347 n += wcount[i];
3348
3349 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
3350 if (e == 0) return;
3351 n = 0;
3352
3353 m=0;
3354 for (i=0; i < windings; ++i) {
3355 stbtt__point *p = pts + m;
3356 m += wcount[i];
3357 j = wcount[i]-1;
3358 for (k=0; k < wcount[i]; j=k++) {
3359 int a=k,b=j;
3360 // skip the edge if horizontal
3361 if (p[j].y == p[k].y)
3362 continue;
3363 // add edge from j to k to the list
3364 e[n].invert = 0;
3365 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
3366 e[n].invert = 1;
3367 a=j,b=k;
3368 }
3369 e[n].x0 = p[a].x * scale_x + shift_x;
3370 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
3371 e[n].x1 = p[b].x * scale_x + shift_x;
3372 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
3373 ++n;
3374 }
3375 }
3376
3377 // now sort the edges by their highest point (should snap to integer, and then by x)
3378 //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
3379 stbtt__sort_edges(e, n);
3380
3381 // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
3382 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
3383
3384 STBTT_free(e, userdata);
3385 }
3386
stbtt__add_point(stbtt__point * points,int n,float x,float y)3387 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
3388 {
3389 if (!points) return; // during first pass, it's unallocated
3390 points[n].x = x;
3391 points[n].y = y;
3392 }
3393
3394 // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
stbtt__tesselate_curve(stbtt__point * points,int * num_points,float x0,float y0,float x1,float y1,float x2,float y2,float objspace_flatness_squared,int n)3395 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
3396 {
3397 // midpoint
3398 float mx = (x0 + 2*x1 + x2)/4;
3399 float my = (y0 + 2*y1 + y2)/4;
3400 // versus directly drawn line
3401 float dx = (x0+x2)/2 - mx;
3402 float dy = (y0+y2)/2 - my;
3403 if (n > 16) // 65536 segments on one curve better be enough!
3404 return 1;
3405 if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
3406 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
3407 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
3408 } else {
3409 stbtt__add_point(points, *num_points,x2,y2);
3410 *num_points = *num_points+1;
3411 }
3412 return 1;
3413 }
3414
stbtt__tesselate_cubic(stbtt__point * points,int * num_points,float x0,float y0,float x1,float y1,float x2,float y2,float x3,float y3,float objspace_flatness_squared,int n)3415 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
3416 {
3417 // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
3418 float dx0 = x1-x0;
3419 float dy0 = y1-y0;
3420 float dx1 = x2-x1;
3421 float dy1 = y2-y1;
3422 float dx2 = x3-x2;
3423 float dy2 = y3-y2;
3424 float dx = x3-x0;
3425 float dy = y3-y0;
3426 float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
3427 float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
3428 float flatness_squared = longlen*longlen-shortlen*shortlen;
3429
3430 if (n > 16) // 65536 segments on one curve better be enough!
3431 return;
3432
3433 if (flatness_squared > objspace_flatness_squared) {
3434 float x01 = (x0+x1)/2;
3435 float y01 = (y0+y1)/2;
3436 float x12 = (x1+x2)/2;
3437 float y12 = (y1+y2)/2;
3438 float x23 = (x2+x3)/2;
3439 float y23 = (y2+y3)/2;
3440
3441 float xa = (x01+x12)/2;
3442 float ya = (y01+y12)/2;
3443 float xb = (x12+x23)/2;
3444 float yb = (y12+y23)/2;
3445
3446 float mx = (xa+xb)/2;
3447 float my = (ya+yb)/2;
3448
3449 stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
3450 stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
3451 } else {
3452 stbtt__add_point(points, *num_points,x3,y3);
3453 *num_points = *num_points+1;
3454 }
3455 }
3456
3457 // returns number of contours
stbtt_FlattenCurves(stbtt_vertex * vertices,int num_verts,float objspace_flatness,int ** contour_lengths,int * num_contours,void * userdata)3458 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
3459 {
3460 stbtt__point *points=0;
3461 int num_points=0;
3462
3463 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
3464 int i,n=0,start=0, pass;
3465
3466 // count how many "moves" there are to get the contour count
3467 for (i=0; i < num_verts; ++i)
3468 if (vertices[i].type == STBTT_vmove)
3469 ++n;
3470
3471 *num_contours = n;
3472 if (n == 0) return 0;
3473
3474 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
3475
3476 if (*contour_lengths == 0) {
3477 *num_contours = 0;
3478 return 0;
3479 }
3480
3481 // make two passes through the points so we don't need to realloc
3482 for (pass=0; pass < 2; ++pass) {
3483 float x=0,y=0;
3484 if (pass == 1) {
3485 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
3486 if (points == NULL) goto error;
3487 }
3488 num_points = 0;
3489 n= -1;
3490 for (i=0; i < num_verts; ++i) {
3491 switch (vertices[i].type) {
3492 case STBTT_vmove:
3493 // start the next contour
3494 if (n >= 0)
3495 (*contour_lengths)[n] = num_points - start;
3496 ++n;
3497 start = num_points;
3498
3499 x = vertices[i].x, y = vertices[i].y;
3500 stbtt__add_point(points, num_points++, x,y);
3501 break;
3502 case STBTT_vline:
3503 x = vertices[i].x, y = vertices[i].y;
3504 stbtt__add_point(points, num_points++, x, y);
3505 break;
3506 case STBTT_vcurve:
3507 stbtt__tesselate_curve(points, &num_points, x,y,
3508 vertices[i].cx, vertices[i].cy,
3509 vertices[i].x, vertices[i].y,
3510 objspace_flatness_squared, 0);
3511 x = vertices[i].x, y = vertices[i].y;
3512 break;
3513 case STBTT_vcubic:
3514 stbtt__tesselate_cubic(points, &num_points, x,y,
3515 vertices[i].cx, vertices[i].cy,
3516 vertices[i].cx1, vertices[i].cy1,
3517 vertices[i].x, vertices[i].y,
3518 objspace_flatness_squared, 0);
3519 x = vertices[i].x, y = vertices[i].y;
3520 break;
3521 }
3522 }
3523 (*contour_lengths)[n] = num_points - start;
3524 }
3525
3526 return points;
3527 error:
3528 STBTT_free(points, userdata);
3529 STBTT_free(*contour_lengths, userdata);
3530 *contour_lengths = 0;
3531 *num_contours = 0;
3532 return NULL;
3533 }
3534
stbtt_Rasterize(stbtt__bitmap * result,float flatness_in_pixels,stbtt_vertex * vertices,int num_verts,float scale_x,float scale_y,float shift_x,float shift_y,int x_off,int y_off,int invert,void * userdata)3535 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
3536 {
3537 float scale = scale_x > scale_y ? scale_y : scale_x;
3538 int winding_count = 0;
3539 int *winding_lengths = NULL;
3540 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
3541 if (windings) {
3542 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
3543 STBTT_free(winding_lengths, userdata);
3544 STBTT_free(windings, userdata);
3545 }
3546 }
3547
stbtt_FreeBitmap(unsigned char * bitmap,void * userdata)3548 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
3549 {
3550 STBTT_free(bitmap, userdata);
3551 }
3552
stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo * info,float scale_x,float scale_y,float shift_x,float shift_y,int glyph,int * width,int * height,int * xoff,int * yoff)3553 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
3554 {
3555 int ix0,iy0,ix1,iy1;
3556 stbtt__bitmap gbm;
3557 stbtt_vertex *vertices;
3558 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3559
3560 if (scale_x == 0) scale_x = scale_y;
3561 if (scale_y == 0) {
3562 if (scale_x == 0) {
3563 STBTT_free(vertices, info->userdata);
3564 return NULL;
3565 }
3566 scale_y = scale_x;
3567 }
3568
3569 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
3570
3571 // now we get the size
3572 gbm.w = (ix1 - ix0);
3573 gbm.h = (iy1 - iy0);
3574 gbm.pixels = NULL; // in case we error
3575
3576 if (width ) *width = gbm.w;
3577 if (height) *height = gbm.h;
3578 if (xoff ) *xoff = ix0;
3579 if (yoff ) *yoff = iy0;
3580
3581 if (gbm.w && gbm.h) {
3582 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
3583 if (gbm.pixels) {
3584 gbm.stride = gbm.w;
3585
3586 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
3587 }
3588 }
3589 STBTT_free(vertices, info->userdata);
3590 return gbm.pixels;
3591 }
3592
stbtt_GetGlyphBitmap(const stbtt_fontinfo * info,float scale_x,float scale_y,int glyph,int * width,int * height,int * xoff,int * yoff)3593 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
3594 {
3595 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
3596 }
3597
stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,float shift_x,float shift_y,int glyph)3598 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
3599 {
3600 int ix0,iy0;
3601 stbtt_vertex *vertices;
3602 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3603 stbtt__bitmap gbm;
3604
3605 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
3606 gbm.pixels = output;
3607 gbm.w = out_w;
3608 gbm.h = out_h;
3609 gbm.stride = out_stride;
3610
3611 if (gbm.w && gbm.h)
3612 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
3613
3614 STBTT_free(vertices, info->userdata);
3615 }
3616
stbtt_MakeGlyphBitmap(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,int glyph)3617 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
3618 {
3619 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
3620 }
3621
stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo * info,float scale_x,float scale_y,float shift_x,float shift_y,int codepoint,int * width,int * height,int * xoff,int * yoff)3622 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
3623 {
3624 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
3625 }
3626
stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,float shift_x,float shift_y,int oversample_x,int oversample_y,float * sub_x,float * sub_y,int codepoint)3627 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
3628 {
3629 stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
3630 }
3631
stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,float shift_x,float shift_y,int codepoint)3632 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
3633 {
3634 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
3635 }
3636
stbtt_GetCodepointBitmap(const stbtt_fontinfo * info,float scale_x,float scale_y,int codepoint,int * width,int * height,int * xoff,int * yoff)3637 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
3638 {
3639 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
3640 }
3641
stbtt_MakeCodepointBitmap(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,int codepoint)3642 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
3643 {
3644 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
3645 }
3646
3647 //////////////////////////////////////////////////////////////////////////////
3648 //
3649 // bitmap baking
3650 //
3651 // This is SUPER-CRAPPY packing to keep source code small
3652
stbtt_BakeFontBitmap_internal(unsigned char * data,int offset,float pixel_height,unsigned char * pixels,int pw,int ph,int first_char,int num_chars,stbtt_bakedchar * chardata)3653 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
3654 float pixel_height, // height of font in pixels
3655 unsigned char *pixels, int pw, int ph, // bitmap to be filled in
3656 int first_char, int num_chars, // characters to bake
3657 stbtt_bakedchar *chardata)
3658 {
3659 float scale;
3660 int x,y,bottom_y, i;
3661 stbtt_fontinfo f;
3662 f.userdata = NULL;
3663 if (!stbtt_InitFont(&f, data, offset))
3664 return -1;
3665 STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
3666 x=y=1;
3667 bottom_y = 1;
3668
3669 scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
3670
3671 for (i=0; i < num_chars; ++i) {
3672 int advance, lsb, x0,y0,x1,y1,gw,gh;
3673 int g = stbtt_FindGlyphIndex(&f, first_char + i);
3674 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
3675 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
3676 gw = x1-x0;
3677 gh = y1-y0;
3678 if (x + gw + 1 >= pw)
3679 y = bottom_y, x = 1; // advance to next row
3680 if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
3681 return -i;
3682 STBTT_assert(x+gw < pw);
3683 STBTT_assert(y+gh < ph);
3684 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
3685 chardata[i].x0 = (stbtt_int16) x;
3686 chardata[i].y0 = (stbtt_int16) y;
3687 chardata[i].x1 = (stbtt_int16) (x + gw);
3688 chardata[i].y1 = (stbtt_int16) (y + gh);
3689 chardata[i].xadvance = scale * advance;
3690 chardata[i].xoff = (float) x0;
3691 chardata[i].yoff = (float) y0;
3692 x = x + gw + 1;
3693 if (y+gh+1 > bottom_y)
3694 bottom_y = y+gh+1;
3695 }
3696 return bottom_y;
3697 }
3698
stbtt_GetBakedQuad(const stbtt_bakedchar * chardata,int pw,int ph,int char_index,float * xpos,float * ypos,stbtt_aligned_quad * q,int opengl_fillrule)3699 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
3700 {
3701 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
3702 float ipw = 1.0f / pw, iph = 1.0f / ph;
3703 const stbtt_bakedchar *b = chardata + char_index;
3704 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
3705 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
3706
3707 q->x0 = round_x + d3d_bias;
3708 q->y0 = round_y + d3d_bias;
3709 q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
3710 q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
3711
3712 q->s0 = b->x0 * ipw;
3713 q->t0 = b->y0 * iph;
3714 q->s1 = b->x1 * ipw;
3715 q->t1 = b->y1 * iph;
3716
3717 *xpos += b->xadvance;
3718 }
3719
3720 //////////////////////////////////////////////////////////////////////////////
3721 //
3722 // rectangle packing replacement routines if you don't have stb_rect_pack.h
3723 //
3724
3725 #ifndef STB_RECT_PACK_VERSION
3726
3727 typedef int stbrp_coord;
3728
3729 ////////////////////////////////////////////////////////////////////////////////////
3730 // //
3731 // //
3732 // COMPILER WARNING ?!?!? //
3733 // //
3734 // //
3735 // if you get a compile warning due to these symbols being defined more than //
3736 // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
3737 // //
3738 ////////////////////////////////////////////////////////////////////////////////////
3739
3740 typedef struct
3741 {
3742 int width,height;
3743 int x,y,bottom_y;
3744 } stbrp_context;
3745
3746 typedef struct
3747 {
3748 unsigned char x;
3749 } stbrp_node;
3750
3751 struct stbrp_rect
3752 {
3753 stbrp_coord x,y;
3754 int id,w,h,was_packed;
3755 };
3756
stbrp_init_target(stbrp_context * con,int pw,int ph,stbrp_node * nodes,int num_nodes)3757 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
3758 {
3759 con->width = pw;
3760 con->height = ph;
3761 con->x = 0;
3762 con->y = 0;
3763 con->bottom_y = 0;
3764 STBTT__NOTUSED(nodes);
3765 STBTT__NOTUSED(num_nodes);
3766 }
3767
stbrp_pack_rects(stbrp_context * con,stbrp_rect * rects,int num_rects)3768 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
3769 {
3770 int i;
3771 for (i=0; i < num_rects; ++i) {
3772 if (con->x + rects[i].w > con->width) {
3773 con->x = 0;
3774 con->y = con->bottom_y;
3775 }
3776 if (con->y + rects[i].h > con->height)
3777 break;
3778 rects[i].x = con->x;
3779 rects[i].y = con->y;
3780 rects[i].was_packed = 1;
3781 con->x += rects[i].w;
3782 if (con->y + rects[i].h > con->bottom_y)
3783 con->bottom_y = con->y + rects[i].h;
3784 }
3785 for ( ; i < num_rects; ++i)
3786 rects[i].was_packed = 0;
3787 }
3788 #endif
3789
3790 //////////////////////////////////////////////////////////////////////////////
3791 //
3792 // bitmap baking
3793 //
3794 // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
3795 // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
3796
stbtt_PackBegin(stbtt_pack_context * spc,unsigned char * pixels,int pw,int ph,int stride_in_bytes,int padding,void * alloc_context)3797 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
3798 {
3799 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
3800 int num_nodes = pw - padding;
3801 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
3802
3803 if (context == NULL || nodes == NULL) {
3804 if (context != NULL) STBTT_free(context, alloc_context);
3805 if (nodes != NULL) STBTT_free(nodes , alloc_context);
3806 return 0;
3807 }
3808
3809 spc->user_allocator_context = alloc_context;
3810 spc->width = pw;
3811 spc->height = ph;
3812 spc->pixels = pixels;
3813 spc->pack_info = context;
3814 spc->nodes = nodes;
3815 spc->padding = padding;
3816 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
3817 spc->h_oversample = 1;
3818 spc->v_oversample = 1;
3819 spc->skip_missing = 0;
3820
3821 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
3822
3823 if (pixels)
3824 STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
3825
3826 return 1;
3827 }
3828
stbtt_PackEnd(stbtt_pack_context * spc)3829 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
3830 {
3831 STBTT_free(spc->nodes , spc->user_allocator_context);
3832 STBTT_free(spc->pack_info, spc->user_allocator_context);
3833 }
3834
stbtt_PackSetOversampling(stbtt_pack_context * spc,unsigned int h_oversample,unsigned int v_oversample)3835 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
3836 {
3837 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
3838 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
3839 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
3840 spc->h_oversample = h_oversample;
3841 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
3842 spc->v_oversample = v_oversample;
3843 }
3844
stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context * spc,int skip)3845 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
3846 {
3847 spc->skip_missing = skip;
3848 }
3849
3850 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
3851
stbtt__h_prefilter(unsigned char * pixels,int w,int h,int stride_in_bytes,unsigned int kernel_width)3852 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
3853 {
3854 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3855 int safe_w = w - kernel_width;
3856 int j;
3857 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
3858 for (j=0; j < h; ++j) {
3859 int i;
3860 unsigned int total;
3861 STBTT_memset(buffer, 0, kernel_width);
3862
3863 total = 0;
3864
3865 // make kernel_width a constant in common cases so compiler can optimize out the divide
3866 switch (kernel_width) {
3867 case 2:
3868 for (i=0; i <= safe_w; ++i) {
3869 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3870 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3871 pixels[i] = (unsigned char) (total / 2);
3872 }
3873 break;
3874 case 3:
3875 for (i=0; i <= safe_w; ++i) {
3876 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3877 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3878 pixels[i] = (unsigned char) (total / 3);
3879 }
3880 break;
3881 case 4:
3882 for (i=0; i <= safe_w; ++i) {
3883 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3884 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3885 pixels[i] = (unsigned char) (total / 4);
3886 }
3887 break;
3888 case 5:
3889 for (i=0; i <= safe_w; ++i) {
3890 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3891 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3892 pixels[i] = (unsigned char) (total / 5);
3893 }
3894 break;
3895 default:
3896 for (i=0; i <= safe_w; ++i) {
3897 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3898 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3899 pixels[i] = (unsigned char) (total / kernel_width);
3900 }
3901 break;
3902 }
3903
3904 for (; i < w; ++i) {
3905 STBTT_assert(pixels[i] == 0);
3906 total -= buffer[i & STBTT__OVER_MASK];
3907 pixels[i] = (unsigned char) (total / kernel_width);
3908 }
3909
3910 pixels += stride_in_bytes;
3911 }
3912 }
3913
stbtt__v_prefilter(unsigned char * pixels,int w,int h,int stride_in_bytes,unsigned int kernel_width)3914 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
3915 {
3916 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3917 int safe_h = h - kernel_width;
3918 int j;
3919 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
3920 for (j=0; j < w; ++j) {
3921 int i;
3922 unsigned int total;
3923 STBTT_memset(buffer, 0, kernel_width);
3924
3925 total = 0;
3926
3927 // make kernel_width a constant in common cases so compiler can optimize out the divide
3928 switch (kernel_width) {
3929 case 2:
3930 for (i=0; i <= safe_h; ++i) {
3931 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3932 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3933 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
3934 }
3935 break;
3936 case 3:
3937 for (i=0; i <= safe_h; ++i) {
3938 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3939 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3940 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
3941 }
3942 break;
3943 case 4:
3944 for (i=0; i <= safe_h; ++i) {
3945 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3946 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3947 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
3948 }
3949 break;
3950 case 5:
3951 for (i=0; i <= safe_h; ++i) {
3952 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3953 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3954 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
3955 }
3956 break;
3957 default:
3958 for (i=0; i <= safe_h; ++i) {
3959 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3960 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3961 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
3962 }
3963 break;
3964 }
3965
3966 for (; i < h; ++i) {
3967 STBTT_assert(pixels[i*stride_in_bytes] == 0);
3968 total -= buffer[i & STBTT__OVER_MASK];
3969 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
3970 }
3971
3972 pixels += 1;
3973 }
3974 }
3975
stbtt__oversample_shift(int oversample)3976 static float stbtt__oversample_shift(int oversample)
3977 {
3978 if (!oversample)
3979 return 0.0f;
3980
3981 // The prefilter is a box filter of width "oversample",
3982 // which shifts phase by (oversample - 1)/2 pixels in
3983 // oversampled space. We want to shift in the opposite
3984 // direction to counter this.
3985 return (float)-(oversample - 1) / (2.0f * (float)oversample);
3986 }
3987
3988 // rects array must be big enough to accommodate all characters in the given ranges
stbtt_PackFontRangesGatherRects(stbtt_pack_context * spc,const stbtt_fontinfo * info,stbtt_pack_range * ranges,int num_ranges,stbrp_rect * rects)3989 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
3990 {
3991 int i,j,k;
3992
3993 k=0;
3994 for (i=0; i < num_ranges; ++i) {
3995 float fh = ranges[i].font_size;
3996 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
3997 ranges[i].h_oversample = (unsigned char) spc->h_oversample;
3998 ranges[i].v_oversample = (unsigned char) spc->v_oversample;
3999 for (j=0; j < ranges[i].num_chars; ++j) {
4000 int x0,y0,x1,y1;
4001 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4002 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4003 if (glyph == 0 && spc->skip_missing) {
4004 rects[k].w = rects[k].h = 0;
4005 } else {
4006 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
4007 scale * spc->h_oversample,
4008 scale * spc->v_oversample,
4009 0,0,
4010 &x0,&y0,&x1,&y1);
4011 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
4012 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
4013 }
4014 ++k;
4015 }
4016 }
4017
4018 return k;
4019 }
4020
stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo * info,unsigned char * output,int out_w,int out_h,int out_stride,float scale_x,float scale_y,float shift_x,float shift_y,int prefilter_x,int prefilter_y,float * sub_x,float * sub_y,int glyph)4021 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
4022 {
4023 stbtt_MakeGlyphBitmapSubpixel(info,
4024 output,
4025 out_w - (prefilter_x - 1),
4026 out_h - (prefilter_y - 1),
4027 out_stride,
4028 scale_x,
4029 scale_y,
4030 shift_x,
4031 shift_y,
4032 glyph);
4033
4034 if (prefilter_x > 1)
4035 stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
4036
4037 if (prefilter_y > 1)
4038 stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
4039
4040 *sub_x = stbtt__oversample_shift(prefilter_x);
4041 *sub_y = stbtt__oversample_shift(prefilter_y);
4042 }
4043
4044 // rects array must be big enough to accommodate all characters in the given ranges
stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context * spc,const stbtt_fontinfo * info,stbtt_pack_range * ranges,int num_ranges,stbrp_rect * rects)4045 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
4046 {
4047 int i,j,k, return_value = 1;
4048
4049 // save current values
4050 int old_h_over = spc->h_oversample;
4051 int old_v_over = spc->v_oversample;
4052
4053 k = 0;
4054 for (i=0; i < num_ranges; ++i) {
4055 float fh = ranges[i].font_size;
4056 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4057 float recip_h,recip_v,sub_x,sub_y;
4058 spc->h_oversample = ranges[i].h_oversample;
4059 spc->v_oversample = ranges[i].v_oversample;
4060 recip_h = 1.0f / spc->h_oversample;
4061 recip_v = 1.0f / spc->v_oversample;
4062 sub_x = stbtt__oversample_shift(spc->h_oversample);
4063 sub_y = stbtt__oversample_shift(spc->v_oversample);
4064 for (j=0; j < ranges[i].num_chars; ++j) {
4065 stbrp_rect *r = &rects[k];
4066 if (r->was_packed && r->w != 0 && r->h != 0) {
4067 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
4068 int advance, lsb, x0,y0,x1,y1;
4069 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4070 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4071 stbrp_coord pad = (stbrp_coord) spc->padding;
4072
4073 // pad on left and top
4074 r->x += pad;
4075 r->y += pad;
4076 r->w -= pad;
4077 r->h -= pad;
4078 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
4079 stbtt_GetGlyphBitmapBox(info, glyph,
4080 scale * spc->h_oversample,
4081 scale * spc->v_oversample,
4082 &x0,&y0,&x1,&y1);
4083 stbtt_MakeGlyphBitmapSubpixel(info,
4084 spc->pixels + r->x + r->y*spc->stride_in_bytes,
4085 r->w - spc->h_oversample+1,
4086 r->h - spc->v_oversample+1,
4087 spc->stride_in_bytes,
4088 scale * spc->h_oversample,
4089 scale * spc->v_oversample,
4090 0,0,
4091 glyph);
4092
4093 if (spc->h_oversample > 1)
4094 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4095 r->w, r->h, spc->stride_in_bytes,
4096 spc->h_oversample);
4097
4098 if (spc->v_oversample > 1)
4099 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4100 r->w, r->h, spc->stride_in_bytes,
4101 spc->v_oversample);
4102
4103 bc->x0 = (stbtt_int16) r->x;
4104 bc->y0 = (stbtt_int16) r->y;
4105 bc->x1 = (stbtt_int16) (r->x + r->w);
4106 bc->y1 = (stbtt_int16) (r->y + r->h);
4107 bc->xadvance = scale * advance;
4108 bc->xoff = (float) x0 * recip_h + sub_x;
4109 bc->yoff = (float) y0 * recip_v + sub_y;
4110 bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
4111 bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
4112 } else {
4113 return_value = 0; // if any fail, report failure
4114 }
4115
4116 ++k;
4117 }
4118 }
4119
4120 // restore original values
4121 spc->h_oversample = old_h_over;
4122 spc->v_oversample = old_v_over;
4123
4124 return return_value;
4125 }
4126
stbtt_PackFontRangesPackRects(stbtt_pack_context * spc,stbrp_rect * rects,int num_rects)4127 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
4128 {
4129 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
4130 }
4131
stbtt_PackFontRanges(stbtt_pack_context * spc,const unsigned char * fontdata,int font_index,stbtt_pack_range * ranges,int num_ranges)4132 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
4133 {
4134 stbtt_fontinfo info;
4135 int i,j,n, return_value = 1;
4136 //stbrp_context *context = (stbrp_context *) spc->pack_info;
4137 stbrp_rect *rects;
4138
4139 // flag all characters as NOT packed
4140 for (i=0; i < num_ranges; ++i)
4141 for (j=0; j < ranges[i].num_chars; ++j)
4142 ranges[i].chardata_for_range[j].x0 =
4143 ranges[i].chardata_for_range[j].y0 =
4144 ranges[i].chardata_for_range[j].x1 =
4145 ranges[i].chardata_for_range[j].y1 = 0;
4146
4147 n = 0;
4148 for (i=0; i < num_ranges; ++i)
4149 n += ranges[i].num_chars;
4150
4151 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
4152 if (rects == NULL)
4153 return 0;
4154
4155 info.userdata = spc->user_allocator_context;
4156 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
4157
4158 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
4159
4160 stbtt_PackFontRangesPackRects(spc, rects, n);
4161
4162 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
4163
4164 STBTT_free(rects, spc->user_allocator_context);
4165 return return_value;
4166 }
4167
stbtt_PackFontRange(stbtt_pack_context * spc,const unsigned char * fontdata,int font_index,float font_size,int first_unicode_codepoint_in_range,int num_chars_in_range,stbtt_packedchar * chardata_for_range)4168 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
4169 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
4170 {
4171 stbtt_pack_range range;
4172 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
4173 range.array_of_unicode_codepoints = NULL;
4174 range.num_chars = num_chars_in_range;
4175 range.chardata_for_range = chardata_for_range;
4176 range.font_size = font_size;
4177 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
4178 }
4179
stbtt_GetScaledFontVMetrics(const unsigned char * fontdata,int index,float size,float * ascent,float * descent,float * lineGap)4180 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
4181 {
4182 int i_ascent, i_descent, i_lineGap;
4183 float scale;
4184 stbtt_fontinfo info;
4185 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
4186 scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
4187 stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
4188 *ascent = (float) i_ascent * scale;
4189 *descent = (float) i_descent * scale;
4190 *lineGap = (float) i_lineGap * scale;
4191 }
4192
stbtt_GetPackedQuad(const stbtt_packedchar * chardata,int pw,int ph,int char_index,float * xpos,float * ypos,stbtt_aligned_quad * q,int align_to_integer)4193 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
4194 {
4195 float ipw = 1.0f / pw, iph = 1.0f / ph;
4196 const stbtt_packedchar *b = chardata + char_index;
4197
4198 if (align_to_integer) {
4199 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
4200 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
4201 q->x0 = x;
4202 q->y0 = y;
4203 q->x1 = x + b->xoff2 - b->xoff;
4204 q->y1 = y + b->yoff2 - b->yoff;
4205 } else {
4206 q->x0 = *xpos + b->xoff;
4207 q->y0 = *ypos + b->yoff;
4208 q->x1 = *xpos + b->xoff2;
4209 q->y1 = *ypos + b->yoff2;
4210 }
4211
4212 q->s0 = b->x0 * ipw;
4213 q->t0 = b->y0 * iph;
4214 q->s1 = b->x1 * ipw;
4215 q->t1 = b->y1 * iph;
4216
4217 *xpos += b->xadvance;
4218 }
4219
4220 //////////////////////////////////////////////////////////////////////////////
4221 //
4222 // sdf computation
4223 //
4224
4225 #define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
4226 #define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
4227
stbtt__ray_intersect_bezier(float orig[2],float ray[2],float q0[2],float q1[2],float q2[2],float hits[2][2])4228 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
4229 {
4230 float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
4231 float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
4232 float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
4233 float roperp = orig[1]*ray[0] - orig[0]*ray[1];
4234
4235 float a = q0perp - 2*q1perp + q2perp;
4236 float b = q1perp - q0perp;
4237 float c = q0perp - roperp;
4238
4239 float s0 = 0., s1 = 0.;
4240 int num_s = 0;
4241
4242 if (a != 0.0) {
4243 float discr = b*b - a*c;
4244 if (discr > 0.0) {
4245 float rcpna = -1 / a;
4246 float d = (float) STBTT_sqrt(discr);
4247 s0 = (b+d) * rcpna;
4248 s1 = (b-d) * rcpna;
4249 if (s0 >= 0.0 && s0 <= 1.0)
4250 num_s = 1;
4251 if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
4252 if (num_s == 0) s0 = s1;
4253 ++num_s;
4254 }
4255 }
4256 } else {
4257 // 2*b*s + c = 0
4258 // s = -c / (2*b)
4259 s0 = c / (-2 * b);
4260 if (s0 >= 0.0 && s0 <= 1.0)
4261 num_s = 1;
4262 }
4263
4264 if (num_s == 0)
4265 return 0;
4266 else {
4267 float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
4268 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
4269
4270 float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
4271 float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
4272 float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
4273 float rod = orig[0]*rayn_x + orig[1]*rayn_y;
4274
4275 float q10d = q1d - q0d;
4276 float q20d = q2d - q0d;
4277 float q0rd = q0d - rod;
4278
4279 hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
4280 hits[0][1] = a*s0+b;
4281
4282 if (num_s > 1) {
4283 hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
4284 hits[1][1] = a*s1+b;
4285 return 2;
4286 } else {
4287 return 1;
4288 }
4289 }
4290 }
4291
equal(float * a,float * b)4292 static int equal(float *a, float *b)
4293 {
4294 return (a[0] == b[0] && a[1] == b[1]);
4295 }
4296
stbtt__compute_crossings_x(float x,float y,int nverts,stbtt_vertex * verts)4297 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
4298 {
4299 int i;
4300 float orig[2], ray[2] = { 1, 0 };
4301 float y_frac;
4302 int winding = 0;
4303
4304 orig[0] = x;
4305 //orig[1] = y; // [DEAR IMGUI] commmented double assignment
4306
4307 // make sure y never passes through a vertex of the shape
4308 y_frac = (float) STBTT_fmod(y, 1.0f);
4309 if (y_frac < 0.01f)
4310 y += 0.01f;
4311 else if (y_frac > 0.99f)
4312 y -= 0.01f;
4313 orig[1] = y;
4314
4315 // test a ray from (-infinity,y) to (x,y)
4316 for (i=0; i < nverts; ++i) {
4317 if (verts[i].type == STBTT_vline) {
4318 int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
4319 int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
4320 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4321 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4322 if (x_inter < x)
4323 winding += (y0 < y1) ? 1 : -1;
4324 }
4325 }
4326 if (verts[i].type == STBTT_vcurve) {
4327 int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
4328 int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
4329 int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
4330 int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
4331 int by = STBTT_max(y0,STBTT_max(y1,y2));
4332 if (y > ay && y < by && x > ax) {
4333 float q0[2],q1[2],q2[2];
4334 float hits[2][2];
4335 q0[0] = (float)x0;
4336 q0[1] = (float)y0;
4337 q1[0] = (float)x1;
4338 q1[1] = (float)y1;
4339 q2[0] = (float)x2;
4340 q2[1] = (float)y2;
4341 if (equal(q0,q1) || equal(q1,q2)) {
4342 x0 = (int)verts[i-1].x;
4343 y0 = (int)verts[i-1].y;
4344 x1 = (int)verts[i ].x;
4345 y1 = (int)verts[i ].y;
4346 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4347 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4348 if (x_inter < x)
4349 winding += (y0 < y1) ? 1 : -1;
4350 }
4351 } else {
4352 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
4353 if (num_hits >= 1)
4354 if (hits[0][0] < 0)
4355 winding += (hits[0][1] < 0 ? -1 : 1);
4356 if (num_hits >= 2)
4357 if (hits[1][0] < 0)
4358 winding += (hits[1][1] < 0 ? -1 : 1);
4359 }
4360 }
4361 }
4362 }
4363 return winding;
4364 }
4365
stbtt__cuberoot(float x)4366 static float stbtt__cuberoot( float x )
4367 {
4368 if (x<0)
4369 return -(float) STBTT_pow(-x,1.0f/3.0f);
4370 else
4371 return (float) STBTT_pow( x,1.0f/3.0f);
4372 }
4373
4374 // x^3 + c*x^2 + b*x + a = 0
stbtt__solve_cubic(float a,float b,float c,float * r)4375 static int stbtt__solve_cubic(float a, float b, float c, float* r)
4376 {
4377 float s = -a / 3;
4378 float p = b - a*a / 3;
4379 float q = a * (2*a*a - 9*b) / 27 + c;
4380 float p3 = p*p*p;
4381 float d = q*q + 4*p3 / 27;
4382 if (d >= 0) {
4383 float z = (float) STBTT_sqrt(d);
4384 float u = (-q + z) / 2;
4385 float v = (-q - z) / 2;
4386 u = stbtt__cuberoot(u);
4387 v = stbtt__cuberoot(v);
4388 r[0] = s + u + v;
4389 return 1;
4390 } else {
4391 float u = (float) STBTT_sqrt(-p/3);
4392 float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4393 float m = (float) STBTT_cos(v);
4394 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4395 r[0] = s + u * 2 * m;
4396 r[1] = s - u * (m + n);
4397 r[2] = s - u * (m - n);
4398
4399 //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
4400 //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
4401 //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
4402 return 3;
4403 }
4404 }
4405
stbtt_GetGlyphSDF(const stbtt_fontinfo * info,float scale,int glyph,int padding,unsigned char onedge_value,float pixel_dist_scale,int * width,int * height,int * xoff,int * yoff)4406 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
4407 {
4408 float scale_x = scale, scale_y = scale;
4409 int ix0,iy0,ix1,iy1;
4410 int w,h;
4411 unsigned char *data;
4412
4413 // if one scale is 0, use same scale for both
4414 if (scale_x == 0) scale_x = scale_y;
4415 if (scale_y == 0) {
4416 if (scale_x == 0) return NULL; // if both scales are 0, return NULL
4417 scale_y = scale_x;
4418 }
4419
4420 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
4421
4422 // if empty, return NULL
4423 if (ix0 == ix1 || iy0 == iy1)
4424 return NULL;
4425
4426 ix0 -= padding;
4427 iy0 -= padding;
4428 ix1 += padding;
4429 iy1 += padding;
4430
4431 w = (ix1 - ix0);
4432 h = (iy1 - iy0);
4433
4434 if (width ) *width = w;
4435 if (height) *height = h;
4436 if (xoff ) *xoff = ix0;
4437 if (yoff ) *yoff = iy0;
4438
4439 // invert for y-downwards bitmaps
4440 scale_y = -scale_y;
4441
4442 {
4443 int x,y,i,j;
4444 float *precompute;
4445 stbtt_vertex *verts;
4446 int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
4447 data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
4448 precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
4449
4450 for (i=0,j=num_verts-1; i < num_verts; j=i++) {
4451 if (verts[i].type == STBTT_vline) {
4452 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4453 float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
4454 float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
4455 precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
4456 } else if (verts[i].type == STBTT_vcurve) {
4457 float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
4458 float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
4459 float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
4460 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4461 float len2 = bx*bx + by*by;
4462 if (len2 != 0.0f)
4463 precompute[i] = 1.0f / (bx*bx + by*by);
4464 else
4465 precompute[i] = 0.0f;
4466 } else
4467 precompute[i] = 0.0f;
4468 }
4469
4470 for (y=iy0; y < iy1; ++y) {
4471 for (x=ix0; x < ix1; ++x) {
4472 float val;
4473 float min_dist = 999999.0f;
4474 float sx = (float) x + 0.5f;
4475 float sy = (float) y + 0.5f;
4476 float x_gspace = (sx / scale_x);
4477 float y_gspace = (sy / scale_y);
4478
4479 int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
4480
4481 for (i=0; i < num_verts; ++i) {
4482 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4483
4484 // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
4485 float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4486 if (dist2 < min_dist*min_dist)
4487 min_dist = (float) STBTT_sqrt(dist2);
4488
4489 if (verts[i].type == STBTT_vline) {
4490 float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
4491
4492 // coarse culling against bbox
4493 //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
4494 // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
4495 float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4496 STBTT_assert(i != 0);
4497 if (dist < min_dist) {
4498 // check position along line
4499 // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
4500 // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
4501 float dx = x1-x0, dy = y1-y0;
4502 float px = x0-sx, py = y0-sy;
4503 // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
4504 // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
4505 float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
4506 if (t >= 0.0f && t <= 1.0f)
4507 min_dist = dist;
4508 }
4509 } else if (verts[i].type == STBTT_vcurve) {
4510 float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
4511 float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
4512 float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
4513 float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
4514 float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
4515 float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
4516 // coarse culling against bbox to avoid computing cubic unnecessarily
4517 if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
4518 int num=0;
4519 float ax = x1-x0, ay = y1-y0;
4520 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4521 float mx = x0 - sx, my = y0 - sy;
4522 float res[3],px,py,t,it;
4523 float a_inv = precompute[i];
4524 if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
4525 float a = 3*(ax*bx + ay*by);
4526 float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
4527 float c = mx*ax+my*ay;
4528 if (a == 0.0) { // if a is 0, it's linear
4529 if (b != 0.0) {
4530 res[num++] = -c/b;
4531 }
4532 } else {
4533 float discriminant = b*b - 4*a*c;
4534 if (discriminant < 0)
4535 num = 0;
4536 else {
4537 float root = (float) STBTT_sqrt(discriminant);
4538 res[0] = (-b - root)/(2*a);
4539 res[1] = (-b + root)/(2*a);
4540 num = 2; // don't bother distinguishing 1-solution case, as code below will still work
4541 }
4542 }
4543 } else {
4544 float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
4545 float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
4546 float d = (mx*ax+my*ay) * a_inv;
4547 num = stbtt__solve_cubic(b, c, d, res);
4548 }
4549 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4550 t = res[0], it = 1.0f - t;
4551 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4552 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4553 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4554 if (dist2 < min_dist * min_dist)
4555 min_dist = (float) STBTT_sqrt(dist2);
4556 }
4557 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
4558 t = res[1], it = 1.0f - t;
4559 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4560 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4561 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4562 if (dist2 < min_dist * min_dist)
4563 min_dist = (float) STBTT_sqrt(dist2);
4564 }
4565 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
4566 t = res[2], it = 1.0f - t;
4567 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4568 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4569 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4570 if (dist2 < min_dist * min_dist)
4571 min_dist = (float) STBTT_sqrt(dist2);
4572 }
4573 }
4574 }
4575 }
4576 if (winding == 0)
4577 min_dist = -min_dist; // if outside the shape, value is negative
4578 val = onedge_value + pixel_dist_scale * min_dist;
4579 if (val < 0)
4580 val = 0;
4581 else if (val > 255)
4582 val = 255;
4583 data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
4584 }
4585 }
4586 STBTT_free(precompute, info->userdata);
4587 STBTT_free(verts, info->userdata);
4588 }
4589 return data;
4590 }
4591
stbtt_GetCodepointSDF(const stbtt_fontinfo * info,float scale,int codepoint,int padding,unsigned char onedge_value,float pixel_dist_scale,int * width,int * height,int * xoff,int * yoff)4592 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
4593 {
4594 return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
4595 }
4596
stbtt_FreeSDF(unsigned char * bitmap,void * userdata)4597 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
4598 {
4599 STBTT_free(bitmap, userdata);
4600 }
4601
4602 //////////////////////////////////////////////////////////////////////////////
4603 //
4604 // font name matching -- recommended not to use this
4605 //
4606
4607 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 * s1,stbtt_int32 len1,stbtt_uint8 * s2,stbtt_int32 len2)4608 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
4609 {
4610 stbtt_int32 i=0;
4611
4612 // convert utf16 to utf8 and compare the results while converting
4613 while (len2) {
4614 stbtt_uint16 ch = s2[0]*256 + s2[1];
4615 if (ch < 0x80) {
4616 if (i >= len1) return -1;
4617 if (s1[i++] != ch) return -1;
4618 } else if (ch < 0x800) {
4619 if (i+1 >= len1) return -1;
4620 if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
4621 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
4622 } else if (ch >= 0xd800 && ch < 0xdc00) {
4623 stbtt_uint32 c;
4624 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
4625 if (i+3 >= len1) return -1;
4626 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
4627 if (s1[i++] != 0xf0 + (c >> 18)) return -1;
4628 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
4629 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
4630 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
4631 s2 += 2; // plus another 2 below
4632 len2 -= 2;
4633 } else if (ch >= 0xdc00 && ch < 0xe000) {
4634 return -1;
4635 } else {
4636 if (i+2 >= len1) return -1;
4637 if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
4638 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
4639 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
4640 }
4641 s2 += 2;
4642 len2 -= 2;
4643 }
4644 return i;
4645 }
4646
stbtt_CompareUTF8toUTF16_bigendian_internal(char * s1,int len1,char * s2,int len2)4647 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
4648 {
4649 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
4650 }
4651
4652 // returns results in whatever encoding you request... but note that 2-byte encodings
4653 // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
stbtt_GetFontNameString(const stbtt_fontinfo * font,int * length,int platformID,int encodingID,int languageID,int nameID)4654 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
4655 {
4656 stbtt_int32 i,count,stringOffset;
4657 stbtt_uint8 *fc = font->data;
4658 stbtt_uint32 offset = font->fontstart;
4659 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
4660 if (!nm) return NULL;
4661
4662 count = ttUSHORT(fc+nm+2);
4663 stringOffset = nm + ttUSHORT(fc+nm+4);
4664 for (i=0; i < count; ++i) {
4665 stbtt_uint32 loc = nm + 6 + 12 * i;
4666 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
4667 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
4668 *length = ttUSHORT(fc+loc+8);
4669 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
4670 }
4671 }
4672 return NULL;
4673 }
4674
stbtt__matchpair(stbtt_uint8 * fc,stbtt_uint32 nm,stbtt_uint8 * name,stbtt_int32 nlen,stbtt_int32 target_id,stbtt_int32 next_id)4675 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
4676 {
4677 stbtt_int32 i;
4678 stbtt_int32 count = ttUSHORT(fc+nm+2);
4679 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
4680
4681 for (i=0; i < count; ++i) {
4682 stbtt_uint32 loc = nm + 6 + 12 * i;
4683 stbtt_int32 id = ttUSHORT(fc+loc+6);
4684 if (id == target_id) {
4685 // find the encoding
4686 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
4687
4688 // is this a Unicode encoding?
4689 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
4690 stbtt_int32 slen = ttUSHORT(fc+loc+8);
4691 stbtt_int32 off = ttUSHORT(fc+loc+10);
4692
4693 // check if there's a prefix match
4694 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
4695 if (matchlen >= 0) {
4696 // check for target_id+1 immediately following, with same encoding & language
4697 if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
4698 slen = ttUSHORT(fc+loc+12+8);
4699 off = ttUSHORT(fc+loc+12+10);
4700 if (slen == 0) {
4701 if (matchlen == nlen)
4702 return 1;
4703 } else if (matchlen < nlen && name[matchlen] == ' ') {
4704 ++matchlen;
4705 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
4706 return 1;
4707 }
4708 } else {
4709 // if nothing immediately following
4710 if (matchlen == nlen)
4711 return 1;
4712 }
4713 }
4714 }
4715
4716 // @TODO handle other encodings
4717 }
4718 }
4719 return 0;
4720 }
4721
stbtt__matches(stbtt_uint8 * fc,stbtt_uint32 offset,stbtt_uint8 * name,stbtt_int32 flags)4722 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
4723 {
4724 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
4725 stbtt_uint32 nm,hd;
4726 if (!stbtt__isfont(fc+offset)) return 0;
4727
4728 // check italics/bold/underline flags in macStyle...
4729 if (flags) {
4730 hd = stbtt__find_table(fc, offset, "head");
4731 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
4732 }
4733
4734 nm = stbtt__find_table(fc, offset, "name");
4735 if (!nm) return 0;
4736
4737 if (flags) {
4738 // if we checked the macStyle flags, then just check the family and ignore the subfamily
4739 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
4740 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
4741 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4742 } else {
4743 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
4744 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
4745 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4746 }
4747
4748 return 0;
4749 }
4750
stbtt_FindMatchingFont_internal(unsigned char * font_collection,char * name_utf8,stbtt_int32 flags)4751 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
4752 {
4753 stbtt_int32 i;
4754 for (i=0;;++i) {
4755 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
4756 if (off < 0) return off;
4757 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
4758 return off;
4759 }
4760 }
4761
4762 #if defined(__GNUC__) || defined(__clang__)
4763 #pragma GCC diagnostic push
4764 #pragma GCC diagnostic ignored "-Wcast-qual"
4765 #endif
4766
stbtt_BakeFontBitmap(const unsigned char * data,int offset,float pixel_height,unsigned char * pixels,int pw,int ph,int first_char,int num_chars,stbtt_bakedchar * chardata)4767 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
4768 float pixel_height, unsigned char *pixels, int pw, int ph,
4769 int first_char, int num_chars, stbtt_bakedchar *chardata)
4770 {
4771 return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
4772 }
4773
stbtt_GetFontOffsetForIndex(const unsigned char * data,int index)4774 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
4775 {
4776 return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
4777 }
4778
stbtt_GetNumberOfFonts(const unsigned char * data)4779 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
4780 {
4781 return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
4782 }
4783
stbtt_InitFont(stbtt_fontinfo * info,const unsigned char * data,int offset)4784 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
4785 {
4786 return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
4787 }
4788
stbtt_FindMatchingFont(const unsigned char * fontdata,const char * name,int flags)4789 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
4790 {
4791 return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
4792 }
4793
stbtt_CompareUTF8toUTF16_bigendian(const char * s1,int len1,const char * s2,int len2)4794 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
4795 {
4796 return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
4797 }
4798
4799 #if defined(__GNUC__) || defined(__clang__)
4800 #pragma GCC diagnostic pop
4801 #endif
4802
4803 #endif // STB_TRUETYPE_IMPLEMENTATION
4804
4805
4806 // FULL VERSION HISTORY
4807 //
4808 // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
4809 // 1.18 (2018-01-29) add missing function
4810 // 1.17 (2017-07-23) make more arguments const; doc fix
4811 // 1.16 (2017-07-12) SDF support
4812 // 1.15 (2017-03-03) make more arguments const
4813 // 1.14 (2017-01-16) num-fonts-in-TTC function
4814 // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
4815 // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
4816 // 1.11 (2016-04-02) fix unused-variable warning
4817 // 1.10 (2016-04-02) allow user-defined fabs() replacement
4818 // fix memory leak if fontsize=0.0
4819 // fix warning from duplicate typedef
4820 // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
4821 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
4822 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
4823 // allow PackFontRanges to pack and render in separate phases;
4824 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
4825 // fixed an assert() bug in the new rasterizer
4826 // replace assert() with STBTT_assert() in new rasterizer
4827 // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
4828 // also more precise AA rasterizer, except if shapes overlap
4829 // remove need for STBTT_sort
4830 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
4831 // 1.04 (2015-04-15) typo in example
4832 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
4833 // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
4834 // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
4835 // non-oversampled; STBTT_POINT_SIZE for packed case only
4836 // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
4837 // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
4838 // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
4839 // 0.8b (2014-07-07) fix a warning
4840 // 0.8 (2014-05-25) fix a few more warnings
4841 // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
4842 // 0.6c (2012-07-24) improve documentation
4843 // 0.6b (2012-07-20) fix a few more warnings
4844 // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
4845 // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
4846 // 0.5 (2011-12-09) bugfixes:
4847 // subpixel glyph renderer computed wrong bounding box
4848 // first vertex of shape can be off-curve (FreeSans)
4849 // 0.4b (2011-12-03) fixed an error in the font baking example
4850 // 0.4 (2011-12-01) kerning, subpixel rendering (tor)
4851 // bugfixes for:
4852 // codepoint-to-glyph conversion using table fmt=12
4853 // codepoint-to-glyph conversion using table fmt=4
4854 // stbtt_GetBakedQuad with non-square texture (Zer)
4855 // updated Hello World! sample to use kerning and subpixel
4856 // fixed some warnings
4857 // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
4858 // userdata, malloc-from-userdata, non-zero fill (stb)
4859 // 0.2 (2009-03-11) Fix unsigned/signed char warnings
4860 // 0.1 (2009-03-09) First public release
4861 //
4862
4863 /*
4864 ------------------------------------------------------------------------------
4865 This software is available under 2 licenses -- choose whichever you prefer.
4866 ------------------------------------------------------------------------------
4867 ALTERNATIVE A - MIT License
4868 Copyright (c) 2017 Sean Barrett
4869 Permission is hereby granted, free of charge, to any person obtaining a copy of
4870 this software and associated documentation files (the "Software"), to deal in
4871 the Software without restriction, including without limitation the rights to
4872 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
4873 of the Software, and to permit persons to whom the Software is furnished to do
4874 so, subject to the following conditions:
4875 The above copyright notice and this permission notice shall be included in all
4876 copies or substantial portions of the Software.
4877 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4878 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4879 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4880 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4881 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4882 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4883 SOFTWARE.
4884 ------------------------------------------------------------------------------
4885 ALTERNATIVE B - Public Domain (www.unlicense.org)
4886 This is free and unencumbered software released into the public domain.
4887 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
4888 software, either in source code form or as a compiled binary, for any purpose,
4889 commercial or non-commercial, and by any means.
4890 In jurisdictions that recognize copyright laws, the author or authors of this
4891 software dedicate any and all copyright interest in the software to the public
4892 domain. We make this dedication for the benefit of the public at large and to
4893 the detriment of our heirs and successors. We intend this dedication to be an
4894 overt act of relinquishment in perpetuity of all present and future rights to
4895 this software under copyright law.
4896 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4897 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4898 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4899 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
4900 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4901 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4902 ------------------------------------------------------------------------------
4903 */
4904