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