diff --git a/headers/private/interface/moreUTF8.h b/headers/private/interface/moreUTF8.h index 758a313b72..c45948caf9 100644 --- a/headers/private/interface/moreUTF8.h +++ b/headers/private/interface/moreUTF8.h @@ -24,20 +24,6 @@ UTF8NextCharLen(const char *text) return ptr - text; } -static inline uint32 -UTF8CountBytes(const char *text, uint32 numChars) -{ - const char *ptr = text; - - while (numChars) { - ptr += UTF8NextCharLen(ptr); - numChars--; - } - - return ptr - text; -} - - static inline uint32 UTF8PreviousCharLen(const char *text, const char *limit) { @@ -55,4 +41,33 @@ UTF8PreviousCharLen(const char *text, const char *limit) return text - ptr; } +static inline uint32 +UTF8CountBytes(const char *text, uint32 numChars) +{ + const char *ptr = text; + + while (numChars) { + ptr += UTF8NextCharLen(ptr); + numChars--; + } + + return ptr - text; +} + +static inline uint32 +UTF8CountChars(const char *text, int32 numBytes) +{ + const char* ptr = text; + const char* last = ptr + numBytes - 1; + + uint32 count = 0; + while (ptr <= last) { + ptr += UTF8NextCharLen(ptr); + count++; + } + + return count; +} + + #endif diff --git a/headers/private/servers/app/ServerFont.h b/headers/private/servers/app/ServerFont.h index f4063e8dbe..680e786dcb 100644 --- a/headers/private/servers/app/ServerFont.h +++ b/headers/private/servers/app/ServerFont.h @@ -120,7 +120,7 @@ class ServerFont { float widthArray[], escapement_delta delta) const; - float StringWidth(const char* string, int32 numChars) const; + float StringWidth(const char* string, int32 numBytes) const; FT_Face GetFTFace() const { return fStyle->GetFTFace(); }; diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index 580a864a8c..73521f3a6d 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -402,22 +402,39 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, // StringWidth float -ServerFont::StringWidth(const char* string, int32 numChars) const +ServerFont::StringWidth(const char* string, int32 numBytes) const { - // TODO: we're lazy for now and reuse the existing - // functionality in GetEscapements - escapement_delta delta; - delta.space = 0.0; - delta.nonspace = 0.0; + if (!string || numBytes <= 0) + return 0.0; - float* widthArray = new float[numChars]; + FT_Face face = fStyle->GetFTFace(); + if (!face) + return 0.0; - GetEscapements(string, numChars, widthArray, delta); float width = 0.0; - for (int32 i = 0; i < numChars; i++) - width += widthArray[i] * fSize; - delete[] widthArray; + int32 convertedLength = numBytes * 2; + char* convertedBuffer = new char[convertedLength]; + + int32 state = 0; + status_t ret; + if ((ret = convert_from_utf8(B_UNICODE_CONVERSION, + string, &numBytes, + convertedBuffer, &convertedLength, + &state, B_SUBSTITUTE)) >= B_OK + && (ret = swap_data(B_INT16_TYPE, convertedBuffer, convertedLength, + B_SWAP_BENDIAN_TO_HOST)) >= B_OK) { + + uint16* glyphIndex = (uint16*)convertedBuffer; + // just to be sure + int numChars = convertedLength / sizeof(uint16); + + for (int i = 0; i < numChars; i++) { + FT_Load_Char(face, glyphIndex[i], FT_LOAD_NO_BITMAP); + width += ((float)face->glyph->metrics.horiAdvance / 64.0) / fSize; + } + } + delete[] convertedBuffer; return width; }