aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjackpoz <giacomopoz@gmail.com>2014-06-20 22:13:10 +0200
committerjackpoz <giacomopoz@gmail.com>2014-06-20 23:30:44 +0200
commit0892c71a16a1fc01822946bdb006eff5bdec9315 (patch)
tree2f72fb60be5aab72ad73b2bd9b244db4b9830de5
parentffcdcea13a0958b7db68312749d28eadf218ce70 (diff)
Core/Dependencies: Clean up recastnavigation folder
Remove old files from recastnavigation folder and update the structure to the same of https://github.com/memononen/recastnavigation/ to allow easier updates.
-rw-r--r--dep/PackageList.txt4
-rw-r--r--dep/recastnavigation/Detour/CMakeLists.txt13
-rw-r--r--dep/recastnavigation/Detour/Include/DetourAlloc.h (renamed from dep/recastnavigation/Detour/DetourAlloc.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourAssert.h (renamed from dep/recastnavigation/Detour/DetourAssert.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourCommon.h (renamed from dep/recastnavigation/Detour/DetourCommon.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourNavMesh.h (renamed from dep/recastnavigation/Detour/DetourNavMesh.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourNavMeshBuilder.h (renamed from dep/recastnavigation/Detour/DetourNavMeshBuilder.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h (renamed from dep/recastnavigation/Detour/DetourNavMeshQuery.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourNode.h (renamed from dep/recastnavigation/Detour/DetourNode.h)0
-rw-r--r--dep/recastnavigation/Detour/Include/DetourStatus.h (renamed from dep/recastnavigation/Detour/DetourStatus.h)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourAlloc.cpp (renamed from dep/recastnavigation/Detour/DetourAlloc.cpp)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourCommon.cpp (renamed from dep/recastnavigation/Detour/DetourCommon.cpp)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourNavMesh.cpp (renamed from dep/recastnavigation/Detour/DetourNavMesh.cpp)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourNavMeshBuilder.cpp (renamed from dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp (renamed from dep/recastnavigation/Detour/DetourNavMeshQuery.cpp)0
-rw-r--r--dep/recastnavigation/Detour/Source/DetourNode.cpp (renamed from dep/recastnavigation/Detour/DetourNode.cpp)0
-rw-r--r--dep/recastnavigation/Readme.txt76
-rw-r--r--dep/recastnavigation/Recast/CMakeLists.txt22
-rw-r--r--dep/recastnavigation/Recast/Include/Recast.h (renamed from dep/recastnavigation/Recast/Recast.h)0
-rw-r--r--dep/recastnavigation/Recast/Include/RecastAlloc.h (renamed from dep/recastnavigation/Recast/RecastAlloc.h)0
-rw-r--r--dep/recastnavigation/Recast/Include/RecastAssert.h (renamed from dep/recastnavigation/Recast/RecastAssert.h)0
-rw-r--r--dep/recastnavigation/Recast/Source/Recast.cpp (renamed from dep/recastnavigation/Recast/Recast.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastAlloc.cpp (renamed from dep/recastnavigation/Recast/RecastAlloc.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastArea.cpp (renamed from dep/recastnavigation/Recast/RecastArea.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastContour.cpp (renamed from dep/recastnavigation/Recast/RecastContour.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastFilter.cpp (renamed from dep/recastnavigation/Recast/RecastFilter.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastLayers.cpp (renamed from dep/recastnavigation/Recast/RecastLayers.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastMesh.cpp (renamed from dep/recastnavigation/Recast/RecastMesh.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastMeshDetail.cpp (renamed from dep/recastnavigation/Recast/RecastMeshDetail.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastRasterization.cpp (renamed from dep/recastnavigation/Recast/RecastRasterization.cpp)0
-rw-r--r--dep/recastnavigation/Recast/Source/RecastRegion.cpp (renamed from dep/recastnavigation/Recast/RecastRegion.cpp)0
-rw-r--r--dep/recastnavigation/TODO.txt20
-rw-r--r--dep/recastnavigation/recast_hotfix1.diff13
-rw-r--r--dep/recastnavigation/recast_hotfix2.diff38
-rw-r--r--dep/recastnavigation/recastnavigation.diff4066
-rw-r--r--src/server/collision/CMakeLists.txt1
-rw-r--r--src/server/game/CMakeLists.txt2
-rw-r--r--src/server/scripts/CMakeLists.txt2
-rw-r--r--src/server/worldserver/CMakeLists.txt1
-rw-r--r--src/tools/mmaps_generator/CMakeLists.txt2
40 files changed, 4096 insertions, 164 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index e4ecd80d08f..cfc0ae9af59 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -41,5 +41,5 @@ gSOAP (a portable development toolkit for C and C++ XML Web services and XML dat
Version: 2.8.10
recastnavigation (Recast is state of the art navigation mesh construction toolset for games)
- http://code.google.com/p/recastnavigation/
- Version: 1.4
+ https://github.com/memononen/recastnavigation
+ Version: 740a7ba51600a3c87ce5667ae276a38284a1ce75
diff --git a/dep/recastnavigation/Detour/CMakeLists.txt b/dep/recastnavigation/Detour/CMakeLists.txt
index b7c0853efc4..5f3542e96b9 100644
--- a/dep/recastnavigation/Detour/CMakeLists.txt
+++ b/dep/recastnavigation/Detour/CMakeLists.txt
@@ -9,13 +9,14 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
set(Detour_STAT_SRCS
- DetourAlloc.cpp
- DetourCommon.cpp
- DetourNavMesh.cpp
- DetourNavMeshBuilder.cpp
- DetourNavMeshQuery.cpp
- DetourNode.cpp
+ Source/DetourAlloc.cpp
+ Source/DetourCommon.cpp
+ Source/DetourNavMesh.cpp
+ Source/DetourNavMeshBuilder.cpp
+ Source/DetourNavMeshQuery.cpp
+ Source/DetourNode.cpp
)
+include_directories(Include)
if(WIN32)
include_directories(
diff --git a/dep/recastnavigation/Detour/DetourAlloc.h b/dep/recastnavigation/Detour/Include/DetourAlloc.h
index e814b62a716..e814b62a716 100644
--- a/dep/recastnavigation/Detour/DetourAlloc.h
+++ b/dep/recastnavigation/Detour/Include/DetourAlloc.h
diff --git a/dep/recastnavigation/Detour/DetourAssert.h b/dep/recastnavigation/Detour/Include/DetourAssert.h
index 3cf652288fa..3cf652288fa 100644
--- a/dep/recastnavigation/Detour/DetourAssert.h
+++ b/dep/recastnavigation/Detour/Include/DetourAssert.h
diff --git a/dep/recastnavigation/Detour/DetourCommon.h b/dep/recastnavigation/Detour/Include/DetourCommon.h
index 0888614ea9b..0888614ea9b 100644
--- a/dep/recastnavigation/Detour/DetourCommon.h
+++ b/dep/recastnavigation/Detour/Include/DetourCommon.h
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.h b/dep/recastnavigation/Detour/Include/DetourNavMesh.h
index cdd473f1aff..cdd473f1aff 100644
--- a/dep/recastnavigation/Detour/DetourNavMesh.h
+++ b/dep/recastnavigation/Detour/Include/DetourNavMesh.h
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h b/dep/recastnavigation/Detour/Include/DetourNavMeshBuilder.h
index c80d1717630..c80d1717630 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
+++ b/dep/recastnavigation/Detour/Include/DetourNavMeshBuilder.h
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.h b/dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h
index 4a5112c9eb9..4a5112c9eb9 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshQuery.h
+++ b/dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h
diff --git a/dep/recastnavigation/Detour/DetourNode.h b/dep/recastnavigation/Detour/Include/DetourNode.h
index b68c922d038..b68c922d038 100644
--- a/dep/recastnavigation/Detour/DetourNode.h
+++ b/dep/recastnavigation/Detour/Include/DetourNode.h
diff --git a/dep/recastnavigation/Detour/DetourStatus.h b/dep/recastnavigation/Detour/Include/DetourStatus.h
index af822c4a92d..af822c4a92d 100644
--- a/dep/recastnavigation/Detour/DetourStatus.h
+++ b/dep/recastnavigation/Detour/Include/DetourStatus.h
diff --git a/dep/recastnavigation/Detour/DetourAlloc.cpp b/dep/recastnavigation/Detour/Source/DetourAlloc.cpp
index 5f671df5bdb..5f671df5bdb 100644
--- a/dep/recastnavigation/Detour/DetourAlloc.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourAlloc.cpp
diff --git a/dep/recastnavigation/Detour/DetourCommon.cpp b/dep/recastnavigation/Detour/Source/DetourCommon.cpp
index b5700f5930b..b5700f5930b 100644
--- a/dep/recastnavigation/Detour/DetourCommon.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourCommon.cpp
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.cpp b/dep/recastnavigation/Detour/Source/DetourNavMesh.cpp
index 51740509950..51740509950 100644
--- a/dep/recastnavigation/Detour/DetourNavMesh.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourNavMesh.cpp
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp b/dep/recastnavigation/Detour/Source/DetourNavMeshBuilder.cpp
index 9d8471b96a1..9d8471b96a1 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourNavMeshBuilder.cpp
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp b/dep/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp
index f1709dfd4cf..f1709dfd4cf 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp
diff --git a/dep/recastnavigation/Detour/DetourNode.cpp b/dep/recastnavigation/Detour/Source/DetourNode.cpp
index 4c8215e20d0..4c8215e20d0 100644
--- a/dep/recastnavigation/Detour/DetourNode.cpp
+++ b/dep/recastnavigation/Detour/Source/DetourNode.cpp
diff --git a/dep/recastnavigation/Readme.txt b/dep/recastnavigation/Readme.txt
index 0c2f7b1675f..1383b01d582 100644
--- a/dep/recastnavigation/Readme.txt
+++ b/dep/recastnavigation/Readme.txt
@@ -32,9 +32,6 @@ the regions as simple polygons.
The toolset code is located in the Recast folder and demo application using the Recast
toolset is located in the RecastDemo folder.
-The project files with this distribution can be compiled with Microsoft Visual C++ 2008
-(you can download it for free) and XCode 3.1.
-
Detour
@@ -43,78 +40,7 @@ Recast is accompanied with Detour, path-finding and spatial reasoning toolkit. Y
Detour offers simple static navigation mesh which is suitable for many simple cases, as well as tiled navigation mesh which allows you to plug in and out pieces of the mesh. The tiled mesh allows to create systems where you stream new navigation data in and out as the player progresses the level, or you may regenerate tiles as the world changes.
-Latest code available at http://code.google.com/p/recastnavigation/
-
-
---
-
-Release Notes
-
-----------------
-* Recast 1.4
- Released August 24th, 2009
-
-- Added detail height mesh generation (RecastDetailMesh.cpp) for single,
- tiled statmeshes as well as tilemesh.
-- Added feature to contour tracing which detects extra vertices along
- tile edges which should be removed later.
-- Changed the tiled stat mesh preprocess, so that it first generated
- polymeshes per tile and finally combines them.
-- Fixed bug in the GUI code where invisible buttons could be pressed.
-
-----------------
-* Recast 1.31
- Released July 24th, 2009
-
-- Better cost and heuristic functions.
-- Fixed tile navmesh raycast on tile borders.
-
-----------------
-* Recast 1.3
- Released July 14th, 2009
-
-- Added dtTileNavMesh which allows to dynamically add and remove navmesh pieces at runtime.
-- Renamed stat navmesh types to dtStat* (i.e. dtPoly is now dtStatPoly).
-- Moved common code used by tile and stat navmesh to DetourNode.h/cpp and DetourCommon.h/cpp.
-- Refactores the demo code.
-
-----------------
-* Recast 1.2
- Released June 17th, 2009
-
-- Added tiled mesh generation. The tiled generation allows to generate navigation for
- much larger worlds, it removes some of the artifacts that comes from distance fields
- in open areas, and allows later streaming and dynamic runtime generation
-- Improved and added some debug draw modes
-- API change: The helper function rcBuildNavMesh does not exists anymore,
- had to change few internal things to cope with the tiled processing,
- similar API functionality will be added later once the tiled process matures
-- The demo is getting way too complicated, need to split demos
-- Fixed several filtering functions so that the mesh is tighter to the geometry,
- sometimes there could be up error up to tow voxel units close to walls,
- now it should be just one.
-
-----------------
-* Recast 1.1
- Released April 11th, 2009
-
-This is the first release of Detour.
-
-----------------
-* Recast 1.0
- Released March 29th, 2009
-
-This is the first release of Recast.
-
-The process is not always as robust as I would wish. The watershed phase sometimes swallows tiny islands
-which are close to edges. These droppings are handled in rcBuildContours, but the code is not
-particularly robust either.
-
-Another non-robust case is when portal contours (contours shared between two regions) are always
-assumed to be straight. That can lead to overlapping contours specially when the level has
-large open areas.
-
-
+Latest code available at https://github.com/memononen/recastnavigation
Mikko Mononen
memon@inside.org
diff --git a/dep/recastnavigation/Recast/CMakeLists.txt b/dep/recastnavigation/Recast/CMakeLists.txt
index 10028f8535f..f4869bf8773 100644
--- a/dep/recastnavigation/Recast/CMakeLists.txt
+++ b/dep/recastnavigation/Recast/CMakeLists.txt
@@ -9,18 +9,20 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
set(Recast_STAT_SRCS
- Recast.cpp
- RecastAlloc.cpp
- RecastArea.cpp
- RecastContour.cpp
- RecastFilter.cpp
- RecastLayers.cpp
- RecastMesh.cpp
- RecastMeshDetail.cpp
- RecastRasterization.cpp
- RecastRegion.cpp
+ Source/Recast.cpp
+ Source/RecastAlloc.cpp
+ Source/RecastArea.cpp
+ Source/RecastContour.cpp
+ Source/RecastFilter.cpp
+ Source/RecastLayers.cpp
+ Source/RecastMesh.cpp
+ Source/RecastMeshDetail.cpp
+ Source/RecastRasterization.cpp
+ Source/RecastRegion.cpp
)
+include_directories(Include)
+
if(WIN32)
include_directories(
${CMAKE_SOURCE_DIR}/dep/zlib
diff --git a/dep/recastnavigation/Recast/Recast.h b/dep/recastnavigation/Recast/Include/Recast.h
index 3f4ae96d1c9..3f4ae96d1c9 100644
--- a/dep/recastnavigation/Recast/Recast.h
+++ b/dep/recastnavigation/Recast/Include/Recast.h
diff --git a/dep/recastnavigation/Recast/RecastAlloc.h b/dep/recastnavigation/Recast/Include/RecastAlloc.h
index 438be9ea56b..438be9ea56b 100644
--- a/dep/recastnavigation/Recast/RecastAlloc.h
+++ b/dep/recastnavigation/Recast/Include/RecastAlloc.h
diff --git a/dep/recastnavigation/Recast/RecastAssert.h b/dep/recastnavigation/Recast/Include/RecastAssert.h
index 2aca0d9a14f..2aca0d9a14f 100644
--- a/dep/recastnavigation/Recast/RecastAssert.h
+++ b/dep/recastnavigation/Recast/Include/RecastAssert.h
diff --git a/dep/recastnavigation/Recast/Recast.cpp b/dep/recastnavigation/Recast/Source/Recast.cpp
index b9d86036c3f..b9d86036c3f 100644
--- a/dep/recastnavigation/Recast/Recast.cpp
+++ b/dep/recastnavigation/Recast/Source/Recast.cpp
diff --git a/dep/recastnavigation/Recast/RecastAlloc.cpp b/dep/recastnavigation/Recast/Source/RecastAlloc.cpp
index b5ec1516146..b5ec1516146 100644
--- a/dep/recastnavigation/Recast/RecastAlloc.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastAlloc.cpp
diff --git a/dep/recastnavigation/Recast/RecastArea.cpp b/dep/recastnavigation/Recast/Source/RecastArea.cpp
index 1a338cd9b8c..1a338cd9b8c 100644
--- a/dep/recastnavigation/Recast/RecastArea.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastArea.cpp
diff --git a/dep/recastnavigation/Recast/RecastContour.cpp b/dep/recastnavigation/Recast/Source/RecastContour.cpp
index 5c324bcedfe..5c324bcedfe 100644
--- a/dep/recastnavigation/Recast/RecastContour.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastContour.cpp
diff --git a/dep/recastnavigation/Recast/RecastFilter.cpp b/dep/recastnavigation/Recast/Source/RecastFilter.cpp
index bf985c362c9..bf985c362c9 100644
--- a/dep/recastnavigation/Recast/RecastFilter.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastFilter.cpp
diff --git a/dep/recastnavigation/Recast/RecastLayers.cpp b/dep/recastnavigation/Recast/Source/RecastLayers.cpp
index 204f72e8cb2..204f72e8cb2 100644
--- a/dep/recastnavigation/Recast/RecastLayers.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastLayers.cpp
diff --git a/dep/recastnavigation/Recast/RecastMesh.cpp b/dep/recastnavigation/Recast/Source/RecastMesh.cpp
index 8af609b79fb..8af609b79fb 100644
--- a/dep/recastnavigation/Recast/RecastMesh.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastMesh.cpp
diff --git a/dep/recastnavigation/Recast/RecastMeshDetail.cpp b/dep/recastnavigation/Recast/Source/RecastMeshDetail.cpp
index 8325b883707..8325b883707 100644
--- a/dep/recastnavigation/Recast/RecastMeshDetail.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastMeshDetail.cpp
diff --git a/dep/recastnavigation/Recast/RecastRasterization.cpp b/dep/recastnavigation/Recast/Source/RecastRasterization.cpp
index 45a7d35bf3e..45a7d35bf3e 100644
--- a/dep/recastnavigation/Recast/RecastRasterization.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastRasterization.cpp
diff --git a/dep/recastnavigation/Recast/RecastRegion.cpp b/dep/recastnavigation/Recast/Source/RecastRegion.cpp
index 589fac29203..589fac29203 100644
--- a/dep/recastnavigation/Recast/RecastRegion.cpp
+++ b/dep/recastnavigation/Recast/Source/RecastRegion.cpp
diff --git a/dep/recastnavigation/TODO.txt b/dep/recastnavigation/TODO.txt
deleted file mode 100644
index b911c0e4720..00000000000
--- a/dep/recastnavigation/TODO.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-TODO/Roadmap
-
-Summer/Autumn 2009
-
-- Off mesh links (jump links)
-- Area annotations
-- Embed extra data per polygon
-- Height conforming navmesh
-
-
-Autumn/Winter 2009/2010
-
-- Detour path following
-- More dynamic example with tile navmesh
-- Faster small tile process
-
-
-More info at http://digestingduck.blogspot.com/2009/07/recast-and-detour-roadmap.html
-
--
diff --git a/dep/recastnavigation/recast_hotfix1.diff b/dep/recastnavigation/recast_hotfix1.diff
deleted file mode 100644
index d370b0a68c8..00000000000
--- a/dep/recastnavigation/recast_hotfix1.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dep/recastnavigation/Detour/DetourNavMesh.h b/dep/recastnavigation/Detour/DetourNavMesh.h
-index 52d2c50..99e30c7 100644
---- a/dep/recastnavigation/Detour/DetourNavMesh.h
-+++ b/dep/recastnavigation/Detour/DetourNavMesh.h
-@@ -21,7 +21,7 @@
-
- #include "DetourAlloc.h"
-
--#ifdef WIN32
-+#if defined(WIN32) && !defined(__MINGW32__)
- typedef unsigned __int64 uint64;
- #else
- #include <stdint.h>
diff --git a/dep/recastnavigation/recast_hotfix2.diff b/dep/recastnavigation/recast_hotfix2.diff
deleted file mode 100644
index cd73165dcb7..00000000000
--- a/dep/recastnavigation/recast_hotfix2.diff
+++ /dev/null
@@ -1,38 +0,0 @@
-diff --git a/dep/recastnavigation/Detour/DetourNavMesh.h b/dep/recastnavigation/Detour/DetourNavMesh.h
-index c094e41..9c61a9b 100644
---- a/dep/recastnavigation/Detour/DetourNavMesh.h
-+++ b/dep/recastnavigation/Detour/DetourNavMesh.h
-@@ -25,7 +25,8 @@
-
- // Edited by TC
- #if defined(WIN32) && !defined(__MINGW32__)
--typedef unsigned __int64 uint64;
-+/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
-+typedef unsigned __int64 uint64_d;
- #else
- #include <stdint.h>
- #ifndef uint64_t
-@@ -33,7 +34,8 @@ typedef unsigned __int64 uint64;
- #include <linux/types.h>
- #endif
- #endif
--typedef uint64_t uint64;
-+/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
-+typedef uint64_t uint64_d;
- #endif
-
- // Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
-@@ -48,11 +50,11 @@ static const int STATIC_POLY_BITS = 31;
-
- /// A handle to a polygon within a navigation mesh tile.
- /// @ingroup detour
--typedef uint64 dtPolyRef; // Edited by TC
-+typedef uint64_d dtPolyRef; // Edited by TC
-
- /// A handle to a tile within a navigation mesh.
- /// @ingroup detour
--typedef uint64 dtTileRef; // Edited by TC
-+typedef uint64_d dtTileRef; // Edited by TC
-
- /// The maximum number of vertices per navigation polygon.
- /// @ingroup detour
diff --git a/dep/recastnavigation/recastnavigation.diff b/dep/recastnavigation/recastnavigation.diff
new file mode 100644
index 00000000000..68e976c955e
--- /dev/null
+++ b/dep/recastnavigation/recastnavigation.diff
@@ -0,0 +1,4066 @@
+ 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(-)
+
+diff --git a/Detour/Include/DetourNavMesh.h b/Detour/Include/DetourNavMesh.h
+index 95a63e4..cdd473f 100644
+--- a/Detour/Include/DetourNavMesh.h
++++ b/Detour/Include/DetourNavMesh.h
+@@ -22,39 +22,35 @@
+ #include "DetourAlloc.h"
+ #include "DetourStatus.h"
+
+-// Undefine (or define in a build cofnig) the following line to use 64bit polyref.
+-// Generally not needed, useful for very large worlds.
+-// Note: tiles build using 32bit refs are not compatible with 64bit refs!
+-//#define DT_POLYREF64 1
+-
+-#ifdef DT_POLYREF64
+-// TODO: figure out a multiplatform version of uint64_t
+-// - maybe: https://code.google.com/p/msinttypes/
+-// - or: http://www.azillionmonkeys.com/qed/pstdint.h
++
++// Edited by TC
++#if defined(WIN32) && !defined(__MINGW32__)
++/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
++typedef unsigned __int64 uint64_d;
++#else
+ #include <stdint.h>
++#ifndef uint64_t
++#ifdef __linux__
++#include <linux/types.h>
++#endif
+ #endif
++/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
++typedef uint64_t uint64_d;
++#endif
+
+ // Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
+ // It is also recommended that you change dtHashRef() to a proper 64-bit hash.
+
++// Edited by TC
++// We cannot have over 31 bits for either tile nor poly
++// without changing polyCount to use 64bits too.
+ /// A handle to a polygon within a navigation mesh tile.
+ /// @ingroup detour
+-#ifdef DT_POLYREF64
+-static const unsigned int DT_SALT_BITS = 16;
+-static const unsigned int DT_TILE_BITS = 28;
+-static const unsigned int DT_POLY_BITS = 20;
+-typedef uint64_t dtPolyRef;
+-#else
+-typedef unsigned int dtPolyRef;
+-#endif
++typedef uint64_d dtPolyRef; // Edited by TC
+
+ /// A handle to a tile within a navigation mesh.
+ /// @ingroup detour
+-#ifdef DT_POLYREF64
+-typedef uint64_t dtTileRef;
+-#else
+-typedef unsigned int dtTileRef;
+-#endif
++typedef uint64_d dtTileRef; // Edited by TC
+
+ /// The maximum number of vertices per navigation polygon.
+ /// @ingroup detour
+@@ -94,6 +90,12 @@ static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
+ /// @ingroup detour
+ static const int DT_MAX_AREAS = 64;
+
++static const int STATIC_SALT_BITS = 12;
++static const int STATIC_TILE_BITS = 21;
++static const int STATIC_POLY_BITS = 31;
++// we cannot have over 31 bits for either tile nor poly
++// without changing polyCount to use 64bits too.
++
+ /// Tile flags used for various functions and fields.
+ /// For an example, see dtNavMesh::addTile().
+ enum dtTileFlags
+@@ -492,11 +494,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
+ {
+-#ifdef DT_POLYREF64
+- return ((dtPolyRef)salt << (DT_POLY_BITS+DT_TILE_BITS)) | ((dtPolyRef)it << DT_POLY_BITS) | (dtPolyRef)ip;
+-#else
+ return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
+-#endif
+ }
+
+ /// Decodes a standard polygon reference.
+@@ -508,21 +506,12 @@ public:
+ /// @see #encodePolyId
+ inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
+ {
+-#ifdef DT_POLYREF64
+- const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
+- const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
+- const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
+- salt = (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
+- it = (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
+- ip = (unsigned int)(ref & polyMask);
+-#else
+ const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
+ const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
+ const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
+ salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
+ it = (unsigned int)((ref >> m_polyBits) & tileMask);
+ ip = (unsigned int)(ref & polyMask);
+-#endif
+ }
+
+ /// Extracts a tile's salt value from the specified polygon reference.
+@@ -531,13 +520,8 @@ public:
+ /// @see #encodePolyId
+ inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
+ {
+-#ifdef DT_POLYREF64
+- const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
+- return (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
+-#else
+ const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
+ return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
+-#endif
+ }
+
+ /// Extracts the tile's index from the specified polygon reference.
+@@ -546,13 +530,8 @@ public:
+ /// @see #encodePolyId
+ inline unsigned int decodePolyIdTile(dtPolyRef ref) const
+ {
+-#ifdef DT_POLYREF64
+- const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
+- return (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
+-#else
+ const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
+ return (unsigned int)((ref >> m_polyBits) & tileMask);
+-#endif
+ }
+
+ /// Extracts the polygon's index (within its tile) from the specified polygon reference.
+@@ -561,13 +540,8 @@ public:
+ /// @see #encodePolyId
+ inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
+ {
+-#ifdef DT_POLYREF64
+- const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
+- return (unsigned int)(ref & polyMask);
+-#else
+ const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
+ return (unsigned int)(ref & polyMask);
+-#endif
+ }
+
+ /// @}
+@@ -626,11 +600,9 @@ private:
+ dtMeshTile* m_nextFree; ///< Freelist of tiles.
+ dtMeshTile* m_tiles; ///< List of tiles.
+
+-#ifndef DT_POLYREF64
+ unsigned int m_saltBits; ///< Number of salt bits in the tile ID.
+ unsigned int m_tileBits; ///< Number of tile bits in the tile ID.
+ unsigned int m_polyBits; ///< Number of poly bits in the tile ID.
+-#endif
+ };
+
+ /// Allocates a navigation mesh object using the Detour allocator.
+diff --git a/Detour/Source/DetourCommon.cpp b/Detour/Source/DetourCommon.cpp
+index a98d8c8..b5700f5 100644
+--- a/Detour/Source/DetourCommon.cpp
++++ b/Detour/Source/DetourCommon.cpp
+@@ -16,14 +16,14 @@
+ // 3. This notice may not be removed or altered from any source distribution.
+ //
+
++#include <math.h>
+ #include "DetourCommon.h"
+-#include "DetourMath.h"
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ float dtSqrt(float x)
+ {
+- return dtMathSqrtf(x);
++ return sqrtf(x);
+ }
+
+ void dtClosestPtPointTriangle(float* closest, const float* p,
+diff --git a/Detour/Source/DetourNavMesh.cpp b/Detour/Source/DetourNavMesh.cpp
+index 9d627be..5174050 100644
+--- a/Detour/Source/DetourNavMesh.cpp
++++ b/Detour/Source/DetourNavMesh.cpp
+@@ -16,13 +16,13 @@
+ // 3. This notice may not be removed or altered from any source distribution.
+ //
+
++#include <math.h>
+ #include <float.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include "DetourNavMesh.h"
+ #include "DetourNode.h"
+ #include "DetourCommon.h"
+-#include "DetourMath.h"
+ #include "DetourAlloc.h"
+ #include "DetourAssert.h"
+ #include <new>
+@@ -193,13 +193,11 @@ dtNavMesh::dtNavMesh() :
+ m_tileLutMask(0),
+ m_posLookup(0),
+ m_nextFree(0),
+- m_tiles(0)
++ m_tiles(0),
++ m_saltBits(0),
++ m_tileBits(0),
++ m_polyBits(0)
+ {
+-#ifndef DT_POLYREF64
+- m_saltBits = 0;
+- m_tileBits = 0;
+- m_polyBits = 0;
+-#endif
+ memset(&m_params, 0, sizeof(dtNavMeshParams));
+ m_orig[0] = 0;
+ m_orig[1] = 0;
+@@ -250,17 +248,11 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
+ m_nextFree = &m_tiles[i];
+ }
+
+- // Init ID generator values.
+-#ifndef DT_POLYREF64
+- m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles));
+- m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys));
+- // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
+- m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits);
+-
+- if (m_saltBits < 10)
+- return DT_FAILURE | DT_INVALID_PARAM;
+-#endif
+-
++ // Edited by TC
++ m_tileBits = STATIC_TILE_BITS;
++ m_polyBits = STATIC_POLY_BITS;
++ m_saltBits = STATIC_SALT_BITS;
++
+ return DT_SUCCESS;
+ }
+
+@@ -1242,11 +1234,7 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
+ tile->offMeshCons = 0;
+
+ // Update salt, salt should never be zero.
+-#ifdef DT_POLYREF64
+- tile->salt = (tile->salt+1) & ((1<<DT_SALT_BITS)-1);
+-#else
+ tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
+-#endif
+ if (tile->salt == 0)
+ tile->salt++;
+
+diff --git a/Detour/Source/DetourNavMeshBuilder.cpp b/Detour/Source/DetourNavMeshBuilder.cpp
+index 1bf271b..9d8471b 100644
+--- a/Detour/Source/DetourNavMeshBuilder.cpp
++++ b/Detour/Source/DetourNavMeshBuilder.cpp
+@@ -16,13 +16,13 @@
+ // 3. This notice may not be removed or altered from any source distribution.
+ //
+
++#include <math.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <float.h>
+ #include "DetourNavMesh.h"
+ #include "DetourCommon.h"
+-#include "DetourMath.h"
+ #include "DetourNavMeshBuilder.h"
+ #include "DetourAlloc.h"
+ #include "DetourAssert.h"
+@@ -202,8 +202,8 @@ static int createBVTree(const unsigned short* verts, const int /*nverts*/,
+ if (z > it.bmax[2]) it.bmax[2] = z;
+ }
+ // Remap y
+- it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
+- it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
++ it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs);
++ it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs);
+ }
+
+ int curNode = 0;
+diff --git a/Detour/Source/DetourNavMeshQuery.cpp b/Detour/Source/DetourNavMeshQuery.cpp
+index 2e30464..f1709df 100644
+--- a/Detour/Source/DetourNavMeshQuery.cpp
++++ b/Detour/Source/DetourNavMeshQuery.cpp
+@@ -16,13 +16,13 @@
+ // 3. This notice may not be removed or altered from any source distribution.
+ //
+
++#include <math.h>
+ #include <float.h>
+ #include <string.h>
+ #include "DetourNavMeshQuery.h"
+ #include "DetourNavMesh.h"
+ #include "DetourNode.h"
+ #include "DetourCommon.h"
+-#include "DetourMath.h"
+ #include "DetourAlloc.h"
+ #include "DetourAssert.h"
+ #include <new>
+@@ -99,8 +99,9 @@ inline float dtQueryFilter::getCost(const float* pa, const float* pb,
+ return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()];
+ }
+ #endif
+-
+-static const float H_SCALE = 0.999f; // Search heuristic scale.
++
++// Edited by TC
++static const float H_SCALE = 2.0f; // Search heuristic scale.
+
+
+ dtNavMeshQuery* dtAllocNavMeshQuery()
+@@ -3305,7 +3306,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
+ dtVsub(hitNormal, centerPos, hitPos);
+ dtVnormalize(hitNormal);
+
+- *hitDist = dtMathSqrtf(radiusSqr);
++ *hitDist = sqrtf(radiusSqr);
+
+ return status;
+ }
+diff --git a/Detour/Source/DetourNode.cpp b/Detour/Source/DetourNode.cpp
+index 57cb206..4c8215e 100644
+--- a/Detour/Source/DetourNode.cpp
++++ b/Detour/Source/DetourNode.cpp
+@@ -22,30 +22,17 @@
+ #include "DetourCommon.h"
+ #include <string.h>
+
+-#ifdef DT_POLYREF64
+-// From Thomas Wang, https://gist.github.com/badboy/6267743
+ inline unsigned int dtHashRef(dtPolyRef a)
+ {
+- a = (~a) + (a << 18); // a = (a << 18) - a - 1;
+- a = a ^ (a >> 31);
+- a = a * 21; // a = (a + (a << 2)) + (a << 4);
+- a = a ^ (a >> 11);
+- a = a + (a << 6);
+- a = a ^ (a >> 22);
+- return (unsigned int)a;
++ // Edited by TC
++ a = (~a) + (a << 18);
++ a = a ^ (a >> 31);
++ a = a * 21;
++ a = a ^ (a >> 11);
++ a = a + (a << 6);
++ a = a ^ (a >> 22);
++ return (unsigned int)a;
+ }
+-#else
+-inline unsigned int dtHashRef(dtPolyRef a)
+-{
+- a += ~(a<<15);
+- a ^= (a>>10);
+- a += (a<<3);
+- a ^= (a>>6);
+- a += ~(a<<11);
+- a ^= (a>>16);
+- return (unsigned int)a;
+-}
+-#endif
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ dtNodePool::dtNodePool(int maxNodes, int hashSize) :
+diff --git a/DetourCrowd/Source/DetourObstacleAvoidance.cpp b/DetourCrowd/Source/DetourObstacleAvoidance.cpp
+index 0fad9ef..d3f90b7 100644
+--- a/DetourCrowd/Source/DetourObstacleAvoidance.cpp
++++ b/DetourCrowd/Source/DetourObstacleAvoidance.cpp
+@@ -18,10 +18,10 @@
+
+ #include "DetourObstacleAvoidance.h"
+ #include "DetourCommon.h"
+-#include "DetourMath.h"
+ #include "DetourAlloc.h"
+ #include "DetourAssert.h"
+ #include <string.h>
++#include <math.h>
+ #include <float.h>
+ #include <new>
+
+@@ -58,7 +58,7 @@ static int isectRaySeg(const float* ap, const float* u,
+ dtVsub(v,bq,bp);
+ dtVsub(w,ap,bp);
+ float d = dtVperp2D(u,v);
+- if (dtMathFabs(d) < 1e-6f) return 0;
++ if (fabsf(d) < 1e-6f) return 0;
+ d = 1.0f/d;
+ t = dtVperp2D(v,w) * d;
+ if (t < 0 || t > 1) return 0;
+@@ -482,7 +482,7 @@ int dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const flo
+ const int nd = dtClamp(ndivs, 1, DT_MAX_PATTERN_DIVS);
+ const int nr = dtClamp(nrings, 1, DT_MAX_PATTERN_RINGS);
+ const float da = (1.0f/nd) * DT_PI*2;
+- const float dang = dtMathAtan2f(dvel[2], dvel[0]);
++ const float dang = atan2f(dvel[2], dvel[0]);
+
+ // 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
+--- a/Recast/Include/Recast.h
++++ b/Recast/Include/Recast.h
+@@ -243,7 +243,7 @@ struct rcConfig
+ };
+
+ /// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
+-static const int RC_SPAN_HEIGHT_BITS = 13;
++static const int RC_SPAN_HEIGHT_BITS = 16; // EDITED BY TC
+ /// Defines the maximum value for rcSpan::smin and rcSpan::smax.
+ static const int RC_SPAN_MAX_HEIGHT = (1<<RC_SPAN_HEIGHT_BITS)-1;
+
+@@ -255,9 +255,9 @@ static const int RC_SPANS_PER_POOL = 2048;
+ /// @see rcHeightfield
+ struct rcSpan
+ {
+- unsigned int smin : 13; ///< The lower limit of the span. [Limit: < #smax]
+- unsigned int smax : 13; ///< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
+- unsigned int area : 6; ///< The area id assigned to the span.
++ unsigned int smin : 16; ///< The lower limit of the span. [Limit: < #smax]
++ unsigned int smax : 16; ///< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
++ unsigned char area; ///< The area id assigned to the span.
+ 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
diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt
index a83bb9dad1c..a2024bff7cb 100644
--- a/src/server/collision/CMakeLists.txt
+++ b/src/server/collision/CMakeLists.txt
@@ -34,6 +34,7 @@ include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
${CMAKE_SOURCE_DIR}/src/server/shared/Debugging
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index bf46c1fd7c6..26fd0814dcb 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -103,7 +103,9 @@ set(game_STAT_SRCS
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/SFMT
${CMAKE_SOURCE_DIR}/dep/zlib
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index c1a9435de52..938520209a0 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -47,7 +47,9 @@ message("")
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/SFMT
${CMAKE_SOURCE_DIR}/dep/zlib
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index d1d2ef11848..78a29dbedf6 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -45,6 +45,7 @@ include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/dep/gsoap
${CMAKE_SOURCE_DIR}/dep/sockets/include
${CMAKE_SOURCE_DIR}/dep/SFMT
diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt
index 591e0cc8e98..c0268680657 100644
--- a/src/tools/mmaps_generator/CMakeLists.txt
+++ b/src/tools/mmaps_generator/CMakeLists.txt
@@ -18,7 +18,9 @@ set(mmap_gen_Includes
${CMAKE_SOURCE_DIR}/dep/bzip2
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
+ ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/game/Conditions
${CMAKE_SOURCE_DIR}/src/server/collision