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.
This commit is contained in:
parent
c2d165af94
commit
5b74b2752e
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue