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