Added features, ccmp and mark.

This commit is contained in:
be5invis 2015-08-04 22:23:15 +08:00
parent 651a017d71
commit b4fb48bdb6
11 changed files with 212 additions and 63 deletions

View file

@ -143,11 +143,11 @@ define [buildFont para recursive] : begin {
define markLFZero (.anchors (.lf [tm (.x MIDDLE .y 0 .type BASE)]))
define capitalMarks (.anchors (.above markAboveCap.anchors.above .below markBelowZero.anchors.below .trailing markTrailingZero.anchors.trailing .lf markLFZero.anchors.lf))
define bMarks (.anchors (.above markAboveCap.anchors.above .below markBelowZero.anchors.below .trailing markTrailingZero.anchors.trailing .lf markLFZero.anchors.lf))
define eMarks (.anchors (.above markAboveLower.anchors.above .below markBelowZero.anchors.below .trailing markTrailingZero.anchors.trailing .lf markLFZero.anchors.lf))
define pMarks (.anchors (.above markAboveLower.anchors.above .below markBelowLower.anchors.below .trailing markTrailingLower.anchors.trailing .lf markLFLower.anchors.lf))
define ifMarks (.anchors (.above markAboveCap.anchors.above .below markBelowLower.anchors.below .trailing markTrailingLower.anchors.trailing .lf markLFLower.anchors.lf))
define capitalMarks (.anchors (.above markAboveCap.anchors.above .below markBelowZero.anchors.below))
define bMarks (.anchors (.above markAboveCap.anchors.above .below markBelowZero.anchors.below))
define eMarks (.anchors (.above markAboveLower.anchors.above .below markBelowZero.anchors.below))
define pMarks (.anchors (.above markAboveLower.anchors.above .below markBelowLower.anchors.below))
define ifMarks (.anchors (.above markAboveCap.anchors.above .below markBelowLower.anchors.below))
Stroke.bindParameters para
@ -220,7 +220,6 @@ define [buildFont para recursive] : begin {
local [dont-export] : set currentGlyph.dontExport true
this.gizmo = globalTransform
this.set-width WIDTH
begin @::[steps.map formOf]
return nothing
}]] env)
@ -264,14 +263,12 @@ define [buildFont para recursive] : begin {
if [pickHash && [not pickHash.(name)]] : return nothing
local variant : variantSelector`name || default
local chosenGlyph glyphs`[name + '.' + variant]
set glyphs`name chosenGlyph
create-glyph name : glyph-construction {
include chosenGlyph AS_BASE
if unicode : assign-unicode unicode
}
local allAliases : Object.keys glyphs :.filter [[k] -> [glyphs`k === glyphs.(chosenGlyph.name)]]
set dependencyProfile`name : allAliases.concat dependencyProfile.(chosenGlyph.name)
if unicode : begin {
chosenGlyph.assign-unicode unicode
set chosenGlyph.dontExport false
set unicodeGlyphs.(chosenGlyph.unicode`[chosenGlyph.unicode.length - 1]) chosenGlyph
}
}
define [italic-variant name unicode] : create-glyph name : glyph-construction {
if [para.italicangle > 0] {

View file

@ -0,0 +1,58 @@
lookup ccmpManual {
sub [i j]' @MG_above by [dotlessi dotlessj];
sub eta iotaBelow' by iotaLF;
sub eta @MG_above iotaBelow' by iotaLF;
sub eta @MG_above @MG_above iotaBelow' by iotaLF;
sub eta @MG_above @MG_above @MG_above iotaBelow' by iotaLF;
sub [a A u cyra cyrA] ogonekBelow' by ogonekTR;
sub [a A u cyra cyrA] @MG_above ogonekBelow' by ogonekTR;
sub [a A u cyra cyrA] @MG_above @MG_above ogonekBelow' by ogonekTR;
sub [a A u cyra cyrA] @MG_above @MG_above @MG_above ogonekBelow' by ogonekTR;
} ccmpManual;
feature ccmp {
script latn;
language dflt;
lookup ccmpManual;
script grek;
language dflt;
lookup ccmpManual;
script cyrl;
language dflt;
lookup ccmpManual;
script dflt;
language dflt;
lookup ccmpManual;
} ccmp;
feature mark {
script latn;
language dflt;
lookup markAuto;
script grek;
language dflt;
lookup markAuto;
script cyrl;
language dflt;
lookup markAuto;
script dflt;
language dflt;
lookup markAuto;
} 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

@ -18,7 +18,7 @@ RemoveOverlap();
ReplaceWithReference(4, 1);
Print("Simplifying");
AddExtrema();
Simplify(0, 2);
Simplify(0, 3);
Print("Finalizing");
CorrectDirection();
CanonicalContours();

View file

@ -46,7 +46,20 @@ if(argv.dumpmap) {
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')
// var ccmp = ttfFont.features.ccmp;
// featurefile += 'lookup ccmpAuto {' + ccmp.join(';\n') + ';} ccmpAuto;';
// markGlyphs
for(var key in ttfFont.features.markGlyphs){
featurefile += '@MG_' + key + '= [' + ttfFont.features.markGlyphs[key].join(' ') + '];\n'
}
// mark
var mark = ttfFont.features.mark;
featurefile += 'lookup markAuto {' + mark.marks.join(';\n') + ';\n' + mark.bases.join(';\n') + ';} markAuto;'
// mkmk
var mkmk = ttfFont.features.mkmk;
featurefile += 'lookup mkmkAuto {' + mkmk.marks.join(';\n') + ';\n' + mkmk.bases.join(';\n') + ';} mkmkAuto;'
fs.writeFileSync(argv.dumpfeature, featurefile, 'utf8');
};

View file

@ -320,45 +320,100 @@ define customDecompositions (
."\u0384" " \u0301"
."\u0385" " \u0308\u0301"
)
define [decompositionModify s] : s.replace [regex '\u0313\u0300'] "\u1FCD"
:.replace [regex '\u0313\u0301'] "\u1FCE"
:.replace [regex '\u0313\u0342'] "\u1FCF"
:.replace [regex '\u0314\u0300'] "\u1FDD"
:.replace [regex '\u0314\u0301'] "\u1FDE"
:.replace [regex '\u0314\u0342'] "\u1FDF"
define [subParts parts] : begin {
local hasMarkAbove false
foreach p [items-of parts] : if [isAboveMark p] : set hasMarkAbove true
# replace dotted-i and dotted-j with dotless equalivents
if [[parts.0 === glyphs.i || parts.0 === glyphs.ukrainiani] && hasMarkAbove] : parts.0 = glyphs.dotlessi
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
# composite greek overmarks
for [local j 0] [j < parts.length] [inc j] : piecewise {
[parts.(j) === glyphs.closeApostropheAbove] : begin {
set parts.(j) null
piecewise {
[parts.[j + 1] === glyphs.graveAbove] : set parts.[j + 1] glyphs.psilivaria
[parts.[j + 1] === glyphs.acuteAbove] : set parts.[j + 1] glyphs.psilioxia
[parts.[j + 1] === glyphs.perispomeniAbove] : set parts.[j + 1] glyphs.psiliperispomeni
}
}
[parts.(j) === glyphs.invCommaAbove] : begin {
set parts.(j) null
piecewise {
[parts.[j + 1] === glyphs.graveAbove] : set parts.[j + 1] glyphs.dasiavaria
[parts.[j + 1] === glyphs.acuteAbove] : set parts.[j + 1] glyphs.dasiaoxia
[parts.[j + 1] === glyphs.perispomeniAbove] : set parts.[j + 1] glyphs.dasiaperispomeni
}
}
}
return : parts.filter [[x] -> [not [not x]]]
}
define [pad s n] : begin {
while [s.length < n] : s = '0' + s
return s
}
set font.features.ccmp ()
foreach code [range 0x0000 0xFFFF] : if [not unicodeGlyphs`code] : begin {
local str : String.fromCharCode code
local nfd : fallback customDecompositions.(str) : decompositionModify : str.normalize 'NFD'
local nfd : fallback customDecompositions.(str) : str.normalize 'NFD'
if [nfd.length > 1] : begin {
local parts ()
local allFound true
local hasMarkAbove false
foreach j [range 0 nfd.length] : begin {
set parts`j unicodeGlyphs`[nfd.charCodeAt j]
if [not parts`j] : set allFound false
if [isAboveMark parts`j] : set hasMarkAbove true
}
if allFound : begin {
local aliased false
local namingParts : parts.slice 0
if [[parts.0 === glyphs.i || parts.0 === glyphs.ukrainiani] && hasMarkAbove] : parts.0 = glyphs.dotlessi
if [parts.0 === glyphs.j && hasMarkAbove] : parts.0 = glyphs.dotlessj
local glyphName : namingParts.map [[part] -> part.name] :.join '_'
if glyphs.(glyphName) : begin {
local j 2
while glyphs.[glyphName + '.alias' + j] : inc j
set glyphName [glyphName + '.alias' + j]
set aliased true
}
set parts : subParts parts
local composition : namingParts.map [[part] -> part.name] :.join ' '
local glyphName : 'uni' + [pad [[code.toString 16].toUpperCase] 4]
create-glyph glyphName : glyph-construction {
assign-unicode code
include parts.0 AS_BASE
foreach part [items-of : parts.slice 1] : include part
}
if [not aliased] : font.features.ccmp.push : 'sub ' + [glyphName.replace [regex '_' 'g'] ' '] + ' by ' + glyphName
if [not glyphs.(composition)] : begin {
font.features.ccmp.push : 'sub ' + composition + ' by ' + glyphName
set glyphs.(composition) glyphs.(glyphName)
}
}
}
}
### Generate MARK and MKMK features
set font.features.mark (.marks () .bases ())
set font.features.mkmk (.marks () .bases ())
set font.features.markGlyphs (.)
define [buildAnchorDescription glyph inserter propx propy] : begin {
local buf ''
foreach key [items-of : Object.keys glyph.anchors] : buf = buf + ' <anchor ' + [Math.round [upmscale * glyph.anchors.(key).(propx)]] + ' ' + [Math.round [upmscale * glyph.anchors.(key).(propy)]] + '> ' + inserter + ' @' + key
return buf
}
foreach glyph [items-of glyphList] : if [glyph.anchors && [begin [local anchorKeys : Object.keys glyph.anchors] anchorKeys.length]] : begin {
local isMarkGlyph false
foreach key [items-of anchorKeys] : if [glyph.anchors.(key).type == 'mark'] : set isMarkGlyph true
if isMarkGlyph {
then {
font.features.mark.marks.push : 'markClass [' + glyph.name + '] ' + [buildAnchorDescription glyph '' 'x' 'y']
font.features.mkmk.marks.push : 'markClass [' + glyph.name + '] ' + [buildAnchorDescription glyph '' 'x' 'y']
font.features.mkmk.bases.push : 'pos mark [' + glyph.name + '] ' + [buildAnchorDescription glyph 'mark' 'mbx' 'mby']
foreach key [items-of anchorKeys] : begin {
if [not font.features.markGlyphs.(key)] : set font.features.markGlyphs.(key) ()
font.features.markGlyphs.(key).push glyph.name
}
}
else : font.features.mark.bases.push : 'pos base [' + glyph.name + '] ' + [buildAnchorDescription glyph 'mark' 'x' 'y']
}
}

View file

@ -95,7 +95,8 @@ create-glyph 'dje' : glyph-construction {
define [GeShape top] : glyph-construction {
include : LShape top
include : FlipAround MIDDLE [top / 2] 1 [-1]
include : VBarRight RIGHTSB [top + ACCENT] top
include : VBarRight RIGHTSB top [top + ACCENT]
reverse-last
}
create-glyph 'Ge' : glyph-construction {
assign-unicode 0x490

View file

@ -195,23 +195,23 @@ define [BShape top] : glyph-construction {
local turnbottom : bowl / 2
include : create-stroke
:.start-from SB top
:.start-from [SB - O] top
:.heads-to RIGHTWARD
:.set-width 0 STROKE
:.line-to [RIGHTSB - SB * 0.5 - turnbottom] top
:.arc-hv-to [RIGHTSB - SB * 0.5] turntop
:.arc-vh-to [RIGHTSB - SB * 0.5 - turnbottom] [bowl - STROKE]
:.line-to SB [bowl - STROKE]
:.line-to [SB - O] [bowl - STROKE]
:.heads-to LEFTWARD
include : create-stroke
:.start-from SB 0
:.start-from [SB - O] 0
:.heads-to RIGHTWARD
:.set-width STROKE 0
:.line-to [RIGHTSB - turnbottom] 0
:.arc-hv-to RIGHTSB turnbottom
:.arc-vh-to [RIGHTSB - turnbottom] bowl
:.line-to SB bowl
:.line-to [SB - O] bowl
:.heads-to LEFTWARD
include : create-stroke
@ -244,14 +244,14 @@ create-glyph 'D' : glyph-construction {
:.heads-to UPWARD
include : create-stroke
:.start-from SB 0
:.start-from [SB - O] 0
:.heads-to RIGHTWARD
:.set-width STROKE 0
:.line-to [RIGHTSB - bsmooth] 0
:.arc-hv-to RIGHTSB dsmooth
:.line-to RIGHTSB [CAP - dsmooth]
:.arc-vh-to [RIGHTSB - bsmooth] CAP
:.line-to SB CAP
:.line-to [SB - O] CAP
:.heads-to LEFTWARD
}
create-glyph 'P' : glyph-construction {
@ -267,13 +267,13 @@ create-glyph 'P' : glyph-construction {
local turnRadius : [bowlTop - bowlBottom] / 2
include : create-stroke
:.start-from [SB * 1.25 + HALFSTROKE * 0.1] bowlTop
:.start-from [SB * 1.25 - O] bowlTop
:.heads-to RIGHTWARD
:.set-width 0 STROKE
:.line-to [RIGHTSB - turnRadius] bowlTop
:.arc-hv-to [RIGHTSB - O] turn
:.arc-vh-to [RIGHTSB - turnRadius] bowlBottom
:.line-to [SB * 1.25 + HALFSTROKE * 0.1] bowlBottom
:.line-to [SB * 1.25 - O] bowlBottom
:.heads-to LEFTWARD
include : create-stroke
@ -396,9 +396,9 @@ create-glyph 'U' : glyph-construction {
define [FShape] : glyph-construction {
include : create-stroke :.start-from [SB * 1.5] 0 :.heads-to UPWARD :.set-width 0 STROKE
:.line-to [SB * 1.5] CAP :.heads-to UPWARD
include : create-stroke :.start-from [SB * 1.5] CAP :.set-width 0 STROKE :.heads-to RIGHTWARD
include : create-stroke :.start-from [SB * 1.5 - O] CAP :.set-width 0 STROKE :.heads-to RIGHTWARD
:.line-to RIGHTSB CAP :.heads-to RIGHTWARD
include : create-stroke :.start-from [SB * 1.5] [CAP * 0.54] :.set-width HALFSTROKE HALFSTROKE :.heads-to RIGHTWARD
include : create-stroke :.start-from [SB * 1.5 - O] [CAP * 0.54] :.set-width HALFSTROKE HALFSTROKE :.heads-to RIGHTWARD
:.line-to [RIGHTSB - HALFSTROKE] [CAP * 0.54] :.heads-to RIGHTWARD
}
create-glyph 'F' : glyph-construction {
@ -413,7 +413,7 @@ create-glyph 'E' : glyph-construction {
include capitalMarks
include : FShape
include : create-stroke :.start-from [SB * 1.5] 0 :.set-width STROKE 0 :.heads-to RIGHTWARD
include : create-stroke :.start-from [SB * 1.5 - O] 0 :.set-width STROKE 0 :.heads-to RIGHTWARD
:.line-to RIGHTSB 0 :.heads-to RIGHTWARD
}
define [HShape top] : glyph-construction {
@ -421,8 +421,8 @@ define [HShape top] : glyph-construction {
:.line-to SB top :.heads-to UPWARD
include : create-stroke :.start-from RIGHTSB 0 :.heads-to UPWARD :.set-width STROKE 0
:.line-to RIGHTSB top :.heads-to UPWARD
include : create-stroke :.start-from SB [top / 2] :.set-width HALFSTROKE HALFSTROKE :.heads-to RIGHTWARD
:.line-to RIGHTSB [top / 2] :.heads-to RIGHTWARD
include : create-stroke :.start-from [SB - O] [top / 2] :.set-width HALFSTROKE HALFSTROKE :.heads-to RIGHTWARD
:.line-to [RIGHTSB + O] [top / 2] :.heads-to RIGHTWARD
}
create-glyph 'H' : glyph-construction {
set-width WIDTH
@ -438,7 +438,7 @@ define [LShape top] : glyph-construction {
:.line-to [SB * 1.5] 0
:.heads-to DOWNWARD
include : create-stroke
:.start-from [SB * 1.5] 0
:.start-from [SB * 1.5 - O] 0
:.set-width STROKE 0
:.heads-to RIGHTWARD
:.line-to RIGHTSB 0

View file

@ -346,7 +346,7 @@ create-glyph 'ogonekBelow' : glyph-construction {
local ogonekBot : [mix belowMarkTop belowMarkBot 0.75] + markStress * 2
local ogonekLeft : markMiddle - markExtend * 0.2
local ogonekRight : markMiddle + markExtend * 0.85
set-anchor 'trailing' MARK markMiddle 0 ogonekRight ogonekBot
set-anchor 'below' MARK markMiddle 0 markMiddle belowMarkBot
include : create-stroke
:.start-from markMiddle 0
@ -358,14 +358,27 @@ create-glyph 'ogonekBelow' : glyph-construction {
:.line-to ogonekRight ogonekBot
:.heads-to RIGHTWARD
}
create-glyph 'ogonekTR' : glyph-construction {
set-width 0
include glyphs.ogonekBelow
local ogonekBot : [mix belowMarkTop belowMarkBot 0.75] + markStress * 2
local ogonekRight : markMiddle + markExtend * 0.85
set-anchor 'trailing' MARK markMiddle 0 ogonekRight ogonekBot
}
create-glyph 'iotaBelow' : glyph-construction {
set-width 0
assign-unicode 0x345
set-anchor 'lf' MARK markMiddle 0 markMiddle belowMarkBot
set-anchor 'below' MARK markMiddle 0 markMiddle belowMarkBot
include : VBar markMiddle belowMarkBot belowMarkTop [markHalfStroke * 2]
}
create-glyph 'iotaLF' : glyph-construction {
# iotabelow glyph for /eta
set-width 0
set-anchor 'lf' MARK markMiddle 0 markMiddle belowMarkBot
include : VBar markMiddle belowMarkBot belowMarkTop [markHalfStroke * 2]
}
# Flipped below marks
create-glyph 'dotBelow' : glyph-construction {
set-width 0

View file

@ -28,7 +28,7 @@ $(OBJDIR)/.pass0-iosevka-bolditalic.ttf : $(FILES) | $(OBJDIR)
$(ABFEAT) : $(OBJDIR)/.pass0-%.ab.fea : $(OBJDIR)/.pass0-%.ttf
-@echo Autobuild feature $@ from $<
$(FEATURE) : $(OBJDIR)/.pass0-%.fea : features/common.fea $(OBJDIR)/.pass0-%.ab.fea
$(FEATURE) : $(OBJDIR)/.pass0-%.fea : $(OBJDIR)/.pass0-%.ab.fea features/common.fea
cat $^ > $@
# Pass 1 : Outline cleanup and merge

View file

@ -39,7 +39,7 @@ define regular (
.family 'Iosevka'
.style 'Regular'
.weight 400
.version 'r0.0.9'
.version 'r0.0.10'
.variantSelector (.)
.copyright 'Copyright (c) 2015 Belleve Invis.'
)

View file

@ -123,14 +123,26 @@ define [Glyph.prototype.include component copyAnchors] : begin {
[[fallback anchorThis.mbx anchorThis.x] - anchorThat.x]
[[fallback anchorThis.mby anchorThis.y] - anchorThat.y]
)
if [anchorThat.mbx !== nothing && anchorThat.mby !== nothing] : begin {
set this.anchors`markid (
.x [anchorThis.x + anchorThat.mbx - anchorThat.x]
.y [anchorThis.y + anchorThat.mby - anchorThat.y]
.type anchorThis.type
.mbx anchorThis.mbx
.mby anchorThis.mby
)
# 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]
.y [anchorThis.y + anchorThat.mby - anchorThat.y]
.type anchorThis.type
.mbx anchorThis.mbx
.mby anchorThis.mby
)
}
else {
set this.anchors`markid (
.mbx [anchorThis.mbx + anchorThat.mbx - anchorThat.x]
.mby [anchorThis.mby + anchorThat.mby - anchorThat.y]
.type anchorThis.type
.x anchorThis.x
.y anchorThis.y
)
}
}
}
}