gosu 0.13.2 → 0.13.3

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gosu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.13.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Raschke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-16 00:00:00.000000000 Z
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  2D game development library.
@@ -136,9 +136,7 @@ files:
136
136
  - src/WindowUIKit.cpp
137
137
  - src/stb_image.h
138
138
  - src/stb_image_write.h
139
- - src/stb_truetype.h
140
139
  - src/stb_vorbis.c
141
- - src/utf8proc.h
142
140
  homepage: https://www.libgosu.org/
143
141
  licenses:
144
142
  - MIT
@@ -1,4566 +0,0 @@
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
- */