From 7fd012418dd22c9ed5d90a8fc069b963b69694a8 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 4 Mar 2018 15:09:27 -0500 Subject: [PATCH] Migrated (and cleaned up) OS X opentype.m. --- darwin/OLD_attrstr.h | 26 ++++++ darwin/OLD_opentype.m | 191 ----------------------------------------- darwin/attrstr.h | 4 + darwin/opentype.m | 112 ++++++++++++++++++++++++ darwin/uipriv_darwin.h | 26 ------ 5 files changed, 142 insertions(+), 217 deletions(-) create mode 100644 darwin/OLD_attrstr.h delete mode 100644 darwin/OLD_opentype.m create mode 100644 darwin/attrstr.h create mode 100644 darwin/opentype.m diff --git a/darwin/OLD_attrstr.h b/darwin/OLD_attrstr.h new file mode 100644 index 00000000..abe80cee --- /dev/null +++ b/darwin/OLD_attrstr.h @@ -0,0 +1,26 @@ +// 4 march 2018 + +// fontmatch.m +extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd); +extern CTFontDescriptorRef fontdescAppendFeatures(CTFontDescriptorRef desc, const uiOpenTypeFeatures *otf); +extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc); + +// attrstr.m +extern void initUnderlineColors(void); +extern void uninitUnderlineColors(void); +typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y); +extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks); + +// aat.m +typedef void (^aatBlock)(uint16_t type, uint16_t selector); +extern void openTypeToAAT(char a, char b, char c, char d, uint32_t value, aatBlock f); + +// opentype.m +// TODO this is only used by opentype.m and aat.m; figure out some better way to handle this +// TODO remove x8tox32() +#define x8tox32(x) ((uint32_t) (((uint8_t) (x)) & 0xFF)) +#define mkTag(a, b, c, d) \ + ((x8tox32(a) << 24) | \ + (x8tox32(b) << 16) | \ + (x8tox32(c) << 8) | \ + x8tox32(d)) diff --git a/darwin/OLD_opentype.m b/darwin/OLD_opentype.m deleted file mode 100644 index 890aa02a..00000000 --- a/darwin/OLD_opentype.m +++ /dev/null @@ -1,191 +0,0 @@ -// 11 may 2017 -#import "uipriv_darwin.h" - -struct uiOpenTypeFeatures { - NSMutableDictionary *tags; -}; - -uiOpenTypeFeatures *uiNewOpenTypeFeatures(void) -{ - uiOpenTypeFeatures *otf; - - otf = uiNew(uiOpenTypeFeatures); - otf->tags = [NSMutableDictionary new]; - return otf; -} - -void uiFreeOpenTypeFeatures(uiOpenTypeFeatures *otf) -{ - [otf->tags release]; - uiFree(otf); -} - -uiOpenTypeFeatures *uiOpenTypeFeaturesClone(const uiOpenTypeFeatures *otf) -{ - uiOpenTypeFeatures *out; - - out = uiNew(uiOpenTypeFeatures); - out->tags = [otf->tags mutableCopy]; - return out; -} - -// why are there no NSNumber methods for stdint.h or the equivalent core foundation types?... -#define mkMapObject(tag) [NSNumber numberWithUnsignedLongLong:((unsigned long long) tag)] -#define mapObjectValue(num) ((uint32_t) [num unsignedLongLongValue]) - -void uiOpenTypeFeaturesAdd(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value) -{ - NSNumber *tn, *vn; - - tn = mkMapObject(mkTag(a, b, c, d)); - vn = mkMapObject(value); - [otf->tags setObject:vn forKey:tn]; -} - -void uiOpenTypeFeaturesRemove(uiOpenTypeFeatures *otf, char a, char b, char c, char d) -{ - NSNumber *tn; - - tn = mkMapObject(mkTag(a, b, c, d)); - // documented as doing nothing if tn is not in otf->tags - [otf->tags removeObjectForKey:tn]; -} - -// TODO will the const wreck stuff up? -int uiOpenTypeFeaturesGet(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t *value) -{ - NSNumber *tn, *vn; - - tn = mkMapObject(mkTag(a, b, c, d)); - vn = (NSNumber *) [otf->tags objectForKey:tn]; - if (vn == nil) - return 0; - *value = mapObjectValue(vn); - // TODO release vn? - return 1; -} - -void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) -{ - [otf->tags enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { - NSNumber *tn = (NSNumber *) key; - NSNumber *vn = (NSNumber *) value; - uint32_t tag; - uint8_t a, b, c, d; - uiForEach ret; - - tag = mapObjectValue(tn); - a = (uint8_t) ((tag >> 24) & 0xFF); - b = (uint8_t) ((tag >> 16) & 0xFF); - c = (uint8_t) ((tag >> 8) & 0xFF); - d = (uint8_t) (tag & 0xFF); - ret = (*f)(otf, (char) a, (char) b, (char) c, (char) d, - mapObjectValue(vn), data); - // TODO for all: require exact match? - if (ret == uiForEachStop) - *stop = YES; - }]; -} - -int uiOpenTypeFeaturesEqual(const uiOpenTypeFeatures *a, const uiOpenTypeFeatures *b) -{ - if (a == NULL && b == NULL) - return 1; - if (a == NULL || b == NULL) - return 0; - return [a->tags isEqualToDictionary:b->tags]; -} - -// TODO explain all this -// TODO rename outerArray and innerDict (the names made sense when this was part of fontdescAppendFeatures(), but not here) -// TODO make all this use enumerateKeysAndObjects (which requires duplicating code)? -static uiForEach otfArrayForEachAAT(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) -{ - CFMutableArrayRef outerArray = (CFMutableArrayRef) data; - - openTypeToAAT(a, b, c, d, value, ^(uint16_t type, uint16_t selector) { - CFDictionaryRef innerDict; - CFNumberRef numType, numSelector; - // not well documented, but fixed-size arrays don't support __block either (VLAs are documented as being unsupported) - const void *keys[2], *values[2]; - - keys[0] = kCTFontFeatureTypeIdentifierKey; - keys[1] = kCTFontFeatureSelectorIdentifierKey; - numType = CFNumberCreate(NULL, kCFNumberSInt16Type, - (const SInt16 *) (&type)); - numSelector = CFNumberCreate(NULL, kCFNumberSInt16Type, - (const SInt16 *) (&selector)); - 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); - }); - return uiForEachContinue; -} - -// TODO find out which fonts differ in AAT small caps and test them with this -static uiForEach otfArrayForEachOT(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) -{ - CFMutableArrayRef outerArray = (CFMutableArrayRef) data; - CFDictionaryRef innerDict; - // TODO rename this to tagstr (and all the other variables likewise...) - CFStringRef strTag; - CFNumberRef numValue; - char tagcstr[5]; - const void *keys[2], *values[2]; - - tagcstr[0] = a; - tagcstr[1] = b; - tagcstr[2] = c; - tagcstr[3] = d; - tagcstr[4] = '\0'; - keys[0] = *FUTURE_kCTFontOpenTypeFeatureTag; - keys[1] = *FUTURE_kCTFontOpenTypeFeatureValue; - strTag = CFStringCreateWithCString(NULL, tagcstr, kCFStringEncodingUTF8); - if (strTag == NULL) { - // TODO - } - numValue = CFNumberCreate(NULL, kCFNumberSInt32Type, - (const SInt32 *) (&value)); - values[0] = strTag; - values[1] = numValue; - innerDict = CFDictionaryCreate(NULL, - keys, values, 2, - // TODO are these correct? - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - if (innerDict == NULL) { - // TODO - } - CFArrayAppendValue(outerArray, innerDict); - CFRelease(innerDict); - CFRelease(numValue); - CFRelease(strTag); - return uiForEachContinue; -} - -CFArrayRef otfToFeaturesArray(const uiOpenTypeFeatures *otf) -{ - CFMutableArrayRef outerArray; - uiOpenTypeFeaturesForEachFunc f; - - outerArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if (outerArray == NULL) { - // TODO - } - f = otfArrayForEachAAT; - if (FUTURE_kCTFontOpenTypeFeatureTag != NULL && FUTURE_kCTFontOpenTypeFeatureValue != NULL) - f = otfArrayForEachOT; - uiOpenTypeFeaturesForEach(otf, f, outerArray); - return outerArray; -} diff --git a/darwin/attrstr.h b/darwin/attrstr.h new file mode 100644 index 00000000..8221b8b4 --- /dev/null +++ b/darwin/attrstr.h @@ -0,0 +1,4 @@ +// 4 march 2018 + +// opentype.m +extern CFArrayRef uiprivOpenTypeFeaturesToCTFeatures(const uiOpenTypeFeatures *otf); diff --git a/darwin/opentype.m b/darwin/opentype.m new file mode 100644 index 00000000..0b2647e9 --- /dev/null +++ b/darwin/opentype.m @@ -0,0 +1,112 @@ +// 11 may 2017 +#import "uipriv_darwin.h" + +struct addCTFeatureEntryParams { + CFMutableArrayRef array; + const void *tagKey; + BOOL tagIsNumber; + CFNumberType tagType; + const void *tagValue; + const void *valueKey; + CFNumberType valueType; + const void *valueValue; +}; + +static void addCTFeatureEntry(struct addCTFeatureEntryParams *p) +{ + CFDictionaryRef featureDict; + CFNumberRef tagNum, valueNum; + const void *keys[2], *values[2]; + + keys[0] = p->tagKey; + tagNum = NULL; + values[0] = p->tagValue; + if (p->tagIsNumber) { + tagNum = CFNumberCreate(NULL, p->tagType, p->tagValue); + values[0] = tagNum; + } + + keys[1] = p->valueKey; + valueNum = CFNumberCreate(NULL, p->valueType, p->valueValue); + values[1] = valueNum; + + featureDict = CFDictionaryCreate(NULL, + keys, values, 2, + // TODO are these correct? + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (featureDict == NULL) { + // TODO + } + CFArrayAppendValue(p->array, featureDict); + + CFRelease(featureDict); + CFRelease(valueNum); + if (p->tagIsNumber) + CFRelease(tagNum); +} + +static uiForEach otfArrayForEachAAT(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) +{ + __block struct addCTFeatureEntryParams p; + + p.array = (CFMutableArrayRef) data; + p.tagIsNumber = YES; + openTypeToAAT(a, b, c, d, value, ^(uint16_t type, uint16_t selector) { + p.tagKey = kCTFontFeatureTypeIdentifierKey; + p.tagType = kCFNumberSInt16Type; + p.tagValue = (const SInt16 *) (&type); + p.valueKey = kCTFontFeatureSelectorIdentifierKey; + p.valueType = kCFNumberSInt16Type; + p.valueValue = (const SInt16 *) (&selector); + addCTFeatureEntry(&p); + }); + return uiForEachContinue; +} + +// TODO find out which fonts differ in AAT small caps and test them with this +static uiForEach otfArrayForEachOT(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) +{ + struct addCTFeatureEntryParams p; + char tagcstr[5]; + CFStringRef tagstr; + + p.array = (CFMutableArrayRef) data; + + p.tagKey = *FUTURE_kCTFontOpenTypeFeatureTag; + p.tagIsNumber = NO; + tagcstr[0] = a; + tagcstr[1] = b; + tagcstr[2] = c; + tagcstr[3] = d; + tagcstr[4] = '\0'; + tagstr = CFStringCreateWithCString(NULL, tagcstr, kCFStringEncodingUTF8); + if (tagstr == NULL) { + // TODO + } + p.tagValue = tagstr; + + p.valueKey = *FUTURE_kCTFontOpenTypeFeatureValue; + p.valueType = kCFNumberSInt32Type; + p.valueValue = (const SInt32 *) (&value); + addCTFeatureEntry(&p); + + CFRelease(strTag); + return uiForEachContinue; +} + +CFArrayRef uiprivOpenTypeFeaturesToCTFeatures(const uiOpenTypeFeatures *otf) +{ + CFMutableArrayRef array; + uiOpenTypeFeaturesForEachFunc f; + + array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (array == NULL) { + // TODO + } + f = otfArrayForEachAAT; + if (FUTURE_kCTFontOpenTypeFeatureTag != NULL && FUTURE_kCTFontOpenTypeFeatureValue != NULL) + f = otfArrayForEachOT; + uiOpenTypeFeaturesForEach(otf, f, array); + return array; +} diff --git a/darwin/uipriv_darwin.h b/darwin/uipriv_darwin.h index 0303c32c..4d5ebdc3 100644 --- a/darwin/uipriv_darwin.h +++ b/darwin/uipriv_darwin.h @@ -142,32 +142,6 @@ extern NSImage *imageImage(uiImage *); extern void doManualMove(NSWindow *w, NSEvent *initialEvent); extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge); -// fontmatch.m -extern CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd); -extern CTFontDescriptorRef fontdescAppendFeatures(CTFontDescriptorRef desc, const uiOpenTypeFeatures *otf); -extern void fontdescFromCTFontDescriptor(CTFontDescriptorRef ctdesc, uiDrawFontDescriptor *uidesc); - -// attrstr.m -extern void initUnderlineColors(void); -extern void uninitUnderlineColors(void); -typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y); -extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks); - -// aat.m -typedef void (^aatBlock)(uint16_t type, uint16_t selector); -extern void openTypeToAAT(char a, char b, char c, char d, uint32_t value, aatBlock f); - -// opentype.m -// TODO this is only used by opentype.m and aat.m; figure out some better way to handle this -// TODO remove x8tox32() -#define x8tox32(x) ((uint32_t) (((uint8_t) (x)) & 0xFF)) -#define mkTag(a, b, c, d) \ - ((x8tox32(a) << 24) | \ - (x8tox32(b) << 16) | \ - (x8tox32(c) << 8) | \ - x8tox32(d)) -extern CFArrayRef otfToFeaturesArray(const uiOpenTypeFeatures *otf); - // future.m extern CFStringRef *FUTURE_kCTFontOpenTypeFeatureTag; extern CFStringRef *FUTURE_kCTFontOpenTypeFeatureValue;