diff --git a/README.md b/README.md index 508ec7c..b5e0429 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Quit your editor/program. Unzip and open the folder. To build Iosevka you should: 1. Ensure that `node`, `FontForge`, `ttfautohint`, `ttx` and `make` are runnable in your terminal. -2. Install the newest `patel-c` (≥ 0.21.0) by `npm install patel -g` +2. Install the newest `patel-c` (≥ 0.25.0) by `npm install patel -g` 3. Install necessary libs by `npm install` 4. `make`. diff --git a/buildglyphs.patel b/buildglyphs.patel index 05ea563..2c6c8b9 100644 --- a/buildglyphs.patel +++ b/buildglyphs.patel @@ -1,12 +1,8 @@ -define Glyph [require './support/glyph'].Glyph -define Stroke [require './support/stroke'].Stroke -define tp [require './support/transform'].transformPoint -define utp [require './support/transform'].untransform -define inverse [require './support/transform'].inverse -define unorm [require 'unorm'] -define spirokit [require './support/spirokit'] - - +import './support/glyph' as Glyph +import './support/stroke' as Stroke +import './support/spirokit' as spirokit +import './support/transform' as [object [transformPoint tp] [untransform utp] inverse] +import 'unorm' as unorm ### File inclusion macro define-macro $$include : syntax-rules @@ -101,7 +97,7 @@ define [tagged tag fn] : lambda [] : begin set this.defaultTag _tag return nothing -define [buildFont para recursive] : begin +export as build : define [buildFont para recursive recursiveCodes] : begin define variantSelector para.variantSelector define font this @@ -426,7 +422,4 @@ define [buildFont para recursive] : begin $$include 'glyphs/autobuilds.patel' set font.glyfMap glyphs - return font - - -exports.build = buildFont \ No newline at end of file + return font \ No newline at end of file diff --git a/extract.js b/extract.js index 367b552..3c49978 100644 --- a/extract.js +++ b/extract.js @@ -3,7 +3,7 @@ var TTFWriter = require('node-sfnt').TTFWriter; var TTF = require('node-sfnt').TTF; var argv = require('yargs').argv; -var Glyph = require('./support/glyph').Glyph; +var Glyph = require('./support/glyph'); function toBuffer(arrayBuffer) { var length = arrayBuffer.byteLength; diff --git a/glyphs/autobuilds.patel b/glyphs/autobuilds.patel index 0ea98a2..5a88279 100644 --- a/glyphs/autobuilds.patel +++ b/glyphs/autobuilds.patel @@ -116,6 +116,8 @@ define customDecompositions { ."\u21AE" "" } +define iotaBelowToLF : function [p] : if (p === glyphs.iotaBelow) glyphs.iotaLF p +define ogonekBelowToTR : function [p] : if (p === glyphs.ogonekBelow) glyphs.ogonekTR p define [subParts parts] : begin local hasMarkAbove false foreach p [items-of parts] : if [isAboveMark p] : set hasMarkAbove true @@ -125,8 +127,8 @@ define [subParts parts] : begin if (parts.0 === glyphs.j && hasMarkAbove) : parts.0 = glyphs.dotlessj # replace below marks with trailing marks - if parts.0.anchors.lf : set parts : parts.map : function [p] : if (p === glyphs.iotaBelow) glyphs.iotaLF p - if parts.0.anchors.trailing : set parts : parts.map : function [p] : if (p === glyphs.ogonekBelow) glyphs.ogonekTR p + if parts.0.anchors.lf : set parts : parts.map iotaBelowToLF + if parts.0.anchors.trailing : set parts : parts.map ogonekBelowToTR # composite greek overmarks for [local j 0] (j < parts.length) [inc j] : piecewise @@ -153,7 +155,7 @@ define [pad s n] : begin return s -set font.features.ccmp {} +#set font.features.ccmp {} define [shorter x y] : if (x.length < y.length) x y define [decideName namingParts parts code] : begin local baseName namingParts.0.name @@ -168,32 +170,42 @@ define [decideName namingParts parts code] : begin let : begin local nComposed 0 - foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs.(code)] : begin + local foundDecompositions {} + local itsName : [part] -> part.name + local [buildForCode code] : if [not unicodeGlyphs.(code)] : begin local str : String.fromCharCode code local nfd : fallback customDecompositions.(str) : unorm.nfd str if (nfd.length > 1) : begin local parts {} local allFound true foreach j [range 0 nfd.length] : begin - set parts.(j) unicodeGlyphs.([nfd.charCodeAt j]) - if [not parts.(j)] : set allFound false + local part unicodeGlyphs.([nfd.charCodeAt j]) + if [not part] : then : set allFound false + : else : set parts.(j) unicodeGlyphs.([nfd.charCodeAt j]) if allFound : begin local namingParts : parts.slice 0 set parts : subParts parts - local composition : namingParts.map ([part] -> part.name) :.join ' ' + # local composition : namingParts.map itsName :.join ' ' local glyphName : decideName namingParts parts code - create-glyph glyphName : glyph-construction - assign-unicode code - include parts.0 AS_BASE - set-width parts.0.advanceWidth - foreach part [items-of : parts.slice 1] : begin - include part - # eject right-bottom serifs - if (part.name === 'rtailBR') : eject-contour 'serifRB' - if [not glyphs.(composition)] : begin - font.features.ccmp.push : 'sub ' + composition + ' by ' + glyphName - set glyphs.(composition) glyphs.(glyphName) + foundDecompositions.push {glyphName code parts} inc nComposed + + if recursiveCodes : recursiveCodes.forEach buildForCode + : else : foreach code [range 0x0000 0xFFFF] : buildForCode code + + define construction : glyph-construction + assign-unicode code + include parts.0 AS_BASE + set-width parts.0.advanceWidth + foreach part [items-of : parts.slice 1] : begin + include part + # eject right-bottom serifs + if (part.name === 'rtailBR') : eject-contour 'serifRB' +# if [not glyphs.(composition)] : begin +# font.features.ccmp.push : 'sub ' + composition + ' by ' + glyphName +# set glyphs.(composition) glyphs.(glyphName) + foreach [{glyphName code parts} : items-of foundDecompositions] : begin + create-glyph glyphName construction progress "Precomposed (\(nComposed) glyphs)" diff --git a/glyphs/common-shapes.patel b/glyphs/common-shapes.patel index d0c35ec..36eedfa 100644 --- a/glyphs/common-shapes.patel +++ b/glyphs/common-shapes.patel @@ -381,13 +381,15 @@ define [WaveShape l r cy extendy tension sw] : glyph-construction g4 r (cy + endwavey) # Derived subfonts -define [Fork glyphs params] : begin +define [Fork gs params] : begin local p : Object.create params local shouldBuildList {} - foreach glyphid [items-of glyphs] : set shouldBuildList : shouldBuildList.concat {glyphid :: dependencyProfile.(glyphid)} + foreach glyphid [items-of gs] : set shouldBuildList : shouldBuildList.concat {glyphid :: dependencyProfile.(glyphid)} set shouldBuildList : shouldBuildList.filter : [x] -> [not [not x]] + local shouldBuildUnicodes : shouldBuildList.map ([x] -> [if (glyphs.(x) && glyphs.(x).unicode) glyphs.(x).unicode.0 nothing]) + :.filter ([x] -> [not [not x]]) try : begin - local forkFont : buildFont.call [TempFont] p shouldBuildList + local forkFont : buildFont.call [TempFont] p shouldBuildList shouldBuildUnicodes : ex : begin if ex.glyfMap : return ex.glyfMap diff --git a/glyphs/greek.patel b/glyphs/greek.patel index 7eacc16..74e3ddc 100644 --- a/glyphs/greek.patel +++ b/glyphs/greek.patel @@ -255,7 +255,7 @@ create-glyph 'eta' : glyph-construction include pMarks set-anchor 'lf' BASE (SB + HALFSTROKE) 0 - include : nShoulder (SB + STROKE * CORRECTION_HX) RIGHTSB (STROKE * 0.3) XH DESCENDER SMALLSMOOTHA SMALLSMOOTHB + include : nShoulder (SB + STROKE * CORRECTION_HX) RIGHTSB SHOULDERFINE XH DESCENDER SMALLSMOOTHA SMALLSMOOTHB include : VBarLeft SB 0 XH if SLAB : begin include : LeftwardTopSerif SB XH SIDEJUT diff --git a/glyphs/latin-extend-basis.patel b/glyphs/latin-extend-basis.patel index 6ab722d..70d807a 100644 --- a/glyphs/latin-extend-basis.patel +++ b/glyphs/latin-extend-basis.patel @@ -379,7 +379,7 @@ create-glyph 'Eng' : glyph-construction assign-unicode 0x14A include capitalMarks - include : nShoulder (SB + STROKE) RIGHTSB (STROKE * 0.3) CAP (HOOK + HALFSTROKE + O) SMOOTHA SMOOTHB + include : nShoulder (SB + STROKE) RIGHTSB SHOULDERFINE CAP (HOOK + HALFSTROKE + O) SMOOTHA SMOOTHB include : VerticalHook (RIGHTSB - HALFSTROKE * CORRECTION_HX) (HOOK + HALFSTROKE + O) [Math.max ((SB - RIGHTSB) / 2 + HALFSTROKE) (-HOOKX)] HOOK include : VBar (SB + HALFSTROKE * CORRECTION_HX) 0 CAP @@ -741,7 +741,7 @@ create-glyph 'latinEta' : glyph-construction include ifMarks set-anchor 'lf' BASE (SB + HALFSTROKE) 0 - include : nShoulder (SB + STROKE) RIGHTSB (STROKE * 0.3) CAP DESCENDER SMALLSMOOTHA SMALLSMOOTHB + include : nShoulder (SB + STROKE) RIGHTSB SHOULDERFINE CAP DESCENDER SMALLSMOOTHA SMALLSMOOTHB include : VBar (SB + HALFSTROKE * CORRECTION_HX) 0 CAP if SLAB : begin include : LeftwardTopSerif SB CAP SIDEJUT @@ -758,7 +758,7 @@ create-glyph 'latineta' : glyph-construction include pMarks set-anchor 'lf' BASE (SB + HALFSTROKE) 0 - include : nShoulder (SB + STROKE * CORRECTION_HX) RIGHTSB (STROKE * 0.3) XH DESCENDER SMALLSMOOTHA SMALLSMOOTHB + include : nShoulder (SB + STROKE * CORRECTION_HX) RIGHTSB SHOULDERFINE XH DESCENDER SMALLSMOOTHA SMALLSMOOTHB include : VBarLeft SB 0 XH if SLAB : begin include : LeftwardTopSerif SB XH SIDEJUT diff --git a/glyphs/overmarks.patel b/glyphs/overmarks.patel index c2ff8f3..f27a394 100644 --- a/glyphs/overmarks.patel +++ b/glyphs/overmarks.patel @@ -117,6 +117,7 @@ create-glyph 'tildeAbove' : glyph-construction :.set-width markHalfStroke markHalfStroke :.cubic-to [mix leftEnd rightEnd tildeWaveX] [mix bot top tildeWave] [mix leftEnd rightEnd (1 - tildeWaveX)] [mix bot top (1 - tildeWave)] rightEnd [mix tbot ttop (1 - tildeWaveEnd)] :.set-samples 11 + :.to-outline include s diff --git a/makesupport.mk b/makesupport.mk index 025696e..d539b70 100644 --- a/makesupport.mk +++ b/makesupport.mk @@ -1,14 +1,20 @@ -SUPPORT_FILES = support/glyph.js support/stroke.js support/spiroexpand.js support/spirokit.js parameters.js extract.js generate.js emptyfont.toml parameters.toml +SUPPORT_FILES_FROM_PATEL = support/glyph.js support/stroke.js support/spiroexpand.js support/spirokit.js parameters.js +SUPPORT_FILES = $(SUPPORT_FILES_FROM_PATEL) support/glyph.js support/stroke.js support/spiroexpand.js support/spirokit.js parameters.js extract.js generate.js emptyfont.toml parameters.toml GLYPH_SEGMENTS = glyphs/common-shapes.patel glyphs/overmarks.patel glyphs/latin-basic-capital.patel glyphs/latin-basic-lower.patel glyphs/greek.patel glyphs/cyrillic-basic.patel glyphs/latin-extend-basis.patel glyphs/latin-extend-decorated.patel glyphs/cyrillic-extended.patel glyphs/numbers.patel glyphs/symbol-punctuation.patel glyphs/symbol-math.patel glyphs/symbol-geometric.patel glyphs/symbol-other.patel glyphs/symbol-letter.patel glyphs/autobuilds.patel SCRIPTS = $(SUPPORT_FILES) buildglyphs.js +SCRIPTS_FROM_PATEL = $(SUPPORT_FILES_FROM_PATEL) buildglyphs.js buildglyphs.js : buildglyphs.patel $(GLYPH_SEGMENTS) - patel-c --optimize --strict $< -o $@ - -$(SUPPORT_FILES) : patel-c --strict $< -o $@ + +$(SUPPORT_FILES_FROM_PATEL) : + patel-c --optimize --strict $< -o $@ support/glyph.js : support/glyph.patel support/stroke.js : support/stroke.patel support/spirokit.js : support/spirokit.patel support/spiroexpand.js : support/spiroexpand.patel -parameters.js : parameters.patel \ No newline at end of file +parameters.js : parameters.patel + +cleanscripts : + -@rm $(SCRIPTS_FROM_PATEL) +scripts : $(SCRIPTS) \ No newline at end of file diff --git a/parameters.patel b/parameters.patel index 2cc983e..a8f217d 100644 --- a/parameters.patel +++ b/parameters.patel @@ -1,4 +1,4 @@ -define [build parametersData styles] : begin +export : define [build parametersData styles] : begin local param {.} local variantSelector {.} foreach [style : items-of styles] : begin @@ -8,7 +8,4 @@ define [build parametersData styles] : begin if hive.variantSelector : foreach [k : items-of : Object.keys hive.variantSelector] : begin set variantSelector.(k) hive.variantSelector.(k) param.variantSelector = variantSelector - return param - - -exports.build = build \ No newline at end of file + return param \ No newline at end of file diff --git a/support/glyph.patel b/support/glyph.patel index 9c12a15..d8752dd 100644 --- a/support/glyph.patel +++ b/support/glyph.patel @@ -1,8 +1,7 @@ -define bezierCubic2Q2 [require 'node-sfnt/lib/math/bezierCubic2Q2'] -define tp [require './transform'].transformPoint -define utp [require './transform'].untransform -define Stroke [require './stroke'].Stroke -define Bezier [require 'bezier-js'] +import 'node-sfnt/lib/math/bezierCubic2Q2' as bezierCubic2Q2 +import './transform' as [object [transformPoint tp] [untransform utp] inverse] +import 'bezier-js' as Bezier + define [mix a b p] : a + (b - a) * p define [ratio l r m] : if [l === r] 0 ((m - l) / (r - l)) @@ -17,7 +16,7 @@ define id { define [fallback] : for [local j 0] (j < arguments.length) [inc j] : if (arguments.(j) !== nothing) : return arguments.(j) define aFunction {.unapply [function [obj arity] [if (obj <@ Function) {obj} null]]} -define [Glyph name] : begin +export default : define [Glyph name] : begin set this.name name set this.unicode {} set this.contours {} @@ -80,24 +79,6 @@ define [Glyph.prototype.reverse-last] : begin if [this.contours && this.contours.(this.contours.length - 1)] : begin this.contours.(this.contours.length - 1) = [this.contours.(this.contours.length - 1).reverse] -define [Glyph.prototype.put-shapes contours] : begin - local t this.gizmo - set this.gizmo id - foreach contour [items-of contours] : if contour : begin - this.start-from contour.0.x contour.0.y - for [local j 1] (j < contour.length) [inc j] : begin - local point contour.(j) - if point.cubic - : then : begin - local p2 contour.((j + 1)) - local p3 contour.((j + 2)) - this.cubic-to point.x point.y p2.x p2.y p3.x p3.y - j = j + 2 - : else : if point.onCurve [this.line-to point.x point.y] [this.curve-control point.x point.y] - this.tag-contour [fallback contour.tag this.defaultTag] - set this.gizmo t - return this - define [Glyph.prototype.tag-contour tag n] : begin if this.contours : begin local lastContour this.contours.(this.contours.length - 1) @@ -110,7 +91,6 @@ define [Glyph.prototype.eject-contour tag] : begin define [Glyph.prototype.include component copyAnchors quenches] : begin local glyph : match component [aFunction it] : return : component.call this - [Stroke.is it] {.contours [component.to-outline]} {:: contours} {.contours contours} otherwise component local contours glyph.contours @@ -123,14 +103,14 @@ define [Glyph.prototype.include component copyAnchors quenches] : begin local anchorThat glyph.anchors.(markid) if (anchorThis && (anchorThis.type === 'base' || anchorThis.mbx !== nothing && anchorThis.mby !== nothing) && anchorThat && anchorThat.type === 'mark') : begin set {shiftx shifty} { - ([fallback anchorThis.mbx anchorThis.x] - anchorThat.x) + ([fallback anchorThis.mbx anchorThis.x] - anchorThat.x) ([fallback anchorThis.mby anchorThis.y] - anchorThat.y) } # we have a mark-to-mark position if (anchorThat.mbx !== nothing && anchorThat.mby !== nothing) : if (anchorThis.type === 'base') then set this.anchors.(markid) { - .x (anchorThis.x + anchorThat.mbx - anchorThat.x) + .x (anchorThis.x + anchorThat.mbx - anchorThat.x) .y (anchorThis.y + anchorThat.mby - anchorThat.y) .type anchorThis.type .mbx anchorThis.mbx @@ -138,7 +118,7 @@ define [Glyph.prototype.include component copyAnchors quenches] : begin } else set this.anchors.(markid) { - .mbx (anchorThis.mbx + anchorThat.mbx - anchorThat.x) + .mbx (anchorThis.mbx + anchorThat.mbx - anchorThat.x) .mby (anchorThis.mby + anchorThat.mby - anchorThat.y) .type anchorThis.type .x anchorThis.x @@ -147,13 +127,15 @@ define [Glyph.prototype.include component copyAnchors quenches] : begin set transform.x : transform.x + shiftx set transform.y : transform.y + shifty if contours : begin - this.put-shapes : contours.map : function [contour] : begin + foreach [contour : items-of contours] : begin + local doput true if quenches : foreach [tag : items-of quenches] : begin - if [contour.tag === tag] : return null - return : begin - local r : contour.map : function [point] : tp transform point - set r.tag contour.tag - * r + if [contour.tag === tag] : set doput false + if doput : begin + local c {} + foreach [point : items-of contour] : c.push : tp transform point + set c.tag contour.tag + this.contours.push c if (([not contours] || copyAnchors) && glyph.anchors) : set this.anchors : let [a {.}] [anchors glyph.anchors] [keys : Object.keys glyph.anchors] : begin foreach k [items-of keys] [set a.(k) anchors.(k)] * a @@ -238,6 +220,4 @@ define [Glyph.prototype.cleanup t] : begin if [oncurveRemovable p0 p1 p2 t] : set p1.unimportant true foreach point [items-of contour] : if [not point.unimportant] : cleanedContour.push point this.contours.(c) = cleanedContour - return this - -exports.Glyph = Glyph \ No newline at end of file + return this \ No newline at end of file diff --git a/support/intersection.js b/support/intersection.js index b578ffd..2bf3e21 100644 --- a/support/intersection.js +++ b/support/intersection.js @@ -1,4 +1,4 @@ -exports.intersection = function (line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) { +module.exports = function (line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) { // if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point var denominator, a, b, numerator1, numerator2, result = { x: null, diff --git a/support/monotonic-interpolate.js b/support/monotonic-interpolate.js index fedb6ed..c44e4a5 100644 --- a/support/monotonic-interpolate.js +++ b/support/monotonic-interpolate.js @@ -1,4 +1,4 @@ -exports.createInterpolant = function(xs, ys) { +module.exports = function(xs, ys) { var i, length = xs.length; // Deal with length issues diff --git a/support/spiroexpand.patel b/support/spiroexpand.patel index d6b060f..7e069e8 100644 --- a/support/spiroexpand.patel +++ b/support/spiroexpand.patel @@ -1,11 +1,10 @@ -define smooth [require './monotonic-interpolate'].createInterpolant -define tp [require './transform'].transformPoint -define utp [require './transform'].untransform +import './monotonic-interpolate' as smooth +import './transform' as [object [transformPoint tp] [untransform utp] inverse] define [fallback] : for [local j 0] (j < arguments.length) [inc j] : if (arguments.(j) !== nothing) : return arguments.(j) define [linreg x0 y0 x1 y1 x] : y0 + (x - x0) * (y1 - y0) / (x1 - x0) -define [SpiroExpansionContext] : begin +export default : define [SpiroExpansionContext] : begin set this.gizmo {.xx 1 .yy 1 .xy 0 .yy 0 .x 0 .y 0} set this.controlKnots {} set this.defaultd1 0 @@ -146,6 +145,4 @@ define [SpiroExpansionContext.prototype.expand contrast] : begin "left" "right" "right" "left" type type - return {.lhs lhs .rhs rhs} - -exports.SpiroExpansionContext = SpiroExpansionContext \ No newline at end of file + return {.lhs lhs .rhs rhs} \ No newline at end of file diff --git a/support/spirokit.patel b/support/spirokit.patel index 4eb708a..4831ab3 100644 --- a/support/spirokit.patel +++ b/support/spirokit.patel @@ -1,9 +1,10 @@ -define libspiro : require 'libspiro-js' -define SpiroExpansionContext [require './spiroexpand'].SpiroExpansionContext +import 'libspiro-js' as libspiro +import './spiroexpand' as SpiroExpansionContext + define [fallback] : for [local j 0] (j < arguments.length) [inc j] : if (arguments.(j) !== nothing) : return arguments.(j) define [mix a b p] : a + (b - a) * p -define [SetupBuilders args] : begin +export : define [SetupBuilders args] : begin define [object para Glyph CONTRAST globalTransform CONTRAST STROKE SUPERNESS] args define [g4 x y f] {.x x .y y .type 'g4' .af f} @@ -170,6 +171,4 @@ define [SetupBuilders args] : begin g4 g2 corner flat curl close end straight widths heading unimportant important alsothru alsothruthem bezcontrols quadcontrols archv arcvh complexThru - dispiro spiro-outline] - -exports.SetupBuilders = SetupBuilders \ No newline at end of file + dispiro spiro-outline] \ No newline at end of file diff --git a/support/stroke.patel b/support/stroke.patel index e97af51..7408585 100644 --- a/support/stroke.patel +++ b/support/stroke.patel @@ -1,8 +1,7 @@ -define smooth [require './monotonic-interpolate'].createInterpolant -define intersection [require './intersection'].intersection -define Bezier [require 'bezier-js'] -define tp [require './transform'].transformPoint -define utp [require './transform'].untransform +import './monotonic-interpolate' as smooth +import 'bezier-js' as Bezier +import './intersection' as intersection +import './transform' as [object [transformPoint tp] [untransform utp] inverse] define [fallback] : for [local j 0] (j < arguments.length) [inc j] : if (arguments.(j) !== nothing) : return arguments.(j) define [mix a b p] : a + (b - a) * p @@ -16,7 +15,7 @@ define KAPPA 0.51 define BKAPPA : KAPPA + 0.1 define CKAPPA BKAPPA -define [Stroke] : begin +export default : define [Stroke] : begin this.points = {} this.samples = SAMPLES this.gizmo = {