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