Fix precomposed iota with double marks (#2229).
This commit is contained in:
parent
f80097b88d
commit
03f3423e5d
8 changed files with 79 additions and 35 deletions
|
@ -1,2 +1,4 @@
|
|||
* Fix broken `s`/`t` variants for `U+01BE`. (#2223)
|
||||
* Fix broken `s`/`t` variants for `U+01BE`. (#2223).
|
||||
* Fix precomposed iota with double marks (#2229).
|
||||
* Fix leaning mark placement on letters around i/l.
|
||||
* Fix sans-serif linking for `U+2781`..`U+2784` and `U+278B`..`U+278E`.
|
||||
|
|
|
@ -174,16 +174,16 @@ glyph-block AutoBuild-Accents : begin
|
|||
# Handle ogonek
|
||||
substParts parts ogonek.ignore {[hasBaseAnchor 'trailing']} {ogonek.matcher} {} ogonek.production
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
define [pad _s n] : begin
|
||||
local s _s
|
||||
while (s.length < n) : s = '0' + s
|
||||
|
|
|
@ -12,6 +12,7 @@ glyph-module
|
|||
glyph-block Mark-Doppelganger : if [not recursive] : begin
|
||||
glyph-block-import CommonShapes
|
||||
glyph-block-import Common-Derivatives
|
||||
glyph-block-import Mark-Adjustment : TieAnchorMap LeaningAnchorMap
|
||||
|
||||
define [DeriveMarkChange gr gn akFrom akTo] : begin
|
||||
DeriveMeshT {gn} AnyDerivingCv : function [gns] : begin
|
||||
|
@ -29,11 +30,6 @@ glyph-block Mark-Doppelganger : if [not recursive] : begin
|
|||
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
|
||||
|
@ -46,10 +42,7 @@ glyph-block Mark-Doppelganger : if [not recursive] : begin
|
|||
DeriveMarkChange TieMark gn akFrom akTo
|
||||
|
||||
|
||||
define LeaningAnchorMap : list
|
||||
list 'above' 'leaningAbove'
|
||||
list 'below' 'leaningBelow'
|
||||
|
||||
local spacerGlyphSet : new Set
|
||||
do : foreach { u gn g } [glyphStore.encodedEntries] : DeriveLeaningMark gn g
|
||||
: where : [DeriveLeaningMark gn g] : begin
|
||||
local selection null
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$$include '../../meta/macros.ptl'
|
||||
|
||||
import [mix fallback SuffixCfg] from "@iosevka/util"
|
||||
import [ScheduleLeaningMark MathSansSerif] from "@iosevka/glyph/relation"
|
||||
import [MathSansSerif] from "@iosevka/glyph/relation"
|
||||
|
||||
glyph-module
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
$$include '../meta/macros.ptl'
|
||||
|
||||
import [mix clamp fallback] from "@iosevka/util"
|
||||
import [Dotless CvDecompose RightDependentTrigger RightDependentLink DependentSelector] from "@iosevka/glyph/relation"
|
||||
import [Dotless CvDecompose] from "@iosevka/glyph/relation"
|
||||
import [RightDependentTrigger RightDependentLink DependentSelector] from "@iosevka/glyph/relation"
|
||||
import [DesignParameters] from "../meta/aesthetics.mjs"
|
||||
|
||||
glyph-module
|
||||
|
@ -9,14 +10,17 @@ glyph-module
|
|||
glyph-block Letter-Shared : begin
|
||||
glyph-block-import CommonShapes
|
||||
glyph-block-import Common-Derivatives
|
||||
glyph-block-import Mark-Adjustment : TurnMarks
|
||||
glyph-block-import Mark-Adjustment : TurnMarks LeaningAnchorMap
|
||||
|
||||
glyph-block-export CreateAccentedComposition
|
||||
define [CreateAccentedComposition dst u srcGid accentGid]
|
||||
derive-multi-part-glyphs dst u { srcGid accentGid } : function [gns gr] : glyph-proc
|
||||
local { base mark } gns
|
||||
local gMark : query-glyph mark
|
||||
|
||||
include [refer-glyph base] AS_BASE ALSO_METRICS
|
||||
include [refer-glyph mark]
|
||||
currentGlyph.includeMarkWithLeaningSupport gMark LeaningAnchorMap
|
||||
|
||||
if (!gr && accentGid === 'dotAbove') : Dotless.set currentGlyph base
|
||||
|
||||
glyph-block-export CreateOgonekComposition
|
||||
|
|
|
@ -56,6 +56,16 @@ glyph-block Mark-Adjustment : begin
|
|||
if (bLeaningAbove && currentGlyph.baseAnchors.below)
|
||||
set-base-anchor 'leaningBelow' [mix cx bLeaningAbove.x (-1)] currentGlyph.baseAnchors.below.y
|
||||
|
||||
glyph-block-export TieAnchorMap
|
||||
define TieAnchorMap : list
|
||||
list 'above' 'tieAbove'
|
||||
list 'below' 'tieBelow'
|
||||
|
||||
glyph-block-export LeaningAnchorMap
|
||||
define LeaningAnchorMap : list
|
||||
list 'above' 'leaningAbove'
|
||||
list 'below' 'leaningBelow'
|
||||
|
||||
glyph-block-export LeaningAnchor
|
||||
define LeaningAnchor : namespace
|
||||
define [SetProcImpl mkCenter mkLeaning x] : glyph-proc
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
$$include '../meta/macros.ptl'
|
||||
|
||||
import [mix linreg clamp fallback] from "@iosevka/util"
|
||||
import [ScheduleLeaningMark] from "@iosevka/glyph/relation"
|
||||
|
||||
glyph-module
|
||||
|
||||
|
@ -48,7 +49,7 @@ glyph-block Mark-Composite : begin
|
|||
|
||||
local yc : aboveMarkTop - commaAboveRadius + DotRadius * 0.3 + commaOvershoot
|
||||
|
||||
derive-glyphs 'psiliPerispomeni' null 'commaAbove' : function [src gr] : glyph-proc
|
||||
derive-glyphs 'psiliPerispomeni' 0xEF01 'commaAbove' : function [src gr] : glyph-proc
|
||||
set-width 0
|
||||
include : refer-glyph src
|
||||
local radius : Math.max (markExtend - commaAboveRadius) (commaAboveRadius * 1.25)
|
||||
|
@ -63,6 +64,7 @@ glyph-block Mark-Composite : begin
|
|||
set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkStack + markHalfStroke * 2)
|
||||
set-base-anchor 'aboveBraceL' (markMiddle - 0.5 * markExtend) (aboveMarkMid + markHalfStroke)
|
||||
set-base-anchor 'aboveBraceR' (markMiddle + 0.5 * markExtend) (aboveMarkMid + markHalfStroke)
|
||||
ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
derive-glyphs 'psiliPerispomeniGrekUpperTonos' null 'psiliPerispomeni' : function [src gr] : glyph-proc
|
||||
set-width 0
|
||||
|
@ -76,7 +78,7 @@ glyph-block Mark-Composite : begin
|
|||
set-width [query-glyph 'markBaseSpace'].advanceWidth
|
||||
include : refer-glyph src
|
||||
|
||||
derive-glyphs 'dasiaPerispomeni' null 'revCommaAbove' : function [src gr] : glyph-proc
|
||||
derive-glyphs 'dasiaPerispomeni' 0xEF02 'revCommaAbove' : function [src gr] : glyph-proc
|
||||
set-width 0
|
||||
include : refer-glyph src
|
||||
local radius : Math.max (markExtend - commaAboveRadius) (commaAboveRadius * 1.25)
|
||||
|
@ -91,6 +93,7 @@ glyph-block Mark-Composite : begin
|
|||
set-mark-anchor 'above' markMiddle XH markMiddle (aboveMarkStack + markHalfStroke * 2)
|
||||
set-base-anchor 'aboveBraceL' (markMiddle - 0.5 * markExtend) (aboveMarkMid + markHalfStroke)
|
||||
set-base-anchor 'aboveBraceR' (markMiddle + 0.5 * markExtend) (aboveMarkMid + markHalfStroke)
|
||||
ScheduleLeaningMark.set currentGlyph
|
||||
|
||||
derive-glyphs 'dasiaPerispomeniGrekUpperTonos' null 'dasiaPerispomeni' : function [src gr] : glyph-proc
|
||||
set-width 0
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as Geom from "@iosevka/geometry";
|
|||
import { Anchor } from "@iosevka/geometry/anchor";
|
||||
import { Vec2 } from "@iosevka/geometry/point";
|
||||
import { Transform } from "@iosevka/geometry/transform";
|
||||
import { ScheduleLeaningMark } from "./relation.mjs";
|
||||
|
||||
export class Glyph {
|
||||
constructor(identifier) {
|
||||
|
@ -105,14 +106,19 @@ export class Glyph {
|
|||
}
|
||||
includeGlyph(g, copyAnchors, copyWidth) {
|
||||
if (g instanceof Function) throw new Error("Unreachable");
|
||||
if (g.isMarkSet) throw new Error("Invalid component to be introduced.");
|
||||
// Combine anchors and get offset
|
||||
let shift = new Vec2(0, 0);
|
||||
this.combineMarks(g, shift);
|
||||
this.includeGlyphImpl(g, shift.x, shift.y);
|
||||
if (g.isMarkSet) throw new Error("Invalid component to be introduced.");
|
||||
if (copyAnchors) this.copyAnchors(g);
|
||||
if (copyWidth && g.advanceWidth >= 0) this.advanceWidth = g.advanceWidth;
|
||||
}
|
||||
includeMarkWithLeaningSupport(g, lm) {
|
||||
let shift = new Vec2(0, 0);
|
||||
this.combineMarks(g, shift, lm);
|
||||
this.includeGlyphImpl(g, shift.x, shift.y);
|
||||
}
|
||||
includeGlyphImpl(g, shiftX, shiftY) {
|
||||
if (g._m_identifier) {
|
||||
this.includeGeometry(new Geom.ReferenceGeometry(g, shiftX, shiftY));
|
||||
|
@ -157,26 +163,52 @@ export class Glyph {
|
|||
this.geometry = this.geometry.filterTag(t => tag !== t);
|
||||
}
|
||||
// Anchors
|
||||
combineMarks(g, shift) {
|
||||
combineMarks(g, shift, lm) {
|
||||
if (!g.markAnchors) return;
|
||||
for (const m in g.markAnchors) {
|
||||
const markThat = g.markAnchors[m];
|
||||
const baseThis = this.baseAnchors[m];
|
||||
if (!baseThis) continue;
|
||||
shift.x = baseThis.x - markThat.x;
|
||||
shift.y = baseThis.y - markThat.y;
|
||||
const fScheduledLeaning = lm && ScheduleLeaningMark.get(g);
|
||||
for (const mk in g.markAnchors) {
|
||||
// Find the base mark class and anchor
|
||||
const baseThisN = this.baseAnchors[mk];
|
||||
if (!baseThisN) continue;
|
||||
|
||||
// Find the leaning base mark class and anchor, if any
|
||||
let mkLeaning = mk;
|
||||
if (fScheduledLeaning) {
|
||||
for (const [mkT, mkLeaningT] of lm)
|
||||
if (mk === mkT && this.baseAnchors[mkLeaningT]) mkLeaning = mkLeaningT;
|
||||
}
|
||||
const baseThisL = this.baseAnchors[mkLeaning];
|
||||
if (!baseThisL) continue;
|
||||
|
||||
// Find the mark anchor in mark glyph
|
||||
const markThat = g.markAnchors[mk];
|
||||
|
||||
// Calculate the shift
|
||||
shift.x = baseThisL.x - markThat.x;
|
||||
shift.y = baseThisL.y - markThat.y;
|
||||
|
||||
// Place anchors from mark glyph to current glyph
|
||||
let fSuppress = true;
|
||||
if (g.baseAnchors) {
|
||||
for (const m2 in g.baseAnchors) {
|
||||
if (m2 === m) fSuppress = false;
|
||||
const baseDerived = g.baseAnchors[m2];
|
||||
this.baseAnchors[m2] = new Anchor(
|
||||
shift.x + baseDerived.x,
|
||||
shift.y + baseDerived.y,
|
||||
for (const mkNewMark in g.baseAnchors) {
|
||||
const baseDerived = g.baseAnchors[mkNewMark];
|
||||
this.baseAnchors[mkNewMark] = new Anchor(
|
||||
baseThisN.x - markThat.x + baseDerived.x,
|
||||
baseThisN.y - markThat.y + baseDerived.y,
|
||||
);
|
||||
if (mkNewMark === mk) {
|
||||
fSuppress = false;
|
||||
if (mkLeaning !== mk) {
|
||||
this.baseAnchors[mkLeaning] = new Anchor(
|
||||
baseThisL.x - markThat.x + baseDerived.x,
|
||||
baseThisL.y - markThat.y + baseDerived.y,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fSuppress) delete this.baseAnchors[m];
|
||||
if (fSuppress) delete this.baseAnchors[mk];
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAnchors(g) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue