151 lines
No EOL
5.2 KiB
Text
151 lines
No EOL
5.2 KiB
Text
define bezierCubic2Q2 [require 'node-sfnt/lib/math/bezierCubic2Q2']
|
|
define tp [require './transform'].transformPoint
|
|
define Stroke [require './stroke'].Stroke
|
|
|
|
define id (
|
|
.xx 1
|
|
.yx 0
|
|
.xy 0
|
|
.yy 1
|
|
.x 0
|
|
.y 0
|
|
)
|
|
define [fallback] : for [local j 0] [j < arguments.length] [inc j] : if [arguments`j !== nothing] : return arguments`j
|
|
define aFunction (.unapply [function [obj arity] [if [obj <@ Function] (obj) null]])
|
|
|
|
define [Glyph name] : begin {
|
|
set this.name name
|
|
set this.unicode ()
|
|
set this.contours ()
|
|
set this.advanceWidth 500
|
|
set this.anchors (.)
|
|
set this.gizmo (
|
|
.xx 1
|
|
.yx 0
|
|
.xy 0
|
|
.yy 1
|
|
.x 0
|
|
.y 0
|
|
)
|
|
set this.dependencies ()
|
|
return nothing
|
|
}
|
|
define Glyph.is (.unapply [function [obj arity] [if [obj <@ Glyph] (obj) null]])
|
|
define [Glyph.prototype.set-width w] : begin {
|
|
this.advanceWidth = w
|
|
return this
|
|
}
|
|
define [Glyph.prototype.assign-unicode u] : begin {
|
|
this.unicode.push : piecewise {
|
|
[[typeof u] === 'string'] : u.charCodeAt 0
|
|
true u
|
|
}
|
|
return this
|
|
}
|
|
|
|
define [Glyph.prototype.start-from x y] : begin {
|
|
this.contours.push ([tp this.gizmo (.x x .y y .onCurve true)])
|
|
return this
|
|
}
|
|
define [Glyph.prototype.line-to x y] : begin {
|
|
this.contours`[this.contours.length - 1].push [tp this.gizmo (.x x .y y .onCurve true)]
|
|
return this
|
|
}
|
|
define [Glyph.prototype.curve-control x y] : begin {
|
|
this.contours`[this.contours.length - 1].push [tp this.gizmo (.x x .y y .onCurve false)]
|
|
return this
|
|
}
|
|
define [Glyph.prototype.curve-to xc yc x y] : begin {
|
|
this.contours`[this.contours.length - 1].push [tp this.gizmo (.x xc .y yc .onCurve false)] [tp this.gizmo (.x x .y y .onCurve true)]
|
|
return this
|
|
}
|
|
define [Glyph.prototype.cubic-to x1 y1 x2 y2 x y] : begin {
|
|
local lastContour this.contours`[this.contours.length - 1]
|
|
local lastPoint lastContour`[lastContour.length - 1]
|
|
local segments [bezierCubic2Q2 lastPoint (.x x1 .y y1) (.x x2 .y y2) (.x x .y y)]
|
|
foreach (p0 (.x xc .y yc) (.x xf .y yf)) [items-of segments] : this.curve-to xc yc xf yf
|
|
return this
|
|
}
|
|
define [Glyph.prototype.reverse-last] : begin {
|
|
this.contours.[this.contours.length - 1] = [this.contours.[this.contours.length - 1].reverse]
|
|
}
|
|
define [Glyph.prototype.put-shapes contours] : begin {
|
|
# do not double-transform
|
|
local t this.gizmo
|
|
set this.gizmo id
|
|
foreach contour [items-of contours] : begin {
|
|
this.start-from contour.0.x contour.0.y
|
|
for [local j 1] [j < contour.length] [inc j] : begin {
|
|
local point contour`j
|
|
if point.cubic [begin {
|
|
local p2 contour`[j + 1]
|
|
local p3 contour`[j + 2]
|
|
this.cubic-to point.x point.y p2.x p2.y p3.x p3.y
|
|
j = j + 2
|
|
}] [if point.onCurve [this.line-to point.x point.y] [this.curve-control point.x point.y]]
|
|
}
|
|
}
|
|
set this.gizmo t
|
|
return this
|
|
}
|
|
define [Glyph.prototype.include component copyAnchors] : begin {
|
|
local glyph : match component {
|
|
[aFunction it] : return : component.call this
|
|
[Stroke.is it] (.contours [component.to-outline 0 0])
|
|
(:: contours) (.contours contours)
|
|
otherwise component
|
|
}
|
|
local contours glyph.contours
|
|
local transform (.x 0 .y 0 .xx 1 .yy 1 .xy 0 .yx 0)
|
|
local shiftx 0
|
|
local shifty 0
|
|
if [this.anchors && glyph.anchors] : foreach markid [items-of [Object.keys this.anchors]] : begin {
|
|
local anchorThis this.anchors`markid
|
|
local anchorThat glyph.anchors`markid
|
|
if [anchorThis && [anchorThis.type === 'base' || anchorThis.mbx !== nothing && anchorThis.mby !== nothing] && anchorThat && anchorThat.type === 'mark'] : begin {
|
|
set (shiftx shifty) (
|
|
[[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
|
|
)
|
|
}
|
|
}
|
|
}
|
|
set transform.x : transform.x + shiftx
|
|
set transform.y : transform.y + shifty
|
|
if contours : begin {
|
|
this.put-shapes : contours.map : function [contour] {
|
|
contour.map : function [point] : tp transform point
|
|
}
|
|
}
|
|
if [[[not contours] || copyAnchors] && glyph.anchors] : set this.anchors : let [a (.)] [anchors glyph.anchors] [keys : Object.keys glyph.anchors] : begin {
|
|
foreach k [items-of keys] [set a`k anchors`k]
|
|
* a
|
|
}
|
|
piecewise {
|
|
glyph.name : this.dependencies.push glyph.name
|
|
glyph.dependencies : this.dependencies = [this.dependencies.concat glyph.dependencies]
|
|
}
|
|
}
|
|
define [Glyph.prototype.apply-transform transform] : set this.contours : this.contours.map : function [contour] : begin {
|
|
return : contour.map : function [point] [tp transform point]
|
|
}
|
|
define [Glyph.prototype.create-stroke] : begin {
|
|
local s : new Stroke
|
|
s.gizmo = [Object.create this.gizmo]
|
|
return s
|
|
}
|
|
define [Glyph.prototype.set-anchor id type x y mbx mby] : begin {
|
|
local anchorpoint [tp this.gizmo (.x x .y y)]
|
|
local markbasepoint : if [mbx !== nothing && mby !== nothing] [tp this.gizmo (.x mbx .y mby)] (.x nothing .y nothing)
|
|
this.anchors`id = (.x anchorpoint.x .y anchorpoint.y .type type .mbx markbasepoint.x .mby markbasepoint.y)
|
|
}
|
|
|
|
exports.Glyph = Glyph |