We hanve a new macro [$$include]
This commit is contained in:
parent
b111ec4e46
commit
c0acabc535
4 changed files with 338 additions and 312 deletions
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if [not recursive] : set font.glyf : font.glyf.filter : function [glyph] : glyph && [not glyph.dontExport]
|
|
||||||
set font.glyfMap glyphs
|
|
||||||
return font
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.build = buildFont
|
|
|
@ -1,280 +0,0 @@
|
||||||
define Glyph [require './support/glyph'].Glyph
|
|
||||||
define Stroke [require './support/stroke'].Stroke
|
|
||||||
define tp [require './support/transform'].transformPoint
|
|
||||||
|
|
||||||
### COMMON FUNCTIONS
|
|
||||||
|
|
||||||
define [mix a b p] : a + [b - a] * p
|
|
||||||
define [linreg x0 y0 x1 y1 x] : y0 + [x - x0] * [y1 - y0] / [x1 - x0]
|
|
||||||
define [fallback] : for [local j 0] [j < arguments.length] [inc j] : if [arguments`j !== nothing] : return arguments`j
|
|
||||||
|
|
||||||
define emptyFontStr : JSON.stringify [require './empty.json']
|
|
||||||
|
|
||||||
define [buildFont para recursive] : begin {
|
|
||||||
|
|
||||||
define variantSelector para.variantSelector
|
|
||||||
define font : JSON.parse emptyFontStr
|
|
||||||
define glyphList font.glyf
|
|
||||||
define glyphs (.'.notdef' glyphList.0)
|
|
||||||
define unicodeGlyphs ()
|
|
||||||
|
|
||||||
define globalTransform (
|
|
||||||
.xx 1
|
|
||||||
.yx [Math.tan [para.italicangle / 180 * Math.PI]]
|
|
||||||
.xy 0
|
|
||||||
.yy 1
|
|
||||||
.x 0
|
|
||||||
.y 0
|
|
||||||
)
|
|
||||||
|
|
||||||
define ITALICCOR : 1 / [Math.sqrt [1 - globalTransform.yx * globalTransform.yx]]
|
|
||||||
|
|
||||||
define UPWARD (.x [-ITALICCOR] .y 0)
|
|
||||||
define DOWNWARD (.x ITALICCOR .y 0)
|
|
||||||
define RIGHTWARD (.x globalTransform.yx .y 1)
|
|
||||||
define LEFTWARD (.x [- globalTransform.yx] .y [-1])
|
|
||||||
|
|
||||||
# metrics
|
|
||||||
define DESCENDER para.descender
|
|
||||||
define WIDTH para.width
|
|
||||||
define CAP para.cap
|
|
||||||
define XH para.xheight
|
|
||||||
define O para.o
|
|
||||||
define OXHOOK para.oxhook
|
|
||||||
define SB para.sb
|
|
||||||
define HOOK para.hook
|
|
||||||
define AHOOK para.ahook
|
|
||||||
define SHOOK para.shook
|
|
||||||
define RHOOK para.rhook
|
|
||||||
define SMOOTH para.smooth
|
|
||||||
define SMALLSMOOTH para.smallsmooth
|
|
||||||
define STROKE para.stroke
|
|
||||||
define DOTSIZE para.dotsize
|
|
||||||
define PERIODSIZE para.periodsize
|
|
||||||
define BARPOS para.barpos
|
|
||||||
define GBARPOS para.gbarpos
|
|
||||||
define FIVEBARPOS para.fivebarpos
|
|
||||||
define LONGJUT para.longjut
|
|
||||||
define ACCENT para.accent
|
|
||||||
define ACCENTX para.accentx
|
|
||||||
|
|
||||||
|
|
||||||
# derived metrics
|
|
||||||
define XO : XH - O
|
|
||||||
define CAPO : CAP - O
|
|
||||||
define HALFSTROKE : STROKE / 2
|
|
||||||
define RIGHTSB : WIDTH - SB
|
|
||||||
define MIDDLE : WIDTH / 2
|
|
||||||
define CAPMIDDLE : CAP / 2
|
|
||||||
define CAP_SMOOTH : CAP - SMOOTH
|
|
||||||
define DOTRADIUS : DOTSIZE / 2
|
|
||||||
define PERIODRADIUS : PERIODSIZE / 2
|
|
||||||
|
|
||||||
define SMOOTHA : SMOOTH - globalTransform.yx * para.smoothadjust
|
|
||||||
define SMOOTHB : SMOOTH + globalTransform.yx * para.smoothadjust
|
|
||||||
define SMALLSMOOTHA : SMALLSMOOTH - globalTransform.yx * para.smoothadjust
|
|
||||||
define SMALLSMOOTHB : SMALLSMOOTH + globalTransform.yx * para.smoothadjust
|
|
||||||
define ITALICCORS : STROKE * globalTransform.yx
|
|
||||||
|
|
||||||
# style parameters
|
|
||||||
define EBARPOS : para.ebarpos || BARPOS
|
|
||||||
define KAPPA para.kappa
|
|
||||||
define COKAPPA : 1 - KAPPA
|
|
||||||
define BKAPPA : para.bkappa || KAPPA + 0.1
|
|
||||||
define CKAPPA : para.ckappa || BKAPPA
|
|
||||||
define COBKAPPA : 1 - BKAPPA
|
|
||||||
define KAPPA_HOOK : para.kappa_hook || BKAPPA + 0.1
|
|
||||||
define KAPPA_AHOOK : para.kappa_ahook || KAPPA_HOOK
|
|
||||||
define TAILADJX : WIDTH * 0.2
|
|
||||||
define TAILADJY : XH * 0.25
|
|
||||||
define TAILADJKAPPA 0.75
|
|
||||||
define TAILADJSX : WIDTH * 0.2
|
|
||||||
define TAILADJSY 0
|
|
||||||
define TAILADJSKAPPA 0.75
|
|
||||||
define ILBALANCE : LONGJUT * 0.04
|
|
||||||
define JBALANCE : para.jbalance || HALFSTROKE + ILBALANCE
|
|
||||||
define TBALANCE : para.tbalance || JBALANCE
|
|
||||||
define TBALANCE2 : para.tbalance2 || TBALANCE
|
|
||||||
define RBALANCE : para.rbalance || JBALANCE * 0.3
|
|
||||||
|
|
||||||
# Blackness parameters
|
|
||||||
# We will estimate blackness using lower-case 'e'
|
|
||||||
define WHITENESS : [[XH - STROKE * 2.5] * [RIGHTSB - SB] * [1 / 3]] / [XH * [RIGHTSB - SB]]
|
|
||||||
define [adviceBlackness crowdedness] : Math.min STROKE [[RIGHTSB - SB] * [1 - WHITENESS] / crowdedness]
|
|
||||||
|
|
||||||
# Anchor parameters
|
|
||||||
define BASE 'base'
|
|
||||||
define MARK 'mark'
|
|
||||||
define MARKBASE 'markbase'
|
|
||||||
|
|
||||||
define AS_BASE 'AS-BASE'
|
|
||||||
define [Upright angle] (.xx 1 .yx [-[Math.tan [[fallback angle para.italicangle] / 180 * Math.PI]]] .xy 0 .yy 1 .x 0 .y 0)
|
|
||||||
define [Italify angle] (.xx 1 .yx [Math.tan [[fallback angle para.italicangle] / 180 * Math.PI]] .xy 0 .yy 1 .x 0 .y 0)
|
|
||||||
define [Scale sx sy] (.xx sx .yx 0 .xy 0 .yy [fallback sy sx] .x 0 .y 0)
|
|
||||||
define [Translate x y] (.xx 1 .yx 0 .xy 0 .yy 1 .x x .y y)
|
|
||||||
|
|
||||||
define [tm anchor] : return (
|
|
||||||
.x [anchor.x * globalTransform.xx + anchor.y * globalTransform.yx + globalTransform.x]
|
|
||||||
.y [anchor.x * globalTransform.xy + anchor.y * globalTransform.yy + globalTransform.y]
|
|
||||||
.type anchor.type
|
|
||||||
)
|
|
||||||
|
|
||||||
define markAboveLower (.anchors (.above [tm (.x MIDDLE .y XH .type BASE)]))
|
|
||||||
define markAboveCap (.anchors (.above [tm (.x MIDDLE .y CAP .type BASE)]))
|
|
||||||
define markBelowLower (.anchors (.below [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
|
||||||
define markBelowZero (.anchors (.below [tm (.x MIDDLE .y 0 .type BASE)]))
|
|
||||||
define markTrailingLower (.anchors (.trailing [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
|
||||||
define markTrailingZero (.anchors (.trailing [tm (.x MIDDLE .y 0 .type BASE)]))
|
|
||||||
define markLFLower (.anchors (.lf [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
|
||||||
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))
|
|
||||||
|
|
||||||
Stroke.bindParameters para
|
|
||||||
|
|
||||||
### Font names
|
|
||||||
set font.name.fontFamily para.family
|
|
||||||
set font.name.fontSubFamily para.style
|
|
||||||
set font.name.preferredFamily para.family
|
|
||||||
set font.name.preferredSubFamily para.style
|
|
||||||
set font.name.uniqueSubFamily : para.family + ' ' + para.style + ' ' + para.version
|
|
||||||
set font.name.version para.version
|
|
||||||
set font.name.fullName : if [para.style != 'Regular'] [para.family + ' ' + para.style] para.family
|
|
||||||
set font.name.postScriptName : font.name.fullName.replace [regex ' ' 'g'] '-'
|
|
||||||
set font.name.copyright para.copyright
|
|
||||||
set font.'OS/2'.usWeightClass para.weight
|
|
||||||
set font.'OS/2'.bProportion 9 # Monospaced
|
|
||||||
set font.'OS/2'.bWeight : 1 + para.weight / 100
|
|
||||||
set font.'OS/2'.fsSelection : [if para.isBold 32 0] + [if para.isItalic 1 0] + [if [[not para.isBold] && [not para.isItalic]] 64 0] + 128
|
|
||||||
set font.head.macStyle : [if para.isBold 1 0] + [if para.isItalic 2 0]
|
|
||||||
|
|
||||||
### Metric metadata
|
|
||||||
# Note: we use 1000upm in design, and 4096upm in production
|
|
||||||
|
|
||||||
define upmscale : fallback para.upmscale 1
|
|
||||||
|
|
||||||
set font.head.unitsPerEm 1000
|
|
||||||
set font.hhea.ascent [CAP + ACCENT * 1.5]
|
|
||||||
set font.'OS/2'.usWinAscent [CAP + ACCENT * 1.5]
|
|
||||||
set font.'OS/2'.sTypoAscender [CAP + ACCENT * 1.5]
|
|
||||||
set font.hhea.descent [DESCENDER - ACCENT * 0.5]
|
|
||||||
set font.'OS/2'.usWinDescent [Math.abs [DESCENDER - ACCENT * 0.5]]
|
|
||||||
set font.'OS/2'.sTypoDescender [DESCENDER - ACCENT * 0.5]
|
|
||||||
set font.hhea.lineGap [CAP * 0.2]
|
|
||||||
set font.'OS/2'.sTypoLineGap [CAP * 0.2]
|
|
||||||
set font.'OS/2'.sxHeight XH
|
|
||||||
set font.post.italicAnvle [0 - para.italicangle]
|
|
||||||
|
|
||||||
### Necessary macros
|
|
||||||
define-macro glyph-construction : syntax-rules {
|
|
||||||
@`[glyph-construction @::steps] ('.syntactic-closure' @`[lambda [] [begin {
|
|
||||||
local currentGlyph this
|
|
||||||
local set-width : this.set-width.bind this
|
|
||||||
local assign-unicode : lambda [code] : begin {
|
|
||||||
currentGlyph.assign-unicode code
|
|
||||||
set unicodeGlyphs.(currentGlyph.unicode`[currentGlyph.unicode.length - 1]) currentGlyph
|
|
||||||
}
|
|
||||||
local start-from : this.start-from.bind this
|
|
||||||
local line-to : this.line-to.bind this
|
|
||||||
local curve-to : this.curve-to.bind this
|
|
||||||
local cubic-to : this.cubic-to.bind this
|
|
||||||
local arc-hv-to : this.arc-hv-to.bind this
|
|
||||||
local arc-vh-to : this.arc-vh-to.bind this
|
|
||||||
local put-shapes : this.put-shapes.bind this
|
|
||||||
local reverse-last : this.reverse-last.bind this
|
|
||||||
local include : this.include.bind this
|
|
||||||
local create-stroke : this.create-stroke.bind this
|
|
||||||
local set-anchor : this.set-anchor.bind this
|
|
||||||
local apply-transform : this.apply-transform.bind this
|
|
||||||
|
|
||||||
# Actually I can define them using macros, but it makes compilation slow.
|
|
||||||
# define-macro set-width : syntax-rules { @`[set-width @::args] @`[currentGlyph.set-width @::args] }
|
|
||||||
# define-macro start-from : syntax-rules { @`[start-from @::args] @`[currentGlyph.start-from @::args] }
|
|
||||||
# define-macro line-to : syntax-rules { @`[line-to @::args] @`[currentGlyph.line-to @::args] }
|
|
||||||
# define-macro curve-to : syntax-rules { @`[curve-to @::args] @`[currentGlyph.curve-to @::args] }
|
|
||||||
# define-macro cubic-to : syntax-rules { @`[cubic-to @::args] @`[currentGlyph.cubic-to @::args] }
|
|
||||||
# define-macro include : syntax-rules { @`[include @::args] @`[currentGlyph.include @::args] }
|
|
||||||
# define-macro create-stroke : syntax-rules { @`[create-stroke @::args] @`[currentGlyph.create-stroke @::args] }
|
|
||||||
# define-macro set-anchor : syntax-rules { @`[set-anchor @::args] @`[currentGlyph.set-anchor @::args] }
|
|
||||||
# define-macro apply-transform : syntax-rules { @`[apply-transform @::args] @`[currentGlyph.apply-transform @::args] }
|
|
||||||
# define-macro reverse-last : syntax-rules { @`[reverse-last @::args] @`[currentGlyph.reverse-last @::args] }
|
|
||||||
|
|
||||||
local [dont-export] : set currentGlyph.dontExport true
|
|
||||||
this.gizmo = globalTransform
|
|
||||||
this.set-width WIDTH
|
|
||||||
begin @::[steps.map formOf]
|
|
||||||
return nothing
|
|
||||||
}]] env)
|
|
||||||
}
|
|
||||||
|
|
||||||
local dependencyProfile (.)
|
|
||||||
local nTemp 0
|
|
||||||
local pickHash : if recursive {
|
|
||||||
then : let [h (.)] : begin {
|
|
||||||
foreach j [items-of recursive] : set h.(j) j
|
|
||||||
* h
|
|
||||||
}
|
|
||||||
else nothing
|
|
||||||
}
|
|
||||||
define [create-glyph name actions] : piecewise {
|
|
||||||
[name && actions] : begin {
|
|
||||||
if [pickHash && [not pickHash.(name)]] : return nothing
|
|
||||||
process.stderr.write : "Building /" + name + [if recursive " (recursive)" ""] + " for " + para.family + ' ' + para.style + "\n"
|
|
||||||
set dependencyProfile`name ()
|
|
||||||
define glyphObject [new Glyph name]
|
|
||||||
glyphObject.set-width WIDTH
|
|
||||||
glyphList.push glyphObject
|
|
||||||
glyphs`name = glyphObject
|
|
||||||
actions.call glyphObject
|
|
||||||
foreach d [items-of glyphObject.dependencies] : begin {
|
|
||||||
local allAliases : Object.keys glyphs :.filter [[k] -> [glyphs`k === glyphs`d]]
|
|
||||||
dependencyProfile`name = [dependencyProfile`name.concat dependencyProfile`d allAliases]
|
|
||||||
}
|
|
||||||
return glyphObject
|
|
||||||
}
|
|
||||||
true : begin {
|
|
||||||
local actions arguments.0
|
|
||||||
local glyphObject [new Glyph ['.temp-' + [set nTemp [inc nTemp]]]]
|
|
||||||
glyphObject.set-width WIDTH
|
|
||||||
actions.call glyphObject
|
|
||||||
return glyphObject
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define [select-variant name unicode default] : begin {
|
|
||||||
if [pickHash && [not pickHash.(name)]] : return nothing
|
|
||||||
local variant : variantSelector`name || default
|
|
||||||
local chosenGlyph glyphs`[name + '.' + variant]
|
|
||||||
set glyphs`name chosenGlyph
|
|
||||||
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] {
|
|
||||||
then : include glyphs.[name + '.italic'] AS_BASE
|
|
||||||
else : include glyphs.[name + '.upright'] AS_BASE
|
|
||||||
}
|
|
||||||
if unicode : assign-unicode unicode
|
|
||||||
}
|
|
||||||
define [alias newid unicode oldid] : create-glyph newid : glyph-construction {
|
|
||||||
if unicode : assign-unicode unicode
|
|
||||||
include glyphs`oldid AS_BASE
|
|
||||||
}
|
|
||||||
|
|
||||||
###### HERE WE GO!
|
|
||||||
|
|
||||||
create-glyph 'space' : glyph-construction {
|
|
||||||
set-width WIDTH
|
|
||||||
assign-unicode ' '
|
|
||||||
include eMarks
|
|
||||||
}
|
|
336
buildglyphs.patel
Normal file
336
buildglyphs.patel
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
define Glyph [require './support/glyph'].Glyph
|
||||||
|
define Stroke [require './support/stroke'].Stroke
|
||||||
|
define tp [require './support/transform'].transformPoint
|
||||||
|
|
||||||
|
### COMMON FUNCTIONS
|
||||||
|
|
||||||
|
define [mix a b p] : a + [b - a] * p
|
||||||
|
define [linreg x0 y0 x1 y1 x] : y0 + [x - x0] * [y1 - y0] / [x1 - x0]
|
||||||
|
define [fallback] : for [local j 0] [j < arguments.length] [inc j] : if [arguments`j !== nothing] : return arguments`j
|
||||||
|
|
||||||
|
define emptyFontStr : JSON.stringify [require './empty.json']
|
||||||
|
|
||||||
|
define-macro $$include : syntax-rules {
|
||||||
|
('$$include' ('.quote' file)) : begin {
|
||||||
|
local path : require 'path'
|
||||||
|
local fs : require 'fs'
|
||||||
|
local f0 [[env.macros.get 'input-path']].1
|
||||||
|
local parse [require './syntax.js'].parse
|
||||||
|
|
||||||
|
local absolutePath : path.resolve [path.dirname f0] [formOf file]
|
||||||
|
local ast : parse [fs.readFileSync absolutePath 'utf-8'] (.included true)
|
||||||
|
return ('.syntactic-closure' ast env)
|
||||||
|
}
|
||||||
|
otherwise @`nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
define [buildFont para recursive] : begin {
|
||||||
|
|
||||||
|
define variantSelector para.variantSelector
|
||||||
|
define font : JSON.parse emptyFontStr
|
||||||
|
define glyphList font.glyf
|
||||||
|
define glyphs (.'.notdef' glyphList.0)
|
||||||
|
define unicodeGlyphs ()
|
||||||
|
|
||||||
|
define globalTransform (
|
||||||
|
.xx 1
|
||||||
|
.yx [Math.tan [para.italicangle / 180 * Math.PI]]
|
||||||
|
.xy 0
|
||||||
|
.yy 1
|
||||||
|
.x 0
|
||||||
|
.y 0
|
||||||
|
)
|
||||||
|
|
||||||
|
define ITALICCOR : 1 / [Math.sqrt [1 - globalTransform.yx * globalTransform.yx]]
|
||||||
|
|
||||||
|
define UPWARD (.x [-ITALICCOR] .y 0)
|
||||||
|
define DOWNWARD (.x ITALICCOR .y 0)
|
||||||
|
define RIGHTWARD (.x globalTransform.yx .y 1)
|
||||||
|
define LEFTWARD (.x [- globalTransform.yx] .y [-1])
|
||||||
|
|
||||||
|
# metrics
|
||||||
|
define DESCENDER para.descender
|
||||||
|
define WIDTH para.width
|
||||||
|
define CAP para.cap
|
||||||
|
define XH para.xheight
|
||||||
|
define O para.o
|
||||||
|
define OXHOOK para.oxhook
|
||||||
|
define SB para.sb
|
||||||
|
define HOOK para.hook
|
||||||
|
define AHOOK para.ahook
|
||||||
|
define SHOOK para.shook
|
||||||
|
define RHOOK para.rhook
|
||||||
|
define SMOOTH para.smooth
|
||||||
|
define SMALLSMOOTH para.smallsmooth
|
||||||
|
define STROKE para.stroke
|
||||||
|
define DOTSIZE para.dotsize
|
||||||
|
define PERIODSIZE para.periodsize
|
||||||
|
define BARPOS para.barpos
|
||||||
|
define GBARPOS para.gbarpos
|
||||||
|
define FIVEBARPOS para.fivebarpos
|
||||||
|
define LONGJUT para.longjut
|
||||||
|
define ACCENT para.accent
|
||||||
|
define ACCENTX para.accentx
|
||||||
|
|
||||||
|
|
||||||
|
# derived metrics
|
||||||
|
define XO : XH - O
|
||||||
|
define CAPO : CAP - O
|
||||||
|
define HALFSTROKE : STROKE / 2
|
||||||
|
define RIGHTSB : WIDTH - SB
|
||||||
|
define MIDDLE : WIDTH / 2
|
||||||
|
define CAPMIDDLE : CAP / 2
|
||||||
|
define CAP_SMOOTH : CAP - SMOOTH
|
||||||
|
define DOTRADIUS : DOTSIZE / 2
|
||||||
|
define PERIODRADIUS : PERIODSIZE / 2
|
||||||
|
|
||||||
|
define SMOOTHA : SMOOTH - globalTransform.yx * para.smoothadjust
|
||||||
|
define SMOOTHB : SMOOTH + globalTransform.yx * para.smoothadjust
|
||||||
|
define SMALLSMOOTHA : SMALLSMOOTH - globalTransform.yx * para.smoothadjust
|
||||||
|
define SMALLSMOOTHB : SMALLSMOOTH + globalTransform.yx * para.smoothadjust
|
||||||
|
define ITALICCORS : STROKE * globalTransform.yx
|
||||||
|
|
||||||
|
# style parameters
|
||||||
|
define EBARPOS : para.ebarpos || BARPOS
|
||||||
|
define KAPPA para.kappa
|
||||||
|
define COKAPPA : 1 - KAPPA
|
||||||
|
define BKAPPA : para.bkappa || KAPPA + 0.1
|
||||||
|
define CKAPPA : para.ckappa || BKAPPA
|
||||||
|
define COBKAPPA : 1 - BKAPPA
|
||||||
|
define KAPPA_HOOK : para.kappa_hook || BKAPPA + 0.1
|
||||||
|
define KAPPA_AHOOK : para.kappa_ahook || KAPPA_HOOK
|
||||||
|
define TAILADJX : WIDTH * 0.2
|
||||||
|
define TAILADJY : XH * 0.25
|
||||||
|
define TAILADJKAPPA 0.75
|
||||||
|
define TAILADJSX : WIDTH * 0.2
|
||||||
|
define TAILADJSY 0
|
||||||
|
define TAILADJSKAPPA 0.75
|
||||||
|
define ILBALANCE : LONGJUT * 0.04
|
||||||
|
define JBALANCE : para.jbalance || HALFSTROKE + ILBALANCE
|
||||||
|
define TBALANCE : para.tbalance || JBALANCE
|
||||||
|
define TBALANCE2 : para.tbalance2 || TBALANCE
|
||||||
|
define RBALANCE : para.rbalance || JBALANCE * 0.3
|
||||||
|
|
||||||
|
# Blackness parameters
|
||||||
|
# We will estimate blackness using lower-case 'e'
|
||||||
|
define WHITENESS : [[XH - STROKE * 2.5] * [RIGHTSB - SB] * [1 / 3]] / [XH * [RIGHTSB - SB]]
|
||||||
|
define [adviceBlackness crowdedness] : Math.min STROKE [[RIGHTSB - SB] * [1 - WHITENESS] / crowdedness]
|
||||||
|
|
||||||
|
# Anchor parameters
|
||||||
|
define BASE 'base'
|
||||||
|
define MARK 'mark'
|
||||||
|
define MARKBASE 'markbase'
|
||||||
|
|
||||||
|
define AS_BASE 'AS-BASE'
|
||||||
|
define [Upright angle] (.xx 1 .yx [-[Math.tan [[fallback angle para.italicangle] / 180 * Math.PI]]] .xy 0 .yy 1 .x 0 .y 0)
|
||||||
|
define [Italify angle] (.xx 1 .yx [Math.tan [[fallback angle para.italicangle] / 180 * Math.PI]] .xy 0 .yy 1 .x 0 .y 0)
|
||||||
|
define [Scale sx sy] (.xx sx .yx 0 .xy 0 .yy [fallback sy sx] .x 0 .y 0)
|
||||||
|
define [Translate x y] (.xx 1 .yx 0 .xy 0 .yy 1 .x x .y y)
|
||||||
|
|
||||||
|
define [tm anchor] : return (
|
||||||
|
.x [anchor.x * globalTransform.xx + anchor.y * globalTransform.yx + globalTransform.x]
|
||||||
|
.y [anchor.x * globalTransform.xy + anchor.y * globalTransform.yy + globalTransform.y]
|
||||||
|
.type anchor.type
|
||||||
|
)
|
||||||
|
|
||||||
|
define markAboveLower (.anchors (.above [tm (.x MIDDLE .y XH .type BASE)]))
|
||||||
|
define markAboveCap (.anchors (.above [tm (.x MIDDLE .y CAP .type BASE)]))
|
||||||
|
define markBelowLower (.anchors (.below [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
||||||
|
define markBelowZero (.anchors (.below [tm (.x MIDDLE .y 0 .type BASE)]))
|
||||||
|
define markTrailingLower (.anchors (.trailing [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
||||||
|
define markTrailingZero (.anchors (.trailing [tm (.x MIDDLE .y 0 .type BASE)]))
|
||||||
|
define markLFLower (.anchors (.lf [tm (.x MIDDLE .y DESCENDER .type BASE)]))
|
||||||
|
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))
|
||||||
|
|
||||||
|
Stroke.bindParameters para
|
||||||
|
|
||||||
|
### Font names
|
||||||
|
set font.name.fontFamily para.family
|
||||||
|
set font.name.fontSubFamily para.style
|
||||||
|
set font.name.preferredFamily para.family
|
||||||
|
set font.name.preferredSubFamily para.style
|
||||||
|
set font.name.uniqueSubFamily : para.family + ' ' + para.style + ' ' + para.version
|
||||||
|
set font.name.version para.version
|
||||||
|
set font.name.fullName : if [para.style != 'Regular'] [para.family + ' ' + para.style] para.family
|
||||||
|
set font.name.postScriptName : font.name.fullName.replace [regex ' ' 'g'] '-'
|
||||||
|
set font.name.copyright para.copyright
|
||||||
|
set font.'OS/2'.usWeightClass para.weight
|
||||||
|
set font.'OS/2'.bProportion 9 # Monospaced
|
||||||
|
set font.'OS/2'.bWeight : 1 + para.weight / 100
|
||||||
|
set font.'OS/2'.fsSelection : [if para.isBold 32 0] + [if para.isItalic 1 0] + [if [[not para.isBold] && [not para.isItalic]] 64 0] + 128
|
||||||
|
set font.head.macStyle : [if para.isBold 1 0] + [if para.isItalic 2 0]
|
||||||
|
|
||||||
|
### Metric metadata
|
||||||
|
# Note: we use 1000upm in design, and 4096upm in production
|
||||||
|
|
||||||
|
define upmscale : fallback para.upmscale 1
|
||||||
|
|
||||||
|
set font.head.unitsPerEm 1000
|
||||||
|
set font.hhea.ascent [CAP + ACCENT * 1.5]
|
||||||
|
set font.'OS/2'.usWinAscent [CAP + ACCENT * 1.5]
|
||||||
|
set font.'OS/2'.sTypoAscender [CAP + ACCENT * 1.5]
|
||||||
|
set font.hhea.descent [DESCENDER - ACCENT * 0.5]
|
||||||
|
set font.'OS/2'.usWinDescent [Math.abs [DESCENDER - ACCENT * 0.5]]
|
||||||
|
set font.'OS/2'.sTypoDescender [DESCENDER - ACCENT * 0.5]
|
||||||
|
set font.hhea.lineGap [CAP * 0.2]
|
||||||
|
set font.'OS/2'.sTypoLineGap [CAP * 0.2]
|
||||||
|
set font.'OS/2'.sxHeight XH
|
||||||
|
set font.post.italicAnvle [0 - para.italicangle]
|
||||||
|
|
||||||
|
### Necessary macros
|
||||||
|
define-macro glyph-construction : syntax-rules {
|
||||||
|
@`[glyph-construction @::steps] ('.syntactic-closure' @`[lambda [] [begin {
|
||||||
|
local currentGlyph this
|
||||||
|
local set-width : this.set-width.bind this
|
||||||
|
local assign-unicode : lambda [code] : begin {
|
||||||
|
currentGlyph.assign-unicode code
|
||||||
|
set unicodeGlyphs.(currentGlyph.unicode`[currentGlyph.unicode.length - 1]) currentGlyph
|
||||||
|
}
|
||||||
|
local start-from : this.start-from.bind this
|
||||||
|
local line-to : this.line-to.bind this
|
||||||
|
local curve-to : this.curve-to.bind this
|
||||||
|
local cubic-to : this.cubic-to.bind this
|
||||||
|
local arc-hv-to : this.arc-hv-to.bind this
|
||||||
|
local arc-vh-to : this.arc-vh-to.bind this
|
||||||
|
local put-shapes : this.put-shapes.bind this
|
||||||
|
local reverse-last : this.reverse-last.bind this
|
||||||
|
local include : this.include.bind this
|
||||||
|
local create-stroke : this.create-stroke.bind this
|
||||||
|
local set-anchor : this.set-anchor.bind this
|
||||||
|
local apply-transform : this.apply-transform.bind this
|
||||||
|
|
||||||
|
# Actually I can define them using macros, but it makes compilation slow.
|
||||||
|
# define-macro set-width : syntax-rules { @`[set-width @::args] @`[currentGlyph.set-width @::args] }
|
||||||
|
# define-macro start-from : syntax-rules { @`[start-from @::args] @`[currentGlyph.start-from @::args] }
|
||||||
|
# define-macro line-to : syntax-rules { @`[line-to @::args] @`[currentGlyph.line-to @::args] }
|
||||||
|
# define-macro curve-to : syntax-rules { @`[curve-to @::args] @`[currentGlyph.curve-to @::args] }
|
||||||
|
# define-macro cubic-to : syntax-rules { @`[cubic-to @::args] @`[currentGlyph.cubic-to @::args] }
|
||||||
|
# define-macro include : syntax-rules { @`[include @::args] @`[currentGlyph.include @::args] }
|
||||||
|
# define-macro create-stroke : syntax-rules { @`[create-stroke @::args] @`[currentGlyph.create-stroke @::args] }
|
||||||
|
# define-macro set-anchor : syntax-rules { @`[set-anchor @::args] @`[currentGlyph.set-anchor @::args] }
|
||||||
|
# define-macro apply-transform : syntax-rules { @`[apply-transform @::args] @`[currentGlyph.apply-transform @::args] }
|
||||||
|
# define-macro reverse-last : syntax-rules { @`[reverse-last @::args] @`[currentGlyph.reverse-last @::args] }
|
||||||
|
|
||||||
|
local [dont-export] : set currentGlyph.dontExport true
|
||||||
|
this.gizmo = globalTransform
|
||||||
|
this.set-width WIDTH
|
||||||
|
begin @::[steps.map formOf]
|
||||||
|
return nothing
|
||||||
|
}]] env)
|
||||||
|
}
|
||||||
|
|
||||||
|
local dependencyProfile (.)
|
||||||
|
local nTemp 0
|
||||||
|
local pickHash : if recursive {
|
||||||
|
then : let [h (.)] : begin {
|
||||||
|
foreach j [items-of recursive] : set h.(j) j
|
||||||
|
* h
|
||||||
|
}
|
||||||
|
else nothing
|
||||||
|
}
|
||||||
|
define [create-glyph name actions] : piecewise {
|
||||||
|
[name && actions] : begin {
|
||||||
|
if [pickHash && [not pickHash.(name)]] : return nothing
|
||||||
|
process.stderr.write : "Building /" + name + [if recursive " (recursive)" ""] + " for " + para.family + ' ' + para.style + "\n"
|
||||||
|
set dependencyProfile`name ()
|
||||||
|
define glyphObject [new Glyph name]
|
||||||
|
glyphObject.set-width WIDTH
|
||||||
|
glyphList.push glyphObject
|
||||||
|
glyphs`name = glyphObject
|
||||||
|
actions.call glyphObject
|
||||||
|
foreach d [items-of glyphObject.dependencies] : begin {
|
||||||
|
local allAliases : Object.keys glyphs :.filter [[k] -> [glyphs`k === glyphs`d]]
|
||||||
|
dependencyProfile`name = [dependencyProfile`name.concat dependencyProfile`d allAliases]
|
||||||
|
}
|
||||||
|
return glyphObject
|
||||||
|
}
|
||||||
|
true : begin {
|
||||||
|
local actions arguments.0
|
||||||
|
local glyphObject [new Glyph ['.temp-' + [set nTemp [inc nTemp]]]]
|
||||||
|
glyphObject.set-width WIDTH
|
||||||
|
actions.call glyphObject
|
||||||
|
return glyphObject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define [select-variant name unicode default] : begin {
|
||||||
|
if [pickHash && [not pickHash.(name)]] : return nothing
|
||||||
|
local variant : variantSelector`name || default
|
||||||
|
local chosenGlyph glyphs`[name + '.' + variant]
|
||||||
|
set glyphs`name chosenGlyph
|
||||||
|
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] {
|
||||||
|
then : include glyphs.[name + '.italic'] AS_BASE
|
||||||
|
else : include glyphs.[name + '.upright'] AS_BASE
|
||||||
|
}
|
||||||
|
if unicode : assign-unicode unicode
|
||||||
|
}
|
||||||
|
define [alias newid unicode oldid] : create-glyph newid : glyph-construction {
|
||||||
|
if unicode : assign-unicode unicode
|
||||||
|
include glyphs`oldid AS_BASE
|
||||||
|
}
|
||||||
|
|
||||||
|
###### HERE WE GO!
|
||||||
|
|
||||||
|
create-glyph 'space' : glyph-construction {
|
||||||
|
set-width WIDTH
|
||||||
|
assign-unicode ' '
|
||||||
|
include eMarks
|
||||||
|
}
|
||||||
|
|
||||||
|
$$include 'glyphs/common-shapes.patel'
|
||||||
|
$$include 'glyphs/overmarks.patel'
|
||||||
|
$$include 'glyphs/latin-basic-capital.patel'
|
||||||
|
$$include 'glyphs/latin-basic-lower.patel'
|
||||||
|
$$include 'glyphs/greek.patel'
|
||||||
|
$$include 'glyphs/cyrillic-basic.patel'
|
||||||
|
$$include 'glyphs/latin-extend.patel'
|
||||||
|
$$include 'glyphs/cyrillic-extended.patel'
|
||||||
|
$$include 'glyphs/numbers.patel'
|
||||||
|
$$include 'glyphs/symbol-ascii.patel'
|
||||||
|
$$include 'glyphs/symbol-extend.patel'
|
||||||
|
$$include 'glyphs/symbol-geometric.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
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [not recursive] : set font.glyf : font.glyf.filter : function [glyph] : glyph && [not glyph.dontExport]
|
||||||
|
set font.glyfMap glyphs
|
||||||
|
return font
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.build = buildFont
|
6
makefile
6
makefile
|
@ -35,10 +35,8 @@ update : $(FILES)
|
||||||
$(SUPPORT_FILES) :
|
$(SUPPORT_FILES) :
|
||||||
patel-c $< -o $@ --strict
|
patel-c $< -o $@ --strict
|
||||||
|
|
||||||
.buildglyphs.all.patel : buildglyphs-intro.patel $(GLYPH_SEGMENTS) buildglyphs-final.patel
|
buildglyphs.js : buildglyphs.patel $(GLYPH_SEGMENTS)
|
||||||
cat $^ > .buildglyphs.all.patel
|
patel-c --strict $< -o $@
|
||||||
buildglyphs.js : .buildglyphs.all.patel
|
|
||||||
patel-c --strict $^ -o $@
|
|
||||||
support/glyph.js : support/glyph.patel
|
support/glyph.js : support/glyph.patel
|
||||||
support/stroke.js : support/stroke.patel
|
support/stroke.js : support/stroke.patel
|
||||||
parameters.js : parameters.patel
|
parameters.js : parameters.patel
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue