diff --git a/Backers.md b/Backers.md index cf02e619f..885037c47 100644 --- a/Backers.md +++ b/Backers.md @@ -30,3 +30,4 @@ You can join them in supporting Iosevka development by [pledging on Patreon](htt - Beni Cherniavsky-Paskin - Bartłomiej T. Listwon - Will Binns-Smith +- Jeff S \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index 5239e12c2..9da444a65 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -5,7 +5,7 @@ The support code is licensed under Berkeley Software Distribution license. --- --- -Copyright (c) 2015-2017 Belleve Invis (belleve@typeof.net). +Copyright (c) 2015-2019 Belleve Invis (belleve@typeof.net). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. @@ -18,7 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND --- -Copyright 2015-2017, Belleve Invis (belleve@typeof.net). +Copyright 2015-2019, Belleve Invis (belleve@typeof.net). This Font Software is licensed under the SIL Open Font License, Version 1.1. diff --git a/README.md b/README.md index 7bfc33601..2c75225dd 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ Coders’ typeface, built from code. Quit your editor/program. Unzip and open the folder. -* **[Instructions for Windows](https://www.microsoft.com/en-us/Typography/TrueTypeInstall.aspx)** +* **Instructions for Windows**: Download the fonts from the [Releases](https://github.com/be5invis/Iosevka/releases), select the font files and right click, then hit "Install". + * On Windows 10 1809 or newer the default font installation is per-user, and it may cause compatibility issues for some applications, mostly written in Java. To cope with this, right click and select "Install for all users" instead. [Ref.](https://youtrack.jetbrains.com/issue/JRE-1166?p=IDEA-200145) * **[Instructions for macOS](http://support.apple.com/kb/HT2509)** * Standard distribution in Homebrew: `brew tap caskroom/fonts && brew cask install font-iosevka` (May be outdated). * Customizable install using Homebrew: see [robertgzr/homebrew-tap](https://github.com/robertgzr/homebrew-tap). @@ -90,13 +91,14 @@ Since version 2.0, Iosevka would no longer support building via `makefile`. To i oblique = "oblique" ``` -3. Run `npm run build -- contents:` and the built fonts would be available in `dist/`. Aside from `contents:`, other options are: +3. Run `npm run build -- contents::` and the built fonts would be avaliable in `dist/`. Aside from `contents::`, other options are: - 1. `contents:` : TTF (Hinted and Unhinted), WOFF(2) and Webfont CSS; - 2. `ttf:` : TTF; - 3. `ttf-unhinted:` : Unhinted TTF only; - 4. `woff:` : TTF and WOFF only; - 5. `woff2:` : TTF and WOFF2 only; + 1. `contents::` : TTF (Hinted and Unhinted), WOFF(2) and Webfont CSS; + 2. `ttf::` : TTF; + 3. `ttf-unhinted::` : Unhinted TTF only; + 4. `woff::` : TTF and WOFF only; + 5. `woff2::` : TTF and WOFF2 only; + - Note: Since version 2.2.0, we are using two colons (`::`) in the build target names. The current available styles for `design`/`upright`/`italic`/`oblique` options are: @@ -163,11 +165,16 @@ The current available styles for `design`/`upright`/`italic`/`oblique` options a * `v-l-italic` : Italic `l` (default for italic). * `v-l-tailed` : `l` with a curved tail. * `v-l-hookybottom` : `l` with a straight tail. + * `v-l-line` : `l` like a straight line. * Styles for letter `i`: * `v-i-hooky` : Hooky `i`. * `v-i-zshaped` : Z-shaped `i`. * `v-i-serifed` : Serifed `i` (default for upright and oblique). * `v-i-italic` : Italic `i` (default for italic). + * `v-i-line` : `i` like a straight line. + * Styles for letter `j`: + * `v-j-line`: `j` like a straight line. + * `v-j-serifed`: `j` with top serif (default). * Styles for letter `a`: * `v-a-doublestorey` : Double-storey `a` (default for upright and oblique). * `v-a-singlestorey` : Single-storey `a` (default for italic). @@ -205,12 +212,17 @@ The current available styles for `design`/`upright`/`italic`/`oblique` options a * `v-tilde-low` : Lower tilde `~` (default). * `v-asterisk-high` : Higher asterisk `*` (default). * `v-asterisk-low` : Lower asterisk `*`. + * `v-asterisk-hexhigh` : Higher six-pointed asterisk `*`. + * `v-asterisk-hexlow` : Lower six-pointed asterisk `*`. * `v-paragraph-high` : Higher paragraph symbol `¶` (default). * `v-paragraph-low` : Lower paragraph symbol `¶`. * `v-caret-high` : Higher circumflex `^` (default). * `v-caret-low` : Lower circumflex `^`. * `v-underscore-high` : Higher underscore `_` (default). * `v-underscore-low` : Lower underscore `_`. + * Styles for Percent (`%`): + * `v-percent-dots`: Percent `%`, Per-mille `‰` and basis point `‱` will use rectangular dots. + * `v-percent-rings`: Percent `%`, Per-mille `‰` and basis point `‱` will use rings (default). * Styles for At (`@`): * `v-at-long` : The long, three-fold At symbol in Iosevka 1.7.x. * `v-at-fourfold` : The traditional, four-fold At symbol. diff --git a/glyphs/autobuilds.ptl b/glyphs/autobuilds.ptl index 34c5441ac..b3d89fd45 100644 --- a/glyphs/autobuilds.ptl +++ b/glyphs/autobuilds.ptl @@ -1024,7 +1024,7 @@ export : define [apply] : begin set glyphList.length font.glyf.length for [local j 0] (j < font.glyf.length) [inc j] : set glyphList.(j) font.glyf.(j) - if (!recursive && (!para.noCJKV || para.makeFFXX) && para.spacing > 0) : do + if (!recursive && para.spacing > 0) : do define [createDoubleWidth records] : begin local scale : 1.25 / (WIDTH / 500) local pendingGlyphs : records.map : [record] => record.1 @@ -1042,12 +1042,17 @@ export : define [apply] : begin that-glyph.include : Translate (FULLWIDTH / 2 - this-glyph.advanceWidth / 2) 0 createDoubleWidth : let [a {}] : begin - foreach [j : range 1 0x5f] : if [not unicodeGlyphs.(0xff00 + j)] : a.push {(0xff00 + j) unicodeGlyphs.(0x20 + j).name} - if para.fullwidth_codes : foreach [j : items-of para.fullwidth_codes] : if (unicodeGlyphs.(j) && unicodeGlyphs.(j).advanceWidth < 1000) : begin - a.push {j unicodeGlyphs.(j).name} - a.push {0xFFE0 'cent'} - a.push {0xFFE1 'sterling'} - a.push {0xFFE5 'yen'} + if para.fullwidth_codes : foreach [j : items-of para.fullwidth_codes] : begin + if (unicodeGlyphs.(j) && unicodeGlyphs.(j).advanceWidth < 1000) : begin + a.push {j unicodeGlyphs.(j).name} + + if (!para.noCJKV || para.makeFFXX) : begin + foreach [j : range 1 0x5f] : begin + if [not unicodeGlyphs.(0xff00 + j)] : begin + a.push {(0xff00 + j) unicodeGlyphs.(0x20 + j).name} + a.push {0xFFE0 'cent'} + a.push {0xFFE1 'sterling'} + a.push {0xFFE5 'yen'} * a if para.stressFW : begin diff --git a/glyphs/common-shapes.ptl b/glyphs/common-shapes.ptl index 49e33023e..c0cfc30f3 100644 --- a/glyphs/common-shapes.ptl +++ b/glyphs/common-shapes.ptl @@ -18,13 +18,15 @@ export : define [apply] : begin set introduced true return : if introduced fs null - define [select-variant name unicode] : begin + define [select-variant name unicode altname altmap] : begin if (pickHash && [not pickHash.(name)]) : return nothing local variant : variantSelector.(name) || para.defaultVariant.(name) if [not variant] : begin throw : new Error "Variant for \(name) is not assigned." + if (altmap && altmap.(variant)) : set variant altmap.(variant) local chosenGlyph glyphs.((name + '.' + variant)) - create-glyph name : glyph-construction + + create-glyph [fallback altname name] : glyph-construction include chosenGlyph AS_BASE ALSO_METRICS if unicode : assign-unicode unicode set currentGlyph.featureSelector : queryFeatureSelector name para diff --git a/glyphs/letters-unified-basic.ptl b/glyphs/letters-unified-basic.ptl index 3041ce73b..2bbd4b734 100644 --- a/glyphs/letters-unified-basic.ptl +++ b/glyphs/letters-unified-basic.ptl @@ -83,6 +83,11 @@ export : define [apply] : begin include : RightwardBottomSerif MIDDLE 0 LONGJUT save 'dotlessi.zshaped' + sketch # dotlessi.line + include markset.e + include : VBar (MIDDLE) 0 XH + save 'dotlessi.line' + sketch # dotlessi.serifed include markset.e local balance IBALANCE @@ -202,6 +207,11 @@ export : define [apply] : begin save 'dotlessj.straight' + sketch # dotlessj.line + include markset.p + include : VBar MIDDLE DESCENDER XH + save 'dotlessj.line' + sketch # dotlessj.serifed include markset.p include glyphs.'dotlessj.straight' AS_BASE @@ -213,18 +223,15 @@ export : define [apply] : begin select-variant 'dotlessj' 0x237 - sketch # j - set-width WIDTH - - include glyphs.dotlessj AS_BASE - include glyphs.dotAbove - save 'j' 'j' - save 'grkj' 0x3F3 - save 'cyrje' 0x458 - + composite 'j' glyphs.dotlessj glyphs.dotAbove [into-unicode 'j'] if (glyphs.j && glyphs.dotlessj) : begin - composite 'j.straight' glyphs.'dotlessj.straight' glyphs.dotAbove - composite 'j.serifed' glyphs.'dotlessj.serifed' glyphs.dotAbove + local fs : queryFeatureSelector 'dotlessj' para + local fs_j : queryFeatureSelector 'dotlessj' para 'j' + foreach [{k gid} : pairs-of fs] : begin + composite fs_j.(k) glyphs.(gid) glyphs.dotAbove + set glyphs.j.featureSelector fs_j + alias "grkj" 0x3F3 'j' + alias "cyrje" 0x458 'j' sketch # jcurlytail include markset.p @@ -296,11 +303,6 @@ export : define [apply] : begin save 'smcpL' 0x29F ### l - create-glyph 'l.straight' : glyph-construction - include markset.b - set currentGlyph.cmpPriority (-2) - include : VBar MIDDLE 0 CAP - sketch # l.hooky include markset.b local middle : MIDDLE + LBALANCE2 @@ -320,6 +322,12 @@ export : define [apply] : begin save 'l.zshaped' + sketch # l.line + include markset.b + include : VBar MIDDLE 0 (CAP * 0.6) + include : VBar MIDDLE (CAP * 0.4) CAP + save 'l.line' + sketch # l.serifed include markset.b include : VBar (MIDDLE + LBALANCE) 0 CAP @@ -671,10 +679,16 @@ export : define [apply] : begin local div : fallback _div 1 local rightSB : WIDTH * div - SB local middle : MIDDLE * div - local fine : if barStraight + local fineOuter : if barStraight adviceBlackness WShape.fineS div - [adviceBlackness WShape.fine div] / WShape.fineOffset - local fineOffset : fine / 2 * HVCONTRAST * WShape.fineOffset + adviceBlackness WShape.fineOuter div + local fineInner : if barStraight + adviceBlackness WShape.fineS div + adviceBlackness WShape.fineInner div + local fineHeight : (fineOuter + fineInner) / 2 + + local fineOffsetOuter : fineOuter / 2 * HVCONTRAST * [if barStraight WShape.fineOffsetS WShape.fineOffset] + local fineOffsetInner : fineInner / 2 * HVCONTRAST * [if barStraight WShape.fineOffsetS WShape.fineOffset] local m1 : WIDTH * div * [if barStraight WShape.m1S WShape.m1] + [if barStraight O 0] local m2 : WIDTH * div * [if barStraight WShape.m2S WShape.m2] - [if barStraight O 0] local wheight : if barStraight top (top * 0.6) @@ -683,58 +697,73 @@ export : define [apply] : begin include : dispiro widths.lhs flat (SB + O * 2) top [heading DOWNWARD] - g4 (m1 - fineOffset) 0 [widths.lhs fine] + g4 (m1 - fineOffsetOuter) 0 [widths.lhs fineOuter] : else : begin include : dispiro widths.lhs flat SB top [heading DOWNWARD] curl SB (top * 0.75) [heading DOWNWARD] quadcontrols 0 0.3 6 unimportant - g4 (m1 - fineOffset) 0 [widths.lhs fine] + g4 (m1 - fineOffsetOuter) 0 [widths.lhs fineOuter] # bottom cap 1 - start-from (m1 + fineOffset) 0 - line-to (m1 - fineOffset) 0 - line-to m1 fine + start-from (m1 + fineOffsetInner) 0 + line-to (m1 - fineOffsetOuter) 0 + line-to m1 fineHeight - include : dispiro - widths.lhs fine - flat (middle - fineOffset) wheight - #quadcontrols 0 0.1 6 unimportant - g4 (m1 + fineOffset) 0 [widths.rhs fine] - include : dispiro - widths.rhs fine - flat (middle + fineOffset) wheight - #quadcontrols 0 0.1 6 unimportant - curl (m2 - fineOffset) 0 [widths.lhs fine] + include : difference + union + dispiro + widths.lhs fineInner + flat (middle - fineOffsetInner) wheight + #quadcontrols 0 0.1 6 unimportant + g4 (m1 + fineOffsetInner) 0 [widths.rhs fineInner] + dispiro + widths.rhs fineInner + flat (middle + fineOffsetInner) wheight + #quadcontrols 0 0.1 6 unimportant + curl (m2 - fineOffsetInner) 0 [widths.lhs fineInner] + union + spiro-outline + corner 0 0 + corner (WIDTH * div) 0 + corner (WIDTH * div) (-WIDTH * div) + corner 0 (-WIDTH * div) + spiro-outline + corner 0 wheight + corner (WIDTH * div) wheight + corner (WIDTH * div) (wheight + WIDTH * div) + corner 0 (wheight + WIDTH * div) # middle cap - start-from (middle + fineOffset) wheight - line-to middle (wheight - fine) - line-to (middle - fineOffset) wheight + start-from (middle + fineOffsetInner) wheight + line-to middle (wheight - fineHeight) + line-to (middle - fineOffsetInner) wheight # bottom cap 2 - start-from (m2 + fineOffset) 0 - line-to (m2 - fineOffset) 0 - line-to m2 fine + start-from (m2 + fineOffsetOuter) 0 + line-to (m2 - fineOffsetInner) 0 + line-to m2 fineHeight if barStraight : begin include : dispiro widths.rhs flat (rightSB - O * 2) top [heading DOWNWARD] - g4 (m2 + fineOffset) 0 [widths.rhs fine] + g4 (m2 + fineOffsetOuter) 0 [widths.rhs fineOuter] : else : begin include : dispiro widths.rhs flat rightSB top [heading DOWNWARD] curl rightSB (top * 0.75) [heading DOWNWARD] quadcontrols 0 0.3 6 unimportant - g4 (m2 + fineOffset) 0 [widths.rhs fine] + g4 (m2 + fineOffsetOuter) 0 [widths.rhs fineOuter] include : AIVSerifs top SB rightSB - set WShape.fine 5.5 + set WShape.fineOuter 5 + set WShape.fineInner 6 set WShape.fineS 5.5 - set WShape.fineOffset 1.375 + set WShape.fineOffset 1.5 + set WShape.fineOffsetS 1.375 set WShape.m1 0.325 set WShape.m2 0.675 set WShape.m1S 0.30 @@ -758,10 +787,10 @@ export : define [apply] : begin define [WHooktopShape top barStraight _div] : glyph-construction local div : fallback _div 1 - local fine : if barStraight + local fineOuter : if barStraight adviceBlackness WShape.fineS div - [adviceBlackness WShape.fine div] / WShape.fineOffset - local fineOffset : fine / 2 * HVCONTRAST * WShape.fineOffset + adviceBlackness WShape.fineOuter div + local fineOffsetOuter : fineOuter / 2 * HVCONTRAST * [if barStraight WShape.fineOffsetS WShape.fineOffset] local rightSB : WIDTH * div - SB local m2 : WIDTH * div * [if barStraight WShape.m2S WShape.m2] - [if barStraight O 0] @@ -778,7 +807,7 @@ export : define [apply] : begin widths.rhs straight.down.start rightSB (top - HOOK) [heading DOWNWARD] quadcontrols 0 0.3 6 unimportant g2 - g4 (m2 + fineOffset) 0 [widths.rhs fine] + g4 (m2 + fineOffsetOuter) 0 [widths.rhs fineOuter] include : VerticalHook (rightSB - HALFSTROKE * HVCONTRAST) (top - HOOK) (HOOKX * 0.65) (-HOOK + HALFSTROKE) @@ -2773,7 +2802,7 @@ export : define [apply] : begin include : VerticalHook MIDDLE 0 LONGJUT HOOK save 'iviby' 0x285 - define fbar : XH * 0.91 + STROKE * 0.25 + define fbar : XH * para.fbarpos + STROKE * para.fbarStrokeAdj sketch # f.straight local fovershoot2 (O * 2) include markset.b diff --git a/glyphs/symbol-geometric.ptl b/glyphs/symbol-geometric.ptl index 57ebd2a1f..578fecb1e 100644 --- a/glyphs/symbol-geometric.ptl +++ b/glyphs/symbol-geometric.ptl @@ -369,7 +369,8 @@ export : define [apply] : begin define [hollowScale w d s] : (w - [fallback s GEOMETRYSTROKE] * [fallback d : WIDTH / shapeWidth]) / w - define [hollow newid unicode oldid zx zy cx cy] : sketch + define [hollow newid unicode oldid zx zy cx cy] : create-glyph newid : glyph-construction + depends-on glyphs.(oldid) local isWide : glyphs.(oldid).advanceWidth > WIDTH local zoom : hollowScale squareRadius (WIDTH / glyphs.(oldid).advanceWidth) include : difference @@ -381,9 +382,10 @@ export : define [apply] : begin if isWide : include UnFullWidthify include : FlipAround [fallback cx MIDDLE] [fallback cy symbolMid] [fallback zx zoom] [fallback zy zx zoom] if isWide : include FullWidthify - save newid unicode + include : into-unicode unicode - define [hollowWithCenter newid unicode oldid zx zy cx cy] : sketch + define [hollowWithCenter newid unicode oldid zx zy cx cy] : create-glyph newid : glyph-construction + depends-on glyphs.(oldid) local isWide : glyphs.(oldid).advanceWidth > WIDTH local zoom : hollowScale squareRadius (WIDTH / glyphs.(oldid).advanceWidth) local zx1 : mix [fallback zx zoom] 1 0.25 @@ -404,8 +406,10 @@ export : define [apply] : begin if isWide : include UnFullWidthify include : FlipAround [fallback cx MIDDLE] [fallback cy symbolMid] zx2 zy2 if isWide : include FullWidthify - save newid unicode - define [doubleHollow newid unicode oldid zx zy cx cy] : sketch + include : into-unicode unicode + + define [doubleHollow newid unicode oldid zx zy cx cy] : create-glyph newid : glyph-construction + depends-on glyphs.(oldid) local isWide : glyphs.(oldid).advanceWidth > WIDTH local zoom : hollowScale squareRadius (WIDTH / glyphs.(oldid).advanceWidth) local zx1 : mix [fallback zx zoom] 1 0.25 @@ -433,9 +437,9 @@ export : define [apply] : begin if isWide : include UnFullWidthify include : FlipAround [fallback cx MIDDLE] [fallback cy symbolMid] zx3 zy3 if isWide : include FullWidthify - save newid unicode + include : into-unicode unicode - define [resized newid unicode id x y s sy] : sketch + define [resized newid unicode id x y s sy] : create-glyph newid : glyph-construction include glyphs.(id) AS_BASE include UnFullWidthify include : FlipAround x y s [fallback sy s] diff --git a/glyphs/symbol-punctuation.ptl b/glyphs/symbol-punctuation.ptl index 713a9bc7d..e912d0165 100644 --- a/glyphs/symbol-punctuation.ptl +++ b/glyphs/symbol-punctuation.ptl @@ -525,27 +525,33 @@ export : define [apply] : begin do "Asterisk" local asteriskCenterY : parenTop - LONGJUT * 1.5 - local asteriskKinds {{1.2 STROKE 'asterisk'} {0.85 STROKE 'smallasterisk'} {1 GEOMETRYSTROKE 'opAsterisk'}} - foreach [{size stroke name} : items-of asteriskKinds] : begin + local asteriskKinds : list + list 5 1.2 STROKE 'asterisk' 'high' 'low' + list 5 0.85 STROKE 'smallasterisk' 'high' 'low' + list 5 1 GEOMETRYSTROKE 'opAsterisk' 'high' 'low' + list 6 1.2 STROKE 'asterisk' 'hexhigh' 'hexlow' + foreach [{sides size stroke name high low} : items-of asteriskKinds] : begin sketch local radius : LONGJUT * size local fine : stroke * 0.4 - local final : 0.5 * [Math.min stroke (radius * Math.PI * 2 / 10)] + local final : 0.5 * [Math.min stroke (radius * Math.PI / sides)] - foreach j [range 0 5] : begin - local s : Math.sin (j / 5 * Math.PI * 2) - local c : Math.cos (j / 5 * Math.PI * 2) + foreach j [range 0 sides] : begin + local s : Math.sin (j / sides * Math.PI * 2) + local c : Math.cos (j / sides * Math.PI * 2) include : dispiro flat MIDDLE asteriskCenterY [widths fine fine] curl (MIDDLE + radius * s) (asteriskCenterY + radius * c) [widths final final] - save (name + '.high') - composite (name + '.low') glyphs.(name + '.high') + save (name + '.' + high) + + composite (name + '.' + low) glyphs.(name + '.' + high) Upright Translate 0 (symbolMid - asteriskCenterY) begin markset.plus Italify select-variant 'asterisk' '*' + select-variant 'asterisk' nothing 'asterisk.dfltlow' {.high 'low' .hexhigh 'hexlow'} do "Slashes and numbersign" define slashDefautLeft : SB + HALFSTROKE @@ -919,7 +925,7 @@ export : define [apply] : begin save 'ellipsis' 0x2026 do 'Percentages' - sketch # percent + sketch # percent.dots set-width WIDTH local dotwidth ([adviceBlackness 4] * 1.5) local cor : HVCONTRAST / [Math.sqrt (1 - [Math.pow ((RIGHTSB - SB - STROKE) / (CAP - 0)) 2])] @@ -931,7 +937,7 @@ export : define [apply] : begin include : VBarLeft SB [mix CAP 0 0.3] CAP dotwidth include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotwidth - save 'percent' '%' + save 'percent.dots' sketch # permille local dotwidth ([adviceBlackness 4] * 1.5) @@ -944,7 +950,7 @@ export : define [apply] : begin include : VBarLeft [mix SB RIGHTSB 0.075] [mix CAP 0 0.3] CAP dotwidth include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotwidth include : VBarRight (RIGHTSB - [Math.max (WIDTH * 0.25) (dotwidth * 1.5)]) 0 [mix 0 CAP 0.3] dotwidth - save 'permille' 0x2030 + save 'permille.dots' sketch # basepoint local dotwidth ([adviceBlackness 4] * 1.5) @@ -959,7 +965,89 @@ export : define [apply] : begin include : VBarRight RIGHTSB 0 [mix 0 CAP 0.3] dotfine include : VBar [mix [mix SB RIGHTSB 0.1] RIGHTSB 0.5] 0 [mix 0 CAP 0.3] dotfine include : VBarLeft [mix SB RIGHTSB 0.1] 0 [mix 0 CAP 0.3] dotfine - save 'basepoint' 0x2031 + save 'basepoint.dots' + + sketch # percent.rings + set-width WIDTH + local l : SB / 2 + local r : WIDTH - l + local m : mix l r (1 / 2) + local sma : SMOOTHA * 0.5 + local smb : SMOOTHB * 0.5 + local sw : adviceBlackness 4 + local fine : adviceBlackness 5 + local cor : HVCONTRAST / [Math.sqrt (1 - [Math.pow ((r - l - sw) / (CAP - 0)) 2])] + local pTerm : (fine / 2) / [Math.hypot CAP (r - l)] + local pFine : 1 / 2 - [Math.max (CAP / 10) (STROKE / 2)] / [Math.hypot CAP (r - l)] + + include : OShape CAP (CAP / 2) l m sw sma smb + include : OShape (CAP / 2) 0 m r sw sma smb + + include : dispiro + widths.rhs (sw * cor) + flat r CAP [heading DOWNWARD] + curl [mix r l pFine] [mix CAP 0 pFine] [widths.heading (fine * cor) 0 DOWNWARD] + + include : dispiro + widths.rhs (sw * cor) + flat l 0 [heading UPWARD] + curl [mix l r pFine] [mix 0 CAP pFine] [widths.heading (fine * cor) 0 UPWARD] + save 'percent.rings' + + sketch # permille.rings, basepoint.rings + set-width WIDTH + local l : SB / 2 + local r : WIDTH - l + local m : mix l r (1 / 2) + local sma : SMOOTHA * 0.5 + local smb : SMOOTHB * 0.5 + local sw : adviceBlackness 4 + local fine : adviceBlackness 5 + local cor : HVCONTRAST / [Math.sqrt (1 - [Math.pow ((r - l - sw) / (CAP - 0)) 2])] + local pTerm : (fine / 2) / [Math.hypot CAP (r - l)] + local pFine : 1 / 2 - (STROKE / 2) / [Math.hypot CAP (r - l)] + + local otop : CAP / 2 - [Math.max (CAP / 5) (fine * 2)] / 2 + local coOtop : CAP - otop + + include : OShape CAP (CAP - otop) l m sw sma smb + + include : dispiro + flat l [mix otop coOtop 0.3] [widths.center fine] + curl r (CAP - otop) [widths.center sw] + + # bottom row + branch + local l1 : l - O + local r2 r + local gap : SB / 2 - O * 2 + local fill : ((r2 - l1) - gap) / 2 + local r1 : l1 + fill + local l2 : r1 + gap + local swp : adviceBlackness 4 + include : OShape otop 0 l1 r1 swp sma smb + include : OShape otop 0 l2 r2 swp sma smb + save 'permille.rings' + branch + local l1 : l - O + local r3 r + local gap : SB / 2 - O + local fill : ((r3 - l1) - 2 * gap) / 3 + local r1 : l1 + fill + local l2 : r1 + gap + local r2 : l2 + fill + local l3 : r2 + gap + local swp : adviceBlackness 6 + local smap : SMOOTHA * (1/3) + local smbp : SMOOTHB * (1/3) + include : OShape otop 0 l1 r1 swp smap smbp + include : OShape otop 0 l2 r2 swp smap smbp + include : OShape otop 0 l3 r3 swp smap smbp + save 'basepoint.rings' + + select-variant 'percent' '%' + select-variant 'permille' 0x2030 + select-variant 'basepoint' 0x2031 do "ASCII Marks" local MarkZoom : glyph-construction diff --git a/images/charvars.png b/images/charvars.png index c139503ce..dfdddad67 100644 Binary files a/images/charvars.png and b/images/charvars.png differ diff --git a/images/download-options.png b/images/download-options.png index cbc4972b7..8b28374af 100644 Binary files a/images/download-options.png and b/images/download-options.png differ diff --git a/images/family.png b/images/family.png index 0fe2f4fa7..b5d176a5d 100644 Binary files a/images/family.png and b/images/family.png differ diff --git a/images/languages.png b/images/languages.png index ff137631a..798a0096e 100644 Binary files a/images/languages.png and b/images/languages.png differ diff --git a/images/ligations.png b/images/ligations.png index 93eb67478..786d9f2dc 100644 Binary files a/images/ligations.png and b/images/ligations.png differ diff --git a/images/matrix.png b/images/matrix.png index c2bd7fbd3..0f8ef3350 100644 Binary files a/images/matrix.png and b/images/matrix.png differ diff --git a/images/preview-all.png b/images/preview-all.png index 7f141ea88..3a646d6dc 100644 Binary files a/images/preview-all.png and b/images/preview-all.png differ diff --git a/images/stylesets.png b/images/stylesets.png index 38265dcf3..117616885 100644 Binary files a/images/stylesets.png and b/images/stylesets.png differ diff --git a/images/variants.png b/images/variants.png index 8f67d4cfd..365570fba 100644 Binary files a/images/variants.png and b/images/variants.png differ diff --git a/images/weights.png b/images/weights.png index e14b6da08..58778717f 100644 Binary files a/images/weights.png and b/images/weights.png differ diff --git a/meta/feature/ligation.ptl b/meta/feature/ligation.ptl index 4857a0dcb..f1614e881 100644 --- a/meta/feature/ligation.ptl +++ b/meta/feature/ligation.ptl @@ -45,7 +45,7 @@ local [acskip] { 'slash' 'bar' 'at' 'ampersand' 'percent' 'numbersign' 'numbersign.upright' 'numbersign.slanted' } -local [asterisk_center] ({'asterisk' 'asterisk.high' 'asterisk.low'} ~> {'asterisk.low' 'asterisk.low' 'asterisk.low'}) +local [asterisk_center] ({'asterisk' 'asterisk.high' 'asterisk.low' 'asterisk.hexhigh' 'asterisk.hexlow'} ~> {'asterisk.dfltlow' 'asterisk.low' 'asterisk.low' 'asterisk.hexlow' 'asterisk.hexlow'}) local [colon_center] ({'colon' 'colon.mid'} ~> {'colon.mid' 'colon.mid'}) local [caret_center] ({'asciicaret' 'asciicaret.high' 'asciicaret.low'} ~> {'asciicaret.low' 'asciicaret.low' 'asciicaret.low'}) local [tilde_center] ({'asciitilde' 'asciitilde.high' 'asciitilde.low'} ~> {'asciitilde.low' 'asciitilde.low' 'asciitilde.low'}) diff --git a/package.json b/package.json index d97930f43..582d76019 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iosevka", - "version": "2.1.0", + "version": "2.2.0", "main": "./generate.js", "engines": { "node": ">=8.4.0" @@ -24,7 +24,7 @@ "ttf2woff": "^2.0.1", "ttf2woff2": "^2.0.3", "unorm": "^1.4.1", - "verda": "^0.2.0", + "verda": "^1.0.0-0", "yargs": "^12.0.0" }, "devDependencies": { diff --git a/parameters.toml b/parameters.toml index cd1bdad2c..6d058b670 100644 --- a/parameters.toml +++ b/parameters.toml @@ -1,5 +1,5 @@ [iosevka] -copyright = 'Copyright (c) 2015-2017 Belleve Invis.' +copyright = 'Copyright (c) 2015-2019 Belleve Invis.' licence = '''This font software is licenced under the SIL Open Font Licence, Version 1.1. This is licence is avaliable with a FAQ at: http://scripts.sil.org/OFL. This font software is distributes on an 'AS IS' basis, without warranties or conditions of any kind, either express or implied. See the SIL Open Font licence fot the specific language, premissions and limitations governing your use of this font software.''' manufacturer = 'Belleve Invis' designer = 'Belleve Invis' @@ -39,12 +39,14 @@ smallsmooth = 220 # Vertical arc size in lowercase letters. smoothadjust = 120 # Parameter to balance arcs in slanted shapes. superness = 2.2 # Superness of arcs. -barpos = 0.525 # Position of the middle bar in most letters, like `E`. -overlaypos = 0.52 # Position of the overlay mark. -ebarpos = 0.50 # Position of the middle bar in `e`. +barpos = 0.525 # Position of the middle bar in most letters, like `E`. +overlaypos = 0.52 # Position of the overlay mark. +ebarpos = 0.50 # Position of the middle bar in `e`. gbarpos = 0.42 pbarpos = 0.53 fivebarpos = 0.64 +fbarpos = 0.91 # Position of the middle bar in `f` +fbarStrokeAdj = 0.25 # Portion of the fill above the f-bar position hook = 155 # Hook depth in most letters. ahook = 130 diff --git a/snapshot/index.html b/snapshot/index.html index ac920c261..ffcd5ce76 100644 --- a/snapshot/index.html +++ b/snapshot/index.html @@ -239,6 +239,30 @@
  • cv55 $$ +
  • + cv56 + ii +
  • + cv57 + jj +
  • + cv58 + jj +
  • + cv59 + ll +
  • + cv60 + ** +
  • + cv61 + ** +
  • + cv62 + %% +
  • + cv63 + %%
  • diff --git a/utility/ttf-to-woff.js b/utility/ttf-to-woff.js index b344ae143..40f5cadec 100644 --- a/utility/ttf-to-woff.js +++ b/utility/ttf-to-woff.js @@ -4,7 +4,7 @@ const ttf2woff = require("ttf2woff"); module.exports = function(from, to) { const input = fs.readFileSync(from); - var ttf = new Uint8Array(input); - var woff = new Buffer(ttf2woff(ttf, {}).buffer); + const ttf = new Uint8Array(input); + const woff = Buffer.from(ttf2woff(ttf, {}).buffer); fs.writeFileSync(to, woff); }; diff --git a/utility/ttf-to-woff2.js b/utility/ttf-to-woff2.js index a154f5cb2..dd65f0897 100644 --- a/utility/ttf-to-woff2.js +++ b/utility/ttf-to-woff2.js @@ -4,6 +4,6 @@ const ttf2woff2 = require("ttf2woff2"); module.exports = function(from, to) { const input = fs.readFileSync(from); - var woff = ttf2woff2(input); + const woff = ttf2woff2(input); fs.writeFileSync(to, woff); }; diff --git a/variants.toml b/variants.toml index 965a3acdd..2c385ded1 100644 --- a/variants.toml +++ b/variants.toml @@ -223,10 +223,45 @@ tag = "cv54" dollar = "throughcap" tag = "cv55" +[simple.v-i-line] +dotlessi = "line" +tag = "cv56" + +[simple.v-j-line] +dotlessj = "line" +tag = "cv57" + +[simple.v-j-serifed] +dotlessj = "serifed" +tag = "cv58" + +[simple.v-l-line] +l = "line" +tag = "cv59" + +[simple.v-asterisk-hexhigh] +asterisk = "hexhigh" +tag = "cv60" + +[simple.v-asterisk-hexlow] +asterisk = "hexlow" +tag = "cv61" + +[simple.v-percent-dots] +percent = "dots" +permille = "dots" +basepoint = "dots" +tag = "cv62" + +[simple.v-percent-rings] +percent = "rings" +permille = "rings" +basepoint = "rings" +tag = "cv63" + [simple.others] I = 'serifed' J = 'serifed' -dotlessj = 'serifed' [default] design = [ @@ -246,11 +281,13 @@ design = [ 'v-numbersign-upright', 'v-three-twoarcs', 'v-one-hooky', + 'v-percent-rings', 'others' ] upright = [ 'v-a-doublestorey', 'v-i-serifed', + 'v-j-serifed', 'v-l-serifed', 'v-g-doublestorey', 'v-y-straight', @@ -259,6 +296,7 @@ upright = [ italic = [ 'v-a-singlestorey', 'v-i-italic', + 'v-j-serifed', 'v-l-italic', 'v-g-singlestorey', 'v-y-curly', @@ -271,19 +309,19 @@ design = ['v-one-serifed'] # Composite character options, overrides default settings above. # Andale Mono Style [composite.ss01] -design = ['v-i-hooky', 'v-a-doublestorey', 'v-l-zshaped', 'v-at-fourfold', 'v-zero-dotted', 'v-g-doublestorey', 'v-brace-straight', 'v-underscore-low', 'v-numbersign-slanted'] +design = ['v-i-hooky', 'v-a-doublestorey', 'v-l-zshaped', 'v-at-fourfold', 'v-zero-dotted', 'v-g-doublestorey', 'v-brace-straight', 'v-underscore-low', 'v-numbersign-slanted', 'v-asterisk-hexhigh'] # Anonymous Pro Style [composite.ss02] -design = ['v-at-fourfold', 'v-a-doublestorey', 'v-asterisk-low', 'v-brace-straight', 'v-g-singlestorey', 'v-l-serifed', 'v-i-serifed'] +design = ['v-at-fourfold', 'v-a-doublestorey', 'v-brace-straight', 'v-g-singlestorey', 'v-l-serifed', 'v-i-serifed', 'v-asterisk-hexlow'] # Consolas Style [composite.ss03] -design = ['v-at-fourfold', 'v-underscore-low', 'v-brace-straight', 'v-numbersign-slanted'] +design = ['v-at-fourfold', 'v-underscore-low', 'v-brace-straight', 'v-numbersign-slanted', 'v-asterisk-hexhigh'] # Menlo Style [composite.ss04] -design = ['v-at-long', 'v-a-doublestorey', 'v-underscore-low', 'v-g-singlestorey', 'v-i-serifed', 'v-l-italic', 'v-brace-straight', 'v-asterisk-low', 'v-numbersign-slanted'] +design = ['v-at-long', 'v-a-doublestorey', 'v-underscore-low', 'v-g-singlestorey', 'v-i-serifed', 'v-l-italic', 'v-brace-straight', 'v-numbersign-slanted', 'v-asterisk-hexlow'] # Fira Mono Style [composite.ss05] @@ -295,11 +333,11 @@ design = ['v-at-fourfold', 'v-a-doublestorey', 'v-i-serifed', 'v-l-serifed', 'v- # Monaco Style [composite.ss07] -design = ['v-at-fourfold', 'v-a-singlestorey', 'v-i-zshaped', 'v-g-singlestorey', 'v-l-zshaped', 'v-brace-straight', 'v-numbersign-slanted'] +design = ['v-at-fourfold', 'v-a-singlestorey', 'v-i-zshaped', 'v-g-singlestorey', 'v-l-zshaped', 'v-brace-straight', 'v-numbersign-slanted', 'v-asterisk-hexhigh'] # Pragmata Pro Style [composite.ss08] -design = ['v-at-long', 'v-a-doublestorey', 'v-l-serifed', 'v-i-serifed', 'v-asterisk-low', 'v-zero-dotted', 'v-brace-straight', 'v-dollar-open', 'v-underscore-low', 'v-numbersign-slanted'] +design = ['v-at-long', 'v-a-doublestorey', 'v-l-serifed', 'v-i-serifed', 'v-asterisk-low', 'v-zero-dotted', 'v-brace-straight', 'v-dollar-open', 'v-underscore-low', 'v-numbersign-slanted', 'v-percent-dots'] # Source Code Pro Style [composite.ss09] diff --git a/verdafile.js b/verdafile.js index 68c590e30..9f7fdab1b 100644 --- a/verdafile.js +++ b/verdafile.js @@ -1,13 +1,13 @@ "use strict"; -const { - want, - rule: { task, file, oracle, phony }, - macro: { FileList }, - action: { run, node, cd, cp, rm }, - journal, - argv -} = require("verda"); +const build = require("verda").create(); +const { task, tasks, file, files, oracle, oracles, computed, computes, phony } = build.ruleTypes; +const { de, fu } = build.rules; +const { run, node, cd, cp, rm } = build.actions; +const { FileList } = build.predefinedFuncs; +module.exports = build; + +/////////////////////////////////////////////////////////// const fs = require("fs"); const path = require("path"); @@ -21,23 +21,31 @@ const PATEL_C = ["node", "./node_modules/patel/bin/patel-c"]; const GENERATE = ["node", "gen/generator"]; const webfontFormats = [["woff2", "woff2"], ["woff", "woff"], ["ttf", "truetype"]]; -const BUILD_PLANS = path.resolve(__dirname, "./build-plans.toml"); -const PRIVATE_BUILD_PLANS = path.resolve(__dirname, "./private-build-plans.toml"); +const BUILD_PLANS = path.relative(__dirname, path.resolve(__dirname, "./build-plans.toml")); +const PRIVATE_BUILD_PLANS = path.relative( + __dirname, + path.resolve(__dirname, "./private-build-plans.toml") +); // Save journal to build/ -journal(`${BUILD}/.verda-journal`); -want(...argv._); +build.setJournal(`${BUILD}/.verda-build-journal`); +build.setSelfTracking(); /////////////////////////////////////////////////////////// ////// Oracles ////// /////////////////////////////////////////////////////////// -oracle(`o:version`).def(async () => { +const Version = oracle(`version`, async () => { const package_json = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"))); return package_json.version; }); -oracle(`o:raw-plans`).def(async () => { +const RawPlans = oracle(`raw-plans`, async target => { + await target.need(fu(BUILD_PLANS)); + if (fs.existsSync(PRIVATE_BUILD_PLANS)) { + await target.need(fu(PRIVATE_BUILD_PLANS)); + } + const t = toml.parse(fs.readFileSync(BUILD_PLANS, "utf-8")); if (fs.existsSync(PRIVATE_BUILD_PLANS)) { Object.assign( @@ -67,24 +75,24 @@ oracle(`o:raw-plans`).def(async () => { return t; }); -oracle("o:build-plans").def(async target => { - const [rp] = await target.need(`o:raw-plans`); +const BuildPlans = computed("build-plans", async target => { + const [rp] = await target.need(RawPlans); return rp.buildPlans; }); -oracle("o:export-plans").def(async target => { - const [rp] = await target.need(`o:raw-plans`); +const ExportPlans = computed("export-plans", async target => { + const [rp] = await target.need(RawPlans); return rp.exportPlans; }); -oracle("o:raw-collect-plans").def(async target => { - const [rp] = await target.need(`o:raw-plans`); +const RawCollectPlans = computed("raw-collect-plans", async target => { + const [rp] = await target.need(RawPlans); return rp.collectPlans; }); -oracle("o:weights").def(async target => { - const [rp] = await target.need(`o:raw-plans`); +const Weights = computed("weights", async target => { + const [rp] = await target.need(RawPlans); return rp.weights; }); -oracle("o:slants").def(async target => { - const [rp] = await target.need(`o:raw-plans`); +const Slants = computed("slants", async target => { + const [rp] = await target.need(RawPlans); return rp.slants; }); @@ -109,16 +117,16 @@ function getSuffixSet(weights, slants) { return mapping; } -oracle(`o:suffixes`).def(async target => { - const [weights, slants] = await target.need(`o:weights`, `o:slants`); +const Suffixes = computed(`suffixes`, async target => { + const [weights, slants] = await target.need(Weights, Slants); return getSuffixSet(weights, slants); }); -oracle(`o:font-building-parameters`).def(async target => { +const FontBuildingParameters = computed(`font-building-parameters`, async target => { const [buildPlans, defaultWeights, defaultSlants] = await target.need( - `o:build-plans`, - `o:weights`, - `o:slants` + BuildPlans, + Weights, + Slants ); const fontInfos = {}; const bp = {}; @@ -152,8 +160,8 @@ oracle(`o:font-building-parameters`).def(async target => { return { fontInfos, buildPlans: bp }; }); -oracle(`o:collect-plans`).def(async target => { - const [rawCollectPlans, suffixMapping] = await target.need(`o:raw-collect-plans`, `o:suffixes`); +const CollectPlans = computed(`collect-plans`, async target => { + const [rawCollectPlans, suffixMapping] = await target.need(RawCollectPlans, Suffixes); const composition = {}, groups = {}; for (const gid in rawCollectPlans) { @@ -174,23 +182,23 @@ oracle(`o:collect-plans`).def(async target => { return { composition, groups }; }); -oracle("hives-of:***").def(async (target, gid) => { - const [{ fontInfos }] = await target.need("o:font-building-parameters"); +const HivesOf = computes.group("hives-of", async (target, gid) => { + const [{ fontInfos }] = await target.need(FontBuildingParameters); return fontInfos[gid]; }); -oracle("group-info:***").def(async (target, gid) => { - const [{ buildPlans }] = await target.need("o:font-building-parameters"); +const GroupInfo = computes.group("group-info", async (target, gid) => { + const [{ buildPlans }] = await target.need(FontBuildingParameters); return buildPlans[gid]; }); -oracle("group-fonts-of:***").def(async (target, gid) => { - const [plan] = await target.need(`group-info:${gid}`); +const GroupFontsOf = computes.group("group-fonts-of", async (target, gid) => { + const [plan] = await target.need(GroupInfo(gid)); return plan.targets; }); -oracle("collection-parts-of:*").def(async (target, id) => { - const [{ composition }] = await target.need("o:collect-plans"); +const CollectionPartsOf = computes.group("collection-parts-of", async (target, id) => { + const [{ composition }] = await target.need(CollectPlans); return composition[id]; }); @@ -198,14 +206,15 @@ oracle("collection-parts-of:*").def(async (target, id) => { ////// Font Building ////// /////////////////////////////////////////////////////////// -file(`${BUILD}/*/*.ttf`).def(async (target, prefix, suffix) => { +const BuildTTF = files(`${BUILD}/*/*.ttf`, async (target, path) => { + const [, suffix] = path.$; const [{ hives, family, menuWeight, menuStyle }, version] = await target.need( - `hives-of:${suffix}`, - `o:version` + HivesOf(suffix), + Version ); - const otd = target.path.dir + "/" + target.path.name + ".otd"; - const charmap = target.path.dir + "/" + target.path.name + ".charmap"; - await target.need("scripts", "parameters.toml", `dir:${target.path.dir}`); + const otd = path.dir + "/" + path.name + ".otd"; + const charmap = path.dir + "/" + path.name + ".charmap"; + await target.need(Scripts, fu`parameters.toml`, de`${path.dir}`); await run( GENERATE, ["-o", otd], @@ -216,12 +225,11 @@ file(`${BUILD}/*/*.ttf`).def(async (target, prefix, suffix) => { ["--menu-slant", menuStyle], hives ); - await run("otfccbuild", otd, "-o", target.path.full, "-O3", "--keep-average-char-width"); + await run("otfccbuild", otd, "-o", path.full, "-O3", "--keep-average-char-width"); await rm(otd); }); - -file(`${BUILD}/*/*.charmap`).def(async target => { - await target.need(target.path.dir + "/" + target.path.name + ".ttf"); +const BuildCM = files(`${BUILD}/*/*.charmap`, async (target, path) => { + await target.need(BuildTTF(path.dir + "/" + path.name + ".ttf")); }); /////////////////////////////////////////////////////////// @@ -229,70 +237,72 @@ file(`${BUILD}/*/*.charmap`).def(async target => { /////////////////////////////////////////////////////////// // Per group file -file(`${DIST}/*/ttf-unhinted/*.ttf`).def(async (target, dir, file) => { - const [from] = await target.need(`${BUILD}/${dir}/${file}.ttf`, `dir:${target.path.dir}`); - await cp(from.full, target.path.full); +const DistUnhintedTTF = files(`${DIST}/*/ttf-unhinted/*.ttf`, async (target, path) => { + const [gr, f] = path.$; + const [from] = await target.need(BuildTTF`${BUILD}/${gr}/${f}.ttf`, de`${path.dir}`); + await cp(from.full, path.full); }); -file(`${DIST}/*/ttf/*.ttf`).def(async (target, dir, file) => { - const [from] = await target.need( - `${DIST}/${dir}/ttf-unhinted/${file}.ttf`, - `dir:${target.path.dir}` - ); - await run("ttfautohint", from.full, target.path.full); +const DistHintedTTF = files(`${DIST}/*/ttf/*.ttf`, async (target, path) => { + const [gr, f] = path.$; + const [from] = await target.need(BuildTTF`${BUILD}/${gr}/${f}.ttf`, de`${path.dir}`); + await run("ttfautohint", from.full, path.full); }); -file(`${DIST}/*/woff/*.woff`).def(async (target, dir, file) => { - const [from] = await target.need(`${DIST}/${dir}/ttf/${file}.ttf`, `dir:${target.path.dir}`); - await node(`utility/ttf-to-woff.js`, from.full, target.path.full); +const DistWoff = files(`${DIST}/*/woff/*.woff`, async (target, path) => { + const [group, f] = path.$; + const [from] = await target.need(DistHintedTTF`${DIST}/${group}/ttf/${f}.ttf`, de`${path.dir}`); + await node(`utility/ttf-to-woff.js`, from.full, path.full); }); -file(`${DIST}/*/woff2/*.woff2`).def(async (target, dir, file) => { - const [from] = await target.need(`${DIST}/${dir}/ttf/${file}.ttf`, `dir:${target.path.dir}`); - await node(`utility/ttf-to-woff2.js`, from.full, target.path.full); +const DistWoff2 = files(`${DIST}/*/woff2/*.woff2`, async (target, path) => { + const [group, f] = path.$; + const [from] = await target.need(DistHintedTTF`${DIST}/${group}/ttf/${f}.ttf`, de`${path.dir}`); + await node(`utility/ttf-to-woff2.js`, from.full, path.full); }); // TTC -file(`${DIST}/collections/*/*.ttc`).def(async (target, cid, fileName) => { - const [parts] = await target.need(`collection-parts-of:${fileName}`); - await target.need(`dir:${target.path.dir}`); - const [ttfs] = await target.need(parts.map(part => `${DIST}/${part.dir}/ttf/${part.file}.ttf`)); - await run(`otfcc-ttcize`, ttfs.map(p => p.full), "-o", target.path.full); +const DistTTC = files(`${DIST}/collections/*/*.ttc`, async (target, { full, dir, $: [, f] }) => { + const [parts] = await target.need(CollectionPartsOf(f)); + await target.need(de`${dir}`); + const [ttfs] = await target.need( + parts.map(part => DistHintedTTF`${DIST}/${part.dir}/ttf/${part.file}.ttf`) + ); + await run(`otfcc-ttcize`, ttfs.map(p => p.full), "-o", full); }); // Group-level -task("ttf:***").def(async (target, gid) => { - const [ts] = await target.need(`group-fonts-of:${gid}`); - await target.need(ts.map(tn => `${DIST}/${gid}/ttf/${tn}.ttf`)); +const GroupTTFs = tasks.group("ttf", async (target, gid) => { + const [ts] = await target.need(GroupFontsOf(gid)); + await target.need(ts.map(tn => DistHintedTTF`${DIST}/${gid}/ttf/${tn}.ttf`)); }); -task("ttf-unhinted:***").def(async (target, gid) => { - const [ts] = await target.need(`group-fonts-of:${gid}`); - await target.need(ts.map(tn => `${DIST}/${gid}/ttf-unhinted/${tn}.ttf`)); +const GroupUnhintedTTFs = tasks.group("ttf-unhinted", async (target, gid) => { + const [ts] = await target.need(GroupFontsOf(gid)); + await target.need(ts.map(tn => DistUnhintedTTF`${DIST}/${gid}/ttf-unhinted/${tn}.ttf`)); }); -task("woff:***").def(async (target, gid) => { - const [ts] = await target.need(`group-fonts-of:${gid}`); - await target.need(ts.map(tn => `${DIST}/${gid}/woff/${tn}.woff`)); +const GroupWoffs = tasks.group("woff", async (target, gid) => { + const [ts] = await target.need(GroupFontsOf(gid)); + await target.need(ts.map(tn => DistWoff`${DIST}/${gid}/woff/${tn}.woff`)); }); -task("woff2:***").def(async (target, gid) => { - const [ts] = await target.need(`group-fonts-of:${gid}`); - await target.need(ts.map(tn => `${DIST}/${gid}/woff2/${tn}.woff2`)); +const GroupWoff2s = tasks.group("woff2", async (target, gid) => { + const [ts] = await target.need(GroupFontsOf(gid)); + await target.need(ts.map(tn => DistWoff2`${DIST}/${gid}/woff2/${tn}.woff2`)); }); -task("fonts:***").def(async (target, gid) => { - await target.need(`ttf:${gid}`, `ttf-unhinted:${gid}`, `woff:${gid}`, `woff2:${gid}`); +const GroupFonts = tasks.group("fonts", async (target, gid) => { + await target.need(GroupTTFs(gid), GroupUnhintedTTFs(gid), GroupWoffs(gid), GroupWoff2s(gid)); }); // Charmap (for specimen) -file(`${DIST}/*/*.charmap`).def(async (target, gid, suffix) => { - const [src] = await target.need(`${BUILD}/${gid}/${suffix}.charmap`, `dir:${target.path.dir}`); - await cp(src.full, target.path.full); -}); +const DistCharMaps = files( + `${DIST}/*/*.charmap`, + async (target, { full, dir, $: [gid, suffix] }) => { + const [src] = await target.need(BuildCM`${BUILD}/${gid}/${suffix}.charmap`, de`${dir}`); + await cp(src.full, full); + } +); // Webfont CSS -file(`${DIST}/*/webfont.css`).def(async (target, gid) => { +const DistWebFontCSS = files(`${DIST}/*/webfont.css`, async (target, { dir, $: [gid] }) => { // Note: this target does NOT depend on the font files. - const [gr, ts] = await target.need( - `group-info:${gid}`, - `group-fonts-of:${gid}`, - `dir:${target.path.dir}` - ); - const hs = await target.need(...ts.map(t => `hives-of:${t}`)); + const [gr, ts] = await target.need(GroupInfo(gid), GroupFontsOf(gid), de(dir)); + const hs = await target.need(...ts.map(HivesOf)); await node( "utility/make-webfont-css.js", `${DIST}/${gid}/webfont.css`, @@ -302,153 +312,158 @@ file(`${DIST}/*/webfont.css`).def(async (target, gid) => { ); }); -task("contents:***").def(async (target, gid) => { - const [gr] = await target.need(`group-info:${gid}`); +const GroupContents = tasks.group("contents", async (target, gid) => { + const [gr] = await target.need(GroupInfo(gid)); await target.need( - `fonts:${gid}`, - `${DIST}/${gid}/webfont.css`, - `${DIST}/${gid}/${gr.prefix}-regular.charmap` + GroupFonts(gid), + DistWebFontCSS`${DIST}/${gid}/webfont.css`, + DistCharMaps`${DIST}/${gid}/${gr.prefix}-regular.charmap` ); return gid; }); // Archive -task(`${ARCHIVE_DIR}/*-*.zip`).def(async (target, gid) => { +const ArchiveFile = files(`${ARCHIVE_DIR}/*-*.zip`, async (target, { dir, full, $: [gid] }) => { // Note: this target does NOT depend on the font files. - const [exportPlans] = await target.need(`o:export-plans`, `dir:${target.path.dir}`); - await target.need(`contents:${exportPlans[gid]}`); + const [exportPlans] = await target.need(ExportPlans, de`${dir}`); + await target.need(GroupContents(exportPlans[gid])); await cd(`${DIST}/${exportPlans[gid]}`).run( ["7z", "a"], ["-tzip", "-r", "-mx=9"], - `../../${target.path.full}`, + `../../${full}`, `./` ); }); -task(`archive:***`).def(async (target, gid) => { - const [version] = await target.need(`o:version`); - await target.need(`${ARCHIVE_DIR}/${gid}-${version}.zip`); +const GroupArchives = tasks.group(`archive`, async (target, gid) => { + const [version] = await target.need(Version); + await target.need(ArchiveFile`${ARCHIVE_DIR}/${gid}-${version}.zip`); }); // Collection-level -task("collection-fonts:***").def(async (target, cid) => { - const [{ groups }] = await target.need("o:collect-plans"); - await target.need(groups[cid].map(file => `${DIST}/collections/${cid}/${file}.ttc`)); +const CollectionFontsOf = tasks.group("collection-fonts", async (target, cid) => { + const [{ groups }] = await target.need(CollectPlans); + await target.need(groups[cid].map(file => DistTTC`${DIST}/collections/${cid}/${file}.ttc`)); }); -task(`${ARCHIVE_DIR}/ttc-*-*.zip`).def(async (target, cid) => { - // Note: this target does NOT depend on the font files. - await target.need(`dir:${target.path.dir}`); - await target.need(`collection-fonts:${cid}`); - await cd(`${DIST}/collections/${cid}`).run( - ["7z", "a"], - ["-tzip", "-r", "-mx=9"], - `../../../${target.path.full}`, - `./` - ); -}); -task(`collection-archive:***`).def(async (target, cid) => { - const [version] = await target.need(`o:version`); - await target.need(`${ARCHIVE_DIR}/ttc-${cid}-${version}.zip`); +const TTCArchiveFile = files( + `${ARCHIVE_DIR}/ttc-*-*.zip`, + async (target, { dir, full, $: [cid] }) => { + // Note: this target does NOT depend on the font files. + await target.need(de`${dir}`); + await target.need(CollectionFontsOf(cid)); + await cd(`${DIST}/collections/${cid}`).run( + ["7z", "a"], + ["-tzip", "-r", "-mx=9"], + `../../../${full}`, + `./` + ); + } +); +const CollectionArchive = tasks.group(`collection-archive`, async (target, cid) => { + const [version] = await target.need(Version); + await target.need(TTCArchiveFile`${ARCHIVE_DIR}/ttc-${cid}-${version}.zip`); }); /////////////////////////////////////////////////////////// ////// Root Tasks ////// /////////////////////////////////////////////////////////// -task(`pages`).def(async target => { - const [sans, slab] = await target.need(`contents:iosevka`, `contents:iosevka-slab`); +const Pages = task(`pages`, async target => { + const [sans, slab] = await target.need(GroupContents`iosevka`, GroupContents`iosevka-slab`); await cp(`${DIST}/${sans}`, `pages/${sans}`); await cp(`${DIST}/${slab}`, `pages/${slab}`); }); -task(`sample-images:pre`).def(async target => { - const [sans, slab] = await target.need(`contents:iosevka`, `contents:iosevka-slab`); +const SampleImagesPre = task(`sample-images:pre`, async target => { + const [sans, slab] = await target.need(GroupContents`iosevka`, GroupContents`iosevka-slab`); await cp(`${DIST}/${sans}`, `snapshot/${sans}`); await cp(`${DIST}/${slab}`, `snapshot/${slab}`); }); -file(`snapshot/index.css`).def(async target => { - await target.need(`snapshot/index.styl`); +const SnapShotCSS = file(`snapshot/index.css`, async target => { + await target.need(fu`snapshot/index.styl`); await cd(`snapshot`).run(`stylus`, `index.styl`, `-c`); }); -task(`sample-images:take`).def(async target => { - await target.need(`sample-images:pre`, `snapshot/index.css`); +const TakeSampleImages = task(`sample-images:take`, async target => { + await target.need(SampleImagesPre, SnapShotCSS); await cd(`snapshot`).run("npx", "electron", "get-snap.js", ["--dir", "../images"]); }); -file(`images/*.png`).def(async target => { - await target.need(`sample-images:take`); - await run("optipng", target.path.full); +const ScreenShot = files(`images/*.png`, async (target, { full }) => { + await target.need(TakeSampleImages); + await run("optipng", full); }); -task(`sample-images`).def(async target => { - await target.need(`sample-images:take`); + +const SampleImages = task(`sample-images`, async target => { + await target.need(TakeSampleImages); await target.need( - `images/charvars.png`, - `images/download-options.png`, - `images/family.png`, - `images/languages.png`, - `images/ligations.png`, - `images/matrix.png`, - `images/preview-all.png`, - `images/stylesets.png`, - `images/variants.png`, - `images/weights.png` + ScreenShot`images/charvars.png`, + ScreenShot`images/download-options.png`, + ScreenShot`images/family.png`, + ScreenShot`images/languages.png`, + ScreenShot`images/ligations.png`, + ScreenShot`images/matrix.png`, + ScreenShot`images/preview-all.png`, + ScreenShot`images/stylesets.png`, + ScreenShot`images/variants.png`, + ScreenShot`images/weights.png` ); }); -task(`all:archives`).def(async target => { - const [exportPlans, collectPlans] = await target.need("o:export-plans", "o:collect-plans"); +const AllArchives = task(`all:archives`, async target => { + const [exportPlans, collectPlans] = await target.need(ExportPlans, CollectPlans); await target.need( - Object.keys(exportPlans).map(gid => `archive:${gid}`), - Object.keys(collectPlans.groups).map(cid => `collection-archive:${cid}`) + Object.keys(exportPlans).map(GroupArchives), + Object.keys(collectPlans.groups).map(CollectionArchive) ); }); -phony(`clean`).def(async () => { +phony(`clean`, async () => { await rm(`build`); await rm(`dist`); await rm(`release-archives`); + build.deleteJournal(); // Disable journal }); -phony(`release`).def(async target => { - await target.need(`all:archives`, `sample-images`, `pages`); +phony(`release`, async target => { + await target.need(AllArchives, SampleImages, Pages); }); /////////////////////////////////////////////////////////// ////// Script Building ////// /////////////////////////////////////////////////////////// -const MARCOS = [`file-updated:meta/macros.ptl`]; -oracle("{ptl|js}-scripts-under:***").def((target, $ext, $1) => +const MARCOS = [fu`meta/macros.ptl`]; +const ScriptsUnder = oracles("{ptl|js}-scripts-under::***", (target, $ext, $1) => FileList({ under: $1, pattern: `**/*.${$ext}` })(target) ); -oracle("scripts:{ptl|js}").def(async (target, ext) => { +const ScriptFiles = computes.group("script-files", async (target, ext) => { const [gen, meta, glyphs, support] = await target.need( - `${ext}-scripts-under:gen`, - `${ext}-scripts-under:meta`, - `${ext}-scripts-under:glyphs`, - `${ext}-scripts-under:support` + ScriptsUnder`${ext}-scripts-under::gen`, + ScriptsUnder`${ext}-scripts-under::meta`, + ScriptsUnder`${ext}-scripts-under::glyphs`, + ScriptsUnder`${ext}-scripts-under::support` ); return [...gen, ...meta, ...glyphs, ...support]; }); -oracle("scripts:js-from-ptl").def(async target => { - const [ptl] = await target.need("scripts:ptl"); - return target.trackModification(ptl.map(x => x.replace(/\.ptl$/g, ".js"))); +const JavaScriptFromPtl = computed("scripts-js-from-ptl", async target => { + const [ptl] = await target.need(ScriptFiles`ptl`); + return ptl.map(x => x.replace(/\.ptl$/g, ".js")); }); -file(`{gen|glyphs|support|meta}/**/*.js`).def(async target => { - const [jsFromPtl] = await target.need("scripts:js-from-ptl"); - if (jsFromPtl.indexOf(target.path.full) >= 0) { - const ptl = target.path.full.replace(/\.js$/g, ".ptl"); - if (/^glyphs\//.test(target.path.full)) { +const ScriptJS = files(`{gen|glyphs|support|meta}/**/*.js`, async (target, path) => { + const [jsFromPtl] = await target.need(JavaScriptFromPtl); + if (jsFromPtl.indexOf(path.full) >= 0) { + const ptl = path.full.replace(/\.js$/g, ".ptl"); + if (/^glyphs\//.test(path.full)) { await target.need(MARCOS); } - await target.need(`file-updated:${ptl}`); - await run(PATEL_C, "--strict", ptl, "-o", target.path.full); + await target.need(fu`${ptl}`); + await run(PATEL_C, "--strict", ptl, "-o", path.full); } else { - await target.need(`file-updated:${target.path.full}`); + await target.need(fu`${path.full}`); } }); -task("scripts").def(async target => { - const [jsFromPtl] = await target.need("scripts:js-from-ptl"); +const Scripts = task("scripts", async target => { + const [jsFromPtl] = await target.need(JavaScriptFromPtl); await target.need(jsFromPtl); - const [js] = await target.need("scripts:js"); - await target.need(js); - await target.need(`parameters.toml`, `variants.toml`, `emptyfont.toml`); + const [js] = await target.need(ScriptFiles`js`); + await target.need(js.map(ScriptJS)); + await target.need(fu`parameters.toml`, fu`variants.toml`, fu`emptyfont.toml`); });