diff --git a/.gitignore b/.gitignore index 8e039f3..539a1b5 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ node_modules test/ preview/ build/ +dist/ ref/ pages/ releases/ diff --git a/features/common.fea b/features/common.fea index 0bd3406..13f7305 100644 --- a/features/common.fea +++ b/features/common.fea @@ -40,19 +40,23 @@ feature ccmp { feature mark { script latn; language dflt; - lookup markAuto_letter; + lookup markAuto_letter1; + lookup markAuto_letter2; lookup markAuto_overlay; script grek; language dflt; - lookup markAuto_letter; + lookup markAuto_letter1; + lookup markAuto_letter2; lookup markAuto_overlay; script cyrl; language dflt; - lookup markAuto_letter; + lookup markAuto_letter1; + lookup markAuto_letter2; lookup markAuto_overlay; script dflt; language dflt; - lookup markAuto_letter; + lookup markAuto_letter1; + lookup markAuto_letter2; lookup markAuto_overlay; } mark; @@ -70,38 +74,3 @@ feature mkmk { language dflt; lookup mkmkAuto; } mkmk; - -lookup slashzero { - sub zero by zero.slashed; -} slashzero; -lookup dotzero { - sub zero by zero.dotted; -} dotzero; -lookup blankzero { - sub zero by zero.unslashed; -} blankzero; - -feature cv01 { script latn; sub a by a.upright; } cv01; -feature cv02 { script latn; sub a by a.italic; } cv02; -feature cv03 { script latn; sub i by i.serifed; } cv03; -feature cv04 { script latn; sub i by i.italic; } cv04; -feature cv05 { script latn; sub i by i.hooky; } cv05; -feature cv06 { script latn; sub i by i.zshaped; } cv06; -feature cv07 { script latn; sub l by l.serifed; } cv07; -feature cv08 { script latn; sub l by l.italic; } cv08; -feature cv09 { script latn; sub l by l.hooky; } cv09; -feature cv10 { script latn; sub l by l.zshaped; } cv10; -feature cv11 { script latn; sub g by g.doublestorey; } cv11; -feature cv12 { script latn; sub g by g.singlestorey; } cv12; -feature cv13 { script latn; lookup slashzero; script dflt; lookup slashzero; } cv13; -feature cv14 { script latn; lookup dotzero; script dflt; lookup dotzero; } cv14; -feature cv15 { script latn; lookup blankzero; script dflt; lookup blankzero; } cv15; - -feature ss01 { script latn; sub [i l] by [i.serifed l.serifed]; } ss01; -feature ss02 { script latn; sub [i l] by [i.hooky l.hooky]; } ss02; -feature ss03 { script latn; sub [i l] by [i.zshaped l.zshaped]; } ss03; -feature ss04 { script latn; sub g by g.doublestorey; } ss04; -feature ss05 { script latn; sub g by g.singlestorey; } ss05; -feature ss06 { script latn; lookup slashzero; script dflt; lookup slashzero; } ss06; -feature ss07 { script latn; lookup dotzero; script dflt; lookup dotzero; } ss07; -feature ss08 { script latn; lookup blankzero; script dflt; lookup blankzero; } ss08; \ No newline at end of file diff --git a/generator.js b/generator.js index 8ff5636..290fa99 100644 --- a/generator.js +++ b/generator.js @@ -20,6 +20,7 @@ var font = function(){ console.log(' Start build font ' + fontUniqueName); var font = buildGlyphs.build.call(emptyFont, para); console.log(' ' + fontUniqueName + " Successfully built."); + font.features.sscompose = para.sscompose return font; }(); @@ -38,6 +39,20 @@ if(argv.feature) (function(){ console.log(' Writing feature file -> ' + argv.feature); var featurefile = '\n\n'; // markGlyphs + for(var feature in font.features.cv) { + var base = [], replace = []; + for(var key in font.features.cv[feature]) { + base.push(key); + replace.push(font.features.cv[feature][key]); + }; + var lookupName = feature + 'Auto'; + featurefile += 'lookup ' + lookupName + ' { sub [' + base.join(' ') + '] by [' + replace.join(' ') + '];} ' + lookupName + ';\n\n'; + featurefile += 'feature ' + feature + ' { script latn; lookup ' + lookupName + '; script grek; lookup ' + lookupName + '; script cyrl; lookup ' + lookupName + '; script dflt; lookup ' + lookupName + '; } ' + feature + ';\n\n'; + } + for(var feature in font.features.sscompose) { + var stmt = font.features.sscompose[feature].map(function(lookup){ return 'lookup ' + lookup + 'Auto'}).join(';') + featurefile += 'feature ' + feature + ' { script latn; ' + stmt + '; script grek; ' + stmt + '; script cyrl; ' + stmt + '; script dflt; ' + stmt + '; } ' + feature + ';\n\n'; + } for(var key in font.features.markGlyphs){ featurefile += '@MG_' + key + '= [' + font.features.markGlyphs[key].join(' ') + '];\n' } diff --git a/glyphs/autobuilds.ptl b/glyphs/autobuilds.ptl index 83b7479..0cea5aa 100644 --- a/glyphs/autobuilds.ptl +++ b/glyphs/autobuilds.ptl @@ -2,6 +2,8 @@ # Build accented glyphs define [isAboveMark mark] : mark && mark.anchors && mark.anchors.above && mark.anchors.above.type === MARK +set font.features {.} +set font.features.cv {.} define customDecompositions { # Latvians use comma instead of cedillas in several letters. @@ -160,7 +162,7 @@ define [pad s n] : begin #set font.features.ccmp {} define [shorter x y] : if (x.length < y.length) x y -let : begin +local {cfv} : let : begin local nComposed 0 local foundDecompositions {.} define [decideName namingParts parts code] : begin @@ -171,7 +173,7 @@ let : begin local j 2 while foundDecompositions.(glyphName + j) [inc j] set glyphName (glyphName + j) - if (glyphName.length > 30) : set glyphName ('uni' + [pad [[code.toString 16].toUpperCase] 4]) + if (glyphName.length > 27) : set glyphName ('uni' + [pad [[code.toString 16].toUpperCase] 4]) return glyphName local [buildForCode code] : if [not unicodeGlyphs.(code)] : begin local str : String.fromCharCode code @@ -195,8 +197,9 @@ let : begin #if (global && global.gc) : global.gc progress "Composition Decision" + local {glyphName code parts} {} define construction : glyph-construction - assign-unicode code + if code : assign-unicode code include parts.0 AS_BASE set-width parts.0.advanceWidth @@ -205,18 +208,40 @@ let : begin include part names.push part.name if (part.name === 'rtailBR') : eject-contour 'serifRB' - #progress "Compose [\[names.join ' + ']] --> \(glyphName)" + + define [cfv glyphName _pa] : if (!recursive && _pa.0.featureSelector) : begin + local h {.} + foreach [feature : items-of : Object.keys _pa.0.featureSelector] : begin + local variant _pa.0.featureSelector.(feature) + local variantRoot glyphs.(variant) + if variantRoot : begin + set parts {variantRoot :: [_pa.slice 1]} + set code null + create-glyph (glyphName + '.' + feature) construction + + set h.(feature) (glyphName + '.' + feature) + if glyphs.(glyphName) : set glyphs.(glyphName).featureSelector h + foreach [_id : items-of : Object.keys foundDecompositions] : begin - local {glyphName code parts} foundDecompositions.(_id) + set {glyphName code parts} foundDecompositions.(_id) create-glyph glyphName construction + cfv glyphName parts + progress "Unicode Precomposites (\(nComposed) glyphs)" + + list cfv -symbol-block "Manual Precomposites" - composite 'i.serifed' glyphs.'dotlessi.serifed' glyphs.dotAbove - composite 'i.italic' glyphs.'dotlessi.italic' glyphs.dotAbove - composite 'i.hooky' glyphs.'dotlessi.hooky' glyphs.dotAbove - composite 'i.zshaped' glyphs.'dotlessi.zshaped' glyphs.dotAbove +symbol-block "Manual Precomposites and CV variants" + cfv 'i' {glyphs.dotlessi glyphs.dotAbove} + cfv 'cyrUkrainiani' {glyphs.i} + + foreach [name : items-of : Object.keys glyphs] : begin + if glyphs.(name).featureSelector : begin + local fs glyphs.(name).featureSelector + foreach [feature : items-of : Object.keys fs] : begin + if [not font.features.cv.(feature)] : set font.features.cv.(feature) {.} + set font.features.cv.(feature).(name) fs.(feature) local MarkZoom : glyph-construction apply-transform : Upright @@ -231,7 +256,17 @@ symbol-block "Manual Precomposites" composite 'latin1acute' glyphs.space glyphs.acuteAbove MarkZoom [into-unicode 0xB4] composite 'degree' glyphs.space glyphs.ringAbove MarkZoom [into-unicode 0xB0] - composite 'asciitilde.centered' glyphs.asciitilde [Upright] [Translate 0 (parenMid - XH - ACCENT)] [Italify] + if [not recursive] : begin + composite 'asciitilde.centered' glyphs.asciitilde [Upright] [Translate 0 (parenMid - XH - ACCENT)] [Italify] + set glyphs.asciitilde.featureSelector { + .cv16 'asciitilde' + .cv17 'asciitilde.centered' + } + composite 'asterisk.centered' glyphs.asterisk [Upright] [Translate 0 (parenMid - glyphs.asterisk.centery)] [Italify] + set glyphs.asterisk.featureSelector { + .cv18 'asterisk' + .cv19 'asterisk.centered' + } define [suggestName name] : begin if glyphs.(name) : begin @@ -261,7 +296,14 @@ define [createCircledGlyphs records] : if [not recursive] : begin apply-transform : Translate (width / 2) (CAP / 2 * dscale) apply-transform : Italify refair this - include : OShape (CAP * dscale + [Math.max (CAP * 0.175) (sw * 3)]) (-[Math.max (CAP * 0.175) (sw * 3)]) [Math.max (SB + O * 3) (width / 2 - CAP / 2 * dscale - sw * 2.5)] [Math.min (width - SB - O * 3) (width / 2 + CAP / 2 * dscale + sw * 2.5)] sw (SMALLSMOOTHA * width / WIDTH) (SMALLSMOOTHB * width / WIDTH) + include : OShape + * (CAP * dscale + [Math.max (CAP * 0.175) (sw * 3)]) + * (-[Math.max (CAP * 0.175) (sw * 3)]) + * [Math.max (SB + O * 3) (width / 2 - CAP / 2 * dscale - sw * 2.5)] + * [Math.min (width - SB - O * 3) (width / 2 + CAP / 2 * dscale + sw * 2.5)] + * sw + * (SMALLSMOOTHA * width / WIDTH) + * (SMALLSMOOTHB * width / WIDTH) apply-transform : Upright apply-transform : Translate 0 (parenMid - CAP * dscale / 2) apply-transform : Italify @@ -724,7 +766,6 @@ if [not recursive] : begin set font.glyf : font.glyf.filter [lambda [g] : g.advanceWidth <= WIDTH] set glyphList font.glyf - set font.features {.} set font.features.mark {.} set font.features.mkmk {.marks {} .bases {}} set font.features.markGlyphs {.} @@ -749,7 +790,8 @@ if [not recursive] : begin then : lookup.marks.push : 'markClass ' + glyph.name + [buildAnchorDescription glyph '' 'x' 'y' 'mark' th] else : lookup.bases.push : 'pos base ' + glyph.name + [buildAnchorDescription glyph 'mark' 'x' 'y' 'mark' th] - createMarkLookup 'letter' {'above' 'below' 'trailing' 'lf' 'topright' 'bottomright'} + createMarkLookup 'letter1' {'above' 'below'} + createMarkLookup 'letter2' {'trailing' 'lf' 'topright' 'bottomright'} createMarkLookup 'overlay' {'overlay' 'slash'} # mkmk and GDEF foreach glyph [items-of glyphList] : if (glyph.anchors && [begin [local anchorKeys : Object.keys glyph.anchors] anchorKeys.length]) diff --git a/glyphs/common-shapes.ptl b/glyphs/common-shapes.ptl index 04f56a9..9875b3d 100644 --- a/glyphs/common-shapes.ptl +++ b/glyphs/common-shapes.ptl @@ -1,11 +1,12 @@ ###### COMMON GLYPH CONSTRUCTIONS -define [select-variant name unicode default] : begin +define [select-variant name unicode default featureSelector] : begin if (pickHash && [not pickHash.(name)]) : return nothing local variant : variantSelector.(name) || default local chosenGlyph glyphs.((name + '.' + variant)) create-glyph name : glyph-construction include chosenGlyph AS_BASE if unicode : assign-unicode unicode + if featureSelector : set currentGlyph.featureSelector featureSelector define [italic-variant name unicode] : create-glyph name : glyph-construction if para.isItalic @@ -13,10 +14,12 @@ define [italic-variant name unicode] : create-glyph name : glyph-construction else : include glyphs.(name + '.upright') AS_BASE if unicode : assign-unicode unicode -define [alias newid unicode oldid] : create-glyph newid : glyph-construction - if unicode : assign-unicode unicode - include glyphs.(oldid) AS_BASE - set-width glyphs.(oldid).advanceWidth +define [alias newid unicode oldid] : begin + create-glyph newid : glyph-construction + if unicode : assign-unicode unicode + include glyphs.(oldid) AS_BASE + set-width glyphs.(oldid).advanceWidth + set this.featureSelector glyphs.(oldid).featureSelector define [composite newid] : let [parts : {}.slice.call arguments 1] : begin create-glyph [fallback newid ('glyph' + [set nTemp (nTemp + 1)])] : glyph-construction diff --git a/glyphs/letters-unified-basic.ptl b/glyphs/letters-unified-basic.ptl index a481dab..cc3f7a5 100644 --- a/glyphs/letters-unified-basic.ptl +++ b/glyphs/letters-unified-basic.ptl @@ -67,12 +67,17 @@ symbol-block 'i' set-anchor 'above' BASE (left + HALFSTROKE * HVCONTRAST + [linreg 18 0.25 126 0 STROKE] * TANSLANT * WIDTH) XH set-anchor 'below' BASE middle 0 - select-variant 'dotlessi' 0x131 [if para.isItalic 'italic' 'serifed'] + select-variant 'dotlessi' 0x131 [if para.isItalic 'italic' 'serifed'] { + .'cv03' 'dotlessi.serifed' + .'cv04' 'dotlessi.italic' + .'cv05' 'dotlessi.hooky' + .'cv06' 'dotlessi.zshaped' + } + create-glyph 'iogonek.dotless' : glyph-construction include glyphs.dotlessi AS_BASE include glyphs.ogonekBelow - create-glyph 'i' : glyph-construction set-width WIDTH assign-unicode 'i' @@ -291,7 +296,12 @@ symbol-block 'l' set-anchor 'below' BASE middle 0 set this.barx (left + HALFSTROKE) - select-variant 'l' 'l' [if para.isItalic 'italic' 'serifed'] + select-variant 'l' 'l' [if para.isItalic 'italic' 'serifed'] { + .'cv07' 'l.serifed' + .'cv08' 'l.italic' + .'cv09' 'l.hooky' + .'cv10' 'l.zshaped' + } alias 'palochka' 0x4CF 'l' turned 'turnl' 0xA781 'l' MIDDLE (XH / 2) pMarks @@ -526,13 +536,10 @@ symbol-block 'a' include : RightwardBottomSerif RIGHTSB 0 SIDEJUT tag-contour 'serifRB' - create-glyph 'a' : glyph-construction - set-width WIDTH - assign-unicode 'a' - - if (para.isItalic) - then : include glyphs.'a.italic' AS_BASE - else : include glyphs.'a.upright' AS_BASE + select-variant 'a' 'a' [if para.isItalic 'italic' 'upright'] { + .'cv01' 'a.upright' + .'cv02' 'a.italic' + } alias 'cyra' 0x430 'a' create-glyph 'scripta' : glyph-construction @@ -1687,7 +1694,10 @@ symbol-block 'g' include : RightwardTopSerif RIGHTSB XH SIDEJUT tag-contour 'serifRT' - select-variant 'g' 'g' 'doublestorey' + select-variant 'g' 'g' 'doublestorey' { + .cv11 'g.doublestorey' + .cv12 'g.singlestorey' + } alias 'scriptg' 0x261 'g.singlestorey' turned nothing 0x1D77 'g' MIDDLE [mix DESCENDER XH 0.5] diff --git a/glyphs/numbers.ptl b/glyphs/numbers.ptl index e11cbf2..b201685 100644 --- a/glyphs/numbers.ptl +++ b/glyphs/numbers.ptl @@ -21,7 +21,11 @@ symbol-block "Numbers" local radius : Math.min DOTRADIUS ((RIGHTSB - SB - STROKE * 2) / 4) include : Ring (CAPMIDDLE + radius) (CAPMIDDLE - radius) (MIDDLE + radius) (MIDDLE - radius) - select-variant 'zero' '0' 'slashed' + select-variant 'zero' '0' 'slashed' { + .cv13 'zero.slashed' + .cv14 'zero.dotted' + .cv15 'zero.unslashed' + } create-glyph 'one' : glyph-construction diff --git a/glyphs/symbol-punctuation.ptl b/glyphs/symbol-punctuation.ptl index 26c4c61..157f424 100644 --- a/glyphs/symbol-punctuation.ptl +++ b/glyphs/symbol-punctuation.ptl @@ -369,6 +369,8 @@ symbol-block 'Typographic Symbols' include : dispiro flat MIDDLE centery [widths fine fine] curl (MIDDLE + radius * s) (centery + radius * c) [widths final final] + + set currentGlyph.centery centery create-glyph 'numbersign' : glyph-construction set-width WIDTH assign-unicode '#' diff --git a/makefile b/makefile index 60e776d..36d702b 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,5 @@ default: fonts -OBJDIR = build include makesupport.mk PARAM_DEFAULT = FAST='$(FAST)' SUFFIX='$(SUFFIX)' VARIANTNAME='$(VARIANTNAME)' STYLE_COMMON='$(STYLE_COMMON)' STYLE_UPRIGHT='$(STYLE_UPRIGHT)' STYLE_ITALIC='$(STYLE_ITALIC)' VERSION='$(VERSION)' ARCPREFIX='$(ARCPREFIX)' PARAM_SLAB = FAST='$(FAST)' SUFFIX='$(SUFFIX)-slab' VARIANTNAME='$(VARIANTNAME)' STYLE_COMMON='$(STYLE_COMMON)' STYLE_SUFFIX='slab' STYLE_UPRIGHT='$(STYLE_UPRIGHT)' STYLE_ITALIC='$(STYLE_ITALIC)' VERSION='$(VERSION)' ARCPREFIX='$(ARCPREFIX)' @@ -14,20 +13,18 @@ test : test-default test-slab pages : pages-default pages-slab release : release-default release-slab -$(OBJDIR) : - @- mkdir $@ # svgs -svgs-default : $(SCRIPTS) | $(OBJDIR) +svgs-default : $(SCRIPTS) | $(OBJDIR) $(DISTDIR) @$(MAKE) -f onegroup.mk svgs $(PARAM_DEFAULT) -svgs-slab : $(SCRIPTS) | $(OBJDIR) +svgs-slab : $(SCRIPTS) | $(OBJDIR) $(DISTDIR) @$(MAKE) -f onegroup.mk svgs $(PARAM_SLAB) # ttfs -fonts-default : $(SCRIPTS) | $(OBJDIR) +fonts-default : $(SCRIPTS) | $(OBJDIR) $(DISTDIR) @$(MAKE) -f onegroup.mk fonts $(PARAM_DEFAULT) -fonts-slab : $(SCRIPTS) | $(OBJDIR) +fonts-slab : $(SCRIPTS) | $(OBJDIR) $(DISTDIR) @$(MAKE) -f onegroup.mk fonts $(PARAM_SLAB) diff --git a/makesupport.mk b/makesupport.mk index 2d45f4d..71edf6a 100644 --- a/makesupport.mk +++ b/makesupport.mk @@ -1,3 +1,11 @@ +OBJDIR = build +DISTDIR = dist + +$(OBJDIR) : + @- mkdir $@ +$(DISTDIR) : + @- mkdir $@ + PATELC = node ./node_modules/patel/bin/patel-c SUPPORT_FILES_FROM_aki = support/glyph.js support/spiroexpand.js support/spirokit.js parameters.js SUPPORT_FILES = $(SUPPORT_FILES_FROM_aki) support/point.js generator.js emptyfont.toml parameters.toml support/fairify.js diff --git a/onegroup.mk b/onegroup.mk index 0e478ab..d11c606 100644 --- a/onegroup.mk +++ b/onegroup.mk @@ -1,7 +1,6 @@ default: fonts TARGETUPM = 1000 -OBJDIR = build include makesupport.mk PREFIX = $(VARIANTNAME)iosevka$(SUFFIX) ARCPREFIXB = iosevka$(SUFFIX) @@ -38,7 +37,9 @@ PASS2 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass2-,$(TARGETS)) PASS3 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass3-,$(TARGETS)) PASS4 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass4-,$(TARGETS)) -fonts : $(TARGETS) +DISTTARGETS = $(subst $(OBJDIR)/,$(DISTDIR)/,$(TARGETS)) + +fonts : $(DISTTARGETS) svgs : $(SVG0) @@ -116,8 +117,8 @@ $(PASS4) : $(OBJDIR)/.pass4-%.ttf : pass4-finalize.js $(OBJDIR)/.pass3-%.ttf $(TARGETS) : $(OBJDIR)/%.ttf : $(OBJDIR)/.pass4-%.ttf ttfautohint $< $@ -$(OBJDIR) : - @- mkdir $@ +$(DISTTARGETS) : $(DISTDIR)/%.ttf : $(OBJDIR)/%.ttf + cp $< $@ # releaseing RELEASEDIR = releases diff --git a/parameters.toml b/parameters.toml index c7fa208..3c9a93a 100644 --- a/parameters.toml +++ b/parameters.toml @@ -63,6 +63,18 @@ lllcrowdedness = 3.33333333 [iosevka.variantSelector] +[iosevka.sscompose] +ss01 = ['cv04', 'cv07'] +ss02 = ['cv05', 'cv09'] +ss03 = ['cv06', 'cv10'] +ss04 = ['cv11'] +ss05 = ['cv12'] +ss06 = ['cv13'] +ss07 = ['cv14'] +ss08 = ['cv15'] +ss09 = ['cv16', 'cv18'] +ss10 = ['cv17', 'cv19'] + # Spacings [cjk] cjk = true diff --git a/pass4-finalize.js b/pass4-finalize.js index f0839cb..c799c3f 100644 --- a/pass4-finalize.js +++ b/pass4-finalize.js @@ -39,6 +39,7 @@ function writettf(ttf, file){ } var ttf = readttf(process.argv[2]); +delete ttf.FFTM // Fixes xAvgCharWidth var spacewidth = ttf.head.unitsPerEm / 2; for(var j = 0; j < ttf.glyf.length; j++) if(ttf.glyf[j] && ttf.glyf[j].unicode && ttf.glyf[j].unicode[0] === 0x20) {