diff --git a/project/src/text/Font.cpp b/project/src/text/Font.cpp index 033759f2a..13f422230 100644 --- a/project/src/text/Font.cpp +++ b/project/src/text/Font.cpp @@ -16,6 +16,12 @@ #include FT_OUTLINE_H #endif +#ifdef ANDROID +#include +#include +#include +#endif + // from http://stackoverflow.com/questions/2948308/how-do-i-read-utf-8-characters-via-a-pointer #define IS_IN_RANGE(c, f, l) (((c) >= (f)) && ((c) <= (l))) @@ -622,6 +628,136 @@ namespace lime { } + #ifdef ANDROID + /* + * This code was written by Rich Felker in 2010; no copyright is claimed. + * This code is in the public domain. Attribution is appreciated but + * unnecessary. + */ + #define OOB(c,b) (((((b)>>3)-0x10)|(((b)>>3)+((int32_t)(c)>>26))) & ~7) + #define R(a,b) ((uint32_t)((a==0x80 ? 0x40-b : -a) << 23)) + #define C(x) ( x<2 ? -1 : ( R(0x80,0xc0) | x ) ) + #define D(x) C((x+16)) + #define E(x) ( ( x==0 ? R(0xa0,0xc0) : \ + x==0xd ? R(0x80,0xa0) : \ + R(0x80,0xc0) ) \ + | ( R(0x80,0xc0) >> 6 ) \ + | x ) + #define F(x) ( ( x>=5 ? 0 : \ + x==0 ? R(0x90,0xc0) : \ + x==4 ? R(0x80,0xa0) : \ + R(0x80,0xc0) ) \ + | ( R(0x80,0xc0) >> 6 ) \ + | ( R(0x80,0xc0) >> 12 ) \ + | x ) + #define SA 0xc2u + #define SB 0xf4u + + const uint32_t bittab[] = { + C(0x2),C(0x3),C(0x4),C(0x5),C(0x6),C(0x7), + C(0x8),C(0x9),C(0xa),C(0xb),C(0xc),C(0xd),C(0xe),C(0xf), + D(0x0),D(0x1),D(0x2),D(0x3),D(0x4),D(0x5),D(0x6),D(0x7), + D(0x8),D(0x9),D(0xa),D(0xb),D(0xc),D(0xd),D(0xe),D(0xf), + E(0x0),E(0x1),E(0x2),E(0x3),E(0x4),E(0x5),E(0x6),E(0x7), + E(0x8),E(0x9),E(0xa),E(0xb),E(0xc),E(0xd),E(0xe),E(0xf), + F(0x0),F(0x1),F(0x2),F(0x3),F(0x4) + }; + + // includes minor modifications + + size_t _mbsrtowcs(wchar_t * ws, const char **src, size_t wn, mbstate_t *st) + { + const unsigned char *s = (const unsigned char *)*src; + size_t wn0 = wn; + unsigned c = 0; + + if (st && (c = *(unsigned *)st)) { + if (ws) { + *(unsigned *)st = 0; + goto resume; + } else { + goto resume0; + } + } + + if (!ws) for (;;) { + if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { + while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { + s += 4; + wn -= 4; + } + } + if (*s-1u < 0x7f) { + s++; + wn--; + continue; + } + if (*s-SA > SB-SA) break; + c = bittab[*s++-SA]; + resume0: + if (OOB(c,*s)) { s--; break; } + s++; + if (c&(1U<<25)) { + if (*s-0x80u >= 0x40) { s-=2; break; } + s++; + if (c&(1U<<19)) { + if (*s-0x80u >= 0x40) { s-=3; break; } + s++; + } + } + wn--; + c = 0; + } else for (;;) { + if (!wn) { + *src = (const char *)s; + return wn0; + } + if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { + while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { + *ws++ = *s++; + *ws++ = *s++; + *ws++ = *s++; + *ws++ = *s++; + wn -= 4; + } + } + if (*s-1u < 0x7f) { + *ws++ = *s++; + wn--; + continue; + } + if (*s-SA > SB-SA) break; + c = bittab[*s++-SA]; + resume: + if (OOB(c,*s)) { s--; break; } + c = (c<<6) | *s++-0x80; + if (c&(1U<<31)) { + if (*s-0x80u >= 0x40) { s-=2; break; } + c = (c<<6) | *s++-0x80; + if (c&(1U<<31)) { + if (*s-0x80u >= 0x40) { s-=3; break; } + c = (c<<6) | *s++-0x80; + } + } + *ws++ = c; + wn--; + c = 0; + } + + if (!c && !*s) { + if (ws) { + *ws = 0; + *src = 0; + } + return wn0-wn; + } + errno = EILSEQ; + if (ws) *src = (const char *)s; + return -1; + } + #endif + + wchar_t *Font::GetFamilyName () { #ifdef LIME_FREETYPE @@ -644,7 +780,12 @@ namespace lime { len = sfnt_name.string_len; family_name = new wchar_t[len + 1]; - mbstowcs (&family_name[0], &reinterpret_cast(sfnt_name.string)[0], len); + #ifdef ANDROID + // Fix some devices (Android 4.x or older) that have a bad stdc implementation + _mbsrtowcs (family_name, (const char**)&sfnt_name.string, len, 0); + #else + mbstowcs (family_name, (const char*)sfnt_name.string, len); + #endif family_name[len] = L'\0'; return family_name;