aboutsummaryrefslogtreecommitdiffhomepage
path: root/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gtk')
-rwxr-xr-xgtk/PlatGTK.cxx41
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;
}