From 5b74b2752eb5d3ac34f7a3c08d742b13280d527f Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 19 Apr 2016 14:39:33 -0400 Subject: [PATCH] Decided to use character offsets instead of byte offsets for text layout attributes. This removes the shaky code from the OS X and Windows backends to compute a list of character offsets for byte offsets. The equivalent code for GTK+ to convert chars to bytes will be much more solid; it will be written next. --- darwin/drawtext.m | 60 +++---------------------------------------- windows/drawtext.cpp | 61 ++------------------------------------------ 2 files changed, 6 insertions(+), 115 deletions(-) diff --git a/darwin/drawtext.m b/darwin/drawtext.m index 3274f4bf..6206c810 100644 --- a/darwin/drawtext.m +++ b/darwin/drawtext.m @@ -439,78 +439,27 @@ void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metri struct uiDrawTextLayout { CFMutableAttributedStringRef mas; - intmax_t *bytesToCharacters; double width; }; -// TODO this is *really* iffy, but we need to know character offsets... -// TODO clean up the local variable names and improve documentation -static intmax_t *strToCFStrOffsetList(const char *str, CFMutableStringRef *cfstr) -{ - intmax_t *bytesToCharacters; - intmax_t i, len; - - len = strlen(str); - bytesToCharacters = (intmax_t *) uiAlloc(len * sizeof (intmax_t), "intmax_t[]"); - - *cfstr = CFStringCreateMutable(NULL, 0); - if (*cfstr == NULL) - complain("error creating CFMutableStringRef for storing string in strToCFStrOffset()"); - - i = 0; - while (i < len) { - CFStringRef substr; - intmax_t n; - intmax_t j; - intmax_t pos; - - // figure out how many characters to convert and convert them - for (n = 1; (i + n - 1) < len; n++) { - substr = CFStringCreateWithBytes(NULL, (const UInt8 *) (str + i), n, kCFStringEncodingUTF8, false); - if (substr != NULL) // found a full character - break; - } - // if this test passes we either: - // - reached the end of the string without a successful conversion (invalid string) - // - ran into allocation issues - if (substr == NULL) - complain("something bad happened when trying to prepare string in strToCFStrOffset()"); - - // now save the character offsets for those bytes - pos = CFStringGetLength(*cfstr); - for (j = 0; j < n; j++) - bytesToCharacters[j] = pos; - - // and add the characters that we converted - CFStringAppend(*cfstr, substr); - CFRelease(substr); // TODO correct? - - // and go to the next - i += n; - } - - return bytesToCharacters; -} - uiDrawTextLayout *uiDrawNewTextLayout(const char *str, uiDrawTextFont *defaultFont, double width) { uiDrawTextLayout *layout; - CFMutableStringRef cfstr; +//TODO CFStringRef cfstr; CFAttributedStringRef immutable; CFMutableDictionaryRef attr; layout = uiNew(uiDrawTextLayout); - layout->bytesToCharacters = strToCFStrOffsetList(str, &cfstr); - attr = newAttrList(); // this will retain defaultFont->f; no need to worry CFDictionaryAddValue(attr, kCTFontAttributeName, defaultFont->f); - immutable = CFAttributedStringCreate(NULL, cfstr, attr); + // TODO convert the NSString call to a CFString call + immutable = CFAttributedStringCreate(NULL, (CFStringRef) [NSString stringWithUTF8String:str], attr); if (immutable == NULL) complain("error creating immutable attributed string in uiDrawNewTextLayout()"); - CFRelease(cfstr); +//TODO CFRelease(cfstr); CFRelease(attr); layout->mas = CFAttributedStringCreateMutableCopy(NULL, 0, immutable); @@ -526,7 +475,6 @@ uiDrawTextLayout *uiDrawNewTextLayout(const char *str, uiDrawTextFont *defaultFo void uiDrawFreeTextLayout(uiDrawTextLayout *layout) { CFRelease(layout->mas); - uiFree(layout->bytesToCharacters); uiFree(layout); } diff --git a/windows/drawtext.cpp b/windows/drawtext.cpp index 5ce4a0e7..d320d1a2 100644 --- a/windows/drawtext.cpp +++ b/windows/drawtext.cpp @@ -318,69 +318,12 @@ void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metri struct uiDrawTextLayout { IDWriteTextFormat *format; IDWriteTextLayout *layout; - intmax_t *bytesToCharacters; }; -#define MBTWC(str, n, wstr, bufsiz) MultiByteToWideChar(CP_UTF8, 0, str, n, wstr, bufsiz) -#define MBTWCErr(str, n, wstr, bufsiz) MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, n, wstr, bufsiz) - -// TODO figure out how ranges are specified in DirectWrite -// TODO clean up the local variable names and improve documentation -static intmax_t *toUTF16Offsets(const char *str, WCHAR **wstr, intmax_t *wlenout) -{ - intmax_t *bytesToCharacters; - intmax_t i, len; - int wlen; - intmax_t outpos; - - len = strlen(str); - bytesToCharacters = (intmax_t *) uiAlloc(len * sizeof (intmax_t), "intmax_t[]"); - - wlen = MBTWC(str, -1, NULL, 0); - if (wlen == 0) - logLastError("error figuring out number of characters to convert to in toUTF16Offsets()"); - *wstr = (WCHAR *) uiAlloc(wlen * sizeof (WCHAR), "WCHAR[]"); - *wlenout = wlen; - - i = 0; - outpos = 0; - while (i < len) { - intmax_t n; - intmax_t j; - BOOL found; - int m; - - // figure out how many characters to convert and convert them - found = FALSE; - for (n = 1; (i + n - 1) < len; n++) { - // we need MB_ERR_INVALID_CHARS here for this to work properly - m = MBTWCErr(str + i, n, *wstr + outpos, wlen - outpos); - if (m != 0) { // found a full character - found = TRUE; - break; - } - } - // if this test passes we reached the end of the string without a successful conversion (invalid string) - if (!found) - logLastError("something bad happened when trying to prepare string in uiDrawNewTextLayout()"); - - // now save the character offsets for those bytes - for (j = 0; j < m; j++) - bytesToCharacters[j] = outpos; - - // and go to the next - i += n; - outpos += m; - } - - return bytesToCharacters; -} - uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width) { uiDrawTextLayout *layout; WCHAR *wtext; - intmax_t wlen; HRESULT hr; layout = uiNew(uiDrawTextLayout); @@ -400,8 +343,8 @@ uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultF if (hr != S_OK) logHRESULT("error creating IDWriteTextFormat in uiDrawNewTextLayout()", hr); - layout->bytesToCharacters = toUTF16Offsets(text, &wtext, &wlen); - hr = dwfactory->CreateTextLayout(wtext, wlen, + wtext = toUTF16(text); + hr = dwfactory->CreateTextLayout(wtext, wcslen(wtext), layout->format, // FLOAT is float, not double, so this should work... TODO FLT_MAX, FLT_MAX,