diff --git a/headers/private/interface/moreUTF8.h b/headers/private/interface/moreUTF8.h index c45948caf9..8fee6e25f2 100644 --- a/headers/private/interface/moreUTF8.h +++ b/headers/private/interface/moreUTF8.h @@ -1,22 +1,20 @@ #ifndef __MOREUTF8 #define __MOREUTF8 +#include static inline bool IsInsideGlyph(uchar ch) { return (ch & 0xC0) == 0x80; +// return (ch & 0x80); } - static inline uint32 -UTF8NextCharLen(const char *text) +UTF8NextCharLenUnsafe(const char *text) { const char *ptr = text; - - if (ptr == NULL || *ptr == 0) - return 0; - + do { ptr++; } while (IsInsideGlyph(*ptr)); @@ -24,6 +22,15 @@ UTF8NextCharLen(const char *text) return ptr - text; } +static inline uint32 +UTF8NextCharLen(const char *text) +{ + if (text == NULL || *text == 0) + return 0; + + return UTF8NextCharLenUnsafe(text); +} + static inline uint32 UTF8PreviousCharLen(const char *text, const char *limit) { @@ -41,17 +48,39 @@ UTF8PreviousCharLen(const char *text, const char *limit) return text - ptr; } +// TODO: use this function in other places of this file... +static inline uint32 +count_utf8_bytes(uchar ch) +{ + // the number of high bits set until the first + // unset bit determine the count of bytes used for + // this glyph from this byte on + uchar bit = 1 << 7; + uint32 count = 1; + if (ch & bit) { + bit = bit >> 1; + while (ch & bit) { + count++; + bit = bit >> 1; + } + } + return count; +} + static inline uint32 UTF8CountBytes(const char *text, uint32 numChars) { - const char *ptr = text; - - while (numChars) { - ptr += UTF8NextCharLen(ptr); - numChars--; + if (text) { + // iterate over numChars glyphs incrementing ptr by the + // number of bytes for each glyph, which is encoded in + // the first byte of any glyph. + const char *ptr = text; + while (numChars--) { + ptr += count_utf8_bytes(*ptr); + } + return ptr - text; } - - return ptr - text; + return 0; } static inline uint32 diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index 4e92541300..268904fe54 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -294,7 +294,7 @@ ServerFont::GetGlyphShapes(const char charArray[], int32 numChars) const if (!face) return NULL; - FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); + FT_Set_Char_Size(face, 0, int32(fSize * 64), 72, 72); Angle rotation(fRotation); Angle shear(fShear); @@ -344,7 +344,7 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, if (!face) return NULL; - FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); + FT_Set_Char_Size(face, 0, int32(fSize * 64), 72, 72); Angle rotation(fRotation); Angle shear(fShear); @@ -408,7 +408,7 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, if (!face) return false; - FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); + FT_Set_Char_Size(face, 0, int32(fSize * 64), 72, 72); // UTF8 handling...this can probably be smarter // Here is what I do in the AGGTextRenderer to handle UTF8... @@ -428,13 +428,14 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, uint16* glyphIndex = (uint16*)convertedBuffer; // just to be sure - numChars = convertedLength / sizeof(uint16); + numChars = min_c((uint32)numChars, convertedLength / sizeof(uint16)); for (int i = 0; i < numChars; i++) { FT_Load_Char(face, glyphIndex[i], FT_LOAD_NO_BITMAP); -// widthArray[i] = float(face->glyph->metrics.width / 64) / fSize; - widthArray[i] = ((float)face->glyph->metrics.horiAdvance / 64.0) / fSize; - widthArray[i] += is_white_space(glyphIndex[i]) ? delta.space : delta.nonspace; + if (face->glyph) { + widthArray[i] = ((float)face->glyph->metrics.horiAdvance / 64.0) / fSize; + widthArray[i] += is_white_space(glyphIndex[i]) ? delta.space : delta.nonspace; + } } } delete[] convertedBuffer;