diff --git a/README.md b/README.md index 4ecb43381..5e214f430 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Building 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` bt `npm install patel -g` +2. Install the newest `patel-c` (≥ 0.21.0) by `npm install patel -g` 3. Install necessary libs by `npm install` 4. `make`. diff --git a/buildglyphs.patel b/buildglyphs.patel index c2a361b02..af0fd5c9c 100644 --- a/buildglyphs.patel +++ b/buildglyphs.patel @@ -167,6 +167,7 @@ define [buildFont para recursive] : begin define OPERATORSTROKE : adviceBlackness 3.2 define [adviceSSmooth y sign] : ((y - STROKE * 2) * 0.2 + STROKE) + sign * globalTransform.yx * para.smoothadjust + define [adviceGlottalStopSmooth y sign] : ((y - STROKE) * 0.25 + STROKE / 2) + sign * globalTransform.yx * para.smoothadjust # Anchor parameters define BASE 'base' @@ -447,7 +448,6 @@ define [buildFont para recursive] : begin # Metric metadata # Note: we use 1000upm in design, and (1000 * upmsacle)upm in production, to avoid rounding error. - define upmscale : fallback para.upmscale 1 let [asc : 1250 * CAP / (CAP - DESCENDER)] [desc : 1250 * DESCENDER / (CAP - DESCENDER)] : begin set font.head.unitsPerEm 1000 @@ -501,35 +501,6 @@ define [buildFont para recursive] : begin $$include 'glyphs/symbol-other.patel' $$include 'glyphs/autobuilds.patel' - ### Zoom all glyphs by para.upmscale - - set font.head.unitsPerEm : upmscale * font.head.unitsPerEm - set font.hhea.ascent : upmscale * font.hhea.ascent - set font.'OS/2'.usWinAscent : upmscale * font.'OS/2'.usWinAscent - set font.'OS/2'.sTypoAscender : upmscale * font.'OS/2'.sTypoAscender - set font.hhea.descent : upmscale * font.hhea.descent - set font.'OS/2'.usWinDescent : upmscale * font.'OS/2'.usWinDescent - set font.'OS/2'.sTypoDescender : upmscale * font.'OS/2'.sTypoDescender - set font.hhea.lineGap : upmscale * font.hhea.lineGap - set font.'OS/2'.sTypoLineGap : upmscale * font.'OS/2'.sTypoLineGap - set font.'OS/2'.sxHeight : upmscale * font.'OS/2'.sxHeight - set font.'OS/2'.sCapHeight : upmscale * font.'OS/2'.sCapHeight - - if (upmscale != 1) : foreach glyph [items-of glyphList] : begin - glyph.advanceWidth = glyph.advanceWidth * upmscale - if glyph.contours: foreach contour [items-of glyph.contours] : foreach point [items-of contour] : begin - point.x = point.x * upmscale - point.y = point.y * upmscale - - # We will uprightify all italic glyphs before outputing - # to prevent rounding error for common glyphs - local finalUprightify : Upright - finalUprightify.x = 0 - finalUprightify.y = 0 - if [not recursive] : foreach glyph [items-of glyphList] : begin - glyph.apply-transform finalUprightify - glyph.cleanup - set font.glyfMap glyphs return font diff --git a/extract.js b/extract.js index 466dba8a6..20ad38a51 100644 --- a/extract.js +++ b/extract.js @@ -3,6 +3,8 @@ var TTFWriter = require('node-sfnt').TTFWriter; var TTF = require('node-sfnt').TTF; var argv = require('yargs').argv; +var Glyph = require('./support/glyph').Glyph; + function toBuffer(arrayBuffer) { var length = arrayBuffer.byteLength; var view = new DataView(arrayBuffer, 0, length); @@ -16,20 +18,20 @@ function pad(s, n){ while(s.length < n) s = '0' + s; return s; } var options = {preserveOS2Version: true} -var ttfFont = JSON.parse(fs.readFileSync(argv._[0], 'utf-8')); +var font = JSON.parse(fs.readFileSync(argv._[0], 'utf-8')); if(argv.charmap) { - fs.writeFileSync(argv.charmap, JSON.stringify(ttfFont.glyf.map(function(glyph){ return [glyph.name, glyph.unicode, glyph.advanceWidth === 0 && glyph.anchors && Object.keys(glyph.anchors).length > 0]})), 'utf8') + fs.writeFileSync(argv.charmap, JSON.stringify(font.glyf.map(function(glyph){ return [glyph.name, glyph.unicode, glyph.advanceWidth === 0 && glyph.anchors && Object.keys(glyph.anchors).length > 0]})), 'utf8') }; if(argv.feature) { var featurefile = '\n\n'; // markGlyphs - for(var key in ttfFont.features.markGlyphs){ - featurefile += '@MG_' + key + '= [' + ttfFont.features.markGlyphs[key].join(' ') + '];\n' + for(var key in font.features.markGlyphs){ + featurefile += '@MG_' + key + '= [' + font.features.markGlyphs[key].join(' ') + '];\n' } // mark - var mark = ttfFont.features.mark; + var mark = font.features.mark; for(var id in mark) { var lookup = mark[id]; var lookupName = 'markAuto_' + id; @@ -37,14 +39,43 @@ if(argv.feature) { } // mkmk - var mkmk = ttfFont.features.mkmk; + var mkmk = font.features.mkmk; featurefile += 'lookup mkmkAuto {' + mkmk.marks.join(';\n') + ';\n' + mkmk.bases.join(';\n') + ';} mkmkAuto;' // gdef - var gdef = ttfFont.features.gdef; + var gdef = font.features.gdef; featurefile += '@GDEF_Simple = [' + gdef.simple.join(' \n') + '];\n@GDEF_Ligature =[' + gdef.ligature.join(' \n') + '];\n@GDEF_Mark = [' + gdef.mark.join(' \n') + '];\ntable GDEF { GlyphClassDef @GDEF_Simple, @GDEF_Ligature, @GDEF_Mark, ;} GDEF;' fs.writeFileSync(argv.feature, featurefile, 'utf8'); }; -if(argv.ttf) fs.writeFileSync(argv.ttf, toBuffer(new TTFWriter(options).write(ttfFont))); \ No newline at end of file +if(argv.ttf) { + var upm = (argv.upm - 0) || 1000; + var upmscale = upm / font.head.unitsPerEm; + var skew = (argv.uprightify ? 1 : 0) * Math.tan((font.post.italicAngle || 0) / 180 * Math.PI); + for(var j = 0; j < font.glyf.length; j++){ + var g = font.glyf[j]; + g.advanceWidth *= upmscale; + if(g.contours) for(var k = 0; k < g.contours.length; k++) { + var contour = g.contours[k]; + for(var p = 0; p < contour.length; p++) { + contour[p].y *= upmscale; + contour[p].x = contour[p].x * upmscale + contour[p].y * skew; + } + } + Glyph.prototype.cleanup.call(g); + } + font.head.unitsPerEm *= upmscale; + font.hhea.ascent *= upmscale; + font['OS/2'].usWinAscent *= upmscale; + font['OS/2'].sTypoAscender *= upmscale; + font.hhea.descent *= upmscale; + font['OS/2'].usWinDescent *= upmscale; + font['OS/2'].sTypoDescender *= upmscale; + font.hhea.lineGap *= upmscale; + font['OS/2'].sTypoLineGap *= upmscale; + font['OS/2'].sxHeight *= upmscale; + font['OS/2'].sCapHeight *= upmscale; + + fs.writeFileSync(argv.ttf, toBuffer(new TTFWriter(options).write(font))); +} \ No newline at end of file diff --git a/glyphs/common-shapes.patel b/glyphs/common-shapes.patel index eef15668a..ff1c6b789 100644 --- a/glyphs/common-shapes.patel +++ b/glyphs/common-shapes.patel @@ -204,35 +204,34 @@ define [smallo u d l r _width _sma _smb ai] : glyph-construction local sma : fallback _sma SMALLSMOOTHA local smb : fallback _smb SMALLSMOOTHB local mc : CORRECTION_OMIDX * width - if (u - d > sma + smb) - then : begin - include : spiro - prepare : widths width 0 - g4 (middle - mc) (u - O) - archv - [if ai flat.ai flat] (l + O) (u - sma) - [if ai curl.ai curl] (l + O) (d + smb) - arcvh - g4 (middle + mc) (d + O) - archv - [if ai flat.ai flat] (r - O) (d + sma) - [if ai curl.ai curl] (r - O) (u - smb) - arcvh - close - else : begin - local ymiddlea : mix d u (smb / (sma + smb)) - local ymiddleb : mix d u (sma / (sma + smb)) - include : spiro - prepare : widths width 0 - g4 (middle - mc) (u - O) - archv - g4 (l + O) ymiddlea - arcvh - g4 (middle + mc) (d + O) - archv - g4 (r - O) ymiddleb - arcvh - close + if (u - d > sma + smb) : then : begin + include : spiro + prepare : widths width 0 + g4 (middle - mc) (u - O) + archv + [if ai flat.ai flat] (l + O) (u - sma) + [if ai curl.ai curl] (l + O) (d + smb) + arcvh + g4 (middle + mc) (d + O) + archv + [if ai flat.ai flat] (r - O) (d + sma) + [if ai curl.ai curl] (r - O) (u - smb) + arcvh + close + : else : begin + local ymiddlea : mix d u (smb / (sma + smb)) + local ymiddleb : mix d u (sma / (sma + smb)) + include : spiro + prepare : widths width 0 + g4 (middle - mc) (u - O) + archv + g4 (l + O) ymiddlea + arcvh + g4 (middle + mc) (d + O) + archv + g4 (r - O) ymiddleb + arcvh + close define [HBar xleft xright y _fine] : glyph-construction @@ -343,7 +342,6 @@ define [hookend y p f dontextend] : return {.type 'interpolate' .af [lambda [bef # Derived subfonts define [Fork glyphs params] : begin local p : Object.create params - p.upmscale = 1 local shouldBuildList {} foreach glyphid [items-of glyphs] : set shouldBuildList : shouldBuildList.concat {glyphid :: dependencyProfile.(glyphid)} local forkFont : buildFont p shouldBuildList diff --git a/glyphs/latin-extend-basis.patel b/glyphs/latin-extend-basis.patel index a0809c19a..704f061e6 100644 --- a/glyphs/latin-extend-basis.patel +++ b/glyphs/latin-extend-basis.patel @@ -794,7 +794,7 @@ create-glyph 'glottalstop' : glyph-construction widths.rhs g4 SB (CAP - HOOK) hookstart CAPO - g4 RIGHTSB (CAP - SMOOTHB) + g4 RIGHTSB (CAP - [adviceGlottalStopSmooth CAP 1]) alsothru 0.5 0.45 [widths (ESS / 2) (ESS / 2)] flat (MIDDLE - HALFSTROKE * CORRECTION_HX) (XH * 0.3) [widths STROKE 0] curl (MIDDLE - HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] @@ -806,7 +806,7 @@ create-glyph 'revglottalstop' : glyph-construction widths.lhs g4 RIGHTSB (CAP - HOOK) hookstart CAPO - g4 SB (CAP - SMOOTHB) + g4 SB (CAP - [adviceGlottalStopSmooth CAP (-1)]) alsothru 0.5 0.45 [widths (ESS / 2) (ESS / 2)] flat (MIDDLE + HALFSTROKE * CORRECTION_HX) (XH * 0.3) [widths 0 STROKE] curl (MIDDLE + HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] @@ -818,7 +818,7 @@ create-glyph 'smallglottalstop' : glyph-construction widths.rhs g4 SB (XH - HOOK) hookstart XO - g4 RIGHTSB (XH - SMOOTHB) + g4 RIGHTSB (XH - [adviceGlottalStopSmooth XH 1]) alsothru 0.5 0.45 [widths (ESS / 2) (ESS / 2)] flat (MIDDLE - HALFSTROKE * CORRECTION_HX) (XH * 0.15) [widths STROKE 0] curl (MIDDLE - HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] @@ -830,7 +830,7 @@ create-glyph 'invglottalstopbar' : glyph-construction widths.lhs g4 RIGHTSB (XH - HOOK) hookstart XO - g4 SB (XH - SMOOTHB) + g4 SB (XH - [adviceGlottalStopSmooth XH 1]) alsothru 0.5 0.45 [widths (ESS / 2) (ESS / 2)] flat (MIDDLE + HALFSTROKE * CORRECTION_HX) (XH * 0.15) [widths 0 STROKE] curl (MIDDLE + HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] @@ -843,7 +843,7 @@ create-glyph 'fineglottalstop' : glyph-construction widths.rhs (markHalfStroke * 2) g4 SB (CAP - HOOK) hookstart CAPO - g4 RIGHTSB (CAP - SMOOTHB) + g4 RIGHTSB (CAP - [adviceGlottalStopSmooth CAP 1]) alsothru 0.5 0.45 [widths markHalfStroke markHalfStroke] flat (MIDDLE - HALFSTROKE * CORRECTION_HX) (XH * 0.3) [widths (markHalfStroke * 2) 0] curl (MIDDLE - HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] @@ -854,7 +854,7 @@ create-glyph 'finerevglottalstop' : glyph-construction widths.lhs (markHalfStroke * 2) g4 RIGHTSB (CAP - HOOK) hookstart CAPO - g4 SB (CAP - SMOOTHB) + g4 SB (CAP - [adviceGlottalStopSmooth CAP (-1)]) alsothru 0.5 0.45 [widths markHalfStroke markHalfStroke] flat (MIDDLE + HALFSTROKE * CORRECTION_HX) (XH * 0.3) [widths 0 (markHalfStroke * 2)] curl (MIDDLE + HALFSTROKE * CORRECTION_HX) 0 [heading DOWNWARD] diff --git a/glyphs/latin-extend-decorated.patel b/glyphs/latin-extend-decorated.patel index cc5239a09..f75ea60b1 100644 --- a/glyphs/latin-extend-decorated.patel +++ b/glyphs/latin-extend-decorated.patel @@ -865,12 +865,13 @@ define [ErTail left w dohook] : glyph-construction local right WIDTH local mid : mix left right 0.5 local rise : (WIDTH - left) * 0.3 + local sw : fallback w (markFine * 2) include : spiro - widths.center - g2 (left - markFine * 2 * CORRECTION_HX) (XH * 0.5) - g2 (mid - markFine * 2 * CORRECTION_HX) (XH * 0.5 + rise) [widths 0 STROKE] + widths.center sw + g2 (left) (XH * 0.5) + g2 (mid - sw * CORRECTION_HX) (XH * 0.5 + rise) [widths 0 sw] include : spiro - widths.rhs [fallback w (markFine * 2)] + widths.rhs sw flat mid (XH * 0.5 + rise) [heading DOWNWARD] curl mid (XH * 0.5 + [if dohook 0 (rise - 1)]) [heading DOWNWARD] if dohook {[hookend (XH * 0.5 - rise)]} {[arcvh]} @@ -879,20 +880,20 @@ define [ErTail left w dohook] : glyph-construction create-glyph 'rhotichook' : glyph-construction assign-unicode 0x2DE - include : ErTail 0 STROKE true + include : ErTail (-STROKE * CORRECTION_HX) STROKE true create-glyph 'er' : glyph-construction assign-unicode 0x25A include eMarks local f : Thinner {'schwa'} 0.85 include f.schwa - include : ErTail (WIDTH * 0.85 - SB) + include : ErTail (WIDTH * 0.85 - SB - markFine * CORRECTION_HX) create-glyph 'revlatinepsiloner' : glyph-construction assign-unicode 0x25D include eMarks local f : Thinner {'revlatinepsilon'} 0.85 include f.revlatinepsilon - include : ErTail (WIDTH * 0.85 - SB) + include : ErTail (WIDTH * 0.85 - SB - markFine * CORRECTION_HX) # Belted define [Belt] : glyph-construction diff --git a/glyphs/numbers.patel b/glyphs/numbers.patel index 48947eed1..1764f03da 100644 --- a/glyphs/numbers.patel +++ b/glyphs/numbers.patel @@ -158,24 +158,23 @@ create-glyph 'eight' : glyph-construction set-width WIDTH assign-unicode '8' - local sma : SMOOTHA * 0.975 + CORRECTION_VS * CORRECTION_HX - local smb : SMOOTHB * 0.975 - CORRECTION_VS * CORRECTION_HX + local sm : SMOOTH * 0.975 local p 0.96 include : spiro widths.lhs - g4 (MIDDLE - CORRECTION_OMIDS + CORRECTION_VS) (CAP - O - STROKE) + g4 (MIDDLE) (CAP - O - STROKE) [heading RIGHTWARD] archv 1 - g4 ([mix SB RIGHTSB p] - STROKE) (CAP - smb * p) + g4 ([mix SB RIGHTSB p] - STROKE) (CAP - sm * p) [heading DOWNWARD] alsothru 0.5 0.5 [widths HALFSTROKE HALFSTROKE] - g4 (SB + STROKE) smb [widths 0 STROKE] + g4 (SB + STROKE) sm [widths.heading 0 STROKE DOWNWARD] arcvh 1 - g4 (MIDDLE + CORRECTION_OMIDS - CORRECTION_VS) (O + STROKE) + g4 (MIDDLE) (O + STROKE) [heading RIGHTWARD] archv 1 - g4 (RIGHTSB - STROKE) sma [widths 0 STROKE] + g4 (RIGHTSB - STROKE) sm [widths.heading 0 STROKE UPWARD] alsothru 0.5 0.5 [widths HALFSTROKE HALFSTROKE] - g4 ([mix RIGHTSB SB p] + STROKE) (CAP - sma * p) [widths STROKE 0] + g4 ([mix RIGHTSB SB p] + STROKE) (CAP - sm * p) [widths.heading STROKE 0 UPWARD] arcvh 1 close diff --git a/makefile b/makefile index 13c7c17fb..db7b7f3c8 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ TARGETUPM = 1000 -SUPPORT_FILES = support/glyph.js support/stroke.js support/spiroexpand.js parameters.js generate.js emptyfont.toml parameters.toml +SUPPORT_FILES = support/glyph.js support/stroke.js support/spiroexpand.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-ascii.patel glyphs/symbol-punctuation.patel glyphs/symbol-math.patel glyphs/symbol-geometric.patel glyphs/symbol-other.patel glyphs/symbol-letter.patel glyphs/autobuilds.patel OBJDIR = build @@ -44,7 +44,7 @@ $(OBJDIR)/.pass0-iosevkacc-bolditalic.fdt : $(FILES) | $(OBJDIR) node generate -o $@ iosevka cc w-bold s-italic x-bolditalic $(PASS0) : $(OBJDIR)/.pass0-%.ttf : $(OBJDIR)/.pass0-%.fdt - node extract --ttf $@ $< + node extract --upm 16000 --uprightify 1 --ttf $@ $< $(ABFEAT) : $(OBJDIR)/.pass0-%.ab.fea : $(OBJDIR)/.pass0-%.fdt node extract --feature $@ $< $(MAPS) : $(OBJDIR)/%.charmap : $(OBJDIR)/.pass0-%.fdt diff --git a/parameters.toml b/parameters.toml index e765d35a9..ecf5d47e7 100644 --- a/parameters.toml +++ b/parameters.toml @@ -5,7 +5,6 @@ codename = 'Yoikata' copyright = 'Copyright (c) 2015 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.''' -upmscale = 16 width = 500 cap = 724 xheight = 530