Updated stb_truetype, fixed compiler warnings. Compiles with -Wall now.
This commit is contained in:
parent
fa66b9a9f3
commit
8561fb6d00
Binary file not shown.
@ -168,6 +168,16 @@
|
|||||||
6B324AD6111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD6111C00D700EBD2FD /* PBXTextBookmark */;
|
6B324AD6111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD6111C00D700EBD2FD /* PBXTextBookmark */;
|
||||||
6B324AD7111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD7111C00D700EBD2FD /* PBXTextBookmark */;
|
6B324AD7111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD7111C00D700EBD2FD /* PBXTextBookmark */;
|
||||||
6B324AD8111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD8111C00D700EBD2FD /* PBXTextBookmark */;
|
6B324AD8111C00D700EBD2FD /* PBXTextBookmark */ = 6B324AD8111C00D700EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324ADA111C012300EBD2FD /* PBXTextBookmark */ = 6B324ADA111C012300EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324ADB111C012300EBD2FD /* PBXTextBookmark */ = 6B324ADB111C012300EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324ADD111C014A00EBD2FD /* PBXTextBookmark */ = 6B324ADD111C014A00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324ADE111C014A00EBD2FD /* PBXTextBookmark */ = 6B324ADE111C014A00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE0111C020F00EBD2FD /* PBXTextBookmark */ = 6B324AE0111C020F00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE1111C020F00EBD2FD /* PBXTextBookmark */ = 6B324AE1111C020F00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE6111C07AB00EBD2FD /* PBXTextBookmark */ = 6B324AE6111C07AB00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE7111C07AB00EBD2FD /* PBXTextBookmark */ = 6B324AE7111C07AB00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE8111C07AB00EBD2FD /* PBXTextBookmark */ = 6B324AE8111C07AB00EBD2FD /* PBXTextBookmark */;
|
||||||
|
6B324AE9111C07AB00EBD2FD /* PBXTextBookmark */ = 6B324AE9111C07AB00EBD2FD /* PBXTextBookmark */;
|
||||||
6B69739F10FFCA4500984788 = 6B69739F10FFCA4500984788 /* PBXTextBookmark */;
|
6B69739F10FFCA4500984788 = 6B69739F10FFCA4500984788 /* PBXTextBookmark */;
|
||||||
6B6973A210FFCA4500984788 = 6B6973A210FFCA4500984788 /* PBXTextBookmark */;
|
6B6973A210FFCA4500984788 = 6B6973A210FFCA4500984788 /* PBXTextBookmark */;
|
||||||
6B8DE70D10B01BBF00DF20FB = 6B8DE70D10B01BBF00DF20FB /* PBXTextBookmark */;
|
6B8DE70D10B01BBF00DF20FB = 6B8DE70D10B01BBF00DF20FB /* PBXTextBookmark */;
|
||||||
@ -778,7 +788,7 @@
|
|||||||
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
name = "imguiRenderGL.cpp: 217";
|
name = "imguiRenderGL.cpp: 217";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 5230;
|
rLoc = 5234;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 474;
|
vrLen = 474;
|
||||||
vrLoc = 4904;
|
vrLoc = 4904;
|
||||||
@ -808,7 +818,7 @@
|
|||||||
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
name = "imguiRenderGL.cpp: 217";
|
name = "imguiRenderGL.cpp: 217";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 5230;
|
rLoc = 5234;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 474;
|
vrLen = 474;
|
||||||
vrLoc = 4904;
|
vrLoc = 4904;
|
||||||
@ -848,7 +858,7 @@
|
|||||||
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
name = "stb_truetype.h: 667";
|
name = "stb_truetype.h: 667";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 27261;
|
rLoc = 27273;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 975;
|
vrLen = 975;
|
||||||
vrLoc = 26909;
|
vrLoc = 26909;
|
||||||
@ -878,7 +888,7 @@
|
|||||||
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
name = "stb_truetype.h: 667";
|
name = "stb_truetype.h: 667";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 27261;
|
rLoc = 27273;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 975;
|
vrLen = 975;
|
||||||
vrLoc = 26909;
|
vrLoc = 26909;
|
||||||
@ -958,7 +968,7 @@
|
|||||||
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
name = "imguiRenderGL.cpp: 218";
|
name = "imguiRenderGL.cpp: 218";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 5173;
|
rLoc = 5177;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 529;
|
vrLen = 529;
|
||||||
vrLoc = 5014;
|
vrLoc = 5014;
|
||||||
@ -1086,7 +1096,7 @@
|
|||||||
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
name = "imguiRenderGL.cpp: 218";
|
name = "imguiRenderGL.cpp: 218";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 5173;
|
rLoc = 5177;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 529;
|
vrLen = 529;
|
||||||
vrLoc = 5014;
|
vrLoc = 5014;
|
||||||
@ -1131,6 +1141,99 @@
|
|||||||
vrLen = 1033;
|
vrLen = 1033;
|
||||||
vrLoc = 2157;
|
vrLoc = 2157;
|
||||||
};
|
};
|
||||||
|
6B324ADA111C012300EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
rLen = 1;
|
||||||
|
rLoc = 631;
|
||||||
|
rType = 1;
|
||||||
|
};
|
||||||
|
6B324ADB111C012300EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
name = "stb_truetype.h: 632";
|
||||||
|
rLen = 99;
|
||||||
|
rLoc = 26099;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 982;
|
||||||
|
vrLoc = 25496;
|
||||||
|
};
|
||||||
|
6B324ADD111C014A00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
comments = "warning: 'y' may be used uninitialized in this function";
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
rLen = 1;
|
||||||
|
rLoc = 1331;
|
||||||
|
rType = 1;
|
||||||
|
};
|
||||||
|
6B324ADE111C014A00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
name = "stb_truetype.h: 1332";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 50386;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 705;
|
||||||
|
vrLoc = 50169;
|
||||||
|
};
|
||||||
|
6B324AE0111C020F00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
comments = "warning: multi-line comment";
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
rLen = 1;
|
||||||
|
rLoc = 64;
|
||||||
|
rType = 1;
|
||||||
|
};
|
||||||
|
6B324AE1111C020F00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
name = "stb_truetype.h: 65";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 2715;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 984;
|
||||||
|
vrLoc = 2229;
|
||||||
|
};
|
||||||
|
6B324AE6111C07AB00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
name = "stb_truetype.h: 641";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 26733;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 909;
|
||||||
|
vrLoc = 26283;
|
||||||
|
};
|
||||||
|
6B324AE7111C07AB00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
|
name = "imguiRenderGL.cpp: 218";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 5177;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 470;
|
||||||
|
vrLoc = 5073;
|
||||||
|
};
|
||||||
|
6B324AE8111C07AB00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
|
name = "stb_truetype.h: 641";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 26733;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 909;
|
||||||
|
vrLoc = 26283;
|
||||||
|
};
|
||||||
|
6B324AE9111C07AB00EBD2FD /* PBXTextBookmark */ = {
|
||||||
|
isa = PBXTextBookmark;
|
||||||
|
fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
|
||||||
|
name = "imguiRenderGL.cpp: 24";
|
||||||
|
rLen = 0;
|
||||||
|
rLoc = 1047;
|
||||||
|
rType = 0;
|
||||||
|
vrLen = 735;
|
||||||
|
vrLoc = 837;
|
||||||
|
};
|
||||||
6B555DAE100B211D00247EA3 /* imguiRenderGL.h */ = {
|
6B555DAE100B211D00247EA3 /* imguiRenderGL.h */ = {
|
||||||
uiCtxt = {
|
uiCtxt = {
|
||||||
sepNavIntBoundsRect = "{{0, 0}, {915, 492}}";
|
sepNavIntBoundsRect = "{{0, 0}, {915, 492}}";
|
||||||
@ -1140,16 +1243,16 @@
|
|||||||
};
|
};
|
||||||
6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = {
|
6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = {
|
||||||
uiCtxt = {
|
uiCtxt = {
|
||||||
sepNavIntBoundsRect = "{{0, 0}, {815, 7020}}";
|
sepNavIntBoundsRect = "{{0, 0}, {815, 6992}}";
|
||||||
sepNavSelRange = "{5173, 0}";
|
sepNavSelRange = "{1047, 0}";
|
||||||
sepNavVisRange = "{5073, 597}";
|
sepNavVisRange = "{837, 735}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
6B555DF6100B273500247EA3 /* stb_truetype.h */ = {
|
6B555DF6100B273500247EA3 /* stb_truetype.h */ = {
|
||||||
uiCtxt = {
|
uiCtxt = {
|
||||||
sepNavIntBoundsRect = "{{0, 0}, {815, 26848}}";
|
sepNavIntBoundsRect = "{{0, 0}, {1258, 29344}}";
|
||||||
sepNavSelRange = "{2449, 0}";
|
sepNavSelRange = "{26733, 0}";
|
||||||
sepNavVisRange = "{2157, 1033}";
|
sepNavVisRange = "{26283, 909}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
6B624169103434880002E346 /* RecastMeshDetail.cpp */ = {
|
6B624169103434880002E346 /* RecastMeshDetail.cpp */ = {
|
||||||
@ -1362,7 +1465,7 @@
|
|||||||
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
fRef = 6B555DF6100B273500247EA3 /* stb_truetype.h */;
|
||||||
name = "stb_truetype.h: 673";
|
name = "stb_truetype.h: 673";
|
||||||
rLen = 0;
|
rLen = 0;
|
||||||
rLoc = 27352;
|
rLoc = 27364;
|
||||||
rType = 0;
|
rType = 0;
|
||||||
vrLen = 857;
|
vrLen = 857;
|
||||||
vrLoc = 26962;
|
vrLoc = 26962;
|
||||||
|
@ -281,14 +281,13 @@
|
|||||||
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
|
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
|
||||||
<array>
|
<array>
|
||||||
<array>
|
<array>
|
||||||
<integer>13</integer>
|
<integer>55</integer>
|
||||||
<integer>12</integer>
|
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</array>
|
</array>
|
||||||
</array>
|
</array>
|
||||||
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
||||||
<string>{{0, 126}, {358, 643}}</string>
|
<string>{{0, 606}, {358, 643}}</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>PBXTopSmartGroupGIDs</key>
|
<key>PBXTopSmartGroupGIDs</key>
|
||||||
<array/>
|
<array/>
|
||||||
@ -323,7 +322,7 @@
|
|||||||
<key>PBXProjectModuleGUID</key>
|
<key>PBXProjectModuleGUID</key>
|
||||||
<string>6B8632A30F78115100E2684A</string>
|
<string>6B8632A30F78115100E2684A</string>
|
||||||
<key>PBXProjectModuleLabel</key>
|
<key>PBXProjectModuleLabel</key>
|
||||||
<string>stb_truetype.h</string>
|
<string>imguiRenderGL.cpp</string>
|
||||||
<key>PBXSplitModuleInNavigatorKey</key>
|
<key>PBXSplitModuleInNavigatorKey</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>Split0</key>
|
<key>Split0</key>
|
||||||
@ -331,11 +330,11 @@
|
|||||||
<key>PBXProjectModuleGUID</key>
|
<key>PBXProjectModuleGUID</key>
|
||||||
<string>6B8632A40F78115100E2684A</string>
|
<string>6B8632A40F78115100E2684A</string>
|
||||||
<key>PBXProjectModuleLabel</key>
|
<key>PBXProjectModuleLabel</key>
|
||||||
<string>stb_truetype.h</string>
|
<string>imguiRenderGL.cpp</string>
|
||||||
<key>_historyCapacity</key>
|
<key>_historyCapacity</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>bookmark</key>
|
<key>bookmark</key>
|
||||||
<string>6B324AD8111C00D700EBD2FD</string>
|
<string>6B324AE9111C07AB00EBD2FD</string>
|
||||||
<key>history</key>
|
<key>history</key>
|
||||||
<array>
|
<array>
|
||||||
<string>6B8DE70D10B01BBF00DF20FB</string>
|
<string>6B8DE70D10B01BBF00DF20FB</string>
|
||||||
@ -393,11 +392,11 @@
|
|||||||
<string>6B324AC4111C00D700EBD2FD</string>
|
<string>6B324AC4111C00D700EBD2FD</string>
|
||||||
<string>6B324AC5111C00D700EBD2FD</string>
|
<string>6B324AC5111C00D700EBD2FD</string>
|
||||||
<string>6B324AC6111C00D700EBD2FD</string>
|
<string>6B324AC6111C00D700EBD2FD</string>
|
||||||
<string>6B324AC7111C00D700EBD2FD</string>
|
|
||||||
<string>6B324AC8111C00D700EBD2FD</string>
|
<string>6B324AC8111C00D700EBD2FD</string>
|
||||||
<string>6B324AC9111C00D700EBD2FD</string>
|
<string>6B324AC9111C00D700EBD2FD</string>
|
||||||
<string>6B324ACA111C00D700EBD2FD</string>
|
<string>6B324ACA111C00D700EBD2FD</string>
|
||||||
<string>6B324ACB111C00D700EBD2FD</string>
|
<string>6B324AE6111C07AB00EBD2FD</string>
|
||||||
|
<string>6B324AE7111C07AB00EBD2FD</string>
|
||||||
</array>
|
</array>
|
||||||
<key>prevStack</key>
|
<key>prevStack</key>
|
||||||
<array>
|
<array>
|
||||||
@ -471,6 +470,7 @@
|
|||||||
<string>6B324AD5111C00D700EBD2FD</string>
|
<string>6B324AD5111C00D700EBD2FD</string>
|
||||||
<string>6B324AD6111C00D700EBD2FD</string>
|
<string>6B324AD6111C00D700EBD2FD</string>
|
||||||
<string>6B324AD7111C00D700EBD2FD</string>
|
<string>6B324AD7111C00D700EBD2FD</string>
|
||||||
|
<string>6B324AE8111C07AB00EBD2FD</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<key>SplitCount</key>
|
<key>SplitCount</key>
|
||||||
@ -484,18 +484,18 @@
|
|||||||
<key>GeometryConfiguration</key>
|
<key>GeometryConfiguration</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>Frame</key>
|
<key>Frame</key>
|
||||||
<string>{{0, 0}, {876, 399}}</string>
|
<string>{{0, 0}, {876, 423}}</string>
|
||||||
<key>RubberWindowFrame</key>
|
<key>RubberWindowFrame</key>
|
||||||
<string>11 76 1256 702 0 0 1280 778 </string>
|
<string>11 76 1256 702 0 0 1280 778 </string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Module</key>
|
<key>Module</key>
|
||||||
<string>PBXNavigatorGroup</string>
|
<string>PBXNavigatorGroup</string>
|
||||||
<key>Proportion</key>
|
<key>Proportion</key>
|
||||||
<string>399pt</string>
|
<string>423pt</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>Proportion</key>
|
<key>Proportion</key>
|
||||||
<string>257pt</string>
|
<string>233pt</string>
|
||||||
<key>Tabs</key>
|
<key>Tabs</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@ -563,7 +563,7 @@
|
|||||||
<key>GeometryConfiguration</key>
|
<key>GeometryConfiguration</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>Frame</key>
|
<key>Frame</key>
|
||||||
<string>{{10, 27}, {876, 230}}</string>
|
<string>{{10, 27}, {876, 206}}</string>
|
||||||
<key>RubberWindowFrame</key>
|
<key>RubberWindowFrame</key>
|
||||||
<string>11 76 1256 702 0 0 1280 778 </string>
|
<string>11 76 1256 702 0 0 1280 778 </string>
|
||||||
</dict>
|
</dict>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// stb_truetype.h - v0.2 - public domain - 2009 Sean Barrett / RAD Game Tools
|
// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools
|
||||||
//
|
//
|
||||||
// This library processes TrueType files:
|
// This library processes TrueType files:
|
||||||
// parse files
|
// parse files
|
||||||
@ -7,13 +7,20 @@
|
|||||||
// render glyphs to one-channel bitmaps with antialiasing (box filter)
|
// render glyphs to one-channel bitmaps with antialiasing (box filter)
|
||||||
//
|
//
|
||||||
// Todo:
|
// Todo:
|
||||||
|
// non-MS cmaps
|
||||||
// crashproof on bad data
|
// crashproof on bad data
|
||||||
// hinting
|
// hinting
|
||||||
// subpixel positioning when rendering bitmap
|
// subpixel positioning when rendering bitmap
|
||||||
// cleartype-style AA
|
// cleartype-style AA
|
||||||
//
|
//
|
||||||
|
// ADDITIONAL CONTRIBUTORS
|
||||||
|
//
|
||||||
|
// Mikko Mononen: compound shape support, more cmap formats
|
||||||
|
//
|
||||||
// VERSIONS
|
// 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.2 (2009-03-11) Fix unsigned/signed char warnings
|
||||||
// 0.1 (2009-03-09) First public release
|
// 0.1 (2009-03-09) First public release
|
||||||
//
|
//
|
||||||
@ -57,12 +64,12 @@
|
|||||||
// recommend it.
|
// recommend it.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// SOURCE STATISTICS (based on v.1, 1700 LOC)
|
// SOURCE STATISTICS (based on v0.3, 1800 LOC)
|
||||||
//
|
//
|
||||||
// Documentation & header file 350 LOC \___ 500 LOC documentation
|
// Documentation & header file 350 LOC \___ 500 LOC documentation
|
||||||
// Sample code 140 LOC /
|
// Sample code 140 LOC /
|
||||||
// Truetype parsing 480 LOC ---- 500 LOC TrueType
|
// Truetype parsing 580 LOC ---- 600 LOC TrueType
|
||||||
// Software rasterization 240 LOC \
|
// Software rasterization 240 LOC \ .
|
||||||
// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation
|
// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation
|
||||||
// Bitmap management 70 LOC /
|
// Bitmap management 70 LOC /
|
||||||
// Baked bitmap interface 70 LOC /
|
// Baked bitmap interface 70 LOC /
|
||||||
@ -130,18 +137,18 @@ void my_stbtt_print(float x, float y, char *text)
|
|||||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||||
#include "stb_truetype.h"
|
#include "stb_truetype.h"
|
||||||
|
|
||||||
char ttf_buffer[1<<20];
|
char ttf_buffer[1<<25];
|
||||||
|
|
||||||
int main(int arg, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
stbtt_fontinfo font;
|
stbtt_fontinfo font;
|
||||||
unsigned char *bitmap;
|
unsigned char *bitmap;
|
||||||
int w,h,i,j;
|
int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
|
||||||
|
|
||||||
fread(ttf_buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
|
fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
|
||||||
|
|
||||||
stbtt_InitFont(&font, ttf_buffer, 0);
|
stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
|
||||||
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, 20), 'a', &w, &h, 0,0);
|
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
|
||||||
|
|
||||||
for (j=0; j < h; ++j) {
|
for (j=0; j < h; ++j) {
|
||||||
for (i=0; i < w; ++i)
|
for (i=0; i < w; ++i)
|
||||||
@ -242,8 +249,8 @@ int main(int arg, char **argv)
|
|||||||
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
|
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
|
||||||
#ifndef STBTT_malloc
|
#ifndef STBTT_malloc
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#define STBTT_malloc(x) malloc(x)
|
#define STBTT_malloc(x,u) malloc(x)
|
||||||
#define STBTT_free(x) free(x)
|
#define STBTT_free(x,u) free(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBTT_assert
|
#ifndef STBTT_assert
|
||||||
@ -335,6 +342,7 @@ extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
|
|||||||
// the stack or as a global or etc.
|
// the stack or as a global or etc.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
void *userdata;
|
||||||
unsigned char *data; // pointer to .ttf file
|
unsigned char *data; // pointer to .ttf file
|
||||||
int fontstart; // offset of start of font
|
int fontstart; // offset of start of font
|
||||||
|
|
||||||
@ -431,7 +439,7 @@ extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbt
|
|||||||
// returns # of vertices and fills *vertices with the pointer to them
|
// returns # of vertices and fills *vertices with the pointer to them
|
||||||
// these are expressed in "unscaled" coordinates
|
// these are expressed in "unscaled" coordinates
|
||||||
|
|
||||||
extern void stbtt_FreeShape(stbtt_vertex *vertices);
|
extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
|
||||||
// frees the data allocated above
|
// frees the data allocated above
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -439,7 +447,7 @@ extern void stbtt_FreeShape(stbtt_vertex *vertices);
|
|||||||
// BITMAP RENDERING
|
// BITMAP RENDERING
|
||||||
//
|
//
|
||||||
|
|
||||||
extern void stbtt_FreeBitmap(unsigned char *bitmap);
|
extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
|
||||||
// frees the bitmap allocated below
|
// 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);
|
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);
|
||||||
@ -477,7 +485,7 @@ typedef struct
|
|||||||
unsigned char *pixels;
|
unsigned char *pixels;
|
||||||
} stbtt__bitmap;
|
} 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);
|
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);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -577,6 +585,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // __STB_INCLUDE_STB_TRUETYPE_H__
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -629,7 +638,7 @@ static int stbtt__isfont(const stbtt_uint8 *font)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @OPTIMIZE: binary search
|
// @OPTIMIZE: binary search
|
||||||
static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, char *tag)
|
static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
|
||||||
{
|
{
|
||||||
stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
|
stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
|
||||||
stbtt_uint32 tabledir = fontstart + 12;
|
stbtt_uint32 tabledir = fontstart + 12;
|
||||||
@ -693,11 +702,17 @@ int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontsta
|
|||||||
for (i=0; i < numTables; ++i) {
|
for (i=0; i < numTables; ++i) {
|
||||||
stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
|
stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
|
||||||
// find an encoding we understand:
|
// find an encoding we understand:
|
||||||
if (ttUSHORT(data+encoding_record) == 3 && ttUSHORT(data+encoding_record+2) == 1) {
|
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
|
// MS/Unicode
|
||||||
info->index_map = cmap + ttULONG(data+encoding_record+4);
|
info->index_map = cmap + ttULONG(data+encoding_record+4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (info->index_map == 0)
|
if (info->index_map == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -760,7 +775,7 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
|
|||||||
}
|
}
|
||||||
search += 2;
|
search += 2;
|
||||||
|
|
||||||
item = (search - endCount) >> 1;
|
item = (stbtt_uint16) ((search - endCount) >> 1);
|
||||||
|
|
||||||
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
||||||
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
||||||
@ -773,6 +788,25 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
|
|||||||
return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item);
|
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);
|
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
|
// @TODO
|
||||||
STBTT_assert(0);
|
STBTT_assert(0);
|
||||||
@ -833,8 +867,8 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
stbtt_int16 numberOfContours;
|
stbtt_int16 numberOfContours;
|
||||||
stbtt_uint8 *endPtsOfContours;
|
stbtt_uint8 *endPtsOfContours;
|
||||||
stbtt_uint8 *data = info->data;
|
stbtt_uint8 *data = info->data;
|
||||||
stbtt_vertex *vertices;
|
stbtt_vertex *vertices=0;
|
||||||
int num_vertices;
|
int num_vertices=0;
|
||||||
int g = stbtt__GetGlyfOffset(info, glyph_index);
|
int g = stbtt__GetGlyfOffset(info, glyph_index);
|
||||||
|
|
||||||
*pvertices = NULL;
|
*pvertices = NULL;
|
||||||
@ -844,7 +878,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
numberOfContours = ttSHORT(data + g);
|
numberOfContours = ttSHORT(data + g);
|
||||||
|
|
||||||
if (numberOfContours > 0) {
|
if (numberOfContours > 0) {
|
||||||
stbtt_uint8 flags,flagcount;
|
stbtt_uint8 flags=0,flagcount;
|
||||||
stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;
|
stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;
|
||||||
stbtt_int16 x,y,cx,cy,sx,sy;
|
stbtt_int16 x,y,cx,cy,sx,sy;
|
||||||
stbtt_uint8 *points;
|
stbtt_uint8 *points;
|
||||||
@ -855,7 +889,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
|
n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
|
||||||
|
|
||||||
m = n + numberOfContours; // a loose bound on how many vertices we might need
|
m = n + numberOfContours; // a loose bound on how many vertices we might need
|
||||||
vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]));
|
vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
|
||||||
if (vertices == 0)
|
if (vertices == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -889,7 +923,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
x += (flags & 16) ? dx : -dx; // ???
|
x += (flags & 16) ? dx : -dx; // ???
|
||||||
} else {
|
} else {
|
||||||
if (!(flags & 16)) {
|
if (!(flags & 16)) {
|
||||||
x += (stbtt_int16) (points[0]*256 + points[1]);
|
x = x + (stbtt_int16) (points[0]*256 + points[1]);
|
||||||
points += 2;
|
points += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -905,7 +939,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
y += (flags & 32) ? dy : -dy; // ???
|
y += (flags & 32) ? dy : -dy; // ???
|
||||||
} else {
|
} else {
|
||||||
if (!(flags & 32)) {
|
if (!(flags & 32)) {
|
||||||
y += (stbtt_int16) (points[0]*256 + points[1]);
|
y = y + (stbtt_int16) (points[0]*256 + points[1]);
|
||||||
points += 2;
|
points += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -957,10 +991,89 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|||||||
else
|
else
|
||||||
stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
|
stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
|
||||||
}
|
}
|
||||||
} else if (numberOfContours < 0) {
|
} else if (numberOfContours == -1) {
|
||||||
// @TODO handle compound contours
|
// 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);
|
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;
|
*pvertices = vertices;
|
||||||
return num_vertices;
|
return num_vertices;
|
||||||
@ -1006,9 +1119,9 @@ float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
|
|||||||
return (float) height / fheight;
|
return (float) height / fheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stbtt_FreeShape(stbtt_vertex *v)
|
void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
||||||
{
|
{
|
||||||
STBTT_free(v);
|
STBTT_free(v, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -1035,6 +1148,7 @@ void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, floa
|
|||||||
|
|
||||||
typedef struct stbtt__edge {
|
typedef struct stbtt__edge {
|
||||||
float x0,y0, x1,y1;
|
float x0,y0, x1,y1;
|
||||||
|
int invert;
|
||||||
} stbtt__edge;
|
} stbtt__edge;
|
||||||
|
|
||||||
typedef struct stbtt__active_edge
|
typedef struct stbtt__active_edge
|
||||||
@ -1049,9 +1163,9 @@ typedef struct stbtt__active_edge
|
|||||||
#define FIX (1 << FIXSHIFT)
|
#define FIX (1 << FIXSHIFT)
|
||||||
#define FIXMASK (FIX-1)
|
#define FIXMASK (FIX-1)
|
||||||
|
|
||||||
static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point)
|
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)); // @TODO: make a pool of these!!!
|
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);
|
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||||
STBTT_assert(e->y0 <= start_point);
|
STBTT_assert(e->y0 <= start_point);
|
||||||
if (!z) return z;
|
if (!z) return z;
|
||||||
@ -1064,7 +1178,7 @@ static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_poi
|
|||||||
z->x -= off_x * FIX;
|
z->x -= off_x * FIX;
|
||||||
z->ey = e->y1;
|
z->ey = e->y1;
|
||||||
z->next = 0;
|
z->next = 0;
|
||||||
z->valid = 1;
|
z->valid = e->invert ? 1 : -1;
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,46 +1187,47 @@ static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_poi
|
|||||||
// are wrong, or if the user supplies a too-small bitmap
|
// 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)
|
static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
|
||||||
{
|
{
|
||||||
// @TODO: convert this from xor fill to non-zero winding
|
// non-zero winding fill
|
||||||
|
int x0=0, w=0;
|
||||||
|
|
||||||
while (e) {
|
while (e) {
|
||||||
int x0,x1,i,j;
|
if (w == 0) {
|
||||||
|
// if we're currently at zero, we need to record the edge start point
|
||||||
x0 = e->x; e = e->next;
|
x0 = e->x; w += e->valid;
|
||||||
if (!e)
|
} else {
|
||||||
return; // unbalanced number of edges
|
int x1 = e->x; w += e->valid;
|
||||||
|
// if we went to zero, we need to draw
|
||||||
x1 = e->x; e = e->next;
|
if (w == 0) {
|
||||||
STBTT_assert(x1 >= x0);
|
int i = x0 >> FIXSHIFT;
|
||||||
|
int j = x1 >> FIXSHIFT;
|
||||||
i = x0 >> FIXSHIFT;
|
|
||||||
j = x1 >> FIXSHIFT;
|
|
||||||
|
|
||||||
if (i < len && j >= 0) {
|
if (i < len && j >= 0) {
|
||||||
if (i == j) {
|
if (i == j) {
|
||||||
// x0,x1 are the same pixel, so compute combined coverage
|
// x0,x1 are the same pixel, so compute combined coverage
|
||||||
scanline[i] += (x1 - x0) * max_weight >> FIXSHIFT;
|
scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
|
||||||
} else {
|
} else {
|
||||||
if (i >= 0) // add antialiasing for x0
|
if (i >= 0) // add antialiasing for x0
|
||||||
scanline[i] += ((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT;
|
scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
|
||||||
else
|
else
|
||||||
i = -1; // clip
|
i = -1; // clip
|
||||||
|
|
||||||
if (j < len) // add antialiasing for x1
|
if (j < len) // add antialiasing for x1
|
||||||
scanline[j] += ((x1 & FIXMASK) * max_weight) >> FIXSHIFT;
|
scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
|
||||||
else
|
else
|
||||||
j = len; // clip
|
j = len; // clip
|
||||||
|
|
||||||
for (++i; i < j; ++i) // fill pixels between x0 and x1
|
for (++i; i < j; ++i) // fill pixels between x0 and x1
|
||||||
scanline[i] += max_weight;
|
scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!e)
|
e = e->next;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y)
|
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;
|
stbtt__active_edge *active = NULL;
|
||||||
int y,j=0;
|
int y,j=0;
|
||||||
@ -1121,7 +1236,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
unsigned char scanline_data[512], *scanline;
|
unsigned char scanline_data[512], *scanline;
|
||||||
|
|
||||||
if (result->w > 512)
|
if (result->w > 512)
|
||||||
scanline = (unsigned char *) STBTT_malloc(result->w);
|
scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
|
||||||
else
|
else
|
||||||
scanline = scanline_data;
|
scanline = scanline_data;
|
||||||
|
|
||||||
@ -1143,7 +1258,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
*step = z->next; // delete from list
|
*step = z->next; // delete from list
|
||||||
STBTT_assert(z->valid);
|
STBTT_assert(z->valid);
|
||||||
z->valid = 0;
|
z->valid = 0;
|
||||||
STBTT_free(z);
|
STBTT_free(z, userdata);
|
||||||
} else {
|
} else {
|
||||||
z->x += z->dx; // advance to position for current scanline
|
z->x += z->dx; // advance to position for current scanline
|
||||||
step = &((*step)->next); // advance through list
|
step = &((*step)->next); // advance through list
|
||||||
@ -1172,7 +1287,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
// insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
|
// insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
|
||||||
while (e->y0 <= scan_y) {
|
while (e->y0 <= scan_y) {
|
||||||
if (e->y1 > scan_y) {
|
if (e->y1 > scan_y) {
|
||||||
stbtt__active_edge *z = new_active(e, off_x, scan_y);
|
stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
|
||||||
// find insertion point
|
// find insertion point
|
||||||
if (active == NULL)
|
if (active == NULL)
|
||||||
active = z;
|
active = z;
|
||||||
@ -1206,11 +1321,11 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
|||||||
while (active) {
|
while (active) {
|
||||||
stbtt__active_edge *z = active;
|
stbtt__active_edge *z = active;
|
||||||
active = active->next;
|
active = active->next;
|
||||||
STBTT_free(z);
|
STBTT_free(z, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scanline != scanline_data)
|
if (scanline != scanline_data)
|
||||||
STBTT_free(scanline);
|
STBTT_free(scanline, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stbtt__edge_compare(const void *p, const void *q)
|
static int stbtt__edge_compare(const void *p, const void *q)
|
||||||
@ -1228,7 +1343,7 @@ typedef struct
|
|||||||
float x,y;
|
float x,y;
|
||||||
} stbtt__point;
|
} 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)
|
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;
|
float y_scale_inv = invert ? -scale_y : scale_y;
|
||||||
stbtt__edge *e;
|
stbtt__edge *e;
|
||||||
@ -1241,7 +1356,7 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
|||||||
for (i=0; i < windings; ++i)
|
for (i=0; i < windings; ++i)
|
||||||
n += wcount[i];
|
n += wcount[i];
|
||||||
|
|
||||||
e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1)); // add an extra one as a sentinel
|
e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
|
||||||
if (e == 0) return;
|
if (e == 0) return;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
@ -1256,8 +1371,11 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
|||||||
if (p[j].y == p[k].y)
|
if (p[j].y == p[k].y)
|
||||||
continue;
|
continue;
|
||||||
// add edge from j to k to the list
|
// add edge from j to k to the list
|
||||||
if (invert ? p[j].y > p[k].y : p[j].y < p[k].y)
|
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;
|
a=j,b=k;
|
||||||
|
}
|
||||||
e[n].x0 = p[a].x * scale_x;
|
e[n].x0 = p[a].x * scale_x;
|
||||||
e[n].y0 = p[a].y * y_scale_inv * vsubsample;
|
e[n].y0 = p[a].y * y_scale_inv * vsubsample;
|
||||||
e[n].x1 = p[b].x * scale_x;
|
e[n].x1 = p[b].x * scale_x;
|
||||||
@ -1270,9 +1388,9 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
|||||||
STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
|
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
|
// 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);
|
stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
|
||||||
|
|
||||||
STBTT_free(e);
|
STBTT_free(e, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
|
static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
|
||||||
@ -1304,7 +1422,7 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns number of contours
|
// returns number of contours
|
||||||
stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_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;
|
stbtt__point *points=0;
|
||||||
int num_points=0;
|
int num_points=0;
|
||||||
@ -1320,7 +1438,7 @@ stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float o
|
|||||||
*num_contours = n;
|
*num_contours = n;
|
||||||
if (n == 0) return 0;
|
if (n == 0) return 0;
|
||||||
|
|
||||||
*contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n);
|
*contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
|
||||||
|
|
||||||
if (*contour_lengths == 0) {
|
if (*contour_lengths == 0) {
|
||||||
*num_contours = 0;
|
*num_contours = 0;
|
||||||
@ -1329,9 +1447,9 @@ stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float o
|
|||||||
|
|
||||||
// make two passes through the points so we don't need to realloc
|
// make two passes through the points so we don't need to realloc
|
||||||
for (pass=0; pass < 2; ++pass) {
|
for (pass=0; pass < 2; ++pass) {
|
||||||
float x,y;
|
float x=0,y=0;
|
||||||
if (pass == 1) {
|
if (pass == 1) {
|
||||||
points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]));
|
points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
|
||||||
if (points == NULL) goto error;
|
if (points == NULL) goto error;
|
||||||
}
|
}
|
||||||
num_points = 0;
|
num_points = 0;
|
||||||
@ -1366,28 +1484,28 @@ stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float o
|
|||||||
|
|
||||||
return points;
|
return points;
|
||||||
error:
|
error:
|
||||||
STBTT_free(points);
|
STBTT_free(points, userdata);
|
||||||
STBTT_free(*contour_lengths);
|
STBTT_free(*contour_lengths, userdata);
|
||||||
*contour_lengths = 0;
|
*contour_lengths = 0;
|
||||||
*num_contours = 0;
|
*num_contours = 0;
|
||||||
return NULL;
|
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 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;
|
float scale = scale_x > scale_y ? scale_y : scale_x;
|
||||||
int winding_count, *winding_lengths;
|
int winding_count, *winding_lengths;
|
||||||
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count);
|
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
|
||||||
if (windings) {
|
if (windings) {
|
||||||
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert);
|
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata);
|
||||||
STBTT_free(winding_lengths);
|
STBTT_free(winding_lengths, userdata);
|
||||||
STBTT_free(windings);
|
STBTT_free(windings, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stbtt_FreeBitmap(unsigned char *bitmap)
|
void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
|
||||||
{
|
{
|
||||||
STBTT_free(bitmap);
|
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)
|
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
|
||||||
@ -1416,14 +1534,14 @@ unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, f
|
|||||||
if (yoff ) *yoff = iy0;
|
if (yoff ) *yoff = iy0;
|
||||||
|
|
||||||
if (gbm.w && gbm.h) {
|
if (gbm.w && gbm.h) {
|
||||||
gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h);
|
gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
|
||||||
if (gbm.pixels) {
|
if (gbm.pixels) {
|
||||||
gbm.stride = gbm.w;
|
gbm.stride = gbm.w;
|
||||||
|
|
||||||
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1);
|
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STBTT_free(vertices);
|
STBTT_free(vertices, info->userdata);
|
||||||
return gbm.pixels;
|
return gbm.pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1441,9 +1559,9 @@ void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, in
|
|||||||
gbm.stride = out_stride;
|
gbm.stride = out_stride;
|
||||||
|
|
||||||
if (gbm.w && gbm.h)
|
if (gbm.w && gbm.h)
|
||||||
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1);
|
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata);
|
||||||
|
|
||||||
STBTT_free(vertices);
|
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)
|
unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
|
||||||
@ -1492,10 +1610,10 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font
|
|||||||
STBTT_assert(x+gw < pw);
|
STBTT_assert(x+gw < pw);
|
||||||
STBTT_assert(y+gh < ph);
|
STBTT_assert(y+gh < ph);
|
||||||
stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
|
stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
|
||||||
chardata[i].x0 = x;
|
chardata[i].x0 = (stbtt_int16) x;
|
||||||
chardata[i].y0 = y;
|
chardata[i].y0 = (stbtt_int16) y;
|
||||||
chardata[i].x1 = x + gw;
|
chardata[i].x1 = (stbtt_int16) (x + gw);
|
||||||
chardata[i].y1 = y + gh;
|
chardata[i].y1 = (stbtt_int16) (y + gh);
|
||||||
chardata[i].xadvance = scale * advance;
|
chardata[i].xadvance = scale * advance;
|
||||||
chardata[i].xoff = (float) x0;
|
chardata[i].xoff = (float) x0;
|
||||||
chardata[i].yoff = (float) y0;
|
chardata[i].yoff = (float) y0;
|
||||||
@ -1509,19 +1627,20 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font
|
|||||||
void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
|
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 d3d_bias = opengl_fillrule ? 0 : -0.5f;
|
||||||
|
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||||
stbtt_bakedchar *b = chardata + char_index;
|
stbtt_bakedchar *b = chardata + char_index;
|
||||||
int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
|
int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
|
||||||
int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
|
int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
|
||||||
|
|
||||||
q->x0 = round_x - 0.5f + d3d_bias;
|
q->x0 = round_x + d3d_bias;
|
||||||
q->y0 = round_y - 0.5f + d3d_bias;
|
q->y0 = round_y + d3d_bias;
|
||||||
q->x1 = round_x + b->x1 - b->x0 + 0.5f + d3d_bias;
|
q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
|
||||||
q->y1 = round_y + b->y1 - b->y0 + 0.5f + d3d_bias;
|
q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
|
||||||
|
|
||||||
q->s0 = (b->x0 - 0.5f) / pw;
|
q->s0 = b->x0 * ipw;
|
||||||
q->t0 = (b->y0 - 0.5f) / pw;
|
q->t0 = b->y0 * ipw;
|
||||||
q->s1 = (b->x1 + 0.5f) / ph;
|
q->s1 = b->x1 * iph;
|
||||||
q->t1 = (b->y1 + 0.5f) / ph;
|
q->t1 = b->y1 * iph;
|
||||||
|
|
||||||
*xpos += b->xadvance;
|
*xpos += b->xadvance;
|
||||||
}
|
}
|
||||||
@ -1685,5 +1804,3 @@ int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // STB_TRUETYPE_IMPLEMENTATION
|
#endif // STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
|
||||||
#endif // __STB_INCLUDE_STB_TRUETYPE_H__
|
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_opengl.h"
|
#include "SDL_opengl.h"
|
||||||
#define STBTT_malloc(x) malloc(x)
|
#define STBTT_malloc(x,y) malloc(x)
|
||||||
#define STBTT_free(x) free(x)
|
#define STBTT_free(x,y) free(x)
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include "stb_truetype.h"
|
#include "stb_truetype.h"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user