diff options
Diffstat (limited to 'gtk')
-rwxr-xr-x | gtk/PlatGTK.cxx | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 87c57abcd..e73e4678d 100755 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -896,14 +896,34 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI PLATFORM_ASSERT(static_cast<size_t>(i) == text.length()); } else { int positionsCalculated = 0; + const char *charSetID = CharacterSetID(PFont(font_)->characterSet); + std::string utfForm; + { + gsize bytesRead = 0; + gsize bytesWritten = 0; + GError *error = nullptr; + UniqueStr textInUTF8(g_convert(text.data(), text.length(), + "UTF-8", charSetID, + &bytesRead, + &bytesWritten, + &error)); + if ((bytesWritten > 0) && (bytesRead == text.length()) && !error) { + // Extra allocation here but avoiding it makes code more complex + utfForm.assign(textInUTF8.get(), bytesWritten); + } + if (error) { +#ifdef DEBUG + fprintf(stderr, "MeasureWidths: %s.\n", error->message); +#endif + g_error_free(error); + } + } if (et == EncodingType::dbcs) { - SetConverter(PFont(font_)->characterSet); - std::string utfForm = UTF8FromIconv(conv, text); if (!utfForm.empty()) { // Convert to UTF-8 so can ask Pango for widths, then // Loop through UTF-8 and DBCS forms, taking account of different // character byte lengths. - Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); + Converter convMeasure("UCS-2", charSetID, false); int i = 0; ClusterIterator iti(layoutMeasure.get(), utfForm); int clusterStart = iti.curIndex; @@ -915,7 +935,7 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI while (!iti.finished) { iti.Next(); const int clusterEnd = iti.curIndex; - const int places = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); + const int places = g_utf8_strlen(utfForm.data() + clusterStart, clusterEnd - clusterStart); int place = 1; while (clusterStart < clusterEnd) { size_t lenChar = MultiByteLenFromIconv(convMeasure, text.data()+i, text.length()-i); @@ -933,12 +953,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI if (positionsCalculated < 1) { const size_t lenPositions = text.length(); // Either 8-bit or DBCS conversion failed so treat as 8-bit. - SetConverter(PFont(font_)->characterSet); const bool rtlCheck = PFont(font_)->characterSet == CharacterSet::Hebrew || PFont(font_)->characterSet == CharacterSet::Arabic; - std::string utfForm = UTF8FromIconv(conv, text); if (utfForm.empty()) { utfForm = UTF8FromLatin1(text); +#ifdef DEBUG + fprintf(stderr, "MeasureWidths: Fall back to Latin1 [%s]\n", utfForm.c_str()); +#endif } size_t i = 0; // Each 8-bit input character may take 1 or 2 bytes in UTF-8 @@ -953,9 +974,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI while (!iti.finished) { iti.Next(); const int clusterEnd = iti.curIndex; - const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); - if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) { + const int ligatureLength = g_utf8_strlen(utfForm.data() + clusterStart, clusterEnd - clusterStart); + if (((i + ligatureLength) > lenPositions) || + (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3)))) { // Something has gone wrong: exit quickly but pretend all the characters are equally spaced: +#ifdef DEBUG + fprintf(stderr, "MeasureWidths: result too long.\n"); +#endif EquallySpaced(layoutMeasure.get(), positions, lenPositions); return; } |