Add support for OpenType frac feature (#1230).

This commit is contained in:
be5invis 2021-10-09 18:51:58 -07:00
parent 844f4023c4
commit 35ecd6dddc
6 changed files with 125 additions and 16 deletions

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;