// 14 february 2017 #import "uipriv_darwin.h" static void boolspec(uiAttributeSpec *spec, uint16_t type, uint16_t ifTrue, uint16_t ifFalse, specToAATEnumFunc f, void *data) { if (spec->Value != 0) { (*f)(type, ifTrue, data); return; } (*f)(type, ifFalse, data); } int specToAAT(uiAttributeSpec *spec, specToAATEnumFunc f, void *data) { switch (spec->Type) { case uiAttributeStandardLigatures: boolspec(spec, kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector, f, data); return 1; case uiAttributeRequiredLigatures: boolspec(spec, kLigaturesType, kRequiredLigaturesOnSelector, kRequiredLigaturesOffSelector, f, data); return 1; case uiAttributeDiscretionaryLigatures: boolspec(spec, kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector, f, data); return 1; case uiAttributeContextualLigatures: boolspec(spec, kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector, f, data); return 1; case uiAttributeHistoricalLigatures: boolspec(spec, kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector, f, data); return 1; case uiAttributeUnicase: // TODO is this correct, or should we provide an else case? if (spec->Value != 0) // this is undocumented; it comes from Core Text's internal AAT-to-OpenType conversion table (*f)(kLetterCaseType, 14, data); return 1; // TODO make an array? case uiAttributeNumberSpacings: switch (spec->Value) { case uiAttributeNumberSpacingProportional: (*f)(kNumberSpacingType, kProportionalNumbersSelector, data); break; case uiAttributeNumberSpacingTabular: (*f)(kNumberSpacingType, kMonospacedNumbersSelector, data); break; } return 1; // TODO make an array? case uiAttributeSuperscripts: switch (spec->Value) { case uiAttributeSuperscriptNone: (*f)(kVerticalPositionType, kNormalPositionSelector, data); break; case uiAttributeSuperscriptSuperscript: (*f)(kVerticalPositionType, kSuperiorsSelector, data); break; case uiAttributeSuperscriptSubscript: (*f)(kVerticalPositionType, kInferiorsSelector, data); break; case uiAttributeSuperscriptOrdinal: (*f)(kVerticalPositionType, kOrdinalsSelector, data); break; case uiAttributeSuperscriptScientificInferior: (*f)(kVerticalPositionType, kScientificInferiorsSelector, data); break; } return 1; // TODO make an array? case uiAttributeFractionForms: switch (spec->Value) { case uiAttributeFractionFormNone: (*f)(kFractionsType, kNoFractionsSelector, data); break; case uiAttributeFractionFormVertical: (*f)(kFractionsType, kVerticalFractionsSelector, data); break; case uiAttributeFractionFormDiagonal: (*f)(kFractionsType, kDiagonalFractionsSelector, data); break; } return 1; case uiAttributeSlashedZero: boolspec(spec, kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector, f, data); return 1; case uiAttributeMathematicalGreek: boolspec(spec, kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector, f, data); return 1; case uiAttributeOrnamentalForms: (*f)(kOrnamentSetsType, (uint16_t) (spec->Value), data); return 1; case uiAttributeSpecificCharacterForm: (*f)(kCharacterAlternativesType, (uint16_t) (spec->Value), data); return 1; case uiAttributeTitlingCapitalForms: // TODO is this correct, or should we provide an else case? if (spec->Value != 0) (*f)(kStyleOptionsType, kTitlingCapsSelector, data); return 1; // TODO make an array? case uiAttributeHanCharacterForms: switch (spec->Value) { case uiAttributeHanCharacterFormTraditional: (*f)(kCharacterShapeType, kTraditionalCharactersSelector, data); break; case uiAttributeHanCharacterFormSimplified: (*f)(kCharacterShapeType, kSimplifiedCharactersSelector, data); break; case uiAttributeHanCharacterFormJIS1978: (*f)(kCharacterShapeType, kJIS1978CharactersSelector, data); break; case uiAttributeHanCharacterFormJIS1983: (*f)(kCharacterShapeType, kJIS1983CharactersSelector, data); break; case uiAttributeHanCharacterFormJIS1990: (*f)(kCharacterShapeType, kJIS1990CharactersSelector, data); break; case uiAttributeHanCharacterFormExpert: (*f)(kCharacterShapeType, kExpertCharactersSelector, data); break; case uiAttributeHanCharacterFormJIS2004: (*f)(kCharacterShapeType, kJIS2004CharactersSelector, data); break; case uiAttributeHanCharacterFormHojo: (*f)(kCharacterShapeType, kHojoCharactersSelector, data); break; case uiAttributeHanCharacterFormNLC: (*f)(kCharacterShapeType, kNLCCharactersSelector, data); break; case uiAttributeHanCharacterFormTraditionalNames: (*f)(kCharacterShapeType, kTraditionalNamesCharactersSelector, data); break; } return 1; case uiAttributeLowercaseNumbers: // TODO is this correct, or should we provide an else case? if (spec->Value != 0) (*f)(kNumberCaseType, kLowerCaseNumbersSelector, data); return 1; case uiAttributeHanjaToHangul: // TODO is this correct, or should we provide an else case? if (spec->Value != 0) (*f)(kTransliterationType, kHanjaToHangulSelector, data); return 1; case uiAttributeGlyphAnnotations: (*f)(kAnnotationType, (uint16_t) (spec->Value), data); return 1; case uiAttributeRubyKanaForms: // include this for completeness boolspec(spec, kRubyKanaType, kRubyKanaSelector, kNoRubyKanaSelector, f, data); // this is the current one boolspec(spec, kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector, f, data); return 1; case uiAttributeCJKRomansToItalics: // include this for completeness boolspec(spec, kItalicCJKRomanType, kCJKItalicRomanSelector, kNoCJKItalicRomanSelector, f, data); // this is the current one boolspec(spec, kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector, f, data); return 1; case uiAttributeCaseSensitiveForms: boolspec(spec, kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector, f, data); return 1; case uiAttributeCapitalSpacing: boolspec(spec, kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector, f, data); return 1; case uiAttributeAlternateHorizontalKana: boolspec(spec, kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, f, data); return 1; case uiAttributeAlternateVerticalKana: boolspec(spec, kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector, f, data); return 1; case uiAttributeStylisticAlternative1: boolspec(spec, kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector, f, data); return 1; case uiAttributeStylisticAlternative2: boolspec(spec, kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector, f, data); return 1; case uiAttributeStylisticAlternative3: boolspec(spec, kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector, f, data); return 1; case uiAttributeStylisticAlternative4: boolspec(spec, kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector, f, data); return 1; case uiAttributeStylisticAlternative5: boolspec(spec, kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector, f, data); return 1; case uiAttributeStylisticAlternative6: boolspec(spec, kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector, f, data); return 1; case uiAttributeStylisticAlternative7: boolspec(spec, kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative8: boolspec(spec, kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector, f, data); return 1; case uiAttributeStylisticAlternative9: boolspec(spec, kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector, f, data); return 1; case uiAttributeStylisticAlternative10: boolspec(spec, kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative11: boolspec(spec, kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative12: boolspec(spec, kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector, f, data); return 1; case uiAttributeStylisticAlternative13: boolspec(spec, kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative14: boolspec(spec, kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative15: boolspec(spec, kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative16: boolspec(spec, kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative17: boolspec(spec, kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative18: boolspec(spec, kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative19: boolspec(spec, kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector, f, data); return 1; case uiAttributeStylisticAlternative20: boolspec(spec, kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector, f, data); return 1; case uiAttributeContextualAlternates: boolspec(spec, kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector, f, data); return 1; case uiAttributeSwashes: boolspec(spec, kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector, f, data); return 1; case uiAttributeContextualSwashes: boolspec(spec, kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector, f, data); return 1; // TODO use arrays? case uiAttributeLowercaseCapForms: switch (spec->Value) { case uiAttributeCapFormNormal: (*f)(kLowerCaseType, kDefaultLowerCaseSelector, data); break; case uiAttributeCapFormSmallCaps: // include this for compatibility (some fonts that come with OS X still use this!) // TODO make it boolean? (*f)(kLetterCaseType, kSmallCapsSelector, data); // this is the current one (*f)(kLowerCaseType, kLowerCaseSmallCapsSelector, data); break; case uiAttributeCapFormPetiteCaps: (*f)(kLowerCaseType, kLowerCasePetiteCapsSelector, data); break; } return 1; // TODO use arrays? case uiAttributeUppercaseCapForms: switch (spec->Value) { case uiAttributeCapFormNormal: (*f)(kUpperCaseType, kDefaultUpperCaseSelector, data); break; case uiAttributeCapFormSmallCaps: (*f)(kUpperCaseType, kUpperCaseSmallCapsSelector, data); break; case uiAttributeCapFormPetiteCaps: (*f)(kUpperCaseType, kUpperCasePetiteCapsSelector, data); break; } return 1; } return 0; }