Add full-serifed variants for K and k, and related letters (#2696). (#2700)

This commit is contained in:
Belleve 2025-03-02 17:48:49 -10:00 committed by GitHub
parent 345a54b091
commit 2615efb03a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 162 additions and 60 deletions

1
changes/33.1.0.md Normal file
View file

@ -0,0 +1 @@
* Add full-serifed variants for `K` and `k`, and related letters (#2696).

View file

@ -20,23 +20,54 @@ glyph-block Letter-Latin-K : begin
local [KBalanceRight slabLegs straightBar] : if slabLegs 0 : if straightBar (Width / 32) 0
local [KO slabLegs straightBar top stroke] : if straightBar (([if slabLegs (0) (-4)] * OX - stroke / 3) * (XH / top)) 0
define [KAttachment shape mode top left right stroke straightBar] : begin
if [not shape] : return [no-shape]
# The mode parameter of KLegSlabs is a bitmasked interger, with the following bits [F T B]
# F: Whether the serif is full
# B: Bottom serif type
# T: Top serif type
define [HasRtSerif mode] : maskBit mode 1
define [HasRbSerif mode] : maskBit mode 0
define flex-params [KLegSlabs] : glyph-proc
local-parameter : mode -- 0
local-parameter : straightBar -- false
local-parameter : top -- XH
local-parameter : left -- SB
local-parameter : right -- RightSB
local-parameter : stroke -- Stroke
local-parameter : attachment -- nothing
local-parameter : maskRT -- no-shape
local-parameter : maskRB -- no-shape
local Ok : KO mode true top stroke
local kshRight : right + [KBalanceRight true straightBar]
local serifLengthAdj : Ok + [HSwToV stroke]
return : shape.rSideJut
x -- (kshRight - serifLengthAdj)
local sideJutAdj : Ok + [HSwToV stroke]
local symJutExtraAdj : HSwToV (0.5 * stroke)
local slabIsFull : maskBit mode 2
if [HasRtSerif mode] : include : tagged 'serifRT' : if slabIsFull
then : union
HSerif.rt (kshRight - sideJutAdj) top (SideJut + sideJutAdj)
HSerif.lt (kshRight - sideJutAdj) top (SideJut)
else : difference
HSerif.rt (kshRight - sideJutAdj) top (SideJut + sideJutAdj)
maskRT
if [HasRbSerif mode] : include : tagged 'serifRB' : if slabIsFull
then : union
HSerif.rb (kshRight - sideJutAdj) 0 (SideJut + sideJutAdj)
HSerif.lb (kshRight - sideJutAdj) 0 (SideJut)
else : difference
HSerif.rb (kshRight - sideJutAdj) 0 (SideJut + sideJutAdj)
maskRB
if attachment : begin
include : difference
attachment.rSideJut
x -- (kshRight - sideJutAdj)
y -- 0
jut -- (Jut + serifLengthAdj)
define [KSlabs mode top left right stroke straightBar] : glyph-proc
local Ok : KO mode true top stroke
local kshRight : right + [KBalanceRight true straightBar]
local serifLengthAdj : Ok + [HSwToV stroke]
include : tagged 'serifRT' : if [maskBit mode 1] [HSerif.rt (kshRight - serifLengthAdj) top (SideJut + serifLengthAdj)] [no-shape]
include : tagged 'serifRB' : if [maskBit mode 0] [HSerif.rb (kshRight - serifLengthAdj) 0 (SideJut + serifLengthAdj)] [no-shape]
jut -- (Jut + sideJutAdj)
maskRB
define KLegs : namespace
export : define [Straight fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
@ -53,21 +84,34 @@ glyph-block Letter-Latin-K : begin
local kshRightSerifs : right + [KBalanceRight true true]
local serifLengthAdj : Ok + [HSwToV stroke]
define [TopStrokeMask offset] : Rect top 0 kshLeft [if [maskBit slabLegs 1] (kshRightSerifs + offset + SideJut - TanSlope * Stroke) (2 * Width)]
define [BottomStrokeMask offset] : Rect top 0 kshLeft [if [maskBit slabLegs 0] (kshRightSerifs + offset + SideJut + TanSlope * Stroke) (2 * Width)]
define TopMask : object
forStroke : function [offset] : begin
local xRight : if [HasRtSerif slabLegs] (kshRightSerifs + offset + SideJut - TanSlope * Stroke) VERY-FAR
return : Rect top 0 kshLeft xRight
forSerifs : function [] : intersection
TopMask.forStroke (-0.1)
HalfRectTriangle (kshRightTop - Ok - TINY) top (kshLeft + stroke - TINY) attach
define BottomMask : object
forStroke : function [offset] : begin
local xRight : if [HasRbSerif slabLegs] (kshRightSerifs + offset + SideJut + TanSlope * Stroke) VERY-FAR
return : Rect top 0 kshLeft xRight
forSerifs : function []
HalfRectTriangle (kshRightBot - Ok - TINY) 0 (kshLeft + stroke - TINY) attach2
if fHookTop
: then : begin
define kHookTopMix 0.5
if fHookTop : include : dispiro
widths.rhs stroke
straight.left.start (kshRightBot + [if [maskBit slabLegs 1] SideJut 0] - TanSlope * stroke) (top - stroke)
straight.left.start (kshRightBot + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke)
flat [mix (kshRightTop - Ok) (kshLeft + stroke) kHookTopMix] [mix top attach kHookTopMix] [widths.rhs : mix stroke fine kHookTopMix]
curl (kshLeft + stroke) attach [widths.rhs fine]
: else : begin
set-base-anchor 'armOverlay' [mix kshLeft kshRightTop : StrokeWidthBlend 0.5 0.65] [mix attach top : StrokeWidthBlend 0.5 0.7]
include : intersection
TopStrokeMask 0
TopMask.forStroke 0
dispiro
widths.rhs stroke
flat (kshRightTop - Ok) top
@ -76,7 +120,7 @@ glyph-block Letter-Latin-K : begin
set-base-anchor 'legOverlay' [mix kshLeft kshRightBot : StrokeWidthBlend 0.5 0.65] [mix attach2 0 : StrokeWidthBlend 0.5 0.7]
include : intersection
BottomStrokeMask (-0.1)
BottomMask.forStroke (-0.1)
spiro-outline
corner (kshLeft + stroke) 0
corner (kshLeft + stroke) (attach + 1)
@ -87,15 +131,16 @@ glyph-block Letter-Latin-K : begin
flat (kshRightBot - Ok) 0 [widths.lhs stroke]
curl (kshLeft + stroke) attach2 [widths.lhs fine]
include : difference
union
KSlabs slabLegs top left right stroke true
KAttachment attachment slabLegs top left right stroke true
union
HalfRectTriangle (kshRightBot - Ok - TINY) 0 (kshLeft + stroke - TINY) attach2
intersection
TopStrokeMask (-0.1)
HalfRectTriangle (kshRightTop - Ok - TINY) top (kshLeft + stroke - TINY) attach
include : KLegSlabs
mode -- slabLegs
top -- top
left -- left
right -- right
stroke -- stroke
straighrBar -- true
attachment -- attachment
maskRT -- TopMask.forSerifs
maskRB -- BottomMask.forSerifs
export : define [Symmetric leadGap hookDepth] : function [fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
local fine : AdviceStroke [if leadGap 3.5 3]
@ -110,7 +155,9 @@ glyph-block Letter-Latin-K : begin
if [not hookDepth] : set-base-anchor 'trailing' (kshRight - Ok) 0
define [StrokeMask bit t b offset] : Rect t b kshLeft [if [maskBit slabLegs bit] (kshRight + offset) (2 * Width)]
define [StrokeMask fTop t b offset] : begin
local hasSerif : if fTop [HasRtSerif slabLegs] [HasRbSerif slabLegs]
return : Rect t b kshLeft [if hasSerif (kshRight + offset) (2 * Width)]
if fHookTop
: then : begin
@ -120,7 +167,7 @@ glyph-block Letter-Latin-K : begin
Rect top (0.5 * top) kshLeft (2 * Width)
dispiro
widths.rhs stroke
straight.left.start (kshRight + [if [maskBit slabLegs 1] SideJut 0] - TanSlope * stroke) (top - stroke)
straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke)
flat [mix (kshRightHookTop - Ok) xAttach kHookTopMix] [mix top yAttach kHookTopMix] [widths.rhs : mix stroke fine kHookTopMix]
curl [mix (kshRightHookTop - Ok) xAttach 2] [mix top yAttach 2] [widths.rhs fine]
: else : begin
@ -166,18 +213,25 @@ glyph-block Letter-Latin-K : begin
corner (xAttach - 1) coYAttach
corner (xAttach - 1) 0
include : difference
union
KSlabs slabLegs top left right stroke true
KAttachment attachment slabLegs top left right stroke true
union
intersection
define [TopSerifMask] : intersection
StrokeMask 1 top (0.5 * top) (-0.1)
HalfRectTriangle (kshRight - Ok - TINY) top ([mix (kshRight - Ok) xAttach 2] - TINY) [mix top yAttach 2]
intersection
define [BotSerifMask] : intersection
StrokeMask 0 (0.5 * top) 0 (-0.1)
HalfRectTriangle (kshRight - Ok - TINY) 0 ([mix (kshRight - Ok) xAttach 2] - TINY) [mix 0 coYAttach 2]
include : KLegSlabs
mode -- slabLegs
top -- top
left -- left
right -- right
stroke -- stroke
straighrBar -- true
attachment -- attachment
maskRT -- TopSerifMask
maskRB -- BotSerifMask
export : define [Curly fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
local turn : top * 0.99
local fine : AdviceStroke 3.5
@ -201,7 +255,7 @@ glyph-block Letter-Latin-K : begin
Rect top 0 kshLeft (2 * Width)
if fHookTop
dispiro
straight.left.start (kshRight + [if [maskBit slabLegs 1] SideJut 0] - TanSlope * stroke) (top - stroke) [widths.rhs stroke]
straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke) [widths.rhs stroke]
upperCurvatureHT
g4 xAttach1 yAttach1 [widths.rhs fine]
dispiro
@ -216,7 +270,7 @@ glyph-block Letter-Latin-K : begin
g4 xAttach2 yAttach2 [widths.center fine]
if fHookTop
spiro-outline
straight.left.start (kshRight + [if [maskBit slabLegs 1] SideJut 0] - TanSlope * stroke) (top - stroke + TINY)
straight.left.start (kshRight + [if [HasRtSerif slabLegs] SideJut 0] - TanSlope * stroke) (top - stroke + TINY)
upperCurvatureHT
corner (xAttach1 - TINY) yAttach1
corner (-Width) yAttach1
@ -229,13 +283,20 @@ glyph-block Letter-Latin-K : begin
corner (kshLeft + stroke) (yAttach1 + TINY)
corner kshLeft 0
corner kshLeft top
include : difference
union
KSlabs slabLegs top left right stroke false
KAttachment attachment slabLegs top left right stroke false
union
HalfRectTriangle kshRight top xAttach1 yAttach1
HalfRectTriangle (kshRight - O - [HSwToV : 0.5 * stroke]) 0 xAttach2 yAttach2
define [TopSerifMask] : HalfRectTriangle kshRight top xAttach1 yAttach1
define [BotSerifMask] : HalfRectTriangle (kshRight - O - [HSwToV : 0.5 * stroke]) 0 xAttach2 yAttach2
include : KLegSlabs
mode -- slabLegs
top -- top
left -- left
right -- right
stroke -- stroke
straighrBar -- false
attachment -- attachment
maskRT -- TopSerifMask
maskRB -- BotSerifMask
define [CursiveDimen left right top stroke slabLT slabLegs] : begin
define kshLeft : left + [KBalance slabLegs true]
@ -297,11 +358,18 @@ glyph-block Letter-Latin-K : begin
curl (dim.kshRight - dim.Ok) 0 [widths.rhs]
CursiveLoopT spiro-outline (-O) left right stroke top slabLT slabLegs
include : difference
union
KSlabs [if slabLegs 1 0] top left right stroke true
KAttachment attachment slabLegs top left right stroke true
HalfRectTriangle (dim.kshRight - dim.Ok - TINY) 0 (dim.arcTerminalX - TINY) dim.arcTerminalY
define [BotSerifMask] : HalfRectTriangle (dim.kshRight - dim.Ok - TINY) 0 (dim.arcTerminalX - TINY) dim.arcTerminalY
include : KLegSlabs
mode -- [if slabLegs 1 0]
top -- top
left -- left
right -- right
stroke -- stroke
straighrBar -- true
attachment -- attachment
maskRT -- no-shape
maskRB -- BotSerifMask
export : define [CursiveTailed fHookTop left right stroke top slabLT slabLegs attachment] : glyph-proc
define dim : CursiveDimen left right top stroke slabLT slabLegs
@ -351,6 +419,11 @@ glyph-block Letter-Latin-K : begin
serifed : match body
[Just 'symmetricConnectedKH'] { 1 1 2 }
__ { 1 1 3 }
fullSerifedKra { 2 1 7 }
fullSerifedKappa { 2 0 7 }
fullSerifed : match body
[Just 'symmetricConnectedKH'] { 1 1 6 }
__ { 1 1 7 }
define [UpperKLTSerif top sw xBarLeft slabType] : match slabType
2 : HSerif.lt xBarLeft top SideJut
@ -488,6 +561,7 @@ glyph-block Letter-Latin-K : begin
bottomRightSerifed { 0 0 1 }
topLeftAndBottomRightSerifed { 1 0 1 }
serifed { 1 1 3 }
fullSerifed { 1 1 7 }
foreach { suffix { LegsImpl {slabLT slabLB slabLegs} } } [pairs-of LowerKConfig] : do
local straightBar : LegsImpl !== KLegs.Curly

View file

@ -13,6 +13,13 @@ export function bitOr(...xs) {
return x;
}
export function bitShl(x, y) {
return x << y;
}
export function bitShr(x, y) {
return x >>> y;
}
const pcNibbleLookup = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
export function popCountByte(x) {
return pcNibbleLookup[x & 0x0f] + pcNibbleLookup[(x >>> 4) & 0x0f];

View file

@ -1192,6 +1192,14 @@ selectorAffix.K = "serifed"
selectorAffix."K/sansSerif" = "serifless"
selectorAffix.KDescender = "serifed"
[prime.capital-k.variants-buildup.stages.serifs.full-serifed]
rank = 6
nonBreakingVariantAdditionPriority = 100
descriptionAffix = "full serifs at legs"
selectorAffix.K = "fullSerifed"
selectorAffix."K/sansSerif" = "serifless"
selectorAffix.KDescender = "fullSerifed"
[prime.capital-l]
@ -3335,6 +3343,18 @@ selectorAffix.kDescender = "serifed"
selectorAffix."grek/kappa" = "serifedKappa"
selectorAffix."grek/kappa/sansSerif" = "serifless"
[prime.k.variants-buildup.stages.serifs.full-serifed]
rank = 6
nonBreakingVariantAdditionPriority = 100
descriptionAffix = "full serifs at legs"
selectorAffix.k = "fullSerifed"
selectorAffix."k/sansSerif" = "serifless"
selectorAffix."latn/kappa" = "fullSerifedKra"
selectorAffix.kHookTop = "fullSerifed"
selectorAffix.kDescender = "fullSerifed"
selectorAffix."grek/kappa" = "fullSerifedKappa"
selectorAffix."grek/kappa/sansSerif" = "serifless"
[prime.l]