aboutsummaryrefslogtreecommitdiff
path: root/dep/recastnavigation/recastnavigation.diff
diff options
context:
space:
mode:
Diffstat (limited to 'dep/recastnavigation/recastnavigation.diff')
-rw-r--r--dep/recastnavigation/recastnavigation.diff3676
1 files changed, 29 insertions, 3647 deletions
diff --git a/dep/recastnavigation/recastnavigation.diff b/dep/recastnavigation/recastnavigation.diff
index 68e976c955e..42bab6474e3 100644
--- a/dep/recastnavigation/recastnavigation.diff
+++ b/dep/recastnavigation/recastnavigation.diff
@@ -1,25 +1,21 @@
- Detour/Include/DetourNavMesh.h | 76 +-
- Detour/Include/DetourNavMeshQuery.h | 0
- Detour/Include/DetourNode.h | 0
- Detour/Source/DetourCommon.cpp | 4 +-
- Detour/Source/DetourNavMesh.cpp | 32 +-
- Detour/Source/DetourNavMeshBuilder.cpp | 6 +-
- Detour/Source/DetourNavMeshQuery.cpp | 9 +-
- Detour/Source/DetourNode.cpp | 29 +-
- DetourCrowd/Include/DetourObstacleAvoidance.h | 0
- DetourCrowd/Source/DetourObstacleAvoidance.cpp | 6 +-
- Recast/Include/Recast.h | 8 +-
- Recast/Source/RecastContour.cpp | 0
- Recast/Source/RecastLayers.cpp | 0
- Recast/Source/RecastMesh.cpp | 0
- Recast/Source/RecastMeshDetail.cpp | 0
- Recast/Source/RecastRegion.cpp | 0
- RecastDemo/Contrib/stb_truetype.h | 3612 ++++++++++++------------
- RecastDemo/Include/NavMeshPruneTool.h | 0
- 18 files changed, 1865 insertions(+), 1917 deletions(-)
+From b84e9ffbd1d1e1fb2f5d78cc53d2bb7b56c3fce3 Mon Sep 17 00:00:00 2001
+From: jackpoz <giacomopoz@gmail.com>
+Date: Fri, 20 Jun 2014 23:15:04 +0200
+Subject: [PATCH] Add custom trinitycore changes
+
+---
+ Detour/Include/DetourNavMesh.h | 76 ++++++++------------------
+ Detour/Source/DetourCommon.cpp | 4 +-
+ Detour/Source/DetourNavMesh.cpp | 32 ++++-------
+ Detour/Source/DetourNavMeshBuilder.cpp | 6 +-
+ Detour/Source/DetourNavMeshQuery.cpp | 9 +--
+ Detour/Source/DetourNode.cpp | 29 +++-------
+ DetourCrowd/Source/DetourObstacleAvoidance.cpp | 6 +-
+ Recast/Include/Recast.h | 8 +--
+ 8 files changed, 59 insertions(+), 111 deletions(-)
diff --git a/Detour/Include/DetourNavMesh.h b/Detour/Include/DetourNavMesh.h
-index 95a63e4..cdd473f 100644
+index 1060845..782ddbc 100644
--- a/Detour/Include/DetourNavMesh.h
+++ b/Detour/Include/DetourNavMesh.h
@@ -22,39 +22,35 @@
@@ -93,7 +89,7 @@ index 95a63e4..cdd473f 100644
/// Tile flags used for various functions and fields.
/// For an example, see dtNavMesh::addTile().
enum dtTileFlags
-@@ -492,11 +494,7 @@ public:
+@@ -511,11 +513,7 @@ public:
/// @param[in] ip The index of the polygon within the tile.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{
@@ -105,7 +101,7 @@ index 95a63e4..cdd473f 100644
}
/// Decodes a standard polygon reference.
-@@ -508,21 +506,12 @@ public:
+@@ -527,21 +525,12 @@ public:
/// @see #encodePolyId
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{
@@ -127,7 +123,7 @@ index 95a63e4..cdd473f 100644
}
/// Extracts a tile's salt value from the specified polygon reference.
-@@ -531,13 +520,8 @@ public:
+@@ -550,13 +539,8 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{
@@ -141,7 +137,7 @@ index 95a63e4..cdd473f 100644
}
/// Extracts the tile's index from the specified polygon reference.
-@@ -546,13 +530,8 @@ public:
+@@ -565,13 +549,8 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{
@@ -155,7 +151,7 @@ index 95a63e4..cdd473f 100644
}
/// Extracts the polygon's index (within its tile) from the specified polygon reference.
-@@ -561,13 +540,8 @@ public:
+@@ -580,13 +559,8 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{
@@ -169,7 +165,7 @@ index 95a63e4..cdd473f 100644
}
/// @}
-@@ -626,11 +600,9 @@ private:
+@@ -645,11 +619,9 @@ private:
dtMeshTile* m_nextFree; ///< Freelist of tiles.
dtMeshTile* m_tiles; ///< List of tiles.
@@ -305,7 +301,7 @@ index 1bf271b..9d8471b 100644
int curNode = 0;
diff --git a/Detour/Source/DetourNavMeshQuery.cpp b/Detour/Source/DetourNavMeshQuery.cpp
-index 2e30464..f1709df 100644
+index 9debb4d..ec3a294 100644
--- a/Detour/Source/DetourNavMeshQuery.cpp
+++ b/Detour/Source/DetourNavMeshQuery.cpp
@@ -16,13 +16,13 @@
@@ -335,7 +331,7 @@ index 2e30464..f1709df 100644
dtNavMeshQuery* dtAllocNavMeshQuery()
-@@ -3305,7 +3306,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
+@@ -3504,7 +3505,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
dtVsub(hitNormal, centerPos, hitPos);
dtVnormalize(hitNormal);
@@ -345,7 +341,7 @@ index 2e30464..f1709df 100644
return status;
}
diff --git a/Detour/Source/DetourNode.cpp b/Detour/Source/DetourNode.cpp
-index 57cb206..4c8215e 100644
+index 5cf6548..1d18977 100644
--- a/Detour/Source/DetourNode.cpp
+++ b/Detour/Source/DetourNode.cpp
@@ -22,30 +22,17 @@
@@ -422,7 +418,7 @@ index 0fad9ef..d3f90b7 100644
// Always add sample at zero
pat[npat*2+0] = 0;
diff --git a/Recast/Include/Recast.h b/Recast/Include/Recast.h
-index 336837e..3f4ae96 100644
+index 83ca606..66974cd 100644
--- a/Recast/Include/Recast.h
+++ b/Recast/Include/Recast.h
@@ -243,7 +243,7 @@ struct rcConfig
@@ -447,3620 +443,6 @@ index 336837e..3f4ae96 100644
rcSpan* next; ///< The next span higher up in column.
};
-diff --git a/RecastDemo/Contrib/stb_truetype.h b/RecastDemo/Contrib/stb_truetype.h
-index fd72578..92dc8c2 100644
---- a/RecastDemo/Contrib/stb_truetype.h
-+++ b/RecastDemo/Contrib/stb_truetype.h
-@@ -1,1806 +1,1806 @@
--// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools
--//
--// This library processes TrueType files:
--// parse files
--// extract glyph metrics
--// extract glyph shapes
--// render glyphs to one-channel bitmaps with antialiasing (box filter)
--//
--// Todo:
--// non-MS cmaps
--// crashproof on bad data
--// hinting
--// subpixel positioning when rendering bitmap
--// cleartype-style AA
--//
--// ADDITIONAL CONTRIBUTORS
--//
--// Mikko Mononen: compound shape support, more cmap formats
--//
--// VERSIONS
--//
--// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
--// userdata, malloc-from-userdata, non-zero fill (STB)
--// 0.2 (2009-03-11) Fix unsigned/signed char warnings
--// 0.1 (2009-03-09) First public release
--//
--// USAGE
--//
--// Include this file in whatever places neeed to refer to it. In ONE C/C++
--// file, write:
--// #define STB_TRUETYPE_IMPLEMENTATION
--// before the #include of this file. This expands out the actual
--// implementation into that C/C++ file.
--//
--// Look at the header-file sections below for the API, but here's a quick skim:
--//
--// Simple 3D API (don't ship this, but it's fine for tools and quick start,
--// and you can cut and paste from it to move to more advanced)
--// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
--// stbtt_GetBakedQuad() -- compute quad to draw for a given char
--//
--// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
--// stbtt_InitFont()
--// stbtt_GetFontOffsetForIndex() -- use for TTC font collections
--//
--// Render a unicode codepoint to a bitmap
--// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
--// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
--// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
--//
--// Character advance/positioning
--// stbtt_GetCodepointHMetrics()
--// stbtt_GetFontVMetrics()
--//
--// NOTES
--//
--// The system uses the raw data found in the .ttf file without changing it
--// and without building auxiliary data structures. This is a bit inefficient
--// on little-endian systems (the data is big-endian), but assuming you're
--// caching the bitmaps or glyph shapes this shouldn't be a big deal.
--//
--// It appears to be very hard to programmatically determine what font a
--// given file is in a general way. I provide an API for this, but I don't
--// recommend it.
--//
--//
--// SOURCE STATISTICS (based on v0.3, 1800 LOC)
--//
--// Documentation & header file 350 LOC \___ 500 LOC documentation
--// Sample code 140 LOC /
--// Truetype parsing 580 LOC ---- 600 LOC TrueType
--// Software rasterization 240 LOC \ .
--// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation
--// Bitmap management 70 LOC /
--// Baked bitmap interface 70 LOC /
--// Font name matching & access 150 LOC ---- 150
--// C runtime library abstraction 60 LOC ---- 60
--
--
--//////////////////////////////////////////////////////////////////////////////
--//////////////////////////////////////////////////////////////////////////////
--////
--//// SAMPLE PROGRAMS
--////
--//
--// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
--//
--#if 0
--#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
--#include "stb_truetype.h"
--
--char ttf_buffer[1<<20];
--unsigned char temp_bitmap[512*512];
--
--stbtt_chardata cdata[96]; // ASCII 32..126 is 95 glyphs
--GLstbtt_uint ftex;
--
--void my_stbtt_initfont(void)
--{
-- fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
-- stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
-- // can free ttf_buffer at this point
-- glGenTextures(1, &ftex);
-- glBindTexture(GL_TEXTURE_2D, ftex);
-- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
-- // can free temp_bitmap at this point
-- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
--}
--
--void my_stbtt_print(float x, float y, char *text)
--{
-- // assume orthographic projection with units = screen pixels, origin at top left
-- glBindTexture(GL_TEXTURE_2D, ftex);
-- glBegin(GL_QUADS);
-- while (*text) {
-- if (*text >= 32 && *text < 128) {
-- stbtt_aligned_quad q;
-- stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d
-- glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
-- glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
-- glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
-- glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
-- }
-- ++text;
-- }
-- glEnd();
--}
--#endif
--//
--//
--//////////////////////////////////////////////////////////////////////////////
--//
--// Complete program (this compiles): get a single bitmap, print as ASCII art
--//
--#if 0
--#include <stdio.h>
--#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
--#include "stb_truetype.h"
--
--char ttf_buffer[1<<25];
--
--int main(int argc, char **argv)
--{
-- stbtt_fontinfo font;
-- unsigned char *bitmap;
-- int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
--
-- fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
--
-- stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
-- bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
--
-- for (j=0; j < h; ++j) {
-- for (i=0; i < w; ++i)
-- putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
-- putchar('\n');
-- }
-- return 0;
--}
--#endif
--//
--// Output:
--//
--// .ii.
--// @@@@@@.
--// V@Mio@@o
--// :i. V@V
--// :oM@@M
--// :@@@MM@M
--// @@o o@M
--// :@@. M@M
--// @@@o@@@@
--// :M@@V:@@.
--//
--//////////////////////////////////////////////////////////////////////////////
--//
--// Complete program: print "Hello World!" banner, with bugs
--//
--#if 0
--int main(int arg, char **argv)
--{
-- unsigned char screen[20][79];
-- int i,j, pos=0;
-- float scale;
-- char *text = "Heljo World!";
--
-- fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
-- stbtt_InitFont(&font, buffer, 0);
--
-- scale = stbtt_ScaleForPixelHeight(&font, 16);
-- memset(screen, 0, sizeof(screen));
--
-- while (*text) {
-- int advance,lsb,x0,y0,x1,y1, newpos, baseline=13;
-- stbtt_GetCodepointHMetrics(&font, *text, &advance, &lsb);
-- stbtt_GetCodepointBitmapBox(&font, *text, scale,scale, &x0,&y0,&x1,&y1);
-- newpos = pos + (int) (lsb * scale) + x0;
-- stbtt_MakeCodepointBitmap(&font, &screen[baseline + y0][newpos], x1-x0,y1-y0, 79, scale,scale, *text);
-- // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
-- // because this API is really for baking character bitmaps into textures
-- pos += (int) (advance * scale);
-- ++text;
-- }
--
-- for (j=0; j < 20; ++j) {
-- for (i=0; i < 79; ++i)
-- putchar(" .:ioVM@"[screen[j][i]>>5]);
-- putchar('\n');
-- }
--
-- return 0;
--}
--#endif
--
--
--//////////////////////////////////////////////////////////////////////////////
--//////////////////////////////////////////////////////////////////////////////
--////
--//// INTEGRATION WITH RUNTIME LIBRARIES
--////
--
--#ifdef STB_TRUETYPE_IMPLEMENTATION
-- // #define your own (u)stbtt_int8/16/32 before including to override this
-- #ifndef stbtt_uint8
-- typedef unsigned char stbtt_uint8;
-- typedef signed char stbtt_int8;
-- typedef unsigned short stbtt_uint16;
-- typedef signed short stbtt_int16;
-- typedef unsigned int stbtt_uint32;
-- typedef signed int stbtt_int32;
-- #endif
--
-- typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
-- typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
--
-- // #define your own STBTT_sort() to override this to avoid qsort
-- #ifndef STBTT_sort
-- #include <stdlib.h>
-- #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
-- #endif
--
-- // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
-- #ifndef STBTT_ifloor
-- #include <math.h>
-- #define STBTT_ifloor(x) ((int) floor(x))
-- #define STBTT_iceil(x) ((int) ceil(x))
-- #endif
--
-- // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
-- #ifndef STBTT_malloc
-- #include <malloc.h>
-- #define STBTT_malloc(x,u) malloc(x)
-- #define STBTT_free(x,u) free(x)
-- #endif
--
-- #ifndef STBTT_assert
-- #include <assert.h>
-- #define STBTT_assert(x) assert(x)
-- #endif
--
-- #ifndef STBTT_strlen
-- #include <string.h>
-- #define STBTT_strlen(x) strlen(x)
-- #endif
--
-- #ifndef STBTT_memcpy
-- #include <memory.h>
-- #define STBTT_memcpy memcpy
-- #define STBTT_memset memset
-- #endif
--#endif
--
--///////////////////////////////////////////////////////////////////////////////
--///////////////////////////////////////////////////////////////////////////////
--////
--//// INTERFACE
--////
--////
--
--#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
--#define __STB_INCLUDE_STB_TRUETYPE_H__
--
--#ifdef __cplusplus
--extern "C" {
--#endif
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// TEXTURE BAKING API
--//
--// If you use this API, you only have to call two functions ever.
--//
--
--typedef struct
--{
-- unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
-- float xoff,yoff,xadvance;
--} stbtt_bakedchar;
--
--extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
-- float pixel_height, // height of font in pixels
-- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
-- int first_char, int num_chars, // characters to bake
-- stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
--// if return is positive, the first unused row of the bitmap
--// if return is negative, returns the negative of the number of characters that fit
--// if return is 0, no characters fit and no rows were used
--// This uses a very crappy packing.
--
--typedef struct
--{
-- float x0,y0,s0,t0; // top-left
-- float x1,y1,s1,t1; // bottom-right
--} stbtt_aligned_quad;
--
--extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above
-- int char_index, // character to display
-- float *xpos, float *ypos, // pointers to current position in screen pixel space
-- stbtt_aligned_quad *q, // output: quad to draw
-- int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
--// Call GetBakedQuad with char_index = 'character - first_char', and it
--// creates the quad you need to draw and advances the current position.
--// It's inefficient; you might want to c&p it and optimize it.
--
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// FONT LOADING
--//
--//
--
--extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
--// Each .ttf file may have more than one font. Each has a sequential index
--// number starting from 0. Call this function to get the font offset for a
--// given index; it returns -1 if the index is out of range. A regular .ttf
--// file will only define one font and it always be at offset 0, so it will
--// return '0' for index 0, and -1 for all other indices. You can just skip
--// this step if you know it's that kind of font.
--
--
--// The following structure is defined publically so you can declare one on
--// the stack or as a global or etc.
--typedef struct
--{
-- void *userdata;
-- unsigned char *data; // pointer to .ttf file
-- int fontstart; // offset of start of font
--
-- int numGlyphs; // number of glyphs, needed for range checking
--
-- int loca,head,glyf,hhea,hmtx; // table locations as offset from start of .ttf
-- int index_map; // a cmap mapping for our chosen character encoding
-- int indexToLocFormat; // format needed to map from glyph index to glyph
--} stbtt_fontinfo;
--
--extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
--// Given an offset into the file that defines a font, this function builds
--// the necessary cached info for the rest of the system. You must allocate
--// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
--// need to do anything special to free it, because the contents are a pure
--// cache with no additional data structures. Returns 0 on failure.
--
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// CHARACTER TO GLYPH-INDEX CONVERSIOn
--
--int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
--// If you're going to perform multiple operations on the same character
--// and you want a speed-up, call this function with the character you're
--// going to process, then use glyph-based functions instead of the
--// codepoint-based functions.
--
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// CHARACTER PROPERTIES
--//
--
--extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
--// computes a scale factor to produce a font whose "height" is 'pixels' tall.
--// Height is measured as the distance from the highest ascender to the lowest
--// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
--// and computing:
--// scale = pixels / (ascent - descent)
--// so if you prefer to measure height by the ascent only, use a similar calculation.
--
--extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
--// ascent is the coordinate above the baseline the font extends; descent
--// is the coordinate below the baseline the font extends (i.e. it is typically negative)
--// lineGap is the spacing between one row's descent and the next row's ascent...
--// so you should advance the vertical position by "*ascent - *descent + *lineGap"
--// these are expressed in unscaled coordinates
--
--extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
--// leftSideBearing is the offset from the current horizontal position to the left edge of the character
--// advanceWidth is the offset from the current horizontal position to the next horizontal position
--// these are expressed in unscaled coordinates
--
--extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
--// an additional amount to add to the 'advance' value between ch1 and ch2
--// @TODO; for now always returns 0!
--
--extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
--// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
--
--extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
--extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
--extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
--// as above, but takes one or more glyph indices for greater efficiency
--
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// GLYPH SHAPES (you probably don't need these, but they have to go before
--// the bitmaps for C declaration-order reasons)
--//
--
--#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
-- enum {
-- STBTT_vmove=1,
-- STBTT_vline,
-- STBTT_vcurve
-- };
--#endif
--
--#ifndef stbtt_vertex // you can predefine this to use different values
-- // (we share this with other code at RAD)
-- #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
-- typedef struct
-- {
-- stbtt_vertex_type x,y,cx,cy;
-- unsigned char type,padding;
-- } stbtt_vertex;
--#endif
--
--extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
--extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
--// returns # of vertices and fills *vertices with the pointer to them
--// these are expressed in "unscaled" coordinates
--
--extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
--// frees the data allocated above
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// BITMAP RENDERING
--//
--
--extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
--// frees the bitmap allocated below
--
--extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
--// allocates a large-enough single-channel 8bpp bitmap and renders the
--// specified character/glyph at the specified scale into it, with
--// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
--// *width & *height are filled out with the width & height of the bitmap,
--// which is stored left-to-right, top-to-bottom.
--//
--// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
--
--extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
--// the same as above, but you pass in storage for the bitmap in the form
--// of 'output', with row spacing of 'out_stride' bytes. the bitmap is
--// clipped to out_w/out_h bytes. call the next function to get the
--// height and width and positioning info
--
--extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
--// get the bbox of the bitmap centered around the glyph origin; so the
--// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
--// the bitmap top left is (leftSideBearing*scale,iy0).
--// (Note that the bitmap uses y-increases-down, but the shape uses
--// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
--
--extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
--extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
--extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
--
--//extern void stbtt_get_true_bbox(stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
--
--// @TODO: don't expose this structure
--typedef struct
--{
-- int w,h,stride;
-- unsigned char *pixels;
--} stbtt__bitmap;
--
--extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata);
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// Finding the right font...
--//
--// You should really just solve this offline, keep your own tables
--// of what font is what, and don't try to get it out of the .ttf file.
--// That's because getting it out of the .ttf file is really hard, because
--// the names in the file can appear in many possible encodings, in many
--// possible languages, and e.g. if you need a case-insensitive comparison,
--// the details of that depend on the encoding & language in a complex way
--// (actually underspecified in truetype, but also gigantic).
--//
--// But you can use the provided functions in two possible ways:
--// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
--// unicode-encoded names to try to find the font you want;
--// you can run this before calling stbtt_InitFont()
--//
--// stbtt_GetFontNameString() lets you get any of the various strings
--// from the file yourself and do your own comparisons on them.
--// You have to have called stbtt_InitFont() first.
--
--
--extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
--// returns the offset (not index) of the font that matches, or -1 if none
--// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
--// if you use any other flag, use a font name like "Arial"; this checks
--// the 'macStyle' header field; i don't know if fonts set this consistently
--#define STBTT_MACSTYLE_DONTCARE 0
--#define STBTT_MACSTYLE_BOLD 1
--#define STBTT_MACSTYLE_ITALIC 2
--#define STBTT_MACSTYLE_UNDERSCORE 4
--#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
--
--extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
--// returns 1/0 whether the first string interpreted as utf8 is identical to
--// the second string interpreted as big-endian utf16... useful for strings from next func
--
--extern char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
--// returns the string (which may be big-endian double byte, e.g. for unicode)
--// and puts the length in bytes in *length.
--//
--// some of the values for the IDs are below; for more see the truetype spec:
--// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
--// http://www.microsoft.com/typography/otspec/name.htm
--
--enum { // platformID
-- STBTT_PLATFORM_ID_UNICODE =0,
-- STBTT_PLATFORM_ID_MAC =1,
-- STBTT_PLATFORM_ID_ISO =2,
-- STBTT_PLATFORM_ID_MICROSOFT =3
--};
--
--enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
-- STBTT_UNICODE_EID_UNICODE_1_0 =0,
-- STBTT_UNICODE_EID_UNICODE_1_1 =1,
-- STBTT_UNICODE_EID_ISO_10646 =2,
-- STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
-- STBTT_UNICODE_EID_UNICODE_2_0_FULL=4,
--};
--
--enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
-- STBTT_MS_EID_SYMBOL =0,
-- STBTT_MS_EID_UNICODE_BMP =1,
-- STBTT_MS_EID_SHIFTJIS =2,
-- STBTT_MS_EID_UNICODE_FULL =10,
--};
--
--enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
-- STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
-- STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
-- STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
-- STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7,
--};
--
--enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
-- // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
-- STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
-- STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
-- STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
-- STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
-- STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
-- STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D,
--};
--
--enum { // languageID for STBTT_PLATFORM_ID_MAC
-- STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
-- STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
-- STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
-- STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
-- STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
-- STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
-- STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19,
--};
--
--#ifdef __cplusplus
--}
--#endif
--
--#endif // __STB_INCLUDE_STB_TRUETYPE_H__
--
--///////////////////////////////////////////////////////////////////////////////
--///////////////////////////////////////////////////////////////////////////////
--////
--//// IMPLEMENTATION
--////
--////
--
--#ifdef STB_TRUETYPE_IMPLEMENTATION
--
--//////////////////////////////////////////////////////////////////////////
--//
--// accessors to parse data from file
--//
--
--// on platforms that don't allow misaligned reads, if we want to allow
--// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
--
--#define ttBYTE(p) (* (stbtt_uint8 *) (p))
--#define ttCHAR(p) (* (stbtt_int8 *) (p))
--#define ttFixed(p) ttLONG(p)
--
--#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
--
-- #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
-- #define ttSHORT(p) (* (stbtt_int16 *) (p))
-- #define ttULONG(p) (* (stbtt_uint32 *) (p))
-- #define ttLONG(p) (* (stbtt_int32 *) (p))
--
--#else
--
-- stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-- stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-- stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-- stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
--
--#endif
--
--#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
--#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
--
--static int stbtt__isfont(const stbtt_uint8 *font)
--{
-- // check the version number
-- if (stbtt_tag(font, "1")) return 1; // TrueType 1
-- if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
-- if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
-- if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
-- return 0;
--}
--
--// @OPTIMIZE: binary search
--static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
--{
-- stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
-- stbtt_uint32 tabledir = fontstart + 12;
-- stbtt_int32 i;
-- for (i=0; i < num_tables; ++i) {
-- stbtt_uint32 loc = tabledir + 16*i;
-- if (stbtt_tag(data+loc+0, tag))
-- return ttULONG(data+loc+8);
-- }
-- return 0;
--}
--
--int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index)
--{
-- // if it's just a font, there's only one valid index
-- if (stbtt__isfont(font_collection))
-- return index == 0 ? 0 : -1;
--
-- // check if it's a TTC
-- if (stbtt_tag(font_collection, "ttcf")) {
-- // version 1?
-- if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
-- stbtt_int32 n = ttLONG(font_collection+8);
-- if (index >= n)
-- return -1;
-- return ttULONG(font_collection+12+index*14);
-- }
-- }
-- return -1;
--}
--
--int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart)
--{
-- stbtt_uint8 *data = (stbtt_uint8 *) data2;
-- stbtt_uint32 cmap, t;
-- stbtt_int32 i,numTables;
--
-- info->data = data;
-- info->fontstart = fontstart;
--
-- cmap = stbtt__find_table(data, fontstart, "cmap");
-- info->loca = stbtt__find_table(data, fontstart, "loca");
-- info->head = stbtt__find_table(data, fontstart, "head");
-- info->glyf = stbtt__find_table(data, fontstart, "glyf");
-- info->hhea = stbtt__find_table(data, fontstart, "hhea");
-- info->hmtx = stbtt__find_table(data, fontstart, "hmtx");
-- if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
-- return 0;
--
-- t = stbtt__find_table(data, fontstart, "maxp");
-- if (t)
-- info->numGlyphs = ttUSHORT(data+t+4);
-- else
-- info->numGlyphs = 0xffff;
--
-- // find a cmap encoding table we understand *now* to avoid searching
-- // later. (todo: could make this installable)
-- // the same regardless of glyph.
-- numTables = ttUSHORT(data + cmap + 2);
-- info->index_map = 0;
-- for (i=0; i < numTables; ++i) {
-- stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
-- // find an encoding we understand:
-- switch(ttUSHORT(data+encoding_record)) {
-- case STBTT_PLATFORM_ID_MICROSOFT:
-- switch (ttUSHORT(data+encoding_record+2)) {
-- case STBTT_MS_EID_UNICODE_BMP:
-- case STBTT_MS_EID_UNICODE_FULL:
-- // MS/Unicode
-- info->index_map = cmap + ttULONG(data+encoding_record+4);
-- break;
-- }
-- break;
-- }
-- }
-- if (info->index_map == 0)
-- return 0;
--
-- info->indexToLocFormat = ttUSHORT(data+info->head + 50);
-- return 1;
--}
--
--int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
--{
-- stbtt_uint8 *data = info->data;
-- stbtt_uint32 index_map = info->index_map;
--
-- stbtt_uint16 format = ttUSHORT(data + index_map + 0);
-- if (format == 0) { // apple byte encoding
-- stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
-- if (unicode_codepoint < bytes-6)
-- return ttBYTE(data + index_map + 6 + unicode_codepoint);
-- return 0;
-- } else if (format == 6) {
-- stbtt_uint32 first = ttUSHORT(data + index_map + 6);
-- stbtt_uint32 count = ttUSHORT(data + index_map + 8);
-- if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
-- return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
-- return 0;
-- } else if (format == 2) {
-- STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
-- return 0;
-- } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
-- stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
-- stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
-- stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
-- stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
-- stbtt_uint16 item, offset, start, end;
--
-- // do a binary search of the segments
-- stbtt_uint32 endCount = index_map + 14;
-- stbtt_uint32 search = endCount;
--
-- if (unicode_codepoint > 0xffff)
-- return 0;
--
-- // they lie from endCount .. endCount + segCount
-- // but searchRange is the nearest power of two, so...
-- if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
-- search += rangeShift*2;
--
-- // now decrement to bias correctly to find smallest
-- search -= 2;
-- while (entrySelector) {
-- stbtt_uint16 start, end;
-- searchRange >>= 1;
-- start = ttUSHORT(data + search + 2 + segcount*2 + 2);
-- end = ttUSHORT(data + search + 2);
-- start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
-- end = ttUSHORT(data + search + searchRange*2);
-- if (unicode_codepoint > end)
-- search += searchRange*2;
-- --entrySelector;
-- }
-- search += 2;
--
-- item = (stbtt_uint16) ((search - endCount) >> 1);
--
-- STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
-- start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
-- end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
-- if (unicode_codepoint < start)
-- return 0;
--
-- offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
-- if (offset == 0)
-- return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item);
--
-- return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
-- } else if (format == 12) {
-- stbtt_uint16 ngroups = ttUSHORT(data+index_map+6);
-- stbtt_int32 low,high;
-- low = 0; high = (stbtt_int32)ngroups;
-- // Binary search the right group.
-- while (low <= high) {
-- stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
-- stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
-- stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
-- if ((stbtt_uint32) unicode_codepoint < start_char)
-- high = mid-1;
-- else if ((stbtt_uint32) unicode_codepoint > end_char)
-- low = mid+1;
-- else {
-- stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
-- return start_glyph + unicode_codepoint-start_char;
-- }
-- }
-- return 0; // not found
-- }
-- // @TODO
-- STBTT_assert(0);
-- return 0;
--}
--
--int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
--{
-- return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
--}
--
--static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int16 x, stbtt_int16 y, stbtt_int16 cx, stbtt_int16 cy)
--{
-- v->type = type;
-- v->x = x;
-- v->y = y;
-- v->cx = cx;
-- v->cy = cy;
--}
--
--static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
--{
-- int g1,g2;
--
-- if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
-- if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
--
-- if (info->indexToLocFormat == 0) {
-- g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
-- g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
-- } else {
-- g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
-- g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
-- }
--
-- return g1==g2 ? -1 : g1; // if length is 0, return -1
--}
--
--int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
--{
-- int g = stbtt__GetGlyfOffset(info, glyph_index);
-- if (g < 0) return 0;
--
-- if (x0) *x0 = ttSHORT(info->data + g + 2);
-- if (y0) *y0 = ttSHORT(info->data + g + 4);
-- if (x1) *x1 = ttSHORT(info->data + g + 6);
-- if (y1) *y1 = ttSHORT(info->data + g + 8);
-- return 1;
--}
--
--int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
--{
-- return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
--}
--
--int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
--{
-- stbtt_int16 numberOfContours;
-- stbtt_uint8 *endPtsOfContours;
-- stbtt_uint8 *data = info->data;
-- stbtt_vertex *vertices=0;
-- int num_vertices=0;
-- int g = stbtt__GetGlyfOffset(info, glyph_index);
--
-- *pvertices = NULL;
--
-- if (g < 0) return 0;
--
-- numberOfContours = ttSHORT(data + g);
--
-- if (numberOfContours > 0) {
-- stbtt_uint8 flags=0,flagcount;
-- stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;
-- stbtt_int16 x,y,cx,cy,sx,sy;
-- stbtt_uint8 *points;
-- endPtsOfContours = (data + g + 10);
-- ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
-- points = data + g + 10 + numberOfContours * 2 + 2 + ins;
--
-- n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
--
-- m = n + numberOfContours; // a loose bound on how many vertices we might need
-- vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
-- if (vertices == 0)
-- return 0;
--
-- next_move = 0;
-- flagcount=0;
--
-- // in first pass, we load uninterpreted data into the allocated array
-- // above, shifted to the end of the array so we won't overwrite it when
-- // we create our final data starting from the front
--
-- off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
--
-- // first load flags
--
-- for (i=0; i < n; ++i) {
-- if (flagcount == 0) {
-- flags = *points++;
-- if (flags & 8)
-- flagcount = *points++;
-- } else
-- --flagcount;
-- vertices[off+i].type = flags;
-- }
--
-- // now load x coordinates
-- x=0;
-- for (i=0; i < n; ++i) {
-- flags = vertices[off+i].type;
-- if (flags & 2) {
-- stbtt_int16 dx = *points++;
-- x += (flags & 16) ? dx : -dx; // ???
-- } else {
-- if (!(flags & 16)) {
-- x = x + (stbtt_int16) (points[0]*256 + points[1]);
-- points += 2;
-- }
-- }
-- vertices[off+i].x = x;
-- }
--
-- // now load y coordinates
-- y=0;
-- for (i=0; i < n; ++i) {
-- flags = vertices[off+i].type;
-- if (flags & 4) {
-- stbtt_int16 dy = *points++;
-- y += (flags & 32) ? dy : -dy; // ???
-- } else {
-- if (!(flags & 32)) {
-- y = y + (stbtt_int16) (points[0]*256 + points[1]);
-- points += 2;
-- }
-- }
-- vertices[off+i].y = y;
-- }
--
-- // now convert them to our format
-- num_vertices=0;
-- sx = sy = cx = cy = 0;
-- for (i=0; i < n; ++i) {
-- flags = vertices[off+i].type;
-- x = (stbtt_int16) vertices[off+i].x;
-- y = (stbtt_int16) vertices[off+i].y;
-- if (next_move == i) {
-- // when we get to the end, we have to close the shape explicitly
-- if (i != 0) {
-- if (was_off)
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
-- else
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
-- }
--
-- // now start the new one
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,x,y,0,0);
-- next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
-- ++j;
-- was_off = 0;
-- sx = x;
-- sy = y;
-- } else {
-- if (!(flags & 1)) { // if it's a curve
-- if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
-- cx = x;
-- cy = y;
-- was_off = 1;
-- } else {
-- if (was_off)
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
-- else
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
-- was_off = 0;
-- }
-- }
-- }
-- if (i != 0) {
-- if (was_off)
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
-- else
-- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
-- }
-- } else if (numberOfContours == -1) {
-- // Compound shapes.
-- int more = 1;
-- stbtt_uint8 *comp = data + g + 10;
-- num_vertices = 0;
-- vertices = 0;
-- while (more) {
-- stbtt_uint16 flags, gidx;
-- int comp_num_verts = 0, i;
-- stbtt_vertex *comp_verts = 0, *tmp = 0;
-- float mtx[6] = {1,0,0,1,0,0}, m, n;
--
-- flags = ttSHORT(comp); comp+=2;
-- gidx = ttSHORT(comp); comp+=2;
--
-- if (flags & 2) { // XY values
-- if (flags & 1) { // shorts
-- mtx[4] = ttSHORT(comp); comp+=2;
-- mtx[5] = ttSHORT(comp); comp+=2;
-- } else {
-- mtx[4] = ttCHAR(comp); comp+=1;
-- mtx[5] = ttCHAR(comp); comp+=1;
-- }
-- }
-- else {
-- // @TODO handle matching point
-- STBTT_assert(0);
-- }
-- if (flags & (1<<3)) { // WE_HAVE_A_SCALE
-- mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-- mtx[1] = mtx[2] = 0;
-- } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
-- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-- mtx[1] = mtx[2] = 0;
-- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-- } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
-- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-- mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
-- mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
-- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-- }
--
-- // Find transformation scales.
-- m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
-- n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
--
-- // Get indexed glyph.
-- comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
-- if (comp_num_verts > 0) {
-- // Transform vertices.
-- for (i = 0; i < comp_num_verts; ++i) {
-- stbtt_vertex* v = &comp_verts[i];
-- stbtt_vertex_type x,y;
-- x=v->x; y=v->y;
-- v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-- v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-- x=v->cx; y=v->cy;
-- v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-- v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-- }
-- // Append vertices.
-- tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
-- if (!tmp) {
-- if (vertices) STBTT_free(vertices, info->userdata);
-- if (comp_verts) STBTT_free(comp_verts, info->userdata);
-- return 0;
-- }
-- if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
-- memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
-- if (vertices) STBTT_free(vertices, info->userdata);
-- vertices = tmp;
-- STBTT_free(comp_verts, info->userdata);
-- num_vertices += comp_num_verts;
-- }
-- // More components ?
-- more = flags & (1<<5);
-- }
-- } else if (numberOfContours < 0) {
-- // @TODO other compound variations?
-- STBTT_assert(0);
-- } else {
-- // numberOfCounters == 0, do nothing
-- }
--
-- *pvertices = vertices;
-- return num_vertices;
--}
--
--void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
--{
-- stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
-- if (glyph_index < numOfLongHorMetrics) {
-- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
-- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
-- } else {
-- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
-- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
-- }
--}
--
--int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * /*info*/, int /*glyph1*/, int /*glyph2*/)
--{
-- return 0;
--}
--
--int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * /*info*/, int /*ch1*/, int /*ch2*/)
--{
-- return 0;
--}
--
--void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
--{
-- stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
--}
--
--void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
--{
-- if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
-- if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
-- if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
--}
--
--float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
--{
-- int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
-- return (float) height / fheight;
--}
--
--void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
--{
-- STBTT_free(v, info->userdata);
--}
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// antialiasing software rasterizer
--//
--
--void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
--{
-- int x0,y0,x1,y1;
-- if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1))
-- x0=y0=x1=y1=0; // e.g. space character
-- // now move to integral bboxes (treating pixels as little squares, what pixels get touched)?
-- if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x);
-- if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y);
-- if (ix1) *ix1 = STBTT_iceil (x1 * scale_x);
-- if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y);
--}
--
--void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
--{
-- stbtt_GetGlyphBitmapBox(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y, ix0,iy0,ix1,iy1);
--}
--
--typedef struct stbtt__edge {
-- float x0,y0, x1,y1;
-- int invert;
--} stbtt__edge;
--
--typedef struct stbtt__active_edge
--{
-- int x,dx;
-- float ey;
-- struct stbtt__active_edge *next;
-- int valid;
--} stbtt__active_edge;
--
--#define FIXSHIFT 10
--#define FIX (1 << FIXSHIFT)
--#define FIXMASK (FIX-1)
--
--static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata)
--{
-- stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!!
-- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
-- STBTT_assert(e->y0 <= start_point);
-- if (!z) return z;
-- // round dx down to avoid going too far
-- if (dxdy < 0)
-- z->dx = -STBTT_ifloor(FIX * -dxdy);
-- else
-- z->dx = STBTT_ifloor(FIX * dxdy);
-- z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
-- z->x -= off_x * FIX;
-- z->ey = e->y1;
-- z->next = 0;
-- z->valid = e->invert ? 1 : -1;
-- return z;
--}
--
--// note: this routine clips fills that extend off the edges... ideally this
--// wouldn't happen, but it could happen if the truetype glyph bounding boxes
--// are wrong, or if the user supplies a too-small bitmap
--static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
--{
-- // non-zero winding fill
-- int x0=0, w=0;
--
-- while (e) {
-- if (w == 0) {
-- // if we're currently at zero, we need to record the edge start point
-- x0 = e->x; w += e->valid;
-- } else {
-- int x1 = e->x; w += e->valid;
-- // if we went to zero, we need to draw
-- if (w == 0) {
-- int i = x0 >> FIXSHIFT;
-- int j = x1 >> FIXSHIFT;
--
-- if (i < len && j >= 0) {
-- if (i == j) {
-- // x0,x1 are the same pixel, so compute combined coverage
-- scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
-- } else {
-- if (i >= 0) // add antialiasing for x0
-- scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
-- else
-- i = -1; // clip
--
-- if (j < len) // add antialiasing for x1
-- scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
-- else
-- j = len; // clip
--
-- for (++i; i < j; ++i) // fill pixels between x0 and x1
-- scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
-- }
-- }
-- }
-- }
--
-- e = e->next;
-- }
--}
--
--static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
--{
-- stbtt__active_edge *active = NULL;
-- int y,j=0;
-- int max_weight = (255 / vsubsample); // weight per vertical scanline
-- int s; // vertical subsample index
-- unsigned char scanline_data[512], *scanline;
--
-- if (result->w > 512)
-- scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
-- else
-- scanline = scanline_data;
--
-- y = off_y * vsubsample;
-- e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
--
-- while (j < result->h) {
-- STBTT_memset(scanline, 0, result->w);
-- for (s=0; s < vsubsample; ++s) {
-- // find center of pixel for this scanline
-- float scan_y = y + 0.5f;
-- stbtt__active_edge **step = &active;
--
-- // update all active edges;
-- // remove all active edges that terminate before the center of this scanline
-- while (*step) {
-- stbtt__active_edge * z = *step;
-- if (z->ey <= scan_y) {
-- *step = z->next; // delete from list
-- STBTT_assert(z->valid);
-- z->valid = 0;
-- STBTT_free(z, userdata);
-- } else {
-- z->x += z->dx; // advance to position for current scanline
-- step = &((*step)->next); // advance through list
-- }
-- }
--
-- // resort the list if needed
-- for(;;) {
-- int changed=0;
-- step = &active;
-- while (*step && (*step)->next) {
-- if ((*step)->x > (*step)->next->x) {
-- stbtt__active_edge *t = *step;
-- stbtt__active_edge *q = t->next;
--
-- t->next = q->next;
-- q->next = t;
-- *step = q;
-- changed = 1;
-- }
-- step = &(*step)->next;
-- }
-- if (!changed) break;
-- }
--
-- // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
-- while (e->y0 <= scan_y) {
-- if (e->y1 > scan_y) {
-- stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
-- // find insertion point
-- if (active == NULL)
-- active = z;
-- else if (z->x < active->x) {
-- // insert at front
-- z->next = active;
-- active = z;
-- } else {
-- // find thing to insert AFTER
-- stbtt__active_edge *p = active;
-- while (p->next && p->next->x < z->x)
-- p = p->next;
-- // at this point, p->next->x is NOT < z->x
-- z->next = p->next;
-- p->next = z;
-- }
-- }
-- ++e;
-- }
--
-- // now process all active edges in XOR fashion
-- if (active)
-- stbtt__fill_active_edges(scanline, result->w, active, max_weight);
--
-- ++y;
-- }
-- STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
-- ++j;
-- }
--
-- while (active) {
-- stbtt__active_edge *z = active;
-- active = active->next;
-- STBTT_free(z, userdata);
-- }
--
-- if (scanline != scanline_data)
-- STBTT_free(scanline, userdata);
--}
--
--static int stbtt__edge_compare(const void *p, const void *q)
--{
-- stbtt__edge *a = (stbtt__edge *) p;
-- stbtt__edge *b = (stbtt__edge *) q;
--
-- if (a->y0 < b->y0) return -1;
-- if (a->y0 > b->y0) return 1;
-- return 0;
--}
--
--typedef struct
--{
-- float x,y;
--} stbtt__point;
--
--static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata)
--{
-- float y_scale_inv = invert ? -scale_y : scale_y;
-- stbtt__edge *e;
-- int n,i,j,k,m;
-- int vsubsample = result->h < 8 ? 15 : 5;
-- // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
--
-- // now we have to blow out the windings into explicit edge lists
-- n = 0;
-- for (i=0; i < windings; ++i)
-- n += wcount[i];
--
-- e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
-- if (e == 0) return;
-- n = 0;
--
-- m=0;
-- for (i=0; i < windings; ++i) {
-- stbtt__point *p = pts + m;
-- m += wcount[i];
-- j = wcount[i]-1;
-- for (k=0; k < wcount[i]; j=k++) {
-- int a=k,b=j;
-- // skip the edge if horizontal
-- if (p[j].y == p[k].y)
-- continue;
-- // add edge from j to k to the list
-- e[n].invert = 0;
-- if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
-- e[n].invert = 1;
-- a=j,b=k;
-- }
-- e[n].x0 = p[a].x * scale_x;
-- e[n].y0 = p[a].y * y_scale_inv * vsubsample;
-- e[n].x1 = p[b].x * scale_x;
-- e[n].y1 = p[b].y * y_scale_inv * vsubsample;
-- ++n;
-- }
-- }
--
-- // now sort the edges by their highest point (should snap to integer, and then by x)
-- STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
--
-- // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
-- stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
--
-- STBTT_free(e, userdata);
--}
--
--static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
--{
-- if (!points) return; // during first pass, it's unallocated
-- points[n].x = x;
-- points[n].y = y;
--}
--
--// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
--static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
--{
-- // midpoint
-- float mx = (x0 + 2*x1 + x2)/4;
-- float my = (y0 + 2*y1 + y2)/4;
-- // versus directly drawn line
-- float dx = (x0+x2)/2 - mx;
-- float dy = (y0+y2)/2 - my;
-- if (n > 16) // 65536 segments on one curve better be enough!
-- return 1;
-- if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
-- stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
-- stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
-- } else {
-- stbtt__add_point(points, *num_points,x2,y2);
-- *num_points = *num_points+1;
-- }
-- return 1;
--}
--
--// returns number of contours
--stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
--{
-- stbtt__point *points=0;
-- int num_points=0;
--
-- float objspace_flatness_squared = objspace_flatness * objspace_flatness;
-- int i,n=0,start=0, pass;
--
-- // count how many "moves" there are to get the contour count
-- for (i=0; i < num_verts; ++i)
-- if (vertices[i].type == STBTT_vmove)
-- ++n;
--
-- *num_contours = n;
-- if (n == 0) return 0;
--
-- *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
--
-- if (*contour_lengths == 0) {
-- *num_contours = 0;
-- return 0;
-- }
--
-- // make two passes through the points so we don't need to realloc
-- for (pass=0; pass < 2; ++pass) {
-- float x=0,y=0;
-- if (pass == 1) {
-- points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
-- if (points == NULL) goto error;
-- }
-- num_points = 0;
-- n= -1;
-- for (i=0; i < num_verts; ++i) {
-- switch (vertices[i].type) {
-- case STBTT_vmove:
-- // start the next contour
-- if (n >= 0)
-- (*contour_lengths)[n] = num_points - start;
-- ++n;
-- start = num_points;
--
-- x = vertices[i].x, y = vertices[i].y;
-- stbtt__add_point(points, num_points++, x,y);
-- break;
-- case STBTT_vline:
-- x = vertices[i].x, y = vertices[i].y;
-- stbtt__add_point(points, num_points++, x, y);
-- break;
-- case STBTT_vcurve:
-- stbtt__tesselate_curve(points, &num_points, x,y,
-- vertices[i].cx, vertices[i].cy,
-- vertices[i].x, vertices[i].y,
-- objspace_flatness_squared, 0);
-- x = vertices[i].x, y = vertices[i].y;
-- break;
-- }
-- }
-- (*contour_lengths)[n] = num_points - start;
-- }
--
-- return points;
--error:
-- STBTT_free(points, userdata);
-- STBTT_free(*contour_lengths, userdata);
-- *contour_lengths = 0;
-- *num_contours = 0;
-- return NULL;
--}
--
--void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata)
--{
-- float scale = scale_x > scale_y ? scale_y : scale_x;
-- int winding_count, *winding_lengths;
-- stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
-- if (windings) {
-- stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata);
-- STBTT_free(winding_lengths, userdata);
-- STBTT_free(windings, userdata);
-- }
--}
--
--void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
--{
-- STBTT_free(bitmap, userdata);
--}
--
--unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
--{
-- int ix0,iy0,ix1,iy1;
-- stbtt__bitmap gbm;
-- stbtt_vertex *vertices;
-- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
--
-- if (scale_x == 0) scale_x = scale_y;
-- if (scale_y == 0) {
-- if (scale_x == 0) return NULL;
-- scale_y = scale_x;
-- }
--
-- stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
--
-- // now we get the size
-- gbm.w = (ix1 - ix0);
-- gbm.h = (iy1 - iy0);
-- gbm.pixels = NULL; // in case we error
--
-- if (width ) *width = gbm.w;
-- if (height) *height = gbm.h;
-- if (xoff ) *xoff = ix0;
-- if (yoff ) *yoff = iy0;
--
-- if (gbm.w && gbm.h) {
-- gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
-- if (gbm.pixels) {
-- gbm.stride = gbm.w;
--
-- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata);
-- }
-- }
-- STBTT_free(vertices, info->userdata);
-- return gbm.pixels;
--}
--
--void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
--{
-- int ix0,iy0;
-- stbtt_vertex *vertices;
-- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-- stbtt__bitmap gbm;
--
-- stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,0,0);
-- gbm.pixels = output;
-- gbm.w = out_w;
-- gbm.h = out_h;
-- gbm.stride = out_stride;
--
-- if (gbm.w && gbm.h)
-- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata);
--
-- STBTT_free(vertices, info->userdata);
--}
--
--unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
--{
-- return stbtt_GetGlyphBitmap(info, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
--}
--
--void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
--{
-- stbtt_MakeGlyphBitmap(info, output, out_w, out_h, out_stride, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint));
--}
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// bitmap baking
--//
--// This is SUPER-SHITTY packing to keep source code small
--
--extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
-- float pixel_height, // height of font in pixels
-- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
-- int first_char, int num_chars, // characters to bake
-- stbtt_bakedchar *chardata)
--{
-- float scale;
-- int x,y,bottom_y, i;
-- stbtt_fontinfo f;
-- stbtt_InitFont(&f, data, offset);
-- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
-- x=y=1;
-- bottom_y = 1;
--
-- scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
--
-- for (i=0; i < num_chars; ++i) {
-- int advance, lsb, x0,y0,x1,y1,gw,gh;
-- int g = stbtt_FindGlyphIndex(&f, first_char + i);
-- stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
-- stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
-- gw = x1-x0;
-- gh = y1-y0;
-- if (x + gw + 1 >= pw)
-- y = bottom_y, x = 1; // advance to next row
-- if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
-- return -i;
-- STBTT_assert(x+gw < pw);
-- STBTT_assert(y+gh < ph);
-- stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
-- chardata[i].x0 = (stbtt_int16) x;
-- chardata[i].y0 = (stbtt_int16) y;
-- chardata[i].x1 = (stbtt_int16) (x + gw);
-- chardata[i].y1 = (stbtt_int16) (y + gh);
-- chardata[i].xadvance = scale * advance;
-- chardata[i].xoff = (float) x0;
-- chardata[i].yoff = (float) y0;
-- x = x + gw + 2;
-- if (y+gh+2 > bottom_y)
-- bottom_y = y+gh+2;
-- }
-- return bottom_y;
--}
--
--void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
--{
-- float d3d_bias = opengl_fillrule ? 0 : -0.5f;
-- float ipw = 1.0f / pw, iph = 1.0f / ph;
-- stbtt_bakedchar *b = chardata + char_index;
-- int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
-- int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
--
-- q->x0 = round_x + d3d_bias;
-- q->y0 = round_y + d3d_bias;
-- q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
-- q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
--
-- q->s0 = b->x0 * ipw;
-- q->t0 = b->y0 * ipw;
-- q->s1 = b->x1 * iph;
-- q->t1 = b->y1 * iph;
--
-- *xpos += b->xadvance;
--}
--
--//////////////////////////////////////////////////////////////////////////////
--//
--// font name matching -- recommended not to use this
--//
--
--// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
--static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
--{
-- stbtt_int32 i=0;
--
-- // convert utf16 to utf8 and compare the results while converting
-- while (len2) {
-- stbtt_uint16 ch = s2[0]*256 + s2[1];
-- if (ch < 0x80) {
-- if (i >= len1) return -1;
-- if (s1[i++] != ch) return -1;
-- } else if (ch < 0x800) {
-- if (i+1 >= len1) return -1;
-- if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
-- if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
-- } else if (ch >= 0xd800 && ch < 0xdc00) {
-- stbtt_uint32 c;
-- stbtt_uint16 ch2 = s2[2]*256 + s2[3];
-- if (i+3 >= len1) return -1;
-- c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
-- if (s1[i++] != 0xf0 + (c >> 18)) return -1;
-- if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
-- if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
-- if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
-- s2 += 2; // plus another 2 below
-- len2 -= 2;
-- } else if (ch >= 0xdc00 && ch < 0xe000) {
-- return -1;
-- } else {
-- if (i+2 >= len1) return -1;
-- if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
-- if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
-- if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
-- }
-- s2 += 2;
-- len2 -= 2;
-- }
-- return i;
--}
--
--int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
--{
-- return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
--}
--
--// returns results in whatever encoding you request... but note that 2-byte encodings
--// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
--char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
--{
-- stbtt_int32 i,count,stringOffset;
-- stbtt_uint8 *fc = font->data;
-- stbtt_uint32 offset = font->fontstart;
-- stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
-- if (!nm) return NULL;
--
-- count = ttUSHORT(fc+nm+2);
-- stringOffset = nm + ttUSHORT(fc+nm+4);
-- for (i=0; i < count; ++i) {
-- stbtt_uint32 loc = nm + 6 + 12 * i;
-- if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
-- && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
-- *length = ttUSHORT(fc+loc+8);
-- return (char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
-- }
-- }
-- return NULL;
--}
--
--static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
--{
-- stbtt_int32 i;
-- stbtt_int32 count = ttUSHORT(fc+nm+2);
-- stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
--
-- for (i=0; i < count; ++i) {
-- stbtt_uint32 loc = nm + 6 + 12 * i;
-- stbtt_int32 id = ttUSHORT(fc+loc+6);
-- if (id == target_id) {
-- // find the encoding
-- stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
--
-- // is this a Unicode encoding?
-- if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
-- stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10);
--
-- // check if there's a prefix match
-- stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
-- if (matchlen >= 0) {
-- // check for target_id+1 immediately following, with same encoding & language
-- 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) {
-- stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10);
-- if (slen == 0) {
-- if (matchlen == nlen)
-- return 1;
-- } else if (matchlen < nlen && name[matchlen] == ' ') {
-- ++matchlen;
-- if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
-- return 1;
-- }
-- } else {
-- // if nothing immediately following
-- if (matchlen == nlen)
-- return 1;
-- }
-- }
-- }
--
-- // @TODO handle other encodings
-- }
-- }
-- return 0;
--}
--
--static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
--{
-- stbtt_int32 nlen = STBTT_strlen((char *) name);
-- stbtt_uint32 nm,hd;
-- if (!stbtt__isfont(fc+offset)) return 0;
--
-- // check italics/bold/underline flags in macStyle...
-- if (flags) {
-- hd = stbtt__find_table(fc, offset, "head");
-- if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
-- }
--
-- nm = stbtt__find_table(fc, offset, "name");
-- if (!nm) return 0;
--
-- if (flags) {
-- // if we checked the macStyle flags, then just check the family and ignore the subfamily
-- if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
-- if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
-- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
-- } else {
-- if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
-- if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
-- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
-- }
--
-- return 0;
--}
--
--int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags)
--{
-- stbtt_int32 i;
-- for (i=0;;++i) {
-- stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
-- if (off < 0) return off;
-- if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
-- return off;
-- }
--}
--
--#endif // STB_TRUETYPE_IMPLEMENTATION
-+// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools
-+//
-+// This library processes TrueType files:
-+// parse files
-+// extract glyph metrics
-+// extract glyph shapes
-+// render glyphs to one-channel bitmaps with antialiasing (box filter)
-+//
-+// Todo:
-+// non-MS cmaps
-+// crashproof on bad data
-+// hinting
-+// subpixel positioning when rendering bitmap
-+// cleartype-style AA
-+//
-+// ADDITIONAL CONTRIBUTORS
-+//
-+// Mikko Mononen: compound shape support, more cmap formats
-+//
-+// VERSIONS
-+//
-+// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
-+// userdata, malloc-from-userdata, non-zero fill (STB)
-+// 0.2 (2009-03-11) Fix unsigned/signed char warnings
-+// 0.1 (2009-03-09) First public release
-+//
-+// USAGE
-+//
-+// Include this file in whatever places neeed to refer to it. In ONE C/C++
-+// file, write:
-+// #define STB_TRUETYPE_IMPLEMENTATION
-+// before the #include of this file. This expands out the actual
-+// implementation into that C/C++ file.
-+//
-+// Look at the header-file sections below for the API, but here's a quick skim:
-+//
-+// Simple 3D API (don't ship this, but it's fine for tools and quick start,
-+// and you can cut and paste from it to move to more advanced)
-+// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
-+// stbtt_GetBakedQuad() -- compute quad to draw for a given char
-+//
-+// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
-+// stbtt_InitFont()
-+// stbtt_GetFontOffsetForIndex() -- use for TTC font collections
-+//
-+// Render a unicode codepoint to a bitmap
-+// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
-+// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
-+// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
-+//
-+// Character advance/positioning
-+// stbtt_GetCodepointHMetrics()
-+// stbtt_GetFontVMetrics()
-+//
-+// NOTES
-+//
-+// The system uses the raw data found in the .ttf file without changing it
-+// and without building auxiliary data structures. This is a bit inefficient
-+// on little-endian systems (the data is big-endian), but assuming you're
-+// caching the bitmaps or glyph shapes this shouldn't be a big deal.
-+//
-+// It appears to be very hard to programmatically determine what font a
-+// given file is in a general way. I provide an API for this, but I don't
-+// recommend it.
-+//
-+//
-+// SOURCE STATISTICS (based on v0.3, 1800 LOC)
-+//
-+// Documentation & header file 350 LOC \___ 500 LOC documentation
-+// Sample code 140 LOC /
-+// Truetype parsing 580 LOC ---- 600 LOC TrueType
-+// Software rasterization 240 LOC \ .
-+// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation
-+// Bitmap management 70 LOC /
-+// Baked bitmap interface 70 LOC /
-+// Font name matching & access 150 LOC ---- 150
-+// C runtime library abstraction 60 LOC ---- 60
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//////////////////////////////////////////////////////////////////////////////
-+////
-+//// SAMPLE PROGRAMS
-+////
-+//
-+// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
-+//
-+#if 0
-+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
-+#include "stb_truetype.h"
-+
-+char ttf_buffer[1<<20];
-+unsigned char temp_bitmap[512*512];
-+
-+stbtt_chardata cdata[96]; // ASCII 32..126 is 95 glyphs
-+GLstbtt_uint ftex;
-+
-+void my_stbtt_initfont(void)
-+{
-+ fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
-+ stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
-+ // can free ttf_buffer at this point
-+ glGenTextures(1, &ftex);
-+ glBindTexture(GL_TEXTURE_2D, ftex);
-+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
-+ // can free temp_bitmap at this point
-+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-+}
-+
-+void my_stbtt_print(float x, float y, char *text)
-+{
-+ // assume orthographic projection with units = screen pixels, origin at top left
-+ glBindTexture(GL_TEXTURE_2D, ftex);
-+ glBegin(GL_QUADS);
-+ while (*text) {
-+ if (*text >= 32 && *text < 128) {
-+ stbtt_aligned_quad q;
-+ stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d
-+ glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
-+ glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
-+ glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
-+ glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
-+ }
-+ ++text;
-+ }
-+ glEnd();
-+}
-+#endif
-+//
-+//
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// Complete program (this compiles): get a single bitmap, print as ASCII art
-+//
-+#if 0
-+#include <stdio.h>
-+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
-+#include "stb_truetype.h"
-+
-+char ttf_buffer[1<<25];
-+
-+int main(int argc, char **argv)
-+{
-+ stbtt_fontinfo font;
-+ unsigned char *bitmap;
-+ int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
-+
-+ fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
-+
-+ stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
-+ bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
-+
-+ for (j=0; j < h; ++j) {
-+ for (i=0; i < w; ++i)
-+ putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
-+ putchar('\n');
-+ }
-+ return 0;
-+}
-+#endif
-+//
-+// Output:
-+//
-+// .ii.
-+// @@@@@@.
-+// V@Mio@@o
-+// :i. V@V
-+// :oM@@M
-+// :@@@MM@M
-+// @@o o@M
-+// :@@. M@M
-+// @@@o@@@@
-+// :M@@V:@@.
-+//
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// Complete program: print "Hello World!" banner, with bugs
-+//
-+#if 0
-+int main(int arg, char **argv)
-+{
-+ unsigned char screen[20][79];
-+ int i,j, pos=0;
-+ float scale;
-+ char *text = "Heljo World!";
-+
-+ fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
-+ stbtt_InitFont(&font, buffer, 0);
-+
-+ scale = stbtt_ScaleForPixelHeight(&font, 16);
-+ memset(screen, 0, sizeof(screen));
-+
-+ while (*text) {
-+ int advance,lsb,x0,y0,x1,y1, newpos, baseline=13;
-+ stbtt_GetCodepointHMetrics(&font, *text, &advance, &lsb);
-+ stbtt_GetCodepointBitmapBox(&font, *text, scale,scale, &x0,&y0,&x1,&y1);
-+ newpos = pos + (int) (lsb * scale) + x0;
-+ stbtt_MakeCodepointBitmap(&font, &screen[baseline + y0][newpos], x1-x0,y1-y0, 79, scale,scale, *text);
-+ // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
-+ // because this API is really for baking character bitmaps into textures
-+ pos += (int) (advance * scale);
-+ ++text;
-+ }
-+
-+ for (j=0; j < 20; ++j) {
-+ for (i=0; i < 79; ++i)
-+ putchar(" .:ioVM@"[screen[j][i]>>5]);
-+ putchar('\n');
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//////////////////////////////////////////////////////////////////////////////
-+////
-+//// INTEGRATION WITH RUNTIME LIBRARIES
-+////
-+
-+#ifdef STB_TRUETYPE_IMPLEMENTATION
-+ // #define your own (u)stbtt_int8/16/32 before including to override this
-+ #ifndef stbtt_uint8
-+ typedef unsigned char stbtt_uint8;
-+ typedef signed char stbtt_int8;
-+ typedef unsigned short stbtt_uint16;
-+ typedef signed short stbtt_int16;
-+ typedef unsigned int stbtt_uint32;
-+ typedef signed int stbtt_int32;
-+ #endif
-+
-+ typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
-+ typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
-+
-+ // #define your own STBTT_sort() to override this to avoid qsort
-+ #ifndef STBTT_sort
-+ #include <stdlib.h>
-+ #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
-+ #endif
-+
-+ // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
-+ #ifndef STBTT_ifloor
-+ #include <math.h>
-+ #define STBTT_ifloor(x) ((int) floor(x))
-+ #define STBTT_iceil(x) ((int) ceil(x))
-+ #endif
-+
-+ // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
-+ #ifndef STBTT_malloc
-+ #include <malloc.h>
-+ #define STBTT_malloc(x,u) malloc(x)
-+ #define STBTT_free(x,u) free(x)
-+ #endif
-+
-+ #ifndef STBTT_assert
-+ #include <assert.h>
-+ #define STBTT_assert(x) assert(x)
-+ #endif
-+
-+ #ifndef STBTT_strlen
-+ #include <string.h>
-+ #define STBTT_strlen(x) strlen(x)
-+ #endif
-+
-+ #ifndef STBTT_memcpy
-+ #include <memory.h>
-+ #define STBTT_memcpy memcpy
-+ #define STBTT_memset memset
-+ #endif
-+#endif
-+
-+///////////////////////////////////////////////////////////////////////////////
-+///////////////////////////////////////////////////////////////////////////////
-+////
-+//// INTERFACE
-+////
-+////
-+
-+#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
-+#define __STB_INCLUDE_STB_TRUETYPE_H__
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// TEXTURE BAKING API
-+//
-+// If you use this API, you only have to call two functions ever.
-+//
-+
-+typedef struct
-+{
-+ unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
-+ float xoff,yoff,xadvance;
-+} stbtt_bakedchar;
-+
-+extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
-+ float pixel_height, // height of font in pixels
-+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
-+ int first_char, int num_chars, // characters to bake
-+ stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
-+// if return is positive, the first unused row of the bitmap
-+// if return is negative, returns the negative of the number of characters that fit
-+// if return is 0, no characters fit and no rows were used
-+// This uses a very crappy packing.
-+
-+typedef struct
-+{
-+ float x0,y0,s0,t0; // top-left
-+ float x1,y1,s1,t1; // bottom-right
-+} stbtt_aligned_quad;
-+
-+extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above
-+ int char_index, // character to display
-+ float *xpos, float *ypos, // pointers to current position in screen pixel space
-+ stbtt_aligned_quad *q, // output: quad to draw
-+ int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
-+// Call GetBakedQuad with char_index = 'character - first_char', and it
-+// creates the quad you need to draw and advances the current position.
-+// It's inefficient; you might want to c&p it and optimize it.
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// FONT LOADING
-+//
-+//
-+
-+extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
-+// Each .ttf file may have more than one font. Each has a sequential index
-+// number starting from 0. Call this function to get the font offset for a
-+// given index; it returns -1 if the index is out of range. A regular .ttf
-+// file will only define one font and it always be at offset 0, so it will
-+// return '0' for index 0, and -1 for all other indices. You can just skip
-+// this step if you know it's that kind of font.
-+
-+
-+// The following structure is defined publically so you can declare one on
-+// the stack or as a global or etc.
-+typedef struct
-+{
-+ void *userdata;
-+ unsigned char *data; // pointer to .ttf file
-+ int fontstart; // offset of start of font
-+
-+ int numGlyphs; // number of glyphs, needed for range checking
-+
-+ int loca,head,glyf,hhea,hmtx; // table locations as offset from start of .ttf
-+ int index_map; // a cmap mapping for our chosen character encoding
-+ int indexToLocFormat; // format needed to map from glyph index to glyph
-+} stbtt_fontinfo;
-+
-+extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
-+// Given an offset into the file that defines a font, this function builds
-+// the necessary cached info for the rest of the system. You must allocate
-+// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
-+// need to do anything special to free it, because the contents are a pure
-+// cache with no additional data structures. Returns 0 on failure.
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// CHARACTER TO GLYPH-INDEX CONVERSIOn
-+
-+int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
-+// If you're going to perform multiple operations on the same character
-+// and you want a speed-up, call this function with the character you're
-+// going to process, then use glyph-based functions instead of the
-+// codepoint-based functions.
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// CHARACTER PROPERTIES
-+//
-+
-+extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
-+// computes a scale factor to produce a font whose "height" is 'pixels' tall.
-+// Height is measured as the distance from the highest ascender to the lowest
-+// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
-+// and computing:
-+// scale = pixels / (ascent - descent)
-+// so if you prefer to measure height by the ascent only, use a similar calculation.
-+
-+extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
-+// ascent is the coordinate above the baseline the font extends; descent
-+// is the coordinate below the baseline the font extends (i.e. it is typically negative)
-+// lineGap is the spacing between one row's descent and the next row's ascent...
-+// so you should advance the vertical position by "*ascent - *descent + *lineGap"
-+// these are expressed in unscaled coordinates
-+
-+extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
-+// leftSideBearing is the offset from the current horizontal position to the left edge of the character
-+// advanceWidth is the offset from the current horizontal position to the next horizontal position
-+// these are expressed in unscaled coordinates
-+
-+extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
-+// an additional amount to add to the 'advance' value between ch1 and ch2
-+// @TODO; for now always returns 0!
-+
-+extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
-+// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
-+
-+extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
-+extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
-+extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
-+// as above, but takes one or more glyph indices for greater efficiency
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// GLYPH SHAPES (you probably don't need these, but they have to go before
-+// the bitmaps for C declaration-order reasons)
-+//
-+
-+#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
-+ enum {
-+ STBTT_vmove=1,
-+ STBTT_vline,
-+ STBTT_vcurve
-+ };
-+#endif
-+
-+#ifndef stbtt_vertex // you can predefine this to use different values
-+ // (we share this with other code at RAD)
-+ #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
-+ typedef struct
-+ {
-+ stbtt_vertex_type x,y,cx,cy;
-+ unsigned char type,padding;
-+ } stbtt_vertex;
-+#endif
-+
-+extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
-+extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
-+// returns # of vertices and fills *vertices with the pointer to them
-+// these are expressed in "unscaled" coordinates
-+
-+extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
-+// frees the data allocated above
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// BITMAP RENDERING
-+//
-+
-+extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
-+// frees the bitmap allocated below
-+
-+extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
-+// allocates a large-enough single-channel 8bpp bitmap and renders the
-+// specified character/glyph at the specified scale into it, with
-+// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
-+// *width & *height are filled out with the width & height of the bitmap,
-+// which is stored left-to-right, top-to-bottom.
-+//
-+// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
-+
-+extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
-+// the same as above, but you pass in storage for the bitmap in the form
-+// of 'output', with row spacing of 'out_stride' bytes. the bitmap is
-+// clipped to out_w/out_h bytes. call the next function to get the
-+// height and width and positioning info
-+
-+extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-+// get the bbox of the bitmap centered around the glyph origin; so the
-+// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
-+// the bitmap top left is (leftSideBearing*scale,iy0).
-+// (Note that the bitmap uses y-increases-down, but the shape uses
-+// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
-+
-+extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-+extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-+extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
-+
-+//extern void stbtt_get_true_bbox(stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-+
-+// @TODO: don't expose this structure
-+typedef struct
-+{
-+ int w,h,stride;
-+ unsigned char *pixels;
-+} stbtt__bitmap;
-+
-+extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata);
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// Finding the right font...
-+//
-+// You should really just solve this offline, keep your own tables
-+// of what font is what, and don't try to get it out of the .ttf file.
-+// That's because getting it out of the .ttf file is really hard, because
-+// the names in the file can appear in many possible encodings, in many
-+// possible languages, and e.g. if you need a case-insensitive comparison,
-+// the details of that depend on the encoding & language in a complex way
-+// (actually underspecified in truetype, but also gigantic).
-+//
-+// But you can use the provided functions in two possible ways:
-+// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
-+// unicode-encoded names to try to find the font you want;
-+// you can run this before calling stbtt_InitFont()
-+//
-+// stbtt_GetFontNameString() lets you get any of the various strings
-+// from the file yourself and do your own comparisons on them.
-+// You have to have called stbtt_InitFont() first.
-+
-+
-+extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
-+// returns the offset (not index) of the font that matches, or -1 if none
-+// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
-+// if you use any other flag, use a font name like "Arial"; this checks
-+// the 'macStyle' header field; i don't know if fonts set this consistently
-+#define STBTT_MACSTYLE_DONTCARE 0
-+#define STBTT_MACSTYLE_BOLD 1
-+#define STBTT_MACSTYLE_ITALIC 2
-+#define STBTT_MACSTYLE_UNDERSCORE 4
-+#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
-+
-+extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
-+// returns 1/0 whether the first string interpreted as utf8 is identical to
-+// the second string interpreted as big-endian utf16... useful for strings from next func
-+
-+extern char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
-+// returns the string (which may be big-endian double byte, e.g. for unicode)
-+// and puts the length in bytes in *length.
-+//
-+// some of the values for the IDs are below; for more see the truetype spec:
-+// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
-+// http://www.microsoft.com/typography/otspec/name.htm
-+
-+enum { // platformID
-+ STBTT_PLATFORM_ID_UNICODE =0,
-+ STBTT_PLATFORM_ID_MAC =1,
-+ STBTT_PLATFORM_ID_ISO =2,
-+ STBTT_PLATFORM_ID_MICROSOFT =3
-+};
-+
-+enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
-+ STBTT_UNICODE_EID_UNICODE_1_0 =0,
-+ STBTT_UNICODE_EID_UNICODE_1_1 =1,
-+ STBTT_UNICODE_EID_ISO_10646 =2,
-+ STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
-+ STBTT_UNICODE_EID_UNICODE_2_0_FULL=4,
-+};
-+
-+enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
-+ STBTT_MS_EID_SYMBOL =0,
-+ STBTT_MS_EID_UNICODE_BMP =1,
-+ STBTT_MS_EID_SHIFTJIS =2,
-+ STBTT_MS_EID_UNICODE_FULL =10,
-+};
-+
-+enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
-+ STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
-+ STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
-+ STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
-+ STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7,
-+};
-+
-+enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
-+ // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
-+ STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
-+ STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
-+ STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
-+ STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
-+ STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
-+ STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D,
-+};
-+
-+enum { // languageID for STBTT_PLATFORM_ID_MAC
-+ STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
-+ STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
-+ STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
-+ STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
-+ STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
-+ STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
-+ STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19,
-+};
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif // __STB_INCLUDE_STB_TRUETYPE_H__
-+
-+///////////////////////////////////////////////////////////////////////////////
-+///////////////////////////////////////////////////////////////////////////////
-+////
-+//// IMPLEMENTATION
-+////
-+////
-+
-+#ifdef STB_TRUETYPE_IMPLEMENTATION
-+
-+//////////////////////////////////////////////////////////////////////////
-+//
-+// accessors to parse data from file
-+//
-+
-+// on platforms that don't allow misaligned reads, if we want to allow
-+// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
-+
-+#define ttBYTE(p) (* (stbtt_uint8 *) (p))
-+#define ttCHAR(p) (* (stbtt_int8 *) (p))
-+#define ttFixed(p) ttLONG(p)
-+
-+#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
-+
-+ #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
-+ #define ttSHORT(p) (* (stbtt_int16 *) (p))
-+ #define ttULONG(p) (* (stbtt_uint32 *) (p))
-+ #define ttLONG(p) (* (stbtt_int32 *) (p))
-+
-+#else
-+
-+ stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-+ stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-+ stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-+ stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-+
-+#endif
-+
-+#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
-+#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
-+
-+static int stbtt__isfont(const stbtt_uint8 *font)
-+{
-+ // check the version number
-+ if (stbtt_tag(font, "1")) return 1; // TrueType 1
-+ if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
-+ if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
-+ if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
-+ return 0;
-+}
-+
-+// @OPTIMIZE: binary search
-+static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
-+{
-+ stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
-+ stbtt_uint32 tabledir = fontstart + 12;
-+ stbtt_int32 i;
-+ for (i=0; i < num_tables; ++i) {
-+ stbtt_uint32 loc = tabledir + 16*i;
-+ if (stbtt_tag(data+loc+0, tag))
-+ return ttULONG(data+loc+8);
-+ }
-+ return 0;
-+}
-+
-+int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index)
-+{
-+ // if it's just a font, there's only one valid index
-+ if (stbtt__isfont(font_collection))
-+ return index == 0 ? 0 : -1;
-+
-+ // check if it's a TTC
-+ if (stbtt_tag(font_collection, "ttcf")) {
-+ // version 1?
-+ if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
-+ stbtt_int32 n = ttLONG(font_collection+8);
-+ if (index >= n)
-+ return -1;
-+ return ttULONG(font_collection+12+index*14);
-+ }
-+ }
-+ return -1;
-+}
-+
-+int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart)
-+{
-+ stbtt_uint8 *data = (stbtt_uint8 *) data2;
-+ stbtt_uint32 cmap, t;
-+ stbtt_int32 i,numTables;
-+
-+ info->data = data;
-+ info->fontstart = fontstart;
-+
-+ cmap = stbtt__find_table(data, fontstart, "cmap");
-+ info->loca = stbtt__find_table(data, fontstart, "loca");
-+ info->head = stbtt__find_table(data, fontstart, "head");
-+ info->glyf = stbtt__find_table(data, fontstart, "glyf");
-+ info->hhea = stbtt__find_table(data, fontstart, "hhea");
-+ info->hmtx = stbtt__find_table(data, fontstart, "hmtx");
-+ if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
-+ return 0;
-+
-+ t = stbtt__find_table(data, fontstart, "maxp");
-+ if (t)
-+ info->numGlyphs = ttUSHORT(data+t+4);
-+ else
-+ info->numGlyphs = 0xffff;
-+
-+ // find a cmap encoding table we understand *now* to avoid searching
-+ // later. (todo: could make this installable)
-+ // the same regardless of glyph.
-+ numTables = ttUSHORT(data + cmap + 2);
-+ info->index_map = 0;
-+ for (i=0; i < numTables; ++i) {
-+ stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
-+ // find an encoding we understand:
-+ switch(ttUSHORT(data+encoding_record)) {
-+ case STBTT_PLATFORM_ID_MICROSOFT:
-+ switch (ttUSHORT(data+encoding_record+2)) {
-+ case STBTT_MS_EID_UNICODE_BMP:
-+ case STBTT_MS_EID_UNICODE_FULL:
-+ // MS/Unicode
-+ info->index_map = cmap + ttULONG(data+encoding_record+4);
-+ break;
-+ }
-+ break;
-+ }
-+ }
-+ if (info->index_map == 0)
-+ return 0;
-+
-+ info->indexToLocFormat = ttUSHORT(data+info->head + 50);
-+ return 1;
-+}
-+
-+int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
-+{
-+ stbtt_uint8 *data = info->data;
-+ stbtt_uint32 index_map = info->index_map;
-+
-+ stbtt_uint16 format = ttUSHORT(data + index_map + 0);
-+ if (format == 0) { // apple byte encoding
-+ stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
-+ if (unicode_codepoint < bytes-6)
-+ return ttBYTE(data + index_map + 6 + unicode_codepoint);
-+ return 0;
-+ } else if (format == 6) {
-+ stbtt_uint32 first = ttUSHORT(data + index_map + 6);
-+ stbtt_uint32 count = ttUSHORT(data + index_map + 8);
-+ if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
-+ return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
-+ return 0;
-+ } else if (format == 2) {
-+ STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
-+ return 0;
-+ } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
-+ stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
-+ stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
-+ stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
-+ stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
-+ stbtt_uint16 item, offset, start, end;
-+
-+ // do a binary search of the segments
-+ stbtt_uint32 endCount = index_map + 14;
-+ stbtt_uint32 search = endCount;
-+
-+ if (unicode_codepoint > 0xffff)
-+ return 0;
-+
-+ // they lie from endCount .. endCount + segCount
-+ // but searchRange is the nearest power of two, so...
-+ if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
-+ search += rangeShift*2;
-+
-+ // now decrement to bias correctly to find smallest
-+ search -= 2;
-+ while (entrySelector) {
-+ stbtt_uint16 start, end;
-+ searchRange >>= 1;
-+ start = ttUSHORT(data + search + 2 + segcount*2 + 2);
-+ end = ttUSHORT(data + search + 2);
-+ start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
-+ end = ttUSHORT(data + search + searchRange*2);
-+ if (unicode_codepoint > end)
-+ search += searchRange*2;
-+ --entrySelector;
-+ }
-+ search += 2;
-+
-+ item = (stbtt_uint16) ((search - endCount) >> 1);
-+
-+ STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
-+ start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
-+ end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
-+ if (unicode_codepoint < start)
-+ return 0;
-+
-+ offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
-+ if (offset == 0)
-+ return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item);
-+
-+ return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
-+ } else if (format == 12) {
-+ stbtt_uint16 ngroups = ttUSHORT(data+index_map+6);
-+ stbtt_int32 low,high;
-+ low = 0; high = (stbtt_int32)ngroups;
-+ // Binary search the right group.
-+ while (low <= high) {
-+ stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
-+ stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
-+ stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
-+ if ((stbtt_uint32) unicode_codepoint < start_char)
-+ high = mid-1;
-+ else if ((stbtt_uint32) unicode_codepoint > end_char)
-+ low = mid+1;
-+ else {
-+ stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
-+ return start_glyph + unicode_codepoint-start_char;
-+ }
-+ }
-+ return 0; // not found
-+ }
-+ // @TODO
-+ STBTT_assert(0);
-+ return 0;
-+}
-+
-+int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
-+{
-+ return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
-+}
-+
-+static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int16 x, stbtt_int16 y, stbtt_int16 cx, stbtt_int16 cy)
-+{
-+ v->type = type;
-+ v->x = x;
-+ v->y = y;
-+ v->cx = cx;
-+ v->cy = cy;
-+}
-+
-+static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
-+{
-+ int g1,g2;
-+
-+ if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
-+ if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
-+
-+ if (info->indexToLocFormat == 0) {
-+ g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
-+ g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
-+ } else {
-+ g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
-+ g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
-+ }
-+
-+ return g1==g2 ? -1 : g1; // if length is 0, return -1
-+}
-+
-+int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
-+{
-+ int g = stbtt__GetGlyfOffset(info, glyph_index);
-+ if (g < 0) return 0;
-+
-+ if (x0) *x0 = ttSHORT(info->data + g + 2);
-+ if (y0) *y0 = ttSHORT(info->data + g + 4);
-+ if (x1) *x1 = ttSHORT(info->data + g + 6);
-+ if (y1) *y1 = ttSHORT(info->data + g + 8);
-+ return 1;
-+}
-+
-+int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
-+{
-+ return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
-+}
-+
-+int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-+{
-+ stbtt_int16 numberOfContours;
-+ stbtt_uint8 *endPtsOfContours;
-+ stbtt_uint8 *data = info->data;
-+ stbtt_vertex *vertices=0;
-+ int num_vertices=0;
-+ int g = stbtt__GetGlyfOffset(info, glyph_index);
-+
-+ *pvertices = NULL;
-+
-+ if (g < 0) return 0;
-+
-+ numberOfContours = ttSHORT(data + g);
-+
-+ if (numberOfContours > 0) {
-+ stbtt_uint8 flags=0,flagcount;
-+ stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;
-+ stbtt_int16 x,y,cx,cy,sx,sy;
-+ stbtt_uint8 *points;
-+ endPtsOfContours = (data + g + 10);
-+ ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
-+ points = data + g + 10 + numberOfContours * 2 + 2 + ins;
-+
-+ n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
-+
-+ m = n + numberOfContours; // a loose bound on how many vertices we might need
-+ vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
-+ if (vertices == 0)
-+ return 0;
-+
-+ next_move = 0;
-+ flagcount=0;
-+
-+ // in first pass, we load uninterpreted data into the allocated array
-+ // above, shifted to the end of the array so we won't overwrite it when
-+ // we create our final data starting from the front
-+
-+ off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
-+
-+ // first load flags
-+
-+ for (i=0; i < n; ++i) {
-+ if (flagcount == 0) {
-+ flags = *points++;
-+ if (flags & 8)
-+ flagcount = *points++;
-+ } else
-+ --flagcount;
-+ vertices[off+i].type = flags;
-+ }
-+
-+ // now load x coordinates
-+ x=0;
-+ for (i=0; i < n; ++i) {
-+ flags = vertices[off+i].type;
-+ if (flags & 2) {
-+ stbtt_int16 dx = *points++;
-+ x += (flags & 16) ? dx : -dx; // ???
-+ } else {
-+ if (!(flags & 16)) {
-+ x = x + (stbtt_int16) (points[0]*256 + points[1]);
-+ points += 2;
-+ }
-+ }
-+ vertices[off+i].x = x;
-+ }
-+
-+ // now load y coordinates
-+ y=0;
-+ for (i=0; i < n; ++i) {
-+ flags = vertices[off+i].type;
-+ if (flags & 4) {
-+ stbtt_int16 dy = *points++;
-+ y += (flags & 32) ? dy : -dy; // ???
-+ } else {
-+ if (!(flags & 32)) {
-+ y = y + (stbtt_int16) (points[0]*256 + points[1]);
-+ points += 2;
-+ }
-+ }
-+ vertices[off+i].y = y;
-+ }
-+
-+ // now convert them to our format
-+ num_vertices=0;
-+ sx = sy = cx = cy = 0;
-+ for (i=0; i < n; ++i) {
-+ flags = vertices[off+i].type;
-+ x = (stbtt_int16) vertices[off+i].x;
-+ y = (stbtt_int16) vertices[off+i].y;
-+ if (next_move == i) {
-+ // when we get to the end, we have to close the shape explicitly
-+ if (i != 0) {
-+ if (was_off)
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
-+ else
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
-+ }
-+
-+ // now start the new one
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,x,y,0,0);
-+ next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
-+ ++j;
-+ was_off = 0;
-+ sx = x;
-+ sy = y;
-+ } else {
-+ if (!(flags & 1)) { // if it's a curve
-+ if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
-+ cx = x;
-+ cy = y;
-+ was_off = 1;
-+ } else {
-+ if (was_off)
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
-+ else
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
-+ was_off = 0;
-+ }
-+ }
-+ }
-+ if (i != 0) {
-+ if (was_off)
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
-+ else
-+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
-+ }
-+ } else if (numberOfContours == -1) {
-+ // Compound shapes.
-+ int more = 1;
-+ stbtt_uint8 *comp = data + g + 10;
-+ num_vertices = 0;
-+ vertices = 0;
-+ while (more) {
-+ stbtt_uint16 flags, gidx;
-+ int comp_num_verts = 0, i;
-+ stbtt_vertex *comp_verts = 0, *tmp = 0;
-+ float mtx[6] = {1,0,0,1,0,0}, m, n;
-+
-+ flags = ttSHORT(comp); comp+=2;
-+ gidx = ttSHORT(comp); comp+=2;
-+
-+ if (flags & 2) { // XY values
-+ if (flags & 1) { // shorts
-+ mtx[4] = ttSHORT(comp); comp+=2;
-+ mtx[5] = ttSHORT(comp); comp+=2;
-+ } else {
-+ mtx[4] = ttCHAR(comp); comp+=1;
-+ mtx[5] = ttCHAR(comp); comp+=1;
-+ }
-+ }
-+ else {
-+ // @TODO handle matching point
-+ STBTT_assert(0);
-+ }
-+ if (flags & (1<<3)) { // WE_HAVE_A_SCALE
-+ mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-+ mtx[1] = mtx[2] = 0;
-+ } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
-+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-+ mtx[1] = mtx[2] = 0;
-+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-+ } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
-+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
-+ mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
-+ mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
-+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
-+ }
-+
-+ // Find transformation scales.
-+ m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
-+ n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
-+
-+ // Get indexed glyph.
-+ comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
-+ if (comp_num_verts > 0) {
-+ // Transform vertices.
-+ for (i = 0; i < comp_num_verts; ++i) {
-+ stbtt_vertex* v = &comp_verts[i];
-+ stbtt_vertex_type x,y;
-+ x=v->x; y=v->y;
-+ v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-+ v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-+ x=v->cx; y=v->cy;
-+ v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
-+ v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
-+ }
-+ // Append vertices.
-+ tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
-+ if (!tmp) {
-+ if (vertices) STBTT_free(vertices, info->userdata);
-+ if (comp_verts) STBTT_free(comp_verts, info->userdata);
-+ return 0;
-+ }
-+ if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
-+ memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
-+ if (vertices) STBTT_free(vertices, info->userdata);
-+ vertices = tmp;
-+ STBTT_free(comp_verts, info->userdata);
-+ num_vertices += comp_num_verts;
-+ }
-+ // More components ?
-+ more = flags & (1<<5);
-+ }
-+ } else if (numberOfContours < 0) {
-+ // @TODO other compound variations?
-+ STBTT_assert(0);
-+ } else {
-+ // numberOfCounters == 0, do nothing
-+ }
-+
-+ *pvertices = vertices;
-+ return num_vertices;
-+}
-+
-+void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
-+{
-+ stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
-+ if (glyph_index < numOfLongHorMetrics) {
-+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
-+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
-+ } else {
-+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
-+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
-+ }
-+}
-+
-+int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * /*info*/, int /*glyph1*/, int /*glyph2*/)
-+{
-+ return 0;
-+}
-+
-+int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * /*info*/, int /*ch1*/, int /*ch2*/)
-+{
-+ return 0;
-+}
-+
-+void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
-+{
-+ stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
-+}
-+
-+void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
-+{
-+ if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
-+ if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
-+ if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
-+}
-+
-+float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
-+{
-+ int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
-+ return (float) height / fheight;
-+}
-+
-+void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
-+{
-+ STBTT_free(v, info->userdata);
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// antialiasing software rasterizer
-+//
-+
-+void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-+{
-+ int x0,y0,x1,y1;
-+ if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1))
-+ x0=y0=x1=y1=0; // e.g. space character
-+ // now move to integral bboxes (treating pixels as little squares, what pixels get touched)?
-+ if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x);
-+ if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y);
-+ if (ix1) *ix1 = STBTT_iceil (x1 * scale_x);
-+ if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y);
-+}
-+
-+void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-+{
-+ stbtt_GetGlyphBitmapBox(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y, ix0,iy0,ix1,iy1);
-+}
-+
-+typedef struct stbtt__edge {
-+ float x0,y0, x1,y1;
-+ int invert;
-+} stbtt__edge;
-+
-+typedef struct stbtt__active_edge
-+{
-+ int x,dx;
-+ float ey;
-+ struct stbtt__active_edge *next;
-+ int valid;
-+} stbtt__active_edge;
-+
-+#define FIXSHIFT 10
-+#define FIX (1 << FIXSHIFT)
-+#define FIXMASK (FIX-1)
-+
-+static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata)
-+{
-+ stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!!
-+ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
-+ STBTT_assert(e->y0 <= start_point);
-+ if (!z) return z;
-+ // round dx down to avoid going too far
-+ if (dxdy < 0)
-+ z->dx = -STBTT_ifloor(FIX * -dxdy);
-+ else
-+ z->dx = STBTT_ifloor(FIX * dxdy);
-+ z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
-+ z->x -= off_x * FIX;
-+ z->ey = e->y1;
-+ z->next = 0;
-+ z->valid = e->invert ? 1 : -1;
-+ return z;
-+}
-+
-+// note: this routine clips fills that extend off the edges... ideally this
-+// wouldn't happen, but it could happen if the truetype glyph bounding boxes
-+// are wrong, or if the user supplies a too-small bitmap
-+static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
-+{
-+ // non-zero winding fill
-+ int x0=0, w=0;
-+
-+ while (e) {
-+ if (w == 0) {
-+ // if we're currently at zero, we need to record the edge start point
-+ x0 = e->x; w += e->valid;
-+ } else {
-+ int x1 = e->x; w += e->valid;
-+ // if we went to zero, we need to draw
-+ if (w == 0) {
-+ int i = x0 >> FIXSHIFT;
-+ int j = x1 >> FIXSHIFT;
-+
-+ if (i < len && j >= 0) {
-+ if (i == j) {
-+ // x0,x1 are the same pixel, so compute combined coverage
-+ scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
-+ } else {
-+ if (i >= 0) // add antialiasing for x0
-+ scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
-+ else
-+ i = -1; // clip
-+
-+ if (j < len) // add antialiasing for x1
-+ scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
-+ else
-+ j = len; // clip
-+
-+ for (++i; i < j; ++i) // fill pixels between x0 and x1
-+ scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
-+ }
-+ }
-+ }
-+ }
-+
-+ e = e->next;
-+ }
-+}
-+
-+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
-+{
-+ stbtt__active_edge *active = NULL;
-+ int y,j=0;
-+ int max_weight = (255 / vsubsample); // weight per vertical scanline
-+ int s; // vertical subsample index
-+ unsigned char scanline_data[512], *scanline;
-+
-+ if (result->w > 512)
-+ scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
-+ else
-+ scanline = scanline_data;
-+
-+ y = off_y * vsubsample;
-+ e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
-+
-+ while (j < result->h) {
-+ STBTT_memset(scanline, 0, result->w);
-+ for (s=0; s < vsubsample; ++s) {
-+ // find center of pixel for this scanline
-+ float scan_y = y + 0.5f;
-+ stbtt__active_edge **step = &active;
-+
-+ // update all active edges;
-+ // remove all active edges that terminate before the center of this scanline
-+ while (*step) {
-+ stbtt__active_edge * z = *step;
-+ if (z->ey <= scan_y) {
-+ *step = z->next; // delete from list
-+ STBTT_assert(z->valid);
-+ z->valid = 0;
-+ STBTT_free(z, userdata);
-+ } else {
-+ z->x += z->dx; // advance to position for current scanline
-+ step = &((*step)->next); // advance through list
-+ }
-+ }
-+
-+ // resort the list if needed
-+ for(;;) {
-+ int changed=0;
-+ step = &active;
-+ while (*step && (*step)->next) {
-+ if ((*step)->x > (*step)->next->x) {
-+ stbtt__active_edge *t = *step;
-+ stbtt__active_edge *q = t->next;
-+
-+ t->next = q->next;
-+ q->next = t;
-+ *step = q;
-+ changed = 1;
-+ }
-+ step = &(*step)->next;
-+ }
-+ if (!changed) break;
-+ }
-+
-+ // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
-+ while (e->y0 <= scan_y) {
-+ if (e->y1 > scan_y) {
-+ stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
-+ // find insertion point
-+ if (active == NULL)
-+ active = z;
-+ else if (z->x < active->x) {
-+ // insert at front
-+ z->next = active;
-+ active = z;
-+ } else {
-+ // find thing to insert AFTER
-+ stbtt__active_edge *p = active;
-+ while (p->next && p->next->x < z->x)
-+ p = p->next;
-+ // at this point, p->next->x is NOT < z->x
-+ z->next = p->next;
-+ p->next = z;
-+ }
-+ }
-+ ++e;
-+ }
-+
-+ // now process all active edges in XOR fashion
-+ if (active)
-+ stbtt__fill_active_edges(scanline, result->w, active, max_weight);
-+
-+ ++y;
-+ }
-+ STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
-+ ++j;
-+ }
-+
-+ while (active) {
-+ stbtt__active_edge *z = active;
-+ active = active->next;
-+ STBTT_free(z, userdata);
-+ }
-+
-+ if (scanline != scanline_data)
-+ STBTT_free(scanline, userdata);
-+}
-+
-+static int stbtt__edge_compare(const void *p, const void *q)
-+{
-+ stbtt__edge *a = (stbtt__edge *) p;
-+ stbtt__edge *b = (stbtt__edge *) q;
-+
-+ if (a->y0 < b->y0) return -1;
-+ if (a->y0 > b->y0) return 1;
-+ return 0;
-+}
-+
-+typedef struct
-+{
-+ float x,y;
-+} stbtt__point;
-+
-+static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata)
-+{
-+ float y_scale_inv = invert ? -scale_y : scale_y;
-+ stbtt__edge *e;
-+ int n,i,j,k,m;
-+ int vsubsample = result->h < 8 ? 15 : 5;
-+ // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
-+
-+ // now we have to blow out the windings into explicit edge lists
-+ n = 0;
-+ for (i=0; i < windings; ++i)
-+ n += wcount[i];
-+
-+ e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
-+ if (e == 0) return;
-+ n = 0;
-+
-+ m=0;
-+ for (i=0; i < windings; ++i) {
-+ stbtt__point *p = pts + m;
-+ m += wcount[i];
-+ j = wcount[i]-1;
-+ for (k=0; k < wcount[i]; j=k++) {
-+ int a=k,b=j;
-+ // skip the edge if horizontal
-+ if (p[j].y == p[k].y)
-+ continue;
-+ // add edge from j to k to the list
-+ e[n].invert = 0;
-+ if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
-+ e[n].invert = 1;
-+ a=j,b=k;
-+ }
-+ e[n].x0 = p[a].x * scale_x;
-+ e[n].y0 = p[a].y * y_scale_inv * vsubsample;
-+ e[n].x1 = p[b].x * scale_x;
-+ e[n].y1 = p[b].y * y_scale_inv * vsubsample;
-+ ++n;
-+ }
-+ }
-+
-+ // now sort the edges by their highest point (should snap to integer, and then by x)
-+ STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
-+
-+ // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
-+ stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
-+
-+ STBTT_free(e, userdata);
-+}
-+
-+static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
-+{
-+ if (!points) return; // during first pass, it's unallocated
-+ points[n].x = x;
-+ points[n].y = y;
-+}
-+
-+// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
-+static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
-+{
-+ // midpoint
-+ float mx = (x0 + 2*x1 + x2)/4;
-+ float my = (y0 + 2*y1 + y2)/4;
-+ // versus directly drawn line
-+ float dx = (x0+x2)/2 - mx;
-+ float dy = (y0+y2)/2 - my;
-+ if (n > 16) // 65536 segments on one curve better be enough!
-+ return 1;
-+ if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
-+ stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
-+ stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
-+ } else {
-+ stbtt__add_point(points, *num_points,x2,y2);
-+ *num_points = *num_points+1;
-+ }
-+ return 1;
-+}
-+
-+// returns number of contours
-+stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
-+{
-+ stbtt__point *points=0;
-+ int num_points=0;
-+
-+ float objspace_flatness_squared = objspace_flatness * objspace_flatness;
-+ int i,n=0,start=0, pass;
-+
-+ // count how many "moves" there are to get the contour count
-+ for (i=0; i < num_verts; ++i)
-+ if (vertices[i].type == STBTT_vmove)
-+ ++n;
-+
-+ *num_contours = n;
-+ if (n == 0) return 0;
-+
-+ *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
-+
-+ if (*contour_lengths == 0) {
-+ *num_contours = 0;
-+ return 0;
-+ }
-+
-+ // make two passes through the points so we don't need to realloc
-+ for (pass=0; pass < 2; ++pass) {
-+ float x=0,y=0;
-+ if (pass == 1) {
-+ points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
-+ if (points == NULL) goto error;
-+ }
-+ num_points = 0;
-+ n= -1;
-+ for (i=0; i < num_verts; ++i) {
-+ switch (vertices[i].type) {
-+ case STBTT_vmove:
-+ // start the next contour
-+ if (n >= 0)
-+ (*contour_lengths)[n] = num_points - start;
-+ ++n;
-+ start = num_points;
-+
-+ x = vertices[i].x, y = vertices[i].y;
-+ stbtt__add_point(points, num_points++, x,y);
-+ break;
-+ case STBTT_vline:
-+ x = vertices[i].x, y = vertices[i].y;
-+ stbtt__add_point(points, num_points++, x, y);
-+ break;
-+ case STBTT_vcurve:
-+ stbtt__tesselate_curve(points, &num_points, x,y,
-+ vertices[i].cx, vertices[i].cy,
-+ vertices[i].x, vertices[i].y,
-+ objspace_flatness_squared, 0);
-+ x = vertices[i].x, y = vertices[i].y;
-+ break;
-+ }
-+ }
-+ (*contour_lengths)[n] = num_points - start;
-+ }
-+
-+ return points;
-+error:
-+ STBTT_free(points, userdata);
-+ STBTT_free(*contour_lengths, userdata);
-+ *contour_lengths = 0;
-+ *num_contours = 0;
-+ return NULL;
-+}
-+
-+void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata)
-+{
-+ float scale = scale_x > scale_y ? scale_y : scale_x;
-+ int winding_count, *winding_lengths;
-+ stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
-+ if (windings) {
-+ stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata);
-+ STBTT_free(winding_lengths, userdata);
-+ STBTT_free(windings, userdata);
-+ }
-+}
-+
-+void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
-+{
-+ STBTT_free(bitmap, userdata);
-+}
-+
-+unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-+{
-+ int ix0,iy0,ix1,iy1;
-+ stbtt__bitmap gbm;
-+ stbtt_vertex *vertices;
-+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-+
-+ if (scale_x == 0) scale_x = scale_y;
-+ if (scale_y == 0) {
-+ if (scale_x == 0) return NULL;
-+ scale_y = scale_x;
-+ }
-+
-+ stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
-+
-+ // now we get the size
-+ gbm.w = (ix1 - ix0);
-+ gbm.h = (iy1 - iy0);
-+ gbm.pixels = NULL; // in case we error
-+
-+ if (width ) *width = gbm.w;
-+ if (height) *height = gbm.h;
-+ if (xoff ) *xoff = ix0;
-+ if (yoff ) *yoff = iy0;
-+
-+ if (gbm.w && gbm.h) {
-+ gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
-+ if (gbm.pixels) {
-+ gbm.stride = gbm.w;
-+
-+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata);
-+ }
-+ }
-+ STBTT_free(vertices, info->userdata);
-+ return gbm.pixels;
-+}
-+
-+void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
-+{
-+ int ix0,iy0;
-+ stbtt_vertex *vertices;
-+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-+ stbtt__bitmap gbm;
-+
-+ stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,0,0);
-+ gbm.pixels = output;
-+ gbm.w = out_w;
-+ gbm.h = out_h;
-+ gbm.stride = out_stride;
-+
-+ if (gbm.w && gbm.h)
-+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata);
-+
-+ STBTT_free(vertices, info->userdata);
-+}
-+
-+unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-+{
-+ return stbtt_GetGlyphBitmap(info, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
-+}
-+
-+void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
-+{
-+ stbtt_MakeGlyphBitmap(info, output, out_w, out_h, out_stride, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint));
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// bitmap baking
-+//
-+// This is SUPER-SHITTY packing to keep source code small
-+
-+extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
-+ float pixel_height, // height of font in pixels
-+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
-+ int first_char, int num_chars, // characters to bake
-+ stbtt_bakedchar *chardata)
-+{
-+ float scale;
-+ int x,y,bottom_y, i;
-+ stbtt_fontinfo f;
-+ stbtt_InitFont(&f, data, offset);
-+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
-+ x=y=1;
-+ bottom_y = 1;
-+
-+ scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
-+
-+ for (i=0; i < num_chars; ++i) {
-+ int advance, lsb, x0,y0,x1,y1,gw,gh;
-+ int g = stbtt_FindGlyphIndex(&f, first_char + i);
-+ stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
-+ stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
-+ gw = x1-x0;
-+ gh = y1-y0;
-+ if (x + gw + 1 >= pw)
-+ y = bottom_y, x = 1; // advance to next row
-+ if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
-+ return -i;
-+ STBTT_assert(x+gw < pw);
-+ STBTT_assert(y+gh < ph);
-+ stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
-+ chardata[i].x0 = (stbtt_int16) x;
-+ chardata[i].y0 = (stbtt_int16) y;
-+ chardata[i].x1 = (stbtt_int16) (x + gw);
-+ chardata[i].y1 = (stbtt_int16) (y + gh);
-+ chardata[i].xadvance = scale * advance;
-+ chardata[i].xoff = (float) x0;
-+ chardata[i].yoff = (float) y0;
-+ x = x + gw + 2;
-+ if (y+gh+2 > bottom_y)
-+ bottom_y = y+gh+2;
-+ }
-+ return bottom_y;
-+}
-+
-+void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
-+{
-+ float d3d_bias = opengl_fillrule ? 0 : -0.5f;
-+ float ipw = 1.0f / pw, iph = 1.0f / ph;
-+ stbtt_bakedchar *b = chardata + char_index;
-+ int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
-+ int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
-+
-+ q->x0 = round_x + d3d_bias;
-+ q->y0 = round_y + d3d_bias;
-+ q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
-+ q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
-+
-+ q->s0 = b->x0 * ipw;
-+ q->t0 = b->y0 * ipw;
-+ q->s1 = b->x1 * iph;
-+ q->t1 = b->y1 * iph;
-+
-+ *xpos += b->xadvance;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+//
-+// font name matching -- recommended not to use this
-+//
-+
-+// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
-+static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
-+{
-+ stbtt_int32 i=0;
-+
-+ // convert utf16 to utf8 and compare the results while converting
-+ while (len2) {
-+ stbtt_uint16 ch = s2[0]*256 + s2[1];
-+ if (ch < 0x80) {
-+ if (i >= len1) return -1;
-+ if (s1[i++] != ch) return -1;
-+ } else if (ch < 0x800) {
-+ if (i+1 >= len1) return -1;
-+ if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
-+ if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
-+ } else if (ch >= 0xd800 && ch < 0xdc00) {
-+ stbtt_uint32 c;
-+ stbtt_uint16 ch2 = s2[2]*256 + s2[3];
-+ if (i+3 >= len1) return -1;
-+ c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
-+ if (s1[i++] != 0xf0 + (c >> 18)) return -1;
-+ if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
-+ if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
-+ if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
-+ s2 += 2; // plus another 2 below
-+ len2 -= 2;
-+ } else if (ch >= 0xdc00 && ch < 0xe000) {
-+ return -1;
-+ } else {
-+ if (i+2 >= len1) return -1;
-+ if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
-+ if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
-+ if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
-+ }
-+ s2 += 2;
-+ len2 -= 2;
-+ }
-+ return i;
-+}
-+
-+int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
-+{
-+ return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
-+}
-+
-+// returns results in whatever encoding you request... but note that 2-byte encodings
-+// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
-+char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
-+{
-+ stbtt_int32 i,count,stringOffset;
-+ stbtt_uint8 *fc = font->data;
-+ stbtt_uint32 offset = font->fontstart;
-+ stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
-+ if (!nm) return NULL;
-+
-+ count = ttUSHORT(fc+nm+2);
-+ stringOffset = nm + ttUSHORT(fc+nm+4);
-+ for (i=0; i < count; ++i) {
-+ stbtt_uint32 loc = nm + 6 + 12 * i;
-+ if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
-+ && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
-+ *length = ttUSHORT(fc+loc+8);
-+ return (char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
-+ }
-+ }
-+ return NULL;
-+}
-+
-+static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
-+{
-+ stbtt_int32 i;
-+ stbtt_int32 count = ttUSHORT(fc+nm+2);
-+ stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
-+
-+ for (i=0; i < count; ++i) {
-+ stbtt_uint32 loc = nm + 6 + 12 * i;
-+ stbtt_int32 id = ttUSHORT(fc+loc+6);
-+ if (id == target_id) {
-+ // find the encoding
-+ stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
-+
-+ // is this a Unicode encoding?
-+ if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
-+ stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10);
-+
-+ // check if there's a prefix match
-+ stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
-+ if (matchlen >= 0) {
-+ // check for target_id+1 immediately following, with same encoding & language
-+ 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) {
-+ stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10);
-+ if (slen == 0) {
-+ if (matchlen == nlen)
-+ return 1;
-+ } else if (matchlen < nlen && name[matchlen] == ' ') {
-+ ++matchlen;
-+ if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
-+ return 1;
-+ }
-+ } else {
-+ // if nothing immediately following
-+ if (matchlen == nlen)
-+ return 1;
-+ }
-+ }
-+ }
-+
-+ // @TODO handle other encodings
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
-+{
-+ stbtt_int32 nlen = STBTT_strlen((char *) name);
-+ stbtt_uint32 nm,hd;
-+ if (!stbtt__isfont(fc+offset)) return 0;
-+
-+ // check italics/bold/underline flags in macStyle...
-+ if (flags) {
-+ hd = stbtt__find_table(fc, offset, "head");
-+ if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
-+ }
-+
-+ nm = stbtt__find_table(fc, offset, "name");
-+ if (!nm) return 0;
-+
-+ if (flags) {
-+ // if we checked the macStyle flags, then just check the family and ignore the subfamily
-+ if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
-+ if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
-+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
-+ } else {
-+ if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
-+ if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
-+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags)
-+{
-+ stbtt_int32 i;
-+ for (i=0;;++i) {
-+ stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
-+ if (off < 0) return off;
-+ if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
-+ return off;
-+ }
-+}
-+
-+#endif // STB_TRUETYPE_IMPLEMENTATION
+--
+1.9.0.msysgit.0
+