diff --git a/changes/10.3.2.md b/changes/10.3.2.md new file mode 100644 index 000000000..a39ad1f96 --- /dev/null +++ b/changes/10.3.2.md @@ -0,0 +1 @@ + * Add support for OpenType `frac` feature (#1230). \ No newline at end of file diff --git a/font-src/glyphs/auto-build/transformed.ptl b/font-src/glyphs/auto-build/transformed.ptl index 99a389478..89230d57a 100644 --- a/font-src/glyphs/auto-build/transformed.ptl +++ b/font-src/glyphs/auto-build/transformed.ptl @@ -2,7 +2,9 @@ $$include '../../meta/macros.ptl' import [linreg clamp mix fallback] from '../../support/utils' -import [AnyCv DotlessOrNot getGrTree getGrMesh CvDecompose MathSansSerif] from "../../support/gr" +import [getGrTree getGrMesh] from "../../support/gr" +import [AnyCv DotlessOrNot CvDecompose MathSansSerif] from "../../support/gr" +import [NumeratorForm DenominatorForm] from "../../support/gr" extern Map extern Set @@ -50,6 +52,7 @@ glyph-block Autobuild-Transformed-Shared : begin local relatedRecord : record.slice 0 set relatedRecord.0 null set relatedRecord.1 relSrcName + set relatedRecord.2 true relatedRecords.push relatedRecord relSets.push { gr origDstName relDstName } @@ -74,16 +77,16 @@ glyph-block Autobuild-Transformed : begin glyph-block-import Mark-Below : belowMarkBot belowMarkTop glyph-block-import Autobuild-Transformed-Shared : extendRelatedGlyphs link-relations - define [createSuperscripts _records] : begin - local {records relSets targetNameMap} : extendRelatedGlyphs 'sup' _records + define [createSuperscripts prefix gr _records] : begin + local {records relSets targetNameMap} : extendRelatedGlyphs prefix _records local pendingGlyphs : records.map : [record] => record.1 local miniatureFont : Miniature pendingGlyphs crowd -- 3.5 scale -- 0.7 mono -- true - sbscale -- 1 - foreach {unicode glyphid} [items-of records] - if [not : query-glyph targetNameMap.(glyphid)] + sbscale -- 0.75 + foreach { unicode glyphid fRelated } [items-of records] + if [not : query-glyph targetNameMap.(glyphid)] : begin create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc if [not : miniatureFont.queryByName glyphid] : begin throw : new Error "Cannot find glyph \(glyphid)" @@ -94,19 +97,20 @@ glyph-block Autobuild-Transformed : begin include [Scale 0.7] true include [Translate middle (CAP + AccentStackOffset / 2)] true include [Italify] true + if ([not fRelated] && gr) : gr.set [query-glyph glyphid] (targetNameMap.(glyphid)) link-relations relSets return { targetNameMap records } - define [createSubscripts _records] : begin - local {records relSets targetNameMap} : extendRelatedGlyphs 'sub' _records + define [createSubscripts prefix gr _records] : begin + local {records relSets targetNameMap} : extendRelatedGlyphs prefix _records local pendingGlyphs : records.map : [record] => record.1 local miniatureFont : Miniature pendingGlyphs crowd -- 3.5 scale -- 0.7 mono -- true - sbscale -- 1 - foreach {unicode glyphid} [items-of records] - if [not : query-glyph targetNameMap.(glyphid)] + sbscale -- 0.75 + foreach { unicode glyphid fRelated } [items-of records] + if [not : query-glyph targetNameMap.(glyphid)] : begin create-glyph (targetNameMap.(glyphid)) unicode : glyph-proc local middle : [miniatureFont.queryByName glyphid].advanceWidth / 2 include [miniatureFont.queryByName glyphid] AS_BASE ALSO_METRICS @@ -115,6 +119,7 @@ glyph-block Autobuild-Transformed : begin include [Scale 0.7] true include [Translate middle (Descender / 2)] true include [Italify] true + if ([not fRelated] && gr) : gr.set [query-glyph glyphid] (targetNameMap.(glyphid)) link-relations relSets # Not used today -- may be used in the future @@ -191,7 +196,7 @@ glyph-block Autobuild-Transformed : begin link-relations relSets - createSuperscripts : list + createSuperscripts 'sup' null : list list 0x00AA 'aSbRsbUnderlineBelow' list 0x00BA 'oSbRsbUnderlineBelow' list 0x2070 'zero.lnum' @@ -322,15 +327,37 @@ glyph-block Autobuild-Transformed : begin list 0xA7F8 'smcpHbar' list 0xA7F9 'oe' + createSuperscripts 'numerator' NumeratorForm : list + list null 'zero.onum' + list null 'one.onum' + list null 'two.onum' + list null 'three.onum' + list null 'four.onum' + list null 'five.onum' + list null 'six.onum' + list null 'seven.onum' + list null 'eight.onum' + list null 'nine.onum' + list null 'zero.lnum' + list null 'one.lnum' + list null 'two.lnum' + list null 'three.lnum' + list null 'four.lnum' + list null 'five.lnum' + list null 'six.lnum' + list null 'seven.lnum' + list null 'eight.lnum' + list null 'nine.lnum' + do "superscript AE" - define { tnmAHalf jobsAHalf } : createSuperscripts { { null 'AE/AHalf' } } - define { tnmEHalf jobsEHalf } : createSuperscripts { { null 'AE/EHalf' } } + define { tnmAHalf jobsAHalf } : createSuperscripts 'sup' null { { null 'AE/AHalf' } } + define { tnmEHalf jobsEHalf } : createSuperscripts 'sup' null { { null 'AE/EHalf' } } create-glyph 'sup{AE}' 0x1D2D : glyph-proc include [refer-glyph tnmAHalf.('AE/AHalf')] AS_BASE ALSO_METRICS include [refer-glyph tnmEHalf.('AE/EHalf')] CvDecompose.set currentGlyph { tnmAHalf.('AE/AHalf') tnmEHalf.('AE/EHalf') } - createSubscripts : list + createSubscripts 'sub' null : list list 0x2080 'zero.lnum' list 0x2081 'one.lnum' list 0x2082 'two.lnum' @@ -370,6 +397,28 @@ glyph-block Autobuild-Transformed : begin list 0x208D 'parenLeft' list 0x208E 'parenRight' + createSubscripts 'denominator' DenominatorForm : list + list null 'zero.onum' + list null 'one.onum' + list null 'two.onum' + list null 'three.onum' + list null 'four.onum' + list null 'five.onum' + list null 'six.onum' + list null 'seven.onum' + list null 'eight.onum' + list null 'nine.onum' + list null 'zero.lnum' + list null 'one.lnum' + list null 'two.lnum' + list null 'three.lnum' + list null 'four.lnum' + list null 'five.lnum' + list null 'six.lnum' + list null 'seven.lnum' + list null 'eight.lnum' + list null 'nine.lnum' + createMedievalCombs 0 XH : list list 0x363 'a' list 0x364 'e' diff --git a/font-src/glyphs/symbol/punctuation/slashes-and-number-sign.ptl b/font-src/glyphs/symbol/punctuation/slashes-and-number-sign.ptl index 0c4f356c7..79d388c3d 100644 --- a/font-src/glyphs/symbol/punctuation/slashes-and-number-sign.ptl +++ b/font-src/glyphs/symbol/punctuation/slashes-and-number-sign.ptl @@ -26,7 +26,8 @@ glyph-block Symbol-Punctuation-Slashes-And-Number-Sign : begin create-glyph 'slash' '/' : glyph-proc include : SlashShape slashDefautLeft slashDefaultRight - alias 'solidus' 0x2044 'slash' + alias 'solidus' 0x2044 'slash' + alias 'fractionBar' null 'slash' alias 'mathDivSlash' 0x2215 'slash' create-glyph 'doubleSlash' 0x2AFD : glyph-proc diff --git a/font-src/otl/gsub-frac.ptl b/font-src/otl/gsub-frac.ptl new file mode 100644 index 000000000..2e683976f --- /dev/null +++ b/font-src/otl/gsub-frac.ptl @@ -0,0 +1,50 @@ +import [add-common-feature add-feature add-lookup BeginLookupBlock EndLookupBlock ChainRuleBuilder] from "./table-util" +import [NumeratorForm DenominatorForm] from "../support/gr" + +define-operator "~>" 880 'right' : syntax-rules + `(@l ~> @r) `{.left @l .right @r} + +# Name-driven feature pairs +export : define [buildFrac sink glyphStore] : begin + local rec : BeginLookupBlock sink + + define frac : add-feature sink 'frac' + define { chain-rule reverse-rule } : ChainRuleBuilder sink + + define subSolidus : add-lookup sink : object + .type 'gsub_single' + .substitutions : object ['solidus' 'fractionBar'] + + define digitSet { } + define numSet { } + define denSet { } + + foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== ".") : begin + local numForm : NumeratorForm.get g + local denForm : DenominatorForm.get g + if (numForm && denForm) : begin + digitSet.push gid + numSet.push numForm + denSet.push denForm + + define subDen : add-lookup sink : object + .type 'gsub_chaining' + .rules : list + chain-rule [{'fractionBar'}.concat denSet] [digitSet ~> denSet] + + define subNum : add-lookup sink : object + .type 'gsub_reverse' + .rules : list + reverse-rule [digitSet ~> numSet] [{'fractionBar'}.concat numSet] + + frac.lookups.push subSolidus + frac.lookups.push subDen + frac.lookups.push subNum + sink.lookupDep.push {subSolidus subDen} + sink.lookupDep.push {subSolidus subNum} + + add-common-feature sink frac + + EndLookupBlock rec sink + +define [objectIsNotEmpty obj] : obj && [Object.keys obj].length diff --git a/font-src/otl/index.ptl b/font-src/otl/index.ptl index 71c225a8d..84c4755d2 100644 --- a/font-src/otl/index.ptl +++ b/font-src/otl/index.ptl @@ -6,6 +6,7 @@ import [CreateEmptyTable finalizeTable MoveBackUtilityLookups] from "./table-uti import [buildLigations] from './gsub-ligation' import [buildCCMP] from './gsub-ccmp' import [buildGrFeature] from './gsub-gr' +import [buildFrac] from './gsub-frac' import [buildCVSS] from './gsub-cv-ss' import [buildLOCL] from './gsub-locl' import [buildGsubThousands] from './gsub-thousands' @@ -35,6 +36,9 @@ define [buildGSUB para glyphStore markGlyphs] : begin # ccmp buildCCMP gsub glyphStore markGlyphs + # frac + buildFrac gsub glyphStore + # Ligation if para.enableLigation : do define plm : Object.assign {.} para.ligation.defaultBuildup diff --git a/font-src/support/gr.js b/font-src/support/gr.js index 250c1b05b..34364aeb5 100644 --- a/font-src/support/gr.js +++ b/font-src/support/gr.js @@ -44,6 +44,8 @@ const Wwid = OtlTaggedProp("Wwid", "WWID"); const Lnum = OtlTaggedProp("Lnum", "lnum"); const Onum = OtlTaggedProp("Onum", "onum"); const AplForm = OtlTaggedProp("AplForm", "APLF"); +const NumeratorForm = OtlTaggedProp("Numerator", "NUMF"); +const DenominatorForm = OtlTaggedProp("Denominator", "DENF"); const CvDecompose = { get(glyph) { @@ -457,6 +459,8 @@ exports.Wwid = Wwid; exports.Lnum = Lnum; exports.Onum = Onum; exports.AplForm = AplForm; +exports.NumeratorForm = NumeratorForm; +exports.DenominatorForm = DenominatorForm; exports.createGrDisplaySheet = createGrDisplaySheet; exports.linkSuffixGr = linkSuffixGr;