diff --git a/darwin/aat.m b/darwin/aat.m index 0c964e05..d46a3506 100644 --- a/darwin/aat.m +++ b/darwin/aat.m @@ -1,25 +1,18 @@ // 14 february 2017 #import "uipriv_darwin.h" -struct openTypeAATParams { - void (*doAAT)(uint16_t type, uint16_t selector, void *data); - void *data; -}; - -#define pcall(p, type, selector) ((*(p->doAAT))(type, selector, p->data)) - -static void boolspec(uint32_t value, uint16_t type, uint16_t ifTrue, uint16_t ifFalse, struct openTypeAATParams *p) +static void boolspec(uint32_t value, uint16_t type, uint16_t ifTrue, uint16_t ifFalse, aatBlock f) { // TODO are values other than 1 accepted for true by OpenType itself? (same for the rest of the file) if (value != 0) { - pcall(p, type, ifTrue); + f(type, ifTrue); return; } - pcall(p, type, ifFalse); + f(type, ifFalse); } // TODO double-check drawtext example to make sure all of these are used properly (I already screwed dlig up by putting clig twice instead) -static int foreach(char a, char b, char c, char d, uint32_t value, void *data) +void openTypeToAAT(char a, char b, char c, char d, uint32_t value, aatBlock f) { struct openTypeAATParams *p = (struct openTypeAATParams *) data; @@ -28,25 +21,25 @@ static int foreach(char a, char b, char c, char d, uint32_t value, void *data) boolspec(value, kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector, - p); + f); break; case mkTag('r', 'l', 'i', 'g'): boolspec(value, kLigaturesType, kRequiredLigaturesOnSelector, kRequiredLigaturesOffSelector, - p); + f); break; case mkTag('d', 'l', 'i', 'g'): boolspec(value, kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector, - p); + f); break; case mkTag('c', 'l', 'i', 'g'): boolspec(value, kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector, - p); + f); break; case mkTag('h', 'l', 'i', 'g'): // This technically isn't what is meant by "historical ligatures", but Core Text's internal AAT-to-OpenType mapping says to include it, so we include it too @@ -54,117 +47,117 @@ static int foreach(char a, char b, char c, char d, uint32_t value, void *data) boolspec(value, kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector, - p); + f); break; case mkTag('u', 'n', 'i', 'c'): // TODO is this correct, or should we provide an else case? if (value != 0) // this is undocumented; it comes from Core Text's internal AAT-to-OpenType conversion table - pcall(p, kLetterCaseType, 14); + f(p, kLetterCaseType, 14); break; // TODO will the following handle all cases properly, or are elses going to be needed? case mkTag('p', 'n', 'u', 'm'): if (value != 0) - pcall(p, kNumberSpacingType, kProportionalNumbersSelector); + f(p, kNumberSpacingType, kProportionalNumbersSelector); break; case mkTag('t', 'n', 'u', 'm'): if (value != 0) - pcall(p, kNumberSpacingType, kMonospacedNumbersSelector); + f(p, kNumberSpacingType, kMonospacedNumbersSelector); break; // TODO will the following handle all cases properly, or are elses going to be needed? case mkTag('s', 'u', 'p', 's'): if (value != 0) - pcall(p, kVerticalPositionType, kSuperiorsSelector); + f(p, kVerticalPositionType, kSuperiorsSelector); break; case mkTag('s', 'u', 'b', 's'): if (value != 0) - pcall(p, kVerticalPositionType, kInferiorsSelector); + f(p, kVerticalPositionType, kInferiorsSelector); break; case mkTag('o', 'r', 'd', 'n'): if (value != 0) - pcall(p, kVerticalPositionType, kOrdinalsSelector); + f(p, kVerticalPositionType, kOrdinalsSelector); break; case mkTag('s', 'i', 'n', 'f'): if (value != 0) - pcall(p, kVerticalPositionType, kScientificInferiorsSelector); + f(p, kVerticalPositionType, kScientificInferiorsSelector); break; // TODO will the following handle all cases properly, or are elses going to be needed? case mkTag('a', 'f', 'r', 'c'): if (value != 0) - pcall(p, kFractionsType, kVerticalFractionsSelector); + f(p, kFractionsType, kVerticalFractionsSelector); break; case mkTag('f', 'r', 'a', 'c'): if (value != 0) - pcall(p, kFractionsType, kDiagonalFractionsSelector); + f(p, kFractionsType, kDiagonalFractionsSelector); break; case mkTag('z', 'e', 'r', 'o'): boolspec(value, kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector, - p); + f); break; case mkTag('m', 'g', 'r', 'k'): boolspec(value, kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector, - p); + f); break; case mkTag('o', 'r', 'n', 'm'): - pcall(p, kOrnamentSetsType, (uint16_t) value); + f(p, kOrnamentSetsType, (uint16_t) value); break; case mkTag('a', 'a', 'l', 't'): - pcall(p, kCharacterAlternativesType, (uint16_t) value); + f(p, kCharacterAlternativesType, (uint16_t) value); break; case mkTag('t', 'i', 't', 'l'): // TODO is this correct, or should we provide an else case? if (value != 0) - pcall(p, kStyleOptionsType, kTitlingCapsSelector); + f(p, kStyleOptionsType, kTitlingCapsSelector); break; // TODO will the following handle all cases properly, or are elses going to be needed? case mkTag('t', 'r', 'a', 'd'): if (value != 0) - pcall(p, kCharacterShapeType, kTraditionalCharactersSelector); + f(p, kCharacterShapeType, kTraditionalCharactersSelector); break; case mkTag('s', 'm', 'p', 'l'): if (value != 0) - pcall(p, kCharacterShapeType, kSimplifiedCharactersSelector); + f(p, kCharacterShapeType, kSimplifiedCharactersSelector); break; case mkTag('j', 'p', '7', '8'): if (value != 0) - pcall(p, kCharacterShapeType, kJIS1978CharactersSelector); + f(p, kCharacterShapeType, kJIS1978CharactersSelector); break; case mkTag('j', 'p', '8', '3'): if (value != 0) - pcall(p, kCharacterShapeType, kJIS1983CharactersSelector); + f(p, kCharacterShapeType, kJIS1983CharactersSelector); break; case mkTag('j', 'p', '9', '0'): if (value != 0) - pcall(p, kCharacterShapeType, kJIS1990CharactersSelector); + f(p, kCharacterShapeType, kJIS1990CharactersSelector); break; case mkTag('e', 'x', 'p', 't'): if (value != 0) - pcall(p, kCharacterShapeType, kExpertCharactersSelector); + f(p, kCharacterShapeType, kExpertCharactersSelector); break; case mkTag('j', 'p', '0', '4'): if (value != 0) - pcall(p, kCharacterShapeType, kJIS2004CharactersSelector); + f(p, kCharacterShapeType, kJIS2004CharactersSelector); break; case mkTag('h', 'o', 'j', 'o'): if (value != 0) - pcall(p, kCharacterShapeType, kHojoCharactersSelector); + f(p, kCharacterShapeType, kHojoCharactersSelector); break; case mkTag('n', 'l', 'c', 'k'): if (value != 0) - pcall(p, kCharacterShapeType, kNLCCharactersSelector); + f(p, kCharacterShapeType, kNLCCharactersSelector); break; case mkTag('t', 'n', 'a', 'm'): if (value != 0) - pcall(p, kCharacterShapeType, kTraditionalNamesCharactersSelector); + f(p, kCharacterShapeType, kTraditionalNamesCharactersSelector); break; case mkTag('o', 'n', 'u', 'm'): @@ -173,201 +166,201 @@ static int foreach(char a, char b, char c, char d, uint32_t value, void *data) case mkTag('l', 'n', 'u', 'm'): // TODO is this correct, or should we provide an else case? if (value != 0) - pcall(p, kNumberCaseType, kLowerCaseNumbersSelector); + f(p, kNumberCaseType, kLowerCaseNumbersSelector); break; case mkTag('h', 'n', 'g', 'l'): // TODO is this correct, or should we provide an else case? if (value != 0) - pcall(p, kTransliterationType, kHanjaToHangulSelector); + f(p, kTransliterationType, kHanjaToHangulSelector); break; case mkTag('n', 'a', 'l', 't'): - pcall(p, kAnnotationType, (uint16_t) value); + f(p, kAnnotationType, (uint16_t) value); break; case mkTag('r', 'u', 'b', 'y'): // include this for completeness boolspec(value, kRubyKanaType, kRubyKanaSelector, kNoRubyKanaSelector, - p); + f); // this is the current one boolspec(value, kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector, - p); + f); break; case mkTag('i', 't', 'a', 'l'): // include this for completeness boolspec(value, kItalicCJKRomanType, kCJKItalicRomanSelector, kNoCJKItalicRomanSelector, - p); + f); // this is the current one boolspec(value, kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector, - p); + f); break; case mkTag('c', 'a', 's', 'e'): boolspec(value, kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector, - p); + f); break; case mkTag('c', 'p', 's', 'p'): boolspec(value, kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector, - p); + f); break; case mkTag('h', 'k', 'n', 'a'): boolspec(value, kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, - p); + f); break; case mkTag('v', 'k', 'n', 'a'): boolspec(value, kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector, - p); + f); break; case mkTag('s', 's', '0', '1'): boolspec(value, kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector, - p); + f); break; case mkTag('s', 's', '0', '2'): boolspec(value, kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector, - p); + f); break; case mkTag('s', 's', '0', '3'): boolspec(value, kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector, - p); + f); break; case mkTag('s', 's', '0', '4'): boolspec(value, kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector, - p); + f); break; case mkTag('s', 's', '0', '5'): boolspec(value, kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector, - p); + f); break; case mkTag('s', 's', '0', '6'): boolspec(value, kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector, - p); + f); break; case mkTag('s', 's', '0', '7'): boolspec(value, kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector, - p); + f); break; case mkTag('s', 's', '0', '8'): boolspec(value, kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector, - p); + f); break; case mkTag('s', 's', '0', '9'): boolspec(value, kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector, - p); + f); break; case mkTag('s', 's', '1', '0'): boolspec(value, kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '1'): boolspec(value, kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '2'): boolspec(value, kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector, - p); + f); break; case mkTag('s', 's', '1', '3'): boolspec(value, kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '4'): boolspec(value, kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '5'): boolspec(value, kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '6'): boolspec(value, kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '7'): boolspec(value, kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '8'): boolspec(value, kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector, - p); + f); break; case mkTag('s', 's', '1', '9'): boolspec(value, kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector, - p); + f); break; case mkTag('s', 's', '2', '0'): boolspec(value, kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector, - p); + f); break; case mkTag('c', 'a', 'l', 't'): boolspec(value, kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector, - p); + f); break; case mkTag('s', 'w', 's', 'h'): boolspec(value, kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector, - p); + f); break; case mkTag('c', 's', 'w', 'h'): boolspec(value, kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector, - p); + f); break; // TODO will the following handle all cases properly, or are elses going to be needed? @@ -375,35 +368,26 @@ static int foreach(char a, char b, char c, char d, uint32_t value, void *data) if (value != 0) { // include this for compatibility (some fonts that come with OS X still use this!) // TODO make it boolean? - pcall(p, kLetterCaseType, kSmallCapsSelector); + f(p, kLetterCaseType, kSmallCapsSelector); // this is the current one - pcall(p, kLowerCaseType, kLowerCaseSmallCapsSelector); + f(p, kLowerCaseType, kLowerCaseSmallCapsSelector); } break; case mkTag('p', 'c', 'a', 'p'): if (value != 0) - pcall(p, kLowerCaseType, kLowerCasePetiteCapsSelector); + f(p, kLowerCaseType, kLowerCasePetiteCapsSelector); break; // TODO will the following handle all cases properly, or are elses going to be needed? case mkTag('c', '2', 's', 'c'): if (value != 0) - pcall(p, kUpperCaseType, kUpperCaseSmallCapsSelector); + f(p, kUpperCaseType, kUpperCaseSmallCapsSelector); break; case mkTag('c', '2', 'p', 'c'): if (value != 0) - pcall(p, kUpperCaseType, kUpperCasePetiteCapsSelector); + f(p, kUpperCaseType, kUpperCasePetiteCapsSelector); break; } // TODO handle this properly - return 0; -} - -void openTypeToAAT(uiOpenTypeFeatures *otf, void (*doAAT)(uint16_t type, uint16_t selector, void *data), void *data) -{ - struct openTypeAATParams p; - - p.doAAT = doAAT; - p.data = data; - uiOpenTypeFeaturesForEach(otf, foreach, &p); + // (it used to return 0 when this still returned the number of selectors produced but IDK what properly is anymore) } diff --git a/darwin/fontmatch.m b/darwin/fontmatch.m index ba740933..56b8991d 100644 --- a/darwin/fontmatch.m +++ b/darwin/fontmatch.m @@ -258,50 +258,21 @@ CTFontDescriptorRef fontdescToCTFontDescriptor(uiDrawFontDescriptor *fd) CTFontDescriptorRef fontdescAppendFeatures(CTFontDescriptorRef desc, const uiOpenTypeFeatures *otf) { CTFontDescriptorRef new; - CFMutableArrayRef outerArray; - CFDictionaryRef innerDict; - CFNumberRef numType, numSelector; - const void *keys[2], *values[2]; - size_t i; - - 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); - } + CFMutableArrayRef featuresArray; + CFDictionaryRef attrs; + featuresArray = otfToFeaturesArray(otf); keys[0] = kCTFontFeatureSettingsAttribute; - values[0] = outerArray; - innerDict = CFDictionaryCreate(NULL, + values[0] = featuresArray; + attrs = CFDictionaryCreate(NULL, keys, values, 1, // TODO are these correct? &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(outerArray); - new = CTFontDescriptorCreateCopyWithAttributes(desc, innerDict); + CFRelease(featuresArray); + new = CTFontDescriptorCreateCopyWithAttributes(desc, attrs); + CFRelease(attrs); CFRelease(desc); - CFRelease(innerDict); return new; } diff --git a/darwin/opentype.m b/darwin/opentype.m index 52db9560..d6bd6652 100644 --- a/darwin/opentype.m +++ b/darwin/opentype.m @@ -63,7 +63,7 @@ int uiOpenTypeFeaturesGet(uiOpenTypeFeatures *otf, char a, char b, char c, char return 1; } -void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) +void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) { [otf->tags enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { NSNumber *tn = (NSNumber *) key; @@ -87,4 +87,51 @@ int uiOpenTypeFeaturesEqual(const uiOpenTypeFeatures *a, const uiOpenTypeFeature return [a->tags isEqualToDictionary:b->tags]; } -// actual conversion to a feature dictionary is handled in aat.m; see there for details +// 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 int otfArrayForEach(char a, char b, char c, char d, uint32_t value, void *data) +{ + CFMutableArrayRef outerArray = (CFMutableArrayRef) data; + const void *keys[2], *values[2]; + + keys[0] = kCTFontFeatureTypeIdentifierKey; + keys[1] = kCTFontFeatureSelectorIdentifierKey; + openTypeToAAT(a, b, c, d, value, ^(uint16_t type, uint16_t selector) { + CFDictionaryRef innerDict; + CFNumberRef numType, numSelector; + + 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(p->outerArray, innerDict); + CFRelease(innerDict); + CFRelease(numSelector); + CFRelease(numType); + }); + // TODO + return 0; +} + +CFArrayRef otfToFeaturesArray(const uiOpenTypeFeatures *otf) +{ + CFMutableArrayRef outerArray; + + outerArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (outerArray == NULL) { + // TODO + } + uiOpenTypeFeaturesForEach(otf, otfArrayForEach, outerArray); + return outerArray; +} diff --git a/darwin/uipriv_darwin.h b/darwin/uipriv_darwin.h index 4020dd27..56a576d4 100644 --- a/darwin/uipriv_darwin.h +++ b/darwin/uipriv_darwin.h @@ -153,7 +153,8 @@ typedef void (^backgroundBlock)(uiDrawContext *c, uiDrawTextLayout *layout, doub extern CFAttributedStringRef attrstrToCoreFoundation(uiDrawTextLayoutParams *p, NSArray **backgroundBlocks); // aat.m -extern void openTypeToAAT(uiOpenTypeFeatures *otf, void (*doAAT)(uint16_t type, uint16_t selector, void *data), void *data); +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 @@ -164,6 +165,7 @@ extern void openTypeToAAT(uiOpenTypeFeatures *otf, void (*doAAT)(uint16_t type, (x8tox32(b) << 16) | \ (x8tox32(c) << 8) | \ x8tox32(d)) +extern CFArrayRef otfToFeaturesArray(const uiOpenTypeFeatures *otf); // future.m extern CFStringRef *FUTURE_kCTFontOpenTypeFeatureTag; diff --git a/ui_attrstr.h b/ui_attrstr.h index d293f590..ad4169e9 100644 --- a/ui_attrstr.h +++ b/ui_attrstr.h @@ -64,7 +64,8 @@ _UI_EXTERN uiOpenTypeFeatures *uiOpenTypeFeaturesClone(const uiOpenTypeFeatures _UI_EXTERN void uiOpenTypeFeaturesAdd(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value); _UI_EXTERN void uiOpenTypeFeaturesRemove(uiOpenTypeFeatures *otf, char a, char b, char c, char d); _UI_EXTERN int uiOpenTypeFeaturesGet(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t *value); -_UI_EXTERN void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data); +// TODO make other enumerators const (and in general const-correct everything) +_UI_EXTERN void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data); _UI_EXTERN int uiOpenTypeFeaturesEqual(const uiOpenTypeFeatures *a, const uiOpenTypeFeatures *b); typedef struct uiAttributeSpec uiAttributeSpec; diff --git a/unix/opentype.c b/unix/opentype.c index 6700b83e..f9d14e09 100644 --- a/unix/opentype.c +++ b/unix/opentype.c @@ -96,7 +96,7 @@ static void foreach(gpointer key, gpointer value, gpointer data) (*(ofe->f))((char) a, (char) b, (char) c, (char) d, GPOINTER_TO_INT(value), ofe->data); } -void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) +void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) { struct otfForEach ofe; diff --git a/windows/opentype.cpp b/windows/opentype.cpp index 141f8a5f..b27b7d7a 100644 --- a/windows/opentype.cpp +++ b/windows/opentype.cpp @@ -57,7 +57,7 @@ int uiOpenTypeFeaturesGet(uiOpenTypeFeatures *otf, char a, char b, char c, char return 1; } -void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) +void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data) { tagmap::const_iterator iter, end;