Merged features to otfcc

This commit is contained in:
be5invis 2016-05-01 06:56:11 +08:00
parent 5cf5dc8662
commit 6801aacf27
11 changed files with 274 additions and 300 deletions

View File

@ -32,7 +32,7 @@ Iosevka supports accessing all letter variants using OpenType features.
To build Iosevka you should:
1. Ensure that [`node`](http://nodejs.org) (≥ 5.0), [`FontForge`](http://fontforge.org) (with Python scripting support, ≥ Aug. 2015 release), [`ttfautohint`](http://www.freetype.org/ttfautohint/), [`otfcc`](https://github.com/caryll/otfcc) (≥ 0.1.5) and `make` are runnable in your terminal.
1. Ensure that [`node`](http://nodejs.org) (≥ 5.0), [`FontForge`](http://fontforge.org) (with Python scripting support, ≥ Aug. 2015 release), [`ttfautohint`](http://www.freetype.org/ttfautohint/), [`otfcc`](https://github.com/caryll/otfcc) (≥ 0.1.6) and `make` are runnable in your terminal.
- Windows users may need to install MinGW and make \*nix utilities accessible (`mkdir.exe`, `cp.exe`, `cat.exe` and `rm.exe`, in particular) from Command Prompt. Utilities provided by [Git for Windows](https://git-for-windows.github.io/) works fine.
2. Install necessary libs by `npm install`.
3. `make`.

View File

@ -1,76 +0,0 @@
lookup ccmpSubIota { sub iotaBelow by iotaLF; } ccmpSubIota;
lookup ccmpSubOgonek { sub ogonekBelow by ogonekTR; } ccmpSubOgonek;
lookup ccmpManual1 {
sub [i cyrUkrainiani j cyrje iogonekBelow]' @MG_above by [dotlessi dotlessi dotlessj dotlessj iogonek.dotless];
sub eta iotaBelow' lookup ccmpSubIota;
sub eta @MG_above iotaBelow' lookup ccmpSubIota;
sub eta @MG_above @MG_above iotaBelow' lookup ccmpSubIota;
sub eta @MG_above @MG_above @MG_above iotaBelow' lookup ccmpSubIota;
sub [a A u cyra cyrA] ogonekBelow' lookup ccmpSubOgonek;
sub [a A u cyra cyrA] @MG_above ogonekBelow' lookup ccmpSubOgonek;
sub [a A u cyra cyrA] @MG_above @MG_above ogonekBelow' lookup ccmpSubOgonek;
sub [a A u cyra cyrA] @MG_above @MG_above @MG_above ogonekBelow' lookup ccmpSubOgonek;
} ccmpManual1;
lookup ccmpManual2 {
sub commaAbove graveAbove by psilivaria;
sub commaAbove acuteAbove by psilioxia;
sub commaAbove perispomeniAbove by psiliperispomeni;
sub revCommaAbove graveAbove by dasiavaria;
sub revCommaAbove acuteAbove by dasiaoxia;
sub revCommaAbove perispomeniAbove by dasiaperispomeni;
} ccmpManual2;
feature ccmp {
script latn;
language dflt;
lookup ccmpManual1;
script grek;
language dflt;
lookup ccmpManual1;
lookup ccmpManual2;
script cyrl;
language dflt;
lookup ccmpManual1;
script DFLT;
language dflt;
lookup ccmpManual1;
} ccmp;
feature mark {
script latn;
language dflt;
lookup markAuto_letter1;
lookup markAuto_letter2;
lookup markAuto_overlay;
script grek;
language dflt;
lookup markAuto_letter1;
lookup markAuto_letter2;
lookup markAuto_overlay;
script cyrl;
language dflt;
lookup markAuto_letter1;
lookup markAuto_letter2;
lookup markAuto_overlay;
script DFLT;
language dflt;
lookup markAuto_letter1;
lookup markAuto_letter2;
lookup markAuto_overlay;
} mark;
feature mkmk {
script latn;
language dflt;
lookup mkmkAuto;
script grek;
language dflt;
lookup mkmkAuto;
script cyrl;
language dflt;
lookup mkmkAuto;
script DFLT;
language dflt;
lookup mkmkAuto;
} mkmk;

View File

@ -1,9 +0,0 @@
lookup loclSerbian {
sub [cyrbe cyrghe cyrde cyrpe cyrte] by [cyrbe.serbian cyrghe.serbian cyrde.serbian cyrpe.serbian cyrte.serbian];
} loclSerbian;
feature locl {
script cyrl;
language SRB exclude_dflt;
lookup loclSerbian;
} locl;

View File

@ -1,96 +0,0 @@
# Programming ligations
lookup arrowStickFR { sub [hyphen equal] by [lighy.fr ligeq.fr]; } arrowStickFR;
lookup arrowStickLF { sub [hyphen equal] by [lighy.lf ligeq.lf]; } arrowStickLF;
lookup arrowStickFR1 { sub [hyphen equal] by [lighy.fr1 ligeq.fr1]; } arrowStickFR1;
lookup arrowStickL1F { sub [hyphen equal] by [lighy.l1f ligeq.l1f]; } arrowStickL1F;
lookup arrowStickCR { sub [hyphen equal] by [lighy.cr ligeq.cr]; } arrowStickCR;
lookup arrowStickLC { sub [hyphen equal] by [lighy.lc ligeq.lc]; } arrowStickLC;
lookup arrowStickLXC { sub [hyphen equal] by [lighy.lxc ligeq.lxc]; } arrowStickLXC;
lookup arrowStickCF { sub [hyphen equal] by [lighy.cf ligeq.cf]; } arrowStickCF;
lookup arrowStickFC { sub [hyphen equal] by [lighy.fc ligeq.fc]; } arrowStickFC;
lookup arrowStickJF { sub [hyphen equal] by [lighy.jf ligeq.jf]; } arrowStickJF;
lookup arrowStickFJ { sub [hyphen equal] by [lighy.fj ligeq.fj]; } arrowStickFJ;
lookup arrowStickJ1F { sub [hyphen equal] by [lighy.j1f ligeq.j1f]; } arrowStickJ1F;
lookup arrowStickFJ1 { sub [hyphen equal] by [lighy.fj1 ligeq.fj1]; } arrowStickFJ1;
lookup arrowStickJR { sub [hyphen equal] by [lighy.jr ligeq.jr]; } arrowStickJR;
lookup arrowStickLJ { sub [hyphen equal] by [lighy.lj ligeq.lj]; } arrowStickLJ;
lookup arrowStickLR { sub [hyphen equal] by [lighy.lr ligeq.lr]; } arrowStickLR;
lookup lessShift1 { sub less by ligless.shift1; } lessShift1;
lookup greaterShift1 { sub greater by liggreater.shift1; } greaterShift1;
lookup lessShiftN1 { sub less by ligless.shiftN1; } lessShiftN1;
lookup greaterShiftN1 { sub greater by liggreater.shiftN1; } greaterShiftN1;
lookup arrowExclamHTMLComment { sub exclam by ligexclam.htmlcommentstart; } arrowExclamHTMLComment;
@arrowstick = [hyphen equal];
lookup caltArrow1 {
# Arrows, sub
sub less @arrowstick' lookup arrowStickLC @arrowstick' lookup arrowStickCR greater; # <-->, <==>
sub less @arrowstick' lookup arrowStickLR greater; # <->, <=>
sub less @arrowstick' lookup arrowStickLJ less; # <-<, <=<
sub less @arrowstick' lookup arrowStickLC @arrowstick' lookup arrowStickCF; # <--, <==
sub less less' lookup lessShift1 @arrowstick' lookup arrowStickL1F; # <<-, <<=
sub less hyphen' lookup arrowStickLF; # <-
sub less exclam' lookup arrowExclamHTMLComment hyphen' lookup arrowStickLXC hyphen' lookup arrowStickCF; # <!--
sub greater greater' lookup greaterShiftN1 @arrowstick' lookup arrowStickJ1F; # >>-, >>=
sub greater @arrowstick' lookup arrowStickJR greater; # >->, >=>
sub greater [hyphen]' lookup arrowStickJF; # >-
sub @arrowstick' lookup arrowStickFC @arrowstick' lookup arrowStickCR greater; # -->, ==>
sub @arrowstick' lookup arrowStickFR1 greater' lookup greaterShift1 greater; # ->>, =>>
sub @arrowstick' lookup arrowStickFR greater; # ->, =>
sub @arrowstick' lookup arrowStickFJ1 less' lookup lessShiftN1 less; # -<<, =<<
sub @arrowstick' lookup arrowStickFJ less; # -<, =<
} caltArrow1;
feature calt {
script latn;
language dflt;
lookup caltArrow1;
script grek;
language dflt;
lookup caltArrow1;
script cyrl;
language dflt;
lookup caltArrow1;
script DFLT;
language dflt;
lookup caltArrow1;
} calt;
@fwclose = [fwlcloseDoubleQuote fwlcloseSingleQuote dwlcjkSingleQuoteRight dwlcjkDoubleQuoteRight dwlparenRight];
@hwclose = [closeDoubleQuote closeSingleQuote cjkSingleQuoteRight cjkDoubleQuoteRight parenRight];
@fwopen = [fwropenDoubleQuote fwropenSingleQuote dwrcjkSingleQuoteLeft dwrcjkDoubleQuoteLeft dwrparenLeft];
@hwopen = [openDoubleQuote openSingleQuote cjkSingleQuoteLeft cjkDoubleQuoteLeft parenLeft];
@fwquoteopen = [fwropenDoubleQuote fwropenSingleQuote];
@hwquoteopen = [openDoubleQuote openSingleQuote];
@fwtrail = [dwlperiod dwlcomma dwlcjkperiod dwlcjkcomma];
@hwtrail = [period comma cjkperiod cjkcomma];
@fwmid = [dwccolon dwcsemicolon];
@hwmid = [colon semicolon];
lookup cjkCompress {
sub [@fwtrail @hwtrail @fwopen @hwopen @fwmid @hwmid] @fwopen' by @hwopen;
sub @fwclose' [@fwtrail @hwtrail @fwclose @hwclose @fwopen @hwopen @fwmid @hwmid] by @hwclose;
} cjkCompress;
feature opbd {
script latn;
language dflt;
lookup cjkCompress;
script grek;
language dflt;
lookup cjkCompress;
script cyrl;
language dflt;
lookup cjkCompress;
script hani;
language dflt;
lookup cjkCompress;
script kana;
language dflt;
lookup cjkCompress;
script DFLT;
language dflt;
lookup cjkCompress;
} opbd;

View File

@ -1,9 +0,0 @@
lookup loclSerbian {
sub [cyrbe] by [cyrbe.serbian];
} loclSerbian;
feature locl {
script cyrl;
language SRB exclude_dflt;
lookup loclSerbian;
} locl;

View File

@ -44,44 +44,11 @@ if (argv.charmap) (function() {
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';
}
// MG groups
for (var key in font.features.markGlyphs) {
featurefile += '@MG_' + key + '= [' + font.features.markGlyphs[key].join(' ') + '];\n'
}
// mark
var mark = font.features.mark;
for (var id in mark) {
var lookup = mark[id];
var lookupName = 'markAuto_' + id;
featurefile += 'lookup ' + lookupName + ' {' + lookup.marks.join(';\n') + ';\n'
+ lookup.bases.join(';\n') + ';} ' + lookupName + ';'
}
// mkmk
var mkmk = font.features.mkmk;
featurefile += 'lookup mkmkAuto {' + mkmk.marks.join(';\n') + ';\n'
+ mkmk.bases.join(';\n') + ';} mkmkAuto;'
// 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') + '];\n'
+ 'table GDEF { GlyphClassDef @GDEF_Simple, @GDEF_Ligature, @GDEF_Mark, ;} GDEF;'
featurefile += fs.readFileSync(__dirname + '/features/common.fea', 'utf-8');
featurefile += fs.readFileSync(__dirname + '/features/' + (font.parameters.isItalic ? 'italiconly.fea' : 'uprightonly.fea'), 'utf-8');

View File

@ -821,25 +821,43 @@ if [not recursive] : begin
set glyphList.length font.glyf.length
for [local j 0] (j < font.glyf.length) [inc j] : set glyphList.(j) font.glyf.(j)
set font.features.cv {.}
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)
set font.features.mark {.}
set font.features.mkmk {.marks {} .bases {}}
set font.features.markGlyphs {.}
set font.features.gdef {.simple {} .ligature {} .mark {}}
define [buildAnchorDescription glyph inserter propx propy prefix th] : begin
local buf ''
foreach key [items-of : Object.keys glyph.anchors] : if (!th || th.(key)) : buf = buf + ' <anchor ' + [Math.round glyph.anchors.(key).(propx)] + ' ' + [Math.round glyph.anchors.(key).(propy)] + '> ' + inserter + ' @' + prefix + key
return buf
# GPOS mark and mkmk
local markGlyphs {.}
# mark
define [createMarkLookup tableName anchorClasses] : let [lookup : set font.features.mark.(tableName) {.marks {} .bases {}}] : begin
local lookup_mark
.type 'gpos_mark_to_base'
.subtables {}
local lookup_mkmk
.type 'gpos_mark_to_mark'
.subtables {}
set font.GPOS : object
languages
.DFLT_DFLT {.features {'mark0', 'mkmk0'}}
.latn_DFLT {.features {'mark0', 'mkmk0'}}
.grek_DFLT {.features {'mark0', 'mkmk0'}}
.cyrl_DFLT {.features {'mark0', 'mkmk0'}}
features
.mark0 {'l_mark'}
.mkmk0 {'l_mkmk'}
lookups
.l_mark lookup_mark
.l_mkmk lookup_mkmk
set font.GDEF {.glyphClassDef {.}}
# mark and mkmk
define [createBaseInfo g th px py] : begin
local res {.}
local pushed false
foreach key [items-of : Object.keys g.anchors] : if (!th || th.(key)) : begin
set res.(key) : object
.x g.anchors.(key).(px || 'x')
.y g.anchors.(key).(py || 'y')
set pushed true
return : if pushed res nothing
define [createMTSSubtable lookup anchorClasses] : begin
local subtable {.marks {.} .bases {.}}
local th {.}
foreach [ac : items-of anchorClasses] : set th.(ac) true
foreach glyph [items-of glyphList] : if glyph.anchors : begin
@ -848,29 +866,214 @@ if [not recursive] : begin
foreach [key : items-of anchorKeys] : if th.(key) : set hasAnchor true
if hasAnchor : begin
local isMarkGlyph false
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : set isMarkGlyph true
local markKey nothing
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : begin
set isMarkGlyph true
set markKey key
if isMarkGlyph
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]
: then : begin
set subtable.marks.(glyph.name) : object
class markKey
x glyph.anchors.(markKey).x
y glyph.anchors.(markKey).y
if (lookup == lookup_mkmk) : begin
local r : createBaseInfo glyph th 'mbx' 'mby'
if r : set subtable.bases.(glyph.name) r
: else : if (lookup == lookup_mark) : begin
local r : createBaseInfo glyph th 'x' 'y'
if r : set subtable.bases.(glyph.name) r
lookup.subtables.push subtable
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])
then
local isMarkGlyph false
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : set isMarkGlyph true
createMTSSubtable lookup_mark {'above' 'below' 'overlay' 'slash'}
createMTSSubtable lookup_mark {'trailing' 'lf' 'topright' 'bottomright'}
createMTSSubtable lookup_mkmk {'above'}
createMTSSubtable lookup_mkmk {'below'}
createMTSSubtable lookup_mkmk {'trailing' 'lf' 'topright' 'bottomright' 'overlay' 'slash'}
# GDEF
foreach glyph [items-of glyphList] : begin
set font.GDEF.glyphClassDef.(glyph.name) : if [[regex '_'].test glyph.name] 2 1
if (glyph.anchors && [begin [local anchorKeys : Object.keys glyph.anchors] anchorKeys.length]) : begin
foreach key [items-of anchorKeys] : if (glyph.anchors.(key).type == 'mark') : begin
if [not markGlyphs.(key)] : set markGlyphs.(key) {}
markGlyphs.(key).push glyph.name
set font.GDEF.glyphClassDef.(glyph.name) 3
# GSUB
let : begin
local commonList {}
local languages
.DFLT_DFLT {.features commonList}
.latn_DFLT {.features commonList}
.grek_DFLT {.features commonList}
.cyrl_DFLT {.features commonList}
.kana_DFLT {.features commonList}
.hani_DFLT {.features commonList}
local features {.}
local lookups {.}
define [lookup-single name f t] : begin
local subtable {.}
set lookups.(name) {.type 'gsub_single' .subtables {subtable}}
foreach [j : range 0 f.length] : set subtable.(f.(j)) t.(j)
define [chain-rule] : begin
local terms : {}.slice.call arguments 0
local subtable {.match {} .apply {} .inputBegins 0 .inputEnds 0}
local foundi false
local founde false
foreach [j : range 0 terms.length] : if (!foundi && terms.(j).1) : begin
set subtable.inputBegins j
set foundi true
foreach [j : range (terms.length - 1) downtill 0] : if (!founde && terms.(j).1) : begin
set subtable.inputEnds (j + 1)
set founde true
foreach [j : range 0 terms.length] : begin
local term terms.(j)
subtable.match.push term.0
if term.1 : begin
subtable.apply.push {.at j .lookup term.1}
return subtable
define [flatten] : begin
local ans {}
foreach [term : items-of : {}.slice.call arguments 0] : begin
if (term <@ Array)
: then : set ans : ans.concat term
: else : ans.push term
return ans
# cvxx
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 lookups.(feature)] : begin
set features.(feature) {feature}
set lookups.(feature) {.type 'gsub_single' .subtables{{.}}}
commonList.push feature
set lookups.(feature).subtables.0.(name) fs.(feature)
# ssxx
foreach [name : items-of : Object.keys para.sscompose] : begin
commonList.push name
set features.(name) para.sscompose.(name)
#ccmp
commonList.push 'ccmp'
set features.ccmp {'ccmp1' 'ccmp2'}
set lookups.ccmpSubIota {.type 'gsub_single' .subtables {{.iotaBelow 'iotaLF'}}}
set lookups.ccmpSubOgonek {.type 'gsub_single' .subtables {{.ogonekBelow 'ogonekTR'}}}
set lookups.ccmpSubIJ {.type 'gsub_single' .subtables {{
.i 'dotlessi'
.cyrUkrainiani 'dotlessi'
.j 'dotlessj'
.cyrje 'dotlessj'
.iogonekBelow 'iogonek.dotless'
}}}
set lookups.ccmp1
.type 'gsub_chaining'
.subtables : list
chain-rule {{'i' 'cyrUkrainiani' 'j' 'cyrje' 'iogonekBelow'} 'ccmpSubIJ'} {markGlyphs.above}
chain-rule {{'eta'}} {{'iotaBelow'} 'ccmpSubIota'}
chain-rule {{'eta'}} {markGlyphs.above} {{'iotaBelow'} 'ccmpSubIota'}
chain-rule {{'eta'}} {markGlyphs.above} {markGlyphs.above} {{'iotaBelow'} 'ccmpSubIota'}
chain-rule {{'eta'}} {markGlyphs.above} {markGlyphs.above} {markGlyphs.above} {{'iotaBelow'} 'ccmpSubIota'}
chain-rule {{'A' 'a' 'u' 'cyrA' 'cyra'}} {{'ogonekBelow'} 'ccmpSubOgonek'}
chain-rule {{'A' 'a' 'u' 'cyrA' 'cyra'}} {markGlyphs.above} {{'ogonekBelow'} 'ccmpSubOgonek'}
chain-rule {{'A' 'a' 'u' 'cyrA' 'cyra'}} {markGlyphs.above} {markGlyphs.above} {{'ogonekBelow'} 'ccmpSubOgonek'}
chain-rule {{'A' 'a' 'u' 'cyrA' 'cyra'}} {markGlyphs.above} {markGlyphs.above} {markGlyphs.above} {{'ogonekBelow'} 'ccmpSubOgonek'}
set lookups.ccmp2
.type 'gsub_ligature'
.subtables : list : object
psilivaria {'commaAbove' 'graveAbove'}
psilioxia {'commaAbove' 'acuteAbove'}
psiliperispomeni {'commaAbove' 'perispomeniAbove'}
dasiavaria {'revCommaAbove' 'graveAbove'}
dasiaoxia {'revCommaAbove' 'acuteAbove'}
dasiaperispomeni {'revCommaAbove' 'perispomeniAbove'}
if (para.spacing > 0) : let : begin
#calt
local arrowStick {'hyphen' 'equal'}
local less {'less'}
local greater {'greater'}
lookup-single 'arrowStickFR' {'hyphen' 'equal'} {'lighy.fr' 'ligeq.fr'}
lookup-single 'arrowStickLF' {'hyphen' 'equal'} {'lighy.lf' 'ligeq.lf'}
lookup-single 'arrowStickFR1' {'hyphen' 'equal'} {'lighy.fr1' 'ligeq.fr1'}
lookup-single 'arrowStickL1F' {'hyphen' 'equal'} {'lighy.l1f' 'ligeq.l1f'}
lookup-single 'arrowStickCR' {'hyphen' 'equal'} {'lighy.cr' 'ligeq.cr'}
lookup-single 'arrowStickLC' {'hyphen' 'equal'} {'lighy.lc' 'ligeq.lc'}
lookup-single 'arrowStickLXC' {'hyphen' 'equal'} {'lighy.lxc' 'ligeq.lxc'}
lookup-single 'arrowStickCF' {'hyphen' 'equal'} {'lighy.cf' 'ligeq.cf'}
lookup-single 'arrowStickFC' {'hyphen' 'equal'} {'lighy.fc' 'ligeq.fc'}
lookup-single 'arrowStickJF' {'hyphen' 'equal'} {'lighy.jf' 'ligeq.jf'}
lookup-single 'arrowStickFJ' {'hyphen' 'equal'} {'lighy.fj' 'ligeq.fj'}
lookup-single 'arrowStickJ1F' {'hyphen' 'equal'} {'lighy.j1f' 'ligeq.j1f'}
lookup-single 'arrowStickFJ1' {'hyphen' 'equal'} {'lighy.fj1' 'ligeq.fj1'}
lookup-single 'arrowStickJR' {'hyphen' 'equal'} {'lighy.jr' 'ligeq.jr'}
lookup-single 'arrowStickLJ' {'hyphen' 'equal'} {'lighy.lj' 'ligeq.lj'}
lookup-single 'arrowStickLR' {'hyphen' 'equal'} {'lighy.lr' 'ligeq.lr'}
if isMarkGlyph
then
font.features.mkmk.marks.push : 'markClass ' + glyph.name + ' ' + [buildAnchorDescription glyph '' 'x' 'y' 'mkmk']
font.features.mkmk.bases.push : 'pos mark ' + glyph.name + ' ' + [buildAnchorDescription glyph 'mark' 'mbx' 'mby' 'mkmk']
foreach key [items-of anchorKeys] : begin
if [not font.features.markGlyphs.(key)] : set font.features.markGlyphs.(key) {}
font.features.markGlyphs.(key).push glyph.name
font.features.gdef.mark.push glyph.name
else : if [[regex '_'].test glyph.name] [font.features.gdef.ligature.push glyph.name] [font.features.gdef.simple.push glyph.name]
else : if [[regex '_'].test glyph.name] [font.features.gdef.ligature.push glyph.name] [font.features.gdef.simple.push glyph.name]
lookup-single 'lessShift1' {'less'} {'ligless.shift1'}
lookup-single 'greaterShift1' {'greater'} {'liggreater.shift1'}
lookup-single 'lessShiftN1' {'less'} {'ligless.shiftN1'}
lookup-single 'greaterShiftN1' {'greater'} {'liggreater.shiftN1'}
lookup-single 'arrowExclamHTMLComment' {'exclam'} {'ligexclam.htmlcommentstart'}
commonList.push 'calt'
set features.calt {'caltArrow1'}
set lookups.caltArrow1
.type 'gsub_chaining'
.subtables : list
chain-rule {less} {arrowStick 'arrowStickLC'} {arrowStick 'arrowStickCR'} {greater}
chain-rule {less} {arrowStick 'arrowStickLR'} {greater} # <->, <=>
chain-rule {less} {arrowStick 'arrowStickLJ'} {less} # <-<, <=<
chain-rule {less} {arrowStick 'arrowStickLC'} {arrowStick 'arrowStickCF'} # <--, <==
chain-rule {less} {less 'lessShift1'} {arrowStick 'arrowStickL1F'} # <<-, <<=
chain-rule {less} {{'hyphen'} 'arrowStickLF'} # <-
chain-rule {less} {{'exclam'} 'arrowExclamHTMLComment'} {{'hyphen'} 'arrowStickLXC'} {{'hyphen'} 'arrowStickCF'} # <!--
chain-rule {greater} {greater 'greaterShiftN1'} {arrowStick 'arrowStickJ1F'} # >>-, >>=
chain-rule {greater} {arrowStick 'arrowStickJR'} {greater} # >->, >=>
chain-rule {greater} {{'hyphen'} 'arrowStickJF'} # >-
chain-rule {arrowStick 'arrowStickFC'} {arrowStick 'arrowStickCR'} {greater} # -->, ==>
chain-rule {arrowStick 'arrowStickFR1'} {greater 'greaterShift1'} {greater} # ->>, =>>
chain-rule {arrowStick 'arrowStickFR'} {greater} # ->, =>
chain-rule {arrowStick 'arrowStickFJ1'} {less 'lessShiftN1'} {less} # -<<, =<<
chain-rule {arrowStick 'arrowStickFJ'} {less} # -<, =<
#opbd
local fwclose {'fwlcloseDoubleQuote' 'fwlcloseSingleQuote' 'dwlcjkSingleQuoteRight' 'dwlcjkDoubleQuoteRight' 'dwlparenRight'}
local hwclose {'closeDoubleQuote' 'closeSingleQuote' 'cjkSingleQuoteRight' 'cjkDoubleQuoteRight' 'parenRight'}
local fwopen {'fwropenDoubleQuote' 'fwropenSingleQuote' 'dwrcjkSingleQuoteLeft' 'dwrcjkDoubleQuoteLeft' 'dwrparenLeft'}
local hwopen {'openDoubleQuote' 'openSingleQuote' 'cjkSingleQuoteLeft' 'cjkDoubleQuoteLeft' 'parenLeft'}
local fwquoteopen {'fwropenDoubleQuote' 'fwropenSingleQuote'}
local hwquoteopen {'openDoubleQuote' 'openSingleQuote'}
local fwtrail {'dwlperiod' 'dwlcomma' 'dwlcjkperiod' 'dwlcjkcomma'}
local hwtrail {'period' 'comma' 'cjkperiod' 'cjkcomma'}
local fwmid {'dwccolon' 'dwcsemicolon'}
local hwmid {'colon' 'semicolon'}
lookup-single 'closefw' [flatten fwopen fwclose] [flatten hwopen hwclose]
commonList.push 'opbd'
set features.opbd {'opbd1'}
set lookups.opbd1
.type 'gsub_chaining'
.subtables : list
chain-rule {[flatten fwtrail hwtrail fwopen hwopen fwmid hwmid]} {fwopen 'closefw'}
chain-rule {fwclose 'closefw'} {[flatten fwtrail hwtrail fwclose hwclose fwopen hwopen fwmid hwmid]}
#localized SRB
local srbSubtable null
if para.isItalic
: then : set srbSubtable : object
cyrbe 'cyrbe.serbian'
cyrghe 'cyrghe.serbian'
cyrde 'cyrde.serbian'
cyrpe 'cyrpe.serbian'
cyrte 'cyrte.serbian'
: else : set srbSubtable : object
cyrbe 'cyrbe.serbian'
set lookups.locl_srb {.type 'gsub_single' .subtables {srbSubtable}}
set features.locl_srb {'locl_srb'}
set languages.'cyrl_SRB ' {.features [{'locl_srb'}.concat commonList]}
set font.GSUB {.languages languages .features features .lookups lookups}
progress 'Features'

View File

@ -32,12 +32,9 @@ OBLIQUE = $(OBJDIR)/$(PREFIX)-thinoblique.ttf $(OBJDIR)/$(PREFIX)-extralightobli
TARGETS = $(UPRIGHT) $(ITALIC) $(OBLIQUE)
MAPS = $(if $(NOCHARMAP),,$(OBJDIR)/$(PREFIX)-regular.charmap)
FEASRC = features/common.fea features/ligation.fea features/uprightonly.fea features/italiconly.fea
FDTS = $(subst .ttf,.fdt,$(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS)))
SVG0 = $(subst .ttf,.svg,$(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS)))
FEATURE = $(subst .ttf,.fea,$(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS)))
PASS1 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS))
PASS1 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass1-,$(TARGETS))
PASS2 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass2-,$(TARGETS))
@ -48,64 +45,62 @@ fonts : $(DISTTARGETS)
svgs : $(SVG0)
# Pass 0 : file construction
OUTPUTS = --meta $@ --feature $(subst .fdt,.fea,$@) --svg $(subst .fdt,.svg,$@)
OUTPUTS = --meta $@ --svg $(subst .fdt,.svg,$@)
OUTPUT_CM = $(if $(NOCHARMAP),,--charmap $(subst .fdt,.charmap,$(subst $(OBJDIR)/.pass0-,$(OBJDIR)/,$@)))
$(OBJDIR)/.pass0-$(PREFIX)-thin.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-thin.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-thin s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-extralight.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-extralight.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-extralight s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-light.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-light.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-light s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-regular.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-regular.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-book s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) $(OUTPUT_CM)
$(OBJDIR)/.pass0-$(PREFIX)-medium.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-medium.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-medium s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-bold.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-bold.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-bold s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-heavy.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-heavy.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-heavy s-upright $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS)
$(OBJDIR)/.pass0-$(PREFIX)-thinitalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-thinitalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-thin s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-extralightitalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-extralightitalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-extralight s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-lightitalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-lightitalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-light s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-italic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-italic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-book s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-mediumitalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-mediumitalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-medium s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-bolditalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-bolditalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-bold s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-heavyitalic.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-heavyitalic.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-heavy s-italic $(STYLE_ITALIC) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-thinoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-thinoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-thin s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-extralightoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-extralightoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-extralight s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-lightoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-lightoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-light s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-oblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-oblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-book s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-mediumoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-mediumoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-medium s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-boldoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-boldoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-bold s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(OBJDIR)/.pass0-$(PREFIX)-heavyoblique.fdt : $(SCRIPTS) $(FEASRC) | $(OBJDIR) $(DISTDIR)
$(OBJDIR)/.pass0-$(PREFIX)-heavyoblique.fdt : $(SCRIPTS) | $(OBJDIR) $(DISTDIR)
$(NODE_FDT) generator iosevka $(STYLE_COMMON) w-heavy s-oblique $(STYLE_UPRIGHT) $(STYLE_SUFFIX) $(OUTPUTS) --uprightify 1
$(SVG0) : $(OBJDIR)/.pass0-%.svg : $(OBJDIR)/.pass0-%.fdt
$(PASS)
$(FEATURE) : $(OBJDIR)/.pass0-%.fea : $(OBJDIR)/.pass0-%.fdt
$(PASS)
$(MAPS) : $(OBJDIR)/%.charmap : $(OBJDIR)/.pass0-%.fdt
$(PASS)
HINT = ttfautohint --increase-x-height=0
# Pass 1 : Outline cleanup and merge features
$(PASS1) : $(OBJDIR)/.pass1-%.ttf : pass1-cleanup.py $(OBJDIR)/.pass0-%.svg $(OBJDIR)/.pass0-%.fea
$(PASS1) : $(OBJDIR)/.pass1-%.ttf : pass1-cleanup.py $(OBJDIR)/.pass0-%.svg
@fontforge -quiet -script $^ $@.a.ttf $(if $(findstring italic,$@),10,$(if $(findstring oblique,$@),10,0)) $(FAST) $(SUPPRESS_ERRORS)
@$(HINT) $@.a.ttf $@
@-rm $@.a.ttf

