Added ccmp feature.

This commit is contained in:
be5invis 2015-08-04 06:59:39 +08:00
parent 8b712ef1eb
commit 04117471cb
6 changed files with 54 additions and 24 deletions

View file

@ -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
View file

View 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);

View file

@ -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')
};

View file

@ -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
} }
} }
} }

View file

@ -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)