Added ccmp feature.
This commit is contained in:
parent
8b712ef1eb
commit
04117471cb
6 changed files with 54 additions and 24 deletions
|
@ -18,6 +18,6 @@
|
||||||
"postScriptName": "node-sfnt"
|
"postScriptName": "node-sfnt"
|
||||||
},
|
},
|
||||||
"hhea":{"version":1,"ascent":812,"descent":-212,"lineGap":92,"advanceWidthMax":374,"minLeftSideBearing":34,"minRightSideBearing":68,"xMaxExtent":306,"caretSlopeRise":1,"caretSlopeRun":0,"caretOffset":0,"reserved0":0,"reserved1":0,"reserved2":0,"reserved3":0,"metricDataFormat":0,"numOfLongHorMetrics":1},
|
"hhea":{"version":1,"ascent":812,"descent":-212,"lineGap":92,"advanceWidthMax":374,"minLeftSideBearing":34,"minRightSideBearing":68,"xMaxExtent":306,"caretSlopeRise":1,"caretSlopeRun":0,"caretOffset":0,"reserved0":0,"reserved1":0,"reserved2":0,"reserved3":0,"metricDataFormat":0,"numOfLongHorMetrics":1},
|
||||||
"post":{"italicAngle":0,"postoints":65411,"underlinePosition":50,"underlineThickness":0,"isFixedPitch":0,"minMemType42":0,"maxMemType42":0,"minMemType1":0,"maxMemType1":1,"format":3},
|
"post":{"italicAngle":0,"postoints":65411,"underlinePosition":50,"underlineThickness":0,"isFixedPitch":0,"minMemType42":0,"maxMemType42":0,"minMemType1":0,"maxMemType1":1,"format":2},
|
||||||
"OS/2":{"version":4,"xAvgCharWidth":1031,"usWeightClass":400,"usWidthClass":5,"fsType":0,"ySubscriptXSize":665,"ySubscriptYSize":716,"ySubscriptXOffset":0,"ySubscriptYOffset":143,"ySuperscriptXSize":665,"ySuperscriptYSize":716,"ySuperscriptXOffset":0,"ySuperscriptYOffset":491,"yStrikeoutSize":51,"yStrikeoutPosition":265,"sFamilyClass":0,"bFamilyType":2,"bSerifStyle":0,"bWeight":6,"bProportion":3,"bContrast":0,"bStrokeVariation":0,"bArmStyle":0,"bLetterform":0,"bMidline":0,"bXHeight":0,"ulUnicodeRange1":1,"ulUnicodeRange2":268435456,"ulUnicodeRange3":0,"ulUnicodeRange4":0,"achVendID":"PfEd","fsSelection":192,"usFirstCharIndex":0,"usLastCharIndex":0,"sTypoAscender":812,"sTypoDescender":-212,"sTypoLineGap":92,"usWinAscent":812,"usWinDescent":212,"ulCodePageRange1":1,"ulCodePageRange2":0,"sxHeight":792,"sCapHeight":0,"usDefaultChar":0,"usBreakChar":32,"usMaxContext":1}
|
"OS/2":{"version":4,"xAvgCharWidth":1031,"usWeightClass":400,"usWidthClass":5,"fsType":0,"ySubscriptXSize":665,"ySubscriptYSize":716,"ySubscriptXOffset":0,"ySubscriptYOffset":143,"ySuperscriptXSize":665,"ySuperscriptYSize":716,"ySuperscriptXOffset":0,"ySuperscriptYOffset":491,"yStrikeoutSize":51,"yStrikeoutPosition":265,"sFamilyClass":0,"bFamilyType":2,"bSerifStyle":0,"bWeight":6,"bProportion":3,"bContrast":0,"bStrokeVariation":0,"bArmStyle":0,"bLetterform":0,"bMidline":0,"bXHeight":0,"ulUnicodeRange1":1,"ulUnicodeRange2":268435456,"ulUnicodeRange3":0,"ulUnicodeRange4":0,"achVendID":"PfEd","fsSelection":192,"usFirstCharIndex":0,"usLastCharIndex":0,"sTypoAscender":812,"sTypoDescender":-212,"sTypoLineGap":92,"usWinAscent":812,"usWinDescent":212,"ulCodePageRange1":1,"ulCodePageRange2":0,"sxHeight":792,"sCapHeight":0,"usDefaultChar":0,"usBreakChar":32,"usMaxContext":1}
|
||||||
}
|
}
|
0
features/common.fea
Normal file
0
features/common.fea
Normal file
|
@ -7,7 +7,6 @@ ClearTable('fpgm');
|
||||||
ClearTable('prep');
|
ClearTable('prep');
|
||||||
ClearTable('cvt ');
|
ClearTable('cvt ');
|
||||||
ClearTable('maxp');
|
ClearTable('maxp');
|
||||||
|
|
||||||
Print("Outline Cleanup...");
|
Print("Outline Cleanup...");
|
||||||
Simplify(-1, 0);
|
Simplify(-1, 0);
|
||||||
ReplaceWithReference();
|
ReplaceWithReference();
|
||||||
|
@ -24,5 +23,6 @@ Print("Finalizing");
|
||||||
CorrectDirection();
|
CorrectDirection();
|
||||||
CanonicalContours();
|
CanonicalContours();
|
||||||
CanonicalStart();
|
CanonicalStart();
|
||||||
|
MergeFeature($2);
|
||||||
Print("Saving ttf...");
|
Print("Saving ttf...");
|
||||||
Generate($2);
|
Generate($3);
|
17
generate.js
17
generate.js
|
@ -23,6 +23,7 @@ function toBuffer(arrayBuffer) {
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
function pad(s, n){ while(s.length < n) s = '0' + s; return s; }
|
||||||
|
|
||||||
var options = {preserveOS2Version: true}
|
var options = {preserveOS2Version: true}
|
||||||
|
|
||||||
|
@ -31,7 +32,21 @@ var outputPath = argv._[1]
|
||||||
|
|
||||||
var ttfFont = buildGlyphs.build(parameters[variant]);
|
var ttfFont = buildGlyphs.build(parameters[variant]);
|
||||||
|
|
||||||
|
ttfFont.glyf = [ttfFont.glyf[0]].concat(ttfFont.glyf.slice(1).sort(function(a, b){
|
||||||
|
if(a.unicode && b.unicode && a.unicode[0] && b.unicode[0]) return a.unicode[0] - b.unicode[0]
|
||||||
|
else if(a.unicode && a.unicode[0]) return -1
|
||||||
|
else if(b.unicode && b.unicode[0]) return 1
|
||||||
|
else return (a.name > b.name ? 1 : a.name === b.name ? 0 : -1)
|
||||||
|
}));
|
||||||
|
|
||||||
if(outputPath) fs.writeFileSync(outputPath, toBuffer(new TTFWriter(options).write(ttfFont)));
|
if(outputPath) fs.writeFileSync(outputPath, toBuffer(new TTFWriter(options).write(ttfFont)));
|
||||||
if(argv.dumpmap) {
|
if(argv.dumpmap) {
|
||||||
fs.writeFileSync(argv.dumpmap, JSON.stringify(ttfFont.glyf.map(function(glyph){ return [glyph.name, glyph.unicode]})), 'utf8')
|
fs.writeFileSync(argv.dumpmap, JSON.stringify(ttfFont.glyf.map(function(glyph){ return [glyph.name, glyph.unicode]})), 'utf8')
|
||||||
}
|
};
|
||||||
|
if(argv.dumpfeature) {
|
||||||
|
var featurefile = '\n\n';
|
||||||
|
// ccmp
|
||||||
|
var ccmp = ttfFont.features.ccmp;
|
||||||
|
featurefile += 'feature ccmp {' + ccmp.join(';\n') + ';} ccmp;'
|
||||||
|
fs.writeFileSync(argv.dumpfeature, featurefile, 'utf8')
|
||||||
|
};
|
|
@ -1,4 +1,6 @@
|
||||||
### Automatic builds
|
###### Automatic builds
|
||||||
|
|
||||||
|
local font.features (.)
|
||||||
|
|
||||||
# Build miniature clyphs : circled, superscripts, subscripts...
|
# Build miniature clyphs : circled, superscripts, subscripts...
|
||||||
define [Miniature glyphs fold scale] : begin {
|
define [Miniature glyphs fold scale] : begin {
|
||||||
|
@ -325,6 +327,8 @@ define [decompositionModify s] : s.replace [regex '\u0313\u0300'] "\u1FCD"
|
||||||
:.replace [regex '\u0314\u0301'] "\u1FDE"
|
:.replace [regex '\u0314\u0301'] "\u1FDE"
|
||||||
:.replace [regex '\u0314\u0342'] "\u1FDF"
|
:.replace [regex '\u0314\u0342'] "\u1FDF"
|
||||||
|
|
||||||
|
set font.features.ccmp ()
|
||||||
|
|
||||||
foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs`code] : begin {
|
foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs`code] : begin {
|
||||||
local str : String.fromCharCode code
|
local str : String.fromCharCode code
|
||||||
local nfd : fallback customDecompositions.(str) : decompositionModify : str.normalize 'NFD'
|
local nfd : fallback customDecompositions.(str) : decompositionModify : str.normalize 'NFD'
|
||||||
|
@ -338,6 +342,7 @@ foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs`code] : begin {
|
||||||
if [isAboveMark parts`j] : set hasMarkAbove true
|
if [isAboveMark parts`j] : set hasMarkAbove true
|
||||||
}
|
}
|
||||||
if allFound : begin {
|
if allFound : begin {
|
||||||
|
local aliased false
|
||||||
local namingParts : parts.slice 0
|
local namingParts : parts.slice 0
|
||||||
if [[parts.0 === glyphs.i || parts.0 === glyphs.ukrainiani] && hasMarkAbove] : parts.0 = glyphs.dotlessi
|
if [[parts.0 === glyphs.i || parts.0 === glyphs.ukrainiani] && hasMarkAbove] : parts.0 = glyphs.dotlessi
|
||||||
if [parts.0 === glyphs.j && hasMarkAbove] : parts.0 = glyphs.dotlessj
|
if [parts.0 === glyphs.j && hasMarkAbove] : parts.0 = glyphs.dotlessj
|
||||||
|
@ -346,12 +351,14 @@ foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs`code] : begin {
|
||||||
local j 2
|
local j 2
|
||||||
while glyphs.[glyphName + '.alias' + j] : inc j
|
while glyphs.[glyphName + '.alias' + j] : inc j
|
||||||
set glyphName [glyphName + '.alias' + j]
|
set glyphName [glyphName + '.alias' + j]
|
||||||
|
set aliased true
|
||||||
}
|
}
|
||||||
create-glyph glyphName : glyph-construction {
|
create-glyph glyphName : glyph-construction {
|
||||||
assign-unicode code
|
assign-unicode code
|
||||||
include parts.0 AS_BASE
|
include parts.0 AS_BASE
|
||||||
foreach part [items-of : parts.slice 1] : include part
|
foreach part [items-of : parts.slice 1] : include part
|
||||||
}
|
}
|
||||||
|
if [not aliased] : font.features.ccmp.push : 'sub ' + [glyphName.replace [regex '_' 'g'] ' '] + ' by ' + glyphName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
46
makefile
46
makefile
|
@ -1,4 +1,4 @@
|
||||||
SUPPORT_FILES = support/glyph.js support/stroke.js parameters.js
|
SUPPORT_FILES = support/glyph.js support/stroke.js parameters.js generate.js empty.json
|
||||||
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.patel glyphs/cyrillic-extended.patel glyphs/numbers.patel glyphs/symbol-ascii.patel glyphs/symbol-extend.patel glyphs/symbol-geometric.patel glyphs/autobuilds.patel
|
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.patel glyphs/cyrillic-extended.patel glyphs/numbers.patel glyphs/symbol-ascii.patel glyphs/symbol-extend.patel glyphs/symbol-geometric.patel glyphs/autobuilds.patel
|
||||||
OBJDIR = build
|
OBJDIR = build
|
||||||
|
|
||||||
|
@ -6,28 +6,37 @@ SUPPRESS_ERRORS = 2> /dev/null
|
||||||
|
|
||||||
TARGETS = $(OBJDIR)/iosevka-regular.ttf $(OBJDIR)/iosevka-bold.ttf $(OBJDIR)/iosevka-italic.ttf $(OBJDIR)/iosevka-bolditalic.ttf
|
TARGETS = $(OBJDIR)/iosevka-regular.ttf $(OBJDIR)/iosevka-bold.ttf $(OBJDIR)/iosevka-italic.ttf $(OBJDIR)/iosevka-bolditalic.ttf
|
||||||
MAPS = $(subst .ttf,.charmap,$(TARGETS))
|
MAPS = $(subst .ttf,.charmap,$(TARGETS))
|
||||||
STEP0 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS))
|
PASS0 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS))
|
||||||
STEP1 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass1-,$(TARGETS))
|
ABFEAT = $(subst .ttf,.ab.fea,$(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS)))
|
||||||
STEP2 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass2-,$(TARGETS))
|
FEATURE = $(subst .ttf,.fea,$(subst $(OBJDIR)/,$(OBJDIR)/.pass0-,$(TARGETS)))
|
||||||
|
PASS1 = $(subst $(OBJDIR)/,$(OBJDIR)/.pass1-,$(TARGETS))
|
||||||
|
|
||||||
FILES = $(SUPPORT_FILES) buildglyphs.js
|
FILES = $(SUPPORT_FILES) buildglyphs.js
|
||||||
|
|
||||||
fonts : update $(TARGETS)
|
fonts : update $(TARGETS)
|
||||||
|
|
||||||
$(OBJDIR)/.pass0-iosevka-regular.ttf : $(FILES) $(OBJDIR)
|
|
||||||
node generate regular $@ --dumpmap $(OBJDIR)/iosevka-regular.charmap
|
|
||||||
$(OBJDIR)/.pass0-iosevka-bold.ttf : $(FILES) $(OBJDIR)
|
|
||||||
node generate bold $@ --dumpmap $(OBJDIR)/iosevka-bold.charmap
|
|
||||||
$(OBJDIR)/.pass0-iosevka-italic.ttf : $(FILES) $(OBJDIR)
|
|
||||||
node generate italic $@ --dumpmap $(OBJDIR)/iosevka-italic.charmap
|
|
||||||
$(OBJDIR)/.pass0-iosevka-bolditalic.ttf : $(FILES) $(OBJDIR)
|
|
||||||
node generate bolditalic $@ --dumpmap $(OBJDIR)/iosevka-bolditalic.charmap
|
|
||||||
|
|
||||||
# $(STEP1) : $(OBJDIR)/.pass1-%.ttf : $(OBJDIR)/.pass0-%.ttf
|
# Pass 0 : file construction
|
||||||
# fontforge -script pass1-cleanup.pe $< $@ $(SUPPRESS_ERRORS)
|
$(OBJDIR)/.pass0-iosevka-regular.ttf : $(FILES) | $(OBJDIR)
|
||||||
$(STEP2) : $(OBJDIR)/.pass2-%.ttf : $(OBJDIR)/.pass0-%.ttf
|
node generate regular $@ --dumpmap $(OBJDIR)/iosevka-regular.charmap --dumpfeature $(OBJDIR)/.pass0-iosevka-regular.ab.fea
|
||||||
fontforge -script pass2-cleanup.pe $< $@ $(SUPPRESS_ERRORS)
|
$(OBJDIR)/.pass0-iosevka-bold.ttf : $(FILES) | $(OBJDIR)
|
||||||
$(TARGETS) : $(OBJDIR)/%.ttf : $(OBJDIR)/.pass2-%.ttf
|
node generate bold $@ --dumpmap $(OBJDIR)/iosevka-bold.charmap --dumpfeature $(OBJDIR)/.pass0-iosevka-bold.ab.fea
|
||||||
|
$(OBJDIR)/.pass0-iosevka-italic.ttf : $(FILES) | $(OBJDIR)
|
||||||
|
node generate italic $@ --dumpmap $(OBJDIR)/iosevka-italic.charmap --dumpfeature $(OBJDIR)/.pass0-iosevka-italic.ab.fea
|
||||||
|
$(OBJDIR)/.pass0-iosevka-bolditalic.ttf : $(FILES) | $(OBJDIR)
|
||||||
|
node generate bolditalic $@ --dumpmap $(OBJDIR)/iosevka-bolditalic.charmap --dumpfeature $(OBJDIR)/.pass0-iosevka-bolditalic.ab.fea
|
||||||
|
|
||||||
|
$(ABFEAT) : $(OBJDIR)/.pass0-%.ab.fea : $(OBJDIR)/.pass0-%.ttf
|
||||||
|
-@echo Autobuild feature $@ from $<
|
||||||
|
$(FEATURE) : $(OBJDIR)/.pass0-%.fea : features/common.fea $(OBJDIR)/.pass0-%.ab.fea
|
||||||
|
cat $^ > $@
|
||||||
|
|
||||||
|
# Pass 1 : Outline cleanup and merge
|
||||||
|
$(PASS1) : $(OBJDIR)/.pass1-%.ttf : $(OBJDIR)/.pass0-%.ttf $(OBJDIR)/.pass0-%.fea
|
||||||
|
fontforge -script final.pe $^ $@ $(SUPPRESS_ERRORS)
|
||||||
|
|
||||||
|
# Pass 2 : Simplify and output
|
||||||
|
$(TARGETS) : $(OBJDIR)/%.ttf : $(OBJDIR)/.pass1-%.ttf
|
||||||
ttfautohint $< $@
|
ttfautohint $< $@
|
||||||
|
|
||||||
update : $(FILES)
|
update : $(FILES)
|
||||||
|
@ -45,5 +54,4 @@ $(OBJDIR) :
|
||||||
@- mkdir $@
|
@- mkdir $@
|
||||||
|
|
||||||
cleartemps :
|
cleartemps :
|
||||||
-rm $(STEP0)
|
-rm $(PASS0) $(PASS1)
|
||||||
-rm $(STEP1)
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue