Implement leaning mark mechanism for F
, L
, P
, b
, d
, h
, k
, p
, q
, r
to get better mark placement. Now, "narrow" marks will align to these letters' extension parts (#1851).
This commit is contained in:
parent
387389919c
commit
f7fd09172b
33 changed files with 419 additions and 168 deletions
|
@ -1,6 +1,7 @@
|
|||
* Add characters:
|
||||
- CLOCK FACE ONE OCLOCK (`U+1F550`) ... CLOCK FACE TWELVE-THIRTY (`U+1F567`) (#1850).
|
||||
* Implement leaning mark mechanism for `F`, `L`, `P`, `b`, `d`, `h`, `k`, `p`, `q`, `r` to get better mark placement. Now, "narrow" marks will align to these letters' extension parts (#1851).
|
||||
* Fix detached cedilla in Hookless asymmetric LATIN SMALL LETTER T WITH CEDILLA (`U+0163`) (#1914).
|
||||
* Fix broken hookless/tailless/assymetric t variants in ſt ligature (`U+FB05`) (#1915).
|
||||
* Fix broken hookless/tailless/asymmetric t variants in ſt ligature (`U+FB05`) (#1915).
|
||||
* Remove unnecessary tailed variants for Cyrillic Shha with Descender (`U+0527`) (#1916).
|
||||
* Remove unnecessary lower-right serif variants for Latin Lower K with Descender (`U+2C6A`) (#1917).
|
|
@ -21,7 +21,7 @@ function assignSubRank(glyphStore) {
|
|||
// "Fixed" subfamilies are properly built.
|
||||
function validateMonospace(para, glyphStore) {
|
||||
let awSet = new Set();
|
||||
for (const [u, g] of glyphStore.encodedEntries()) {
|
||||
for (const [u, n, g] of glyphStore.encodedEntries()) {
|
||||
const aw = Math.round(g.advanceWidth || 0);
|
||||
if (aw > 0) awSet.add(aw);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Joining, AnyCv, TieMark, Nwid, Wwid } from "../../support/gr.mjs";
|
||||
import { Joining, AnyCv, TieMark, Nwid, Wwid, VS01 } from "../../support/gr.mjs";
|
||||
|
||||
const ApplePostNames = new Map([
|
||||
/* spell-checker: disable */
|
||||
|
@ -286,14 +286,18 @@ export function bySpacing(gSrcBase, gOtBase, internalNameMap, conflictSet) {
|
|||
return n;
|
||||
}
|
||||
|
||||
const NamingGr = [TieMark, VS01];
|
||||
|
||||
export function byGr(gSrcBase, gOtBase, internalNameMap, conflictSet) {
|
||||
if (!gOtBase.name) return 0;
|
||||
let n = 0;
|
||||
for (const cv of AnyCv.query(gSrcBase)) {
|
||||
n += nameByGr(cv, gSrcBase, gOtBase, internalNameMap, conflictSet);
|
||||
}
|
||||
if (TieMark.get(gSrcBase)) {
|
||||
n += nameByGr(TieMark, gSrcBase, gOtBase, internalNameMap, conflictSet);
|
||||
for (const gr of NamingGr) {
|
||||
if (gr.get(gSrcBase)) {
|
||||
n += nameByGr(gr, gSrcBase, gOtBase, internalNameMap, conflictSet);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
###### Automatic builds
|
||||
$$include '../../meta/macros.ptl'
|
||||
|
||||
import [Dotless AnyDerivingCv DotlessOrNot getGrTree CvDecompose] from"../../support/gr.mjs"
|
||||
import [fallback] from"../../support/utils.mjs"
|
||||
import [Dotless AnyDerivingCv DotlessOrNot getGrTree CvDecompose LeaningMark LeaningMarkSpacer] from"../../support/gr.mjs"
|
||||
import [fallback ArrayUtil MatchUtil constant] from"../../support/utils.mjs"
|
||||
import as UnicodeKnowledge from"../../meta/unicode-knowledge.mjs"
|
||||
|
||||
extern Map
|
||||
extern Set
|
||||
|
||||
glyph-module
|
||||
|
||||
glyph-block AutoBuild-Accents : begin
|
||||
|
@ -24,42 +27,150 @@ glyph-block AutoBuild-Accents : begin
|
|||
set map.(key) amended
|
||||
return amended
|
||||
|
||||
# Build accented glyphs
|
||||
define [isAboveMark mark] : begin
|
||||
return : mark && mark.markAnchors && mark.markAnchors.above
|
||||
# Here, we build a simplified substitution builder that does the mark substitutions
|
||||
define [substParts parts ignore backtrack input loookAhead production] : begin
|
||||
local igl 0
|
||||
while (igl < parts.length) : begin
|
||||
local m : substMatch parts igl ignore backtrack input loookAhead
|
||||
if [not m]
|
||||
: then : inc igl
|
||||
: else : begin
|
||||
local inputGlyphs : ArrayUtil.mapIndexToItems parts m
|
||||
local producedGlyphs : production.apply null inputGlyphs
|
||||
foreach i [range (m.length - 1) downtill 0] : begin
|
||||
parts.splice m.(i) 1
|
||||
ArrayUtil.insertSliceAt parts m.0 producedGlyphs
|
||||
set igl : m.(m.length - 1) + 1 + producedGlyphs.length - m.length
|
||||
|
||||
define [MarkSubst lookup] : function [p j parts] : begin
|
||||
foreach { k v } [Object.entries lookup] : begin
|
||||
if (p === [query-glyph k]) : set parts.(j) [query-glyph v]
|
||||
return parts
|
||||
|
||||
define iotaBelowToLF : MarkSubst UnicodeKnowledge.iotaBelowToLfTf
|
||||
define ogonekBelowToTR : MarkSubst UnicodeKnowledge.ogonekBelowToTRTf
|
||||
define grekUpperTonos : MarkSubst UnicodeKnowledge.upperGrekMarkToTonosTf
|
||||
define [substMatch parts igl ignore backtrack input lookAhead] : begin
|
||||
if (igl >= parts.length) : return null
|
||||
if [ignore parts.(igl)] : return null
|
||||
if [not : input.0 parts.(igl)] : return null
|
||||
|
||||
local m { igl }
|
||||
|
||||
# Check input
|
||||
local iglInput : igl + 1
|
||||
foreach iInput [range 1 input.length] : begin
|
||||
while (iglInput < parts.length && [ignore parts.(iglInput)]) : inc iglInput
|
||||
if (iglInput >= parts.length) : return null
|
||||
if [not : input.(iInput) parts.(iglInput)] : return null
|
||||
m.push iglInput
|
||||
inc iglInput
|
||||
|
||||
# Check lookahead
|
||||
local iglLookAhead iglInput
|
||||
foreach iLookAhead [range 0 lookAhead.length] : begin
|
||||
while (iglLookAhead < parts.length && [ignore parts.(iglLookAhead)]) : inc iglLookAhead
|
||||
if (iglLookAhead >= parts.length) : return null
|
||||
if [not : lookAhead.(iLookAhead) parts.(iglLookAhead)] : return null
|
||||
inc iglLookAhead
|
||||
|
||||
# Check backtrack
|
||||
local iglBacktrack : igl - 1
|
||||
foreach iBacktrack [range (backtrack.length - 1) downtill 0] : begin
|
||||
while (iglBacktrack >= 0 && [ignore parts.(iglBacktrack)]) : dec iglBacktrack
|
||||
if (iglBacktrack < 0) : return null
|
||||
if [not : backtrack.(iBacktrack) parts.(iglBacktrack)] : return null
|
||||
dec iglBacktrack
|
||||
|
||||
return m
|
||||
|
||||
define [dotless g] : begin
|
||||
local gDotless : query-glyph : Dotless.get g
|
||||
if [not gDotless] : return null
|
||||
return {gDotless}
|
||||
|
||||
define [isMark k] : function [g] : begin
|
||||
return : g && g.markAnchors && g.markAnchors.(k)
|
||||
define [isMarkExcluding k] : function [g] : begin
|
||||
return : g && g.markAnchors && [Object.keys g.markAnchors].length && !g.markAnchors.(k)
|
||||
define [hasBaseAnchor k] : function [g] : begin
|
||||
return : g && g.baseAnchors && g.baseAnchors.(k)
|
||||
define [isLeaningMark k] : function [g] : begin
|
||||
return : g && g.markAnchors && g.markAnchors.(k) && [LeaningMark.get g]
|
||||
define [leaningMarkSplit g] : begin
|
||||
local spacer : query-glyph : LeaningMarkSpacer.get g
|
||||
local alternative : query-glyph : LeaningMark.get g
|
||||
if (spacer && alternative) : return { spacer alternative }
|
||||
return { g }
|
||||
|
||||
define [markSubst uk] : begin
|
||||
local fromGlyphs : new Set
|
||||
local mapping : new Map
|
||||
foreach { k v } [Object.entries uk] : begin
|
||||
local gFrom : query-glyph k
|
||||
local gTo : query-glyph v
|
||||
if (gFrom && gTo) : begin
|
||||
fromGlyphs.add gFrom
|
||||
mapping.set gFrom gTo
|
||||
|
||||
define [matcher g] : fromGlyphs.has g
|
||||
define [ignore g] : g && g.markAnchors && [Object.keys g.markAnchors].length && ![matcher g]
|
||||
define [production g] : list ([mapping.get g] || g)
|
||||
|
||||
return : object matcher ignore production
|
||||
|
||||
define [markCombine uk] : begin
|
||||
local first : new Set
|
||||
local second : new Set
|
||||
local mapping : new Map
|
||||
|
||||
foreach { k1 m } [Object.entries uk] : begin
|
||||
foreach { k2 v } [Object.entries m] : begin
|
||||
local g1 : query-glyph k1
|
||||
local g2 : query-glyph k2
|
||||
local g3 : query-glyph v
|
||||
if (g1 && g2 && g3) : begin
|
||||
first.add g1
|
||||
second.add g2
|
||||
|
||||
local mm : mapping.get g1
|
||||
if [not mm] : begin
|
||||
set mm : new Map
|
||||
mapping.set g1 mm
|
||||
mm.set g2 g3
|
||||
|
||||
define [matchFirst g] : first.has g
|
||||
define [matchSecond g] : second.has g
|
||||
define [production g1 g2] : begin
|
||||
local mm : mapping.get g1
|
||||
if [not mm] : return { g1 g2 }
|
||||
local g3 : mm.get g2
|
||||
if [not g3] : return { g1 g2 }
|
||||
return { g3 }
|
||||
|
||||
return : object matchFirst matchSecond production
|
||||
|
||||
define iotaLF : markSubst UnicodeKnowledge.iotaBelowToLfTf
|
||||
define ogonek : markSubst UnicodeKnowledge.ogonekBelowToTRTf
|
||||
define upperTonos : markSubst UnicodeKnowledge.upperGrekMarkToTonosTf
|
||||
|
||||
define markComposition : markCombine UnicodeKnowledge.markCompositionTf
|
||||
|
||||
define [subParts parts] : begin
|
||||
# Keep the semantics here synchronized with `ccmp` feature
|
||||
# Handle dotless
|
||||
local hasMarkAbove false
|
||||
foreach p [items-of parts] : if [isAboveMark p] : set hasMarkAbove true
|
||||
if (hasMarkAbove && [Dotless.get parts.0]) : begin
|
||||
local dotless [query-glyph : Dotless.get parts.0]
|
||||
if dotless : set parts.0 dotless
|
||||
### Keep the semantics here synchronized with `ccmp` feature
|
||||
|
||||
# replace below marks with trailing marks
|
||||
if parts.0.baseAnchors.lf : parts.forEach iotaBelowToLF
|
||||
if parts.0.baseAnchors.trailing : parts.forEach ogonekBelowToTR
|
||||
# Handle dotless form
|
||||
substParts parts [isMarkExcluding 'above'] {} {dotless} {[isMark 'above']} dotless
|
||||
|
||||
# composite greek Marks
|
||||
for [local j 0] (j < parts.length) [inc j] : begin
|
||||
foreach { gidFirst seconds } [Object.entries UnicodeKnowledge.markCompositionTf]
|
||||
if (parts.(j) === [query-glyph gidFirst])
|
||||
foreach { gidSecond gidTo } [Object.entries seconds]
|
||||
if (parts.(j + 1) === [query-glyph gidSecond]) : begin
|
||||
set parts.(j) [query-glyph gidTo]; set parts.(j + 1) null
|
||||
# Handle iota subscript
|
||||
substParts parts iotaLF.ignore {[hasBaseAnchor 'lf']} {iotaLF.matcher} {} iotaLF.production
|
||||
|
||||
if parts.0.baseAnchors.grekUpperTonos : grekUpperTonos parts.1 1 parts
|
||||
# Handle ogonek
|
||||
substParts parts ogonek.ignore {[hasBaseAnchor 'trailing']} {ogonek.matcher} {} ogonek.production
|
||||
|
||||
return : parts.filter : function [x] [not : not x]
|
||||
# Handle leaning marks
|
||||
substParts parts [isMarkExcluding 'above'] {[MatchUtil.either [hasBaseAnchor 'leaningAbove'] [isMark 'leaningAbove']]} {[isLeaningMark 'above']} {} leaningMarkSplit
|
||||
substParts parts [isMarkExcluding 'below'] {[MatchUtil.either [hasBaseAnchor 'leaningBelow'] [isMark 'leaningBelow']]} {[isLeaningMark 'below']} {} leaningMarkSplit
|
||||
|
||||
# Handle mark combinations (Greek)
|
||||
substParts parts MatchUtil.never {} { markComposition.matchFirst markComposition.matchSecond } {} markComposition.production
|
||||
|
||||
# Handle upper Greek Tonos marks
|
||||
substParts parts MatchUtil.never {[hasBaseAnchor 'grekUpperTonos']} {upperTonos.matcher} {} upperTonos.production
|
||||
|
||||
define [pad _s n] : begin
|
||||
local s _s
|
||||
|
@ -96,7 +207,7 @@ glyph-block AutoBuild-Accents : begin
|
|||
|
||||
if (allFound && parts.length) : begin
|
||||
local glyphName : 'u' + [code.toString 16 :.padStart 4 '0']
|
||||
set parts : subParts parts
|
||||
subParts parts
|
||||
set foundDecompositions.(glyphName) { glyphName code parts }
|
||||
|
||||
local s_goalName nothing
|
||||
|
|
|
@ -3,29 +3,76 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [TieMark AnyDerivingCv ScheduleLeaningMark LeaningMark LeaningMarkSpacer] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
extern Set
|
||||
|
||||
glyph-module
|
||||
|
||||
glyph-block Mark-Doppelganger : if [not recursive] : begin
|
||||
glyph-block-import CommonShapes
|
||||
glyph-block-import Common-Derivatives
|
||||
|
||||
define AnchorMap : list
|
||||
list 'above' 'tieAbove'
|
||||
list 'below' 'tieBelow'
|
||||
|
||||
foreach { gn g } [glyphStore.namedEntries] : begin
|
||||
local handled false
|
||||
foreach { akFrom akTo } [items-of AnchorMap] : begin
|
||||
if (!handled && g.markAnchors && g.markAnchors.(akFrom)) : begin
|
||||
set handled true
|
||||
local toGN : TieMark.amendName gn
|
||||
define [DeriveMarkChange gr gn akFrom akTo] : begin
|
||||
DeriveMeshT {gn} AnyDerivingCv : function [gns] : begin
|
||||
local srcGn gns.0
|
||||
local src : query-glyph srcGn
|
||||
local toGN : gr.amendName srcGn
|
||||
if [not : query-glyph toGN] : begin
|
||||
create-glyph toGN : glyph-proc
|
||||
include g AS_BASE ALSO_METRICS
|
||||
include [refer-glyph srcGn] AS_BASE ALSO_METRICS
|
||||
set currentGlyph.markAnchors.(akTo) currentGlyph.markAnchors.(akFrom)
|
||||
currentGlyph.deleteMarkAnchor akFrom
|
||||
set currentGlyph.baseAnchors.(akTo) currentGlyph.baseAnchors.(akFrom)
|
||||
currentGlyph.deleteBaseAnchor akFrom
|
||||
TieMark.set g toGN
|
||||
gr.set src toGN
|
||||
return toGN
|
||||
|
||||
|
||||
local spacerGlyphSet : new Set
|
||||
define TieAnchorMap : list
|
||||
list 'above' 'tieAbove'
|
||||
list 'below' 'tieBelow'
|
||||
|
||||
do : foreach { u gn g } [glyphStore.encodedEntries] : DeriveTieMarks gn g
|
||||
: where : [DeriveTieMarks gn g] : begin
|
||||
local selection null
|
||||
foreach { akFrom akTo } [items-of TieAnchorMap] : begin
|
||||
if (!selection && g.markAnchors.(akFrom)) : begin
|
||||
set selection { akFrom akTo }
|
||||
|
||||
if selection : begin
|
||||
local { akFrom akTo } selection
|
||||
DeriveMarkChange TieMark gn akFrom akTo
|
||||
|
||||
|
||||
define LeaningAnchorMap : list
|
||||
list 'above' 'leaningAbove'
|
||||
list 'below' 'leaningBelow'
|
||||
|
||||
do : foreach { u gn g } [glyphStore.encodedEntries] : DeriveLeaningMark gn g
|
||||
: where : [DeriveLeaningMark gn g] : begin
|
||||
local selection null
|
||||
foreach { akFrom akTo } [items-of LeaningAnchorMap] : begin
|
||||
if (!selection && g.markAnchors.(akFrom) && [ScheduleLeaningMark.get g]) : begin
|
||||
set selection { akFrom akTo }
|
||||
|
||||
if selection : begin
|
||||
local { akFrom akTo } selection
|
||||
|
||||
# Build the doppelganger
|
||||
DeriveMarkChange LeaningMark gn akFrom akTo
|
||||
|
||||
# build spacer glyph
|
||||
local deltaX : Math.round : g.baseAnchors.(akFrom).x - g.markAnchors.(akFrom).x
|
||||
local deltaY : Math.round : g.baseAnchors.(akFrom).y - g.markAnchors.(akFrom).y
|
||||
local spacerGn "spacerGlyph{\(akTo)}{\(deltaX)}{\(deltaY)}"
|
||||
|
||||
LeaningMarkSpacer.set g spacerGn
|
||||
|
||||
if [not : spacerGlyphSet.has spacerGn] : begin
|
||||
spacerGlyphSet.add spacerGn
|
||||
create-glyph spacerGn : glyph-proc
|
||||
include g AS_BASE ALSO_METRICS
|
||||
currentGlyph.clearGeometry
|
||||
|
|
|
@ -48,7 +48,9 @@ glyph-block Common-Derivatives : begin
|
|||
alias name unicode (name + '.upright')
|
||||
|
||||
glyph-block-export query-glyph
|
||||
define [query-glyph id] : return : glyphStore.queryByName id
|
||||
define [query-glyph id] : begin
|
||||
if [not id] : return nothing
|
||||
return : glyphStore.queryByName id
|
||||
|
||||
glyph-block-export refer-glyph
|
||||
define [refer-glyph id] : lambda [copyAnchors copyWidth] : begin
|
||||
|
|
|
@ -22,6 +22,7 @@ glyph-block Letter-Cyrillic-Che : begin
|
|||
define SLAB-TAILED-BGR 6
|
||||
|
||||
define [CyrCheShape top pyBar bodyType slabType] : glyph-proc
|
||||
set-base-anchor 'leaningBelow' (RightSB - [HSwToV HalfStroke]) 0
|
||||
local bar : top * [fallback pyBar 0.5]
|
||||
include : match bodyType
|
||||
[Just BODY-TAILED] : RightwardTailedBar RightSB 0 top
|
||||
|
|
|
@ -23,6 +23,7 @@ glyph-block Letter-Greek-Upper-Gamma: begin
|
|||
|
||||
define GammaBarLeft (SB * 1.5)
|
||||
define [GammaShape top slabType] : glyph-proc
|
||||
set-base-anchor 'leaningBelow' (GammaBarLeft + [HSwToV HalfStroke]) 0
|
||||
include : VBar.l GammaBarLeft 0 top
|
||||
include : HBar.t (GammaBarLeft - O) (RightSB - OX) top
|
||||
match slabType
|
||||
|
|
|
@ -503,15 +503,12 @@ glyph-block Letter-Latin-K : begin
|
|||
if slabLT : include : HSerif.lt (SB + [KBalance slabLT straightBar]) Ascender SideJut
|
||||
if slabLB : include : tagged 'serifLB'
|
||||
HSerif.mb (SB + [KBalance slabLT straightBar] + [HSwToV HalfStroke]) 0 Jut
|
||||
set-base-anchor 'leaningAbove' (SB + [KBalance slabLT straightBar] + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
create-glyph "k.\(suffix)" : glyph-proc
|
||||
include : MarkSet.b
|
||||
include : kBaseShape
|
||||
|
||||
create-glyph "k/circumflexBase.\(suffix)" : glyph-proc
|
||||
include [refer-glyph "k.\(suffix)"] AS_BASE ALSO_METRICS
|
||||
set-base-anchor 'above' (SB + [KBalance slabLT straightBar] + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
create-glyph "kDescender.\(suffix)" : glyph-proc
|
||||
include : MarkSet.b
|
||||
include : kBaseShape CyrDescender
|
||||
|
@ -550,7 +547,6 @@ glyph-block Letter-Latin-K : begin
|
|||
|
||||
select-variant 'k' 'k'
|
||||
select-variant 'k/nonCursive' (shapeFrom -- 'k')
|
||||
select-variant 'k/circumflexBase' (follow -- 'k')
|
||||
link-reduced-variant 'k/sansSerif' 'k' MathSansSerif
|
||||
select-variant 'kDescender' 0x2C6A
|
||||
select-variant 'kPalatalHook' 0x1D84 (follow -- 'kDescender')
|
||||
|
@ -578,11 +574,6 @@ glyph-block Letter-Latin-K : begin
|
|||
derive-composites 'KBarLegStroke' 0xA744 'KBar' 'legSlashOver'
|
||||
derive-composites 'kBarLegStroke' 0xA745 'kBar' 'legSlashOver'
|
||||
|
||||
derive-glyphs 'kCaron' 0x1E9 'k/circumflexBase' : lambda [src gr] : glyph-proc
|
||||
local shift : Width + SB - Middle + [HSwToV HalfStroke]
|
||||
include [refer-glyph src] AS_BASE ALSO_METRICS
|
||||
include [refer-glyph "caronAbove"]
|
||||
|
||||
turned 'turnK' 0xA7B0 'K' Middle (CAP / 2)
|
||||
turned 'turnk' 0x29E 'k' Middle (XH / 2) [MarkSet.p]
|
||||
turned 'turnSmcpK' 0x1DF10 'smcpK' Middle (XH / 2)
|
||||
|
|
|
@ -45,6 +45,7 @@ glyph-block Letter-Latin-Lower-B : begin
|
|||
include : Serifs
|
||||
set-base-anchor 'overlayOnExtension' (SB + [HSwToV : 0.5 * Stroke]) yOverlay
|
||||
set-base-anchor 'overlay' Middle (XH / 2)
|
||||
set-base-anchor 'leaningAbove' (SB + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
create-glyph "bBar.\(suffix)" : glyph-proc
|
||||
include [refer-glyph "b.\(suffix)"] AS_BASE ALSO_METRICS
|
||||
|
@ -86,8 +87,9 @@ glyph-block Letter-Latin-Lower-B : begin
|
|||
derive-multi-part-glyphs 'bDot' 0x1E03 {'b' 'dotAbove'} : lambda [srcs gr] : glyph-proc
|
||||
local { base mark } srcs
|
||||
include : refer-glyph mark
|
||||
include : Translate (Width + HalfStroke) 0
|
||||
include : Translate (Width + [HSwToV HalfStroke]) 0
|
||||
include [refer-glyph base] AS_BASE
|
||||
set-base-anchor 'leaningAbove' (Middle + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
glyph-block-import Letter-Blackboard : BBS BBD BBBarLeft
|
||||
create-glyph 'mathbb/b' 0x1D553 : glyph-proc
|
||||
|
|
|
@ -96,6 +96,7 @@ glyph-block Letter-Latin-Lower-D : begin
|
|||
if topSerif : include : topSerif df Ascender
|
||||
if bottomSerif : include : bottomSerif df Ascender
|
||||
set-base-anchor 'overlayOnExtension' (df.rightSB - [HSwToV : 0.5 * Stroke]) yOverlay
|
||||
set-base-anchor 'leaningAbove' (df.rightSB - [HSwToV HalfStroke]) Ascender
|
||||
|
||||
create-glyph "dcroat.\(suffix)" : glyph-proc
|
||||
local df : DivFrame 1
|
||||
|
@ -165,8 +166,9 @@ glyph-block Letter-Latin-Lower-D : begin
|
|||
derive-multi-part-glyphs 'dDot' 0x1E0B {'d' 'dotAbove'} : lambda [srcs gr] : glyph-proc
|
||||
local { base mark } srcs
|
||||
include : refer-glyph mark
|
||||
include : Translate (Width - HalfStroke) 0
|
||||
include : Translate (Width - [HSwToV HalfStroke]) 0
|
||||
include [refer-glyph base] AS_BASE
|
||||
set-base-anchor 'leaningAbove' (Middle - [HSwToV HalfStroke]) Ascender
|
||||
|
||||
derive-composites 'dBar' 0xA7C8 'd'
|
||||
HBar.m (SB - OX) (RightSB + OX) (XH * 0.5) OverlayStroke
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$$include '../../../meta/macros.ptl'
|
||||
|
||||
import [mix fallback SuffixCfg] from"../../../support/utils.mjs"
|
||||
import [Dotless CvDecompose MathSansSerif] from"../../../support/gr.mjs"
|
||||
import [ScheduleLeaningMark MathSansSerif] from"../../../support/gr.mjs"
|
||||
|
||||
glyph-module
|
||||
|
||||
|
@ -57,6 +57,7 @@ glyph-block Letter-Latin-Lower-H : begin
|
|||
foreach { suffix { fTailed {fHasTopSerif Serifs} } } [Object.entries HConfig] : do
|
||||
create-glyph "h.\(suffix)" : glyph-proc
|
||||
include : MarkSet.b
|
||||
set-base-anchor 'leaningAbove' (SB + [HSwToV HalfStroke]) Ascender
|
||||
include : VBar.l SB 0 Ascender
|
||||
include : nShoulder
|
||||
left -- (SB + [HSwToV Stroke])
|
||||
|
@ -65,10 +66,6 @@ glyph-block Letter-Latin-Lower-H : begin
|
|||
if fTailed : include : RightwardTailedBar RightSB 0 (XH - SmallArchDepthB)
|
||||
include : Serifs fTailed false
|
||||
|
||||
create-glyph "h/circumflexBase.\(suffix)" : glyph-proc
|
||||
include [refer-glyph "h.\(suffix)"] AS_BASE ALSO_METRICS
|
||||
set-base-anchor 'above' (SB + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
create-glyph "hBar.\(suffix)" : glyph-proc
|
||||
include [refer-glyph "h.\(suffix)"] AS_BASE ALSO_METRICS
|
||||
include : HBar.mOverlay fHasTopSerif
|
||||
|
@ -125,19 +122,9 @@ glyph-block Letter-Latin-Lower-H : begin
|
|||
|
||||
select-variant 'h' 'h'
|
||||
select-variant 'h/tailless' (shapeFrom -- 'h')
|
||||
select-variant 'h/circumflexBase' (follow -- 'h')
|
||||
link-reduced-variant 'h/descBase' 'h'
|
||||
link-reduced-variant 'h/sansSerif' 'h' MathSansSerif
|
||||
|
||||
derive-glyphs 'hCircumflex' 0x125 'h/circumflexBase' : lambda [src gr] : glyph-proc
|
||||
include [refer-glyph src] AS_BASE ALSO_METRICS
|
||||
include [refer-glyph "circumflexAbove"]
|
||||
|
||||
|
||||
derive-glyphs 'hCaron' 0x21F 'h/circumflexBase' : lambda [src gr] : glyph-proc
|
||||
include [refer-glyph src] AS_BASE ALSO_METRICS
|
||||
include [refer-glyph "caronAbove"]
|
||||
|
||||
select-variant 'hBar' 0x127 (follow -- 'h')
|
||||
turned 'turnh' 0x265 'h/tailless' Middle (XH / 2) [MarkSet.p]
|
||||
|
||||
|
@ -159,6 +146,7 @@ glyph-block Letter-Latin-Lower-H : begin
|
|||
local { base mark } srcs
|
||||
include [refer-glyph base] AS_BASE ALSO_METRICS
|
||||
include : with-transform [ApparentTranslate [HSwToV HalfStroke] (XH - Ascender)] [refer-glyph mark]
|
||||
set-base-anchor 'leaningAbove' (Middle + [HSwToV HalfStroke]) Ascender
|
||||
|
||||
derive-glyphs 'hCedilla' 0x1E29 'h' : lambda [src gr] : glyph-proc
|
||||
local shift : Width + SB - Middle + [HSwToV HalfStroke]
|
||||
|
|
|
@ -51,6 +51,7 @@ glyph-block Letter-Latin-Lower-P : begin
|
|||
include : Serifs XH
|
||||
set-base-anchor 'overlayOnExtension' (SB + [HSwToV : 0.5 * Stroke]) yOverlay
|
||||
set-base-anchor 'strike' Middle (XH / 2)
|
||||
set-base-anchor 'leaningBelow' (SB + [HSwToV HalfStroke]) Descender
|
||||
|
||||
create-glyph "thorn.\(suffix)" : glyph-proc
|
||||
include : MarkSet.bp
|
||||
|
|
|
@ -77,6 +77,7 @@ glyph-block Letter-Latin-Lower-Q : begin
|
|||
include : Body terminal XH Descender
|
||||
if sRT : include : sRT XH
|
||||
if sRB : include : sRB Descender
|
||||
set-base-anchor 'leaningBelow' (RightSB - [HSwToV HalfStroke]) Descender
|
||||
|
||||
create-glyph "QRTail.\(suffix)" : glyph-proc
|
||||
include : MarkSet.capDesc
|
||||
|
|
|
@ -72,17 +72,17 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
[Just rNarrowSerifed] : mix df.width rHookX df.div
|
||||
[Just rNarrow] : xArchMiddle + 0.1
|
||||
__ rHookX
|
||||
local [setMarks doTopSerif] : glyph-proc
|
||||
set-base-anchor 'above' [mix [mix df.leftSB (xBar - [HSwToV Stroke]) : if doTopSerif 0.5 1] df.rightSB 0.5] XH
|
||||
set-base-anchor 'overlay' (xBar - Stroke * 0.25) (XH * 0.5)
|
||||
set-base-anchor 'palatalHookAttach' xBar 0
|
||||
set-base-anchor 'palatalHookPos' (xBar + [PalatalHook.adviceGap Stroke]) 0
|
||||
local [setMarks doTopSerif top bottom] : glyph-proc
|
||||
set-base-anchor 'above' [mix [mix df.leftSB (xBar - [HSwToV Stroke]) : if doTopSerif 0.5 1] df.rightSB 0.5] top
|
||||
set-base-anchor 'leaningBelow' (xBar - [HSwToV HalfStroke]) bottom
|
||||
set-base-anchor 'overlay' (xBar - Stroke * 0.25) [mix bottom top 0.5]
|
||||
set-base-anchor 'palatalHookAttach' xBar bottom
|
||||
set-base-anchor 'palatalHookPos' (xBar + [PalatalHook.adviceGap Stroke]) top
|
||||
|
||||
return : object xBar rBottomSerif rTopSerif fine xArchMiddle skew rHookX rHookXN rHookY hookSuperness setMarks
|
||||
|
||||
define [StandardShape df md doTopSerif doBottomSerif] : glyph-proc
|
||||
define [object xBar rBottomSerif rTopSerif fine xArchMiddle skew rHookX rHookY hookSuperness setMarks] : RDim df md
|
||||
include : setMarks doTopSerif
|
||||
define [object xBar rBottomSerif rTopSerif fine xArchMiddle skew rHookX rHookY hookSuperness] : RDim df md
|
||||
include : dispiro
|
||||
widths.lhs
|
||||
g4.up.start rHookX (XH - rHookY - Stroke * 0.5) [heading Upward]
|
||||
|
@ -97,8 +97,7 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
define [CompactShape df md ts bs] : CompactShapeImpl df md false ts bs
|
||||
define [CornerHookShape df md ts bs] : CompactShapeImpl df md true ts bs
|
||||
define [CompactShapeImpl df md doHookSerif doTopSerif doBottomSerif] : glyph-proc
|
||||
define [object xBar rBottomSerif rTopSerif fine xArchMiddle rHookXN setMarks] : RDim df md
|
||||
include : setMarks doTopSerif
|
||||
define [object xBar rBottomSerif rTopSerif fine xArchMiddle rHookXN] : RDim df md
|
||||
define xCor : if doHookSerif 0 : CorrectionOMidS * [linreg 72 0.75 108 1 Stroke]
|
||||
|
||||
define arcTopShift : match md
|
||||
|
@ -126,8 +125,7 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
if doTopSerif : include : rTopSerif XH
|
||||
|
||||
define [EarlessCornerShape df md doTopSerif doBottomSerif] : glyph-proc
|
||||
define [object xBar xArchMiddle rHookX rHookY hookSuperness rBottomSerif setMarks] : RDim df md
|
||||
include : setMarks doTopSerif
|
||||
define [object xBar xArchMiddle rHookX rHookY hookSuperness rBottomSerif] : RDim df md
|
||||
include : dispiro
|
||||
widths.lhs
|
||||
g4.up.start rHookX (XH - rHookY - Stroke * 0.5) [heading Upward]
|
||||
|
@ -138,8 +136,7 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
if doBottomSerif : include : rBottomSerif 0
|
||||
|
||||
define [EarlessRoundedShape df md doTopSerif doBottomSerif] : glyph-proc
|
||||
define [object xBar xArchMiddle rHookX rHookY hookSuperness rBottomSerif setMarks] : RDim df md
|
||||
include : setMarks doTopSerif
|
||||
define [object xBar xArchMiddle rHookX rHookY hookSuperness rBottomSerif] : RDim df md
|
||||
local hx : Math.max rHookX (xBar + 1.25 * Stroke)
|
||||
include : dispiro
|
||||
widths.lhs
|
||||
|
@ -150,9 +147,8 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
if doBottomSerif : include : rBottomSerif 0
|
||||
|
||||
define [FlapHooklessShape df md doTopSerif doBottomSerif] : glyph-proc
|
||||
define [object xBar rBottomSerif xArchMiddle setMarks] : RDim df md
|
||||
define [object xBar rBottomSerif xArchMiddle] : RDim df md
|
||||
set-base-anchor 'overlay' (xBar - [HSwToV : 0.5 * Stroke]) (XH / 2)
|
||||
include : setMarks doTopSerif
|
||||
include : dispiro
|
||||
widths.lhs
|
||||
g4.left.start (xArchMiddle - CorrectionOMidS * [linreg 72 0.75 108 1 Stroke]) (XH - O)
|
||||
|
@ -184,12 +180,20 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
create-glyph "r.\(suffix)" : glyph-proc
|
||||
set-width df.width
|
||||
include : df.markSet.e
|
||||
|
||||
define [object setMarks] : RDim df mode
|
||||
include : setMarks doTS XH 0
|
||||
|
||||
include : F df mode doTS doBS
|
||||
currentGlyph.copyBaseAnchorIfAbsent 'leaningBelow' 'below'
|
||||
|
||||
create-glyph "rLongLeg.\(suffix)" : glyph-proc
|
||||
set-width df.width
|
||||
include : df.markSet.p
|
||||
define [object xBar rBottomSerif] : RDim df mode
|
||||
|
||||
define [object xBar rBottomSerif setMarks] : RDim df mode
|
||||
include : setMarks doTS XH Descender
|
||||
|
||||
include : F df mode doTS 0
|
||||
eject-contour 'serifLB'
|
||||
include : VBar.r xBar Descender 0
|
||||
|
@ -230,11 +234,10 @@ glyph-block Letter-Latin-Lower-R : begin
|
|||
include : RetroflexHook.rExt xBar 0
|
||||
|
||||
create-glyph "rTurnRTail.\(suffix)" : glyph-proc
|
||||
set-width df.width
|
||||
include : df.markSet.e
|
||||
include : F df mode 0 doBS
|
||||
include [refer-glyph "r.\(suffix)"] AS_BASE ALSO_METRICS
|
||||
eject-contour 'serifLT'
|
||||
include : FlipAround df.middle (XH / 2)
|
||||
include : df.markSet.e
|
||||
|
||||
define [object xBar] : RDim df mode
|
||||
include : RetroflexHook.lExt (df.rightSB - xBar + df.leftSB) 0
|
||||
|
|
|
@ -67,12 +67,12 @@ glyph-block Letter-Latin-Lower-T : begin
|
|||
|
||||
local g : include : HookShapeT dispiro df sym 0 top bot Stroke
|
||||
local gEnd g.knots.(g.knots.length - 1)
|
||||
set-base-anchor 'bottomRight' gEnd.x gEnd.y
|
||||
|
||||
local xLeft : BarLeftPos df sym
|
||||
set-base-anchor 'above' (xLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'leaningAbove' (xLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'hooktopAttach' (xLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'below' [mix xLeft gEnd.x : StrokeWidthBlend 0.375 0.5] bot
|
||||
set-base-anchor 'bottomRight' gEnd.x gEnd.y
|
||||
set-base-anchor 'overlay' (g.knots.0.x + [HSwToV : 0.625 * Stroke]) (XH * 0.58)
|
||||
|
||||
export : define [Retroflex df sym top bot] : Flat.Retroflex df sym top bot
|
||||
|
@ -96,9 +96,9 @@ glyph-block Letter-Latin-Lower-T : begin
|
|||
|
||||
local gEnd g.rhsKnots.(g.rhsKnots.length - 1)
|
||||
|
||||
set-base-anchor 'bottomRight' gEnd.x gEnd.y
|
||||
set-base-anchor 'above' ([BarLeftPos df sym] + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'leaningAbove' ([BarLeftPos df sym] + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'hooktopAttach' ([BarLeftPos df sym] + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'bottomRight' gEnd.x gEnd.y
|
||||
set-base-anchor 'overlay' (g.knots.0.x + [HSwToV : 0.125 * Stroke]) (XH * 0.58)
|
||||
|
||||
export : define [Retroflex df sym top bot] : Flat.Retroflex df sym top bot
|
||||
|
@ -147,7 +147,7 @@ glyph-block Letter-Latin-Lower-T : begin
|
|||
flat xBarLeft [if (shape === RETROFLEX) (bot + Hook + HalfStroke) hd.y]
|
||||
curl xBarLeft top [heading Upward]
|
||||
|
||||
set-base-anchor 'above' (xBarLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'leaningAbove' (xBarLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'hooktopAttach' (xBarLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'topRight' xCrossRight Ascender
|
||||
set-base-anchor 'overlay' (xBarLeft + [HSwToV : 0.625 * Stroke]) (XH * 0.58)
|
||||
|
@ -172,7 +172,8 @@ glyph-block Letter-Latin-Lower-T : begin
|
|||
include : HCrossBar.top xcl xcr yCrossBar
|
||||
set-base-anchor 'overlay' (xLeft + [HSwToV HalfStroke]) (XH * 0.58)
|
||||
set-base-anchor 'hooktopAttach' (xLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'below' (xLeft + [HSwToV HalfStroke]) bot
|
||||
set-base-anchor 'leaningAbove' (xLeft + [HSwToV HalfStroke]) top
|
||||
set-base-anchor 'leaningBelow' (xLeft + [HSwToV HalfStroke]) bot
|
||||
set-base-anchor 'bottomRight' xEnd (bot + Stroke)
|
||||
set-base-anchor 'lTailHookAttach' xEnd (bot + Stroke)
|
||||
|
||||
|
@ -202,6 +203,8 @@ glyph-block Letter-Latin-Lower-T : begin
|
|||
set-width df.width
|
||||
include : df.markSet.b
|
||||
include : Style.Body df sym top 0
|
||||
currentGlyph.copyBaseAnchorIfAbsent 'leaningAbove' 'above'
|
||||
currentGlyph.copyBaseAnchorIfAbsent 'leaningBelow' 'below'
|
||||
|
||||
create-glyph "t/phoneticLeft2.\(suffix)" : glyph-proc
|
||||
set-width df.width
|
||||
|
|
|
@ -27,6 +27,7 @@ glyph-block Letter-Latin-Upper-F : begin
|
|||
define xFBarRight : Width - SB * 1.5
|
||||
|
||||
define [FShape] : with-params [top pyBar serifLT serifLB serifV [stroke : AdviceStroke2 2 3 top]] : glyph-proc
|
||||
set-base-anchor 'leaningBelow' (xFBarLeft + [HSwToV : 0.5 * stroke]) 0
|
||||
include : VBar.l (xFBarLeft) 0 top stroke
|
||||
include : HBar.t (xFBarLeft - O) RightSB top stroke
|
||||
include : tagged 'crossBar'
|
||||
|
|
|
@ -16,6 +16,7 @@ glyph-block Letter-Latin-Upper-L : begin
|
|||
define [LBarLeftX df] : df.leftSB * 1.5
|
||||
define [LRightX df] : df.rightSB - 0.75 * OX
|
||||
define [LShape df top sgr swv] : glyph-proc
|
||||
set-base-anchor 'leaningAbove' ([LBarLeftX df] + [HSwToV : 0.5 * swv]) top
|
||||
include : VBar.l [LBarLeftX df] 0 top swv
|
||||
include : HBar.b ([LBarLeftX df] - O) [LRightX df] 0
|
||||
if (sgr > 1) : begin
|
||||
|
|
|
@ -71,7 +71,7 @@ glyph-block Letter-Latin-Upper-P : begin
|
|||
include : spiro-outline
|
||||
PShapeOutlineKnots top mul bp overshoot sw offset
|
||||
|
||||
define [PShape] : with-params [top [mul PShape.defaultMul] [bp PShape.BarPos] [overshoot PShape.defaultOvershoot] [sw Stroke] [slab null] [withBar true]] : glyph-proc
|
||||
define [PShape] : with-params [top [mul PShape.defaultMul] [bp PShape.BarPos] [overshoot PShape.defaultOvershoot] [sw Stroke] [slab null] [withBar true] [setMark false]] : glyph-proc
|
||||
include : dispiro [widths.rhs sw] [PShapeOutlineKnots top mul bp overshoot sw 0]
|
||||
if withBar : include : tagged 'strokeL' : VBar.l (SB * mul) 0 top sw
|
||||
if slab : include : slab top sw mul
|
||||
|
@ -141,6 +141,7 @@ glyph-block Letter-Latin-Upper-P : begin
|
|||
|
||||
create-glyph "P.\(suffix)" : glyph-proc
|
||||
include : MarkSet.capital
|
||||
set-base-anchor 'leaningBelow' (SB * PShape.defaultMul + [HSwToV HalfStroke]) 0
|
||||
include : difference
|
||||
PShape CAP (slab -- slabs)
|
||||
if fGap [PShape.OpenGap (top -- CAP) (bot -- [if fSlabBot Stroke 0])] [glyph-proc]
|
||||
|
@ -151,6 +152,7 @@ glyph-block Letter-Latin-Upper-P : begin
|
|||
|
||||
create-glyph "smcpP.\(suffix)" : glyph-proc
|
||||
include : MarkSet.e
|
||||
set-base-anchor 'leaningBelow' (SB * PShape.defaultMul + [HSwToV HalfStroke]) 0
|
||||
include : difference
|
||||
PShape XH (slab -- slabs)
|
||||
if fGap [PShape.OpenGap (top -- XH) (bot -- [if fSlabBot Stroke 0])] [glyph-proc]
|
||||
|
|
|
@ -4,7 +4,7 @@ import [Arcs Quadify ShapeConv] from "typo-geom"
|
|||
import [OffsetCurve BezToContoursSink GEOMETRY_PRECISION] from"../../support/geometry/curve-util.mjs"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [ScheduleLeaningMark] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
import [Point] from"../../support/geometry/point.mjs"
|
||||
|
||||
|
@ -30,16 +30,17 @@ glyph-block Mark-Above : begin
|
|||
define commaAboveRadius : 0.85 * DotRadius * markHalfStroke / HalfStroke
|
||||
|
||||
define StdAnchors : namespace
|
||||
export : define [impl mk padding k] : glyph-proc
|
||||
export : define [impl mk padding k fLeaning] : glyph-proc
|
||||
if (mk === 'above')
|
||||
: then : set-mark-anchor mk markMiddle (XH - padding * AccentHeight) markMiddle (aboveMarkStack + padding * AccentHeight)
|
||||
: else : set-mark-anchor mk markMiddle (XH - padding * AccentHeight)
|
||||
set-base-anchor 'aboveBraceL' (markMiddle - k * markExtend) aboveMarkMid
|
||||
set-base-anchor 'aboveBraceR' (markMiddle + k * markExtend) aboveMarkMid
|
||||
if fLeaning : ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
export : define [narrow] : impl 'above' 0 0
|
||||
export : define [mediumNarrow] : impl 'above' 0 0.25
|
||||
export : define [medium] : impl 'above' 0 0.5
|
||||
export : define [narrow] : impl 'above' 0 0 true
|
||||
export : define [mediumNarrow] : impl 'above' 0 0.25 true
|
||||
export : define [medium] : impl 'above' 0 0.5 true
|
||||
export : define [mediumWide] : impl 'above' 0 0.75
|
||||
export : define [wide] : impl 'above' 0 1
|
||||
export : define [extraWide] : impl 'above' 0 1.5
|
||||
|
@ -50,6 +51,7 @@ glyph-block Mark-Above : begin
|
|||
set-width 0
|
||||
include : StdAnchors.narrow
|
||||
include : DrawAt markMiddle aboveMarkMid (DotRadius * kdr)
|
||||
ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
create-glyph "dieresisAbove.\(suffix)" : glyph-proc
|
||||
set-width 0
|
||||
|
@ -195,7 +197,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'circumflexAbove' 0x302 : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaretShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
@ -206,7 +208,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'bardownAbove' 0x1DC6 : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaretRightShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
@ -225,7 +227,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'upbarAbove' 0x1DC7 : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaretLeftShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
@ -258,7 +260,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'caronAbove' 0x30c : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaronShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
@ -269,7 +271,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'barupAbove' 0x1DC4 : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaronRightShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
@ -288,7 +290,7 @@ glyph-block Mark-Above : begin
|
|||
|
||||
create-glyph 'downbarAbove' 0x1DC5 : glyph-proc
|
||||
set-width 0
|
||||
include : StdAnchors.wide
|
||||
include : StdAnchors.medium
|
||||
include : CaronLeftShape
|
||||
xMiddle -- markMiddle
|
||||
width -- CaretCaronWidth
|
||||
|
|
|
@ -8,9 +8,15 @@ glyph-block Mark-Adjustment : begin
|
|||
if currentGlyph.baseAnchors.below : begin
|
||||
local a : currentGlyph.gizmo.unapply currentGlyph.baseAnchors.below
|
||||
if (a.y > y) : set-base-anchor 'below' a.x y
|
||||
if currentGlyph.baseAnchors.leaningBelow : begin
|
||||
local a : currentGlyph.gizmo.unapply currentGlyph.baseAnchors.leaningBelow
|
||||
if (a.y > y) : set-base-anchor 'leaningBelow' a.x y
|
||||
|
||||
glyph-block-export ExtendAboveBaseAnchors
|
||||
define [ExtendAboveBaseAnchors y] : glyph-proc
|
||||
if currentGlyph.baseAnchors.above : begin
|
||||
local a : currentGlyph.gizmo.unapply currentGlyph.baseAnchors.above
|
||||
if (a.y < y) : set-base-anchor 'above' a.x y
|
||||
if currentGlyph.baseAnchors.leaningAbove : begin
|
||||
local a : currentGlyph.gizmo.unapply currentGlyph.baseAnchors.leaningAbove
|
||||
if (a.y < y) : set-base-anchor 'leaningAbove' a.x y
|
||||
|
|
|
@ -3,7 +3,7 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [ScheduleLeaningMark] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
glyph-module
|
||||
|
@ -22,14 +22,15 @@ glyph-block Mark-Below : begin
|
|||
define belowMarkStack (0 - AccentStackOffset)
|
||||
|
||||
define StdAnchors : namespace
|
||||
export : define [impl padding k] : glyph-proc
|
||||
export : define [impl padding k fLeaning] : glyph-proc
|
||||
set-mark-anchor 'below' markMiddle (0 + padding * AccentHeight) markMiddle (belowMarkStack - padding * AccentHeight)
|
||||
set-base-anchor 'belowBraceL' (markMiddle - k * markExtend) belowMarkMid
|
||||
set-base-anchor 'belowBraceR' (markMiddle + k * markExtend) belowMarkMid
|
||||
if fLeaning : ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
export : define [narrow] : impl 0 0
|
||||
export : define [mediumNarrow] : impl 0 0.25
|
||||
export : define [medium] : impl 0 0.5
|
||||
export : define [narrow] : impl 0 0 true
|
||||
export : define [mediumNarrow] : impl 0 0.25 true
|
||||
export : define [medium] : impl 0 0.5 true
|
||||
export : define [mediumWide] : impl 0 0.75
|
||||
export : define [wide] : impl 0 1
|
||||
|
||||
|
@ -174,6 +175,7 @@ glyph-block Mark-Below : begin
|
|||
mirrorAnchor aboveGlyph currentGlyph 'above' 'below'
|
||||
mirrorAnchor aboveGlyph currentGlyph 'aboveBraceL' 'belowBraceR'
|
||||
mirrorAnchor aboveGlyph currentGlyph 'aboveBraceR' 'belowBraceL'
|
||||
if [ScheduleLeaningMark.get aboveGlyph] : ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
TurnAboveMarkToBelow 'graveBelow' 0x316 'graveAbove'
|
||||
TurnAboveMarkToBelow 'acuteBelow' 0x317 'acuteAbove'
|
||||
|
|
|
@ -3,7 +3,6 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
glyph-module
|
||||
|
|
|
@ -3,7 +3,6 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
glyph-module
|
||||
|
|
|
@ -3,7 +3,6 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
glyph-module
|
||||
|
|
|
@ -3,7 +3,6 @@ $$include '../../meta/macros.ptl'
|
|||
import [Arcs Quadify ShapeConv] from "typo-geom"
|
||||
import [mix linreg clamp fallback] from"../../support/utils.mjs"
|
||||
import [DesignParameters] from"../../meta/aesthetics.mjs"
|
||||
import [TieMark TieGlyph] from"../../support/gr.mjs"
|
||||
import [Box] from"../../support/geometry/box.mjs"
|
||||
|
||||
glyph-module
|
||||
|
|
|
@ -300,6 +300,7 @@ class CMarkSet
|
|||
set this.markAnchors markAnchors
|
||||
set this.baseAnchors baseAnchors
|
||||
public [applyToGlyph g] : begin
|
||||
g.clearAnchors
|
||||
g.copyAnchors this
|
||||
|
||||
export : define [compositeBaseAnchors] : begin
|
||||
|
|
|
@ -4,8 +4,8 @@ extern Map
|
|||
extern Set
|
||||
|
||||
define MarkClasses {
|
||||
'above' 'tieAbove' 'topLeft' 'topRight' 'grekUpperTonos' 'aboveBraceL' 'aboveBraceR'
|
||||
'below' 'tieBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf' 'belowBraceL' 'belowBraceR'
|
||||
'above' 'tieAbove' 'leaningAbove' 'topLeft' 'topRight' 'grekUpperTonos' 'aboveBraceL' 'aboveBraceR'
|
||||
'below' 'tieBelow' 'leaningBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf' 'belowBraceL' 'belowBraceR'
|
||||
|
||||
'overlay' 'slash' 'strike'
|
||||
'cvDecompose' 'enclosureInner' 'enclosureInnerFirstHalf' 'enclosureInnerSecondHalf'
|
||||
|
@ -13,10 +13,10 @@ define MarkClasses {
|
|||
}
|
||||
|
||||
define MarkInteractions : new Map : list
|
||||
list 'aboveBraceL' {'aboveBraceL' 'above' 'tieAbove' 'topLeft' 'topRight' 'grekUpperTonos'}
|
||||
list 'aboveBraceR' {'aboveBraceR' 'above' 'tieAbove' 'topLeft' 'topRight' 'grekUpperTonos'}
|
||||
list 'belowBraceL' {'belowBraceL' 'below' 'tieBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf'}
|
||||
list 'belowBraceR' {'belowBraceR' 'below' 'tieBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf'}
|
||||
list 'aboveBraceL' {'aboveBraceL' 'above' 'tieAbove' 'leaningAbove' 'topLeft' 'topRight' 'grekUpperTonos'}
|
||||
list 'aboveBraceR' {'aboveBraceR' 'above' 'tieAbove' 'leaningAbove' 'topLeft' 'topRight' 'grekUpperTonos'}
|
||||
list 'belowBraceL' {'belowBraceL' 'below' 'tieBelow' 'leaningBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf'}
|
||||
list 'belowBraceR' {'belowBraceR' 'below' 'tieBelow' 'leaningBelow' 'bottomLeft' 'bottomRight' 'trailing' 'lf'}
|
||||
|
||||
|
||||
define MkmkStackingLimit : new Set { 'above' 'below' }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$$include '../meta/macros.ptl'
|
||||
|
||||
import [AddCommonFeature AddFeature AddLookup AddFeatureLookup ChainRuleBuilder BeginLookupBlock EndLookupBlock UkMapToLookup UkMap2ToLookup] from"./table-util.mjs"
|
||||
import [AnyCv Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript] from"../support/gr.mjs"
|
||||
import [Dotless TieMark TieGlyph OgonekTrY IsSuperscript IsSubscript LeaningMark LeaningMarkSpacer] from"../support/gr.mjs"
|
||||
import as UnicodeKnowledge from"../meta/unicode-knowledge.mjs"
|
||||
|
||||
extern Set
|
||||
|
@ -40,24 +40,18 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
define groupLF {}
|
||||
define dotlessFrom {}
|
||||
define dotlessTo {}
|
||||
define TieMarkFrom {}
|
||||
define TieMarkTo {}
|
||||
define TieGlyphs {}
|
||||
|
||||
foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== "."): begin
|
||||
if g.baseAnchors.lf : groupLF.push gid
|
||||
if g.baseAnchors.grekUpperTonos : groupGrekUpperTonos.push gid
|
||||
foreach { gn g } [glyphStore.namedEntries] : if (gn.(0) !== "."): begin
|
||||
if g.baseAnchors.lf : groupLF.push gn
|
||||
if g.baseAnchors.grekUpperTonos : groupGrekUpperTonos.push gn
|
||||
if [Dotless.get g] : begin
|
||||
dotlessFrom.push gid
|
||||
dotlessFrom.push gn
|
||||
dotlessTo.push [Dotless.get g]
|
||||
if [TieGlyph.get g] : TieGlyphs.push gid
|
||||
if [TieMark.get g] : begin
|
||||
TieMarkFrom.push gid
|
||||
TieMarkTo.push [TieMark.get g]
|
||||
|
||||
define [IotaLF] : UkMapToLookup UnicodeKnowledge.iotaBelowToLfTf
|
||||
define [GrekUpperTonosTf] : UkMapToLookup UnicodeKnowledge.upperGrekMarkToTonosTf
|
||||
|
||||
# Dotless transform
|
||||
export-lookup : AddLookup sink : object
|
||||
.type 'gsub_chaining'
|
||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'above']
|
||||
|
@ -65,7 +59,7 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
chain-rule (dotlessFrom ~> dotlessTo) (aboveMark ~> null)
|
||||
chain-rule groupGrekUpperTonos [GrekUpperTonosTf]
|
||||
|
||||
# Iota transform (max 6 middle marks are supported)
|
||||
# Iota transform
|
||||
export-lookup : AddLookup sink : object
|
||||
.type 'gsub_chaining'
|
||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs 'below']
|
||||
|
@ -84,7 +78,17 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
'brackAbove' { 'leftBrackAbove' 'rightBrackAbove' }
|
||||
'parenBelow' { 'leftParenBelow' 'rightParenBelow' }
|
||||
|
||||
# Tie marks
|
||||
Ccmp-Group "Tie Mark Transform" : begin
|
||||
define TieMarkFrom {}
|
||||
define TieMarkTo {}
|
||||
define TieGlyphs {}
|
||||
|
||||
foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== ".") : begin
|
||||
if [TieGlyph.get g] : TieGlyphs.push gid
|
||||
if [TieMark.get g] : begin
|
||||
TieMarkFrom.push gid
|
||||
TieMarkTo.push [TieMark.get g]
|
||||
|
||||
define lookupTieMarkLigature : AddLookup sink : object
|
||||
.type 'gsub_ligature'
|
||||
.substitutions : {}.concat
|
||||
|
@ -99,13 +103,47 @@ export : define [buildCCMP sink glyphStore markGlyphs] : begin
|
|||
inputEnds 3
|
||||
apply {{.at 1 .lookup lookupTieMarkLigature}}
|
||||
|
||||
Ccmp-Group "Leaning Mark Trasnform" : begin
|
||||
define LeaningAnchorMap : list
|
||||
list 'above' 'leaningAbove'
|
||||
list 'below' 'leaningBelow'
|
||||
|
||||
foreach { mkCenter mkLeaning } [items-of LeaningAnchorMap] : begin
|
||||
local basesToConsider {}
|
||||
local markFrom {}
|
||||
local markTo {}
|
||||
local markSpacer {}
|
||||
local splitMapping {}
|
||||
|
||||
foreach { gn g } [glyphStore.namedEntries] : if (gn.(0) !== ".") : begin
|
||||
if (![markGlyphs.all.has gn] && g.baseAnchors.(mkLeaning)) : basesToConsider.push gn
|
||||
if (g.markAnchors.(mkCenter) && [LeaningMark.get g] && [LeaningMarkSpacer.get g]) : begin
|
||||
markFrom.push gn
|
||||
markTo.push [LeaningMark.get g]
|
||||
markSpacer.push [LeaningMarkSpacer.get g]
|
||||
splitMapping.push { gn {[LeaningMarkSpacer.get g] [LeaningMark.get g]} }
|
||||
|
||||
define lookupTurnMarkIntoLeaningAndSpacer : AddLookup sink : object
|
||||
.type 'gsub_multiple'
|
||||
.substitutions : Object.fromEntries splitMapping
|
||||
|
||||
export-lookup : AddLookup sink : object
|
||||
.type 'gsub_chaining'
|
||||
.ignoreGlyphs [filterMarkByClassNegated markGlyphs mkCenter]
|
||||
.rules : list
|
||||
object
|
||||
.match { [basesToConsider.concat markSpacer] markFrom }
|
||||
.inputBegins 1
|
||||
.inputEnds 2
|
||||
.apply {{.at 1 .lookup lookupTurnMarkIntoLeaningAndSpacer}}
|
||||
|
||||
Ccmp-Group "Rhotic Hook Transform" : begin
|
||||
define superscripts {}
|
||||
define subscripts {}
|
||||
|
||||
foreach { gid g } [glyphStore.namedEntries] : if (gid.(0) !== "."): begin
|
||||
if [IsSuperscript.get g] : superscripts.push gid
|
||||
if [IsSubscript.get g] : subscripts.push gid
|
||||
foreach { gn g } [glyphStore.namedEntries] : if (gn.(0) !== ".") : begin
|
||||
if [IsSuperscript.get g] : superscripts.push gn
|
||||
if [IsSubscript.get g] : subscripts.push gn
|
||||
|
||||
export-lookup : AddLookup sink : object
|
||||
.type 'gsub_chaining'
|
||||
|
|
|
@ -14,8 +14,14 @@ export class GlyphStore {
|
|||
namedEntries() {
|
||||
return this.nameForward.entries();
|
||||
}
|
||||
encodedEntries() {
|
||||
return this.encodingForward.entries();
|
||||
glyphNames() {
|
||||
return this.nameForward.keys();
|
||||
}
|
||||
*encodedEntries() {
|
||||
for (const [u, g] of this.encodingForward.entries()) {
|
||||
const name = this.nameBackward.get(g);
|
||||
if (name) yield [u, name, g];
|
||||
}
|
||||
}
|
||||
*flattenCodes(g, flatteners) {
|
||||
{
|
||||
|
|
|
@ -23,6 +23,10 @@ export class Glyph {
|
|||
this.ctxTag = null;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `<Glyph ${this._m_identifier}>`;
|
||||
}
|
||||
|
||||
get identifier() {
|
||||
return this._m_identifier;
|
||||
}
|
||||
|
@ -182,6 +186,11 @@ export class Glyph {
|
|||
this.baseAnchors[id] = new Anchor(mbx, mby).transform(this.gizmo);
|
||||
}
|
||||
}
|
||||
copyBaseAnchorIfAbsent(to, from) {
|
||||
if (this.baseAnchors[from] && !this.baseAnchors[to]) {
|
||||
this.baseAnchors[to] = new Anchor(this.baseAnchors[from].x, this.baseAnchors[from].y);
|
||||
}
|
||||
}
|
||||
clearAnchors() {
|
||||
this.baseAnchors = {};
|
||||
this.markAnchors = {};
|
||||
|
|
|
@ -20,6 +20,9 @@ export const LowerYDotAtBelow = LinkedGlyphProp("LowerYDotAtBelow");
|
|||
export const DependentSelector = LinkedGlyphProp("DependentSelector");
|
||||
export const MathSansSerif = LinkedGlyphProp("MathSansSerif");
|
||||
export const VS01 = LinkedGlyphProp("VS01");
|
||||
export const TieMark = LinkedGlyphProp("TieMark");
|
||||
export const LeaningMark = LinkedGlyphProp("LeaningMark");
|
||||
export const LeaningMarkSpacer = LinkedGlyphProp("LeaningMarkSpacer");
|
||||
function LinkedGlyphProp(key) {
|
||||
return {
|
||||
get(glyph) {
|
||||
|
@ -30,6 +33,12 @@ function LinkedGlyphProp(key) {
|
|||
if (typeof toGid !== "string") throw new Error("Must supply a GID instead of a glyph");
|
||||
if (!glyph.related) glyph.related = {};
|
||||
glyph.related[key] = toGid;
|
||||
},
|
||||
amendName(name) {
|
||||
return `${key}{${name}}`;
|
||||
},
|
||||
amendOtName(name) {
|
||||
return `${name}.${key}`;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -61,25 +70,6 @@ function DecompositionProp(key) {
|
|||
};
|
||||
}
|
||||
|
||||
export const TieMark = {
|
||||
tag: "TMRK",
|
||||
get(glyph) {
|
||||
if (glyph && glyph.related) return glyph.related.TieMark;
|
||||
else return null;
|
||||
},
|
||||
set(glyph, toGid) {
|
||||
if (typeof toGid !== "string") throw new Error("Must supply a GID instead of a glyph");
|
||||
if (!glyph.related) glyph.related = {};
|
||||
glyph.related.TieMark = toGid;
|
||||
},
|
||||
amendName(name) {
|
||||
return `TieMark{${name}}`;
|
||||
},
|
||||
amendOtName(name) {
|
||||
return name + ".tieMark";
|
||||
}
|
||||
};
|
||||
|
||||
export const TieGlyph = {
|
||||
get(glyph) {
|
||||
if (glyph && glyph.related) return glyph.related.TieGlyph;
|
||||
|
@ -109,6 +99,7 @@ export const NeqLigationSlashDotted = BoolProp("NeqLigationSlashDotted");
|
|||
export const OgonekTrY = BoolProp("OgonekTrY");
|
||||
export const IsSuperscript = BoolProp("IsSuperscript");
|
||||
export const IsSubscript = BoolProp("IsSubscript");
|
||||
export const ScheduleLeaningMark = BoolProp("ScheduleLeaningMark");
|
||||
|
||||
export const Joining = {
|
||||
get(glyph) {
|
||||
|
@ -242,6 +233,7 @@ export function getGrTree(gid, grSetList, fnGidToGlyph) {
|
|||
getGrTreeImpl(gid, grSetList, fnGidToGlyph, sink);
|
||||
return sink;
|
||||
}
|
||||
|
||||
function getGrTreeImpl(gid, grSetList, fnGidToGlyph, sink) {
|
||||
if (!grSetList.length) return;
|
||||
const g = fnGidToGlyph(gid);
|
||||
|
@ -463,5 +455,6 @@ export const SvInheritableRelations = [
|
|||
DependentSelector,
|
||||
Joining,
|
||||
NeqLigationSlashDotted,
|
||||
OgonekTrY
|
||||
OgonekTrY,
|
||||
ScheduleLeaningMark
|
||||
];
|
||||
|
|
|
@ -80,3 +80,39 @@ export class $NamedParameterPair$ {
|
|||
this.right = r;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export const MatchUtil = {
|
||||
never() {
|
||||
return false;
|
||||
},
|
||||
equal(x) {
|
||||
return y => y === x;
|
||||
},
|
||||
negate(f) {
|
||||
return x => !f(x);
|
||||
},
|
||||
both(a, b) {
|
||||
return x => a(x) && b(x);
|
||||
},
|
||||
either(a, b) {
|
||||
return x => a(x) || b(x);
|
||||
}
|
||||
};
|
||||
export function constant(x) {
|
||||
return () => x;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export const ArrayUtil = {
|
||||
mapIndexToItems(a, indexes) {
|
||||
let answer = [];
|
||||
for (const item of indexes) answer.push(a[item]);
|
||||
return answer;
|
||||
},
|
||||
insertSliceAt(a, i, b) {
|
||||
a.splice(i, 0, ...b);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue