Implemented uiAttributeLanguage on OS X. Untested.
This commit is contained in:
parent
85fd3b72af
commit
669538e9ce
|
@ -1,6 +1,8 @@
|
||||||
// 12 february 2017
|
// 12 february 2017
|
||||||
#import "uipriv_darwin.h"
|
#import "uipriv_darwin.h"
|
||||||
|
|
||||||
|
// LONGTERM FUTURE for typographic features, on 10.10 we can use OpenType tags directly!
|
||||||
|
|
||||||
// this is what AppKit does internally
|
// this is what AppKit does internally
|
||||||
// WebKit does this too; see https://github.com/adobe/webkit/blob/master/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
|
// WebKit does this too; see https://github.com/adobe/webkit/blob/master/Source/WebCore/platform/graphics/mac/GraphicsContextMac.mm
|
||||||
static NSColor *spellingColor = nil;
|
static NSColor *spellingColor = nil;
|
||||||
|
@ -70,8 +72,9 @@ struct foreachParams {
|
||||||
struct fontParams {
|
struct fontParams {
|
||||||
uiDrawFontDescriptor desc;
|
uiDrawFontDescriptor desc;
|
||||||
uint16_t featureTypes[maxFeatures];
|
uint16_t featureTypes[maxFeatures];
|
||||||
uint16_t featureSpecifiers[maxFeatures];
|
uint16_t featureSelectors[maxFeatures];
|
||||||
size_t nFeatures;
|
size_t nFeatures;
|
||||||
|
const char *language;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ensureFontInRange(struct foreachParams *p, size_t start, size_t end)
|
static void ensureFontInRange(struct foreachParams *p, size_t start, size_t end)
|
||||||
|
@ -239,18 +242,27 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
||||||
if (spec->Value == uiDrawUnderlineColorCustom)
|
if (spec->Value == uiDrawUnderlineColorCustom)
|
||||||
CFRelease(color);
|
CFRelease(color);
|
||||||
break;
|
break;
|
||||||
|
// locale identifiers are specified as BCP 47: https://developer.apple.com/reference/corefoundation/cflocale?language=objc
|
||||||
|
case uiAttributeLanguage:
|
||||||
|
// LONGTERM FUTURE when we move to 10.9, switch to using kCTLanguageAttributeName
|
||||||
|
ensureFontInRange(p, start, end);
|
||||||
|
adjustFontInRange(p, start, end, ^(struct fontParams *fp) {
|
||||||
|
fp->language = (const char *) (spec->Value);
|
||||||
|
});
|
||||||
|
break;
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CTFontRef fontdescToCTFont(uiDrawFontDescriptor *fd)
|
static CTFontRef fontdescToCTFont(struct fontParams *fp)
|
||||||
{
|
{
|
||||||
CTFontDescriptorRef desc;
|
CTFontDescriptorRef desc;
|
||||||
CTFontRef font;
|
CTFontRef font;
|
||||||
|
|
||||||
desc = fontdescToCTFontDescriptor(fd);
|
desc = fontdescToCTFontDescriptor(&(fp->desc));
|
||||||
font = CTFontCreateWithFontDescriptor(desc, fd->Size, NULL);
|
desc = fontdescAppendFeatures(desc, fp->featureTypes, fp->featureSelectors, fp->nFeatures, fp->language);
|
||||||
|
font = CTFontCreateWithFontDescriptor(desc, fp->desc.Size, NULL);
|
||||||
CFRelease(desc); // TODO correct?
|
CFRelease(desc); // TODO correct?
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +275,7 @@ static void applyAndFreeFontAttributes(struct foreachParams *p)
|
||||||
CFRange range;
|
CFRange range;
|
||||||
|
|
||||||
fp = (struct fontParams *) [val pointerValue];
|
fp = (struct fontParams *) [val pointerValue];
|
||||||
font = fontdescToCTFont(&(fp->desc));
|
font = fontdescToCTFont(fp);
|
||||||
range.location = [key integerValue];
|
range.location = [key integerValue];
|
||||||
range.length = 1;
|
range.length = 1;
|
||||||
CFAttributedStringSetAttribute(p->mas, range, kCTFontAttributeName, font);
|
CFAttributedStringSetAttribute(p->mas, range, kCTFontAttributeName, font);
|
||||||
|
@ -305,6 +317,7 @@ CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray
|
||||||
CFAttributedStringRef base;
|
CFAttributedStringRef base;
|
||||||
CFMutableAttributedStringRef mas;
|
CFMutableAttributedStringRef mas;
|
||||||
struct foreachParams fep;
|
struct foreachParams fep;
|
||||||
|
struct fontParams ffp;
|
||||||
|
|
||||||
cfstr = CFStringCreateWithCharacters(NULL, attrstrUTF16(p->String), attrstrUTF16Len(p->String));
|
cfstr = CFStringCreateWithCharacters(NULL, attrstrUTF16(p->String), attrstrUTF16Len(p->String));
|
||||||
if (cfstr == NULL) {
|
if (cfstr == NULL) {
|
||||||
|
@ -316,7 +329,9 @@ CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray
|
||||||
if (defaultAttrs == NULL) {
|
if (defaultAttrs == NULL) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
defaultCTFont = fontdescToCTFont(p->DefaultFont);
|
memset(&ffp, 0, sizeof (struct fontParams));
|
||||||
|
ffp.desc = *(p->DefaultFont);
|
||||||
|
defaultCTFont = fontdescToCTFont(&ffp);
|
||||||
CFDictionaryAddValue(defaultAttrs, kCTFontAttributeName, defaultCTFont);
|
CFDictionaryAddValue(defaultAttrs, kCTFontAttributeName, defaultCTFont);
|
||||||
CFRelease(defaultCTFont);
|
CFRelease(defaultCTFont);
|
||||||
ps = mkParagraphStyle(p);
|
ps = mkParagraphStyle(p);
|
||||||
|
|
|
@ -254,6 +254,115 @@ CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd)
|
||||||
stretchesToCTWidths[fd->Stretch]);
|
stretchesToCTWidths[fd->Stretch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fortunately features that aren't supported are simply ignored, so we can copy them all in
|
||||||
|
// LONGTERM FUTURE when we switch to 10.9, the language parameter won't be needed anymore
|
||||||
|
// LONGTERM FUTURE and on 10.10 we can use OpenType tags directly!
|
||||||
|
CTFontDescriptorRef fontdescAppendFeatures(CTFontDescriptorRef desc, const uint16_t *types, const uint16_t *selectors, size_t n, const char *language)
|
||||||
|
{
|
||||||
|
CTFontDescriptorRef new;
|
||||||
|
CFMutableArrayRef outerArray;
|
||||||
|
CFDictionaryRef innerDict;
|
||||||
|
CFNumberRef numType, numSelector;
|
||||||
|
const void *keys[2], *values[2];
|
||||||
|
size_t i;
|
||||||
|
CFArrayRef languages;
|
||||||
|
CFIndex il, nl;
|
||||||
|
CFStringRef curlang;
|
||||||
|
char d[2];
|
||||||
|
|
||||||
|
outerArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||||
|
if (outerArray == NULL) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
keys[0] = kCTFontFeatureTypeIdentifierKey;
|
||||||
|
keys[1] = kCTFontFeatureSelectorIdentifierKey;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
numType = CFNumberCreate(NULL, kCFNumberSInt16Type,
|
||||||
|
(const SInt16 *) (types + i));
|
||||||
|
numSelector = CFNumberCreate(NULL, kCFNumberSInt16Type,
|
||||||
|
(const SInt16 *) (selectors + i));
|
||||||
|
values[0] = numType;
|
||||||
|
values[1] = numSelector;
|
||||||
|
innerDict = CFDictionaryCreate(NULL,
|
||||||
|
keys, values, 2,
|
||||||
|
// TODO are these correct?
|
||||||
|
&kCFCopyStringDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
if (innerDict == NULL) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
CFArrayAppendValue(outerArray, innerDict);
|
||||||
|
CFRelease(innerDict);
|
||||||
|
CFRelease(numSelector);
|
||||||
|
CFRelease(numType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we have to take care of the language
|
||||||
|
// TODO can we assume this is present?
|
||||||
|
if (language != NULL) {
|
||||||
|
languages = CTFontDescriptorCopyAttribute(desc, kCTFontLanguagesAttribute);
|
||||||
|
nl = CFArrayGetCount(languages);
|
||||||
|
d[0] = language[0];
|
||||||
|
if (d[0] >= 'A' && d[0] <= 'Z')
|
||||||
|
d[0] += 'a' - 'A';
|
||||||
|
d[1] = language[1];
|
||||||
|
if (d[1] >= 'A' && d[1] <= 'Z')
|
||||||
|
d[1] += 'a' - 'A';
|
||||||
|
for (il = 0; il < nl; il++) {
|
||||||
|
char c[2];
|
||||||
|
|
||||||
|
curlang = (CFStringRef) CFArrayGetValueAtIndex(languages, il);
|
||||||
|
// TODO check for failure
|
||||||
|
CFStringGetBytes(curlang, CFRangeMake(0, 2),
|
||||||
|
kCFStringEncodingUTF8, 0, false,
|
||||||
|
(UInt8 *) c, 2, NULL);
|
||||||
|
if (c[0] >= 'A' && c[0] <= 'Z')
|
||||||
|
c[0] += 'a' - 'A';
|
||||||
|
if (c[1] >= 'A' && c[1] <= 'Z')
|
||||||
|
c[1] += 'a' - 'A';
|
||||||
|
if (c[0] == d[0] && c[1] == d[1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (il != nl) {
|
||||||
|
uint16_t typ;
|
||||||
|
|
||||||
|
typ = kLanguageTagType;
|
||||||
|
numType = CFNumberCreate(NULL, kCFNumberSInt16Type,
|
||||||
|
(const SInt16 *) (&typ));
|
||||||
|
numSelector = CFNumberCreate(NULL, kCFNumberCFIndexType,
|
||||||
|
&il);
|
||||||
|
values[0] = numType;
|
||||||
|
values[1] = numSelector;
|
||||||
|
innerDict = CFDictionaryCreate(NULL,
|
||||||
|
keys, values, 2,
|
||||||
|
// TODO are these correct?
|
||||||
|
&kCFCopyStringDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
if (innerDict == NULL) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
CFArrayAppendValue(outerArray, innerDict);
|
||||||
|
CFRelease(innerDict);
|
||||||
|
CFRelease(numSelector);
|
||||||
|
CFRelease(numType);
|
||||||
|
}
|
||||||
|
CFRelease(languages);
|
||||||
|
}
|
||||||
|
|
||||||
|
keys[0] = kCTFontFeatureSettingsAttribute;
|
||||||
|
values[0] = outerArray;
|
||||||
|
innerDict = CFDictionaryCreate(NULL,
|
||||||
|
keys, values, 1,
|
||||||
|
// TODO are these correct?
|
||||||
|
&kCFCopyStringDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
CFRelease(outerArray);
|
||||||
|
new = CTFontDescriptorCreateCopyWithAttributes(desc, innerDict);
|
||||||
|
CFRelease(desc);
|
||||||
|
CFRelease(innerDict);
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO deduplicate this from italicCloseness()
|
// TODO deduplicate this from italicCloseness()
|
||||||
static uiDrawTextItalic italicFromCTItalic(CTFontDescriptorRef desc, CFDictionaryRef traits)
|
static uiDrawTextItalic italicFromCTItalic(CTFontDescriptorRef desc, CFDictionaryRef traits)
|
||||||
{
|
{
|
||||||
|
|
|
@ -142,6 +142,7 @@ extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdg
|
||||||
|
|
||||||
// fontmatch.m
|
// fontmatch.m
|
||||||
extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd);
|
extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd);
|
||||||
|
extern CTFontDescriptorRef fontdescAppendFeatures(CTFontDescriptorRef desc, const uint16_t *types, const uint16_t *selectors, size_t n, const char *language);
|
||||||
extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc);
|
extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc);
|
||||||
|
|
||||||
// attrstr.m
|
// attrstr.m
|
||||||
|
|
Loading…
Reference in New Issue