View File

@ -5,7 +5,6 @@ import sys
source = sys.argv[1]
font = fontforge.open(source)
font.mergeFeature(sys.argv[2])
font.selection.all()
# Replace accented characters into references
font.selection.select(("ranges", "unicode", None), 0x1FCD, 0x1FCF, 0x1FDD, 0x1FDF)
@ -40,7 +39,7 @@ font.simplify(0.05, ("smoothcurves", "choosehv"), 0.1)
#font.em = 2000
font.selection.all()
font.layers["Fore"].is_quadratic = True
font.transform(psMat.skew(float(sys.argv[4]) / 180 * math.pi))
font.transform(psMat.skew(float(sys.argv[3]) / 180 * math.pi))
font.em = 1000
font.selection.all()
@ -52,4 +51,4 @@ font.removeOverlap()
font.canonicalContours()
font.canonicalStart()
font.generate(sys.argv[3], flags = ("opentype"))
font.generate(sys.argv[2], flags = ("opentype"))

View File

@ -18,8 +18,8 @@ process.stdin.on('end', function () {
ttf.cvt_ = glyfs.cvt_;
ttf.maxp = glyfs.maxp;
ttf.gasp = glyfs.gasp;
ttf.GDEF = glyfs.GDEF;
ttf.GSUB = glyfs.GSUB;
ttf.GPOS = glyfs.GPOS;
//ttf.GDEF = glyfs.GDEF;
//ttf.GSUB = glyfs.GSUB;
//ttf.GPOS = glyfs.GPOS;
process.stdout.write(JSON.stringify(ttf));
});

View File

@ -201,7 +201,7 @@
</div>
</div>
<div id="display" class="show {{currentFont.cls}}">
<p class="waterfall" v-for="size in waterfall" style="font-size:{{size / 14}}rem">float Fox.quick(h){!isBrown &amp;&amp; jumpOver(doges.lazy)}</p>
<p class="waterfall" v-for="size in waterfall" style="font-size:{{size / 14}}rem">float Fox.quick(h){!isBrown &amp;&amp; jumpO&#x0336;&#x0338;ver(doges&#x0320;&#x0323;&#x0301;.lazy)}</p>
<p class="lipsum" v-for="item in lipsums">{{item}}</p>
<pre class="langs"><code class=patel><span class=keyword>define</span> samples : <span class=keyword>object</span><template v-for="sample in samples">
{<span class=qualifier>.lang</span> <span class=string>'{{sample.lang}}'</span>{{sample.spaces}}<span class=qualifier>.sample</span> <span class=string lang="{{sample.code}}">'{{{sample.sample}}}'</span>}<span class=comment>{{sample.comment}}</span></template></code></pre>