Reduce glyph count of multi digit inset enclosures (#2359)

* Reduce around 4000 glyphs by making multi-digit inset composites decomposable

* Add CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P (`U+1F18A`).

* Nit

* Further improve with stroke geometry
This commit is contained in:
Belleve 2024-05-31 20:41:05 -10:00 committed by GitHub
parent db655f4664
commit 7bc8b823e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 265 additions and 104 deletions

View file

@ -8,4 +8,5 @@
- COMBINING CYRILLIC VZMET (`U+A66F`). - COMBINING CYRILLIC VZMET (`U+A66F`).
- COMBINING CYRILLIC KAVYKA (`U+A67C`) ... CYRILLIC PAYEROK (`U+A67F`). - COMBINING CYRILLIC KAVYKA (`U+A67C`) ... CYRILLIC PAYEROK (`U+A67F`).
- MODIFIER LETTER DOT VERTICAL BAR (`U+A717`) ... MODIFIER LETTER DOT HORIZONTAL BAR (`U+A719`). - MODIFIER LETTER DOT VERTICAL BAR (`U+A717`) ... MODIFIER LETTER DOT HORIZONTAL BAR (`U+A719`).
- CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P (`U+1F18A`).
* Fix mark placement of Sideways U with Diaeresis (`U+1D1E`) when a CV/SS is applied to it (#2353). * Fix mark placement of Sideways U with Diaeresis (`U+1D1E`) when a CV/SS is applied to it (#2353).

View file

@ -16,7 +16,6 @@ define CENTERED true
define NOT-CENTERED false define NOT-CENTERED false
define ALLOW-PROPORTIONAL true define ALLOW-PROPORTIONAL true
define MONOSPACE-ONLY false define MONOSPACE-ONLY false
define StandardSpacing nothing
glyph-block Autobuild-Enclosure-Shared : begin glyph-block Autobuild-Enclosure-Shared : begin
glyph-block-import CommonShapes glyph-block-import CommonShapes
@ -130,23 +129,25 @@ glyph-block AutoBuild-Enclosure : begin
hashCv subGlyph hashCv subGlyph
return : '.ci.' + gniPrefix + '/' + [nameParts.join '/'] return : '.ci.' + gniPrefix + '/' + [nameParts.join '/']
define [EnsureInnerSubGlyphImpl gniPrefix markClass miniatureFont mp actualWidth accumulatedTfm] : function [gidPart] : begin define [EnsureInnerSubGlyphImpl inners markClass miniatureFont mp actualWidth accumulatedTfm] : function [gidPart] : begin
define subGlyph : miniatureFont.queryByNameEnsured gidPart define subGlyph : miniatureFont.queryByNameEnsured gidPart
define gniPart : GlyphNameInnerOf gniPrefix subGlyph mp actualWidth accumulatedTfm define gniPart : GlyphNameInnerOf inners.gniPrefix subGlyph mp actualWidth accumulatedTfm
if [not : query-glyph gniPart] : begin if [query-glyph gniPart] : return gniPart
enclosureInnerPartActualWidth.set gniPart (actualWidth)
create-glyph gniPart : glyph-proc enclosureInnerPartActualWidth.set gniPart (actualWidth)
set-width 0 create-glyph gniPart : glyph-proc
set-mark-anchor 'compositeInner' 0 0 set-width 0
include subGlyph set-mark-anchor 'compositeInner' 0 0
include accumulatedTfm include : inners.buildInnerShape subGlyph
if mp include accumulatedTfm
then : set-mark-anchor markClass 0 0 (actualWidth) 0
else : set-mark-anchor markClass (actualWidth / 2) 0 if mp
: then : set-mark-anchor markClass 0 0 (actualWidth) 0
: else : set-mark-anchor markClass (actualWidth / 2) 0
return gniPart return gniPart
define [EnsureInnerSubGlyphSeq gniPrefix markClass miniatureFont job dimens yCompress kExtraYShift] : begin define [EnsureInnerSubGlyphSeq inners markClass miniatureFont job dimens yCompress kExtraYShift] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define [object width mockInnerWidth dscale] dimens define [object width mockInnerWidth dscale] dimens
@ -168,15 +169,15 @@ glyph-block AutoBuild-Enclosure : begin
local finalParts {} local finalParts {}
foreach partIndex [range 0 parts.length] : do foreach partIndex [range 0 parts.length] : do
define gidPart parts.(partIndex) local gidPart parts.(partIndex)
local actualWidth : [miniatureFont.queryByNameEnsured gidPart].advanceWidth * dscale * xCompress local actualWidth : [miniatureFont.queryByNameEnsured gidPart].advanceWidth * dscale * xCompress
finalParts.push : EnsureComponentGlyphT gidPart finalParts.push : EnsureComponentGlyphT gidPart
EnsureInnerSubGlyphImpl gniPrefix markClass miniatureFont (parts.length > 1) actualWidth accumulatedTfm EnsureInnerSubGlyphImpl inners markClass miniatureFont (parts.length > 1) actualWidth accumulatedTfm
return finalParts return finalParts
define [EnclosureInnerImpl dimens finalParts] : glyph-proc define [EnclosureInnerImpl dimens finalParts] : glyph-proc
define [object width dscale mockInnerWidth] dimens define [object width] dimens
local totalInnerWidth 0 local totalInnerWidth 0
foreach [gniPart : items-of finalParts] : begin foreach [gniPart : items-of finalParts] : begin
@ -186,23 +187,30 @@ glyph-block AutoBuild-Enclosure : begin
include : with-transform [Translate x 0] : refer-glyph gniPart include : with-transform [Translate x 0] : refer-glyph gniPart
set x : x + ([enclosureInnerPartActualWidth.get gniPart] || 0) set x : x + ([enclosureInnerPartActualWidth.get gniPart] || 0)
define [EnclosureInner gniPrefix gnEnclosure miniatureFont job dimens] : begin define [EnclosureInner inners gnEnclosure miniatureFont job dimens] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define [object width mockInnerWidth dscale] dimens define [object width] dimens
local finalParts : EnsureInnerSubGlyphSeq gniPrefix 'enclosureInner' miniatureFont job dimens 1 0
if gnEnclosure : return : glyph-proc
include : EnclosureInnerImpl dimens finalParts
CvDecompose.set currentGlyph [{gnEnclosure}.concat finalParts]
: else : return : new-glyph : EnclosureInnerImpl dimens finalParts
define [TwoRowEnclosureInner gniPrefix gnEnclosure miniatureFont job dimens] : begin local finalParts : EnsureInnerSubGlyphSeq inners 'enclosureInner' miniatureFont job dimens 1 0
if gnEnclosure
: then : begin
return : glyph-proc
include : EnclosureInnerImpl dimens finalParts
CvDecompose.set currentGlyph [{gnEnclosure}.concat finalParts]
: else : begin
return : new-glyph : EnclosureInnerImpl dimens finalParts
define [TwoRowEnclosureInner inners gnEnclosure miniatureFont job dimens] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define [object width mockInnerWidth dscale] dimens define [object width] dimens
local jobFirstHalf { gn unicode [parts.slice 0 (parts.length / 2)] w bal baly } local jobFirstHalf { gn unicode [parts.slice 0 (parts.length / 2)] w bal baly }
local jobSecondHalf { gn unicode [parts.slice (parts.length / 2) ] w bal baly } local jobSecondHalf { gn unicode [parts.slice (parts.length / 2) ] w bal baly }
local finalPartsFirstHalf : EnsureInnerSubGlyphSeq gniPrefix 'enclosureInnerFirstHalf' miniatureFont jobFirstHalf dimens 0.45 (+0.55) local finalPartsFirstHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerFirstHalf" miniatureFont jobFirstHalf dimens 0.45 (+0.55)
local finalPartsSecondHalf : EnsureInnerSubGlyphSeq gniPrefix 'enclosureInnerSecondHalf' miniatureFont jobSecondHalf dimens 0.45 (+0.00) local finalPartsSecondHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerSecondHalf" miniatureFont jobSecondHalf dimens 0.45 (+0.00)
if gnEnclosure : return : glyph-proc
if gnEnclosure
: then : return : glyph-proc
include : EnclosureInnerImpl dimens finalPartsFirstHalf include : EnclosureInnerImpl dimens finalPartsFirstHalf
include : EnclosureInnerImpl dimens finalPartsSecondHalf include : EnclosureInnerImpl dimens finalPartsSecondHalf
CvDecompose.set currentGlyph [{gnEnclosure}.concat finalPartsFirstHalf finalPartsSecondHalf] CvDecompose.set currentGlyph [{gnEnclosure}.concat finalPartsFirstHalf finalPartsSecondHalf]
@ -213,7 +221,7 @@ glyph-block AutoBuild-Enclosure : begin
define [CircCrowd digits width] : 2 + 2 * [Math.pow [AdjustDigitCount digits width] (2 / 3)] * [Math.max 1 (HalfUPM / Width)] define [CircCrowd digits width] : 2 + 2 * [Math.pow [AdjustDigitCount digits width] (2 / 3)] * [Math.max 1 (HalfUPM / Width)]
define [CircScale digits width] : 0.65 / [Math.pow [AdjustDigitCount digits width] 0.5] define [CircScale digits width] : 0.65 / [Math.pow [AdjustDigitCount digits width] 0.5]
define [circleDimens digits w m] : begin define [CircleDimens digits w m] : begin
define width : fallback w Width define width : fallback w Width
define dscale : linreg HalfUPM 0.55 UPM 0.6 width define dscale : linreg HalfUPM 0.55 UPM 0.6 width
define spatt : [linreg HalfUPM 0.22 UPM 0.27 width] * (Width / HalfUPM) define spatt : [linreg HalfUPM 0.22 UPM 0.27 width] * (Width / HalfUPM)
@ -240,8 +248,9 @@ glyph-block AutoBuild-Enclosure : begin
define archDepthB : ArchDepthBOf (SmallArchDepth * (right - left) / (RightSB - SB)) width define archDepthB : ArchDepthBOf (SmallArchDepth * (right - left) / (RightSB - SB)) width
return : object width mockInnerWidth dscale sw0 sw top bot left right mosaicTop mosaicBot mosaicLeft mosaicRight archDepthA archDepthB return : object width mockInnerWidth dscale sw0 sw top bot left right mosaicTop mosaicBot mosaicLeft mosaicRight archDepthA archDepthB
define StandardSpacing : object define StandardInners : object
gniPrefix '' gniPrefix ''
buildInnerShape : function [subGlyph] : return subGlyph
getPara : function [pp digits rows width] : MiniatureParaT pp getPara : function [pp digits rows width] : MiniatureParaT pp
crowd -- [CircCrowd (digits / rows) width] crowd -- [CircCrowd (digits / rows) width]
scale -- [CircScale (digits / rows) width] scale -- [CircScale (digits / rows) width]
@ -249,62 +258,94 @@ glyph-block AutoBuild-Enclosure : begin
mono -- (digits > 1) mono -- (digits > 1)
mono2 -- (digits > 1) mono2 -- (digits > 1)
define ItalicSpacing : object define DecomposableInsetInners : object
gniPrefix 'd'
buildInnerShape : function [subGlyph] : difference
Rect (1.05 * CAP - O) (-0.05 * CAP + O) O (Width - O)
begin subGlyph
getPara : function [pp digits rows width] : MiniatureParaT pp
crowd -- [CircCrowd (digits / rows) width]
scale -- [CircScale (digits / rows) width]
sbscale -- 1
mono -- true
mono2 -- true
define ItalicInners : object
gniPrefix 'i' gniPrefix 'i'
buildInnerShape : function [subGlyph] : return subGlyph
getPara : function[pp digits rows width] : begin getPara : function[pp digits rows width] : begin
define pp1 : pp.createFork : function [a] : begin define pp1 : pp.createFork : function [a] : begin
set a.shape.slope 'italic' set a.shape.slope 'italic'
set a.shape.slopeAngle : mix (para.slopeAngle || 0) 15 (95 / 150) set a.shape.slopeAngle : mix (para.slopeAngle || 0) 15 (95 / 150)
return : StandardSpacing.getPara pp1 digits rows width return : StandardInners.getPara pp1 digits rows width
define [EnclosureT prefix builder spacing digits rows demands fnEnclosure] : begin define [EnclosureT prefix builder inners digits rows demands fnEnclosure] : begin
foreach {suffix ww gap} [items-of circleWidthClasses] : do foreach {suffix ww gap} [items-of circleWidthClasses] : do
define allowProportional : if (digits > 1) MONOSPACE-ONLY ALLOW-PROPORTIONAL define allowProportional : if (digits > 1) MONOSPACE-ONLY ALLOW-PROPORTIONAL
define jobs : CollectJobs builder.decomposable CENTERED allowProportional (prefix + digits) suffix demands define jobs : CollectJobs builder.decomposable CENTERED allowProportional (prefix + digits) suffix demands
define forkedPara : spacing.getPara para digits rows ww define forkedPara : inners.getPara para digits rows ww
define miniatureFont : CreateDerivedFontFromJobs jobs {} : function [gs] : Fork gs forkedPara define miniatureFont : CreateDerivedFontFromJobs jobs {} : function [gs] : Fork gs forkedPara
define gnEnclosure : CircName null (prefix + digits + '.enclosure') {} suffix define gnEnclosure : CircName null (prefix + digits + '.enclosure') {} suffix
if [not : query-glyph gnEnclosure] : create-glyph gnEnclosure : fnEnclosure digits ww gap if [not : query-glyph gnEnclosure] : create-glyph gnEnclosure : fnEnclosure digits ww gap
foreach job [items-of jobs.decomposableJobs] : begin foreach job [items-of jobs.decomposableJobs] : begin
builder.build (prefix + digits) spacing.gniPrefix digits ww gap job miniatureFont gnEnclosure true builder.build (prefix + digits) inners digits ww gap job miniatureFont gnEnclosure true
foreach job [items-of jobs.nonDecomposable] : begin foreach job [items-of jobs.nonDecomposable] : begin
builder.build (prefix + digits) spacing.gniPrefix digits ww gap job miniatureFont gnEnclosure false builder.build (prefix + digits) inners digits ww gap job miniatureFont gnEnclosure false
applyRelations jobs.relApplications applyRelations jobs.relApplications
# Builders and Enclosure Shapes # Builders and Enclosure Shapes
define CircledBuilder : object define CircledBuilder : object
decomposable true decomposable true
build : lambda [prefix gniPrefix digits ww gap job miniatureFont gnEnclosure decomposable] : begin build : lambda [prefix inners digits ww gap job miniatureFont gnEnclosure decomposable] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define dimens : circleDimens digits ww define dimens : CircleDimens digits ww
define [object width mockInnerWidth dscale] dimens define [object width] dimens
if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc
set-width width set-width width
include : EnclosureInner gniPrefix [if decomposable gnEnclosure null] miniatureFont job dimens include : EnclosureInner inners [if decomposable gnEnclosure null] miniatureFont job dimens
include : refer-glyph gnEnclosure include : refer-glyph gnEnclosure
define TwoRowBoxedBuilder : object define TwoRowBoxedBuilder : object
decomposable true decomposable true
build : lambda [prefix gniPrefix digits ww gap job miniatureFont gnEnclosure decomposable] : begin build : lambda [prefix inners digits ww gap job miniatureFont gnEnclosure decomposable] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define dimens : circleDimens digits ww define dimens : CircleDimens digits ww
define [object width mockInnerWidth dscale] dimens define [object width] dimens
if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc
set-width width set-width width
include : TwoRowEnclosureInner gniPrefix [if decomposable gnEnclosure null] miniatureFont job dimens include : TwoRowEnclosureInner inners [if decomposable gnEnclosure null] miniatureFont job dimens
include : refer-glyph gnEnclosure include : refer-glyph gnEnclosure
define InsetBuilder : object define InsetBuilder : object
decomposable false decomposable false
build : lambda [prefix gniPrefix digits ww gap job miniatureFont gnEnclosure decomposable] : begin build : lambda [prefix inners digits ww gap job miniatureFont gnEnclosure decomposable] : begin
define { gn unicode parts w bal baly } job define { gn unicode parts w bal baly } job
define dimens : circleDimens digits ww define dimens : CircleDimens digits ww
define [object width mockInnerWidth dscale] dimens define [object width] dimens
if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc
set-width width set-width width
include : difference include : difference
refer-glyph gnEnclosure refer-glyph gnEnclosure
EnclosureInner gniPrefix [if decomposable gnEnclosure null] miniatureFont job dimens EnclosureInner inners [if decomposable gnEnclosure null] miniatureFont job dimens
define InsetWithGapBuilder : object
decomposable false
build : lambda [prefix inners digits ww gap job miniatureFont gnEnclosure decomposable] : begin
define { gn unicode parts w bal baly } job
define dimens : CircleDimens digits ww
define [object width top bot left right] dimens
if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc
set-width width
local gap : Math.max [AdviceStroke 6] (Width * 0.08)
local [inner] : EnclosureInner inners null miniatureFont job dimens
include : difference
intersection
Rect top bot left right
union
refer-glyph gnEnclosure
remove-holes [inner]
with-outlined gap [inner]
inner
define [AddEnclosureMark digits dimens] : glyph-proc define [AddEnclosureMark digits dimens] : glyph-proc
define [object width dscale mockInnerWidth] dimens define [object width dscale mockInnerWidth] dimens
@ -319,19 +360,19 @@ glyph-block AutoBuild-Enclosure : begin
set-base-anchor 'enclosureInnerSecondHalf' (0.5 * width - 0.5 * dscale * [Math.min (Width * digits) mockInnerWidth]) 0 set-base-anchor 'enclosureInnerSecondHalf' (0.5 * width - 0.5 * dscale * [Math.min (Width * digits) mockInnerWidth]) 0
define [createCircledGlyphs digits demands] define [createCircledGlyphs digits demands]
EnclosureT "circle" CircledBuilder StandardSpacing digits 1 demands CircleEnclosureShape EnclosureT "circle" CircledBuilder StandardInners digits 1 demands CircleEnclosureShape
define [createBackslashCircledGlyphs digits demands] define [createBackslashCircledGlyphs digits demands]
EnclosureT "circle-slashed" CircledBuilder StandardSpacing digits 1 demands BackslashCircleEnclosureShape EnclosureT "circle-slashed" CircledBuilder StandardInners digits 1 demands BackslashCircleEnclosureShape
define [createItalicCircledGlyphs digits demands] define [createItalicCircledGlyphs digits demands]
EnclosureT "circle-italic" CircledBuilder ItalicSpacing digits 1 demands CircleEnclosureShape EnclosureT "circle-italic" CircledBuilder ItalicInners digits 1 demands CircleEnclosureShape
define [CircleEnclosureShape digits ww gap] : glyph-proc define [CircleEnclosureShape digits ww gap] : glyph-proc
define [object width sw top bot left right archDepthA archDepthB] : circleDimens digits ww define [object width sw top bot left right archDepthA archDepthB] : CircleDimens digits ww
set-width width set-width width
include : OShape top bot left right sw archDepthA archDepthB include : OShape top bot left right sw archDepthA archDepthB
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [BackslashCircleEnclosureShape digits ww gap] : glyph-proc define [BackslashCircleEnclosureShape digits ww gap] : glyph-proc
include : CircleEnclosureShape digits ww gap include : CircleEnclosureShape digits ww gap
define [object width sw top bot left right archDepthA archDepthB] : circleDimens digits ww define [object width sw top bot left right archDepthA archDepthB] : CircleDimens digits ww
include : intersection include : intersection
OShapeOutline top bot left right sw archDepthA archDepthB OShapeOutline top bot left right sw archDepthA archDepthB
dispiro dispiro
@ -339,33 +380,33 @@ glyph-block AutoBuild-Enclosure : begin
curl width [mix bot top (1 - 0.77)] curl width [mix bot top (1 - 0.77)]
define [createBoxedGlyphs digits demands] define [createBoxedGlyphs digits demands]
EnclosureT 'boxed' CircledBuilder StandardSpacing digits 1 demands BoxEnclosureShape EnclosureT 'boxed' CircledBuilder StandardInners digits 1 demands BoxEnclosureShape
define [BoxEnclosureShape digits ww gap] : glyph-proc define [BoxEnclosureShape digits ww gap] : glyph-proc
define [object width mockInnerWidth sw top bot left right] : circleDimens digits ww define [object width sw top bot left right] : CircleDimens digits ww
set-width width set-width width
include : union include : union
HBar.t left right top sw HBar.t left right top sw
HBar.b left right bot sw HBar.b left right bot sw
VBar.l left bot top sw VBar.l left bot top sw
VBar.r right bot top sw VBar.r right bot top sw
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [createTwoRowBoxedGlyphs digits demands] define [createTwoRowBoxedGlyphs digits demands]
EnclosureT 'twoRowBoxed' TwoRowBoxedBuilder StandardSpacing digits 2 demands TwoRowBoxEnclosureShape EnclosureT 'twoRowBoxed' TwoRowBoxedBuilder StandardInners digits 2 demands TwoRowBoxEnclosureShape
define [TwoRowBoxEnclosureShape digits ww gap] : glyph-proc define [TwoRowBoxEnclosureShape digits ww gap] : glyph-proc
define [object width mockInnerWidth sw top bot left right] : circleDimens digits ww define [object width sw top bot left right] : CircleDimens digits ww
set-width width set-width width
include : union include : union
HBar.t left right top sw HBar.t left right top sw
HBar.b left right bot sw HBar.b left right bot sw
VBar.l left bot top sw VBar.l left bot top sw
VBar.r right bot top sw VBar.r right bot top sw
include : AddEnclosureMarkTwoLine digits : circleDimens digits ww include : AddEnclosureMarkTwoLine digits : CircleDimens digits ww
define [createDashedBoxedGlyphs digits demands] define [createDashedBoxedGlyphs digits demands]
EnclosureT 'dashed-boxed' CircledBuilder StandardSpacing digits 1 demands DashedBoxEnclosureShape EnclosureT 'dashed-boxed' CircledBuilder StandardInners digits 1 demands DashedBoxEnclosureShape
define [DashedBoxEnclosureShape digits ww cap] : glyph-proc define [DashedBoxEnclosureShape digits ww cap] : glyph-proc
define [object width mockInnerWidth sw top bot left right] : circleDimens digits ww define [object width sw top bot left right] : CircleDimens digits ww
set-width width set-width width
include : difference include : difference
union union
@ -380,33 +421,67 @@ glyph-block AutoBuild-Enclosure : begin
HBar.m left right [mix bot top 0.25] sw HBar.m left right [mix bot top 0.25] sw
HBar.m left right [mix bot top 0.50] sw HBar.m left right [mix bot top 0.50] sw
HBar.m left right [mix bot top 0.75] sw HBar.m left right [mix bot top 0.75] sw
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [createInsetCircledGlyphs digits demands] define [createInsetCircledGlyphs digits demands]
EnclosureT 'inset-circle' InsetBuilder StandardSpacing digits 1 demands InsetCircleEnclosureShape EnclosureT 'inset-circle' InsetBuilder StandardInners digits 1 demands InsetCircleEnclosureShape
define [InsetCircleEnclosureShape digits ww gap] : glyph-proc define [InsetCircleEnclosureShape digits ww gap] : glyph-proc
define [object width sw top bot left right archDepthA archDepthB] : circleDimens digits ww define [object width sw top bot left right archDepthA archDepthB] : CircleDimens digits ww
set-width width set-width width
include : OShapeOutline top bot left right sw archDepthA archDepthB include : OShapeOutline top bot left right sw archDepthA archDepthB
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [createInsetBoxedGlyphs digits demands] define [createInsetBoxedGlyphs digits demands]
EnclosureT 'inset-boxed' InsetBuilder StandardSpacing digits 1 demands InsetBoxEnclosureShape EnclosureT 'inset-boxed' InsetBuilder StandardInners digits 1 demands InsetBoxEnclosureShape
define [InsetBoxEnclosureShape digits ww gap] : glyph-proc define [InsetBoxEnclosureShape digits ww gap] : glyph-proc
define [object width top bot left right] : circleDimens digits ww define [object width top bot left right] : CircleDimens digits ww
set-width width set-width width
include : spiro-outline include : Rect top bot left right
corner left top include : AddEnclosureMark digits : CircleDimens digits ww
corner left bot
corner right bot define [createDecomposableInsetCircledGlyphs digits demands]
corner right top EnclosureT 'inset-circle-decomp' CircledBuilder DecomposableInsetInners digits 1 demands DecomposableInsetCircleEnclosureShape
close define [DecomposableInsetCircleEnclosureShape digits ww gap] : glyph-proc
include : AddEnclosureMark digits : circleDimens digits ww define [object width sw top bot left right archDepthA archDepthB] : CircleDimens digits ww
set-width width
include : difference
OShapeOutline top bot left right sw archDepthA archDepthB
DecomposableInsetKnockout digits ww
include : AddEnclosureMark digits : CircleDimens digits ww
define [createDecomposableInsetBoxedGlyphs digits demands]
EnclosureT 'inset-boxed-decomp' CircledBuilder DecomposableInsetInners digits 1 demands DecomposableInsetBoxEnclosureShape
define [DecomposableInsetBoxEnclosureShape digits ww gap] : glyph-proc
define [object width top bot left right] : CircleDimens digits ww
set-width width
include : difference
Rect top bot left right
DecomposableInsetKnockout digits ww
include : AddEnclosureMark digits : CircleDimens digits ww
define [DecomposableInsetKnockout digits ww] : begin
define [object top bot left right dscale mockInnerWidth] : CircleDimens digits ww
local xMid : mix left right 0.5
local yMid : mix bot top 0.5
local halfHeight : CAP * 0.55 * dscale
local halfWidth : [Math.min (digits * Width) mockInnerWidth] * 0.5 * dscale
return : Rect (yMid + halfHeight) (yMid - halfHeight) (xMid - halfWidth) (xMid + halfWidth)
define [createCrossInsetBoxedGlyphs digits demands]
EnclosureT 'cross-inset-boxed' InsetWithGapBuilder StandardInners digits 1 demands CrossInsetSquareShape
define [CrossInsetSquareShape digits ww gap] : glyph-proc
define [object width sw top bot left right] : CircleDimens digits ww
set-width width
include : difference
Rect top bot left right
ExtLineCenter (-0.1) sw left bot right top
ExtLineCenter (-0.1) sw right bot left top
include : AddEnclosureMark digits : CircleDimens digits ww
define [createInsetDiamondGlyphs digits demands] define [createInsetDiamondGlyphs digits demands]
EnclosureT 'inset-diamond' InsetBuilder StandardSpacing digits 1 demands InsetDiamondEnclosureShape EnclosureT 'inset-diamond' InsetBuilder StandardInners digits 1 demands InsetDiamondEnclosureShape
define [InsetDiamondEnclosureShape digits ww gap] : glyph-proc define [InsetDiamondEnclosureShape digits ww gap] : glyph-proc
define [object width top bot left right] : circleDimens digits ww define [object width top bot left right] : CircleDimens digits ww
set-width width set-width width
include : spiro-outline include : spiro-outline
corner (left + O) [mix bot top 0.5] corner (left + O) [mix bot top 0.5]
@ -414,26 +489,21 @@ glyph-block AutoBuild-Enclosure : begin
corner (right - O) [mix bot top 0.5] corner (right - O) [mix bot top 0.5]
corner [mix left right 0.5] (top - O) corner [mix left right 0.5] (top - O)
close close
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [createInsetMosaicGlyphs digits demands] define [createInsetMosaicGlyphs digits demands]
EnclosureT 'inset-mosaic' InsetBuilder StandardSpacing digits 1 demands InsetMosaicEnclosureShape EnclosureT 'inset-mosaic' InsetBuilder StandardInners digits 1 demands InsetMosaicEnclosureShape
define [InsetMosaicEnclosureShape digits ww gap] : glyph-proc define [InsetMosaicEnclosureShape digits ww gap] : glyph-proc
define [object width mockInnerWidth mosaicTop mosaicBot mosaicLeft mosaicRight] : circleDimens digits ww define [object width mosaicTop mosaicBot mosaicLeft mosaicRight] : CircleDimens digits ww
set-width width set-width width
include : ForceUpright include : ForceUpright
include : spiro-outline include : Rect mosaicTop mosaicBot mosaicLeft mosaicRight
corner mosaicLeft mosaicTop include : AddEnclosureMark digits : CircleDimens digits ww
corner mosaicLeft mosaicBot
corner mosaicRight mosaicBot
corner mosaicRight mosaicTop
close
include : AddEnclosureMark digits : circleDimens digits ww
define [createDoubleCircledGlyphs digits demands] define [createDoubleCircledGlyphs digits demands]
EnclosureT 'double-circle' CircledBuilder StandardSpacing digits 1 demands DoubleCircledEnclosureShape EnclosureT 'double-circle' CircledBuilder StandardInners digits 1 demands DoubleCircledEnclosureShape
define [DoubleCircledEnclosureShape digits ww gap] : glyph-proc define [DoubleCircledEnclosureShape digits ww gap] : glyph-proc
define [object width mockInnerWidth sw0 sw top bot left right archDepthA archDepthB] : circleDimens digits ww (ww * gap) define [object width sw0 sw top bot left right archDepthA archDepthB] : CircleDimens digits ww (ww * gap)
set-width width set-width width
define sw1 : Math.min sw0 (sw / 3) define sw1 : Math.min sw0 (sw / 3)
include : OShape top bot left right sw1 archDepthA archDepthB include : OShape top bot left right sw1 archDepthA archDepthB
@ -445,7 +515,7 @@ glyph-block AutoBuild-Enclosure : begin
begin sw1 begin sw1
archDepthA - sw + sw1 archDepthA - sw + sw1
archDepthB - sw + sw1 archDepthB - sw + sw1
include : AddEnclosureMark digits : circleDimens digits ww include : AddEnclosureMark digits : CircleDimens digits ww
define [BraceCrowd digits width] : 2.75 + [AdjustDigitCount digits width] define [BraceCrowd digits width] : 2.75 + [AdjustDigitCount digits width]
define [BraceScale digits width] : 0.65 / [Math.pow [AdjustDigitCount digits width] 0.5] define [BraceScale digits width] : 0.65 / [Math.pow [AdjustDigitCount digits width] 0.5]
@ -474,9 +544,9 @@ glyph-block AutoBuild-Enclosure : begin
local {gn unicode parts w bal baly} job local {gn unicode parts w bal baly} job
if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc if [not : query-glyph gn] : create-glyph gn [if (w == ww) unicode null] : glyph-proc
define dimens : bracedDottdeDimens digits ww define dimens : bracedDottdeDimens digits ww
define [object width mockInnerWidth dscale] dimens define [object width] dimens
set-width width set-width width
include : EnclosureInner '' [if jobDecomposable gnb null] miniatureFont job dimens include : EnclosureInner StandardInners [if jobDecomposable gnb null] miniatureFont job dimens
include : refer-glyph gnb include : refer-glyph gnb
foreach job [items-of jobs.decomposableJobs] : CreateGlyphImpl true job foreach job [items-of jobs.decomposableJobs] : CreateGlyphImpl true job
@ -485,7 +555,7 @@ glyph-block AutoBuild-Enclosure : begin
define [createBracedGlyphs digits demands] : BracedT 'braced' digits demands BraceShape define [createBracedGlyphs digits demands] : BracedT 'braced' digits demands BraceShape
define [BraceShape digits ww] : glyph-proc define [BraceShape digits ww] : glyph-proc
define [object width dscale pscale sw l r] : bracedDottdeDimens digits ww define [object width pscale sw l r] : bracedDottdeDimens digits ww
local s : TanSlope * SymbolMid / 2 local s : TanSlope * SymbolMid / 2
local p : 0.1 * [Math.sqrt : Math.min 1 (width / (digits * Width))] local p : 0.1 * [Math.sqrt : Math.min 1 (width / (digits * Width))]
set-width width set-width width
@ -508,7 +578,7 @@ glyph-block AutoBuild-Enclosure : begin
define [createHexBracedGlyphs digits demands] : BracedT 'hex-braced' digits demands HexBracedShape define [createHexBracedGlyphs digits demands] : BracedT 'hex-braced' digits demands HexBracedShape
define [HexBracedShape digits ww] : glyph-proc define [HexBracedShape digits ww] : glyph-proc
define [object width dscale pscale sw l r] : bracedDottdeDimens digits ww define [object width pscale sw l r] : bracedDottdeDimens digits ww
local s : TanSlope * SymbolMid / 2 local s : TanSlope * SymbolMid / 2
local p : (1 / 6) * [Math.sqrt : Math.min 1 (width / (digits * Width))] local p : (1 / 6) * [Math.sqrt : Math.min 1 (width / (digits * Width))]
set-width width set-width width
@ -660,21 +730,25 @@ glyph-block AutoBuild-Enclosure : begin
foreach [j : range 36 till 50] : compositions.push : list (0x32B1 + j - 36) [digitGlyphNames j] WideWidth1 foreach [j : range 36 till 50] : compositions.push : list (0x32B1 + j - 36) [digitGlyphNames j] WideWidth1
createCircledGlyphs 2 compositions createCircledGlyphs 2 compositions
do "Single-letter inset circled"
local compositions : list
foreach [j : range 0 26] : compositions.push {(0x1F150 + j) {[glyphStore.queryNameByUnicode (['A'.charCodeAt 0] + j)]} WideWidth1}
createInsetCircledGlyphs 1 compositions
do "Single-digit inset circled" do "Single-digit inset circled"
local compositions : list local compositions : list
list 0x24FF {'zero.lnum'} WideWidth1 list 0x24FF {'zero.lnum'} WideWidth1
list 0x1F10C {'zero.lnum'} WideWidth1 # We don't have serifs for digit 0, so make an alias here list 0x1F10C {'zero.lnum'} WideWidth1 # We don't have serifs for digit 0, so make an alias here
foreach [j : range 1 till 9] : compositions.push : list (0x2776 + j - 1) [digitGlyphNames j] WideWidth1 foreach [j : range 1 till 9] : compositions.push : list (0x2776 + j - 1) [digitGlyphNames j] WideWidth1
foreach [j : range 1 till 9] : compositions.push : list (0x278A + j - 1) [digitGlyphNames j digitSansSerifSuffix] WideWidth1 foreach [j : range 1 till 9] : compositions.push : list (0x278A + j - 1) [digitGlyphNames j digitSansSerifSuffix] WideWidth1
foreach [j : range 0 26] : compositions.push {(0x1F150 + j) {[glyphStore.queryNameByUnicode (['A'.charCodeAt 0] + j)]} WideWidth1} createDecomposableInsetCircledGlyphs 1 compositions
createInsetCircledGlyphs 1 compositions
do "Double-digit inset circled" do "Double-digit inset circled"
local compositions : list local compositions : list
list 0x2793 { "one/sansSerif.lnum" "zero.lnum" } WideWidth1 list 0x2793 { "one/sansSerif.lnum" "zero.lnum" } WideWidth1
foreach [j : range 10 till 10] : compositions.push : list (0x2776 + j - 1) [digitGlyphNames j] WideWidth1 foreach [j : range 10 till 10] : compositions.push : list (0x2776 + j - 1) [digitGlyphNames j] WideWidth1
foreach [j : range 11 till 20] : compositions.push : list (0x24EB + j - 11) [digitGlyphNames j] WideWidth1 foreach [j : range 11 till 20] : compositions.push : list (0x24EB + j - 11) [digitGlyphNames j] WideWidth1
createInsetCircledGlyphs 2 compositions createDecomposableInsetCircledGlyphs 2 compositions
do "boxed" do "boxed"
local compositions {} local compositions {}
@ -750,13 +824,17 @@ glyph-block AutoBuild-Enclosure : begin
list 0xFFFD { "question" } WideWidth2 list 0xFFFD { "question" } WideWidth2
do "double-digit inset boxed" do "double-digit inset boxed"
createInsetBoxedGlyphs 2 : list createDecomposableInsetBoxedGlyphs 2 : list
list 0x1F18B {'I' 'C'} WideWidth1 list 0x1F18B {'I' 'C'} WideWidth1
list 0x1F18C {'P' 'A'} WideWidth1 list 0x1F18C {'P' 'A'} WideWidth1
list 0x1F18D {'S' 'A'} WideWidth1 list 0x1F18D {'S' 'A'} WideWidth1
list 0x1F18E {'A' 'B'} WideWidth1 list 0x1F18E {'A' 'B'} WideWidth1
list 0x1F18F {'W' 'C'} WideWidth1 list 0x1F18F {'W' 'C'} WideWidth1
do "negative square"
createCrossInsetBoxedGlyphs 1 : list
list 0x1F18A { "P" } WideWidth1
do "inset mosaic" do "inset mosaic"
local compositions {} local compositions {}
compositions.push { 0x1FBB1 { [[glyphStore.queryNameByUnicode (0x2714)].replace [regex '.WWID$'] ".NWID"] } WideWidth4 } compositions.push { 0x1FBB1 { [[glyphStore.queryNameByUnicode (0x2714)].replace [regex '.WWID$'] ".NWID"] } WideWidth4 }

View file

@ -4,6 +4,7 @@ import [mix linreg clamp fallback boole boolePn] from "@iosevka/util"
import [Transform] from "@iosevka/geometry/transform" import [Transform] from "@iosevka/geometry/transform"
import [Interpolator] from "@iosevka/geometry/spiro-control" import [Interpolator] from "@iosevka/geometry/spiro-control"
import [Radical] from "@iosevka/glyph/relation" import [Radical] from "@iosevka/glyph/relation"
import [StrokeGeometry RemoveHolesGeometry] from "@iosevka/geometry"
glyph-module glyph-module
@ -670,6 +671,20 @@ glyph-block CommonShapes : begin
glyph-block-export with-transform glyph-block-export with-transform
define [with-transform tfm gr] : new-glyph : composite-proc gr tfm define [with-transform tfm gr] : new-glyph : composite-proc gr tfm
glyph-block-export with-outlined
define [with-outlined sw gr] : new-glyph : glyph-proc
include gr
local g currentGlyph.geometry
local gizmo : currentGlyph.gizmo || GlobalTransform
set currentGlyph.geometry : new StrokeGeometry g gizmo sw HVContrast false
glyph-block-export remove-holes
define [remove-holes gr] : new-glyph : glyph-proc
include gr
local g currentGlyph.geometry
local gizmo : currentGlyph.gizmo || GlobalTransform
set currentGlyph.geometry : new RemoveHolesGeometry g gizmo
glyph-block-export clear-geometry glyph-block-export clear-geometry
define [clear-geometry] : glyph-proc define [clear-geometry] : glyph-proc
currentGlyph.clearGeometry currentGlyph.clearGeometry

View file

@ -195,11 +195,12 @@ define-macro glyph-block-import : syntax-rules
CommonShapes `[no-shape tagged Rect SquareAt Ring RingAt DotAt RingStroke CommonShapes `[no-shape tagged Rect SquareAt Ring RingAt DotAt RingStroke
RingStrokeAt DotStrokeAt Circle Ellipse OShapeT OShape OShapeOutline OShapeFlatTB HSerif RingStrokeAt DotStrokeAt Circle Ellipse OShapeT OShape OShapeOutline OShapeFlatTB HSerif
VSerif NeedSlab NeedNotItalic HBar HOverlayBar VBar FlatSlashShape hookstart hookend arch VSerif NeedSlab NeedNotItalic HBar HOverlayBar VBar FlatSlashShape hookstart hookend
Ungizmo Regizmo FlipAround ScaleAround Realign ForceUpright DiagCor NameUni PointingTo arch Ungizmo Regizmo FlipAround ScaleAround Realign ForceUpright DiagCor NameUni
with-transform clear-geometry clear-anchors AsRadical ExtLineCenter ExtLineLhs ExtLineRhs PointingTo with-transform with-outlined remove-holes clear-geometry clear-anchors
DiagCorDs HCrossBar VERY-FAR MaskAbove MaskBelow MaskLeft MaskRight HalfRectTriangle AsRadical ExtLineCenter ExtLineLhs ExtLineRhs DiagCorDs HCrossBar VERY-FAR MaskAbove
MaskAboveLine MaskBelowLine MaskLeftLine MaskRightLine DotVariants WithDotVariants] MaskBelow MaskLeft MaskRight HalfRectTriangle MaskAboveLine MaskBelowLine MaskLeftLine
MaskRightLine DotVariants WithDotVariants]
define vartiableFilter : if externEnv.$glyphBlockVariableUsage$ define vartiableFilter : if externEnv.$glyphBlockVariableUsage$
lambda [x] externEnv.$glyphBlockVariableUsage$.(x) lambda [x] externEnv.$glyphBlockVariableUsage$.(x)

View file

@ -625,6 +625,72 @@ export class StrokeGeometry extends CachedGeometry {
} }
} }
export class RemoveHolesGeometry extends CachedGeometry {
constructor(geom, gizmo) {
super();
this.m_geom = geom;
this.m_gizmo = gizmo;
}
toContoursImpl(ctx) {
// Produce simplified arcs
const nonTransformedGeometry = new TransformedGeometry(this.m_gizmo.inverse(), this.m_geom);
let arcs = TypoGeom.Boolean.removeOverlap(
CurveUtil.convertShapeToArcs(nonTransformedGeometry.toContours(ctx)),
TypoGeom.Boolean.PolyFillType.pftNonZero,
CurveUtil.BOOLE_RESOLUTION,
);
if (arcs.length > 1) {
let stack = [];
stack.push({
type: "operand",
fillType: TypoGeom.Boolean.PolyFillType.pftNonZero,
shape: [arcs[0]],
});
for (let i = 1; i < arcs.length; i++) {
stack.push({
type: "operand",
fillType: TypoGeom.Boolean.PolyFillType.pftNonZero,
shape: [arcs[i]],
});
stack.push({ type: "operator", operator: TypoGeom.Boolean.ClipType.ctUnion });
}
arcs = TypoGeom.Boolean.combineStack(stack, CurveUtil.BOOLE_RESOLUTION);
}
// Convert to Iosevka format
let sink = new CurveUtil.BezToContoursSink(this.m_gizmo);
TypoGeom.ShapeConv.transferBezArcShape(arcs, sink, CurveUtil.GEOMETRY_PRECISION);
return sink.contours;
}
toReferences() {
return null;
}
getDependencies() {
return this.m_geom.getDependencies();
}
unlinkReferences() {
return new RemoveHolesGeometry(this.m_geom.unlinkReferences(), this.m_gizmo);
}
filterTag(fn) {
return new RemoveHolesGeometry(this.m_geom.filterTag(fn), this.m_gizmo);
}
measureComplexity() {
return this.m_geom.measureComplexity() | CPLX_NON_SIMPLE;
}
hash(h) {
h.beginStruct("RemoveHolesGeometry");
h.embed(this.m_geom);
h.gizmo(this.m_gizmo);
h.endStruct();
}
}
// This special geometry type is used in the finalization phase to create TTF contours. // This special geometry type is used in the finalization phase to create TTF contours.
export class SimplifyGeometry extends CachedGeometry { export class SimplifyGeometry extends CachedGeometry {
constructor(g) { constructor(g) {