gosu 0.13.1 → 0.13.2

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