127 lines
4.8 KiB
Text
127 lines
4.8 KiB
Text
extern isFinite
|
|
import './point' as Point
|
|
import './transform' as : Transform && [object [transformPoint tp] [untransform utp] inverse]
|
|
import './anchor' as Anchor
|
|
import "./utils" as [object fallback mix ratio]
|
|
|
|
define-macro xytransform : syntax-rules
|
|
`[xytransform @tfm @x @y] : begin
|
|
set [env.declarations.get [formOf x]].isParameter 0
|
|
set [env.declarations.get [formOf y]].isParameter 0
|
|
let [t : env.newt] `[begin \\
|
|
set @t @x
|
|
set @x : @x * @tfm.xx + @y * @tfm.yx + @tfm.x
|
|
set @y : @t * @tfm.xy + @y * @tfm.yy + @tfm.y
|
|
]
|
|
|
|
export all : class Glyph
|
|
public [new name] : begin
|
|
set this.name name
|
|
set this.unicode {}
|
|
set this.contours {}
|
|
set this.advanceWidth 500
|
|
set this.autoRefPriority 0
|
|
set this.anchors {.}
|
|
set this.gizmo : Transform.Id
|
|
set this.dependencies {}
|
|
set this.defaultTag null
|
|
return nothing
|
|
static is {.unapply [function [obj arity] [if (obj <@ Glyph) {obj} null]]}
|
|
|
|
public [set-width w] : begin
|
|
this.advanceWidth = w
|
|
return this
|
|
|
|
public [assign-unicode u] : begin
|
|
this.unicode.push : piecewise
|
|
([typeof u] === 'string') : u.charCodeAt 0
|
|
true u
|
|
return this
|
|
|
|
public [retag-contour oldtag newtag] : begin
|
|
if this.contours : foreach [c : items-of this.contours] : if (c.tag === oldtag) : set c.tag newtag
|
|
return this
|
|
public [eject-contour tag] : begin
|
|
set this.contours : this.contours.filter : lambda [c] (c.tag !== tag)
|
|
return this
|
|
public [depends-on glyph] : begin
|
|
piecewise
|
|
glyph.name : this.dependencies.push glyph.name
|
|
glyph.dependencies : this.dependencies = [this.dependencies.concat glyph.dependencies]
|
|
return this
|
|
|
|
public [includeGeometry geom shiftx shifty] : begin
|
|
if (!geom || !geom.contours) : return nothing
|
|
foreach [contour : items-of geom.contours] : begin
|
|
local c {}
|
|
set c.tag : contour.tag || geom.tag || this.defaultTag
|
|
foreach [point : items-of contour] : c.push : Point.translated point shiftx shifty
|
|
this.contours.push c
|
|
|
|
public [combineAnchor markid shift anchorThis anchorThat] : begin
|
|
if (!anchorThis || !anchorThat || anchorThat.type !== Anchor.MARK) : return nothing
|
|
if (anchorThis.type === Anchor.BASE) : begin
|
|
set shift.x : anchorThis.x - anchorThat.x
|
|
set shift.y : anchorThis.y - anchorThat.y
|
|
if (anchorThat.mbx !== nothing && anchorThat.mby !== nothing)
|
|
set this.anchors.(markid) : new Anchor
|
|
* (anchorThis.x + anchorThat.mbx - anchorThat.x)
|
|
* (anchorThis.y + anchorThat.mby - anchorThat.y)
|
|
* Anchor.BASE
|
|
: else : if (anchorThis.mbx !== nothing && anchorThis.mby !== nothing) : begin
|
|
set shift.x : anchorThis.mbx - anchorThat.x
|
|
set shift.y : anchorThis.mby - anchorThat.y
|
|
if (anchorThat.mbx !== nothing && anchorThat.mby !== nothing)
|
|
set this.anchors.(markid) : new Anchor
|
|
* anchorThis.x
|
|
* anchorThis.y
|
|
* anchorThis.type
|
|
* (anchorThis.mbx + anchorThat.mbx - anchorThat.x)
|
|
* (anchorThis.mby + anchorThat.mby - anchorThat.y)
|
|
|
|
public [includeGlyph glyph copyAnchors copyWidth] : begin
|
|
if (glyph <@ Function) : begin
|
|
throw "\(this.name): Cannot include a function using includeGlyph. Use include instead."
|
|
|
|
local shift {.x 0 .y 0}
|
|
if glyph.anchors : foreach { markid anchorThis } [pairs-of this.anchors] : begin
|
|
local anchorThat glyph.anchors.(markid)
|
|
this.combineAnchor markid shift anchorThis anchorThat
|
|
|
|
this.includeGeometry glyph shift.x shift.y
|
|
if ((copyAnchors || glyph.isMarkSet) && glyph.anchors) : begin
|
|
foreach [k : items-of : Object.keys glyph.anchors] : begin
|
|
set this.anchors.(k) glyph.anchors.(k)
|
|
if (glyph.advanceWidth >= 0 && copyWidth) : set this.advanceWidth glyph.advanceWidth
|
|
if glyph.name : this.dependencies.push glyph.name
|
|
if glyph.dependencies : this.dependencies = [this.dependencies.concat glyph.dependencies]
|
|
return this
|
|
|
|
public [include component copyAnchors copyWidth] : begin
|
|
piecewise
|
|
(component <@ Function) : begin
|
|
local t this.defaultTag
|
|
if component.tag : set this.defaultTag component.tag
|
|
component.call this copyAnchors copyWidth
|
|
set this.defaultTag t
|
|
return this
|
|
(component <@ Transform) : return : this.apply-transform component copyAnchors
|
|
(component <@ Array) : begin
|
|
return : this.includeGlyph {.contours component} copyAnchors copyWidth
|
|
true : begin
|
|
return : this.includeGlyph component copyAnchors copyWidth
|
|
|
|
public [apply-transform transform alsoAnchors] : begin
|
|
foreach [c : items-of this.contours] : foreach [j : range 0 c.length] : set c.(j) : tp transform c.(j)
|
|
if alsoAnchors : foreach key [items-of [Object.keys this.anchors]] : begin
|
|
set this.anchors.(key) : Anchor.transform transform this.anchors.(key)
|
|
return this
|
|
|
|
public [set-anchor id type x y mbx mby] : begin
|
|
xytransform this.gizmo x y
|
|
if (mbx !== nothing && mby !== nothing)
|
|
: then : begin
|
|
xytransform this.gizmo mbx mby
|
|
set this.anchors.(id) : new Anchor x y type mbx mby
|
|
: else : set this.anchors.(id) : new Anchor x y type
|
|
return this
|