|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools
|
|
|
|
|
// stb_truetype.h - v0.7 - public domain
|
|
|
|
|
// authored from 2009-2013 by Sean Barrett / RAD Game Tools
|
|
|
|
|
//
|
|
|
|
|
// This library processes TrueType files:
|
|
|
|
|
// parse files
|
|
|
|
@ -9,20 +10,52 @@
|
|
|
|
|
// Todo:
|
|
|
|
|
// non-MS cmaps
|
|
|
|
|
// crashproof on bad data
|
|
|
|
|
// hinting
|
|
|
|
|
// subpixel positioning when rendering bitmap
|
|
|
|
|
// cleartype-style AA
|
|
|
|
|
// hinting? (no longer patented)
|
|
|
|
|
// cleartype-style AA?
|
|
|
|
|
// optimize: use simple memory allocator for intermediates
|
|
|
|
|
// optimize: build edge-list directly from curves
|
|
|
|
|
// optimize: rasterize directly from curves?
|
|
|
|
|
//
|
|
|
|
|
// ADDITIONAL CONTRIBUTORS
|
|
|
|
|
//
|
|
|
|
|
// Mikko Mononen: compound shape support, more cmap formats
|
|
|
|
|
// Tor Andersson: kerning, subpixel rendering
|
|
|
|
|
//
|
|
|
|
|
// VERSIONS
|
|
|
|
|
// Bug/warning reports:
|
|
|
|
|
// "Zer" on mollyrocket (with fix)
|
|
|
|
|
// Cass Everitt
|
|
|
|
|
// stoiko (Haemimont Games)
|
|
|
|
|
// Brian Hook
|
|
|
|
|
// Walter van Niftrik
|
|
|
|
|
//
|
|
|
|
|
// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
|
|
|
|
|
// VERSION HISTORY
|
|
|
|
|
//
|
|
|
|
|
// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
|
|
|
|
|
// 0.6c (2012-07-24) improve documentation
|
|
|
|
|
// 0.6b (2012-07-20) fix a few more warnings
|
|
|
|
|
// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
|
|
|
|
|
// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
|
|
|
|
|
// 0.5 (2011-12-09) bugfixes:
|
|
|
|
|
// subpixel glyph renderer computed wrong bounding box
|
|
|
|
|
// first vertex of shape can be off-curve (FreeSans)
|
|
|
|
|
// 0.4b (2011-12-03) fixed an error in the font baking example
|
|
|
|
|
// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
|
|
|
|
|
// bugfixes for:
|
|
|
|
|
// codepoint-to-glyph conversion using table fmt=12
|
|
|
|
|
// codepoint-to-glyph conversion using table fmt=4
|
|
|
|
|
// stbtt_GetBakedQuad with non-square texture (Zer)
|
|
|
|
|
// updated Hello World! sample to use kerning and subpixel
|
|
|
|
|
// fixed some warnings
|
|
|
|
|
// 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
|
|
|
|
|
// 0.2 (2009-03-11) Fix unsigned/signed char warnings
|
|
|
|
|
// 0.1 (2009-03-09) First public release
|
|
|
|
|
//
|
|
|
|
|
// LICENSE
|
|
|
|
|
//
|
|
|
|
|
// This software is in the public domain. Where that dedication is not
|
|
|
|
|
// recognized, you are granted a perpetual, irrevokable license to copy
|
|
|
|
|
// and modify this file as you see fit.
|
|
|
|
|
//
|
|
|
|
|
// USAGE
|
|
|
|
|
//
|
|
|
|
@ -32,8 +65,6 @@
|
|
|
|
|
// 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
|
|
|
|
@ -51,6 +82,83 @@
|
|
|
|
|
// Character advance/positioning
|
|
|
|
|
// stbtt_GetCodepointHMetrics()
|
|
|
|
|
// stbtt_GetFontVMetrics()
|
|
|
|
|
// stbtt_GetCodepointKernAdvance()
|
|
|
|
|
//
|
|
|
|
|
// ADDITIONAL DOCUMENTATION
|
|
|
|
|
//
|
|
|
|
|
// Immediately after this block comment are a series of sample programs.
|
|
|
|
|
//
|
|
|
|
|
// After the sample programs is the "header file" section. This section
|
|
|
|
|
// includes documentation for each API function.
|
|
|
|
|
//
|
|
|
|
|
// Some important concepts to understand to use this library:
|
|
|
|
|
//
|
|
|
|
|
// Codepoint
|
|
|
|
|
// Characters are defined by unicode codepoints, e.g. 65 is
|
|
|
|
|
// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
|
|
|
|
|
// the hiragana for "ma".
|
|
|
|
|
//
|
|
|
|
|
// Glyph
|
|
|
|
|
// A visual character shape (every codepoint is rendered as
|
|
|
|
|
// some glyph)
|
|
|
|
|
//
|
|
|
|
|
// Glyph index
|
|
|
|
|
// A font-specific integer ID representing a glyph
|
|
|
|
|
//
|
|
|
|
|
// Baseline
|
|
|
|
|
// Glyph shapes are defined relative to a baseline, which is the
|
|
|
|
|
// bottom of uppercase characters. Characters extend both above
|
|
|
|
|
// and below the baseline.
|
|
|
|
|
//
|
|
|
|
|
// Current Point
|
|
|
|
|
// As you draw text to the screen, you keep track of a "current point"
|
|
|
|
|
// which is the origin of each character. The current point's vertical
|
|
|
|
|
// position is the baseline. Even "baked fonts" use this model.
|
|
|
|
|
//
|
|
|
|
|
// Vertical Font Metrics
|
|
|
|
|
// The vertical qualities of the font, used to vertically position
|
|
|
|
|
// and space the characters. See docs for stbtt_GetFontVMetrics.
|
|
|
|
|
//
|
|
|
|
|
// Font Size in Pixels or Points
|
|
|
|
|
// The preferred interface for specifying font sizes in stb_truetype
|
|
|
|
|
// is to specify how tall the font's vertical extent should be in pixels.
|
|
|
|
|
// If that sounds good enough, skip the next paragraph.
|
|
|
|
|
//
|
|
|
|
|
// Most font APIs instead use "points", which are a common typographic
|
|
|
|
|
// measurement for describing font size, defined as 72 points per inch.
|
|
|
|
|
// stb_truetype provides a point API for compatibility. However, true
|
|
|
|
|
// "per inch" conventions don't make much sense on computer displays
|
|
|
|
|
// since they different monitors have different number of pixels per
|
|
|
|
|
// inch. For example, Windows traditionally uses a convention that
|
|
|
|
|
// there are 96 pixels per inch, thus making 'inch' measurements have
|
|
|
|
|
// nothing to do with inches, and thus effectively defining a point to
|
|
|
|
|
// be 1.333 pixels. Additionally, the TrueType font data provides
|
|
|
|
|
// an explicit scale factor to scale a given font's glyphs to points,
|
|
|
|
|
// but the author has observed that this scale factor is often wrong
|
|
|
|
|
// for non-commercial fonts, thus making fonts scaled in points
|
|
|
|
|
// according to the TrueType spec incoherently sized in practice.
|
|
|
|
|
//
|
|
|
|
|
// ADVANCED USAGE
|
|
|
|
|
//
|
|
|
|
|
// Quality:
|
|
|
|
|
//
|
|
|
|
|
// - Use the functions with Subpixel at the end to allow your characters
|
|
|
|
|
// to have subpixel positioning. Since the font is anti-aliased, not
|
|
|
|
|
// hinted, this is very import for quality. (This is not possible with
|
|
|
|
|
// baked fonts.)
|
|
|
|
|
//
|
|
|
|
|
// - Kerning is now supported, and if you're supporting subpixel rendering
|
|
|
|
|
// then kerning is worth using to give your text a polished look.
|
|
|
|
|
//
|
|
|
|
|
// Performance:
|
|
|
|
|
//
|
|
|
|
|
// - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
|
|
|
|
|
// if you don't do this, stb_truetype is forced to do the conversion on
|
|
|
|
|
// every call.
|
|
|
|
|
//
|
|
|
|
|
// - There are a lot of memory allocations. We should modify it to take
|
|
|
|
|
// a temp buffer and allocate from the temp buffer (without freeing),
|
|
|
|
|
// should help performance a lot.
|
|
|
|
|
//
|
|
|
|
|
// NOTES
|
|
|
|
|
//
|
|
|
|
@ -64,14 +172,14 @@
|
|
|
|
|
// recommend it.
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// SOURCE STATISTICS (based on v0.3, 1800 LOC)
|
|
|
|
|
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
|
|
|
|
|
//
|
|
|
|
|
// Documentation & header file 350 LOC \___ 500 LOC documentation
|
|
|
|
|
// Documentation & header file 520 LOC \___ 660 LOC documentation
|
|
|
|
|
// Sample code 140 LOC /
|
|
|
|
|
// Truetype parsing 580 LOC ---- 600 LOC TrueType
|
|
|
|
|
// Truetype parsing 620 LOC ---- 620 LOC TrueType
|
|
|
|
|
// Software rasterization 240 LOC \ .
|
|
|
|
|
// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation
|
|
|
|
|
// Bitmap management 70 LOC /
|
|
|
|
|
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
|
|
|
|
|
// Bitmap management 100 LOC /
|
|
|
|
|
// Baked bitmap interface 70 LOC /
|
|
|
|
|
// Font name matching & access 150 LOC ---- 150
|
|
|
|
|
// C runtime library abstraction 60 LOC ---- 60
|
|
|
|
@ -92,7 +200,7 @@
|
|
|
|
|
char ttf_buffer[1<<20];
|
|
|
|
|
unsigned char temp_bitmap[512*512];
|
|
|
|
|
|
|
|
|
|
stbtt_chardata cdata[96]; // ASCII 32..126 is 95 glyphs
|
|
|
|
|
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
|
|
|
|
|
GLstbtt_uint ftex;
|
|
|
|
|
|
|
|
|
|
void my_stbtt_initfont(void)
|
|
|
|
@ -177,33 +285,41 @@ int main(int argc, char **argv)
|
|
|
|
|
// Complete program: print "Hello World!" banner, with bugs
|
|
|
|
|
//
|
|
|
|
|
#if 0
|
|
|
|
|
char buffer[24<<20];
|
|
|
|
|
unsigned char screen[20][79];
|
|
|
|
|
|
|
|
|
|
int main(int arg, char **argv)
|
|
|
|
|
{
|
|
|
|
|
unsigned char screen[20][79];
|
|
|
|
|
int i,j, pos=0;
|
|
|
|
|
float scale;
|
|
|
|
|
stbtt_fontinfo font;
|
|
|
|
|
int i,j,ascent,baseline,ch=0;
|
|
|
|
|
float scale, xpos=0;
|
|
|
|
|
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));
|
|
|
|
|
scale = stbtt_ScaleForPixelHeight(&font, 15);
|
|
|
|
|
stbtt_GetFontVMetrics(&font, &ascent,0,0);
|
|
|
|
|
baseline = (int) (ascent*scale);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
while (text[ch]) {
|
|
|
|
|
int advance,lsb,x0,y0,x1,y1;
|
|
|
|
|
float x_shift = xpos - (float) floor(xpos);
|
|
|
|
|
stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
|
|
|
|
|
stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
|
|
|
|
|
stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
|
|
|
|
|
// 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;
|
|
|
|
|
// because this API is really for baking character bitmaps into textures. if you want to render
|
|
|
|
|
// a sequence of characters, you really need to render each bitmap to a temp buffer, then
|
|
|
|
|
// "alpha blend" that into the working buffer
|
|
|
|
|
xpos += (advance * scale);
|
|
|
|
|
if (text[ch+1])
|
|
|
|
|
xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
|
|
|
|
|
++ch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j=0; j < 20; ++j) {
|
|
|
|
|
for (i=0; i < 79; ++i)
|
|
|
|
|
for (i=0; i < 78; ++i)
|
|
|
|
|
putchar(" .:ioVM@"[screen[j][i]>>5]);
|
|
|
|
|
putchar('\n');
|
|
|
|
|
}
|
|
|
|
@ -216,8 +332,10 @@ int main(int arg, char **argv)
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////
|
|
|
|
|
//// INTEGRATION WITH RUNTIME LIBRARIES
|
|
|
|
|
//// INTEGRATION WITH YOUR CODEBASE
|
|
|
|
|
////
|
|
|
|
|
//// The following sections allow you to supply alternate definitions
|
|
|
|
|
//// of C library functions used by stb_truetype.
|
|
|
|
|
|
|
|
|
|
#ifdef STB_TRUETYPE_IMPLEMENTATION
|
|
|
|
|
// #define your own (u)stbtt_int8/16/32 before including to override this
|
|
|
|
@ -320,6 +438,12 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa
|
|
|
|
|
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.
|
|
|
|
|
//
|
|
|
|
|
// The coordinate system used assumes y increases downwards.
|
|
|
|
|
//
|
|
|
|
|
// Characters will extend both above and below the current position;
|
|
|
|
|
// see discussion of "BASELINE" above.
|
|
|
|
|
//
|
|
|
|
|
// It's inefficient; you might want to c&p it and optimize it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -330,35 +454,35 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
// Each .ttf/.ttc file may have more than one font. Each font 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
|
|
|
|
|
// the stack or as a global or etc, but you should treat it as opaque.
|
|
|
|
|
typedef struct stbtt_fontinfo
|
|
|
|
|
{
|
|
|
|
|
void *userdata;
|
|
|
|
|
unsigned char *data; // pointer to .ttf file
|
|
|
|
|
int fontstart; // offset of start of font
|
|
|
|
|
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 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
|
|
|
|
|
int loca,head,glyf,hhea,hmtx,kern; // 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.
|
|
|
|
|
// need to do anything special to free it, because the contents are pure
|
|
|
|
|
// value data with no additional data structures. Returns 0 on failure.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
@ -385,12 +509,21 @@ extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
|
|
|
|
|
// scale = pixels / (ascent - descent)
|
|
|
|
|
// so if you prefer to measure height by the ascent only, use a similar calculation.
|
|
|
|
|
|
|
|
|
|
extern float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
|
|
|
|
|
// computes a scale factor to produce a font whose EM size is mapped to
|
|
|
|
|
// 'pixels' tall. This is probably what traditional APIs compute, but
|
|
|
|
|
// I'm not positive.
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
// these are expressed in unscaled coordinates, so you must multiply by
|
|
|
|
|
// the scale factor for a given size
|
|
|
|
|
|
|
|
|
|
extern void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
|
|
|
|
|
// the bounding box around all possible characters
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@ -434,6 +567,9 @@ extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *
|
|
|
|
|
} stbtt_vertex;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
extern int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
|
|
|
|
|
// returns non-zero if nothing is drawn for this glyph
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@ -459,11 +595,19 @@ extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float
|
|
|
|
|
//
|
|
|
|
|
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
|
|
|
|
|
|
|
|
|
|
extern unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
|
|
|
|
|
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
|
|
|
|
|
// shift for the character
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
// the same as stbtt_GetCodepointBitmap, 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 stbtt_GetCodepointBitmapBox to get the
|
|
|
|
|
// width and height and positioning info for it first.
|
|
|
|
|
|
|
|
|
|
extern void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
|
|
|
|
|
// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
|
|
|
|
|
// shift for the character
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@ -472,11 +616,19 @@ extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoin
|
|
|
|
|
// (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_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
|
|
|
|
|
// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
|
|
|
|
|
// shift for the character
|
|
|
|
|
|
|
|
|
|
// the following functions are equivalent to the above functions, but operate
|
|
|
|
|
// on glyph indices instead of Unicode codepoints (for efficiency)
|
|
|
|
|
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 unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
|
|
|
|
|
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_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
|
|
|
|
|
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_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
|
|
|
|
|
|
|
|
|
|
//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
|
|
|
|
@ -485,7 +637,7 @@ typedef struct
|
|
|
|
|
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);
|
|
|
|
|
extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata);
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
@ -524,7 +676,7 @@ extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const ch
|
|
|
|
|
// 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);
|
|
|
|
|
extern const 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.
|
|
|
|
|
//
|
|
|
|
@ -544,21 +696,21 @@ enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
|
|
|
|
|
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,
|
|
|
|
|
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,
|
|
|
|
|
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,
|
|
|
|
|
STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
|
|
|
|
@ -568,7 +720,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
|
|
|
|
|
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,
|
|
|
|
|
STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum { // languageID for STBTT_PLATFORM_ID_MAC
|
|
|
|
@ -578,7 +730,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
|
|
|
|
|
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,
|
|
|
|
|
STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
@ -630,7 +782,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
|
|
|
|
|
static int stbtt__isfont(const stbtt_uint8 *font)
|
|
|
|
|
{
|
|
|
|
|
// check the version number
|
|
|
|
|
if (stbtt_tag(font, "1")) return 1; // TrueType 1
|
|
|
|
|
if (stbtt_tag4(font, '1',0,0,0)) 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
|
|
|
|
@ -679,12 +831,13 @@ int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontsta
|
|
|
|
|
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");
|
|
|
|
|
cmap = stbtt__find_table(data, fontstart, "cmap"); // required
|
|
|
|
|
info->loca = stbtt__find_table(data, fontstart, "loca"); // required
|
|
|
|
|
info->head = stbtt__find_table(data, fontstart, "head"); // required
|
|
|
|
|
info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
|
|
|
|
|
info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
|
|
|
|
|
info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
|
|
|
|
|
info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
|
|
|
|
|
if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
@ -746,7 +899,7 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
|
|
|
|
|
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;
|
|
|
|
|
stbtt_uint16 item, offset, start;
|
|
|
|
|
|
|
|
|
|
// do a binary search of the segments
|
|
|
|
|
stbtt_uint32 endCount = index_map + 14;
|
|
|
|
@ -763,11 +916,9 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
|
|
|
|
|
// now decrement to bias correctly to find smallest
|
|
|
|
|
search -= 2;
|
|
|
|
|
while (entrySelector) {
|
|
|
|
|
stbtt_uint16 start, end;
|
|
|
|
|
stbtt_uint16 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;
|
|
|
|
@ -779,31 +930,33 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
|
|
|
|
|
|
|
|
|
|
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 (stbtt_uint16) (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);
|
|
|
|
|
} else if (format == 12 || format == 13) {
|
|
|
|
|
stbtt_uint32 ngroups = ttULONG(data+index_map+12);
|
|
|
|
|
stbtt_int32 low,high;
|
|
|
|
|
low = 0; high = (stbtt_int32)ngroups;
|
|
|
|
|
// Binary search the right group.
|
|
|
|
|
while (low <= high) {
|
|
|
|
|
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;
|
|
|
|
|
high = mid;
|
|
|
|
|
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;
|
|
|
|
|
if (format == 12)
|
|
|
|
|
return start_glyph + unicode_codepoint-start_char;
|
|
|
|
|
else // format == 13
|
|
|
|
|
return start_glyph;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0; // not found
|
|
|
|
@ -818,13 +971,13 @@ int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, s
|
|
|
|
|
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)
|
|
|
|
|
static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
|
|
|
|
|
{
|
|
|
|
|
v->type = type;
|
|
|
|
|
v->x = x;
|
|
|
|
|
v->y = y;
|
|
|
|
|
v->cx = cx;
|
|
|
|
|
v->cy = cy;
|
|
|
|
|
v->x = (stbtt_int16) x;
|
|
|
|
|
v->y = (stbtt_int16) y;
|
|
|
|
|
v->cx = (stbtt_int16) cx;
|
|
|
|
|
v->cy = (stbtt_int16) cy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
|
|
|
|
@ -862,6 +1015,31 @@ int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, in
|
|
|
|
|
return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
|
|
|
|
|
{
|
|
|
|
|
stbtt_int16 numberOfContours;
|
|
|
|
|
int g = stbtt__GetGlyfOffset(info, glyph_index);
|
|
|
|
|
if (g < 0) return 1;
|
|
|
|
|
numberOfContours = ttSHORT(info->data + g);
|
|
|
|
|
return numberOfContours == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
|
|
|
|
|
stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
|
|
|
|
|
{
|
|
|
|
|
if (start_off) {
|
|
|
|
|
if (was_off)
|
|
|
|
|
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
|
|
|
|
|
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
|
|
|
|
|
} else {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
return num_vertices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
|
|
|
|
|
{
|
|
|
|
|
stbtt_int16 numberOfContours;
|
|
|
|
@ -879,8 +1057,8 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|
|
|
|
|
|
|
|
|
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_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
|
|
|
|
|
stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
|
|
|
|
|
stbtt_uint8 *points;
|
|
|
|
|
endPtsOfContours = (data + g + 10);
|
|
|
|
|
ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
|
|
|
|
@ -888,7 +1066,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|
|
|
|
|
|
|
|
|
n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
|
|
|
|
|
|
|
|
|
|
m = n + numberOfContours; // a loose bound on how many vertices we might need
|
|
|
|
|
m = n + 2*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;
|
|
|
|
@ -927,7 +1105,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|
|
|
|
points += 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vertices[off+i].x = x;
|
|
|
|
|
vertices[off+i].x = (stbtt_int16) x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now load y coordinates
|
|
|
|
@ -943,32 +1121,46 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|
|
|
|
points += 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vertices[off+i].y = y;
|
|
|
|
|
vertices[off+i].y = (stbtt_int16) y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now convert them to our format
|
|
|
|
|
num_vertices=0;
|
|
|
|
|
sx = sy = cx = cy = 0;
|
|
|
|
|
sx = sy = cx = cy = scx = scy = 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);
|
|
|
|
|
}
|
|
|
|
|
if (i != 0)
|
|
|
|
|
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
|
|
|
|
|
|
|
|
|
// now start the new one
|
|
|
|
|
stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,x,y,0,0);
|
|
|
|
|
start_off = !(flags & 1);
|
|
|
|
|
if (start_off) {
|
|
|
|
|
// if we start off with an off-curve point, then when we need to find a point on the curve
|
|
|
|
|
// where we can start, and we need to save some state for when we wraparound.
|
|
|
|
|
scx = x;
|
|
|
|
|
scy = y;
|
|
|
|
|
if (!(vertices[off+i+1].type & 1)) {
|
|
|
|
|
// next point is also a curve point, so interpolate an on-point curve
|
|
|
|
|
sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
|
|
|
|
|
sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
|
|
|
|
|
} else {
|
|
|
|
|
// otherwise just use the next point as our start point
|
|
|
|
|
sx = (stbtt_int32) vertices[off+i+1].x;
|
|
|
|
|
sy = (stbtt_int32) vertices[off+i+1].y;
|
|
|
|
|
++i; // we're using point i+1 as the starting point, so skip it
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
sx = x;
|
|
|
|
|
sy = y;
|
|
|
|
|
}
|
|
|
|
|
stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
|
|
|
|
|
was_off = 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
|
|
|
|
@ -985,12 +1177,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
|
|
|
|
} else if (numberOfContours == -1) {
|
|
|
|
|
// Compound shapes.
|
|
|
|
|
int more = 1;
|
|
|
|
@ -1091,14 +1278,41 @@ void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *ad
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * /*info*/, int /*glyph1*/, int /*glyph2*/)
|
|
|
|
|
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
|
|
|
|
|
{
|
|
|
|
|
stbtt_uint8 *data = info->data + info->kern;
|
|
|
|
|
stbtt_uint32 needle, straw;
|
|
|
|
|
int l, r, m;
|
|
|
|
|
|
|
|
|
|
// we only look at the first table. it must be 'horizontal' and format 0.
|
|
|
|
|
if (!info->kern)
|
|
|
|
|
return 0;
|
|
|
|
|
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
|
|
|
|
return 0;
|
|
|
|
|
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
|
r = ttUSHORT(data+10) - 1;
|
|
|
|
|
needle = glyph1 << 16 | glyph2;
|
|
|
|
|
while (l <= r) {
|
|
|
|
|
m = (l + r) >> 1;
|
|
|
|
|
straw = ttULONG(data+18+(m*6)); // note: unaligned read
|
|
|
|
|
if (needle < straw)
|
|
|
|
|
r = m - 1;
|
|
|
|
|
else if (needle > straw)
|
|
|
|
|
l = m + 1;
|
|
|
|
|
else
|
|
|
|
|
return ttSHORT(data+22+(m*6));
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * /*info*/, int /*ch1*/, int /*ch2*/)
|
|
|
|
|
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs
|
|
|
|
|
return 0;
|
|
|
|
|
return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
|
|
|
|
@ -1113,12 +1327,26 @@ void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent
|
|
|
|
|
if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
|
|
|
|
|
{
|
|
|
|
|
*x0 = ttSHORT(info->data + info->head + 36);
|
|
|
|
|
*y0 = ttSHORT(info->data + info->head + 38);
|
|
|
|
|
*x1 = ttSHORT(info->data + info->head + 40);
|
|
|
|
|
*y1 = ttSHORT(info->data + info->head + 42);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
|
|
|
|
|
{
|
|
|
|
|
int unitsPerEm = ttUSHORT(info->data + info->head + 18);
|
|
|
|
|
return pixels / unitsPerEm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
|
|
|
|
{
|
|
|
|
|
STBTT_free(v, info->userdata);
|
|
|
|
@ -1129,21 +1357,30 @@ void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
|
|
|
|
// 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)
|
|
|
|
|
void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x);
|
|
|
|
|
if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y);
|
|
|
|
|
if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x);
|
|
|
|
|
if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y);
|
|
|
|
|
}
|
|
|
|
|
void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
|
|
|
|
{
|
|
|
|
|
stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
|
|
|
|
{
|
|
|
|
|
stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct stbtt__edge {
|
|
|
|
@ -1343,7 +1580,7 @@ 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)
|
|
|
|
|
static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
|
|
|
|
|
{
|
|
|
|
|
float y_scale_inv = invert ? -scale_y : scale_y;
|
|
|
|
|
stbtt__edge *e;
|
|
|
|
@ -1376,10 +1613,10 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
|
|
|
|
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;
|
|
|
|
|
e[n].x0 = p[a].x * scale_x + shift_x;
|
|
|
|
|
e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y;
|
|
|
|
|
e[n].x1 = p[b].x * scale_x + shift_x;
|
|
|
|
|
e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y;
|
|
|
|
|
++n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1491,13 +1728,13 @@ error:
|
|
|
|
|
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)
|
|
|
|
|
void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
|
|
|
|
|
{
|
|
|
|
|
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__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
|
|
|
|
|
STBTT_free(winding_lengths, userdata);
|
|
|
|
|
STBTT_free(windings, userdata);
|
|
|
|
|
}
|
|
|
|
@ -1508,7 +1745,7 @@ 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)
|
|
|
|
|
unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
|
|
|
|
|
{
|
|
|
|
|
int ix0,iy0,ix1,iy1;
|
|
|
|
|
stbtt__bitmap gbm;
|
|
|
|
@ -1521,7 +1758,7 @@ unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, f
|
|
|
|
|
scale_y = scale_x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
|
|
|
|
|
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
|
|
|
|
|
|
|
|
|
|
// now we get the size
|
|
|
|
|
gbm.w = (ix1 - ix0);
|
|
|
|
@ -1538,47 +1775,67 @@ unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, f
|
|
|
|
|
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_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_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)
|
|
|
|
|
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
|
|
|
|
|
{
|
|
|
|
|
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_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);
|
|
|
|
|
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_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_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
|
|
|
|
|
|
|
|
|
|
STBTT_free(vertices, info->userdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
|
|
|
|
|
{
|
|
|
|
|
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
|
|
|
|
|
{
|
|
|
|
|
stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, 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));
|
|
|
|
|
stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// bitmap baking
|
|
|
|
|
//
|
|
|
|
|
// This is SUPER-SHITTY packing to keep source code small
|
|
|
|
|
// This is SUPER-CRAPPY 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
|
|
|
|
@ -1638,8 +1895,8 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
|
|
|
|
|
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->t0 = b->y0 * iph;
|
|
|
|
|
q->s1 = b->x1 * ipw;
|
|
|
|
|
q->t1 = b->y1 * iph;
|
|
|
|
|
|
|
|
|
|
*xpos += b->xadvance;
|
|
|
|
@ -1651,7 +1908,7 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2)
|
|
|
|
|
{
|
|
|
|
|
stbtt_int32 i=0;
|
|
|
|
|
|
|
|
|
@ -1692,12 +1949,12 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const 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)
|
|
|
|
|
const 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;
|
|
|
|
@ -1712,7 +1969,7 @@ char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platf
|
|
|
|
|
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 (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
@ -1765,7 +2022,7 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name,
|
|
|
|
|
|
|
|
|
|
static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
|
|
|
|
|
{
|
|
|
|
|
stbtt_int32 nlen = STBTT_strlen((char *) name);
|
|
|
|
|
stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
|
|
|
|
|
stbtt_uint32 nm,hd;
|
|
|
|
|
if (!stbtt__isfont(fc+offset)) return 0;
|
|
|
|
|
|
|
|
|
|